Skip to content

Commit 7c84031

Browse files
Use mmapping to avoid unicode issues on windows (#94)
* load fonts from mmapped files to avoid unicode issues in freetype on windows * add a test --------- Co-authored-by: Simon <[email protected]>
1 parent fe61188 commit 7c84031

File tree

4 files changed

+29
-3
lines changed

4 files changed

+29
-3
lines changed

Project.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,15 @@ ColorVectorSpace = "c3611d14-8923-5661-9e6a-0046d554d3a4"
88
Colors = "5ae59095-9a9b-59fe-a467-6f913c188581"
99
FreeType = "b38be410-82b0-50bf-ab77-7b57e271db43"
1010
GeometryBasics = "5c1252a2-5f33-56bf-86c9-59e7332b4326"
11+
Mmap = "a63ad114-7e13-5084-954f-fe012c677804"
1112

1213
[compat]
1314
BaseDirs = "1"
1415
ColorVectorSpace = "0.8, 0.9, 0.10, 0.11"
1516
Colors = "0.11, 0.12, 0.13"
1617
FreeType = "4"
1718
GeometryBasics = "0.4.1, 0.5"
19+
Mmap = "1"
1820
julia = "1.6"
1921

2022
[extras]

src/FreeTypeAbstraction.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import Base: /, *, ==, @lock
66
import Base.Broadcast: BroadcastStyle, Style, broadcasted
77
using GeometryBasics: StaticVector
88
using BaseDirs
9+
import Mmap
910

1011
include("types.jl")
1112
include("findfonts.jl")

src/types.jl

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,16 @@ function newface(facename, faceindex::Real=0, ftlib=FREE_FONT_LIBRARY)
3030
return face[]
3131
end
3232

33+
function newface_mmapped(filepath, faceindex::Real=0, ftlib=FREE_FONT_LIBRARY)
34+
mmapped = open(filepath, "r") do io
35+
Mmap.mmap(io)
36+
end
37+
face = Ref{FT_Face}()
38+
err = @lock LIBRARY_LOCK FT_New_Memory_Face(ftlib[1], mmapped, length(mmapped), Int32(faceindex), face)
39+
check_error(err, "Couldn't load font \"$filepath\"")
40+
return face[], mmapped
41+
end
42+
3343

3444
struct FontExtent{T}
3545
vertical_bearing::Vec{2, T}
@@ -135,9 +145,10 @@ mutable struct FTFont
135145
use_cache::Bool
136146
extent_cache::Dict{UInt64, FontExtent{Float32}}
137147
lock::ReentrantLock # lock this for the duration of any FT operation on ft_ptr
138-
function FTFont(ft_ptr::FreeType.FT_Face, use_cache::Bool=true)
148+
mmapped::Union{Nothing,Vector{UInt8}}
149+
function FTFont(ft_ptr::FreeType.FT_Face, use_cache::Bool=true, mmapped = nothing)
139150
extent_cache = Dict{UInt64, FontExtent{Float32}}()
140-
face = new(ft_ptr, use_cache, extent_cache, ReentrantLock())
151+
face = new(ft_ptr, use_cache, extent_cache, ReentrantLock(), mmapped)
141152
finalizer(safe_free, face)
142153
return face
143154
end
@@ -146,7 +157,10 @@ end
146157
use_cache(face::FTFont) = getfield(face, :use_cache)
147158
get_cache(face::FTFont) = getfield(face, :extent_cache)
148159

149-
FTFont(path::String) = FTFont(newface(path))
160+
function FTFont(path::String, use_cache::Bool=true)
161+
face, mmapped = newface_mmapped(path)
162+
FTFont(face, use_cache, mmapped)
163+
end
150164

151165
# C interop
152166
Base.cconvert(::Type{FreeType.FT_Face}, font::FTFont) = font

test/runtests.jl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,15 @@ end
296296
end
297297
end
298298

299+
@testset "Unicode in path" begin
300+
mktempdir() do dir
301+
path = joinpath(dir, "𝓜𝔂 𝔽𝕒𝕟𝕔𝕪 𝐅𝐨𝐧𝐭 🅵🅸🅻🅴.ttf")
302+
cp(joinpath(@__DIR__, "hack_regular.ttf"), path)
303+
f = FreeTypeAbstraction.FTFont(path)
304+
@test repr(f) == "FTFont (family = Hack, style = Regular)"
305+
end
306+
end
307+
299308
@testset "Thread safety" begin
300309
mktempdir() do dir
301310
n = 100

0 commit comments

Comments
 (0)