~eliasnaur/gio

6 2

multi-line text layout

Details
Message ID
<zS4c0f6eVn_cdejSD4Tf9fOZPFxRciXXldZc4Cvj5mwYyLT8yYW6l8wj15-3gOq3q2Mp2KZTOTcyJyLUYPbDbWAeEppximjgoriH14EVQuo=@sbinet.org>
DKIM signature
missing
Download raw message
hi there,

I am trying to understand the model behind writing lines of text in Gio.

more precisely, in gonum/plot, I am trying to devise a bounding box around a piece of text, as tightly as possible.

I hacked a couple of lines in Gio to display the lines bounding boxes to see what gives:

===
diff --git a/widget/label.go b/widget/label.go
index 629731d..6d783ec 100644
--- a/widget/label.go
+++ b/widget/label.go
@@ -5,8 +5,10 @@ package widget
 import (
 	"fmt"
 	"image"
+	"image/color"
 	"unicode/utf8"

+	"gioui.org/f32"
 	"gioui.org/layout"
 	"gioui.org/op"
 	"gioui.org/op/clip"
@@ -117,6 +119,59 @@ func (l Label) Layout(gtx layout.Context, s text.Shaper, font text.Font, size un
 		paint.PaintOp{}.Add(gtx.Ops)
 		stack.Pop()
 	}
+
+	if true {
+		// glyphboxes
+		it := lineIterator{
+			Lines:     lines,
+			Clip:      cl,
+			Alignment: l.Alignment,
+			Width:     dims.Size.X,
+		}
+		for {
+			var line text.Line
+			if len(it.Lines) > 0 {
+				line = it.Lines[0]
+			}
+			_, off, ok := it.Next()
+			if !ok {
+				break
+			}
+			stack := op.Push(gtx.Ops)
+			op.Offset(layout.FPt(off)).Add(gtx.Ops)
+			var p clip.Path
+			p.Begin(gtx.Ops)
+			fpt := func(v fixed.Int26_6) float32 {
+				return float32(v.Floor())
+			}
+			p.MoveTo(f32.Point{
+				X: fpt(line.Bounds.Min.X),
+				Y: fpt(line.Bounds.Min.Y),
+			})
+			p.LineTo(f32.Point{
+				X: fpt(line.Bounds.Max.X),
+				Y: fpt(line.Bounds.Min.Y),
+			})
+			p.LineTo(f32.Point{
+				X: fpt(line.Bounds.Max.X),
+				Y: fpt(line.Bounds.Max.Y),
+			})
+			p.LineTo(f32.Point{
+				X: fpt(line.Bounds.Min.X),
+				Y: fpt(line.Bounds.Max.Y),
+			})
+			p.Close()
+			clip.Stroke{
+				Path: p.End(),
+				Style: clip.StrokeStyle{
+					Width: 2,
+				},
+			}.Op().Add(gtx.Ops)
+			paint.Fill(gtx.Ops, color.NRGBA{R: 255, B: 255, A: 125})
+			stack.Pop()
+		}
+
+	}
 	return dims
 }
===

this gave something like:
- https://github.com/gonum/plot/pull/650#issuecomment-745471755

(the red lines are the gonum/plot bounding boxes, the magenta ones are the Gio ones)

from this little experiment, it seems a multi-line piece of text's height is defined as (from the top line to the bottom):
- ascent     [line n]
- descent    [line n]
- line-gap   [line n]
- cap-height [line n-1]
- descent    [line n-1]
- line-gap   [line n-1]
[...]
- cap-height [line 0]
- descent    [line 0]
- line-gap   [line 0]

is that mental model correct ?
there's probably something wrong with that mental model, though, because applying this formula to compute the height of a bounding box:

nLines := computeNumberLines(txt)
ftMetrics := sfnt.Font.Metrics(...)
desc   := ftMetrics.Height - ftMetrics.Ascent // total descent (descent + line-gap)
height := nLines * (ftMetrics.CapHeight + desc) - ftMetrics.CapHeight + ftMetrics.Ascent

leads to some part of the many-line text blocks to be cut off. (as can be seen on the faint red-lines for the "Bg\nBg\nBg\nBg\nBg" text block)

what am I missing?

