mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-01 07:35:40 +00:00
text: replace Family with Shaper, add Font, Face
There is now a single shaping implementation, Shaper, for all fonts, replacing Family that only covered a single typeface. A typeface is identified by a name, where the empty string denotes the default typeface. Font is introduced to specify a particular font from the typeface, style, weight and size. Face is changed to an interface for a particular layout and shaping method. The text/shape package is renamed to text/opentype and contains a Face implementation based on golang.org/x/image/font/sfnt. Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
+121
@@ -0,0 +1,121 @@
|
||||
// SPDX-License-Identifier: Unlicense OR MIT
|
||||
|
||||
package text
|
||||
|
||||
import (
|
||||
"gioui.org/op/paint"
|
||||
"golang.org/x/image/math/fixed"
|
||||
)
|
||||
|
||||
type layoutCache struct {
|
||||
m map[layoutKey]*layoutElem
|
||||
head, tail *layoutElem
|
||||
}
|
||||
|
||||
type pathCache struct {
|
||||
m map[pathKey]*path
|
||||
head, tail *path
|
||||
}
|
||||
|
||||
type layoutElem struct {
|
||||
next, prev *layoutElem
|
||||
key layoutKey
|
||||
layout *Layout
|
||||
}
|
||||
|
||||
type path struct {
|
||||
next, prev *path
|
||||
key pathKey
|
||||
val paint.ClipOp
|
||||
}
|
||||
|
||||
type layoutKey struct {
|
||||
ppem fixed.Int26_6
|
||||
str string
|
||||
opts LayoutOptions
|
||||
}
|
||||
|
||||
type pathKey struct {
|
||||
ppem fixed.Int26_6
|
||||
str string
|
||||
}
|
||||
|
||||
const maxSize = 1000
|
||||
|
||||
func (l *layoutCache) Get(k layoutKey) (*Layout, bool) {
|
||||
if lt, ok := l.m[k]; ok {
|
||||
l.remove(lt)
|
||||
l.insert(lt)
|
||||
return lt.layout, true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (l *layoutCache) Put(k layoutKey, lt *Layout) {
|
||||
if l.m == nil {
|
||||
l.m = make(map[layoutKey]*layoutElem)
|
||||
l.head = new(layoutElem)
|
||||
l.tail = new(layoutElem)
|
||||
l.head.prev = l.tail
|
||||
l.tail.next = l.head
|
||||
}
|
||||
val := &layoutElem{key: k, layout: lt}
|
||||
l.m[k] = val
|
||||
l.insert(val)
|
||||
if len(l.m) > maxSize {
|
||||
oldest := l.tail.next
|
||||
l.remove(oldest)
|
||||
delete(l.m, oldest.key)
|
||||
}
|
||||
}
|
||||
|
||||
func (l *layoutCache) remove(lt *layoutElem) {
|
||||
lt.next.prev = lt.prev
|
||||
lt.prev.next = lt.next
|
||||
}
|
||||
|
||||
func (l *layoutCache) insert(lt *layoutElem) {
|
||||
lt.next = l.head
|
||||
lt.prev = l.head.prev
|
||||
lt.prev.next = lt
|
||||
lt.next.prev = lt
|
||||
}
|
||||
|
||||
func (c *pathCache) Get(k pathKey) (paint.ClipOp, bool) {
|
||||
if v, ok := c.m[k]; ok {
|
||||
c.remove(v)
|
||||
c.insert(v)
|
||||
return v.val, true
|
||||
}
|
||||
return paint.ClipOp{}, false
|
||||
}
|
||||
|
||||
func (c *pathCache) Put(k pathKey, v paint.ClipOp) {
|
||||
if c.m == nil {
|
||||
c.m = make(map[pathKey]*path)
|
||||
c.head = new(path)
|
||||
c.tail = new(path)
|
||||
c.head.prev = c.tail
|
||||
c.tail.next = c.head
|
||||
}
|
||||
val := &path{key: k, val: v}
|
||||
c.m[k] = val
|
||||
c.insert(val)
|
||||
if len(c.m) > maxSize {
|
||||
oldest := c.tail.next
|
||||
c.remove(oldest)
|
||||
delete(c.m, oldest.key)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *pathCache) remove(v *path) {
|
||||
v.next.prev = v.prev
|
||||
v.prev.next = v.next
|
||||
}
|
||||
|
||||
func (c *pathCache) insert(v *path) {
|
||||
v.next = c.head
|
||||
v.prev = c.head.prev
|
||||
v.prev.next = v
|
||||
v.next.prev = v
|
||||
}
|
||||
Reference in New Issue
Block a user