MCPcopy
hub / github.com/tdewolff/canvas / ToText

Method ToText

text.go:647–1058  ·  view source on GitHub ↗

ToText takes the added text spans and fits them within a given box of certain width and height using Donald Knuth's line breaking algorithm.

(width, height float64, halign, valign TextAlign, opts *TextOptions)

Source from the content-addressed store, hash-verified

645
646// ToText takes the added text spans and fits them within a given box of certain width and height using Donald Knuth's line breaking algorithm.
647func (rt *RichText) ToText(width, height float64, halign, valign TextAlign, opts *TextOptions) *Text {
648 if opts == nil {
649 opts = &TextOptions{
650 Linebreaker: KnuthLinebreaker{},
651 }
652 } else if opts.Linebreaker == nil {
653 opts.Linebreaker = KnuthLinebreaker{}
654 }
655
656 log := rt.String()
657 logRunes := []rune(log)
658 embeddingLevels := text.EmbeddingLevels(logRunes)
659
660 // itemize string by font face and script, this also splits on embedding level boundaries and
661 // unicode.ReplacementChar (replaced by object)
662 i := 0 // index into logRunes
663 curFace := 0 // index into rt.faces
664 runs := []textRun{}
665 for j := range append(logRunes, 0) {
666 nextFace := rt.locs.index(j)
667 if nextFace != curFace || j == len(logRunes) {
668 items := text.ScriptItemizer(logRunes[i:j], embeddingLevels[i:j])
669 for _, item := range items {
670 direction, rotation := scriptDirection(rt.mode, rt.orient, item.Script, item.Level, rt.faces[curFace].Direction)
671 runs = append(runs, textRun{
672 Text: item.Text,
673 Level: item.Level,
674 Face: rt.faces[curFace],
675 Script: item.Script,
676 Direction: direction,
677 Rotation: rotation,
678 })
679 }
680 curFace = nextFace
681 i = j
682 }
683 }
684
685 // shape text into glyphs and keep index into runs
686 clusterOffset := uint32(0)
687 glyphIndices := indexer{} // indexes glyphs into runs
688 glyphs := make([]text.Glyph, 0, len(logRunes))
689 for _, run := range runs {
690 ppem := run.Face.PPEM(DefaultResolution)
691 glyphRun := run.Face.Font.shaper.Shape(run.Text, ppem, run.Direction, run.Script, run.Face.Language, run.Face.Font.features, run.Face.Font.variations)
692 for i := range glyphRun {
693 glyph := &glyphRun[i]
694 glyph.SFNT = run.Face.Font.SFNT
695 glyph.Size = run.Face.Size
696 glyph.Script = run.Script
697 glyph.Cluster += clusterOffset
698 if obj, ok := rt.objects[glyph.Cluster]; ok {
699 // path/image objects
700 ppem := float64(run.Face.Font.SFNT.Head.UnitsPerEm)
701 xadv, yadv := obj.Width, obj.Height
702 if rt.mode != HorizontalTB {
703 yadv = -yadv
704 }

Callers 10

DrawPreviewWithAssetsFunction · 0.95
renderBlockMethod · 0.95
NewTextBoxFunction · 0.95
TestRichTextPositionsFunction · 0.95
TestRichTextFunction · 0.95
TestTextBoundsFunction · 0.95
mainFunction · 0.95
drawCJKFunction · 0.95
doTestPDFTextFunction · 0.95
drawFunction · 0.95

Calls 15

indexMethod · 0.95
HeightsMethod · 0.95
ResetMethod · 0.95
EmbeddingLevelsFunction · 0.92
ScriptItemizerFunction · 0.92
IsVerticalScriptFunction · 0.92
GlyphsToItemsFunction · 0.92
scriptDirectionFunction · 0.85
reorderSpansFunction · 0.85
PPEMMethod · 0.80
textWidthMethod · 0.80
heightsMethod · 0.80

Tested by 4

TestRichTextPositionsFunction · 0.76
TestRichTextFunction · 0.76
TestTextBoundsFunction · 0.76
doTestPDFTextFunction · 0.76