• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

sile-typesetter / sile / 9688261573

26 Jun 2024 11:43PM UTC coverage: 69.955% (-1.4%) from 71.339%
9688261573

push

github

web-flow
Merge 115d95e3f into 8c5a2a2ba

12182 of 17414 relevant lines covered (69.96%)

4406.38 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.55
/core/font.lua
1
--- font
2
-- @module SILE.font
3
local icu = require("justenoughicu")
372✔
4

5
local lastshaper
6

7
SILE.registerCommand("font", function (options, content)
744✔
8
   if SU.ast.hasContent(content) then
1,880✔
9
      SILE.settings:pushState()
265✔
10
   end
11
   if options.filename then
940✔
12
      SILE.settings:set("font.filename", options.filename)
4✔
13
   end
14
   if options.family then
940✔
15
      SILE.settings:set("font.family", options.family)
634✔
16
      SILE.settings:set("font.filename", "")
634✔
17
   end
18
   if options.size then
940✔
19
      local size = SU.cast("measurement", options.size)
782✔
20
      if not size then
782✔
21
         SU.error("Couldn't parse font size " .. options.size)
×
22
      end
23
      SILE.settings:set("font.size", size:absolute())
1,564✔
24
   end
25
   if options.weight then
940✔
26
      SILE.settings:set("font.weight", 0 + options.weight)
596✔
27
   end
28
   if options.style then
940✔
29
      SILE.settings:set("font.style", options.style)
666✔
30
   end
31
   if options.variant then
940✔
32
      SILE.settings:set("font.variant", options.variant)
569✔
33
   end
34
   if options.features then
940✔
35
      SILE.settings:set("font.features", options.features)
577✔
36
   end
37
   if options.variations then
940✔
38
      SILE.settings:set("font.variations", options.variations)
569✔
39
   end
40
   if options.direction then
940✔
41
      SILE.settings:set("font.direction", options.direction)
574✔
42
   end
43
   if options.language then
940✔
44
      if options.language ~= "und" and icu and icu.canonicalize_language then
596✔
45
         local newlang = icu.canonicalize_language(options.language)
596✔
46
         -- if newlang ~= options.language then
47
         -- SU.warn("Language '"..options.language.."' not canonical, '"..newlang.."' will be used instead.")
48
         -- end
49
         options.language = newlang
596✔
50
      end
51
      SILE.languageSupport.loadLanguage(options.language)
596✔
52
      SILE.settings:set("document.language", options.language)
596✔
53
   end
54
   if options.script then
940✔
55
      SILE.settings:set("font.script", options.script)
1,142✔
56
   elseif SILE.settings:get("document.language") then
738✔
57
      local lang = SILE.languageSupport.languages[SILE.settings:get("document.language")]
738✔
58
      if lang and lang.defaultScript then
369✔
59
         SILE.settings:set("font.script", lang.defaultScript)
1✔
60
      end
61
   end
62
   if options.hyphenchar then
940✔
63
      -- must be in the form of, for example, "-" or "U+2010" or "0x2010" (Unicode hex codepoint)
64
      SILE.settings:set("font.hyphenchar", SU.utf8charfromcodepoint(options.hyphenchar))
1,140✔
65
   end
66

67
   -- We must *actually* load the font here, because by the time we're inside
68
   -- SILE.shaper.shapeToken, it's too late to respond appropriately to things
69
   -- that the post-load hook might want to do.
70
   SILE.font.cache(SILE.font.loadDefaults({}), SILE.shaper.getFace)
1,880✔
71

72
   if SU.ast.hasContent(content) then
1,880✔
73
      SILE.process(content)
265✔
74
      SILE.settings:popState()
265✔
75
      if SILE.shaper._name == "harfbuzzWithColor" and lastshaper then
265✔
76
         SU.debug("color-fonts", "Switching from color fonts shaper back to previous shaper")
1✔
77
         SILE.typesetter:leaveHmode(true)
1✔
78
         lastshaper, SILE.shaper = nil, lastshaper
1✔
79
      end
80
   end
81
end, "Set current font family, size, weight, style, variant, script, direction and language", nil, true)
1,312✔
82

83
SILE.settings:declare({ parameter = "font.family", type = "string or nil", default = "Gentium Plus" })
372✔
84
SILE.settings:declare({ parameter = "font.size", type = "number or integer", default = 10 })
372✔
85
SILE.settings:declare({ parameter = "font.weight", type = "integer", default = 400 })
372✔
86
SILE.settings:declare({ parameter = "font.variant", type = "string", default = "normal" })
372✔
87
SILE.settings:declare({ parameter = "font.script", type = "string", default = "" })
372✔
88
SILE.settings:declare({ parameter = "font.style", type = "string", default = "" })
372✔
89
SILE.settings:declare({ parameter = "font.direction", type = "string", default = "" })
372✔
90
SILE.settings:declare({ parameter = "font.filename", type = "string or nil", default = "" })
372✔
91
SILE.settings:declare({ parameter = "font.features", type = "string", default = "" })
372✔
92
SILE.settings:declare({ parameter = "font.variations", type = "string", default = "" })
372✔
93
SILE.settings:declare({ parameter = "font.hyphenchar", type = "string", default = "-" })
372✔
94

95
SILE.fontCache = {}
372✔
96

97
local _key = function (options)
98
   return table.concat({
40,622✔
99
      options.family,
40,622✔
100
      ("%g"):format(SILE.types.measurement(options.size):tonumber()),
121,866✔
101
      ("%d"):format(options.weight or 0),
40,622✔
102
      options.style,
40,622✔
103
      options.variant,
40,622✔
104
      options.features,
40,622✔
105
      options.variations,
40,622✔
106
      options.direction,
40,622✔
107
      options.filename,
40,622✔
108
   }, ";")
40,622✔
109
end
110

111
local font = {
372✔
112

113
   loadDefaults = function (options)
114
      if not options.family then
7,414✔
115
         options.family = SILE.settings:get("font.family")
10,544✔
116
      end
117
      if not options.size then
7,414✔
118
         options.size = SILE.settings:get("font.size")
10,544✔
119
      end
120
      if not options.weight then
7,414✔
121
         options.weight = SILE.settings:get("font.weight")
10,918✔
122
      end
123
      if not options.style then
7,414✔
124
         options.style = SILE.settings:get("font.style")
10,918✔
125
      end
126
      if not options.variant then
7,414✔
127
         options.variant = SILE.settings:get("font.variant")
14,828✔
128
      end
129
      if SILE.settings:get("font.filename") ~= "" then
14,828✔
130
         options.filename = SILE.settings:get("font.filename")
84✔
131
         options.family = ""
42✔
132
      end
133
      if not options.language then
7,414✔
134
         options.language = SILE.settings:get("document.language")
14,454✔
135
      end
136
      if not options.script then
7,414✔
137
         options.script = SILE.settings:get("font.script")
14,828✔
138
      end
139
      if not options.direction then
7,414✔
140
         options.direction = SILE.settings:get("font.direction")
14,828✔
141
         if not options.direction or options.direction == "" then
7,414✔
142
            options.direction = SILE.typesetter and SILE.typesetter.frame and SILE.typesetter.frame:writingDirection()
6,791✔
143
               or "LTR"
6,791✔
144
         end
145
      end
146
      if not options.features then
5,695✔
147
         options.features = SILE.settings:get("font.features")
11,390✔
148
      end
149
      if not options.variations then
5,695✔
150
         options.variations = SILE.settings:get("font.variations")
11,390✔
151
      end
152
      if not options.hyphenchar then
5,695✔
153
         options.hyphenchar = SILE.settings:get("font.hyphenchar")
11,390✔
154
      end
155
      return options
5,695✔
156
   end,
157

158
   cache = function (options, callback)
159
      local key = _key(options)
4,529✔
160
      if not SILE.fontCache[key] then
4,529✔
161
         SU.debug("fonts", "Looking for", key)
196✔
162
         local face = callback(options)
196✔
163
         SILE.fontCache[key] = face
196✔
164
      end
165
      local cached = SILE.fontCache[key]
4,529✔
166
      SILE.font.postLoadHook(cached)
4,529✔
167
      return cached
4,529✔
168
   end,
169

170
   finish = function ()
171
      for key, font in pairs(SILE.fontCache) do
291✔
172
         if font.tempfilename ~= font.filename then
196✔
173
            SU.debug("fonts", "Removing temporary file of", key, ":", font.tempfilename)
×
174
            os.remove(font.tempfilename)
×
175
         end
176
      end
177
   end,
178

179
   postLoadHook = function (face)
180
      local ot = require("core.opentype-parser")
4,529✔
181
      local font = ot.parseFont(face)
4,529✔
182
      if font.cpal then
4,529✔
183
         SILE.require("packages.color-fonts")
×
184
         if SILE.shaper._name ~= "harfbuzzWithColor" then
×
185
            SU.debug("color-fonts", "Switching to color font Shaper")
×
186
            SILE.typesetter:leaveHmode(true)
×
187
            lastshaper, SILE.shaper = SILE.shaper, SILE.shapers.harfbuzzWithColor()
×
188
         end
189
      end
190
   end,
191

192
   _key = _key,
188✔
193
}
194

195
return font
188✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc