📄 pango-context.c
字号:
PangoGravityHint gravity_hint = state->gravity_hint; if (G_LIKELY (gravity == PANGO_GRAVITY_AUTO)) gravity = state->context->resolved_gravity; state->resolved_gravity = pango_gravity_get_for_script (state->script, gravity, gravity_hint); } if (old_gravity != state->resolved_gravity) { pango_font_description_set_gravity (state->font_desc, state->resolved_gravity); state->changed |= FONT_CHANGED; } } if (state->changed & (SCRIPT_CHANGED | LANG_CHANGED)) { PangoLanguage *old_derived_lang = state->derived_lang; state->derived_lang = compute_derived_language (state->lang, state->script); if (old_derived_lang != state->derived_lang) state->changed |= DERIVED_LANG_CHANGED; } if ((state->changed & DERIVED_LANG_CHANGED) || !state->lang_engine) { PangoMap *lang_map = get_lang_map (state->derived_lang); state->lang_engine = (PangoEngineLang *)pango_map_get_engine (lang_map, state->script); } if (state->changed & (SCRIPT_CHANGED | DERIVED_LANG_CHANGED)) itemize_state_reset_shape_engines (state); if (state->changed & (FONT_CHANGED | DERIVED_LANG_CHANGED) && state->current_fonts) { g_object_unref (state->current_fonts); state->current_fonts = NULL; state->cache = NULL; } if (!state->current_fonts) { state->current_fonts = pango_font_map_load_fontset (state->context->font_map, state->context, state->font_desc, state->derived_lang); state->cache = get_shaper_font_cache (state->current_fonts); } if ((state->changed & FONT_CHANGED) && state->base_font) { g_object_unref (state->base_font); state->base_font = NULL; }}static voiditemize_state_process_run (ItemizeState *state){ const char *p; gboolean last_was_forced_break = FALSE; /* Only one character has type G_UNICODE_LINE_SEPARATOR in Unicode 4.0; * update this if that changes. */#define LINE_SEPARATOR 0x2028 itemize_state_update_for_new_run (state); /* We should never get an empty run */ g_assert (state->run_end != state->run_start); for (p = state->run_start; p < state->run_end; p = g_utf8_next_char (p)) { gunichar wc = g_utf8_get_char (p); gboolean is_forced_break = (wc == '\t' || wc == LINE_SEPARATOR); PangoEngineShape *shape_engine; PangoFont *font; /* We don't want space characters to affect font selection; in general, * it's always wrong to select a font just to render a space. But until * we have a better solution, choosing a font for spaces seems to work * better. However, all fonts are assumed to cover ASCII space, so that * one is an exception. See bug #355987. * * The exception of PrivateUse and Unassigned characters is necessary * to be able to render any of them. (for private or being encoded * scripts, etc.) */ if (wc == 0x0020 || G_UNLIKELY (!g_unichar_isprint (wc) && g_unichar_type (wc) != G_UNICODE_PRIVATE_USE && g_unichar_type (wc) != G_UNICODE_UNASSIGNED)) { shape_engine = NULL; font = NULL; } else { get_shaper_and_font (state, wc, &shape_engine, &font); } itemize_state_add_character (state, shape_engine, font, is_forced_break || last_was_forced_break, p); last_was_forced_break = is_forced_break; } /* Finish the final item from the current segment */ state->item->length = (p - state->text) - state->item->offset; if (!state->item->analysis.shape_engine) { PangoEngineShape *shape_engine; PangoFont *font; if (!get_shaper_and_font (state, ' ', &shape_engine, &font)) { shape_engine = _pango_get_fallback_shaper (); font = NULL; } itemize_state_fill_shaper (state, shape_engine, font); } state->item = NULL;}static voiditemize_state_finish (ItemizeState *state){ g_free (state->embedding_levels); if (state->free_attr_iter) pango_attr_iterator_destroy (state->attr_iter); pango_script_iter_free (state->script_iter); pango_font_description_free (state->font_desc); itemize_state_reset_shape_engines (state); if (state->current_fonts) g_object_unref (state->current_fonts); if (state->base_font) g_object_unref (state->base_font);}/** * pango_itemize_with_base_dir: * @context: a structure holding information that affects the itemization process. * @text: the text to itemize. * @start_index: first byte in @text to process * @length: the number of bytes (not characters) to process * after @start_index. * This must be >= 0. * @base_dir: base direction to use for bidirectional processing * @attrs: the set of attributes that apply to @text. * @cached_iter: Cached attribute iterator, or %NULL * * Like pango_itemize(), but the base direction to use when * computing bidirectional levels (see pango_context_set_base_dir ()), * is specified explicitly rather than gotten from the #PangoContext. * * Return value: a #GList of #PangoItem structures. The items should be * freed using pango_item_free() probably in combination with g_list_foreach(), * and the list itself using g_list_free(). * * Since: 1.4 */GList *pango_itemize_with_base_dir (PangoContext *context, PangoDirection base_dir, const char *text, int start_index, int length, PangoAttrList *attrs, PangoAttrIterator *cached_iter){ ItemizeState state; g_return_val_if_fail (context != NULL, NULL); g_return_val_if_fail (start_index >= 0, NULL); g_return_val_if_fail (length >= 0, NULL); g_return_val_if_fail (length == 0 || text != NULL, NULL); if (length == 0) return NULL; itemize_state_init (&state, context, text, base_dir, start_index, length, attrs, cached_iter, NULL); do itemize_state_process_run (&state); while (itemize_state_next (&state)); itemize_state_finish (&state); return g_list_reverse (state.result);}static GList *itemize_with_font (PangoContext *context, const char *text, int start_index, int length, const PangoFontDescription *desc){ ItemizeState state; if (length == 0) return NULL; itemize_state_init (&state, context, text, context->base_dir, start_index, length, NULL, NULL, desc); do itemize_state_process_run (&state); while (itemize_state_next (&state)); itemize_state_finish (&state); return g_list_reverse (state.result);}/** * pango_itemize: * @context: a structure holding information that affects the itemization process. * @text: the text to itemize. * @start_index: first byte in @text to process * @length: the number of bytes (not characters) to process * after @start_index. * This must be >= 0. * @attrs: the set of attributes that apply to @text. * @cached_iter: Cached attribute iterator, or %NULL * * Breaks a piece of text into segments with consistent * directional level and shaping engine. Each byte of @text will * be contained in exactly one of the items in the returned list; * the generated list of items will be in logical order (the start * offsets of the items are ascending). * * @cached_iter should be an iterator over @attrs currently positioned at a * range before or containing @start_index; @cached_iter will be advanced to * the range covering the position just after @start_index + @length. * (i.e. if itemizing in a loop, just keep passing in the same @cached_iter). * * Return value: a #GList of #PangoItem structures. */GList *pango_itemize (PangoContext *context, const char *text, int start_index, int length, PangoAttrList *attrs, PangoAttrIterator *cached_iter){ g_return_val_if_fail (context != NULL, NULL); g_return_val_if_fail (start_index >= 0, NULL); g_return_val_if_fail (length >= 0, NULL); g_return_val_if_fail (length == 0 || text != NULL, NULL); return pango_itemize_with_base_dir (context, context->base_dir, text, start_index, length, attrs, cached_iter);}static gbooleanget_first_metrics_foreach (PangoFontset *fontset, PangoFont *font, gpointer data){ PangoFontMetrics *fontset_metrics = data; PangoLanguage *language = PANGO_FONTSET_GET_CLASS (fontset)->get_language (fontset); PangoFontMetrics *font_metrics = pango_font_get_metrics (font, language); guint save_ref_count; /* Initialize the fontset metrics to metrics of the first font in the * fontset; saving the refcount and restoring it is a bit of hack but avoids * having to update this code for each metrics addition. */ save_ref_count = fontset_metrics->ref_count; *fontset_metrics = *font_metrics; fontset_metrics->ref_count = save_ref_count; pango_font_metrics_unref (font_metrics); return TRUE; /* Stops iteration */}static PangoFontMetrics *get_base_metrics (PangoFontset *fontset){ PangoFontMetrics *metrics = pango_font_metrics_new (); /* Initialize the metrics from the first font in the fontset */ pango_fontset_foreach (fontset, get_first_metrics_foreach, metrics); return metrics;}static voidupdate_metrics_from_items (PangoFontMetrics *metrics, PangoLanguage *language, GList *items){ GHashTable *fonts_seen = g_hash_table_new (NULL, NULL); int count = 0; GList *l; for (l = items; l; l = l->next) { PangoItem *item = l->data; PangoFont *font = item->analysis.font; if (font != NULL && g_hash_table_lookup (fonts_seen, font) == NULL) { PangoFontMetrics *raw_metrics = pango_font_get_metrics (font, language); g_hash_table_insert (fonts_seen, font, font); /* metrics will already be initialized from the first font in the fontset */ metrics->ascent = MAX (metrics->ascent, raw_metrics->ascent); metrics->descent = MAX (metrics->descent, raw_metrics->descent); if (count == 0) { metrics->approximate_char_width = raw_metrics->approximate_char_width; metrics->approximate_digit_width = raw_metrics->approximate_digit_width; } else { metrics->approximate_char_width += raw_metrics->approximate_char_width; metrics->approximate_digit_width += raw_metrics->approximate_digit_width; } count++; pango_font_metrics_unref (raw_metrics); } } g_hash_table_destroy (fonts_seen); if (count) { metrics->approximate_char_width /= count; metrics->approximate_digit_width /= count; }}/** * pango_context_get_metrics: * @context: a #PangoContext * @desc: a #PangoFontDescription structure * @language: language tag used to determine which script to get the metrics * for. %NULL means that the language tag from the context will * be used. If no language tag is set on the context, metrics * large enough to cover a range of languages will be returned. * The process of determining such metrics is slow, so it is best * to always make sure some real language tag will be used. * * Get overall metric information for a particular font * description. Since the metrics may be substantially different for * different scripts, a language tag can be provided to indicate that * the metrics should be retrieved that correspond to the script(s) * used by that language. * * The #PangoFontDescription is interpreted in the same way as * by pango_itemize(), and the family name may be a comma separated * list of figures. If characters from multiple of these families * would be used to render the string, then the returned fonts would * be a composite of the metrics for the fonts loaded for the * individual families. * * Return value: a #PangoFontMetrics object. The caller must call pango_font_metrics_unref() * when finished using the object. **/PangoFontMetrics *pango_context_get_metrics (PangoContext *context, const PangoFontDescription *desc, PangoLanguage *language){ PangoFontset *current_fonts = NULL; PangoFontMetrics *metrics; const char *sample_str; GList *items; g_return_val_if_fail (PANGO_IS_CONTEXT (context), NULL); g_return_val_if_fail (desc != NULL, NULL); if (!language) language = context->language; current_fonts = pango_font_map_load_fontset (context->font_map, context, desc, language); metrics = get_base_metrics (current_fonts); sample_str = pango_language_get_sample_string (language); items = itemize_with_font (context, sample_str, 0, strlen (sample_str), desc); update_metrics_from_items (metrics, language, items); g_list_foreach (items, (GFunc)pango_item_free, NULL); g_list_free (items); g_object_unref (current_fonts); return metrics;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -