Coverage Report

Created: 2025-07-07 10:01

/work/workdir/UnpackedTarball/cairo/src/cairo-font-options.c
Line
Count
Source (jump to first uncovered line)
1
/* cairo - a vector graphics library with display and print output
2
 *
3
 * Copyright © 2005 Red Hat Inc.
4
 *
5
 * This library is free software; you can redistribute it and/or
6
 * modify it either under the terms of the GNU Lesser General Public
7
 * License version 2.1 as published by the Free Software Foundation
8
 * (the "LGPL") or, at your option, under the terms of the Mozilla
9
 * Public License Version 1.1 (the "MPL"). If you do not alter this
10
 * notice, a recipient may use your version of this file under either
11
 * the MPL or the LGPL.
12
 *
13
 * You should have received a copy of the LGPL along with this library
14
 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
15
 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
16
 * You should have received a copy of the MPL along with this library
17
 * in the file COPYING-MPL-1.1
18
 *
19
 * The contents of this file are subject to the Mozilla Public License
20
 * Version 1.1 (the "License"); you may not use this file except in
21
 * compliance with the License. You may obtain a copy of the License at
22
 * http://www.mozilla.org/MPL/
23
 *
24
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
25
 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
26
 * the specific language governing rights and limitations.
27
 *
28
 * The Original Code is the cairo graphics library.
29
 *
30
 * The Initial Developer of the Original Code is University of Southern
31
 * California.
32
 *
33
 * Contributor(s):
34
 *      Owen Taylor <otaylor@redhat.com>
35
 */
36
37
#include "cairoint.h"
38
#include "cairo-error-private.h"
39
40
/**
41
 * SECTION:cairo-font-options
42
 * @Title: cairo_font_options_t
43
 * @Short_Description: How a font should be rendered
44
 * @See_Also: #cairo_scaled_font_t
45
 *
46
 * The font options specify how fonts should be rendered.  Most of the 
47
 * time the font options implied by a surface are just right and do not 
48
 * need any changes, but for pixel-based targets tweaking font options 
49
 * may result in superior output on a particular display.
50
 **/
51
52
static const cairo_font_options_t _cairo_font_options_nil = {
53
    CAIRO_ANTIALIAS_DEFAULT,
54
    CAIRO_SUBPIXEL_ORDER_DEFAULT,
55
    CAIRO_LCD_FILTER_DEFAULT,
56
    CAIRO_HINT_STYLE_DEFAULT,
57
    CAIRO_HINT_METRICS_DEFAULT,
58
    CAIRO_ROUND_GLYPH_POS_DEFAULT,
59
    NULL
60
};
61
62
/**
63
 * _cairo_font_options_init_default:
64
 * @options: a #cairo_font_options_t
65
 *
66
 * Initializes all fields of the font options object to default values.
67
 **/
68
void
69
_cairo_font_options_init_default (cairo_font_options_t *options)
70
8.14M
{
71
8.14M
    options->antialias = CAIRO_ANTIALIAS_DEFAULT;
72
8.14M
    options->subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
73
8.14M
    options->lcd_filter = CAIRO_LCD_FILTER_DEFAULT;
74
8.14M
    options->hint_style = CAIRO_HINT_STYLE_DEFAULT;
75
8.14M
    options->hint_metrics = CAIRO_HINT_METRICS_DEFAULT;
76
8.14M
    options->round_glyph_positions = CAIRO_ROUND_GLYPH_POS_DEFAULT;
77
8.14M
    options->variations = NULL;
78
8.14M
}
79
80
void
81
_cairo_font_options_init_copy (cairo_font_options_t   *options,
82
             const cairo_font_options_t *other)