cheers,
-s
Details
Message ID
<C7UC2CP00B04.3O0BSGJJV6SPN@themachine>
In-Reply-To
<zS4c0f6eVn_cdejSD4Tf9fOZPFxRciXXldZc4Cvj5mwYyLT8yYW6l8wj15-3gOq3q2Mp2KZTOTcyJyLUYPbDbWAeEppximjgoriH14EVQuo=@sbinet.org> (view parent)
DKIM signature
pass
Download raw message
I haven't thought through your email yet, but wanted to point out that
I've wanted to change the multi-line layout algorithm to match Figma
(and CSS). See

https://www.figma.com/blog/line-height-changes/

With the Figma approach I hope to get rid of some magic padding around
the border of Editor (and maybe Label?). For example textPadding[0] and
pointerPadding[1].

Elias

[0] https://git.sr.ht/~eliasnaur/gio/tree/main/widget/editor.go#L398
[1] https://git.sr.ht/~eliasnaur/gio/tree/main/widget/editor.go#L423

On Wed Dec 16, 2020 at 09:43, Sebastien Binet wrote:
> hi there,
>
> I am trying to understand the model behind writing lines of text in Gio.
>
> more precisely, in gonum/plot, I am trying to devise a bounding box around a piece of text, as tightly as possible.
>
> I hacked a couple of lines in Gio to display the lines bounding boxes to see what gives:
>
> ===
> diff --git a/widget/label.go b/widget/label.go
> index 629731d..6d783ec 100644
> --- a/widget/label.go
> +++ b/widget/label.go
> @@ -5,8 +5,10 @@ package widget
>  import (
>  	"fmt"
>  	"image"
> +	"image/color"
>  	"unicode/utf8"
>
> +	"gioui.org/f32"
>  	"gioui.org/layout"
>  	"gioui.org/op"
>  	"gioui.org/op/clip"
> @@ -117,6 +119,59 @@ func (l Label) Layout(gtx layout.Context, s text.Shaper, font text.Font, size un
>  		paint.PaintOp{}.Add(gtx.Ops)
>  		stack.Pop()
>  	}
> +
> +	if true {
> +		// glyphboxes
> +		it := lineIterator{
> +			Lines:     lines,
> +			Clip:      cl,
> +			Alignment: l.Alignment,
> +			Width:     dims.Size.X,
> +		}
> +		for {
> +			var line text.Line
> +			if len(it.Lines) > 0 {
> +				line = it.Lines[0]
> +			}
> +			_, off, ok := it.Next()
> +			if !ok {
> +				break
> +			}
> +			stack := op.Push(gtx.Ops)
> +			op.Offset(layout.FPt(off)).Add(gtx.Ops)
> +			var p clip.Path
> +			p.Begin(gtx.Ops)
> +			fpt := func(v fixed.Int26_6) float32 {
> +				return float32(v.Floor())
> +			}
> +			p.MoveTo(f32.Point{
> +				X: fpt(line.Bounds.Min.X),
> +				Y: fpt(line.Bounds.Min.Y),
> +			})
> +			p.LineTo(f32.Point{
> +				X: fpt(line.Bounds.Max.X),
> +				Y: fpt(line.Bounds.Min.Y),
> +			})
> +			p.LineTo(f32.Point{
> +				X: fpt(line.Bounds.Max.X),
> +				Y: fpt(line.Bounds.Max.Y),
> +			})
> +			p.LineTo(f32.Point{
> +				X: fpt(line.Bounds.Min.X),
> +				Y: fpt(line.Bounds.Max.Y),
> +			})
> +			p.Close()
> +			clip.Stroke{
> +				Path: p.End(),
> +				Style: clip.StrokeStyle{
> +					Width: 2,
> +				},
> +			}.Op().Add(gtx.Ops)
> +			paint.Fill(gtx.Ops, color.NRGBA{R: 255, B: 255, A: 125})
> +			stack.Pop()
> +		}
> +
> +	}
>  	return dims
>  }
> ===
>
> this gave something like:
> - https://github.com/gonum/plot/pull/650#issuecomment-745471755
>
> (the red lines are the gonum/plot bounding boxes, the magenta ones are the Gio ones)
>
> from this little experiment, it seems a multi-line piece of text's height is defined as (from the top line to the bottom):
> - ascent     [line n]
> - descent    [line n]
> - line-gap   [line n]
> - cap-height [line n-1]
> - descent    [line n-1]
> - line-gap   [line n-1]
> [...]
> - cap-height [line 0]
> - descent    [line 0]
> - line-gap   [line 0]
>
> is that mental model correct ?
> there's probably something wrong with that mental model, though, because applying this formula to compute the height of a bounding box:
>
> nLines := computeNumberLines(txt)
> ftMetrics := sfnt.Font.Metrics(...)
> desc   := ftMetrics.Height - ftMetrics.Ascent // total descent (descent + line-gap)
> height := nLines * (ftMetrics.CapHeight + desc) - ftMetrics.CapHeight + ftMetrics.Ascent
>
> leads to some part of the many-line text blocks to be cut off. (as can be seen on the faint red-lines for the "Bg\nBg\nBg\nBg\nBg" text block)
>
> what am I missing?
>
> cheers,
> -s
Details
Message ID
<C7UYKI9IW9YW.2KU29KLHGYT2@testmac>
In-Reply-To
<zS4c0f6eVn_cdejSD4Tf9fOZPFxRciXXldZc4Cvj5mwYyLT8yYW6l8wj15-3gOq3q2Mp2KZTOTcyJyLUYPbDbWAeEppximjgoriH14EVQuo=@sbinet.org> (view parent)
DKIM signature
fail
Download raw message
DKIM signature: fail
On Wed Dec 16, 2020 at 10:43 AM CET, Sebastien Binet wrote:
> hi there,
>
> I am trying to understand the model behind writing lines of text in Gio.
>
> more precisely, in gonum/plot, I am trying to devise a bounding box
> around a piece of text, as tightly as possible.
>
> I hacked a couple of lines in Gio to display the lines bounding boxes to
> see what gives:
>
> ===
> diff --git a/widget/label.go b/widget/label.go
> index 629731d..6d783ec 100644
> --- a/widget/label.go
> +++ b/widget/label.go
> @@ -5,8 +5,10 @@ package widget
> import (
> "fmt"
> "image"
> + "image/color"
> "unicode/utf8"
>
> + "gioui.org/f32"
> "gioui.org/layout"
> "gioui.org/op"
> "gioui.org/op/clip"
> @@ -117,6 +119,59 @@ func (l Label) Layout(gtx layout.Context, s
> text.Shaper, font text.Font, size un
> paint.PaintOp{}.Add(gtx.Ops)
> stack.Pop()
> }
> +
> + if true {
> + // glyphboxes
> + it := lineIterator{
> + Lines: lines,
> + Clip: cl,
> + Alignment: l.Alignment,
> + Width: dims.Size.X,
> + }
> + for {
> + var line text.Line
> + if len(it.Lines) > 0 {
> + line = it.Lines[0]
> + }
> + _, off, ok := it.Next()
> + if !ok {
> + break
> + }
> + stack := op.Push(gtx.Ops)
> + op.Offset(layout.FPt(off)).Add(gtx.Ops)
> + var p clip.Path
> + p.Begin(gtx.Ops)
> + fpt := func(v fixed.Int26_6) float32 {
> + return float32(v.Floor())
> + }
> + p.MoveTo(f32.Point{
> + X: fpt(line.Bounds.Min.X),
> + Y: fpt(line.Bounds.Min.Y),
> + })
> + p.LineTo(f32.Point{
> + X: fpt(line.Bounds.Max.X),
> + Y: fpt(line.Bounds.Min.Y),
> + })
> + p.LineTo(f32.Point{
> + X: fpt(line.Bounds.Max.X),
> + Y: fpt(line.Bounds.Max.Y),
> + })
> + p.LineTo(f32.Point{
> + X: fpt(line.Bounds.Min.X),
> + Y: fpt(line.Bounds.Max.Y),
> + })
> + p.Close()
> + clip.Stroke{
> + Path: p.End(),
> + Style: clip.StrokeStyle{
> + Width: 2,
> + },
> + }.Op().Add(gtx.Ops)
> + paint.Fill(gtx.Ops, color.NRGBA{R: 255, B: 255, A: 125})
> + stack.Pop()
> + }
> +
> + }
> return dims
> }
> ===
>
> this gave something like:
> - https://github.com/gonum/plot/pull/650#issuecomment-745471755
>
> (the red lines are the gonum/plot bounding boxes, the magenta ones are
> the Gio ones)
>
> from this little experiment, it seems a multi-line piece of text's
> height is defined as (from the top line to the bottom):
> - ascent [line n]
> - descent [line n]
> - line-gap [line n]
> - cap-height [line n-1]
> - descent [line n-1]
> - line-gap [line n-1]
> [...]
> - cap-height [line 0]
> - descent [line 0]
> - line-gap [line 0]
>
> is that mental model correct ?
> there's probably something wrong with that mental model, though, because
> applying this formula to compute the height of a bounding box:
>

There may still be a layout bug in Editor/Label, but note that the
cap-height is not used anywhere. text.Line[0] only defines Ascent and
Descent (inlcuding line-gap). Did I miss something?

Elias

[0] https://git.sr.ht/~eliasnaur/gio/tree/main/text/text.go#L14
Details
Message ID
<UNcFzyxD2QV3wbWZqB2f08TzO4kBfeu5KMTShAa7Yw@cp4-web-027.plabs.ch>
In-Reply-To
<C7UYKI9IW9YW.2KU29KLHGYT2@testmac> (view parent)
DKIM signature
missing
Download raw message
On Thu Dec 17, 2020 at 10:37 CET, Elias Naur wrote:
> On Wed Dec 16, 2020 at 10:43 AM CET, Sebastien Binet wrote:
> > hi there,
> >
> > I am trying to understand the model behind writing lines of text in Gio.
> >
> > more precisely, in gonum/plot, I am trying to devise a bounding box
> > around a piece of text, as tightly as possible.
> >
> > I hacked a couple of lines in Gio to display the lines bounding boxes to
> > see what gives:
> >
> > ===
> > diff --git a/widget/label.go b/widget/label.go
> > index 629731d..6d783ec 100644
> > --- a/widget/label.go
> > +++ b/widget/label.go
> > @@ -5,8 +5,10 @@ package widget
> > import (
> > "fmt"
> > "image"
> > + "image/color"
> > "unicode/utf8"
> >
> > + "gioui.org/f32"
> > "gioui.org/layout"
> > "gioui.org/op"
> > "gioui.org/op/clip"
> > @@ -117,6 +119,59 @@ func (l Label) Layout(gtx layout.Context, s
> > text.Shaper, font text.Font, size un
> > paint.PaintOp{}.Add(gtx.Ops)
> > stack.Pop()
> > }
> > +
> > + if true {
> > + // glyphboxes
> > + it := lineIterator{
> > + Lines: lines,
> > + Clip: cl,
> > + Alignment: l.Alignment,
> > + Width: dims.Size.X,
> > + }
> > + for {
> > + var line text.Line
> > + if len(it.Lines) > 0 {
> > + line = it.Lines[0]
> > + }
> > + _, off, ok := it.Next()
> > + if !ok {
> > + break
> > + }
> > + stack := op.Push(gtx.Ops)
> > + op.Offset(layout.FPt(off)).Add(gtx.Ops)
> > + var p clip.Path
> > + p.Begin(gtx.Ops)
> > + fpt := func(v fixed.Int26_6) float32 {
> > + return float32(v.Floor())
> > + }
> > + p.MoveTo(f32.Point{
> > + X: fpt(line.Bounds.Min.X),
> > + Y: fpt(line.Bounds.Min.Y),
> > + })
> > + p.LineTo(f32.Point{
> > + X: fpt(line.Bounds.Max.X),
> > + Y: fpt(line.Bounds.Min.Y),
> > + })
> > + p.LineTo(f32.Point{
> > + X: fpt(line.Bounds.Max.X),
> > + Y: fpt(line.Bounds.Max.Y),
> > + })
> > + p.LineTo(f32.Point{
> > + X: fpt(line.Bounds.Min.X),
> > + Y: fpt(line.Bounds.Max.Y),
> > + })
> > + p.Close()
> > + clip.Stroke{
> > + Path: p.End(),
> > + Style: clip.StrokeStyle{
> > + Width: 2,
> > + },
> > + }.Op().Add(gtx.Ops)
> > + paint.Fill(gtx.Ops, color.NRGBA{R: 255, B: 255, A: 125})
> > + stack.Pop()
> > + }
> > +
> > + }
> > return dims
> > }
> > ===
> >
> > this gave something like:
> > - https://github.com/gonum/plot/pull/650#issuecomment-745471755
> >
> > (the red lines are the gonum/plot bounding boxes, the magenta ones are
> > the Gio ones)
> >
> > from this little experiment, it seems a multi-line piece of text's
> > height is defined as (from the top line to the bottom):
> > - ascent [line n]
> > - descent [line n]
> > - line-gap [line n]
> > - cap-height [line n-1]
> > - descent [line n-1]
> > - line-gap [line n-1]
> > [...]
> > - cap-height [line 0]
> > - descent [line 0]
> > - line-gap [line 0]
> >
> > is that mental model correct ?
> > there's probably something wrong with that mental model, though, because
> > applying this formula to compute the height of a bounding box:
> >
>
> There may still be a layout bug in Editor/Label, but note that the
> cap-height is not used anywhere. text.Line[0] only defines Ascent and
> Descent (inlcuding line-gap). Did I miss something?

