gui.typeset
Text for the native UI: fonts, fallback, OpenType shaping, bidi, line breaking, paragraph layout, glyph masks and caret geometry.
import gui.typeset
This package turns styled text into lines of positioned glyphs and draws those glyphs as coverage masks. It is the text half of the native UI runtime: the page language uses it to lay out every heading, paragraph and input, and a painter blends its masks into pixels. It is written in Salam with no outside library, and Persian and mixed Persian and English text are the main case it is built for.
The steps are the ones a browser takes. A FontCollection holds fonts, picks a face for every character from a family list like CSS font-family and falls back per script to other faces, the system fonts included. NewParagraph splits styled spans into bidi, script and font runs and shapes each run once with the font's OpenType tables: joining forms, ligatures, kerning and mark positioning. LayoutParagraph breaks lines at any width without shaping again, reorders each line for right to left text and aligns it. RasterizeGlyph and GlyphCache give 8 bit masks, and HitTest, CaretRect and SelectionRects give the geometry an editor needs.
Things to know
- TrueType outlines only. Fonts with CFF outlines (most
.otffiles) are skipped by the collection and refused byLoadFont. - Offsets are UTF-8 byte offsets into
Paragraph.text, the span texts joined together.SpanAtmaps an offset back to its span, and every glyph run carries thetagof its span. - Layout math is fixed point in 1/64 pixel and masks are made with integer math, so the numbers and the pixels are the same on every OS and backend.
- When a font has no Arabic joining features the shaper uses the Unicode presentation forms instead, like
std/ai/imagealways did; that package now uses this one for its fonts. - A mask from
CachedGlyphbelongs to the cache and stays valid until a later call may evict it; draw it before asking for more. - The examples read fonts from the
books/fontsfolder of the Salam repository.
Lay out a mixed Persian and English paragraph
Each span has its own family list and size; the tag lets you find which element a run came from. The paragraph is shaped once, then laid out at two widths. In this right to left paragraph the English word keeps its own left to right order inside the line, and every line is aligned to the right, the start side.
import gui.typeset
import os
import filepath
func main:
fonts := filepath.Join(filepath.Dir(os.Env("SALAM_STD")), "books/fonts/")
mut fc := typeset.NewFontCollection()
typeset.AddFontFile(fc, fonts + "XB Zar.ttf")
typeset.AddFontFile(fc, fonts + "DejaVuSansMono.ttf")
mut spans := Vector {} as Vector<typeset.TextSpan>
spans.push(typeset.TextSpan { text = "زبان برنامهنویسی ", families = "XB Zar", size = 20.0, tag = 1 })
spans.push(typeset.TextSpan { text = "Salam", families = "DejaVu Sans Mono", size = 16.0, tag = 2 })
spans.push(typeset.TextSpan { text = " متن فارسی را درست میچیند.", families = "XB Zar", size = 20.0, tag = 3 })
mut p := typeset.NewParagraph(fc, spans, typeset.ParagraphStyle {})
println "min", typeset.MinContentWidth(p), "max", typeset.MaxContentWidth(p)
each width in [400.0, 160.0]:
mut l := typeset.LayoutParagraph(p, fc, width)
println "width", width, "lines", l.lines.len(), "height", l.height
each line in l.lines:
print " baseline ", line.baseline, ":"
mut k := line.run_start
until k < line.run_start + line.run_count:
run := l.runs.get(k)
if run.glyph_count > 0:
print " [tag ", run.tag, " x ", run.x, (run.rtl ? " rtl" : " ltr"), "]"
end
k++
end
println ""
end
typeset.FreeLayout(l)
end
typeset.FreeParagraph(p)
spans.free()
typeset.FreeFontCollection(fc)
endMinContentWidth and MaxContentWidth are what a flex or table layout needs before it decides the width. Changing only the width calls LayoutParagraph again; the fonts and the shaping stay cached in the paragraph.
Caret and selection in a text input
An input keeps a TextPosition: a byte offset and whether it sticks to the text before it. HitTest turns a click into a position, MoveVisual moves it as the arrow keys do on screen, and CaretRect says where to draw it. On a line that mixes directions the caret walks through the English letters from right to left of the screen, the way the eye follows them.
import gui.typeset
import os
import filepath
func main:
mut fc := typeset.NewFontCollection()
typeset.AddFontFile(fc, filepath.Join(filepath.Dir(os.Env("SALAM_STD")), "books/fonts/XB Zar.ttf"))
mut spans := Vector {} as Vector<typeset.TextSpan>
spans.push(typeset.TextSpan { text = "سلام ABC دنیا", families = "XB Zar", size = 20.0 })
mut st := typeset.ParagraphStyle {}
st.white_space = typeset.WhiteSpace.PreWrap
mut p := typeset.NewParagraph(fc, spans, st)
mut l := typeset.LayoutParagraph(p, fc, 0.0)
mut pos := typeset.HitTest(p, l, l.width, 10.0)
println "click at the right edge: offset", pos.offset
repeat 6:
pos = typeset.MoveVisual(p, l, pos, false)
caret := typeset.CaretRect(p, l, pos)
println "left arrow: offset", pos.offset, "caret x", caret.x
end
rects := typeset.SelectionRects(p, l, 6, 15)
println "selection of 'م ABC د' needs", rects.len(), "rectangles"
rects.free()
typeset.FreeLayout(l)
typeset.FreeParagraph(p)
spans.free()
typeset.FreeFontCollection(fc)
endThe selection of a range that crosses a direction change can need more than one rectangle; here it stays one because the selected pieces sit next to each other on screen. NextGrapheme and NextWordEnd give the logical moves for Backspace, Delete and Ctrl with an arrow key.
Types
FontFace
struct FontFace| Name | Type | Description |
|---|---|---|
path | str = "" | The file the face comes from, empty for bytes. |
index | int = 0 | The face number inside the file. |
family | str = "" | The family name. |
style | str = "" | The style name. |
weight | int = 400 | The weight. |
italic | bool = false | The face is italic. |
loaded | bool = false | The font data is in memory. |
failed | bool = false | Loading the file failed; the face is skipped. |
font | Font | The loaded font. |
import gui.typeset
import os
import filepath
import archive
import compress
func font_path(name: str): str:
ret filepath.Join(filepath.Dir(os.Env("SALAM_STD")), "books/fonts/" + name)
end
func main:
mut ok := false
mut f := typeset.LoadFont(font_path("XB Zar.ttf"), ok)
m := typeset.Metrics(f)
println typeset.FamilyName(f), typeset.StyleName(f), typeset.FullName(f), typeset.NameString(f, 1)
println typeset.Weight(f), typeset.IsItalic(f), typeset.UnitsPerEm(f), typeset.NumGlyphs(f), typeset.FontValid(f)
println m.ascent, m.descent, m.line_gap, m.x_height, m.cap_height, m.underline_position, m.underline_thickness, m.units_per_em
println typeset.ScaleFactor(f, 20.48), typeset.AscentPixels(f, 20.48), typeset.DescentPixels(f, 20.48), typeset.LineHeightPixels(f, 20.48)
beh := typeset.GlyphIndex(f, 0x0628)
mut x0 := 0
mut y0 := 0
mut x1 := 0
mut y1 := 0
println beh, typeset.GlyphAdvance(f, beh), typeset.GlyphBox(f, beh, x0, y0, x1, y1), x0, y0, x1, y1, typeset.GlyphHasOutline(f, beh)
println typeset.KernAdvance(f, beh, beh)
typeset.FreeFont(f)
mut bok := false
mut buf := archive.ReadBinaryFile(font_path("XB Zar Bd.ttf"), bok)
println typeset.FaceCount(buf.data, buf.len), typeset.IsCFFFont(buf.data, buf.len)
mut pok := false
bold := typeset.ParseFontIndex(buf.data, buf.len, 0, pok)
mut fc := typeset.NewFontCollection()
typeset.AddFont(fc, bold)
typeset.AddFontBytes(fc, buf.data, buf.len)
compress.BufFree(buf)
typeset.AddFontFile(fc, font_path("XB Zar.ttf"))
typeset.AddFontFile(fc, font_path("DejaVuSansMono.ttf"))
println typeset.FaceCountIn(fc), typeset.FindFace(fc, "XB Zar", 400, false), typeset.FindFace(fc, "xb zar", 700, false)
println typeset.FaceForCodepoint(fc, "DejaVu Sans Mono, XB Zar", 400, false, 0x41), typeset.FaceForCodepoint(fc, "monospace", 400, false, 0x06F4)
face := fc.faces.get(2)
println face.family, face.style, face.weight, face.italic, typeset.Weight(typeset.FaceFont(fc, 0))
typeset.FreeFontCollection(fc)
mut lf := typeset.LoadFontIndex(font_path("XB Zar It.ttf"), 0, ok)
println typeset.IsItalic(lf)
typeset.FreeFont(lf)
mut more := typeset.NewFontCollection()
println typeset.AddFontDir(more, filepath.Dir(font_path("x"))) > 90
dirs := typeset.SystemFontDirs()
println dirs.len() > 0, typeset.AddSystemFonts(more) >= 0
dirs.free()
typeset.FreeFontCollection(more)
mut pf := typeset.ParseFont(null, 0, ok)
println ok
typeset.FreeFont(pf)
endFontCollection
struct FontCollection| Name | Type | Description |
|---|---|---|
faces | Vector | The faces in the order they were added. |
fallback | HashMap | Cached fallback answers per character. |
memo | HashMap | Cached face choices per family list, weight, style and character, so shaping a page does not match family names again for every character. |
The example for this item is shown with the ones above: gui-typeset-Fonts.salam
ShapedGlyph
struct ShapedGlyph| Name | Type | Description |
|---|---|---|
id | int = 0 | The glyph id. |
cluster | int = 0 | The UTF-8 byte offset of the text it came from. |
x_advance | int = 0 | The advance in font units. |
x_offset | int = 0 | The horizontal offset in font units. |
y_offset | int = 0 | The vertical offset in font units, up is positive. |
import gui.typeset
import os
import filepath
func main:
mut ok := false
mut f := typeset.LoadFont(filepath.Join(filepath.Dir(os.Env("SALAM_STD")), "books/fonts/XB Zar.ttf"), ok)
glyphs := typeset.ShapeText(f, "میخواهم", true, "", "fa")
each g in glyphs:
println g.id, g.cluster, g.x_advance, g.x_offset, g.y_offset
end
glyphs.free()
println typeset.ShapeArabic("سلام")
println typeset.IsRTLText("سلام"), typeset.BaseDirection("Salam سلام") == typeset.TextDirLTR
println typeset.ToVisualOrder("abc سلام", typeset.TextDirAuto)
cps := typeset.VisualCodepoints("لا", typeset.TextDirRTL, true)
println cps.len(), cps.get(0)
cps.free()
typeset.FreeFont(f)
endTextAlign
enum TextAligntext-align.| Name | Type | Description |
|---|---|---|
Start | | At the start side of the paragraph direction. |
End | | At the end side. |
Left | | Left. |
Right | | Right. |
Center | | Centered. |
Justify | | Spaces stretch so lines fill the width, except the last line. |
import gui.typeset
import os
import filepath
func main:
fonts := filepath.Join(filepath.Dir(os.Env("SALAM_STD")), "books/fonts/")
mut fc := typeset.NewFontCollection()
typeset.AddFontFile(fc, fonts + "XB Zar.ttf")
typeset.AddFontFile(fc, fonts + "DejaVuSansMono.ttf")
mut spans := Vector {} as Vector<typeset.TextSpan>
spans.push(typeset.TextSpan { text = "قیمت این کتاب ", families = "XB Zar", size = 18.0, tag = 1, lang = "fa" })
spans.push(typeset.TextSpan { text = "12 USD", families = "DejaVu Sans Mono", size = 14.0, tag = 2, letter_spacing = 0.5 })
spans.push(typeset.TextSpan { text = " است.", families = "XB Zar", size = 18.0, tag = 3, word_spacing = 2.0, line_height = 30.0, line_height_scale = 0.0 })
mut st := typeset.ParagraphStyle {}
st.align = typeset.TextAlign.Justify
st.direction = typeset.TextDirAuto
st.white_space = typeset.WhiteSpace.Normal
st.overflow_wrap = typeset.OverflowWrap.BreakWord
st.max_lines = 3
st.ellipsis = true
st.lang = "fa"
mut p := typeset.NewParagraph(fc, spans, st)
println typeset.MinContentWidth(p), typeset.MaxContentWidth(p), p.min_content, p.max_content
println p.text, p.style.max_lines, p.spans.len(), p.span_starts.get(1), typeset.SpanAt(p, 30)
c := p.chars.get(0)
println c.offset, c.cp, c.span, c.level, c.base, c.flags, c.advance, c.brk, c.face
r := p.runs.get(0)
println r.cp_start, r.cp_end, r.glyph_start, r.glyph_end, r.level, r.face, r.span, r.size64
g := p.glyphs.get(0)
println g.id, g.cp, g.advance, g.x_offset, g.y_offset
mut l := typeset.LayoutParagraph(p, fc, 110.0)
println l.width, l.height, l.max_width, l.truncated, l.lines.len()
each lb in l.lines:
println lb.start, lb.end, lb.cp_start, lb.cp_end, lb.trailing_cp, lb.top, lb.baseline, lb.height, lb.ascent, lb.descent, lb.x, lb.width, lb.run_start, lb.run_count, lb.hard_break, lb.rtl, lb.space_extra
end
each run in l.runs:
println run.face, run.size, run.x, run.width, run.start, run.end, run.cp_start, run.cp_end, run.rtl, run.level, run.tag, run.span, run.glyph_start, run.glyph_count, run.ellipsis
end
pg := l.glyphs.get(0)
println pg.id, pg.x, pg.y, pg.cluster, pg.advance
typeset.FreeLayout(l)
typeset.FreeParagraph(p)
spans.free()
typeset.FreeFontCollection(fc)
endWhiteSpace
enum WhiteSpacewhite-space.| Name | Type | Description |
|---|---|---|
Normal | | Spaces collapse, new lines are spaces, lines wrap. |
NoWrap | | Like normal but lines never wrap. |
Pre | | Spaces and new lines are kept, no wrapping. |
PreWrap | | Spaces and new lines are kept and lines wrap; trailing spaces hang. |
The example for this item is shown with the ones above: gui-typeset-Layout.salam
OverflowWrap
enum OverflowWrapoverflow-wrap.| Name | Type | Description |
|---|---|---|
Normal | | Long words overflow. |
Anywhere | | Split at any letter; min-content counts single letters. |
BreakWord | | Split only when needed; min-content keeps whole words. |
The example for this item is shown with the ones above: gui-typeset-Layout.salam
TextSpan
struct TextSpan| Name | Type | Description |
|---|---|---|
text | str = "" | The text, UTF-8. |
families | str = "sans-serif" | A family list as in CSS font-family, such as "Vazirmatn, sans-serif". |
size | f64 = 16 | Font size in pixels. |
weight | int = 400 | Font weight, 400 regular. |
italic | bool = false | Ask for an italic face. |
letter_spacing | f64 = 0 | Extra pixels after every letter; turns off optional ligatures. |
word_spacing | f64 = 0 | Extra pixels after every space. |
line_height | f64 = 0 | Line height in pixels; 0 means normal. |
line_height_scale | f64 = 0 | Line height as a multiple of the font size, used when line_height is 0. |
tag | int = 0 | Your own number, copied to every glyph run so you can map runs back to elements. |
lang | str = "" | Language such as fa, used to pick the font's language rules. |
The example for this item is shown with the ones above: gui-typeset-Layout.salam
ParagraphStyle
struct ParagraphStyle| Name | Type | Description |
|---|---|---|
align | TextAlign | Line alignment. |
direction | int = 0 | Base direction: TextDirAuto, TextDirLTR or TextDirRTL. |
white_space | WhiteSpace | Space handling. |
overflow_wrap | OverflowWrap | Long word handling. |
max_lines | int = 0 | Keep at most this many lines; 0 means no limit. |
ellipsis | bool = false | Cut overflowing or hidden text with an ellipsis on the end side. |
lang | str = "" | Language for spans that do not set one. |
The example for this item is shown with the ones above: gui-typeset-Layout.salam
CharInfo
struct CharInfo| Name | Type | Description |
|---|---|---|
offset | int = 0 | UTF-8 byte offset in the paragraph text. |
cp | int = 0 | The code point. |
span | int = 0 | The span it belongs to. |
level | int = 0 | The bidi embedding level; odd is right to left. |
base | int = 0 | The paragraph level of its bidi paragraph. |
flags | int = 0 | Internal bits: hidden, hard break, grapheme start, space, word letter. |
advance | int = 0 | Its share of the shaped width, in 1/64 pixel. |
brk | int = 0 | Line break before it: 0 none, 1 allowed, 2 required. |
face | int = -1 | The face chosen for it in the collection. |
The example for this item is shown with the ones above: gui-typeset-Layout.salam
ShapedRun
struct ShapedRun| Name | Type | Description |
|---|---|---|
cp_start | int = 0 | First character index. |
cp_end | int = 0 | One past the last character index. |
glyph_start | int = 0 | First glyph in the paragraph's glyphs. |
glyph_end | int = 0 | One past its last glyph. |
level | int = 0 | Its bidi level. |
face | int = -1 | Its face. |
span | int = 0 | Its span. |
size64 | int = 0 | Font size in 1/64 pixel. |
The example for this item is shown with the ones above: gui-typeset-Layout.salam
ParagraphGlyph
struct ParagraphGlyph| Name | Type | Description |
|---|---|---|
id | int = 0 | The glyph id. |
cp | int = 0 | The character index of its cluster. |
advance | int = 0 | Advance with letter and word spacing. |
x_offset | int = 0 | Horizontal offset. |
y_offset | int = 0 | Vertical offset, up is positive. |
The example for this item is shown with the ones above: gui-typeset-Layout.salam
Paragraph
struct Paragraph| Name | Type | Description |
|---|---|---|
text | str = "" | All span texts joined; offsets point into it. |
style | ParagraphStyle | The paragraph style. |
spans | Vector | The spans. |
span_starts | Vector | The byte offset where each span starts. |
chars | Vector | One entry per code point. |
runs | Vector | The shaped runs in logical order. |
glyphs | Vector | All shaped glyphs. |
min_content | int = 0 | The min-content width in 1/64 pixel. |
max_content | int = 0 | The max-content width in 1/64 pixel. |
The example for this item is shown with the ones above: gui-typeset-Layout.salam
PlacedGlyph
struct PlacedGlyph| Name | Type | Description |
|---|---|---|
id | int = 0 | The glyph id. |
x | f64 = 0 | The pen x of the glyph in pixels. |
y | f64 = 0 | The baseline y with the glyph offset, in pixels. |
cluster | int = 0 | Byte offset of the text it shows. |
advance | f64 = 0 | Its advance in pixels. |
The example for this item is shown with the ones above: gui-typeset-Layout.salam
GlyphRun
struct GlyphRun| Name | Type | Description |
|---|---|---|
face | int = -1 | The face to draw with. |
size | f64 = 0 | Font size in pixels. |
x | f64 = 0 | Left edge in pixels. |
width | f64 = 0 | Width in pixels. |
start | int = 0 | First byte offset. |
end | int = 0 | One past the last byte offset. |
cp_start | int = 0 | First character index. |
cp_end | int = 0 | One past the last character index. |
rtl | bool = false | The run goes right to left. |
level | int = 0 | Its bidi level. |
tag | int = 0 | The tag of its span. |
span | int = 0 | Its span. |
glyph_start | int = 0 | First glyph in the layout's glyphs. |
glyph_count | int = 0 | How many glyphs. |
ellipsis | bool = false | This run is the ellipsis that ends a cut line. |
The example for this item is shown with the ones above: gui-typeset-Layout.salam
LineBox
struct LineBox| Name | Type | Description |
|---|---|---|
start | int = 0 | First byte offset. |
end | int = 0 | One past the last byte offset, the trailing spaces included. |
cp_start | int = 0 | First character index. |
cp_end | int = 0 | One past the last character index. |
trailing_cp | int = 0 | Where the trailing spaces start. |
top | f64 = 0 | Top of the line in pixels. |
baseline | f64 = 0 | Baseline in pixels. |
height | f64 = 0 | Line height in pixels. |
ascent | f64 = 0 | Space above the baseline, half leading included. |
descent | f64 = 0 | Space below the baseline, half leading included. |
x | f64 = 0 | Left edge of the content after alignment. |
width | f64 = 0 | Content width without hanging spaces. |
run_start | int = 0 | First run in the layout's runs. |
run_count | int = 0 | How many runs, in visual order. |
hard_break | bool = false | The line ends with a new line character. |
rtl | bool = false | The paragraph direction of the line is right to left. |
space_extra | int = 0 | Extra width per space from justification, in 1/64 pixel. |
The example for this item is shown with the ones above: gui-typeset-Layout.salam
TextLayout
struct TextLayout| Name | Type | Description |
|---|---|---|
lines | Vector | The lines. |
runs | Vector | Glyph runs of all lines. |
glyphs | Vector | All glyphs. |
width | f64 = 0 | The width: the max width, or the widest line when there was none. |
height | f64 = 0 | The total height. |
max_width | f64 = 0 | The width asked for. |
truncated | bool = false | Lines were dropped or cut. |
The example for this item is shown with the ones above: gui-typeset-Layout.salam
TextPosition
struct TextPosition| Name | Type | Description |
|---|---|---|
offset | int = 0 | Byte offset in the paragraph text. |
upstream | bool = false | Sticks to the text before it, such as the end of a wrapped line. |
line | int = 0 | The line found by hit testing or movement. |
import gui.typeset
import os
import filepath
func main:
mut fc := typeset.NewFontCollection()
typeset.AddFontFile(fc, filepath.Join(filepath.Dir(os.Env("SALAM_STD")), "books/fonts/XB Zar.ttf"))
mut spans := Vector {} as Vector<typeset.TextSpan>
spans.push(typeset.TextSpan { text = "نام Salam است", families = "XB Zar", size = 20.0 })
mut st := typeset.ParagraphStyle {}
st.white_space = typeset.WhiteSpace.PreWrap
mut p := typeset.NewParagraph(fc, spans, st)
mut l := typeset.LayoutParagraph(p, fc, 0.0)
hit := typeset.HitTest(p, l, 40.0, 10.0)
println hit.offset, hit.upstream, hit.line
caret := typeset.CaretRect(p, l, hit)
println caret.x, caret.y, caret.width, caret.height
rects := typeset.SelectionRects(p, l, 3, 12)
each r in rects:
println r.x, r.width
end
rects.free()
println typeset.NextGrapheme(p, 0), typeset.PrevGrapheme(p, 4), typeset.NextWordEnd(p, 0), typeset.PrevWordStart(p, 12)
mut pos := typeset.TextPosition { offset = 0 }
repeat 4:
pos = typeset.MoveVisual(p, l, pos, false)
print pos.offset, " "
end
println ""
typeset.FreeLayout(l)
typeset.FreeParagraph(p)
spans.free()
typeset.FreeFontCollection(fc)
endTextRect
struct TextRect| Name | Type | Description |
|---|---|---|
x | f64 = 0 | Left. |
y | f64 = 0 | Top. |
width | f64 = 0 | Width. |
height | f64 = 0 | Height. |
The example for this item is shown with the ones above: gui-typeset-Editing.salam
GlyphMask
struct GlyphMask| Name | Type | Description |
|---|---|---|
data | void* | Coverage bytes, 0 empty and 255 full. |
width | int = 0 | Width in pixels. |
height | int = 0 | Height in pixels. |
stride | int = 0 | Bytes per row. |
left | int = 0 | Columns from the pen x to the left edge. |
top | int = 0 | Rows from the top edge down to the baseline. |
import gui.typeset
import os
import filepath
func main:
mut ok := false
mut f := typeset.LoadFont(filepath.Join(filepath.Dir(os.Env("SALAM_STD")), "books/fonts/XB Zar.ttf"), ok)
gid := typeset.GlyphIndex(f, 0x0634)
mut m := typeset.RasterizeGlyph(f, gid, 24.0, typeset.SubpixelOf(12.25))
println m.width, m.height, m.stride, m.left, m.top, typeset.GlyphMaskHash(m)
println typeset.GlyphOriginX(12.25, m), typeset.GlyphOriginY(30.0, m)
bp := m.data as u8*
repeat m.height in y:
repeat m.width in x:
print bp[y * m.stride + x] > (127 as u8) ? "#" : "."
end
println ""
end
typeset.FreeGlyphMask(m)
mut cache := typeset.NewGlyphCache(65536)
a := typeset.CachedGlyph(cache, f, gid, 24.0, 12.25)
b := typeset.CachedGlyph(cache, f, gid, 24.0, 40.25)
println a.width == b.width, cache.hits, cache.misses, cache.capacity, cache.bytes > 0, cache.clock, cache.slots.len(), cache.index.size()
slot := cache.slots.get(0)
println slot.key > (0 as i64), slot.mask.width, slot.stamp, slot.used
typeset.FreeGlyphCache(cache)
mut o := typeset.TransformedOutline(f, gid, 0.01, 0.0, 0.0, -0.01, 2.0, 20.0)
pt := o.points.get(0)
println o.points.len(), o.ends.len(), pt.on
mut cov := typeset.OutlineCoverage(o, 64, 64)
println cov.x, cov.y, cov.width, cov.height, cov.values.len()
typeset.FreeCoverageRows(cov)
typeset.FreeOutline(o)
typeset.FreeFont(f)
endCacheSlot
struct CacheSlot| Name | Type | Description |
|---|---|---|
key | i64 = 0 | Font, size, glyph and quarter pixel packed together. |
mask | GlyphMask | The cached mask. |
stamp | i64 = 0 | When it was last used. |
used | bool = false | The slot holds a mask. |
The example for this item is shown with the ones above: gui-typeset-Raster.salam
GlyphCache
struct GlyphCache| Name | Type | Description |
|---|---|---|
capacity | int = 1048576 | The byte budget. |
bytes | int = 0 | Bytes in use. |
hits | int = 0 | Lookups served from the cache. |
misses | int = 0 | Lookups that had to rasterize. |
clock | i64 = 0 | A counter for the least recently used order. |
slots | Vector | The entries. |
index | HashMap | From key to slot. |
The example for this item is shown with the ones above: gui-typeset-Raster.salam
FontMetrics
struct FontMetrics| Name | Type | Description |
|---|---|---|
units_per_em | int = 0 | Font units in one em. |
ascent | int = 0 | Distance from the baseline up to the top of the line, positive. |
descent | int = 0 | Distance from the baseline down to the bottom, positive. |
line_gap | int = 0 | Extra space between lines. |
x_height | int = 0 | Height of a lowercase x. |
cap_height | int = 0 | Height of a capital letter. |
underline_position | int = 0 | Where an underline goes, negative below the baseline. |
underline_thickness | int = 0 | The thickness of an underline. |
The example for this item is shown with the ones above: gui-typeset-Fonts.salam
OutlinePoint
struct OutlinePoint| Name | Type | Description |
|---|---|---|
x | f64 = 0 | The x position. |
y | f64 = 0 | The y position. |
on | bool = false | The point is on the curve, not a control point. |
The example for this item is shown with the ones above: gui-typeset-Raster.salam
GlyphOutline
struct GlyphOutline| Name | Type | Description |
|---|---|---|
points | Vector | All points, contour after contour. |
ends | Vector | Where each contour ends in points (one past its last point). |
The example for this item is shown with the ones above: gui-typeset-Raster.salam
Font
struct Font| Name | Type | Description |
|---|---|---|
data | void* | The font file's bytes, owned by the font. |
size | int = 0 | The number of bytes in data. |
units_per_em | int = 0 | Font units in one em, from the head table. |
num_glyphs | int = 0 | The number of glyphs. |
ascent | int = 0 | The ascent from the hhea table, in font units. |
descent | int = 0 | The descent from the hhea table, negative, in font units. |
line_gap | int = 0 | The line gap from the hhea table. |
glyf | int = 0 | Where the glyf table starts. |
glyf_len | int = 0 | The length of the glyf table. |
loca | int = 0 | Where the loca table starts. |
loca_len | int = 0 | The length of the loca table. |
hmtx | int = 0 | Where the hmtx table starts. |
kern | int = 0 | Where the old kern table starts, 0 when there is none. |
cmap_sub | int = 0 | Where the chosen cmap subtable starts. |
cmap_symbol | bool = false | The cmap is a Windows symbol one. |
num_hmetrics | int = 0 | The number of horizontal metrics. |
loca_long | bool = false | The loca table uses 32 bit offsets. |
ok | bool = false | The font was read correctly. |
id | int = 0 | A number unique to this loaded font, used as a cache key. |
index | int = 0 | The face number inside a TTC collection. |
head | int = 0 | Where the head table starts. |
hhea | int = 0 | Where the hhea table starts. |
os2 | int = 0 | Where the OS/2 table starts, 0 when there is none. |
name | int = 0 | Where the name table starts. |
post | int = 0 | Where the post table starts. |
gsub | int = 0 | Where the GSUB table starts, 0 when there is none. |
gpos | int = 0 | Where the GPOS table starts, 0 when there is none. |
gdef | int = 0 | Where the GDEF table starts, 0 when there is none. |
kern_len | int = 0 | The length of the kern table. |
The example for this item is shown with the ones above: gui-typeset-Fonts.salam
CoverageRows
struct CoverageRows| Name | Type | Description |
|---|---|---|
x | int = 0 | The left column. |
y | int = 0 | The top row. |
width | int = 0 | The width in pixels. |
height | int = 0 | The height in pixels. |
values | Vector | Coverage from 0 to 1, width values per row. |
The example for this item is shown with the ones above: gui-typeset-Raster.salam
Constants and variables
TextDirAuto
const TextDirAuto: i32 = 0The example for this item is shown with the ones above: gui-typeset-Shape.salam
TextDirLTR
const TextDirLTR: i32 = 1The example for this item is shown with the ones above: gui-typeset-Shape.salam
TextDirRTL
const TextDirRTL: i32 = 2The example for this item is shown with the ones above: gui-typeset-Shape.salam
Functions
NewFontCollection
func NewFontCollection(): FontCollectionThe example for this item is shown with the ones above: gui-typeset-Fonts.salam
AddFont
func AddFont(fc &: FontCollection, f: Font): intThe example for this item is shown with the ones above: gui-typeset-Fonts.salam
AddFontBytes
func AddFontBytes(fc &: FontCollection, p: void*, n: int): intThe example for this item is shown with the ones above: gui-typeset-Fonts.salam
AddFontFile
func AddFontFile(fc &: FontCollection, path: str): intThe example for this item is shown with the ones above: gui-typeset-Fonts.salam
SystemFontDirs
func SystemFontDirs(): Vector<str>The example for this item is shown with the ones above: gui-typeset-Fonts.salam
AddFontDir
func AddFontDir(fc &: FontCollection, dir: str): intThe example for this item is shown with the ones above: gui-typeset-Fonts.salam
AddSystemFonts
func AddSystemFonts(fc &: FontCollection): intThe example for this item is shown with the ones above: gui-typeset-Fonts.salam
FaceCountIn
func FaceCountIn(fc: FontCollection): intThe example for this item is shown with the ones above: gui-typeset-Fonts.salam
FaceFont
func FaceFont(fc &: FontCollection, face: int): FontThe example for this item is shown with the ones above: gui-typeset-Fonts.salam
FindFace
func FindFace(fc &: FontCollection, family: str, weight: int, italic: bool): intThe example for this item is shown with the ones above: gui-typeset-Fonts.salam
FaceForCodepoint
func FaceForCodepoint(fc &: FontCollection, families: str, weight: int, italic: bool, cp: int): intThe example for this item is shown with the ones above: gui-typeset-Fonts.salam
FreeFontCollection
func FreeFontCollection(fc &: FontCollection)The example for this item is shown with the ones above: gui-typeset-Fonts.salam
ShapeText
func ShapeText(f: Font, text: str, rtl: bool, script: str, lang: str): Vector<ShapedGlyph>The example for this item is shown with the ones above: gui-typeset-Shape.salam
NewParagraph
func NewParagraph(fc &: FontCollection, spans: Vector<TextSpan>, style: ParagraphStyle): ParagraphThe example for this item is shown with the ones above: gui-typeset-Layout.salam
MinContentWidth
func MinContentWidth(p: Paragraph): f64The example for this item is shown with the ones above: gui-typeset-Layout.salam
MaxContentWidth
func MaxContentWidth(p: Paragraph): f64The example for this item is shown with the ones above: gui-typeset-Layout.salam
SpanAt
func SpanAt(p: Paragraph, offset: int): intThe example for this item is shown with the ones above: gui-typeset-Layout.salam
FreeParagraph
func FreeParagraph(p &: Paragraph)The example for this item is shown with the ones above: gui-typeset-Layout.salam
LayoutParagraph
func LayoutParagraph(p &: Paragraph, fc &: FontCollection, max_width: f64): TextLayoutThe example for this item is shown with the ones above: gui-typeset-Layout.salam
FreeLayout
func FreeLayout(l &: TextLayout)The example for this item is shown with the ones above: gui-typeset-Layout.salam
HitTest
func HitTest(p: Paragraph, l: TextLayout, x: f64, y: f64): TextPositionThe example for this item is shown with the ones above: gui-typeset-Editing.salam
CaretRect
func CaretRect(p: Paragraph, l: TextLayout, pos: TextPosition): TextRectThe example for this item is shown with the ones above: gui-typeset-Editing.salam
SelectionRects
func SelectionRects(p: Paragraph, l: TextLayout, from: int, to_offset: int): Vector<TextRect>The example for this item is shown with the ones above: gui-typeset-Editing.salam
NextGrapheme
func NextGrapheme(p: Paragraph, offset: int): intThe example for this item is shown with the ones above: gui-typeset-Editing.salam
PrevGrapheme
func PrevGrapheme(p: Paragraph, offset: int): intThe example for this item is shown with the ones above: gui-typeset-Editing.salam
NextWordEnd
func NextWordEnd(p: Paragraph, offset: int): intThe example for this item is shown with the ones above: gui-typeset-Editing.salam
PrevWordStart
func PrevWordStart(p: Paragraph, offset: int): intThe example for this item is shown with the ones above: gui-typeset-Editing.salam
MoveVisual
func MoveVisual(p: Paragraph, l: TextLayout, pos: TextPosition, right: bool): TextPositionThe example for this item is shown with the ones above: gui-typeset-Editing.salam
ScaleFactor
func ScaleFactor(f: Font, size: f64): f64The example for this item is shown with the ones above: gui-typeset-Fonts.salam
AscentPixels
func AscentPixels(f: Font, size: f64): f64The example for this item is shown with the ones above: gui-typeset-Fonts.salam
DescentPixels
func DescentPixels(f: Font, size: f64): f64The example for this item is shown with the ones above: gui-typeset-Fonts.salam
LineHeightPixels
func LineHeightPixels(f: Font, size: f64): f64The example for this item is shown with the ones above: gui-typeset-Fonts.salam
GlyphAdvance
func GlyphAdvance(f: Font, glyph: int): intThe example for this item is shown with the ones above: gui-typeset-Fonts.salam
KernAdvance
func KernAdvance(f: Font, glyph1: int, glyph2: int): intThe example for this item is shown with the ones above: gui-typeset-Fonts.salam
ShapeArabic
func ShapeArabic(text: str): strThe example for this item is shown with the ones above: gui-typeset-Shape.salam
RasterizeGlyph
func RasterizeGlyph(f: Font, glyph: int, size: f64, subpixel: int): GlyphMaskThe example for this item is shown with the ones above: gui-typeset-Raster.salam
FreeGlyphMask
func FreeGlyphMask(m &: GlyphMask)The example for this item is shown with the ones above: gui-typeset-Raster.salam
GlyphMaskHash
func GlyphMaskHash(m: GlyphMask): i64The example for this item is shown with the ones above: gui-typeset-Raster.salam
SubpixelOf
func SubpixelOf(x: f64): intThe example for this item is shown with the ones above: gui-typeset-Raster.salam
GlyphOriginX
func GlyphOriginX(x: f64, m: GlyphMask): intThe example for this item is shown with the ones above: gui-typeset-Raster.salam
GlyphOriginY
func GlyphOriginY(y: f64, m: GlyphMask): intThe example for this item is shown with the ones above: gui-typeset-Raster.salam
NewGlyphCache
func NewGlyphCache(capacity_bytes: int): GlyphCacheThe example for this item is shown with the ones above: gui-typeset-Raster.salam
CachedGlyph
func CachedGlyph(c &: GlyphCache, f: Font, glyph: int, size: f64, x: f64): GlyphMaskThe example for this item is shown with the ones above: gui-typeset-Raster.salam
FreeGlyphCache
func FreeGlyphCache(c &: GlyphCache)The example for this item is shown with the ones above: gui-typeset-Raster.salam
NameString
func NameString(f: Font, name_id: int): strThe example for this item is shown with the ones above: gui-typeset-Fonts.salam
FamilyName
func FamilyName(f: Font): strfont-family.The example for this item is shown with the ones above: gui-typeset-Fonts.salam
StyleName
func StyleName(f: Font): strThe example for this item is shown with the ones above: gui-typeset-Fonts.salam
FullName
func FullName(f: Font): strThe example for this item is shown with the ones above: gui-typeset-Fonts.salam
Weight
func Weight(f: Font): intThe example for this item is shown with the ones above: gui-typeset-Fonts.salam
IsItalic
func IsItalic(f: Font): boolThe example for this item is shown with the ones above: gui-typeset-Fonts.salam
Metrics
func Metrics(f: Font): FontMetricsThe example for this item is shown with the ones above: gui-typeset-Fonts.salam
FaceCount
func FaceCount(p: void*, n: int): intThe example for this item is shown with the ones above: gui-typeset-Fonts.salam
GlyphBox
func GlyphBox(f: Font, glyph: int, x0 &: int, y0 &: int, x1 &: int, y1 &: int): boolThe example for this item is shown with the ones above: gui-typeset-Fonts.salam
GlyphHasOutline
func GlyphHasOutline(f: Font, glyph: int): boolThe example for this item is shown with the ones above: gui-typeset-Fonts.salam
TransformedOutline
func TransformedOutline(f: Font, glyph: int, a: f64, b: f64, c: f64, d: f64, dx: f64, dy: f64): GlyphOutlinestd/ai/image draws with it.The example for this item is shown with the ones above: gui-typeset-Raster.salam
FreeOutline
func FreeOutline(o &: GlyphOutline)The example for this item is shown with the ones above: gui-typeset-Raster.salam
ParseFontIndex
func ParseFontIndex(p: void*, n: int, index: int, ok &: bool): FontThe example for this item is shown with the ones above: gui-typeset-Fonts.salam
ParseFont
func ParseFont(p: void*, n: int, ok &: bool): FontThe example for this item is shown with the ones above: gui-typeset-Fonts.salam
LoadFont
func LoadFont(path: str, ok &: bool): Font.ttf file.The example for this item is shown with the ones above: gui-typeset-Fonts.salam
LoadFontIndex
func LoadFontIndex(path: str, index: int, ok &: bool): Font.ttf or .ttc file.The example for this item is shown with the ones above: gui-typeset-Fonts.salam
FreeFont
func FreeFont(f &: Font)The example for this item is shown with the ones above: gui-typeset-Fonts.salam
FontValid
func FontValid(f: Font): boolThe example for this item is shown with the ones above: gui-typeset-Fonts.salam
IsCFFFont
func IsCFFFont(p: void*, n: int): boolThe example for this item is shown with the ones above: gui-typeset-Fonts.salam
UnitsPerEm
func UnitsPerEm(f: Font): intThe example for this item is shown with the ones above: gui-typeset-Fonts.salam
NumGlyphs
func NumGlyphs(f: Font): intThe example for this item is shown with the ones above: gui-typeset-Fonts.salam
GlyphIndex
func GlyphIndex(f: Font, codepoint: int): intThe example for this item is shown with the ones above: gui-typeset-Fonts.salam
IsRTLText
func IsRTLText(text: str): boolThe example for this item is shown with the ones above: gui-typeset-Shape.salam
BaseDirection
func BaseDirection(text: str): intThe example for this item is shown with the ones above: gui-typeset-Shape.salam
ToVisualOrder
func ToVisualOrder(text: str, dir: int): strThe example for this item is shown with the ones above: gui-typeset-Shape.salam
VisualCodepoints
func VisualCodepoints(text: str, dir: int, shape: bool): Vector<int>ToVisualOrder, optionally without shaping.The example for this item is shown with the ones above: gui-typeset-Shape.salam
OutlineCoverage
func OutlineCoverage(o: GlyphOutline, clip_width: int, clip_height: int): CoverageRowsThe example for this item is shown with the ones above: gui-typeset-Raster.salam
FreeCoverageRows
func FreeCoverageRows(c &: CoverageRows)The example for this item is shown with the ones above: gui-typeset-Raster.salam