83
3.79M
{
84
3.79M
    options->antialias = other->antialias;
85
3.79M
    options->subpixel_order = other->subpixel_order;
86
3.79M
    options->lcd_filter = other->lcd_filter;
87
3.79M
    options->hint_style = other->hint_style;
88
3.79M
    options->hint_metrics = other->hint_metrics;
89
3.79M
    options->round_glyph_positions = other->round_glyph_positions;
90
3.79M
    options->variations = other->variations ? strdup (other->variations) : NULL;
91
3.79M
}
92
93
/**
94
 * cairo_font_options_create:
95
 *
96
 * Allocates a new font options object with all options initialized
97
 *  to default values.
98
 *
99
 * Return value: a newly allocated #cairo_font_options_t. Free with
100
 *   cairo_font_options_destroy(). This function always returns a
101
 *   valid pointer; if memory cannot be allocated, then a special
102
 *   error object is returned where all operations on the object do nothing.
103
 *   You can check for this with cairo_font_options_status().
104
 *
105
 * Since: 1.0
106
 **/
107
cairo_font_options_t *
108
cairo_font_options_create (void)
109
4
{
110
4
    cairo_font_options_t *options;
111
112
4
    options = _cairo_malloc (sizeof (cairo_font_options_t));
113
4
    if (!options) {
114
0
  _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
115
0
  return (cairo_font_options_t *) &_cairo_font_options_nil;
116
0
    }
117
118
4
    _cairo_font_options_init_default (options);
119
120
4
    return options;
121
4
}
122
123
/**
124
 * cairo_font_options_copy:
125
 * @original: a #cairo_font_options_t
126
 *
127
 * Allocates a new font options object copying the option values from
128
 *  @original.
129
 *
130
 * Return value: a newly allocated #cairo_font_options_t. Free with
131
 *   cairo_font_options_destroy(). This function always returns a
132
 *   valid pointer; if memory cannot be allocated, then a special
133
 *   error object is returned where all operations on the object do nothing.
134
 *   You can check for this with cairo_font_options_status().
135
 *
136
 * Since: 1.0
137
 **/
138
cairo_font_options_t *
139
cairo_font_options_copy (const cairo_font_options_t *original)
140
9.37k
{
141
9.37k
    cairo_font_options_t *options;
142
143
9.37k
    if (cairo_font_options_status ((cairo_font_options_t *) original))
144
0
  return (cairo_font_options_t *) &_cairo_font_options_nil;
145
146
9.37k
    options = _cairo_malloc (sizeof (cairo_font_options_t));
147
9.37k
    if (!options) {
148
0
  _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
149
0
  return (cairo_font_options_t *) &_cairo_font_options_nil;
150
0
    }
151
152
9.37k
    _cairo_font_options_init_copy (options, original);
153
154
9.37k
    return options;
155
9.37k
}
156
157
void
158
_cairo_font_options_fini (cairo_font_options_t *options)
159
10.1k
{
160
10.1k
    free (options->variations);
161
10.1k
}
162
163
/**
164
 * cairo_font_options_destroy:
165
 * @options: a #cairo_font_options_t
166
 *
167
 * Destroys a #cairo_font_options_t object created with
168
 * cairo_font_options_create() or cairo_font_options_copy().
169
 *
170
 * Since: 1.0
171
 **/
172
void
173
cairo_font_options_destroy (cairo_font_options_t *options)
174
9.37k
{
175
9.37k
    if (cairo_font_options_status (options))
176
0
  return;
177
178
9.37k
    _cairo_font_options_fini (options);
179
9.37k
    free (options);
180
9.37k
}
181
182
/**
183
 * cairo_font_options_status:
184
 * @options: a #cairo_font_options_t
185
 *
186
 * Checks whether an error has previously occurred for this
187
 * font options object
188
 *
189
 * Return value: %CAIRO_STATUS_SUCCESS, %CAIRO_STATUS_NO_MEMORY, or
190
 *  %CAIRO_STATUS_NULL_POINTER.
191
 *
192
 * Since: 1.0
193
 **/
