Commit 89ca1fd6d75edf85a093535703707f484e2e8149

Werner Lemberg 2013-06-25T23:28:02

[cff] Add `darkening-parameters' property. * include/freetype/ftcffdrv.h: Document it. * src/cff/cffdrivr.c (cff_property_set, cff_property_get): Handle `darkening-parameters' property. * src/cff/cf2font.h (CF2_FontRec): Add `darkenParams' array. * src/cff/cf2font.c (cf2_computeDarkening): Add `darkenParams' argument and use it. Update all callers. * src/cff/cf2ft.c (cf2_decoder_parse_charstrings): Copy `darken_params' values. * src/cff/cffobjs.h (CFF_DriverRec): Add `darken_params' array. * src/cff/cffobjs.c (cff_driver_init): Set default values for `darken_params'.

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
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
diff --git a/ChangeLog b/ChangeLog
index 91f9efd..2fbf454 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,28 @@
 2013-06-25  Werner Lemberg  <wl@gnu.org>
 
+	[cff] Add `darkening-parameters' property.
+
+	* include/freetype/ftcffdrv.h: Document it.
+
+	* src/cff/cffdrivr.c (cff_property_set, cff_property_get): Handle
+	`darkening-parameters' property.
+
+	* src/cff/cf2font.h (CF2_FontRec): Add `darkenParams' array.
+
+	* src/cff/cf2font.c (cf2_computeDarkening): Add `darkenParams'
+	argument and use it.
+	Update all callers.
+
+	* src/cff/cf2ft.c (cf2_decoder_parse_charstrings): Copy
+	`darken_params' values.
+
+	* src/cff/cffobjs.h (CFF_DriverRec): Add `darken_params' array.
+
+	* src/cff/cffobjs.c (cff_driver_init): Set default values for
+	`darken_params'.
+
+2013-06-25  Werner Lemberg  <wl@gnu.org>
+
 	[docmaker] Code shuffling.
 
 	* src/tools/docmaker/tohtml.py (re_url): Move regexp...
