@@ -68,12 +68,16 @@ Then this is how this function would match different search strings:
68
68
- "times new roman" => Times New Roman
69
69
- "arial" => no match
70
70
"""
71
- function match_font (face:: FTFont , searchstring )
71
+ function match_font (face:: FTFont , searchparts )
72
72
fname = family_name (face)
73
73
sname = style_name (face)
74
- full_name = " $fname $sname "
75
- # \W splits at all groups of non-word characters (like space, -, ., etc)
76
- searchparts = unique (split (lowercase (searchstring), r" \W +" , keepempty= false ))
74
+ # Regular should get selected / full match if we dont specificy any styling!
75
+ full_name = if sname == " regular"
76
+ " $fname "
77
+ else
78
+ " $fname $sname "
79
+ end
80
+ full_name == " " && return 0
77
81
# count letters of parts that occurred in the font name positively and those that didn't negatively.
78
82
# we assume that the user knows at least parts of the name and doesn't misspell them
79
83
# but they might not know the exact name, especially for long font names, or they
@@ -82,7 +86,7 @@ function match_font(face::FTFont, searchstring)
82
86
# doesn't match against it, therefore rejecting fonts that mismatch more parts
83
87
# than they match. this heuristic should be good enough to provide a hassle-free
84
88
# font selection experience where most spellings that are expected to work, work.
85
- match_score = sum (map (part -> sign ( occursin (part, full_name)) * length (part), searchparts))
89
+ match_score = sum (map (part -> ( 2 * occursin (part, full_name) - 1 ) * length (part), searchparts))
86
90
# give shorter font names that matched equally well a higher score after the decimal point.
87
91
# this should usually pick the "standard" variant of a font as long as it
88
92
# doesn't have a special identifier like "regular", "roman", "book", etc.
@@ -105,28 +109,29 @@ function try_load(fpath)
105
109
end
106
110
107
111
function findfont (
108
- name :: String ;
112
+ searchstring :: String ;
109
113
italic:: Bool = false , # this is unused in the new implementation
110
114
bold:: Bool = false , # and this as well
111
115
additional_fonts:: String = " "
112
116
)
113
117
font_folders = copy (fontpaths ())
114
118
# normalized_name = family_name(name)
115
119
isempty (additional_fonts) || pushfirst! (font_folders, additional_fonts)
116
-
120
+ # \W splits at all groups of non-word characters (like space, -, ., etc)
121
+ searchparts = unique (split (lowercase (searchstring), r" \W +" , keepempty= false ))
117
122
candidates = Pair{FTFont, Float64}[]
118
123
for folder in font_folders
119
124
for font in readdir (folder)
120
125
fpath = joinpath (folder, font)
121
126
face = try_load (fpath)
122
127
face === nothing && continue
123
- score = match_font (face, name)
124
-
128
+ score = match_font (face, searchparts)
125
129
# only take results with net positive character matches into account
126
130
if floor (score) > 0
127
131
push! (candidates, face => score)
128
132
else
129
- finalize (face) # help gc a bit!
133
+ # help gc a bit! Otherwise, this won't end well with the font keeping tons of open files
134
+ finalize (face)
130
135
end
131
136
end
132
137
end
0 commit comments