194
cairo_status_t
195
cairo_font_options_status (cairo_font_options_t *options)
196
17.3M
{
197
17.3M
    if (options == NULL)
198
0
  return CAIRO_STATUS_NULL_POINTER;
199
17.3M
    else if (options == (cairo_font_options_t *) &_cairo_font_options_nil)
200
0
  return CAIRO_STATUS_NO_MEMORY;
201
17.3M
    else
202
17.3M
  return CAIRO_STATUS_SUCCESS;
203
17.3M
}
204
slim_hidden_def (cairo_font_options_status);
205
206
/**
207
 * cairo_font_options_merge:
208
 * @options: a #cairo_font_options_t
209
 * @other: another #cairo_font_options_t
210
 *
211
 * Merges non-default options from @other into @options, replacing
212
 * existing values. This operation can be thought of as somewhat
213
 * similar to compositing @other onto @options with the operation
214
 * of %CAIRO_OPERATOR_OVER.
215
 *
216
 * Since: 1.0
217
 **/
218
void
219
cairo_font_options_merge (cairo_font_options_t       *options,
220
        const cairo_font_options_t *other)
221
2.56M
{
222
2.56M
    if (cairo_font_options_status (options))
223
0
  return;
224
225
2.56M
    if (cairo_font_options_status ((cairo_font_options_t *) other))
226
0
  return;
227
228
2.56M
    if (other->antialias != CAIRO_ANTIALIAS_DEFAULT)
229
2.55M
  options->antialias = other->antialias;
230
2.56M
    if (other->subpixel_order != CAIRO_SUBPIXEL_ORDER_DEFAULT)
231
0
  options->subpixel_order = other->subpixel_order;
232
2.56M
    if (other->lcd_filter != CAIRO_LCD_FILTER_DEFAULT)
233
0
  options->lcd_filter = other->lcd_filter;
234
2.56M
    if (other->hint_style != CAIRO_HINT_STYLE_DEFAULT)
235
532k
  options->hint_style = other->hint_style;
236
2.56M
    if (other->hint_metrics != CAIRO_HINT_METRICS_DEFAULT)
237
0
  options->hint_metrics = other->hint_metrics;
238
2.56M
    if (other->round_glyph_positions != CAIRO_ROUND_GLYPH_POS_DEFAULT)
239
542k
  options->round_glyph_positions = other->round_glyph_positions;
240
241
2.56M
    if (other->variations) {
242
0
      if (options->variations) {
243
0
        char *p;
244
245
        /* 'merge' variations by concatenating - later entries win */
246
0
        p = malloc (strlen (other->variations) + strlen (options->variations) + 2);
247
0
        p[0] = 0;
248
0
        strcat (p, options->variations);
249
0
        strcat (p, ",");
250
0
        strcat (p, other->variations);
251
0
        free (options->variations);
252
0
        options->variations = p;
253
0
      }
254
0
      else {
255
0
        options->variations = strdup (other->variations);
256
0
      }
257
0
    }
258
2.56M
}
259
slim_hidden_def (cairo_font_options_merge);
260
261
/**
262
 * cairo_font_options_equal:
263
 * @options: a #cairo_font_options_t
264
 * @other: another #cairo_font_options_t
265
 *
266
 * Compares two font options objects for equality.
267
 *
268
 * Return value: %TRUE if all fields of the two font options objects match.
269
 *  Note that this function will return %FALSE if either object is in
270
 *  error.
271
 *
272
 * Since: 1.0
273
 **/
274
cairo_bool_t
275
cairo_font_options_equal (const cairo_font_options_t *options,
276
        const cairo_font_options_t *other)
277
2.55M
{
278
2.55M
    if (cairo_font_options_status ((cairo_font_options_t *) options))
279
0
  return FALSE;
280
2.55M
    if (cairo_font_options_status ((cairo_font_options_t *) other))
281
0
  return FALSE;
282
283
2.55M
    if (options == other)
284
0
  return TRUE;
285
286
2.55M
    return (options->antialias == other->antialias &&
287
2.55M
      options->subpixel_order == other->subpixel_order &&
288
2.55M
      options->lcd_filter == other->lcd_filter &&
289
2.55M
      options->hint_style == other->hint_style &&
290
2.55M
      options->hint_metrics == other->hint_metrics &&
291
2.55M
      options->round_glyph_positions == other->round_glyph_positions &&
292
2.55M
            ((options->variations == NULL && other->variations == NULL) ||
293
2.55M
             (options->variations != NULL && other->variations != NULL &&
294
0
              strcmp (options->variations, other->variations) == 0)));
295
2.55M
}
296
slim_hidden_def (cairo_font_options_equal);
297
298
/**
299
 * cairo_font_options_hash:
300
 * @options: a #cairo_font_options_t
301
 *
302
 * Compute a hash for the font options object; this value will
303
 * be useful when storing an object containing a #cairo_font_options_t
304
 * in a hash table.
305
 *
306
 * Return value: the hash value for the font options object.
307
 *   The return value can be cast to a 32-bit type if a
308
 *   32-bit hash value is needed.
309
 *
310
 * Since: 1.0
311
 **/