no. I did: I somehow missed -or forgot to use those, after checking what
the bounding box looked like- the Ascent/Descent fields.

now, the Gio "glyph boxes" (in magenta) look nice:
- https://github.com/gonum/plot/pull/650#issuecomment-747943312

BTW: any interest in packaging this into a "debugging" layout?
I surmise it could be useful for some people.

propably guarded behind a top-level 'const enableGlyphBoxes = false` ?

-s
Details
Message ID
<C7VS9JYGGYY0.OP5RP4TR35N@testmac>
In-Reply-To
<UNcFzyxD2QV3wbWZqB2f08TzO4kBfeu5KMTShAa7Yw@cp4-web-027.plabs.ch> (view parent)
DKIM signature
fail
Download raw message
DKIM signature: fail
On Fri Dec 18, 2020 at 9:38 AM CET, Sebastien Binet wrote:
> On Thu Dec 17, 2020 at 10:37 CET, Elias Naur wrote:
> > On Wed Dec 16, 2020 at 10:43 AM CET, Sebastien Binet wrote:
> > > hi there,
> > >
> > > I am trying to understand the model behind writing lines of text in Gio.
> > >
> > > more precisely, in gonum/plot, I am trying to devise a bounding box
> > > around a piece of text, as tightly as possible.
> > >
> > > I hacked a couple of lines in Gio to display the lines bounding boxes to
> > > see what gives:
> > >
> > > ===
> > > diff --git a/widget/label.go b/widget/label.go
> > > index 629731d..6d783ec 100644
> > > --- a/widget/label.go
> > > +++ b/widget/label.go
> > > @@ -5,8 +5,10 @@ package widget
> > > import (
> > > "fmt"
> > > "image"
> > > + "image/color"
> > > "unicode/utf8"
> > >
> > > + "gioui.org/f32"
> > > "gioui.org/layout"
> > > "gioui.org/op"
> > > "gioui.org/op/clip"
> > > @@ -117,6 +119,59 @@ func (l Label) Layout(gtx layout.Context, s
> > > text.Shaper, font text.Font, size un
> > > paint.PaintOp{}.Add(gtx.Ops)
> > > stack.Pop()
> > > }
> > > +
> > > + if true {
> > > + // glyphboxes
> > > + it := lineIterator{
> > > + Lines: lines,
> > > + Clip: cl,
> > > + Alignment: l.Alignment,
> > > + Width: dims.Size.X,
> > > + }
> > > + for {
> > > + var line text.Line
> > > + if len(it.Lines) > 0 {
> > > + line = it.Lines[0]
> > > + }
> > > + _, off, ok := it.Next()
> > > + if !ok {
> > > + break
> > > + }
> > > + stack := op.Push(gtx.Ops)
> > > + op.Offset(layout.FPt(off)).Add(gtx.Ops)
> > > + var p clip.Path
> > > + p.Begin(gtx.Ops)
> > > + fpt := func(v fixed.Int26_6) float32 {
> > > + return float32(v.Floor())
> > > + }
> > > + p.MoveTo(f32.Point{
> > > + X: fpt(line.Bounds.Min.X),
> > > + Y: fpt(line.Bounds.Min.Y),
> > > + })
> > > + p.LineTo(f32.Point{
> > > + X: fpt(line.Bounds.Max.X),
> > > + Y: fpt(line.Bounds.Min.Y),
> > > + })
> > > + p.LineTo(f32.Point{
> > > + X: fpt(line.Bounds.Max.X),
> > > + Y: fpt(line.Bounds.Max.Y),
> > > + })
> > > + p.LineTo(f32.Point{
> > > + X: fpt(line.Bounds.Min.X),
> > > + Y: fpt(line.Bounds.Max.Y),
> > > + })
> > > + p.Close()
> > > + clip.Stroke{
> > > + Path: p.End(),
> > > + Style: clip.StrokeStyle{
> > > + Width: 2,
> > > + },
> > > + }.Op().Add(gtx.Ops)
> > > + paint.Fill(gtx.Ops, color.NRGBA{R: 255, B: 255, A: 125})
> > > + stack.Pop()
> > > + }
> > > +
> > > + }
> > > return dims
> > > }
> > > ===
> > >
> > > this gave something like:
> > > - https://github.com/gonum/plot/pull/650#issuecomment-745471755
> > >
> > > (the red lines are the gonum/plot bounding boxes, the magenta ones are
> > > the Gio ones)
> > >
> > > from this little experiment, it seems a multi-line piece of text's
> > > height is defined as (from the top line to the bottom):
> > > - ascent [line n]
> > > - descent [line n]
> > > - line-gap [line n]
> > > - cap-height [line n-1]
> > > - descent [line n-1]
> > > - line-gap [line n-1]
> > > [...]
> > > - cap-height [line 0]
> > > - descent [line 0]
> > > - line-gap [line 0]
> > >
> > > is that mental model correct ?
> > > there's probably something wrong with that mental model, though, because
> > > applying this formula to compute the height of a bounding box:
> > >
> >
> > There may still be a layout bug in Editor/Label, but note that the
> > cap-height is not used anywhere. text.Line[0] only defines Ascent and
> > Descent (inlcuding line-gap). Did I miss something?
>
> no. I did: I somehow missed -or forgot to use those, after checking what
> the bounding box looked like- the Ascent/Descent fields.
>
> now, the Gio "glyph boxes" (in magenta) look nice:
> - https://github.com/gonum/plot/pull/650#issuecomment-747943312
>
> BTW: any interest in packaging this into a "debugging" layout?
> I surmise it could be useful for some people.
>
> propably guarded behind a top-level 'const enableGlyphBoxes = false` ?
>

Hmm, I like to idea of debugging guides, but would rather not pollute
the already complex Label/Editor layout code. One idea is to add the
debugging aids to the clip paths of each line or chunk of text, leaving
Editor and Label oblivious to them. And it would work everywhere text is
laid out.

Elias
Details
Message ID
<9ZBRVjI1WsgWBeSO1whk9P4j2nWmag487pLs0uI2v8@cp7-web-041.plabs.ch>
In-Reply-To
<C7VS9JYGGYY0.OP5RP4TR35N@testmac> (view parent)
DKIM signature
missing
Download raw message
On Fri Dec 18, 2020 at 09:54 CET, Elias Naur wrote:
[...]

> > BTW: any interest in packaging this into a "debugging" layout?
> > I surmise it could be useful for some people.
> >
> > propably guarded behind a top-level 'const enableGlyphBoxes = false` ?
> >
>
> Hmm, I like to idea of debugging guides, but would rather not pollute
> the already complex Label/Editor layout code. One idea is to add the
> debugging aids to the clip paths of each line or chunk of text, leaving
> Editor and Label oblivious to them. And it would work everywhere text is
> laid out.

so having the glyphboxes being drawn during the textPath (in
font/opentype)?

I'll give it a stab over the week-end.

-s
Details
Message ID
<C7VX2Z2T4Y7L.R20Q0CGA0KZE@themachine>
In-Reply-To
<9ZBRVjI1WsgWBeSO1whk9P4j2nWmag487pLs0uI2v8@cp7-web-041.plabs.ch> (view parent)
DKIM signature
pass
Download raw message
On Fri Dec 18, 2020 at 09:39, Sebastien Binet wrote:
> On Fri Dec 18, 2020 at 09:54 CET, Elias Naur wrote:
> [...]
>
> > > BTW: any interest in packaging this into a "debugging" layout?
> > > I surmise it could be useful for some people.
> > >
> > > propably guarded behind a top-level 'const enableGlyphBoxes = false` ?
> > >
> >
> > Hmm, I like to idea of debugging guides, but would rather not pollute
> > the already complex Label/Editor layout code. One idea is to add the
> > debugging aids to the clip paths of each line or chunk of text, leaving
> > Editor and Label oblivious to them. And it would work everywhere text is
> > laid out.
>
> so having the glyphboxes being drawn during the textPath (in
> font/opentype)?
>
> I'll give it a stab over the week-end.
>

Sounds good to me, thanks.

Elias
Reply to thread Export thread (mbox)