mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-07 16:18:52 +00:00
General code style clean up for vendor:fontstash
This commit is contained in:
Vendored
+118
-153
@@ -7,6 +7,7 @@ import "core:os"
|
|||||||
import "core:mem"
|
import "core:mem"
|
||||||
import "core:math"
|
import "core:math"
|
||||||
import "core:strings"
|
import "core:strings"
|
||||||
|
import "core:slice"
|
||||||
import stbtt "vendor:stb/truetype"
|
import stbtt "vendor:stb/truetype"
|
||||||
|
|
||||||
// This is a port from Fontstash into odin - specialized for nanovg
|
// This is a port from Fontstash into odin - specialized for nanovg
|
||||||
@@ -118,24 +119,24 @@ FontContext :: struct {
|
|||||||
callbackUpdate: proc(data: rawptr, dirtyRect: [4]f32, textureData: rawptr),
|
callbackUpdate: proc(data: rawptr, dirtyRect: [4]f32, textureData: rawptr),
|
||||||
}
|
}
|
||||||
|
|
||||||
Init :: proc(using ctx: ^FontContext, w, h: int, loc: QuadLocation) {
|
Init :: proc(ctx: ^FontContext, w, h: int, loc: QuadLocation) {
|
||||||
userData = ctx
|
ctx.userData = ctx
|
||||||
location = loc
|
ctx.location = loc
|
||||||
fonts = make([dynamic]Font, 0, 8)
|
ctx.fonts = make([dynamic]Font, 0, 8)
|
||||||
|
|
||||||
itw = f32(1) / f32(w)
|
ctx.itw, ctx.ith = 1.0 / f32(w), 1.0 / f32(h)
|
||||||
ith = f32(1) / f32(h)
|
|
||||||
textureData = make([]byte, w * h)
|
|
||||||
|
|
||||||
width = w
|
ctx.textureData = make([]byte, w * h)
|
||||||
height = h
|
|
||||||
nodes = make([dynamic]AtlasNode, 0, INIT_ATLAS_NODES)
|
ctx.width = w
|
||||||
|
ctx.height = h
|
||||||
|
ctx.nodes = make([dynamic]AtlasNode, 0, INIT_ATLAS_NODES)
|
||||||
__dirtyRectReset(ctx)
|
__dirtyRectReset(ctx)
|
||||||
|
|
||||||
states = make([]State, MAX_STATES)
|
ctx.states = make([]State, MAX_STATES)
|
||||||
|
|
||||||
// NOTE NECESSARY
|
// NOTE NECESSARY
|
||||||
append(&nodes, AtlasNode {
|
append(&ctx.nodes, AtlasNode{
|
||||||
width = i16(w),
|
width = i16(w),
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -145,8 +146,8 @@ Init :: proc(using ctx: ^FontContext, w, h: int, loc: QuadLocation) {
|
|||||||
ClearState(ctx)
|
ClearState(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
Destroy :: proc(using ctx: ^FontContext) {
|
Destroy :: proc(ctx: ^FontContext) {
|
||||||
for font in fonts {
|
for font in ctx.fonts {
|
||||||
if font.freeLoadedData {
|
if font.freeLoadedData {
|
||||||
delete(font.loadedData)
|
delete(font.loadedData)
|
||||||
}
|
}
|
||||||
@@ -155,18 +156,18 @@ Destroy :: proc(using ctx: ^FontContext) {
|
|||||||
delete(font.glyphs)
|
delete(font.glyphs)
|
||||||
}
|
}
|
||||||
|
|
||||||
delete(states)
|
delete(ctx.states)
|
||||||
delete(textureData)
|
delete(ctx.textureData)
|
||||||
delete(fonts)
|
delete(ctx.fonts)
|
||||||
delete(nodes)
|
delete(ctx.nodes)
|
||||||
}
|
}
|
||||||
|
|
||||||
Reset :: proc(using ctx: ^FontContext) {
|
Reset :: proc(ctx: ^FontContext) {
|
||||||
__atlasReset(ctx, width, height)
|
__atlasReset(ctx, ctx.width, ctx.height)
|
||||||
__dirtyRectReset(ctx)
|
__dirtyRectReset(ctx)
|
||||||
mem.zero_slice(textureData)
|
slice.zero(ctx.textureData)
|
||||||
|
|
||||||
for &font in fonts {
|
for &font in ctx.fonts {
|
||||||
__lutReset(&font)
|
__lutReset(&font)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,84 +176,67 @@ Reset :: proc(using ctx: ^FontContext) {
|
|||||||
ClearState(ctx)
|
ClearState(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
__atlasInsertNode :: proc(using ctx: ^FontContext, idx, x, y, w: int) {
|
__atlasInsertNode :: proc(ctx: ^FontContext, idx: int, x, y, w: int) {
|
||||||
// resize is alright here
|
inject_at(&ctx.nodes, idx, AtlasNode{
|
||||||
resize(&nodes, len(nodes) + 1)
|
x = i16(x),
|
||||||
|
y = i16(y),
|
||||||
// shift nodes up once to leave space at idx
|
|
||||||
for i := len(nodes) - 1; i > idx; i -= 1 {
|
|
||||||
nodes[i] = nodes[i - 1]
|
|
||||||
}
|
|
||||||
|
|
||||||
// set new inserted one to properties
|
|
||||||
nodes[idx].x = i16(x)
|
|
||||||
nodes[idx].y = i16(y)
|
|
||||||
nodes[idx].width = i16(w)
|
|
||||||
}
|
|
||||||
|
|
||||||
__atlasRemoveNode :: proc(using ctx: ^FontContext, idx: int) {
|
|
||||||
if len(nodes) == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove node at index, shift elements down
|
|
||||||
for i in idx..<len(nodes) - 1 {
|
|
||||||
nodes[i] = nodes[i + 1]
|
|
||||||
}
|
|
||||||
|
|
||||||
// reduce size of array
|
|
||||||
raw := transmute(^mem.Raw_Dynamic_Array) &nodes
|
|
||||||
raw.len -= 1
|
|
||||||
}
|
|
||||||
|
|
||||||
__atlasExpand :: proc(using ctx: ^FontContext, w, h: int) {
|
|
||||||
if w > width {
|
|
||||||
__atlasInsertNode(ctx, len(nodes), width, 0, w - width)
|
|
||||||
}
|
|
||||||
|
|
||||||
width = w
|
|
||||||
height = h
|
|
||||||
}
|
|
||||||
|
|
||||||
__atlasReset :: proc(using ctx: ^FontContext, w, h: int) {
|
|
||||||
width = w
|
|
||||||
height = h
|
|
||||||
clear(&nodes)
|
|
||||||
|
|
||||||
// init root node
|
|
||||||
append(&nodes, AtlasNode {
|
|
||||||
width = i16(w),
|
width = i16(w),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
__AtlasAddSkylineLevel :: proc(using ctx: ^FontContext, idx, x, y, w, h: int) {
|
__atlasRemoveNode :: proc(ctx: ^FontContext, idx: int) {
|
||||||
|
if len(ctx.nodes) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ordered_remove(&ctx.nodes, idx)
|
||||||
|
}
|
||||||
|
|
||||||
|
__atlasExpand :: proc(ctx: ^FontContext, w, h: int) {
|
||||||
|
if w > ctx.width {
|
||||||
|
__atlasInsertNode(ctx, len(ctx.nodes), ctx.width, 0, w - ctx.width)
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.width, ctx.height = w, h
|
||||||
|
}
|
||||||
|
|
||||||
|
__atlasReset :: proc(ctx: ^FontContext, w, h: int) {
|
||||||
|
ctx.width, ctx.height = w, h
|
||||||
|
clear(&ctx.nodes)
|
||||||
|
|
||||||
|
// init root node
|
||||||
|
append(&ctx.nodes, AtlasNode{
|
||||||
|
width = i16(w),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
__AtlasAddSkylineLevel :: proc(using ctx: ^FontContext, idx: int, x, y, w, h: int) {
|
||||||
// insert new node
|
// insert new node
|
||||||
__atlasInsertNode(ctx, idx, x, y + h, w)
|
__atlasInsertNode(ctx, idx, x, y + h, w)
|
||||||
|
|
||||||
// Delete skyline segments that fall under the shadow of the new segment.
|
// Delete skyline segments that fall under the shadow of the new segment.
|
||||||
for i := idx + 1; i < len(nodes); i += 1 {
|
for i := idx + 1; i < len(nodes); i += 1 {
|
||||||
if nodes[i].x < nodes[i - 1].x + nodes[i - 1].width {
|
if nodes[i].x >= nodes[i-1].x + nodes[i-1].width {
|
||||||
|
break
|
||||||
|
}
|
||||||
shrink := nodes[i-1].x + nodes[i-1].width - nodes[i].x
|
shrink := nodes[i-1].x + nodes[i-1].width - nodes[i].x
|
||||||
nodes[i].x += i16(shrink)
|
nodes[i].x += i16(shrink)
|
||||||
nodes[i].width -= i16(shrink)
|
nodes[i].width -= i16(shrink)
|
||||||
|
|
||||||
if nodes[i].width <= 0 {
|
if nodes[i].width > 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
__atlasRemoveNode(ctx, i)
|
__atlasRemoveNode(ctx, i)
|
||||||
i -= 1
|
i -= 1
|
||||||
} else {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Merge same height skyline segments that are next to each other.
|
// Merge same height skyline segments that are next to each other.
|
||||||
for i := 0; i < len(nodes) - 1; i += 1 {
|
for i := 0; i < len(nodes) - 1; /**/ {
|
||||||
if nodes[i].y == nodes[i+1].y {
|
if nodes[i].y == nodes[i+1].y {
|
||||||
nodes[i].width += nodes[i+1].width
|
nodes[i].width += nodes[i+1].width
|
||||||
__atlasRemoveNode(ctx, i+1)
|
__atlasRemoveNode(ctx, i+1)
|
||||||
i -= 1
|
} else {
|
||||||
|
i += 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -261,14 +245,14 @@ __AtlasRectFits :: proc(using ctx: ^FontContext, i, w, h: int) -> int {
|
|||||||
// Checks if there is enough space at the location of skyline span 'i',
|
// Checks if there is enough space at the location of skyline span 'i',
|
||||||
// and return the max height of all skyline spans under that at that location,
|
// and return the max height of all skyline spans under that at that location,
|
||||||
// (think tetris block being dropped at that position). Or -1 if no space found.
|
// (think tetris block being dropped at that position). Or -1 if no space found.
|
||||||
x := int(nodes[i].x)
|
|
||||||
y := int(nodes[i].y)
|
i := i
|
||||||
|
x, y := int(nodes[i].x), int(nodes[i].y)
|
||||||
|
|
||||||
if x + w > width {
|
if x + w > width {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
i := i
|
|
||||||
space_left := w
|
space_left := w
|
||||||
for space_left > 0 {
|
for space_left > 0 {
|
||||||
if i == len(nodes) {
|
if i == len(nodes) {
|
||||||
@@ -288,8 +272,7 @@ __AtlasRectFits :: proc(using ctx: ^FontContext, i, w, h: int) -> int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
__AtlasAddRect :: proc(using ctx: ^FontContext, rw, rh: int) -> (rx, ry: int, ok: bool) {
|
__AtlasAddRect :: proc(using ctx: ^FontContext, rw, rh: int) -> (rx, ry: int, ok: bool) {
|
||||||
besth := height
|
bestw, besth := width, height
|
||||||
bestw := width
|
|
||||||
besti, bestx, besty := -1, -1, -1
|
besti, bestx, besty := -1, -1, -1
|
||||||
|
|
||||||
// Bottom left fit heuristic.
|
// Bottom left fit heuristic.
|
||||||
@@ -313,18 +296,11 @@ __AtlasAddRect :: proc(using ctx: ^FontContext, rw, rh: int) -> (rx, ry: int, ok
|
|||||||
|
|
||||||
// Perform the actual packing.
|
// Perform the actual packing.
|
||||||
__AtlasAddSkylineLevel(ctx, besti, bestx, besty, rw, rh)
|
__AtlasAddSkylineLevel(ctx, besti, bestx, besty, rw, rh)
|
||||||
ok = true
|
return bestx, besty, true
|
||||||
rx = bestx
|
|
||||||
ry = besty
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
__AtlasAddWhiteRect :: proc(ctx: ^FontContext, w, h: int) {
|
__AtlasAddWhiteRect :: proc(ctx: ^FontContext, w, h: int) -> bool {
|
||||||
gx, gy, ok := __AtlasAddRect(ctx, w, h)
|
gx, gy := __AtlasAddRect(ctx, w, h) or_return
|
||||||
|
|
||||||
if !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rasterize
|
// Rasterize
|
||||||
dst := ctx.textureData[gx + gy * ctx.width:]
|
dst := ctx.textureData[gx + gy * ctx.width:]
|
||||||
@@ -336,10 +312,12 @@ __AtlasAddWhiteRect :: proc(ctx: ^FontContext, w, h: int) {
|
|||||||
dst = dst[ctx.width:]
|
dst = dst[ctx.width:]
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.dirtyRect[0] = cast(f32) min(int(ctx.dirtyRect[0]), gx)
|
ctx.dirtyRect[0] = f32(min(int(ctx.dirtyRect[0]), gx))
|
||||||
ctx.dirtyRect[1] = cast(f32) min(int(ctx.dirtyRect[1]), gy)
|
ctx.dirtyRect[1] = f32(min(int(ctx.dirtyRect[1]), gy))
|
||||||
ctx.dirtyRect[2] = cast(f32) max(int(ctx.dirtyRect[2]), gx + w)
|
ctx.dirtyRect[2] = f32(max(int(ctx.dirtyRect[2]), gx + w))
|
||||||
ctx.dirtyRect[3] = cast(f32) max(int(ctx.dirtyRect[3]), gy + h)
|
ctx.dirtyRect[3] = f32(max(int(ctx.dirtyRect[3]), gy + h))
|
||||||
|
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
AddFontPath :: proc(
|
AddFontPath :: proc(
|
||||||
@@ -372,6 +350,7 @@ AddFontMem :: proc(
|
|||||||
|
|
||||||
stbtt.InitFont(&res.info, &res.loadedData[0], 0)
|
stbtt.InitFont(&res.info, &res.loadedData[0], 0)
|
||||||
ascent, descent, line_gap: i32
|
ascent, descent, line_gap: i32
|
||||||
|
|
||||||
stbtt.GetFontVMetrics(&res.info, &ascent, &descent, &line_gap)
|
stbtt.GetFontVMetrics(&res.info, &ascent, &descent, &line_gap)
|
||||||
fh := f32(ascent - descent)
|
fh := f32(ascent - descent)
|
||||||
res.ascender = f32(ascent) / fh
|
res.ascender = f32(ascent) / fh
|
||||||
@@ -417,9 +396,7 @@ GetFontByName :: proc(ctx: ^FontContext, name: string) -> int {
|
|||||||
|
|
||||||
__lutReset :: proc(font: ^Font) {
|
__lutReset :: proc(font: ^Font) {
|
||||||
// set lookup table
|
// set lookup table
|
||||||
for i in 0..<HASH_LUT_SIZE {
|
slice.fill(font.lut[:], -1)
|
||||||
font.lut[i] = -1
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
__hashint :: proc(a: u32) -> u32 {
|
__hashint :: proc(a: u32) -> u32 {
|
||||||
@@ -464,23 +441,21 @@ __getGlyph :: proc(
|
|||||||
codepoint: rune,
|
codepoint: rune,
|
||||||
isize: i16,
|
isize: i16,
|
||||||
blur: i16 = 0,
|
blur: i16 = 0,
|
||||||
) -> (res: ^Glyph) #no_bounds_check {
|
) -> (res: ^Glyph, ok: bool) #no_bounds_check {
|
||||||
if isize < 2 {
|
if isize < 2 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// find code point and size
|
// find code point and size
|
||||||
h := __hashint(u32(codepoint)) & (HASH_LUT_SIZE - 1)
|
h := __hashint(u32(codepoint)) & (HASH_LUT_SIZE - 1)
|
||||||
i := font.lut[h]
|
for i := font.lut[h]; i != -1; /**/ {
|
||||||
for i != -1 {
|
|
||||||
glyph := &font.glyphs[i]
|
glyph := &font.glyphs[i]
|
||||||
|
|
||||||
if
|
if glyph.codepoint == codepoint &&
|
||||||
glyph.codepoint == codepoint &&
|
|
||||||
glyph.isize == isize &&
|
glyph.isize == isize &&
|
||||||
glyph.blurSize == blur
|
glyph.blurSize == blur {
|
||||||
{
|
|
||||||
res = glyph
|
res = glyph
|
||||||
|
ok = true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -513,16 +488,11 @@ __getGlyph :: proc(
|
|||||||
gh := (y1 - y0) + i32(padding) * 2
|
gh := (y1 - y0) + i32(padding) * 2
|
||||||
|
|
||||||
// Find free spot for the rect in the atlas
|
// Find free spot for the rect in the atlas
|
||||||
gx, gy, ok := __AtlasAddRect(ctx, int(gw), int(gh))
|
gx, gy, rect_ok := __AtlasAddRect(ctx, int(gw), int(gh))
|
||||||
if !ok {
|
if !rect_ok {
|
||||||
// try again with expanded
|
// try again with expanded
|
||||||
ExpandAtlas(ctx, ctx.width * 2, ctx.height * 2)
|
ExpandAtlas(ctx, ctx.width * 2, ctx.height * 2)
|
||||||
gx, gy, ok = __AtlasAddRect(ctx, int(gw), int(gh))
|
gx, gy = __AtlasAddRect(ctx, int(gw), int(gh)) or_return
|
||||||
}
|
|
||||||
|
|
||||||
// still not ok?
|
|
||||||
if !ok {
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init glyph.
|
// Init glyph.
|
||||||
@@ -575,11 +545,12 @@ __getGlyph :: proc(
|
|||||||
__blur(dst, int(gw), int(gh), ctx.width, blurSize)
|
__blur(dst, int(gw), int(gh), ctx.width, blurSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.dirtyRect[0] = cast(f32) min(int(ctx.dirtyRect[0]), int(res.x0))
|
ctx.dirtyRect[0] = f32(min(int(ctx.dirtyRect[0]), int(res.x0)))
|
||||||
ctx.dirtyRect[1] = cast(f32) min(int(ctx.dirtyRect[1]), int(res.y0))
|
ctx.dirtyRect[1] = f32(min(int(ctx.dirtyRect[1]), int(res.y0)))
|
||||||
ctx.dirtyRect[2] = cast(f32) max(int(ctx.dirtyRect[2]), int(res.x1))
|
ctx.dirtyRect[2] = f32(max(int(ctx.dirtyRect[2]), int(res.x1)))
|
||||||
ctx.dirtyRect[3] = cast(f32) max(int(ctx.dirtyRect[3]), int(res.y1))
|
ctx.dirtyRect[3] = f32(max(int(ctx.dirtyRect[3]), int(res.y1)))
|
||||||
|
|
||||||
|
ok = true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -640,7 +611,7 @@ __blurRows :: proc(dst: []u8, w, h, dstStride, alpha: int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
__blur :: proc(dst: []u8, w, h, dstStride: int, blurSize: i16) {
|
__blur :: proc(dst: []u8, w, h, dstStride: int, blurSize: i16) {
|
||||||
assert(blurSize != 0)
|
assert(blurSize > 0)
|
||||||
|
|
||||||
// Calculate the alpha such that 90% of the kernel is within the radius. (Kernel extends to infinity)
|
// Calculate the alpha such that 90% of the kernel is within the radius. (Kernel extends to infinity)
|
||||||
sigma := f32(blurSize) * 0.57735 // 1 / sqrt(3)
|
sigma := f32(blurSize) * 0.57735 // 1 / sqrt(3)
|
||||||
@@ -710,9 +681,10 @@ ExpandAtlas :: proc(ctx: ^FontContext, width, height: int, allocator := context.
|
|||||||
ResetAtlas :: proc(ctx: ^FontContext, width, height: int, allocator := context.allocator) -> bool {
|
ResetAtlas :: proc(ctx: ^FontContext, width, height: int, allocator := context.allocator) -> bool {
|
||||||
if width == ctx.width && height == ctx.height {
|
if width == ctx.width && height == ctx.height {
|
||||||
// just clear
|
// just clear
|
||||||
mem.zero_slice(ctx.textureData)
|
slice.zero(ctx.textureData)
|
||||||
} else {
|
} else {
|
||||||
// realloc
|
// realloc
|
||||||
|
delete(ctx.textureData, allocator)
|
||||||
ctx.textureData = make([]byte, width * height, allocator)
|
ctx.textureData = make([]byte, width * height, allocator)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -732,7 +704,7 @@ ResetAtlas :: proc(ctx: ^FontContext, width, height: int, allocator := context.a
|
|||||||
ctx.itw = 1.0 / f32(width)
|
ctx.itw = 1.0 / f32(width)
|
||||||
ctx.ith = 1.0 / f32(height)
|
ctx.ith = 1.0 / f32(height)
|
||||||
|
|
||||||
__AtlasAddWhiteRect(ctx, 2, 2)
|
_ = __AtlasAddWhiteRect(ctx, 2, 2)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1041,6 +1013,9 @@ TextIterInit :: proc(
|
|||||||
y: f32,
|
y: f32,
|
||||||
text: string,
|
text: string,
|
||||||
) -> (res: TextIter) {
|
) -> (res: TextIter) {
|
||||||
|
|
||||||
|
x, y := x, y
|
||||||
|
|
||||||
state := __getState(ctx)
|
state := __getState(ctx)
|
||||||
res.font = __getFont(ctx, state.font)
|
res.font = __getFont(ctx, state.font)
|
||||||
res.isize = i16(f32(state.size) * 10)
|
res.isize = i16(f32(state.size) * 10)
|
||||||
@@ -1048,15 +1023,12 @@ TextIterInit :: proc(
|
|||||||
res.scale = __getPixelHeightScale(res.font, f32(res.isize) / 10)
|
res.scale = __getPixelHeightScale(res.font, f32(res.isize) / 10)
|
||||||
|
|
||||||
// align horizontally
|
// align horizontally
|
||||||
x := x
|
|
||||||
y := y
|
|
||||||
switch state.ah {
|
switch state.ah {
|
||||||
case .LEFT: {}
|
case .LEFT:
|
||||||
|
/**/
|
||||||
case .CENTER:
|
case .CENTER:
|
||||||
width := TextBounds(ctx, text, x, y, nil)
|
width := TextBounds(ctx, text, x, y, nil)
|
||||||
x = math.round(x - width * 0.5)
|
x = math.round(x - width * 0.5)
|
||||||
|
|
||||||
case .RIGHT:
|
case .RIGHT:
|
||||||
width := TextBounds(ctx, text, x, y, nil)
|
width := TextBounds(ctx, text, x, y, nil)
|
||||||
x -= width
|
x -= width
|
||||||
@@ -1066,10 +1038,8 @@ TextIterInit :: proc(
|
|||||||
y = math.round(y + __getVerticalAlign(ctx, res.font, state.av, res.isize))
|
y = math.round(y + __getVerticalAlign(ctx, res.font, state.av, res.isize))
|
||||||
|
|
||||||
// set positions
|
// set positions
|
||||||
res.x = x
|
res.x, res.nextx = x, x
|
||||||
res.nextx = x
|
res.y, res.nexty = y, y
|
||||||
res.y = y
|
|
||||||
res.nexty = y
|
|
||||||
res.previousGlyphIndex = -1
|
res.previousGlyphIndex = -1
|
||||||
res.spacing = state.spacing
|
res.spacing = state.spacing
|
||||||
res.text = text
|
res.text = text
|
||||||
@@ -1097,13 +1067,12 @@ TextIterNext :: proc(
|
|||||||
iter.x = iter.nextx
|
iter.x = iter.nextx
|
||||||
iter.y = iter.nexty
|
iter.y = iter.nexty
|
||||||
iter.codepointCount += 1
|
iter.codepointCount += 1
|
||||||
glyph := __getGlyph(ctx, iter.font, iter.codepoint, iter.isize, iter.iblur)
|
if glyph, ok := __getGlyph(ctx, iter.font, iter.codepoint, iter.isize, iter.iblur); ok {
|
||||||
|
|
||||||
if glyph != nil {
|
|
||||||
__getQuad(ctx, iter.font, iter.previousGlyphIndex, glyph, iter.scale, iter.spacing, &iter.nextx, &iter.nexty, quad)
|
__getQuad(ctx, iter.font, iter.previousGlyphIndex, glyph, iter.scale, iter.spacing, &iter.nextx, &iter.nexty, quad)
|
||||||
|
iter.previousGlyphIndex = glyph.index
|
||||||
|
} else {
|
||||||
|
iter.previousGlyphIndex = -1
|
||||||
}
|
}
|
||||||
|
|
||||||
iter.previousGlyphIndex = glyph == nil ? -1 : glyph.index
|
|
||||||
ok = true
|
ok = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -1127,12 +1096,9 @@ TextBounds :: proc(
|
|||||||
font := __getFont(ctx, state.font)
|
font := __getFont(ctx, state.font)
|
||||||
|
|
||||||
// bunch of state
|
// bunch of state
|
||||||
x := x
|
x, y := x, y
|
||||||
y := y
|
minx, maxx := x, x
|
||||||
minx := x
|
miny, maxy := y, y
|
||||||
maxx := x
|
|
||||||
miny := y
|
|
||||||
maxy := y
|
|
||||||
start_x := x
|
start_x := x
|
||||||
|
|
||||||
// iterate
|
// iterate
|
||||||
@@ -1143,9 +1109,7 @@ TextBounds :: proc(
|
|||||||
codepoint: rune
|
codepoint: rune
|
||||||
for byte_offset in 0..<len(text) {
|
for byte_offset in 0..<len(text) {
|
||||||
if __decutf8(&utf8state, &codepoint, text[byte_offset]) {
|
if __decutf8(&utf8state, &codepoint, text[byte_offset]) {
|
||||||
glyph := __getGlyph(ctx, font, codepoint, isize, iblur)
|
if glyph, ok := __getGlyph(ctx, font, codepoint, isize, iblur); ok {
|
||||||
|
|
||||||
if glyph != nil {
|
|
||||||
__getQuad(ctx, font, previousGlyphIndex, glyph, scale, state.spacing, &x, &y, &quad)
|
__getQuad(ctx, font, previousGlyphIndex, glyph, scale, state.spacing, &x, &y, &quad)
|
||||||
|
|
||||||
if quad.x0 < minx {
|
if quad.x0 < minx {
|
||||||
@@ -1170,21 +1134,23 @@ TextBounds :: proc(
|
|||||||
maxy = quad.y0
|
maxy = quad.y0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
previousGlyphIndex = glyph.index
|
||||||
|
} else {
|
||||||
|
previousGlyphIndex = -1
|
||||||
}
|
}
|
||||||
|
|
||||||
previousGlyphIndex = glyph == nil ? -1 : glyph.index
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// horizontal alignment
|
// horizontal alignment
|
||||||
advance := x - start_x
|
advance := x - start_x
|
||||||
switch state.ah {
|
switch state.ah {
|
||||||
case .LEFT: {}
|
case .LEFT:
|
||||||
|
/**/
|
||||||
case .CENTER:
|
case .CENTER:
|
||||||
minx -= advance * 0.5
|
minx -= advance * 0.5
|
||||||
maxx -= advance * 0.5
|
maxx -= advance * 0.5
|
||||||
|
|
||||||
case .RIGHT:
|
case .RIGHT:
|
||||||
minx -= advance
|
minx -= advance
|
||||||
maxx -= advance
|
maxx -= advance
|
||||||
@@ -1210,8 +1176,8 @@ VerticalMetrics :: proc(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// reset to single state
|
// reset to single state
|
||||||
BeginState :: proc(using ctx: ^FontContext) {
|
BeginState :: proc(ctx: ^FontContext) {
|
||||||
state_count = 0
|
ctx.state_count = 0
|
||||||
PushState(ctx)
|
PushState(ctx)
|
||||||
ClearState(ctx)
|
ClearState(ctx)
|
||||||
}
|
}
|
||||||
@@ -1223,7 +1189,6 @@ EndState :: proc(using ctx: ^FontContext) {
|
|||||||
if callbackUpdate != nil {
|
if callbackUpdate != nil {
|
||||||
callbackUpdate(userData, dirtyRect, raw_data(textureData))
|
callbackUpdate(userData, dirtyRect, raw_data(textureData))
|
||||||
}
|
}
|
||||||
|
|
||||||
__dirtyRectReset(ctx)
|
__dirtyRectReset(ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user