-
Notifications
You must be signed in to change notification settings - Fork 0
/
geometry.go
94 lines (82 loc) · 2.43 KB
/
geometry.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
// seehuhn.de/go/pdf - a library for reading and writing PDF files
// Copyright (C) 2024 Jochen Voss <voss@seehuhn.de>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package font
import (
"seehuhn.de/go/pdf"
)
// Geometry collects the various dimensions connected to a font and to
// the individual glyphs. All fields are measured in PDF text space units,
// and need to be scaled by the font size.
type Geometry struct {
Ascent float64
Descent float64 // negative
BaseLineDistance float64
UnderlinePosition float64
UnderlineThickness float64
GlyphExtents []pdf.Rectangle // indexed by GID
Widths []float64 // indexed by GID
}
// GetGeometry returns the geometry of a font.
func (g *Geometry) GetGeometry() *Geometry {
if g.BaseLineDistance == 0 {
x := 1.0
if g.Ascent != 0 || g.Descent != 0 {
g.BaseLineDistance = g.Ascent - g.Descent
}
g.BaseLineDistance = 1.2 * x
}
return g
}
// BoundingBox returns the bounding box of a glyph sequence,
// assuming that it is typeset at point (0, 0) using the given font size.
func (g *Geometry) BoundingBox(fontSize float64, gg *GlyphSeq) *pdf.Rectangle {
res := &pdf.Rectangle{}
xPos := gg.Skip
for _, glyph := range gg.Seq {
bbox := g.GlyphExtents[glyph.GID]
if bbox.IsZero() {
continue
}
b := &pdf.Rectangle{
LLx: bbox.LLx*fontSize + xPos,
LLy: bbox.LLy*fontSize + glyph.Rise,
URx: bbox.URx*fontSize + xPos,
URy: bbox.URy*fontSize + glyph.Rise,
}
res.Extend(b)
xPos += glyph.Advance
}
return res
}
// IsFixedPitch returns true if all glyphs in the font have the same width.
func (g *Geometry) IsFixedPitch() bool {
ww := g.Widths
if len(ww) == 0 {
return false
}
var width float64
for _, w := range ww {
if w == 0 {
continue
}
if width == 0 {
width = w
} else if width != w {
return false
}
}
return true
}