312
unsigned long
313
cairo_font_options_hash (const cairo_font_options_t *options)
314
1.19M
{
315
1.19M
    unsigned long hash = 0;
316
317
1.19M
    if (cairo_font_options_status ((cairo_font_options_t *) options))
318
0
  options = &_cairo_font_options_nil; /* force default values */
319
320
1.19M
    if (options->variations)
321
0
      hash = _cairo_string_hash (options->variations, strlen (options->variations));
322
323
1.19M
    return ((options->antialias) |
324
1.19M
      (options->subpixel_order << 4) |
325
1.19M
      (options->lcd_filter << 8) |
326
1.19M
      (options->hint_style << 12) |
327
1.19M
      (options->hint_metrics << 16)) ^ hash;
328
1.19M
}
329
slim_hidden_def (cairo_font_options_hash);
330
331
/**
332
 * cairo_font_options_set_antialias:
333
 * @options: a #cairo_font_options_t
334
 * @antialias: the new antialiasing mode
335
 *
336
 * Sets the antialiasing mode for the font options object. This
337
 * specifies the type of antialiasing to do when rendering text.
338
 *
339
 * Since: 1.0
340
 **/
341
void
342
cairo_font_options_set_antialias (cairo_font_options_t *options,
343
          cairo_antialias_t     antialias)
344
6
{
345
6
    if (cairo_font_options_status (options))
346
0
  return;
347
348
6
    options->antialias = antialias;
349
6
}
350
slim_hidden_def (cairo_font_options_set_antialias);
351
352
/**
353
 * cairo_font_options_get_antialias:
354
 * @options: a #cairo_font_options_t
355
 *
356
 * Gets the antialiasing mode for the font options object.
357
 *
358
 * Return value: the antialiasing mode
359
 *
360
 * Since: 1.0
361
 **/
362
cairo_antialias_t
363
cairo_font_options_get_antialias (const cairo_font_options_t *options)
364
0
{
365
0
    if (cairo_font_options_status ((cairo_font_options_t *) options))
366
0
  return CAIRO_ANTIALIAS_DEFAULT;
367
368
0
    return options->antialias;
369
0
}
370
371
/**
372
 * cairo_font_options_set_subpixel_order:
373
 * @options: a #cairo_font_options_t
374
 * @subpixel_order: the new subpixel order
375
 *
376
 * Sets the subpixel order for the font options object. The subpixel
377
 * order specifies the order of color elements within each pixel on
378
 * the display device when rendering with an antialiasing mode of
379
 * %CAIRO_ANTIALIAS_SUBPIXEL. See the documentation for
380
 * #cairo_subpixel_order_t for full details.
381
 *
382
 * Since: 1.0
383
 **/
384
void
385
cairo_font_options_set_subpixel_order (cairo_font_options_t   *options,
386
               cairo_subpixel_order_t  subpixel_order)
387
2
{
388
2
    if (cairo_font_options_status (options))
389
0
  return;
390
391
2
    options->subpixel_order = subpixel_order;
392
2
}
393
slim_hidden_def (cairo_font_options_set_subpixel_order);
394
395
/**
396
 * cairo_font_options_get_subpixel_order:
397
 * @options: a #cairo_font_options_t
398
 *
399
 * Gets the subpixel order for the font options object.
400
 * See the documentation for #cairo_subpixel_order_t for full details.
401
 *
402
 * Return value: the subpixel order for the font options object
403
 *
404
 * Since: 1.0
405
 **/
406
cairo_subpixel_order_t
407
cairo_font_options_get_subpixel_order (const cairo_font_options_t *options)
408
0
{
409
0
    if (cairo_font_options_status ((cairo_font_options_t *) options))
410
0
  return CAIRO_SUBPIXEL_ORDER_DEFAULT;
411
412
0
    return options->subpixel_order;
413
0
}
414
415
/**
416
 * _cairo_font_options_set_lcd_filter:
417
 * @options: a #cairo_font_options_t
418
 * @lcd_filter: the new LCD filter
419
 *
420
 * Sets the LCD filter for the font options object. The LCD filter
421
 * specifies how pixels are filtered when rendered with an antialiasing
422
 * mode of %CAIRO_ANTIALIAS_SUBPIXEL. See the documentation for
423
 * #cairo_lcd_filter_t for full details.
424
 **/
425
void
426
_cairo_font_options_set_lcd_filter (cairo_font_options_t *options,
427
            cairo_lcd_filter_t    lcd_filter)
428
0
{
429
0
    if (cairo_font_options_status (options))
430
0
  return;
431
432
0
    options->lcd_filter = lcd_filter;
433
0
}
434
435
/**
436
 * _cairo_font_options_get_lcd_filter:
437
 * @options: a #cairo_font_options_t
438
 *
439
 * Gets the LCD filter for the font options object.
440
 * See the documentation for #cairo_lcd_filter_t for full details.
441
 *
442
 * Return value: the LCD filter for the font options object
443
 **/
444
cairo_lcd_filter_t
445
_cairo_font_options_get_lcd_filter (const cairo_font_options_t *options)
446
0
{
447
0
    if (cairo_font_options_status ((cairo_font_options_t *) options))
448
0
  return CAIRO_LCD_FILTER_DEFAULT;
449
450
0
    return options->lcd_filter;
451
0
}
452
453
/**
454
 * _cairo_font_options_set_round_glyph_positions:
455
 * @options: a #cairo_font_options_t
456
 * @round: the new rounding value
457
 *
458
 * Sets the rounding options for the font options object. If rounding is set, a
459
 * glyph's position will be rounded to integer values.
460
 **/
461
void
462
_cairo_font_options_set_round_glyph_positions (cairo_font_options_t *options,
463
                 cairo_round_glyph_positions_t  round)
464
845
{
465
845
    if (cairo_font_options_status (options))
466
0
  return;
467
468
845
    options->round_glyph_positions = round;
469
845
}
470
471
/**
472
 * _cairo_font_options_get_round_glyph_positions:
473
 * @options: a #cairo_font_options_t
474
 *
475
 * Gets the glyph position rounding option for the font options object.
476
 *
477
 * Return value: The round glyph posistions flag for the font options object.
478
 **/
479
cairo_round_glyph_positions_t
480
_cairo_font_options_get_round_glyph_positions (const cairo_font_options_t *options)
481
745k
{
482
745k
    if (cairo_font_options_status ((cairo_font_options_t *) options))
483
0
  return CAIRO_ROUND_GLYPH_POS_DEFAULT;
484
485
745k
    return options->round_glyph_positions;
486
745k
}
487
488
/**
489
 * cairo_font_options_set_hint_style:
490
 * @options: a #cairo_font_options_t
491
 * @hint_style: the new hint style
492
 *
493
 * Sets the hint style for font outlines for the font options object.
494
 * This controls whether to fit font outlines to the pixel grid,
495
 * and if so, whether to optimize for fidelity or contrast.
496
 * See the documentation for #cairo_hint_style_t for full details.
497
 *
498
 * Since: 1.0
499
 **/
500
void
501
cairo_font_options_set_hint_style (cairo_font_options_t *options,
502
           cairo_hint_style_t    hint_style)
503
9.37k
{
504
9.37k
    if (cairo_font_options_status (options))
505
0
  return;
506
507
9.37k
    options->hint_style = hint_style;
508
9.37k
}
509
slim_hidden_def (cairo_font_options_set_hint_style);
510
511
/**
512
 * cairo_font_options_get_hint_style:
513
 * @options: a #cairo_font_options_t
514
 *
515
 * Gets the hint style for font outlines for the font options object.
516
 * See the documentation for #cairo_hint_style_t for full details.
517
 *
518
 * Return value: the hint style for the font options object
519
 *
520
 * Since: 1.0
521
 **/
522
cairo_hint_style_t
523
cairo_font_options_get_hint_style (const cairo_font_options_t *options)
524
23.5k
{
525
23.5k
    if (cairo_font_options_status ((cairo_font_options_t *) options))
526
0
  return CAIRO_HINT_STYLE_DEFAULT;
527
528
23.5k
    return options->hint_style;
529
23.5k
}
530
531
/**
532
 * cairo_font_options_set_hint_metrics:
533
 * @options: a #cairo_font_options_t
534
 * @hint_metrics: the new metrics hinting mode
535
 *
536
 * Sets the metrics hinting mode for the font options object. This
537
 * controls whether metrics are quantized to integer values in
538
 * device units.
539
 * See the documentation for #cairo_hint_metrics_t for full details.
540
 *
541
 * Since: 1.0
542
 **/
543
void
544
cairo_font_options_set_hint_metrics (cairo_font_options_t *options,
545
             cairo_hint_metrics_t  hint_metrics)
546
847
{
547
847
    if (cairo_font_options_status (options))
548
0
  return;
549
550
847
    options->hint_metrics = hint_metrics;
551
847
}
552
slim_hidden_def (cairo_font_options_set_hint_metrics);
553
554
/**
555
 * cairo_font_options_get_hint_metrics:
556
 * @options: a #cairo_font_options_t
557
 *
558
 * Gets the metrics hinting mode for the font options object.
559
 * See the documentation for #cairo_hint_metrics_t for full details.
560
 *
561
 * Return value: the metrics hinting mode for the font options object
562
 *
563
 * Since: 1.0
564
 **/
565
cairo_hint_metrics_t
566
cairo_font_options_get_hint_metrics (const cairo_font_options_t *options)
567
0
{
568
0
    if (cairo_font_options_status ((cairo_font_options_t *) options))
569
0
  return CAIRO_HINT_METRICS_DEFAULT;
570
571
0
    return options->hint_metrics;
572
0
}
573
574
/**
575
 * cairo_font_options_set_variations:
576
 * @options: a #cairo_font_options_t
577
 * @variations: the new font variations, or %NULL
578
 *
579
 * Sets the OpenType font variations for the font options object.
580
 * Font variations are specified as a string with a format that
581
 * is similar to the CSS font-variation-settings. The string contains
582
 * a comma-separated list of axis assignments, which each assignment
583
 * consists of a 4-character axis name and a value, separated by
584
 * whitespace and optional equals sign.
585
 *
586
 * Examples:
587
 *
588
 * wght=200,wdth=140.5
589
 *
590
 * wght 200 , wdth 140.5
591
 *
592
 * Since: 1.16
593
 **/
594
void
595
cairo_font_options_set_variations (cairo_font_options_t *options,
596
                                   const char           *variations)
597
0
{
598
0
  char *tmp = variations ? strdup (variations) : NULL;
599
0
  free (options->variations);
600
0
  options->variations = tmp;
601
0
}
602
603
/**
604
 * cairo_font_options_get_variations:
605
 * @options: a #cairo_font_options_t
606
 *
607
 * Gets the OpenType font variations for the font options object.
608
 * See cairo_font_options_set_variations() for details about the
609
 * string format.
610
 *
611
 * Return value: the font variations for the font options object. The
612
 *   returned string belongs to the @options and must not be modified.
613
 *   It is valid until either the font options object is destroyed or
614
 *   the font variations in this object is modified with
615
 *   cairo_font_options_set_variations().
616
 *
617
 * Since: 1.16
618
 **/
619
const char *
620
cairo_font_options_get_variations (cairo_font_options_t *options)
621
0
{
622
0
  return options->variations;
623
0
}