diff --git a/include/freetype/ftcffdrv.h b/include/freetype/ftcffdrv.h
index ccbcbcc..6235d85 100644
--- a/include/freetype/ftcffdrv.h
+++ b/include/freetype/ftcffdrv.h
@@ -73,7 +73,6 @@ FT_BEGIN_HEADER
    *
    *   {
    *     FT_Library  library;
-   *     FT_Face     face;
    *     FT_UInt     hinting_engine = FT_CFF_HINTING_ADOBE;
    *
    *
@@ -124,7 +123,6 @@ FT_BEGIN_HEADER
    *
    *   {
    *     FT_Library  library;
-   *     FT_Face     face;
    *     FT_Bool     no_stem_darkening = TRUE;
    *
    *
@@ -140,6 +138,50 @@ FT_BEGIN_HEADER
    */
 
 
+  /**************************************************************************
+   *
+   * @property:
+   *   darkening-parameters
+   *
+   * @description:
+   *   By default, the Adobe CFF engine darkens stems as follows (if the
+   *   `no-stem-darkening' property isn't set):
+   *
+   *   {
+   *     stem width <= 0.5px:   darkening amount = 0.4px
+   *     stem width  = 1px:     darkening amount = 0.275px
+   *     stem width  = 1.667px: darkening amount = 0.275px
+   *     stem width >= 2.333px: darkening amount = 0px
+   *   }
+   *
+   *   and piecewise linear in-between.  Using the `darkening-parameters'
+   *   property, these four control points can be changed, as the following
+   *   example demonstrates.
+   *
+   *   {
+   *     FT_Library  library;
+   *     FT_Int      darken_params[8] = {  500, 300,   // x1, y1
+   *                                      1000, 200,   // x2, y2
+   *                                      1500, 100,   // x3, y3
+   *                                      2000,   0 }; // x4, y4
+   *
+   *
+   *     FT_Init_FreeType( &library );
+   *
+   *     FT_Property_Set( library, "cff",
+   *                               "darkening-parameters", darken_params );
+   *   }
+   *
+   *   The x~values give the stem width, and the y~values the darkening
+   *   amount.  All coordinate values must be positive and monotonically
+   *   increasing along the x~axis; the unit is 1000th of pixels.
+   *
+   * @note:
+   *   This property can be used with @FT_Property_Get also.
+   *
+   */
+
+
  /* */
 
 FT_END_HEADER
diff --git a/src/cff/cf2font.c b/src/cff/cf2font.c
index 996db74..fe454c3 100644
--- a/src/cff/cf2font.c
+++ b/src/cff/cf2font.c
@@ -51,15 +51,57 @@
                         CF2_Fixed   stemWidth,
                         CF2_Fixed*  darkenAmount,
                         CF2_Fixed   boldenAmount,
-                        FT_Bool     stemDarkened )
+                        FT_Bool     stemDarkened,
+                        FT_Int*     darkenParams )
   {
+    /*
+     * Total darkening amount is computed in 1000 unit character space
+     * using the modified 5 part curve as Adobe's Avalon rasterizer.
+     * The darkening amount is smaller for thicker stems.
+     * It becomes zero when the stem is thicker than 2.333 pixels.
+     *
+     * By default, we use
+     *
+     *   darkenAmount = 0.4 pixels   if scaledStem <= 0.5 pixels,
+     *   darkenAmount = 0.275 pixels if 1 <= scaledStem <= 1.667 pixels,
+     *   darkenAmount = 0 pixel      if scaledStem >= 2.333 pixels,
+     *
+     * and piecewise linear in-between:
+     *
+     *
+     *   darkening
+     *       ^
+     *       |
+     *       |      (x1,y1)
+     *       |--------+
+     *       |         \
+     *       |          \
+     *       |           \          (x3,y3)
+     *       |            +----------+
+     *       |        (x2,y2)         \
+     *       |                         \
+     *       |                          \
+     *       |                           +-----------------
+     *       |                         (x4,y4)
+     *       +--------------------------------------------->   stem
+     *                                                       thickness
+     *
+     *
+     * This corresponds to the following values for the
+     * `darkening-parameters' property:
+     *
+     *   (x1, y1) = (500, 400)
+     *   (x2, y2) = (1000, 275)
+     *   (x3, y3) = (1667, 275)
+     *   (x4, y4) = (2333, 0)
+     *
+     */
+
     /* Internal calculations are done in units per thousand for */
     /* convenience.                                             */
     CF2_Fixed  stemWidthPer1000, scaledStem;
 
 
-    *darkenAmount = 0;
-
     if ( boldenAmount == 0 && !stemDarkened )
       return;
 
@@ -69,6 +111,16 @@
 
     if ( stemDarkened )
     {
+      FT_Int  x1 = darkenParams[0];
+      FT_Int  y1 = darkenParams[1];
+      FT_Int  x2 = darkenParams[2];
+      FT_Int  y2 = darkenParams[3];
+      FT_Int  x3 = darkenParams[4];
+      FT_Int  y3 = darkenParams[5];
+      FT_Int  x4 = darkenParams[6];
+      FT_Int  y4 = darkenParams[7];
+
+
       /* convert from true character space to 1000 unit character space; */
       /* add synthetic emboldening effect                                */
 
@@ -81,7 +133,7 @@
            stemWidthPer1000 <= ( stemWidth + boldenAmount ) )
       {
         stemWidthPer1000 = 0;                      /* to pacify compiler */
-        scaledStem       = cf2_intToFixed( 2333 );
+        scaledStem       = cf2_intToFixed( x4 );
       }
       else
       {
@@ -89,39 +141,70 @@
 
         if ( ppem > CF2_FIXED_ONE           &&
              scaledStem <= stemWidthPer1000 )
-          scaledStem = cf2_intToFixed( 2333 );
+          scaledStem = cf2_intToFixed( x4 );
       }
 
-      /*
-       * Total darkening amount is computed in 1000 unit character space
-       * using the modified 5 part curve as Avalon rasterizer.
-       * The darkening amount is smaller for thicker stems.
-       * It becomes zero when the stem is thicker than 2.333 pixels.
-       *
-       * By default, we use
-       *
-       *   darkenAmount = 0.4 pixels   if scaledStem <= 0.5 pixels,
-       *   darkenAmount = 0.275 pixels if 1 <= scaledStem <= 1.667 pixels,
-       *   darkenAmount = 0 pixel      if scaledStem >= 2.333 pixels,
-       *
-       * and piecewise linear in-between.
-       *
-       */
-      if ( scaledStem < cf2_intToFixed( 500 ) )
-        *darkenAmount = FT_DivFix( cf2_intToFixed( 400 ), ppem );
-
-      else if ( scaledStem < cf2_intToFixed( 1000 ) )
-        *darkenAmount = FT_DivFix( cf2_intToFixed( 525 ), ppem ) -
-                          FT_MulFix( stemWidthPer1000,
-                                     cf2_floatToFixed( .25 ) );
-
-      else if ( scaledStem < cf2_intToFixed( 1667 ) )
-        *darkenAmount = FT_DivFix( cf2_intToFixed( 275 ), ppem );
-
-      else if ( scaledStem < cf2_intToFixed( 2333 ) )
-        *darkenAmount = FT_DivFix( cf2_intToFixed( 963 ), ppem ) -
-                          FT_MulFix( stemWidthPer1000,
-                                     cf2_floatToFixed( .413 ) );
+      /* now apply the darkening parameters */
+
+      if ( scaledStem < cf2_intToFixed( x1 ) )
+        *darkenAmount = FT_DivFix( cf2_intToFixed( y1 ), ppem );
+
+      else if ( scaledStem < cf2_intToFixed( x2 ) )
+      {
+        FT_Int  xdelta = x2 - x1;
+        FT_Int  ydelta = y2 - y1;
+        FT_Int  x      = stemWidthPer1000 -
+                           FT_DivFix( cf2_intToFixed( x1 ), ppem );
+
+
+        if ( !ydelta )
+          goto Try_x3;
+
+        *darkenAmount = FT_MulFix( x, FT_DivFix( ydelta, xdelta ) ) +
+                          FT_DivFix( cf2_intToFixed( y1 ), ppem );
+      }
+
+      else if ( scaledStem < cf2_intToFixed( x3 ) )
+      {
+      Try_x3:
+        {
+          FT_Int  xdelta = x3 - x2;
+          FT_Int  ydelta = y3 - y2;
+          FT_Int  x      = stemWidthPer1000 -
+                             FT_DivFix( cf2_intToFixed( x2 ), ppem );
+
+
+          if ( !ydelta )
+            goto Try_x4;
+
+          *darkenAmount = FT_MulFix( x, FT_DivFix( ydelta, xdelta ) ) +
+                            FT_DivFix( cf2_intToFixed( y2 ), ppem );
+        }
+      }
+
+      else if ( scaledStem < cf2_intToFixed( x4 ) )
+      {
+      Try_x4:
+        {
+          FT_Int  xdelta = x4 - x3;
+          FT_Int  ydelta = y4 - y3;
+          FT_Int  x      = stemWidthPer1000 -
+                             FT_DivFix( cf2_intToFixed( x3 ), ppem );
+
+
+          if ( !ydelta )
+            goto Use_y4;
+
+          *darkenAmount = FT_MulFix( x, FT_DivFix( ydelta, xdelta ) ) +
+                            FT_DivFix( cf2_intToFixed( y3 ), ppem );
+        }
+      }
+
+      else
+      {
+      Use_y4:
+        *darkenAmount = FT_DivFix( cf2_intToFixed( y4 ), ppem );
+      }
 
       /* use half the amount on each side and convert back to true */
       /* character space                                           */
@@ -268,7 +351,8 @@
                               font->stdVW,
                               &font->darkenX,
                               boldenX,
-                              FALSE );
+                              FALSE,
+                              font->darkenParams );
       }
       else
         cf2_computeDarkening( emRatio,
@@ -276,7 +360,8 @@
                               font->stdVW,
                               &font->darkenX,
                               0,
-                              font->stemDarkened );
+                              font->stemDarkened,
+                              font->darkenParams );
 
 #if 0
       /* since hstem is measured in the y-direction, we use the `d' member */
