Skip to content

Commit dfee5ff

Browse files
committed
fixes + add more needed functionality
1 parent 2804aae commit dfee5ff

File tree

4 files changed

+79
-23
lines changed

4 files changed

+79
-23
lines changed

src/layout.jl

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,15 @@ iter_or_array(x::AbstractArray) = x
55
iter_or_array(x::StaticArray) = repeated(x)
66

77

8-
function metrics_bb(char::Char, font::FTFont, scale)
9-
extent = get_extent(font, char) .* Vec2f0(scale)
8+
function metrics_bb(char::Char, font::FTFont, pixel_size)
9+
extent = get_extent(font, char) .* Vec2f0(pixel_size)
1010
mini = bearing(extent)
11-
return Rect2D(mini, Vec2f0(extent.scale)), extent
11+
return Rect2D(mini, Vec2f0(extent.pixel_size)), extent
12+
end
13+
14+
function glyph_ink_size(char::Char, font::FTFont, pixel_size)
15+
bb, extent = metrics_bb(char, font, pixel_size)
16+
return widths(bb)
1217
end
1318

1419
"""
@@ -41,7 +46,6 @@ function iterate_extents(f, line::AbstractString, fonts, scales)
4146
end
4247
end
4348

44-
4549
function glyph_rects(line::AbstractString, fonts, scales)
4650
rects = Rect2D[]
4751
iterate_extents(line, fonts, scales) do char, box, advance
@@ -53,3 +57,19 @@ end
5357
function boundingbox(line::AbstractString, fonts, scales)
5458
return reduce(union, glyph_rects(line, fonts, scales))
5559
end
60+
61+
function inkboundingbox(ext::FontExtent)
62+
l = leftinkbound(ext)
63+
r = rightinkbound(ext)
64+
b = bottominkbound(ext)
65+
t = topinkbound(ext)
66+
return FRect2D((l, b), (r - l, t - b))
67+
end
68+
69+
function height_insensitive_boundingbox(ext::FontExtent, font::FTFont)
70+
l = leftinkbound(ext)
71+
r = rightinkbound(ext)
72+
b = descender(font)
73+
t = ascender(font)
74+
return FRect2D((l, b), (r - l, t - b))
75+
end

src/rendering.jl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11

2-
function renderface(face::FTFont, c::Char,
3-
pixelsize::Integer=get_pixelsize(face))
2+
function renderface(face::FTFont, c::Char, pixelsize::Integer)
43
set_pixelsize(face, pixelsize)
54
loadchar(face, c)
65
glyph = face.glyph

src/types.jl

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,16 @@ struct FontExtent{T}
3535
scale::Vec{2, T}
3636
end
3737

38+
hadvance(ext::FontExtent) = ext.advance[1]
39+
inkwidth(ext::FontExtent) = ext.scale[1]
40+
inkheight(ext::FontExtent) = ext.scale[2]
41+
hbearing_ori_to_left(ext::FontExtent) = ext.horizontal_bearing[1]
42+
hbearing_ori_to_top(ext::FontExtent) = ext.horizontal_bearing[2]
43+
leftinkbound(ext::FontExtent) = hbearing_ori_to_left(ext)
44+
rightinkbound(ext::FontExtent) = leftinkbound(ext) + inkwidth(ext)
45+
bottominkbound(ext::FontExtent) = hbearing_ori_to_top(ext) - inkheight(ext)
46+
topinkbound(ext::FontExtent) = hbearing_ori_to_top(ext)
47+
3848
BroadcastStyle(::Type{<: FontExtent}) = Style{FontExtent}()
3949
BroadcastStyle(::Style{FontExtent}, x) = Style{FontExtent}()
4050
BroadcastStyle(x, ::Style{FontExtent}) = Style{FontExtent}()
@@ -110,20 +120,18 @@ end
110120

111121
mutable struct FTFont
112122
ft_ptr::FreeType.FT_Face
113-
current_pixelsize::Base.RefValue{Int}
114123
use_cache::Bool
115-
cache::Dict{Tuple{Int, Char}, FontExtent{Float32}}
116-
function FTFont(ft_ptr::FreeType.FT_Face, pixel_size::Int=64, use_cache::Bool=true)
117-
cache = Dict{Tuple{Int, Char}, FontExtent{Float32}}()
118-
face = new(ft_ptr, Ref(pixel_size), use_cache, cache)
124+
extent_cache::Dict{Char, FontExtent{Float32}}
125+
function FTFont(ft_ptr::FreeType.FT_Face, use_cache::Bool=true)
126+
extent_cache = Dict{Tuple{Int, Char}, FontExtent{Float32}}()
127+
face = new(ft_ptr, use_cache, extent_cache)
119128
finalizer(safe_free, face)
120-
FT_Set_Pixel_Sizes(face, pixel_size, 0);
121129
return face
122130
end
123131
end
124132

125133
use_cache(face::FTFont) = getfield(face, :use_cache)
126-
get_cache(face::FTFont) = getfield(face, :cache)
134+
get_cache(face::FTFont) = getfield(face, :extent_cache)
127135

128136
function FTFont(path::String)
129137
return FTFont(newface(path))
@@ -159,13 +167,9 @@ end
159167
# Allow broadcasting over fonts
160168
Base.Broadcast.broadcastable(ft::FTFont) = Ref(ft)
161169

162-
get_pixelsize(face::FTFont) = getfield(face, :current_pixelsize)[]
163-
164170
function set_pixelsize(face::FTFont, size::Integer)
165-
get_pixelsize(face) == size && return size
166171
err = FT_Set_Pixel_Sizes(face, size, size)
167172
check_error(err, "Couldn't set pixelsize")
168-
getfield(face, :current_pixelsize)[] = size
169173
return size
170174
end
171175

@@ -182,13 +186,13 @@ function kerning(c1::Char, c2::Char, face::FTFont)
182186
end
183187

184188
function loadchar(face::FTFont, c::Char)
185-
err = FT_Load_Char(face, c, FT_LOAD_RENDER)
189+
err = FT_Load_Char(face, c, FT_LOAD_RENDER | FT_LOAD_NO_HINTING)
186190
check_error(err, "Could not load char to render.")
187191
end
188192

189193
function get_extent(face::FTFont, char::Char)
190194
if use_cache(face)
191-
get!(get_cache(face), (get_pixelsize(face), char)) do
195+
get!(get_cache(face), char) do
192196
return internal_get_extent(face, char)
193197
end
194198
else
@@ -197,9 +201,11 @@ function get_extent(face::FTFont, char::Char)
197201
end
198202

199203
function internal_get_extent(face::FTFont, char::Char)
200-
err = FT_Load_Char(face, char, FT_LOAD_DEFAULT)
204+
err = FT_Load_Char(face, char, FT_LOAD_NO_SCALE)
201205
check_error(err, "Could not load char to get extend.")
202-
metrics = face.glyph.metrics
203-
# 64 since metrics are in 1/64 units (units to 26.6 fractional pixels)
204-
return FontExtent(metrics, Float32(64))
206+
# This gives us the font metrics in normalized units (-1, 1)
207+
return FontExtent(face.glyph.metrics, Float32(face.units_per_EM))
205208
end
209+
210+
descender(font) = font.descender / font.units_per_EM
211+
ascender(font) = font.ascender / font.units_per_EM

test/runtests.jl

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,37 @@ using FreeType
55

66
face = FreeTypeAbstraction.findfont("hack"; additional_fonts=@__DIR__)
77

8+
FreeTypeAbstraction.get_pixelsize(face)
9+
FreeTypeAbstraction.set_pixelsize(face, 122)
10+
FreeTypeAbstraction.set_pixelsize(face, 64)
11+
err = FT_Load_Char(face, 'm', FT_LOAD_DEFAULT)
12+
metrics = face.glyph.metrics
13+
# 64 since metrics are in 1/64 units (units to 26.6 fractional pixels)
14+
FontExtent(metrics, 64.0)
15+
16+
17+
18+
19+
20+
21+
22+
23+
err = FT_Load_Char(face, 'm', FT_LOAD_NO_AUTOHINT)
24+
metrics = face.glyph.metrics
25+
# 64 since metrics are in 1/64 units (units to 26.6 fractional pixels)
26+
FontExtent(metrics, 1.0)
27+
28+
29+
30+
31+
32+
33+
34+
35+
36+
37+
38+
839
bb = boundingbox("asdasd", face, 1.0)
940
@test bb == Rect(4.0, -1.0, 224.0, 50.0)
1041

0 commit comments

Comments
 (0)