1/* Pango
2 * pango-context.c: Contexts for itemization and shaping
3 *
4 * Copyright (C) 2000, 2006 Red Hat Software
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 */
21
22#include "config.h"
23#include <string.h>
24#include <stdlib.h>
25
26#include "pango-context.h"
27#include "pango-context-private.h"
28#include "pango-impl-utils.h"
29
30#include "pango-font-private.h"
31#include "pango-item-private.h"
32#include "pango-fontset.h"
33#include "pango-fontmap-private.h"
34#include "pango-script-private.h"
35#include "pango-emoji-private.h"
36
37/**
38 * PangoContext:
39 *
40 * A `PangoContext` stores global information used to control the
41 * itemization process.
42 *
43 * The information stored by `PangoContext` includes the fontmap used
44 * to look up fonts, and default values such as the default language,
45 * default gravity, or default font.
46 *
47 * To obtain a `PangoContext`, use [method@Pango.FontMap.create_context].
48 */
49
50struct _PangoContextClass
51{
52 GObjectClass parent_class;
53
54};
55
56static void pango_context_finalize (GObject *object);
57static void context_changed (PangoContext *context);
58
59G_DEFINE_TYPE (PangoContext, pango_context, G_TYPE_OBJECT)
60
61static void
62pango_context_init (PangoContext *context)
63{
64 context->base_dir = PANGO_DIRECTION_WEAK_LTR;
65 context->resolved_gravity = context->base_gravity = PANGO_GRAVITY_SOUTH;
66 context->gravity_hint = PANGO_GRAVITY_HINT_NATURAL;
67
68 context->serial = 1;
69 context->set_language = NULL;
70 context->language = pango_language_get_default ();
71 context->font_map = NULL;
72 context->round_glyph_positions = TRUE;
73
74 context->font_desc = pango_font_description_new ();
75 pango_font_description_set_family_static (desc: context->font_desc, family: "serif");
76 pango_font_description_set_style (desc: context->font_desc, style: PANGO_STYLE_NORMAL);
77 pango_font_description_set_variant (desc: context->font_desc, variant: PANGO_VARIANT_NORMAL);
78 pango_font_description_set_weight (desc: context->font_desc, weight: PANGO_WEIGHT_NORMAL);
79 pango_font_description_set_stretch (desc: context->font_desc, stretch: PANGO_STRETCH_NORMAL);
80 pango_font_description_set_size (desc: context->font_desc, size: 12 * PANGO_SCALE);
81}
82
83static void
84pango_context_class_init (PangoContextClass *klass)
85{
86 GObjectClass *object_class = G_OBJECT_CLASS (klass);
87
88 object_class->finalize = pango_context_finalize;
89}
90
91static void
92pango_context_finalize (GObject *object)
93{
94 PangoContext *context;
95
96 context = PANGO_CONTEXT (object);
97
98 if (context->font_map)
99 g_object_unref (object: context->font_map);
100
101 pango_font_description_free (desc: context->font_desc);
102 if (context->matrix)
103 pango_matrix_free (matrix: context->matrix);
104
105 if (context->metrics)
106 pango_font_metrics_unref (metrics: context->metrics);
107
108 G_OBJECT_CLASS (pango_context_parent_class)->finalize (object);
109}
110
111/**
112 * pango_context_new:
113 *
114 * Creates a new `PangoContext` initialized to default values.
115 *
116 * This function is not particularly useful as it should always
117 * be followed by a [method@Pango.Context.set_font_map] call, and the
118 * function [method@Pango.FontMap.create_context] does these two steps
119 * together and hence users are recommended to use that.
120 *
121 * If you are using Pango as part of a higher-level system,
122 * that system may have it's own way of create a `PangoContext`.
123 * For instance, the GTK toolkit has, among others,
124 * `gtk_widget_get_pango_context()`. Use those instead.
125 *
126 * Return value: the newly allocated `PangoContext`, which should
127 * be freed with g_object_unref().
128 */
129PangoContext *
130pango_context_new (void)
131{
132 PangoContext *context;
133
134 context = g_object_new (PANGO_TYPE_CONTEXT, NULL);
135
136 return context;
137}
138
139static void
140update_resolved_gravity (PangoContext *context)
141{
142 if (context->base_gravity == PANGO_GRAVITY_AUTO)
143 context->resolved_gravity = pango_gravity_get_for_matrix (matrix: context->matrix);
144 else
145 context->resolved_gravity = context->base_gravity;
146}
147
148/**
149 * pango_context_set_matrix:
150 * @context: a `PangoContext`
151 * @matrix: (nullable): a `PangoMatrix`, or %NULL to unset any existing
152 * matrix. (No matrix set is the same as setting the identity matrix.)
153 *
154 * Sets the transformation matrix that will be applied when rendering
155 * with this context.
156 *
157 * Note that reported metrics are in the user space coordinates before
158 * the application of the matrix, not device-space coordinates after the
159 * application of the matrix. So, they don't scale with the matrix, though
160 * they may change slightly for different matrices, depending on how the
161 * text is fit to the pixel grid.
162 *
163 * Since: 1.6
164 */
165void
166pango_context_set_matrix (PangoContext *context,
167 const PangoMatrix *matrix)
168{
169 g_return_if_fail (PANGO_IS_CONTEXT (context));
170
171 if (context->matrix || matrix)
172 context_changed (context);
173
174 if (context->matrix)
175 pango_matrix_free (matrix: context->matrix);
176 if (matrix)
177 context->matrix = pango_matrix_copy (matrix);
178 else
179 context->matrix = NULL;
180
181 update_resolved_gravity (context);
182}
183
184/**
185 * pango_context_get_matrix:
186 * @context: a `PangoContext`
187 *
188 * Gets the transformation matrix that will be applied when
189 * rendering with this context.
190 *
191 * See [method@Pango.Context.set_matrix].
192 *
193 * Return value: (nullable): the matrix, or %NULL if no matrix has
194 * been set (which is the same as the identity matrix). The returned
195 * matrix is owned by Pango and must not be modified or freed.
196 *
197 * Since: 1.6
198 */
199const PangoMatrix *
200pango_context_get_matrix (PangoContext *context)
201{
202 g_return_val_if_fail (PANGO_IS_CONTEXT (context), NULL);
203
204 return context->matrix;
205}
206
207/**
208 * pango_context_set_font_map:
209 * @context: a `PangoContext`
210 * @font_map: the `PangoFontMap` to set.
211 *
212 * Sets the font map to be searched when fonts are looked-up
213 * in this context.
214 *
215 * This is only for internal use by Pango backends, a `PangoContext`
216 * obtained via one of the recommended methods should already have a
217 * suitable font map.
218 */
219void
220pango_context_set_font_map (PangoContext *context,
221 PangoFontMap *font_map)
222{
223 g_return_if_fail (PANGO_IS_CONTEXT (context));
224 g_return_if_fail (!font_map || PANGO_IS_FONT_MAP (font_map));
225
226 if (font_map == context->font_map)
227 return;
228
229 context_changed (context);
230
231 if (font_map)
232 g_object_ref (font_map);
233
234 if (context->font_map)
235 g_object_unref (object: context->font_map);
236
237 context->font_map = font_map;
238 context->fontmap_serial = pango_font_map_get_serial (fontmap: font_map);
239}
240
241/**
242 * pango_context_get_font_map:
243 * @context: a `PangoContext`
244 *
245 * Gets the `PangoFontMap` used to look up fonts for this context.
246 *
247 * Return value: (transfer none): the font map for the `PangoContext`.
248 * This value is owned by Pango and should not be unreferenced.
249 *
250 * Since: 1.6
251 */
252PangoFontMap *
253pango_context_get_font_map (PangoContext *context)
254{
255 g_return_val_if_fail (PANGO_IS_CONTEXT (context), NULL);
256
257 return context->font_map;
258}
259
260/**
261 * pango_context_list_families:
262 * @context: a `PangoContext`
263 * @families: (out) (array length=n_families) (transfer container): location
264 * to store a pointer to an array of `PangoFontFamily`. This array should
265 * be freed with g_free().
266 * @n_families: (out): location to store the number of elements in @descs
267 *
268 * List all families for a context.
269 */
270void
271pango_context_list_families (PangoContext *context,
272 PangoFontFamily ***families,
273 int *n_families)
274{
275 g_return_if_fail (context != NULL);
276 g_return_if_fail (families == NULL || n_families != NULL);
277
278 if (n_families == NULL)
279 return;
280
281 if (context->font_map == NULL)
282 {
283 *n_families = 0;
284 if (families)
285 *families = NULL;
286
287 return;
288 }
289 else
290 pango_font_map_list_families (fontmap: context->font_map, families, n_families);
291}
292
293/**
294 * pango_context_load_font:
295 * @context: a `PangoContext`
296 * @desc: a `PangoFontDescription` describing the font to load
297 *
298 * Loads the font in one of the fontmaps in the context
299 * that is the closest match for @desc.
300 *
301 * Returns: (transfer full) (nullable): the newly allocated `PangoFont`
302 * that was loaded, or %NULL if no font matched.
303 */
304PangoFont *
305pango_context_load_font (PangoContext *context,
306 const PangoFontDescription *desc)
307{
308 g_return_val_if_fail (context != NULL, NULL);
309 g_return_val_if_fail (context->font_map != NULL, NULL);
310
311 return pango_font_map_load_font (fontmap: context->font_map, context, desc);
312}
313
314/**
315 * pango_context_load_fontset:
316 * @context: a `PangoContext`
317 * @desc: a `PangoFontDescription` describing the fonts to load
318 * @language: a `PangoLanguage` the fonts will be used for
319 *
320 * Load a set of fonts in the context that can be used to render
321 * a font matching @desc.
322 *
323 * Returns: (transfer full) (nullable): the newly allocated
324 * `PangoFontset` loaded, or %NULL if no font matched.
325 */
326PangoFontset *
327pango_context_load_fontset (PangoContext *context,
328 const PangoFontDescription *desc,
329 PangoLanguage *language)
330{
331 g_return_val_if_fail (context != NULL, NULL);
332
333 return pango_font_map_load_fontset (fontmap: context->font_map, context, desc, language);
334}
335
336/**
337 * pango_context_set_font_description:
338 * @context: a `PangoContext`
339 * @desc: the new pango font description
340 *
341 * Set the default font description for the context
342 */
343void
344pango_context_set_font_description (PangoContext *context,
345 const PangoFontDescription *desc)
346{
347 g_return_if_fail (context != NULL);
348 g_return_if_fail (desc != NULL);
349
350 if (desc != context->font_desc &&
351 (!desc || !context->font_desc || !pango_font_description_equal(desc1: desc, desc2: context->font_desc)))
352 {
353 context_changed (context);
354
355 pango_font_description_free (desc: context->font_desc);
356 context->font_desc = pango_font_description_copy (desc);
357 }
358}
359
360/**
361 * pango_context_get_font_description:
362 * @context: a `PangoContext`
363 *
364 * Retrieve the default font description for the context.
365 *
366 * Return value: (transfer none): a pointer to the context's default font
367 * description. This value must not be modified or freed.
368 */
369PangoFontDescription *
370pango_context_get_font_description (PangoContext *context)
371{
372 g_return_val_if_fail (context != NULL, NULL);
373
374 return context->font_desc;
375}
376
377/**
378 * pango_context_set_language:
379 * @context: a `PangoContext`
380 * @language: the new language tag.
381 *
382 * Sets the global language tag for the context.
383 *
384 * The default language for the locale of the running process
385 * can be found using [func@Pango.Language.get_default].
386 */
387void
388pango_context_set_language (PangoContext *context,
389 PangoLanguage *language)
390{
391 g_return_if_fail (context != NULL);
392
393 if (language != context->language)
394 context_changed (context);
395
396 context->set_language = language;
397 if (language)
398 context->language = language;
399 else
400 context->language = pango_language_get_default ();
401}
402
403/**
404 * pango_context_get_language:
405 * @context: a `PangoContext`
406 *
407 * Retrieves the global language tag for the context.
408 *
409 * Return value: the global language tag.
410 */
411PangoLanguage *
412pango_context_get_language (PangoContext *context)
413{
414 g_return_val_if_fail (context != NULL, NULL);
415
416 return context->set_language;
417}
418
419/**
420 * pango_context_set_base_dir:
421 * @context: a `PangoContext`
422 * @direction: the new base direction
423 *
424 * Sets the base direction for the context.
425 *
426 * The base direction is used in applying the Unicode bidirectional
427 * algorithm; if the @direction is %PANGO_DIRECTION_LTR or
428 * %PANGO_DIRECTION_RTL, then the value will be used as the paragraph
429 * direction in the Unicode bidirectional algorithm. A value of
430 * %PANGO_DIRECTION_WEAK_LTR or %PANGO_DIRECTION_WEAK_RTL is used only
431 * for paragraphs that do not contain any strong characters themselves.
432 */
433void
434pango_context_set_base_dir (PangoContext *context,
435 PangoDirection direction)
436{
437 g_return_if_fail (context != NULL);
438
439 if (direction != context->base_dir)
440 context_changed (context);
441
442 context->base_dir = direction;
443}
444
445/**
446 * pango_context_get_base_dir:
447 * @context: a `PangoContext`
448 *
449 * Retrieves the base direction for the context.
450 *
451 * See [method@Pango.Context.set_base_dir].
452 *
453 * Return value: the base direction for the context.
454 */
455PangoDirection
456pango_context_get_base_dir (PangoContext *context)
457{
458 g_return_val_if_fail (context != NULL, PANGO_DIRECTION_LTR);
459
460 return context->base_dir;
461}
462
463/**
464 * pango_context_set_base_gravity:
465 * @context: a `PangoContext`
466 * @gravity: the new base gravity
467 *
468 * Sets the base gravity for the context.
469 *
470 * The base gravity is used in laying vertical text out.
471 *
472 * Since: 1.16
473 */
474void
475pango_context_set_base_gravity (PangoContext *context,
476 PangoGravity gravity)
477{
478 g_return_if_fail (context != NULL);
479
480 if (gravity != context->base_gravity)
481 context_changed (context);
482
483 context->base_gravity = gravity;
484
485 update_resolved_gravity (context);
486}
487
488/**
489 * pango_context_get_base_gravity:
490 * @context: a `PangoContext`
491 *
492 * Retrieves the base gravity for the context.
493 *
494 * See [method@Pango.Context.set_base_gravity].
495 *
496 * Return value: the base gravity for the context.
497 *
498 * Since: 1.16
499 */
500PangoGravity
501pango_context_get_base_gravity (PangoContext *context)
502{
503 g_return_val_if_fail (context != NULL, PANGO_GRAVITY_SOUTH);
504
505 return context->base_gravity;
506}
507
508/**
509 * pango_context_get_gravity:
510 * @context: a `PangoContext`
511 *
512 * Retrieves the gravity for the context.
513 *
514 * This is similar to [method@Pango.Context.get_base_gravity],
515 * except for when the base gravity is %PANGO_GRAVITY_AUTO for
516 * which [func@Pango.Gravity.get_for_matrix] is used to return the
517 * gravity from the current context matrix.
518 *
519 * Return value: the resolved gravity for the context.
520 *
521 * Since: 1.16
522 */
523PangoGravity
524pango_context_get_gravity (PangoContext *context)
525{
526 g_return_val_if_fail (context != NULL, PANGO_GRAVITY_SOUTH);
527
528 return context->resolved_gravity;
529}
530
531/**
532 * pango_context_set_gravity_hint:
533 * @context: a `PangoContext`
534 * @hint: the new gravity hint
535 *
536 * Sets the gravity hint for the context.
537 *
538 * The gravity hint is used in laying vertical text out, and
539 * is only relevant if gravity of the context as returned by
540 * [method@Pango.Context.get_gravity] is set to %PANGO_GRAVITY_EAST
541 * or %PANGO_GRAVITY_WEST.
542 *
543 * Since: 1.16
544 */
545void
546pango_context_set_gravity_hint (PangoContext *context,
547 PangoGravityHint hint)
548{
549 g_return_if_fail (context != NULL);
550
551 if (hint != context->gravity_hint)
552 context_changed (context);
553
554 context->gravity_hint = hint;
555}
556
557/**
558 * pango_context_get_gravity_hint:
559 * @context: a `PangoContext`
560 *
561 * Retrieves the gravity hint for the context.
562 *
563 * See [method@Pango.Context.set_gravity_hint] for details.
564 *
565 * Return value: the gravity hint for the context.
566 *
567 * Since: 1.16
568 */
569PangoGravityHint
570pango_context_get_gravity_hint (PangoContext *context)
571{
572 g_return_val_if_fail (context != NULL, PANGO_GRAVITY_HINT_NATURAL);
573
574 return context->gravity_hint;
575}
576
577
578static gboolean
579get_first_metrics_foreach (PangoFontset *fontset,
580 PangoFont *font,
581 gpointer data)
582{
583 PangoFontMetrics *fontset_metrics = data;
584 PangoLanguage *language = PANGO_FONTSET_GET_CLASS (fontset)->get_language (fontset);
585 PangoFontMetrics *font_metrics = pango_font_get_metrics (font, language);
586 guint save_ref_count;
587
588 /* Initialize the fontset metrics to metrics of the first font in the
589 * fontset; saving the refcount and restoring it is a bit of hack but avoids
590 * having to update this code for each metrics addition.
591 */
592 save_ref_count = fontset_metrics->ref_count;
593 *fontset_metrics = *font_metrics;
594 fontset_metrics->ref_count = save_ref_count;
595
596 pango_font_metrics_unref (metrics: font_metrics);
597
598 return TRUE; /* Stops iteration */
599}
600
601static PangoFontMetrics *
602get_base_metrics (PangoFontset *fontset)
603{
604 PangoFontMetrics *metrics = pango_font_metrics_new ();
605
606 /* Initialize the metrics from the first font in the fontset */
607 pango_fontset_foreach (fontset, func: get_first_metrics_foreach, data: metrics);
608
609 return metrics;
610}
611
612static void
613update_metrics_from_items (PangoFontMetrics *metrics,
614 PangoLanguage *language,
615 const char *text,
616 unsigned int text_len,
617 GList *items)
618
619{
620 GHashTable *fonts_seen = g_hash_table_new (NULL, NULL);
621 PangoGlyphString *glyphs = pango_glyph_string_new ();
622 GList *l;
623 glong text_width;
624
625 /* This should typically be called with a sample text string. */
626 g_return_if_fail (text_len > 0);
627
628 metrics->approximate_char_width = 0;
629
630 for (l = items; l; l = l->next)
631 {
632 PangoItem *item = l->data;
633 PangoFont *font = item->analysis.font;
634
635 if (font != NULL && g_hash_table_lookup (hash_table: fonts_seen, key: font) == NULL)
636 {
637 PangoFontMetrics *raw_metrics = pango_font_get_metrics (font, language);
638 g_hash_table_insert (hash_table: fonts_seen, key: font, value: font);
639
640 /* metrics will already be initialized from the first font in the fontset */
641 metrics->ascent = MAX (metrics->ascent, raw_metrics->ascent);
642 metrics->descent = MAX (metrics->descent, raw_metrics->descent);
643 metrics->height = MAX (metrics->height, raw_metrics->height);
644 pango_font_metrics_unref (metrics: raw_metrics);
645 }
646
647 pango_shape_full (item_text: text + item->offset, item_length: item->length,
648 paragraph_text: text, paragraph_length: text_len,
649 analysis: &item->analysis, glyphs);
650 metrics->approximate_char_width += pango_glyph_string_get_width (glyphs);
651 }
652
653 pango_glyph_string_free (string: glyphs);
654 g_hash_table_destroy (hash_table: fonts_seen);
655
656 text_width = pango_utf8_strwidth (p: text);
657 g_assert (text_width > 0);
658 metrics->approximate_char_width /= text_width;
659}
660
661/**
662 * pango_context_get_metrics:
663 * @context: a `PangoContext`
664 * @desc: (nullable): a `PangoFontDescription` structure. %NULL means that the
665 * font description from the context will be used.
666 * @language: (nullable): language tag used to determine which script to get
667 * the metrics for. %NULL means that the language tag from the context
668 * will be used. If no language tag is set on the context, metrics
669 * for the default language (as determined by [func@Pango.Language.get_default]
670 * will be returned.
671 *
672 * Get overall metric information for a particular font description.
673 *
674 * Since the metrics may be substantially different for different scripts,
675 * a language tag can be provided to indicate that the metrics should be
676 * retrieved that correspond to the script(s) used by that language.
677 *
678 * The `PangoFontDescription` is interpreted in the same way as by [func@itemize],
679 * and the family name may be a comma separated list of names. If characters
680 * from multiple of these families would be used to render the string, then
681 * the returned fonts would be a composite of the metrics for the fonts loaded
682 * for the individual families.
683 *
684 * Return value: a `PangoFontMetrics` object. The caller must call
685 * [method@Pango.FontMetrics.unref] when finished using the object.
686 */
687PangoFontMetrics *
688pango_context_get_metrics (PangoContext *context,
689 const PangoFontDescription *desc,
690 PangoLanguage *language)
691{
692 PangoFontset *current_fonts = NULL;
693 PangoFontMetrics *metrics;
694 const char *sample_str;
695 unsigned int text_len;
696 GList *items;
697
698 g_return_val_if_fail (PANGO_IS_CONTEXT (context), NULL);
699
700 if (!desc)
701 desc = context->font_desc;
702
703 if (!language)
704 language = context->language;
705
706 if (desc == context->font_desc &&
707 language == context->language &&
708 context->metrics != NULL)
709 return pango_font_metrics_ref (metrics: context->metrics);
710
711 current_fonts = pango_font_map_load_fontset (fontmap: context->font_map, context, desc, language);
712 metrics = get_base_metrics (fontset: current_fonts);
713
714 sample_str = pango_language_get_sample_string (language);
715 text_len = strlen (s: sample_str);
716 items = pango_itemize_with_font (context, base_dir: context->base_dir,
717 text: sample_str, start_index: 0, length: text_len,
718 NULL, NULL,
719 desc);
720
721 update_metrics_from_items (metrics, language, text: sample_str, text_len, items);
722
723 g_list_foreach (list: items, func: (GFunc)pango_item_free, NULL);
724 g_list_free (list: items);
725
726 g_object_unref (object: current_fonts);
727
728 if (desc == context->font_desc &&
729 language == context->language)
730 context->metrics = pango_font_metrics_ref (metrics);
731
732 return metrics;
733}
734
735static void
736context_changed (PangoContext *context)
737{
738 context->serial++;
739 if (context->serial == 0)
740 context->serial++;
741
742 g_clear_pointer (&context->metrics, pango_font_metrics_unref);
743}
744
745/**
746 * pango_context_changed:
747 * @context: a `PangoContext`
748 *
749 * Forces a change in the context, which will cause any `PangoLayout`
750 * using this context to re-layout.
751 *
752 * This function is only useful when implementing a new backend
753 * for Pango, something applications won't do. Backends should
754 * call this function if they have attached extra data to the context
755 * and such data is changed.
756 *
757 * Since: 1.32.4
758 **/
759void
760pango_context_changed (PangoContext *context)
761{
762 context_changed (context);
763}
764
765static void
766check_fontmap_changed (PangoContext *context)
767{
768 guint old_serial = context->fontmap_serial;
769
770 if (!context->font_map)
771 return;
772
773 context->fontmap_serial = pango_font_map_get_serial (fontmap: context->font_map);
774
775 if (old_serial != context->fontmap_serial)
776 context_changed (context);
777}
778
779/**
780 * pango_context_get_serial:
781 * @context: a `PangoContext`
782 *
783 * Returns the current serial number of @context.
784 *
785 * The serial number is initialized to an small number larger than zero
786 * when a new context is created and is increased whenever the context
787 * is changed using any of the setter functions, or the `PangoFontMap` it
788 * uses to find fonts has changed. The serial may wrap, but will never
789 * have the value 0. Since it can wrap, never compare it with "less than",
790 * always use "not equals".
791 *
792 * This can be used to automatically detect changes to a `PangoContext`,
793 * and is only useful when implementing objects that need update when their
794 * `PangoContext` changes, like `PangoLayout`.
795 *
796 * Return value: The current serial number of @context.
797 *
798 * Since: 1.32.4
799 */
800guint
801pango_context_get_serial (PangoContext *context)
802{
803 check_fontmap_changed (context);
804 return context->serial;
805}
806
807/**
808 * pango_context_set_round_glyph_positions:
809 * @context: a `PangoContext`
810 * @round_positions: whether to round glyph positions
811 *
812 * Sets whether font rendering with this context should
813 * round glyph positions and widths to integral positions,
814 * in device units.
815 *
816 * This is useful when the renderer can't handle subpixel
817 * positioning of glyphs.
818 *
819 * The default value is to round glyph positions, to remain
820 * compatible with previous Pango behavior.
821 *
822 * Since: 1.44
823 */
824void
825pango_context_set_round_glyph_positions (PangoContext *context,
826 gboolean round_positions)
827{
828 if (context->round_glyph_positions != round_positions)
829 {
830 context->round_glyph_positions = round_positions;
831 context_changed (context);
832 }
833}
834
835/**
836 * pango_context_get_round_glyph_positions:
837 * @context: a `PangoContext`
838 *
839 * Returns whether font rendering with this context should
840 * round glyph positions and widths.
841 *
842 * Since: 1.44
843 */
844gboolean
845pango_context_get_round_glyph_positions (PangoContext *context)
846{
847 return context->round_glyph_positions;
848}
849

source code of gtk/subprojects/pango/pango/pango-context.c