static GSList * attrs_at_byte (PangoAttrList *alist, gint bytepos) { PangoAttrIterator *iter = pango_attr_list_get_iterator (alist); GSList *attrs = NULL; do { gint start, end; pango_attr_iterator_range (iter, &start, &end); if (start <= bytepos && bytepos < end) { attrs = pango_attr_iterator_get_attrs (iter); break; } } while (pango_attr_iterator_next (iter)); pango_attr_iterator_destroy (iter); return attrs; }
char * go_pango_attrs_to_markup (PangoAttrList *attrs, char const *text) { PangoAttrIterator * iter; int handled = 0; int from, to; int len; GString *gstr; if (text == NULL) return NULL; if (attrs == NULL || go_pango_attr_list_is_empty (attrs)) return g_strdup (text); len = strlen (text); gstr = g_string_sized_new (len + 1); iter = pango_attr_list_get_iterator (attrs); do { GSList *list, *l; int spans = 0; pango_attr_iterator_range (iter, &from, &to); to = (to > len) ? len : to; /* Since "to" can be really big! */ from = (from > len) ? len : from; /* Since "from" can also be really big! */ if (from > handled) g_string_append_len (gstr, text + handled, from - handled); list = pango_attr_iterator_get_attrs (iter); for (l = list; l != NULL; l = l->next) spans += go_pango_attr_as_markup_string (l->data, gstr); g_slist_free (list); if (to > from) g_string_append_len (gstr, text + from, to - from); while (spans-- > 0) g_string_append (gstr, "</span>"); handled = to; } while (pango_attr_iterator_next (iter)); pango_attr_iterator_destroy (iter); return g_string_free (gstr, FALSE); }
static VALUE rg_attrs(VALUE self) { GSList* list = pango_attr_iterator_get_attrs(_SELF(self)); GSList* base = list; GSList* old = list; VALUE ary = rb_ary_new(); while (list) { rb_ary_push(ary, ATTR2RVAL(list->data)); list = list->next; } while (old) { pango_attribute_destroy((PangoAttribute*)old); old = old->next; } g_slist_free(base); return ary; }
static void html_new_markup (GsfOutput *output, const PangoAttrList *markup, char const *text, html_version_t version) { int handled = 0; PangoAttrIterator * iter; int from, to; int len = strlen (text); GString *closure = g_string_new (""); iter = pango_attr_list_get_iterator ((PangoAttrList *) markup); do { GSList *list, *l; g_string_erase (closure, 0, -1); pango_attr_iterator_range (iter, &from, &to); from = (from > len) ? len : from; /* Since "from" can be really big! */ to = (to > len) ? len : to; /* Since "to" can be really big! */ if (from > handled) cb_html_add_chars (output, text + handled, from - handled); list = pango_attr_iterator_get_attrs (iter); for (l = list; l != NULL; l = l->next) { char const *result = cb_html_attrs_as_string (output, l->data, version); if (result != NULL) g_string_prepend (closure, result); } g_slist_free (list); if (to > from) cb_html_add_chars (output, text + from, to - from); gsf_output_puts (output, closure->str); handled = to; } while (pango_attr_iterator_next (iter)); g_string_free (closure, TRUE); pango_attr_iterator_destroy (iter); return; }
static void dump_attrs (PangoAttrList *attrs, GString *string) { PangoAttrIterator *iter; iter = pango_attr_list_get_iterator (attrs); do { gint start, end; GSList *list, *l; pango_attr_iterator_range (iter, &start, &end); g_string_append_printf (string, "range %d %d\n", start, end); list = pango_attr_iterator_get_attrs (iter); for (l = list; l; l = l->next) { PangoAttribute *attr = l->data; print_attr (attr, string); } g_slist_free_full (list, (GDestroyNotify)pango_attribute_destroy); } while (pango_attr_iterator_next (iter)); pango_attr_iterator_destroy (iter); }
static void go_pango_translate_here (PangoAttrIterator *state_iter, PangoAttrIterator *attr_iter, PangoAttrList *attrs) { double font_scale = 1.; double scale = 1.; int rise = 0; PangoAttribute *pa; PangoFontDescription *desc = pango_font_description_new (); GSList *the_attrs, *l; gint range_start, range_end; pango_attr_iterator_range (attr_iter, &range_start, &range_end); if (range_start == range_end) return; desc = pango_font_description_new (); pango_attr_iterator_get_font (state_iter, desc, NULL, NULL); font_scale = pango_font_description_get_size (desc)/ (double)PANGO_SCALE/10.; pango_font_description_free (desc); pa = pango_attr_iterator_get (state_iter, PANGO_ATTR_SCALE); if (pa) scale = ((PangoAttrFloat *)pa)->value; pa = pango_attr_iterator_get (state_iter, PANGO_ATTR_RISE); if (pa) rise = ((PangoAttrInt *)pa)->value; /* We should probably figured out the default font size used */ /* rather than assuming it is 10 pts * scale */ if (font_scale == 0) font_scale = scale; the_attrs = pango_attr_iterator_get_attrs (attr_iter); for (l = the_attrs; l != NULL; l = l->next) { PangoAttribute *attribute = l->data; PangoAttrType type = attribute->klass->type; if (type == go_pango_attr_superscript_get_attr_type ()) { GOPangoAttrSuperscript *attr = (GOPangoAttrSuperscript *)attribute; if (attr->val) { scale *= GO_SUPERSCRIPT_SCALE; rise += GO_SUPERSCRIPT_RISE * font_scale; font_scale *= GO_SUPERSCRIPT_SCALE; } } else { /* go_pango_attr_subscript_type */ GOPangoAttrSubscript *attr = (GOPangoAttrSubscript *)attribute; if (attr->val) { scale *= GO_SUBSCRIPT_SCALE; rise += GO_SUBSCRIPT_RISE * font_scale; font_scale *= GO_SUBSCRIPT_SCALE; } } } if (the_attrs != NULL) { PangoAttribute *attr = pango_attr_scale_new (scale); attr->start_index = range_start; attr->end_index = range_end; pango_attr_list_insert (attrs, attr); attr = pango_attr_rise_new (rise); attr->start_index = range_start; attr->end_index = range_end; pango_attr_list_insert (attrs, attr); } g_slist_free_full (the_attrs, (GDestroyNotify)pango_attribute_destroy); }
void go_load_pango_attributes_into_buffer (PangoAttrList *markup, GtkTextBuffer *buffer, gchar const *str) { PangoAttrIterator * iter; PangoAttrList *copied_markup; PangoAttrList *our_markup; if (markup == NULL) return; /* For some styles we create named tags. The names are taken from the Pango enums */ copied_markup = pango_attr_list_copy (markup); our_markup = pango_attr_list_filter (copied_markup, go_load_pango_attributes_into_buffer_named_filter, NULL); pango_attr_list_unref (copied_markup); if (our_markup != NULL) { iter = pango_attr_list_get_iterator (our_markup); do { GSList *attr = pango_attr_iterator_get_attrs (iter); if (attr != NULL) { GSList *ptr; gint start, end; GtkTextIter start_iter, end_iter; char const *name; pango_attr_iterator_range (iter, &start, &end); start = go_load_pango_byte_to_char (str, start); end = go_load_pango_byte_to_char (str, end); gtk_text_buffer_get_iter_at_offset (buffer, &start_iter, start); gtk_text_buffer_get_iter_at_offset (buffer, &end_iter, end); for (ptr = attr; ptr != NULL; ptr = ptr->next) { PangoAttribute *attribute = ptr->data; GtkTextTag *tag; int val; switch (attribute->klass->type) { case PANGO_ATTR_STYLE: name = (((PangoAttrInt *)attribute)->value == PANGO_STYLE_NORMAL) ? "PANGO_STYLE_NORMAL" : "PANGO_STYLE_ITALIC"; tag = gtk_text_tag_table_lookup (gtk_text_buffer_get_tag_table (buffer), name); gtk_text_buffer_apply_tag (buffer, tag, &start_iter, &end_iter); break; case PANGO_ATTR_STRIKETHROUGH: name = (((PangoAttrInt *)attribute)->value) ? "PANGO_STRIKETHROUGH_TRUE" : "PANGO_STRIKETHROUGH_FALSE"; tag = gtk_text_tag_table_lookup (gtk_text_buffer_get_tag_table (buffer), name); gtk_text_buffer_apply_tag (buffer, tag, &start_iter, &end_iter); break; case PANGO_ATTR_UNDERLINE: val = ((PangoAttrInt *)attribute)->value; if (val == PANGO_UNDERLINE_NONE) gtk_text_buffer_apply_tag_by_name (buffer,"PANGO_UNDERLINE_NONE", &start_iter, &end_iter); else if (val == PANGO_UNDERLINE_SINGLE) gtk_text_buffer_apply_tag_by_name (buffer,"PANGO_UNDERLINE_SINGLE", &start_iter, &end_iter); else if (val == PANGO_UNDERLINE_DOUBLE) gtk_text_buffer_apply_tag_by_name (buffer,"PANGO_UNDERLINE_DOUBLE", &start_iter, &end_iter); else if (val == PANGO_UNDERLINE_LOW) gtk_text_buffer_apply_tag_by_name (buffer,"PANGO_UNDERLINE_LOW", &start_iter, &end_iter); else if (val == PANGO_UNDERLINE_ERROR) gtk_text_buffer_apply_tag_by_name (buffer,"PANGO_UNDERLINE_ERROR", &start_iter, &end_iter); break; case PANGO_ATTR_WEIGHT: val = ((PangoAttrInt *)attribute)->value; if (val < (PANGO_WEIGHT_THIN + PANGO_WEIGHT_ULTRALIGHT)/2) gtk_text_buffer_apply_tag_by_name (buffer,"PANGO_WEIGHT_THIN", &start_iter, &end_iter); else if (val < (PANGO_WEIGHT_ULTRALIGHT + PANGO_WEIGHT_LIGHT)/2) gtk_text_buffer_apply_tag_by_name (buffer,"PANGO_WEIGHT_ULTRALIGHT", &start_iter, &end_iter); else if (val < (PANGO_WEIGHT_LIGHT + PANGO_WEIGHT_BOOK)/2) gtk_text_buffer_apply_tag_by_name (buffer,"PANGO_WEIGHT_LIGHT", &start_iter, &end_iter); else if (val < (PANGO_WEIGHT_BOOK + PANGO_WEIGHT_NORMAL)/2) gtk_text_buffer_apply_tag_by_name (buffer,"PANGO_WEIGHT_BOOK", &start_iter, &end_iter); else if (val < (PANGO_WEIGHT_NORMAL + PANGO_WEIGHT_MEDIUM)/2) gtk_text_buffer_apply_tag_by_name (buffer,"PANGO_WEIGHT_NORMAL", &start_iter, &end_iter); else if (val < (PANGO_WEIGHT_MEDIUM + PANGO_WEIGHT_SEMIBOLD)/2) gtk_text_buffer_apply_tag_by_name (buffer,"PANGO_WEIGHT_MEDIUM", &start_iter, &end_iter); else if (val < (PANGO_WEIGHT_SEMIBOLD + PANGO_WEIGHT_BOLD)/2) gtk_text_buffer_apply_tag_by_name (buffer,"PANGO_WEIGHT_SEMIBOLD", &start_iter, &end_iter); else if (val < (PANGO_WEIGHT_BOLD + PANGO_WEIGHT_ULTRABOLD)/2) gtk_text_buffer_apply_tag_by_name (buffer,"PANGO_WEIGHT_BOLD", &start_iter, &end_iter); else if (val < (PANGO_WEIGHT_ULTRABOLD + PANGO_WEIGHT_HEAVY)/2) gtk_text_buffer_apply_tag_by_name (buffer,"PANGO_WEIGHT_ULTRABOLD", &start_iter, &end_iter); else if (val < (PANGO_WEIGHT_HEAVY + PANGO_WEIGHT_ULTRAHEAVY)/2) gtk_text_buffer_apply_tag_by_name (buffer,"PANGO_WEIGHT_HEAVY", &start_iter, &end_iter); else gtk_text_buffer_apply_tag_by_name (buffer,"PANGO_WEIGHT_ULTRAHEAVY", &start_iter, &end_iter); break; default: break; } } g_slist_free_full (attr, (GDestroyNotify)pango_attribute_destroy); } } while (pango_attr_iterator_next (iter)); pango_attr_iterator_destroy (iter); pango_attr_list_unref (our_markup); } /* For other styles (that are not at true/false type styles) we use unnamed styles */ copied_markup = pango_attr_list_copy (markup); our_markup = pango_attr_list_filter (copied_markup, go_load_pango_attributes_into_buffer_filter, NULL); pango_attr_list_unref (copied_markup); if (our_markup != NULL) { iter = pango_attr_list_get_iterator (our_markup); do { GSList *attr = pango_attr_iterator_get_attrs (iter); if (attr != NULL) { char *string; GSList *ptr; gint start, end; GtkTextIter start_iter, end_iter; GtkTextTag *tag = gtk_text_buffer_create_tag (buffer, NULL, NULL); for (ptr = attr; ptr != NULL; ptr = ptr->next) { PangoAttribute *attribute = ptr->data; switch (attribute->klass->type) { case PANGO_ATTR_FOREGROUND: string = pango_color_to_string (&((PangoAttrColor *)attribute)->color); g_object_set (G_OBJECT (tag), "foreground", string, "foreground-set", TRUE, NULL); g_free (string); break; case PANGO_ATTR_RISE: g_object_set (G_OBJECT (tag), "rise", ((PangoAttrInt *)attribute)->value, "rise-set", TRUE, NULL); break; default: break; } } pango_attr_iterator_range (iter, &start, &end); start = go_load_pango_byte_to_char (str, start); end = go_load_pango_byte_to_char (str, end); gtk_text_buffer_get_iter_at_offset (buffer, &start_iter, start); gtk_text_buffer_get_iter_at_offset (buffer, &end_iter, end); gtk_text_buffer_apply_tag (buffer, tag, &start_iter, &end_iter); g_slist_free_full (attr, (GDestroyNotify)pango_attribute_destroy); } } while (pango_attr_iterator_next (iter)); pango_attr_iterator_destroy (iter); pango_attr_list_unref (our_markup); } }
/* Shapes the ellipsis using the font and is_cjk information computed by * update_ellipsis_shape() from the first character in the gap. */ static void shape_ellipsis (EllipsizeState *state) { PangoAttrList *attrs = pango_attr_list_new (); GSList *run_attrs; PangoItem *item; PangoGlyphString *glyphs; GSList *l; PangoAttribute *fallback; const char *ellipsis_text; int i; /* Create/reset state->ellipsis_run */ if (!state->ellipsis_run) { state->ellipsis_run = g_slice_new (PangoGlyphItem); state->ellipsis_run->glyphs = pango_glyph_string_new (); state->ellipsis_run->item = NULL; } if (state->ellipsis_run->item) { pango_item_free (state->ellipsis_run->item); state->ellipsis_run->item = NULL; } /* Create an attribute list */ run_attrs = pango_attr_iterator_get_attrs (state->gap_start_attr); for (l = run_attrs; l; l = l->next) { PangoAttribute *attr = l->data; attr->start_index = 0; attr->end_index = G_MAXINT; pango_attr_list_insert (attrs, attr); } g_slist_free (run_attrs); fallback = pango_attr_fallback_new (FALSE); fallback->start_index = 0; fallback->end_index = G_MAXINT; pango_attr_list_insert (attrs, fallback); /* First try using a specific ellipsis character in the best matching font */ if (state->ellipsis_is_cjk) ellipsis_text = "\342\213\257"; /* U+22EF: MIDLINE HORIZONTAL ELLIPSIS, used for CJK */ else ellipsis_text = "\342\200\246"; /* U+2026: HORIZONTAL ELLIPSIS */ item = itemize_text (state, ellipsis_text, attrs); /* If that fails we use "..." in the first matching font */ if (!item->analysis.font || !_pango_engine_shape_covers (item->analysis.shape_engine, item->analysis.font, item->analysis.language, g_utf8_get_char (ellipsis_text))) { pango_item_free (item); /* Modify the fallback iter while it is inside the PangoAttrList; Don't try this at home */ ((PangoAttrInt *)fallback)->value = TRUE; ellipsis_text = "..."; item = itemize_text (state, ellipsis_text, attrs); } pango_attr_list_unref (attrs); state->ellipsis_run->item = item; /* Now shape */ glyphs = state->ellipsis_run->glyphs; pango_shape (ellipsis_text, strlen (ellipsis_text), &item->analysis, glyphs); state->ellipsis_width = 0; for (i = 0; i < glyphs->num_glyphs; i++) state->ellipsis_width += glyphs->glyphs[i].geometry.width; }