-
Notifications
You must be signed in to change notification settings - Fork 0
/
renderer_run_compute_vert.go
120 lines (111 loc) · 4.89 KB
/
renderer_run_compute_vert.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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package ptxt
import "github.com/tinne26/ggfnt"
import "github.com/tinne26/ptxt/internal"
// Precondition: except glyph indices, run data has been cleared
// and slices resized to len(glyphIndices), and we have at least
// one glyph index.
func (self *Renderer) computeVerticalRunLogicalLayout(maxLineLen int) {
if len(self.run.glyphIndices) > 32000 { panic(preViolation) }
currentStrand := self.Strand()
currentFont := currentStrand.Font()
currentScale := int(self.scale)
currentGlyphInterspacing := strandFullVertGlyphInterspacing(currentStrand)*currentScale
var layoutBreak vertLayoutLineBreakTempVariables
layoutBreak.Init(strandFullLineWidth(currentStrand)*currentScale)
self.run.firstRowAscent = int(currentFont.Metrics().Ascent())*currentScale
self.run.top = -self.run.firstRowAscent
if self.boundingMode & noDescent == 0 {
self.run.lastRowDescent = int(currentFont.Metrics().Descent())*currentScale
}
var prevEffectiveGlyph ggfnt.GlyphIndex = ggfnt.GlyphMissing
var prevInterspacing int
var prevBottomAdvance, prevTopAdvance int
var y, index int = self.run.top, 0
var layoutWrap vertLayoutWrapTempVariables
for index < len(self.run.glyphIndices) {
glyphIndex := self.run.glyphIndices[index]
if glyphIndex < ggfnt.MaxGlyphs {
layoutBreak.NotifyNonBreak()
layoutWrap.IncreaseLineCharCount()
memoY := y + prevBottomAdvance
kerning := int(currentFont.Kerning().GetVert(prevEffectiveGlyph, glyphIndex))*currentScale
self.run.kernings[index] = int16(kerning)
self.run.advances[index] = uint16(prevBottomAdvance + prevTopAdvance)
placement := currentFont.Glyphs().Placement(glyphIndex)
horzShift := int(placement.HorzCenter)*currentScale
self.run.horzShifts[index] = uint16(horzShift)
if self.run.right - horzShift < self.run.left {
self.run.left = self.run.right - horzShift
}
prevTopAdvance = int(placement.TopAdvance)*currentScale
y += prevBottomAdvance + prevInterspacing + kerning + prevTopAdvance
prevInterspacing = currentGlyphInterspacing
prevBottomAdvance = int(placement.BottomAdvance)*currentScale
prevEffectiveGlyph = glyphIndex
// line wrapping pain
yWrap := y + prevBottomAdvance
if yWrap <= maxLineLen {
layoutBreak.UpdateMaxRightAdvance(int(placement.Advance)*currentScale - horzShift)
layoutWrap.GlyphNonBreak(currentStrand, glyphIndex, index, memoY, yWrap)
} else {
var yWithBottom int
index, yWithBottom = layoutWrap.GlyphBreak(self, currentStrand, glyphIndex, index, memoY, yWrap)
self.run.right = layoutBreak.NotifyBreak(self, self.run.top, yWithBottom, self.run.right)
y, prevInterspacing, prevBottomAdvance, prevTopAdvance = 0, 0, 0, 0
prevEffectiveGlyph = ggfnt.GlyphMissing
continue
}
} else { // control glyph
switch glyphIndex {
case ggfnt.GlyphNewLine:
if self.elideLineBreak(index) {
// line break should be elided, absorbed by immediately previous line wrapping break
} else {
// apply break
self.run.right = layoutBreak.NotifyBreak(self, self.run.top, y + prevBottomAdvance, self.run.right)
y, prevInterspacing, prevBottomAdvance, prevTopAdvance = 0, 0, 0, 0
prevEffectiveGlyph = ggfnt.GlyphMissing
layoutWrap.PostBreakUpdate(index + 1)
}
case ggfnt.GlyphMissing:
// should typically be triggered at an earlier point,
// so I'm not even sure you can reach this normally
panic("missing glyph")
case ggfnt.GlyphZilch: // we don't change the prevEffectiveGlyph here
self.run.advances[index] = 0
self.run.kernings[index] = 0
self.run.horzShifts[index] = 0
case internal.TwineEffectMarkerGlyph:
panic("unimplemented")
// lineBreaksOnly = false // yes or no? it depends?
// prevEffectiveGlyph = glyphIndex
// TODO: whether this breaks or doesn't break prev effective glyph
// should probably depend on the effect. color changes shouldn't break
// anything. other effects might break. basically, effects with padding
// should break kerning, but maybe we want to leave it to the user,
// as some cases might be ambiguous
default:
// ... some other control glyph, possibly a custom control glyph
// for the font or user code. we are not breaking kerning nor
// interrupting the previous glyph, but that could be discussed (TODO)
self.run.advances[index] = 0
self.run.kernings[index] = 0
self.run.horzShifts[index] = 0
}
}
index += 1
}
// take last x and descent into account
layoutBreak.NotifyTextEnd(self, y + prevBottomAdvance)
}
func (self *Renderer) computeVerticalRunMaskLayout(maxLineLen int) {
panic("sorry, Vertical rendering only supports LogicalBounding at the moment, MaskBounding is still unimplemented")
}
func (self *Renderer) computeVertLineStart(oy int, lineIndex uint16) int {
switch self.align.Vert() {
case VertCenter : return oy - int(self.run.lineLengths[lineIndex] >> 1)
case Bottom : return oy - int(self.run.lineLengths[lineIndex])
default:
return oy
}
}