📄 pango-glyph-item.c
字号:
} } iter->start_glyph = glyph_index; return TRUE;}/** * _pango_glyph_item_iter_init_start: * @iter: pointer to a #PangoGlyphItemIter structure * @glyph_item: the glyph item that @iter points into * @text: text corresponding to the glyph item * * Initializes a #PangoGlyphItemIter structure to point to the * first cluster in a glyph item. * * Return value: %FALSE if there are no clusters in the glyph item; * in this case, the state of @iter is undefined. **/gboolean_pango_glyph_item_iter_init_start (PangoGlyphItemIter *iter, PangoGlyphItem *glyph_item, const char *text){ iter->glyph_item = glyph_item; iter->text = text; if (LTR (glyph_item)) iter->end_glyph = 0; else iter->end_glyph = glyph_item->glyphs->num_glyphs - 1; iter->end_index = glyph_item->item->offset; iter->end_char = 0; /* Advance onto the first cluster of the glyph item */ return _pango_glyph_item_iter_next_cluster (iter);}/** * _pango_glyph_item_iter_init_end: * @iter: pointer to a #PangoGlyphItemIter structure * @glyph_item: the glyph item that @iter points into * @text: text corresponding to the glyph item * * Initializes a #PangoGlyphItemIter structure to point to the * last cluster in a glyph item. * * Return value: %FALSE if there are no clusters in the glyph item; * in this case, the state of @iter is undefined. **/gboolean_pango_glyph_item_iter_init_end (PangoGlyphItemIter *iter, PangoGlyphItem *glyph_item, const char *text){ iter->glyph_item = glyph_item; iter->text = text; if (LTR (glyph_item)) iter->start_glyph = glyph_item->glyphs->num_glyphs; else iter->start_glyph = -1; iter->start_index = glyph_item->item->offset + glyph_item->item->length; iter->start_char = glyph_item->item->num_chars; /* Advance onto the first cluster of the glyph item */ return _pango_glyph_item_iter_prev_cluster (iter);}typedef struct{ PangoGlyphItemIter iter; GSList *segment_attrs;} ApplyAttrsState;/* Tack @attrs onto the attributes of glyph_item */static voidappend_attrs (PangoGlyphItem *glyph_item, GSList *attrs){ glyph_item->item->analysis.extra_attrs = g_slist_concat (glyph_item->item->analysis.extra_attrs, attrs);}/* Make a deep copy of a #GSList of PangoAttribute */static GSList *attr_slist_copy (GSList *attrs){ GSList *tmp_list; GSList *new_attrs; new_attrs = g_slist_copy (attrs); for (tmp_list = new_attrs; tmp_list; tmp_list = tmp_list->next) tmp_list->data = pango_attribute_copy (tmp_list->data); return new_attrs;}/* Split the glyph item at the start of the current cluster */static PangoGlyphItem *split_before_cluster_start (ApplyAttrsState *state){ PangoGlyphItem *split_item; int split_len = state->iter.start_index - state->iter.glyph_item->item->offset; split_item = pango_glyph_item_split (state->iter.glyph_item, state->iter.text, split_len); append_attrs (split_item, state->segment_attrs); /* Adjust iteration to account for the split */ if (LTR (state->iter.glyph_item)) { state->iter.start_glyph -= split_item->glyphs->num_glyphs; state->iter.end_glyph -= split_item->glyphs->num_glyphs; } state->iter.start_char -= split_item->item->num_chars; state->iter.end_char -= split_item->item->num_chars; return split_item;}/** * pango_glyph_item_apply_attrs: * @glyph_item: a shaped item * @text: text that @list applies to * @list: a #PangoAttrList * * Splits a shaped item (PangoGlyphItem) into multiple items based * on an attribute list. The idea is that if you have attributes * that don't affect shaping, such as color or underline, to avoid * affecting shaping, you filter them out (pango_attr_list_filter()), * apply the shaping process and then reapply them to the result using * this function. * * All attributes that start or end inside a cluster are applied * to that cluster; for instance, if half of a cluster is underlined * and the other-half strikethrough, then the cluster will end * up with both underline and strikethrough attributes. In these * cases, it may happen that item->extra_attrs for some of the * result items can have multiple attributes of the same type. * * This function takes ownership of @glyph_item; it will be reused * as one of the elements in the list. * * Return value: a list of glyph items resulting from splitting * @glyph_item. Free the elements using pango_glyph_item_free(), * the list using g_slist_free(). * * Since: 1.2 **/GSList *pango_glyph_item_apply_attrs (PangoGlyphItem *glyph_item, const char *text, PangoAttrList *list){ PangoAttrIterator *iter = pango_attr_list_get_iterator (list); GSList *result = NULL; ApplyAttrsState state; gboolean start_new_segment = FALSE; gboolean have_cluster; int range_start, range_end; /* This routine works by iterating through the item cluster by * cluster; we accumulate the attributes that we need to * add to the next output item, and decide when to split * off an output item based on two criteria: * * A) If start_index < attribute_start < end_index * (attribute starts within cluster) then we need * to split between the last cluster and this cluster. * B) If start_index < attribute_end <= end_index, * (attribute ends within cluster) then we need to * split between this cluster and the next one. */ /* Advance the attr iterator to the start of the item */ do { pango_attr_iterator_range (iter, &range_start, &range_end); if (range_end > glyph_item->item->offset) break; } while (pango_attr_iterator_next (iter)); state.segment_attrs = pango_attr_iterator_get_attrs (iter); /* Short circuit the case when we don't actually need to * split the item */ if (range_start <= glyph_item->item->offset && range_end >= glyph_item->item->offset + glyph_item->item->length) goto out; for (have_cluster = _pango_glyph_item_iter_init_start (&state.iter, glyph_item, text); have_cluster; have_cluster = _pango_glyph_item_iter_next_cluster (&state.iter)) { gboolean have_next; /* [range_start,range_end] is the first range that intersects * the current cluster. */ /* Split item into two, if this cluster isn't a continuation * of the last cluster */ if (start_new_segment) { result = g_slist_prepend (result, split_before_cluster_start (&state)); state.segment_attrs = pango_attr_iterator_get_attrs (iter); } start_new_segment = FALSE; /* Loop over all ranges that intersect this cluster; exiting * leaving [range_start,range_end] being the first range that * intersects the next cluster. */ do { if (range_end > state.iter.end_index) /* Range intersects next cluster */ break; /* Since ranges end in this cluster, the next cluster goes into a * separate segment */ start_new_segment = TRUE; have_next = pango_attr_iterator_next (iter); pango_attr_iterator_range (iter, &range_start, &range_end); if (range_start >= state.iter.end_index) /* New range doesn't intersect this cluster */ { /* No gap between ranges, so previous range must of ended * at cluster boundary. */ g_assert (range_start == state.iter.end_index && start_new_segment); break; } /* If any ranges start *inside* this cluster, then we need * to split the previous cluster into a separate segment */ if (range_start > state.iter.start_index && state.iter.start_index != glyph_item->item->offset) { GSList *new_attrs = attr_slist_copy (state.segment_attrs); result = g_slist_prepend (result, split_before_cluster_start (&state)); state.segment_attrs = new_attrs; } state.segment_attrs = g_slist_concat (state.segment_attrs, pango_attr_iterator_get_attrs (iter)); } while (have_next); } out: /* What's left in glyph_item is the remaining portion */ append_attrs (glyph_item, state.segment_attrs); result = g_slist_prepend (result, glyph_item); if (LTR (glyph_item)) result = g_slist_reverse (result); pango_attr_iterator_destroy (iter); return result;}/** * pango_glyph_item_letter_space: * @glyph_item: a #PangoGlyphItem * @text: text that @glyph_item corresponds to * (glyph_item->item->offset is an offset from the * start of @text) * @log_attrs: logical attributes for the item (the * first logical attribute refers to the position * before the first character in the item) * @letter_spacing: amount of letter spacing to add * in Pango units. May be negative, though too large * negative values will give ugly results. * * Adds spacing between the graphemes of @glyph_item to * give the effect of typographic letter spacing. * * Since: 1.6 **/voidpango_glyph_item_letter_space (PangoGlyphItem *glyph_item, const char *text, PangoLogAttr *log_attrs, int letter_spacing){ PangoGlyphItemIter iter; PangoGlyphInfo *glyphs = glyph_item->glyphs->glyphs; gboolean have_cluster; int space_left, space_right; space_left = letter_spacing / 2; /* hinting */ if ((letter_spacing & (PANGO_SCALE - 1)) == 0) { space_left = PANGO_UNITS_ROUND (space_left); } space_right = letter_spacing - space_left; for (have_cluster = _pango_glyph_item_iter_init_start (&iter, glyph_item, text); have_cluster; have_cluster = _pango_glyph_item_iter_next_cluster (&iter)) { if (!log_attrs[iter.start_char].is_cursor_position) continue; if (iter.start_glyph < iter.end_glyph) /* LTR */ { if (iter.start_char > 0) { glyphs[iter.start_glyph].geometry.width += space_left ; glyphs[iter.start_glyph].geometry.x_offset += space_left ; } if (iter.end_char < glyph_item->item->num_chars) { glyphs[iter.end_glyph-1].geometry.width += space_right; } } else /* RTL */ { if (iter.start_char > 0) { glyphs[iter.start_glyph].geometry.width += space_right; } if (iter.end_char < glyph_item->item->num_chars) { glyphs[iter.end_glyph+1].geometry.x_offset += space_left ; glyphs[iter.end_glyph+1].geometry.width += space_left ; } } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -