summaryrefslogtreecommitdiff
path: root/macros/luatex/optex/base/fonts-resize.opm
blob: 9dcd6a03e826daa571837433db64ec4067fe1579 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
%% This is part of OpTeX project, see http://petr.olsak.net/optex

\_codedecl \setfontsize {Font resizing macros <2020-04-17>} % preloaded in format 

   \_doc -----------------------------
   The \`\setfontsize` `{<sizespec>}` saves the `<sizespec>` to the \`\_sizespec` macro.
   The \`\_optsize` value is calculated from the `<sizespec>`. 
   If the `<sizepec>` is in the `mag<number>` format then the contents of
   the `\_sizespec` macro is re-calculated to the `at<dimen>` format using 
   previous `\_optsize` value. 
   \par \goodbreak
   \_cod -----------------------------

\_newdimen \_optsize         \_optsize=10pt
\_newdimen \_defaultoptsize  \_defaultoptsize=10pt
\_newdimen\_lastmagsize

\_def\_setfontsize #1{%
   \_edef\_sizespec{#1}%
   \_ea \_setoptsize \_sizespec\_relax
   \_reloading
}
\_def\_setoptsize {\_isnextchar a{\_setoptsizeA}
                                 {\_isnextchar m{\_setoptsizeC}{\_setoptsizeB}}}
\_def\_setoptsizeA at#1\_relax{\_optsize=#1\_relax\_lastmagsize=\_optsize}   % at<dimen>
\_def\_setoptsizeB scaled#1\_relax{\_optsize=\_defaultoptsize\_relax} % scaled<scalenum>
\_def\_setoptsizeC mag#1\_relax{%
   \_ifdim\_lastmagsize>\_zo \_optsize=\_lastmagsize \_else \_optsize=\_pdffontsize\_font \_fi
   \_optsize=#1\_optsize 
   \_lastmagsize=\_optsize
   \_edef\_sizespec{at\_the\_optsize}%
}
\_public \setfontsize \defaultoptsize ;

   \_doc -----------------------------
   \`\_resizefont` `{<variant-name>}\<font switch>`, 
   for example `\resizefont{bf}\_tenbf` resizes the font given by the
   variant. The variant `XX` have its font switch `\_tenXX`.
   The \`\_doresizefont``\fontswitch` is used. It works in 
   TFM mode (\`\_doresizetfmfont`) or OTF mode (\^`\_doresizeunifont`).
   In both modes, it does
   \begtt \catcode`\<=13
   \_font \_tenXX = <fontname> \_sizespec
   \endtt
   The `<fontname>` is generated by the `\fontname` \TeX/ primitive where
   \`\_rfontskipat` removes the `at<dimen>` part of the `\_fontname` output.
   The `<fontname>` is generated differently in OTF mode, see 
   \^`\_doresizeunifont` macro.\nl
   The \`\_whatresize` is defined as `<variant-name>`.    
   \_cod -----------------------------

\_def\_resizefont#1#2{%
    \_edef\_whatresize{#1}%
    \_ifx \_fontselector \_undefined \_doresizefont#2%
    \_else \_ea \_doresizefont \_fontselector \_fi
    \_lastmagsize=\_zo
    \_slet{_tryload#1}{_relax}%
}
\_def\_doresizetfmfont#1{\_logfont{#1}%
   \_ea\_font\_ea#1\_ea\_rfontskipat 
      \_fontname \_cs{_ten\_whatresize} \_relax\_space \_sizespec \_relax
}
\_let\_doresizefont=\_doresizetfmfont
\_def\_logfont#1{} % default is no logging of used fonts 

\_def\_rfontskipat#1{\_ifx#1"\_ea\_rfskipatX \_else\_ea\_rfskipatN\_ea#1\_fi}
\_def\_rfskipatX #1" #2\_relax{"\_whichtfm{#1}"} 
\_def\_rfskipatN #1 #2\_relax{\_whichtfm{#1}}

   \_doc -----------------------------
   \`\fontdef` `<font switch>{<modifiers><variant selector>}`
   opens group, runs `<modifiers><variant selector>` (i.e.\ it runs `#2` parameter).
   The font switch `#1` saved in the \`\_fontselector` macro is re-declared
   because the variant selector runs the \^`\_resizefont`. Now, we need to
   keep the current meaning of the font switch `#1` but we must leave the
   opened group. This is done by the \`\_keepmeaning` macro. 
   \nl
   \`\fontlet` `<font switch A> <font switch B> <size spec>` does
   \begtt \catcode`\<=13
   \font <font switch A> = <fontname> <sizespec> 
   \endtt
   The `<fontname>` is extracted using the primitive command `\_fontname <font switch B>`.  
   \_cod -----------------------------

\_def \_fontdef #1#2{\_begingroup
   \_ifx\_fontselector\_undefined \_def\_fontselector{#1}\_fi
   \_reloading #2%
   \_ea \_keepmeaning \_fontselector \_endgroup
}
\_def\_fontlet#1#2{\_ifx #2=\_ea\_fontlet \_ea#1\_else
  \_ea\_font\_ea#1\_ea\_rfontskipat\_fontname#2 \_relax\_space \_fi
}
\_def \_keepmeaning #1#2{\_global\_let\_keepmeaningdata=#1%
   #2\_let#1=\_keepmeaningdata \_global\_let\_keepmeaningdata=\_undefined
}
\_public \fontdef \fontlet ;

   \_doc -----------------------------
   \`\newcurrfontsize` `<size spec>` sets current font size to the `<size spec>`
   It is implemented by \^`\fontlet`.
   The font switch of the current font is extracted by `\_the\_font`.
   We must re-create the control sequence `\_the\_font` because
   its original meaning is set to \"inaccessible" by \TeX/ when `\font`
   primitive is started.
   \nl
   \`\resizethefont` is implemented by `\newcurrfontsize` using data from
   the \^`\_sizespec` macro.
   \_cod -----------------------------

\_def \_newcurrfontsize #1{% \newcurrfontsize{at25pt}
   \_edef\_tmp{\_ea\_csstring \_the\_font}%
   \_ea \_fontlet \_csname \_tmp\_ea\_endcsname \_the\_font \_space #1\_relax
   \_csname \_tmp\_endcsname
}
\_protected\_def \_resizethefont{\_newcurrfontsize\_sizespec}

 \_public \newcurrfontsize \resizethefont ; 

   \_doc -----------------------------
   The variant selector is defined by `\protected\def\XX{\_tryloadXX \_tenXX}`
   The `\_tryloadXX` can be in `\_relax` state if no font modifiers were
   declared. But normally it does \^`\_resizefont``{XX}\tenXX`. This meaning
   is activated by the \`\_reloading` macro.
   \_cod -----------------------------

\_def\_reloading{\_loadf{rm}\_tenrm \_loadf{bf}\_tenbf
   \_loadf{it}\_tenit \_loadf{bi}\_tenbi
}
\_def\_loadf#1#2{\_sdef{_tryload#1}{\_ifmmode \_else \_resizefont{#1}#2\_fi}}
\_def\_tryloadtt{\_resizefont{tt}\_tentt}

\_let\_tryloadrm=\_relax
\_let\_tryloadbf=\_relax
\_let\_tryloadit=\_relax
\_let\_tryloadbi=\_relax

    \_doc ----------------------------
    The font selection system allows to use \`\currvar`
    instead explicitly specified variant selector. The current variant
    is extracted from `\the\font` output which could be `\_tenXX` control
    sequence. Then `\currvar` expands to `\_rm` or `\_it` etc.  
    \_cod ----------------------------   

