Skip to content

Commit c3ca867

Browse files
benoitkuglerandydotxyz
authored andcommitted
[shaping] add Advance; deprecate some other fields
1 parent 292cbfb commit c3ca867

File tree

6 files changed

+100
-41
lines changed

6 files changed

+100
-41
lines changed

shaping/output.go

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,19 @@ type Glyph struct {
2626
// YBearing is the distance between the dot (with offset applied) and
2727
// the top of the glyph content, typically positive
2828
YBearing fixed.Int26_6
29+
// Advance is the distance between the current dot (without offset applied) and the next dot.
30+
// It is typically positive for horizontal text, and negative for vertical text.
31+
Advance fixed.Int26_6
32+
2933
// XAdvance is the distance between the current dot (without offset applied) and the next dot.
3034
// It is typically positive for horizontal text, and always zero for vertical text.
35+
//
36+
// Deprecated: Use Advance instead.
3137
XAdvance fixed.Int26_6
3238
// YAdvance is the distance between the current dot (without offset applied) and the next dot.
3339
// It is typically negative for vertical text, and always zero for horizontal text.
40+
//
41+
// Deprecated: Use Advance instead.
3442
YAdvance fixed.Int26_6
3543

3644
// Offsets to be applied to the dot before actually drawing
@@ -43,11 +51,17 @@ type Glyph struct {
4351
// this glyph cluster. All glyphs sharing the same cluster value
4452
// are part of the same cluster and will have identical RuneCount
4553
// and GlyphCount fields.
54+
//
55+
// Deprecated: Use TextIndex() instead.
4656
ClusterIndex int
4757
// RuneCount is the number of input runes shaped into this output
4858
// glyph cluster.
59+
//
60+
// Deprecated: Use RunesCount() instead.
4961
RuneCount int
5062
// GlyphCount is the number of glyphs in this output glyph cluster.
63+
//
64+
// Deprecated: Use GlyphsCount() instead.
5165
GlyphCount int
5266
GlyphID font.GID
5367
Mask uint32
@@ -59,6 +73,19 @@ type Glyph struct {
5973
startLetterSpacing, endLetterSpacing fixed.Int26_6
6074
}
6175

76+
// TextIndex is the lowest rune index of all runes shaped into
77+
// this glyph cluster. All glyphs sharing the same cluster value
78+
// are part of the same cluster and will have identical RunesCount
79+
// and GlyphsCount values.
80+
func (g Glyph) TextIndex() int { return g.ClusterIndex }
81+
82+
// RuneCount is the number of input runes shaped into this output
83+
// glyph cluster.
84+
func (g Glyph) RunesCount() int { return g.RuneCount }
85+
86+
// GlyphsCount is the number of glyphs in this output glyph cluster.
87+
func (g Glyph) GlyphsCount() int { return g.GlyphCount }
88+
6289
// LeftSideBearing returns the distance from the glyph's X origin to
6390
// its leftmost edge. This value can be negative if the glyph extends
6491
// across the origin.
@@ -70,7 +97,7 @@ func (g Glyph) LeftSideBearing() fixed.Int26_6 {
7097
// the edge of the glyph's advance. This value can be negative if the glyph's
7198
// right edge is after the end of its advance.
7299
func (g Glyph) RightSideBearing() fixed.Int26_6 {
73-
return g.XAdvance - g.Width - g.XBearing
100+
return g.Advance - g.Width - g.XBearing
74101
}
75102

76103
// Bounds describes the minor-axis bounds of a line of text. In a LTR or RTL
@@ -169,14 +196,8 @@ func (o *Output) FromFontUnit(v float32) fixed.Int26_6 {
169196
// and can be used to speed up line wrapping logic.
170197
func (o *Output) RecomputeAdvance() {
171198
advance := fixed.Int26_6(0)
172-
if o.Direction.IsVertical() {
173-
for _, g := range o.Glyphs {
174-
advance += g.YAdvance
175-
}
176-
} else { // horizontal
177-
for _, g := range o.Glyphs {
178-
advance += g.XAdvance
179-
}
199+
for _, g := range o.Glyphs {
200+
advance += g.Advance
180201
}
181202
o.Advance = advance
182203
}
@@ -204,11 +225,11 @@ func (o *Output) advanceSpaceAware(paragraphDir di.Direction) fixed.Int26_6 {
204225
}
205226
if o.Direction.IsVertical() {
206227
if lastG.Height == 0 {
207-
return o.Advance - lastG.YAdvance
228+
return o.Advance - lastG.Advance
208229
}
209230
} else { // horizontal
210231
if lastG.Width == 0 {
211-
return o.Advance - lastG.XAdvance
232+
return o.Advance - lastG.Advance
212233
}
213234
}
214235
return o.Advance - lastG.endLetterSpacing
@@ -228,7 +249,7 @@ func (o *Output) RecalculateAll() {
228249
if o.Direction.IsVertical() {
229250
for i := range o.Glyphs {
230251
g := &o.Glyphs[i]
231-
advance += g.YAdvance
252+
advance += g.Advance
232253
depth := g.XOffset + g.XBearing // start of the glyph
233254
if depth < descent {
234255
descent = depth
@@ -241,7 +262,7 @@ func (o *Output) RecalculateAll() {
241262
} else { // horizontal
242263
for i := range o.Glyphs {
243264
g := &o.Glyphs[i]
244-
advance += g.XAdvance
265+
advance += g.Advance
245266
height := g.YBearing + g.YOffset
246267
if height > ascent {
247268
ascent = height
@@ -276,8 +297,7 @@ func (out *Output) sideways() {
276297
out.Glyphs[i].XBearing = g.YBearing + g.Height
277298
out.Glyphs[i].YBearing = g.Width
278299
// switch advance direction
279-
out.Glyphs[i].XAdvance = 0
280-
out.Glyphs[i].YAdvance = -g.XAdvance // YAdvance is negative
300+
out.Glyphs[i].Advance = -g.Advance // Advance for vertical text is negative
281301
// apply a rotation around the dot, and position the glyph
282302
// below the dot
283303
out.Glyphs[i].XOffset = g.YOffset

shaping/output_test.go

Lines changed: 50 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,32 @@ var (
3232
simpleGlyph_ = Glyph{
3333
GlyphID: simpleGID,
3434
XAdvance: fixed.I(10),
35+
Advance: fixed.I(10),
36+
Width: fixed.I(10),
37+
Height: -fixed.I(10),
38+
YBearing: fixed.I(10),
39+
}
40+
simpleGlyphVert = Glyph{
41+
GlyphID: simpleGID,
3542
YAdvance: -fixed.I(10),
43+
Advance: -fixed.I(10),
3644
Width: fixed.I(10),
3745
Height: -fixed.I(10),
3846
YBearing: fixed.I(10),
3947
}
4048
deepGlyph = Glyph{
4149
GlyphID: deepGID,
4250
XAdvance: fixed.I(10),
51+
Advance: fixed.I(10),
52+
XOffset: -fixed.I(5),
53+
Width: fixed.I(10),
54+
Height: -fixed.I(10),
55+
YBearing: fixed.I(0),
56+
}
57+
deepGlyphVert = Glyph{
58+
GlyphID: deepGID,
4359
YAdvance: -fixed.I(10),
60+
Advance: -fixed.I(10),
4461
XOffset: -fixed.I(5),
4562
Width: fixed.I(10),
4663
Height: -fixed.I(10),
@@ -49,7 +66,18 @@ var (
4966
offsetGlyph = Glyph{
5067
GlyphID: offsetGID,
5168
XAdvance: fixed.I(10),
69+
Advance: fixed.I(10),
70+
XOffset: -fixed.I(2),
71+
YOffset: fixed.I(2),
72+
Width: fixed.I(10),
73+
Height: -fixed.I(10),
74+
YBearing: fixed.I(10),
75+
XBearing: fixed.I(1),
76+
}
77+
offsetGlyphVert = Glyph{
78+
GlyphID: offsetGID,
5279
YAdvance: -fixed.I(10),
80+
Advance: -fixed.I(10),
5381
XOffset: -fixed.I(2),
5482
YOffset: fixed.I(2),
5583
Width: fixed.I(10),
@@ -120,12 +148,12 @@ func TestRecalculate(t *testing.T) {
120148
{
121149
Name: "vertical single simple glyph",
122150
Direction: di.DirectionTTB,
123-
Input: []Glyph{simpleGlyph_},
151+
Input: []Glyph{simpleGlyphVert},
124152
Output: Output{
125-
Glyphs: []Glyph{simpleGlyph_},
126-
Advance: simpleGlyph_.YAdvance,
153+
Glyphs: []Glyph{simpleGlyphVert},
154+
Advance: simpleGlyphVert.YAdvance,
127155
GlyphBounds: Bounds{
128-
Ascent: simpleGlyph_.Width,
156+
Ascent: simpleGlyphVert.Width,
129157
Descent: 0,
130158
},
131159
LineBounds: expectedFontExtents,
@@ -134,27 +162,27 @@ func TestRecalculate(t *testing.T) {
134162
{
135163
Name: "vertical glyph below baseline",
136164
Direction: di.DirectionTTB,
137-
Input: []Glyph{simpleGlyph_, deepGlyph},
165+
Input: []Glyph{simpleGlyphVert, deepGlyphVert},
138166
Output: Output{
139-
Glyphs: []Glyph{simpleGlyph_, deepGlyph},
140-
Advance: simpleGlyph_.YAdvance + deepGlyph.YAdvance,
167+
Glyphs: []Glyph{simpleGlyphVert, deepGlyphVert},
168+
Advance: simpleGlyphVert.YAdvance + deepGlyphVert.YAdvance,
141169
GlyphBounds: Bounds{
142-
Ascent: simpleGlyph_.Width,
143-
Descent: deepGlyph.XOffset + deepGlyph.XBearing,
170+
Ascent: simpleGlyphVert.Width,
171+
Descent: deepGlyphVert.XOffset + deepGlyphVert.XBearing,
144172
},
145173
LineBounds: expectedFontExtents,
146174
},
147175
},
148176
{
149177
Name: "vertical single complex glyph",
150178
Direction: di.DirectionTTB,
151-
Input: []Glyph{offsetGlyph},
179+
Input: []Glyph{offsetGlyphVert},
152180
Output: Output{
153-
Glyphs: []Glyph{offsetGlyph},
154-
Advance: offsetGlyph.YAdvance,
181+
Glyphs: []Glyph{offsetGlyphVert},
182+
Advance: offsetGlyphVert.YAdvance,
155183
GlyphBounds: Bounds{
156-
Ascent: offsetGlyph.Width + offsetGlyph.XOffset + offsetGlyph.XBearing,
157-
Descent: offsetGlyph.XOffset + offsetGlyph.XBearing,
184+
Ascent: offsetGlyphVert.Width + offsetGlyphVert.XOffset + offsetGlyphVert.XBearing,
185+
Descent: offsetGlyphVert.XOffset + offsetGlyphVert.XBearing,
158186
},
159187
LineBounds: expectedFontExtents,
160188
},
@@ -323,7 +351,7 @@ func TestAdvanceSpaceAware(t *testing.T) {
323351
Glyphs: []Glyph{
324352
{
325353
Width: 10,
326-
XAdvance: 10,
354+
Advance: 10,
327355
RuneCount: 1,
328356
GlyphCount: 1,
329357
},
@@ -341,7 +369,7 @@ func TestAdvanceSpaceAware(t *testing.T) {
341369
Glyphs: []Glyph{
342370
{
343371
Width: 0,
344-
XAdvance: 10,
372+
Advance: 10,
345373
RuneCount: 1,
346374
GlyphCount: 1,
347375
},
@@ -359,7 +387,7 @@ func TestAdvanceSpaceAware(t *testing.T) {
359387
Glyphs: []Glyph{
360388
{
361389
Width: 10,
362-
XAdvance: 10,
390+
Advance: 10,
363391
RuneCount: 1,
364392
GlyphCount: 1,
365393
},
@@ -377,7 +405,7 @@ func TestAdvanceSpaceAware(t *testing.T) {
377405
Glyphs: []Glyph{
378406
{
379407
Width: 0,
380-
XAdvance: 10,
408+
Advance: 10,
381409
RuneCount: 1,
382410
GlyphCount: 1,
383411
},
@@ -395,7 +423,7 @@ func TestAdvanceSpaceAware(t *testing.T) {
395423
Glyphs: []Glyph{
396424
{
397425
Width: 10,
398-
XAdvance: 10,
426+
Advance: 10,
399427
RuneCount: 1,
400428
GlyphCount: 1,
401429
},
@@ -413,7 +441,7 @@ func TestAdvanceSpaceAware(t *testing.T) {
413441
Glyphs: []Glyph{
414442
{
415443
Width: 0,
416-
XAdvance: 10,
444+
Advance: 10,
417445
RuneCount: 1,
418446
GlyphCount: 1,
419447
},
@@ -431,7 +459,7 @@ func TestAdvanceSpaceAware(t *testing.T) {
431459
Glyphs: []Glyph{
432460
{
433461
Width: 10,
434-
XAdvance: 10,
462+
Advance: 10,
435463
RuneCount: 1,
436464
GlyphCount: 1,
437465
},
@@ -449,7 +477,7 @@ func TestAdvanceSpaceAware(t *testing.T) {
449477
Glyphs: []Glyph{
450478
{
451479
Width: 0,
452-
XAdvance: 10,
480+
Advance: 10,
453481
RuneCount: 1,
454482
GlyphCount: 1,
455483
},

shaping/shaping.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ func (t *HarfbuzzShaper) Shape(input Input) Output {
113113
t.buf.Shape(font, t.features)
114114

115115
// Convert the shaped text into an Output.
116+
isVertical := input.Direction.IsVertical()
116117
glyphs := make([]Glyph, len(t.buf.Info))
117118
for i := range glyphs {
118119
g := t.buf.Info[i].Glyph
@@ -131,8 +132,13 @@ func (t *HarfbuzzShaper) Shape(input Input) Output {
131132
glyphs[i].Height = fixed.I(int(extents.Height)) >> scaleShift
132133
glyphs[i].XBearing = fixed.I(int(extents.XBearing)) >> scaleShift
133134
glyphs[i].YBearing = fixed.I(int(extents.YBearing)) >> scaleShift
134-
glyphs[i].XAdvance = fixed.I(int(t.buf.Pos[i].XAdvance)) >> scaleShift
135-
glyphs[i].YAdvance = fixed.I(int(t.buf.Pos[i].YAdvance)) >> scaleShift
135+
if isVertical {
136+
glyphs[i].YAdvance = fixed.I(int(t.buf.Pos[i].YAdvance)) >> scaleShift
137+
glyphs[i].Advance = glyphs[i].YAdvance
138+
} else {
139+
glyphs[i].XAdvance = fixed.I(int(t.buf.Pos[i].XAdvance)) >> scaleShift
140+
glyphs[i].Advance = glyphs[i].XAdvance
141+
}
136142
glyphs[i].XOffset = fixed.I(int(t.buf.Pos[i].XOffset)) >> scaleShift
137143
glyphs[i].YOffset = fixed.I(int(t.buf.Pos[i].YOffset)) >> scaleShift
138144
}

shaping/spacing.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ func (run *Output) AddWordSpacing(text []rune, additionalSpacing fixed.Int26_6)
3535
// we have a word separator: add space
3636
// we do it by enlarging the separator glyph advance
3737
// and distributing space around the glyph content
38+
run.Glyphs[i].Advance += additionalSpacing
3839
if isVertical {
3940
run.Glyphs[i].YAdvance += additionalSpacing
4041
run.Glyphs[i].YOffset += additionalSpacing / 2
@@ -64,6 +65,7 @@ func (run *Output) AddLetterSpacing(additionalSpacing fixed.Int26_6, isStartRun,
6465

6566
// start : apply spacing at boundary only if the run is not the first
6667
if startGIdx > 0 || !isStartRun {
68+
run.Glyphs[startGIdx].Advance += halfSpacing
6769
if isVertical {
6870
run.Glyphs[startGIdx].YAdvance += halfSpacing
6971
run.Glyphs[startGIdx].YOffset += halfSpacing
@@ -77,6 +79,7 @@ func (run *Output) AddLetterSpacing(additionalSpacing fixed.Int26_6, isStartRun,
7779
// end : apply spacing at boundary only if the run is not the last
7880
isLastCluster := startGIdx+startGlyph.GlyphCount >= len(run.Glyphs)
7981
if !isLastCluster || !isEndRun {
82+
run.Glyphs[endGIdx].Advance += halfSpacing
8083
if isVertical {
8184
run.Glyphs[endGIdx].YAdvance += halfSpacing
8285
} else {
@@ -99,6 +102,7 @@ func (run *Output) trimStartLetterSpacing() {
99102
}
100103
firstG := &run.Glyphs[0]
101104
halfSpacing := firstG.startLetterSpacing
105+
firstG.Advance -= halfSpacing
102106
if run.Direction.IsVertical() {
103107
firstG.YAdvance -= halfSpacing
104108
firstG.YOffset -= halfSpacing

shaping/wrapping.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -956,10 +956,12 @@ func (l *LineWrapper) postProcessLine(finalLine Line, done bool) (WrappedLine, b
956956
if finalVisualRun.Direction.IsVertical() {
957957
if finalVisualGlyph.Height == 0 {
958958
finalVisualGlyph.YAdvance = 0
959+
finalVisualGlyph.Advance = 0
959960
}
960961
} else { // horizontal
961962
if finalVisualGlyph.Width == 0 {
962963
finalVisualGlyph.XAdvance = 0
964+
finalVisualGlyph.Advance = 0
963965
}
964966
}
965967
beforeTrim := finalVisualRun.Advance

shaping/wrapping_test.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1567,8 +1567,7 @@ func complexGlyph(cluster, runes, glyphs int) Glyph {
15671567
return Glyph{
15681568
Width: fixed.I(10),
15691569
Height: fixed.I(10),
1570-
XAdvance: fixed.I(10),
1571-
YAdvance: fixed.I(10),
1570+
Advance: fixed.I(10),
15721571
YBearing: fixed.I(10),
15731572
ClusterIndex: cluster,
15741573
GlyphCount: glyphs,

0 commit comments

Comments
 (0)