@@ -303,7 +388,8 @@
                             font->stdHW,
                             &font->darkenY,
                             boldenY,
-                            font->stemDarkened );
+                            font->stemDarkened,
+                            font->darkenParams );
 
       if ( font->darkenX != 0 || font->darkenY != 0 )
         font->darkened = TRUE;
diff --git a/src/cff/cf2font.h b/src/cff/cf2font.h
index f9dd1bb..d8860ce 100644
--- a/src/cff/cf2font.h
+++ b/src/cff/cf2font.h
@@ -85,6 +85,8 @@ FT_BEGIN_HEADER
                              /* i.e. darkenX != 0 || darkenY != 0      */
     FT_Bool  stemDarkened;
 
+    FT_Int  darkenParams[8];              /* 1000 unit character space */
+
     /* variables that depend on both FontDict and Transform */
     CF2_Fixed  stdVW;     /* in character space; depends on dict entry */
     CF2_Fixed  stdHW;     /* in character space; depends on dict entry */
diff --git a/src/cff/cf2ft.c b/src/cff/cf2ft.c
index c09a024..4abbc9d 100644
--- a/src/cff/cf2ft.c
+++ b/src/cff/cf2ft.c
@@ -344,6 +344,15 @@
       if ( scaled && !driver->no_stem_darkening )
         font->renderingFlags |= CF2_FlagsDarkened;
 