\_protected \_def \_currvar{\_cs{_currvar:\_ea \_csstring \_the\_font}}
\_sdef{_currvar:_tenrm}{\_rm}
\_sdef{_currvar:_tenbf}{\_bf}
\_sdef{_currvar:_tenit}{\_it}
\_sdef{_currvar:_tenbi}{\_bi}
\_sdef{_currvar:_tentt}{\_tt}
\_public \currvar ;

   \_doc -----------------------------
   The \`\_regtfm` `<font id> <optical size data>` 
   saves the <optical size data> concerned to `<font id>`.
   The `<optical size data>` is in the form as shown below in the code where
   `\_regtfm` is used.
   \nl
   The \`\_wichtfm` `<fontname>` expands to the `<fontname>` or to the corrected
   `<fontname>` read from the `<optical size data>`. It is used in the
   \^`\_rfontskipat` macro and it is used in \^`\fontlet` macro. 
   It means that each `<fontname>` generated by the `\fontname` primitive in the 
   `\fontlet` macro is processed by the `\_whichtfm`. The real `<fontname>` or
   corrected `<fontname>` (depending on the optical data does not exist or exist) 
   is the output of the expansion before `\font` primitive takes this output
   as its parameter.

   The implementation detail: The `\_<font id>:reg` is defined as the
   `<optical size data>` and all control sequences `\_<fontname>:reg`
   from this data line has the same meaning because of the 
   \`\_reversetfm` macro. The `\_whichtfm` expands this data line and apply
   \`\_dowhichtfm`. This macro select the right result from the data line
   by testing with the current `\_optsize` value.
   \_cod -----------------------------

\_def\_regtfm #1 0 #2 *{\_ea\_def \_csname _#1:reg\_endcsname{#2 16380 \_relax}%
  \_def\_tmpa{#1}\_reversetfm #2 * %
}
\_def\_reversetfm #1 #2 {% we need this data for \_setmathfamily 
   \_ea\_let\_csname _#1:reg\_ea\_endcsname
   \_csname _\_tmpa:reg\_endcsname
   \_if*#2\_else \_ea\_reversetfm \_fi
}
\_def\_whichtfm #1{%
   \_ifcsname _#1:reg\_endcsname
      \_ea\_ea\_ea \_dowhichtfm
      \_csname _#1:reg\_ea\_endcsname
   \_else
      #1%
   \_fi
}
\_def\_dowhichtfm #1 #2 {%
   \_ifdim\_optsize<#2pt #1\_ea\_ignoretfm\_else \_ea\_dowhichtfm
\_fi
}
\_def\_ignoretfm #1\_relax{}

   \_doc -----------------------------
   Optical sizes data for preloaded 8bit Latin Modern fonts:
   \_cod -----------------------------

\_regtfm lmr  0 ec-lmr5 5.5 ec-lmr6 6.5 ec-lmr7 7.5 ec-lmr8 8.5 ec-lmr9 9.5
                ec-lmr10 11.1 ec-lmr12 15 ec-lmr17 *
\_regtfm lmbx 0 ec-lmbx5 5.5 ec-lmbx6 6.5 ec-lmbx7 7.5 ec-lmbx8 8.5 ec-lmbx9 9.5 
                ec-lmbx10 11.1 ec-lmbx12 *
\_regtfm lmri 0 ec-lmri7 7.5 ec-lmri8 8.5 ec-lmri9 9.5 ec-lmri10 11.1 ec-lmri12 *
\_regtfm lmtt 0 ec-lmtt8 8.5 ec-lmtt9 9.5 ec-lmtt10 11.1 ec-lmtt12 *

\_setfontsize {at10pt} % default font size

\_endcode %---------------------------------------------------


\sec[setfontsize] Scaling fonts in text mode (low-level macros)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\secc The `\setfontsize` macro

The \^`\setfontsize` `{<size spec>}` 
saves the information about `<size spec>`. This information is taken into
account when a variant selector (for example `\rm`, `\bf`, `\it`, `\bi`)
or `\resizethefont` is used. The `<size spec>` can be:
\begitems
* `at<dimen>`, for example `\setfontsize{at12pt}`. It gives the desired font size directly.
* `scaled<scale factor>`, for example `\setfontsize{scaled1200}`. The font is
  scaled in respect to its native size (which is typically 10\,pt). It
  behaves like `\font\... scaled<number>`.
* `mag<decimal number>`, for example `\setfontsize{mag1.2}`. The font is
  scaled in respect to the current size of the fonts given by the previous
  \^`\setfontsize` command. 
\enditems
The initialization value in \OpTeX/ is given by `\setfontsize{at10pt}`.

The \^`\resizethefont` resizes the currently selected font to the size given by previous
\^`\setfontsize`. For example

\begtt
                     Here is 10 pt text, 
\setfontsize{at12pt} 10 pt text here unchanged...
\resizethefont       and 12 pt text is here.
\endtt
%
The \^`\setfontsize` command acts like {\em font modifier}. It means that it
saves information about fonts but does not change the font actually until
variant selector or \^`\resizethefont` is used.

The following example demonstrates the `mag` format of \^`\setfontsize`
parameter. It is only a curious example probably not used in practical
typography.

\begtt
\def\smaller{\setfontsize{mag.9}\resizethefont}
Text \smaller text \smaller text \smaller text.
\endtt

\secc[fontprimitive] The `\font` primitive

If you load a font directly by `\font` primitive and you want to
create a size-dependent selector for such font then you can use
\~`\resizethefont`:

\begtt
\font\tencomfortaa=Comfortaa-Regular-T1 at10pt
\def\comfortaa{\tencomfortaa\resizethefont}

\comfortaa Here is 10 pt text
\setfontsize{at12pt}
\comfortaa Here is 12 pt text
\endtt
%
The example above uses the 8\,bit `tfm` font. You can use Unicode font too, of
course. The \^`\fontfam` macro initializes the extended `\font` primitive
features for \LuaTeX/ (see section \ref[exfont]).
If you didn't use this command, you must to initialize
these features by the \^`\initunifonts` command explicitly, for example:

\begtt
\initunifonts
\font\tencyklop=[cyklop-regular] at10pt % the font cyklop-regular.otf is loaded
\def\cyklop{\tencyklop\resizethefont}

\cyklop Here is 10 pt text
\setfontsize{at12pt}
\cyklop Here is 12 pt text
\endtt

\secc[fontdef] The \code{\\fontdef} declarator

You can declare `\<newfont>` by the \~`\fontdef` command.

\begtt \catcode`\<=13
  \fontdef \<newfont> {<font modifiers> \<variant-selector>}
  example:
  \fontdef \bigfont {\setfontsize{at15pt}\bf}
\endtt
%
This command runs `<font modifiers> \<variant-selector>` in an internal group and sets the
resulting selected font as `\<newfont>`.

The resulting `\<newfont>` declared by \~`\fontdef` is \"fixed font switch"
independent of \^`\setfontsize` and other font modifiers. More exactly, it is 
fixed font switch when it is used but it can depend on the current font
modifiers and font family and given font modifiers when it is declared.

The parameter of the \~`\fontdef` macro must be exactly finished by the
variant selector. More information about font modifiers
and variant selectors are in the section~\ref[fontsystem].

\secc[fontlet] The \code{\\fontlet} declarator

We have another command for scaling: \^`\fontlet` which is able to resize
arbitrary font given by its font switch.
This font switch was declared it by the
`\font` primitive or the \~`\fontdef` macro.

\begtt \catcode`\<=13
  \fontlet \<newfont> = \<fontswitch> <sizespec>
  example:
  \fontlet \bigfont = \_tenbf at15pt
\endtt

The resulted `\bigfont` is the same as in previous example where \~`\fontdef`
was used. The advantage of \~`\fontdef` macro will be more clear when you load
font families by `\fontfam` and you are using more font modifiers declared
in such families.

Summary: you can declare font switches:
\begitems
* by the `\font` primitive if you know the font file,
* by the \^`\fontlet` command if you know the font switch and the size, or
* by the \~`\fontdef` command if you know the variant and modifiers.
\enditems

\secc Optical sizes

There are font families with more font files where almost the same font is
implemented in various design sizes: `cmr5`, `cmr6`, `cmr7`, `cmr8`, `cmr9`,
`cmr10`, `cmr12`, `cmr17` for example. This feature is called \"optical
sizes". \OpTeX/ chooses a font with an optical size closest to desired size
specified by the \^`\setfontsize`, when `at<dimen>` or `mag<coefficient>` is used.
When `scaled<scale factor>` is used then optical size is chosen using the value
of the `\defaultoptsize` register and such font is scaled by the specified
`<scale factor>`. There is `\defaultoptsize=10pt` by default.

Font collections with optical sizes must be registered by the
\^`\_regtfm` for `tfm` files or \^`\_regoptsizes` for Unicode fonts.
\OpTeX/ registers 8bit Latin Moder fonts in the format (`fonts-resize.opm` file) 
and OTF Latin Modern fonts in the `f-lmfonts.opm` file.

\secc Implementation notes

\_endinput

2020-04-17 \resizethefont introduced
2020-03-17 released