+      font->darkenParams[0] = driver->darken_params[0];
+      font->darkenParams[1] = driver->darken_params[1];
+      font->darkenParams[2] = driver->darken_params[2];
+      font->darkenParams[3] = driver->darken_params[3];
+      font->darkenParams[4] = driver->darken_params[4];
+      font->darkenParams[5] = driver->darken_params[5];
+      font->darkenParams[6] = driver->darken_params[6];
+      font->darkenParams[7] = driver->darken_params[7];
+
       /* now get an outline for this glyph;      */
       /* also get units per em to validate scale */
       font->unitsPerEm = (CF2_Int)cf2_getUnitsPerEm( decoder );
diff --git a/src/cff/cffdrivr.c b/src/cff/cffdrivr.c
index c8ca96b..4652f59 100644
--- a/src/cff/cffdrivr.c
+++ b/src/cff/cffdrivr.c
@@ -586,7 +586,37 @@
     CFF_Driver  driver = (CFF_Driver)module;
 
 
-    if ( !ft_strcmp( property_name, "hinting-engine" ) )
+    if ( !ft_strcmp( property_name, "darkening-parameters" ) )
+    {
+      FT_Int*  darken_params = (FT_Int*)value;
+
+      FT_Int  x1 = darken_params[0];
+      FT_Int  y1 = darken_params[1];
+      FT_Int  x2 = darken_params[2];
+      FT_Int  y2 = darken_params[3];
+      FT_Int  x3 = darken_params[4];
+      FT_Int  y3 = darken_params[5];
+      FT_Int  x4 = darken_params[6];
+      FT_Int  y4 = darken_params[7];
+
+
+      if ( x1 < 0 || x2 < 0 || x3 < 0 || x4 < 0 ||
+           y1 < 0 || y2 < 0 || y3 < 0 || y4 < 0 ||
+           x1 > x2 || x2 > x3 || x3 > x4        )
+        return FT_THROW( Invalid_Argument );
+
+      driver->darken_params[0] = x1;
+      driver->darken_params[1] = y1;
+      driver->darken_params[2] = x2;
+      driver->darken_params[3] = y2;
+      driver->darken_params[4] = x3;
+      driver->darken_params[5] = y3;
+      driver->darken_params[6] = x4;
+      driver->darken_params[7] = y4;
+
+      return error;
+    }
+    else if ( !ft_strcmp( property_name, "hinting-engine" ) )
     {
       FT_UInt*  hinting_engine = (FT_UInt*)value;
 
@@ -624,13 +654,28 @@
     FT_Error    error  = FT_Err_Ok;
     CFF_Driver  driver = (CFF_Driver)module;
 
-    FT_UInt  hinting_engine    = driver->hinting_engine;
-    FT_Bool  no_stem_darkening = driver->no_stem_darkening;
 
+    if ( !ft_strcmp( property_name, "darkening-parameters" ) )
+    {
+      FT_Int*  darken_params = driver->darken_params;
+      FT_Int*  val           = (FT_Int*)value;
 
-    if ( !ft_strcmp( property_name, "hinting-engine" ) )
+
+      val[0] = darken_params[0];
+      val[1] = darken_params[1];
+      val[2] = darken_params[2];
+      val[3] = darken_params[3];
+      val[4] = darken_params[4];
+      val[5] = darken_params[5];
+      val[6] = darken_params[6];
+      val[7] = darken_params[7];
+
+      return error;
+    }
+    else if ( !ft_strcmp( property_name, "hinting-engine" ) )
     {
-      FT_UInt*  val = (FT_UInt*)value;
+      FT_UInt   hinting_engine    = driver->hinting_engine;
+      FT_UInt*  val               = (FT_UInt*)value;
 
 
       *val = hinting_engine;
@@ -639,7 +684,8 @@
     }
     else if ( !ft_strcmp( property_name, "no-stem-darkening" ) )
     {
-      FT_Bool*  val = (FT_Bool*)value;
+      FT_Bool   no_stem_darkening = driver->no_stem_darkening;
+      FT_Bool*  val               = (FT_Bool*)value;
 
 
       *val = no_stem_darkening;
diff --git a/src/cff/cffobjs.c b/src/cff/cffobjs.c
index dd750d1..29c3691 100644
--- a/src/cff/cffobjs.c
+++ b/src/cff/cffobjs.c
@@ -1055,7 +1055,7 @@
     CFF_Driver  driver = (CFF_Driver)module;
 
 
-    /* set default property values */
+    /* set default property values, cf `ftcffdrv.h' */
 #ifdef CFF_CONFIG_OPTION_OLD_ENGINE
     driver->hinting_engine    = FT_CFF_HINTING_FREETYPE;
 #else
@@ -1063,6 +1063,15 @@
 #endif
     driver->no_stem_darkening = FALSE;
 
+    driver->darken_params[0] =  500;
+    driver->darken_params[1] =  400;
+    driver->darken_params[2] = 1000;
+    driver->darken_params[3] =  275;
+    driver->darken_params[4] = 1667;
+    driver->darken_params[5] =  275;
+    driver->darken_params[6] = 2333;
+    driver->darken_params[7] =    0;
+
     return FT_Err_Ok;
   }
 
diff --git a/src/cff/cffobjs.h b/src/cff/cffobjs.h
index b375c20..dfbf9a9 100644
--- a/src/cff/cffobjs.h
+++ b/src/cff/cffobjs.h
@@ -121,6 +121,8 @@ FT_BEGIN_HEADER
     FT_UInt  hinting_engine;
     FT_Bool  no_stem_darkening;
 
+    FT_Int  darken_params[8];
+
   } CFF_DriverRec;
 
 
diff --git a/src/tools/docmaker/sources.py b/src/tools/docmaker/sources.py
index df96208..dab8349 100644
--- a/src/tools/docmaker/sources.py
+++ b/src/tools/docmaker/sources.py
@@ -132,7 +132,7 @@ re_markup_tags = [re_markup_tag1, re_markup_tag2]
 #
 # used to detect a cross-reference, after markup tags have been stripped
 #
-re_crossref = re.compile( r'@((?:\w|-)*)(.*)' )
+re_crossref = re.compile( r'@((?:\w|-)*)(.*)' )    #  @foo
 
 #
 # used to detect italic and bold styles in paragraph text