/* Set the colour of the "valid from" and "valid until" elements on the * Certificate page to red if they are incorrectly in the future or * past. */ static void show_date_state(char* label, void* data, int length) { gchar* labelname = g_strndup(label, strstr(label, ":") - label); GtkLabel* l = GTK_LABEL(gtk_builder_get_object(builder, labelname)); PangoAttrList *attrs = pango_attr_list_new(); PangoAttribute *attr; gboolean* is_invalid = (gboolean*)data; g_free(labelname); if(*is_invalid) { attr = pango_attr_foreground_new(G_MAXUINT16, 0, 0); } else { #if HAVE_GTK == 3 GdkRGBA color; GtkStyleContext *style = gtk_widget_get_style_context(GTK_WIDGET(l)); gtk_style_context_get_color(style, GTK_STATE_FLAG_NORMAL, &color); attr = pango_attr_foreground_new(color.red * G_MAXUINT16, color.green * G_MAXUINT16, color.blue * G_MAXUINT16); #else #if HAVE_GTK == 2 /* In GTK+ 2, there is no GtkStyleContext yet. It * should, in theory, be possible to figure out what the * default foreground color is by using a GTK+ * 2-specific API, but that's too much work and GTK+ 2 * is a minority now anyway, so... */ attr = pango_attr_foreground_new(0, 0, 0); #else /* The configure script only allows GTK+2 or GTK+3. */ #error should not happen #endif #endif } pango_attr_list_insert(attrs, attr); gtk_label_set_attributes(l, attrs); }
static void gimp_combo_tag_entry_style_set (GtkWidget *widget, GtkStyle *previous_style) { GimpComboTagEntry *entry = GIMP_COMBO_TAG_ENTRY (widget); GtkStyle *style = gtk_widget_get_style (widget); GdkColor color; PangoAttribute *attribute; if (GTK_WIDGET_CLASS (parent_class)->style_set) GTK_WIDGET_CLASS (parent_class)->style_set (widget, previous_style); if (entry->normal_item_attr) pango_attr_list_unref (entry->normal_item_attr); entry->normal_item_attr = pango_attr_list_new (); if (style->font_desc) { attribute = pango_attr_font_desc_new (style->font_desc); pango_attr_list_insert (entry->normal_item_attr, attribute); } color = style->text[GTK_STATE_NORMAL]; attribute = pango_attr_foreground_new (color.red, color.green, color.blue); pango_attr_list_insert (entry->normal_item_attr, attribute); if (entry->selected_item_attr) pango_attr_list_unref (entry->selected_item_attr); entry->selected_item_attr = pango_attr_list_copy (entry->normal_item_attr); color = style->text[GTK_STATE_SELECTED]; attribute = pango_attr_foreground_new (color.red, color.green, color.blue); pango_attr_list_insert (entry->selected_item_attr, attribute); color = style->base[GTK_STATE_SELECTED]; attribute = pango_attr_background_new (color.red, color.green, color.blue); pango_attr_list_insert (entry->selected_item_attr, attribute); if (entry->insensitive_item_attr) pango_attr_list_unref (entry->insensitive_item_attr); entry->insensitive_item_attr = pango_attr_list_copy (entry->normal_item_attr); color = style->text[GTK_STATE_INSENSITIVE]; attribute = pango_attr_foreground_new (color.red, color.green, color.blue); pango_attr_list_insert (entry->insensitive_item_attr, attribute); color = style->base[GTK_STATE_INSENSITIVE]; attribute = pango_attr_background_new (color.red, color.green, color.blue); pango_attr_list_insert (entry->insensitive_item_attr, attribute); entry->selected_item_color = style->base[GTK_STATE_SELECTED]; if (entry->arrow_pixbuf) { g_object_unref (entry->arrow_pixbuf); entry->arrow_pixbuf = NULL; } }
static void text_input_preedit_styling(void *data, struct wl_text_input *text_input, uint32_t index, uint32_t length, uint32_t style) { struct text_entry *entry = data; PangoAttribute *attr1 = NULL; PangoAttribute *attr2 = NULL; if (!entry->preedit_info.attr_list) entry->preedit_info.attr_list = pango_attr_list_new(); switch (style) { case WL_TEXT_INPUT_PREEDIT_STYLE_DEFAULT: case WL_TEXT_INPUT_PREEDIT_STYLE_UNDERLINE: attr1 = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE); break; case WL_TEXT_INPUT_PREEDIT_STYLE_INCORRECT: attr1 = pango_attr_underline_new(PANGO_UNDERLINE_ERROR); attr2 = pango_attr_underline_color_new(65535, 0, 0); break; case WL_TEXT_INPUT_PREEDIT_STYLE_SELECTION: attr1 = pango_attr_background_new(0.3 * 65535, 0.3 * 65535, 65535); attr2 = pango_attr_foreground_new(65535, 65535, 65535); break; case WL_TEXT_INPUT_PREEDIT_STYLE_HIGHLIGHT: case WL_TEXT_INPUT_PREEDIT_STYLE_ACTIVE: attr1 = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE); attr2 = pango_attr_weight_new(PANGO_WEIGHT_BOLD); break; case WL_TEXT_INPUT_PREEDIT_STYLE_INACTIVE: attr1 = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE); attr2 = pango_attr_foreground_new(0.3 * 65535, 0.3 * 65535, 0.3 * 65535); break; } if (attr1) { attr1->start_index = entry->cursor + index; attr1->end_index = entry->cursor + index + length; pango_attr_list_insert(entry->preedit_info.attr_list, attr1); } if (attr2) { attr2->start_index = entry->cursor + index; attr2->end_index = entry->cursor + index + length; pango_attr_list_insert(entry->preedit_info.attr_list, attr2); } }
static void create_layout (GtkSourceGutterRendererText *renderer, GtkWidget *widget) { PangoLayout *layout; PangoAttribute *attr; GtkStyleContext *context; GdkRGBA color; PangoAttrList *attr_list; layout = gtk_widget_create_pango_layout (widget, NULL); context = gtk_widget_get_style_context (widget); gtk_style_context_get_color (context, GTK_STATE_FLAG_NORMAL, &color); attr = pango_attr_foreground_new (color.red * 65535, color.green * 65535, color.blue * 65535); attr->start_index = 0; attr->end_index = G_MAXINT; attr_list = pango_attr_list_new (); pango_attr_list_insert (attr_list, attr); renderer->priv->fg_attr = attr; renderer->priv->cached_layout = layout; renderer->priv->cached_attr_list = attr_list; }
static void create_cursor_attr() { if (attr_list) pango_attr_list_unref(attr_list); GdkColor color_bg, color_fg; if (hime_win_color_use) gdk_color_parse(tsin_cursor_color, &color_bg); else gdk_color_parse(TSIN_CURSOR_COLOR_DEFAULT, &color_bg); gdk_color_parse("white", &color_fg); attr_list = pango_attr_list_new (); attr_list_blank = pango_attr_list_new (); PangoAttribute *blue_bg = pango_attr_background_new( color_bg.red, color_bg.green, color_bg.blue); blue_bg->start_index = 0; blue_bg->end_index = 128; pango_attr_list_insert (attr_list, blue_bg); PangoAttribute *white_fg = pango_attr_foreground_new( color_fg.red, color_fg.green, color_fg.blue); white_fg->start_index = 0; white_fg->end_index = 128; pango_attr_list_insert (attr_list, white_fg); }
void LeftMargin::setupMargin(GtkTextView *textView) { if(!mMarginLayout) { GtkWidget *widget = GTK_WIDGET(textView); mMarginLayout = gtk_widget_create_pango_layout(widget, ""); updateTextInfo(textView); pango_layout_set_width(mMarginLayout, mTextWidth); pango_layout_set_alignment(mMarginLayout, PANGO_ALIGN_RIGHT); GtkStyleContext *widgetStyle = gtk_widget_get_style_context(widget); GdkRGBA color; gtk_style_context_get_color(widgetStyle, GTK_STATE_FLAG_NORMAL, &color); mMarginAttr = pango_attr_foreground_new(convertGdkColorToPango(color.red), convertGdkColorToPango(color.green), convertGdkColorToPango(color.blue)); mMarginAttrList = pango_attr_list_new(); mMarginAttr->start_index = 0; mMarginAttr->end_index = G_MAXUINT; pango_attr_list_insert(mMarginAttrList, mMarginAttr); pango_layout_set_attributes(mMarginLayout, mMarginAttrList); } }
static void match_label_color (GstyleColorWidget *self, GstyleColor *color) { PangoLayout *layout; PangoAttrList *attr_list; PangoAttribute *attr; GdkRGBA rgba; GdkRGBA dst_rgba; g_assert (GSTYLE_IS_COLOR_WIDGET (self)); g_assert (GSTYLE_IS_COLOR (color)); layout = gtk_label_get_layout (self->label); attr_list = pango_layout_get_attributes (layout); if (attr_list == NULL) { attr_list = pango_attr_list_new (); gtk_label_set_attributes (self->label, attr_list); pango_attr_list_unref (attr_list); } gstyle_color_fill_rgba (color, &rgba); gstyle_utils_get_contrasted_rgba (rgba, &dst_rgba); attr = pango_attr_foreground_new (dst_rgba.red * 0xffff, dst_rgba.green * 0xffff, dst_rgba.blue * 0xffff); pango_attr_list_change (attr_list, attr); attr = pango_attr_background_new (rgba.red * 0xffff, rgba.green * 0xffff, rgba.blue * 0xffff); pango_attr_list_change (attr_list, attr); }
bool OxLabel_SetTextColor(OxLabelObject* ox, int iRed, int iGreen, int iBlue) { PangoAttrList* pAL = pango_attr_list_new(); pango_attr_list_insert(pAL, pango_attr_foreground_new(iRed, iGreen, iBlue)); gtk_label_set_attributes(GTK_LABEL(ox->pGtk), pAL); return TRUE; }
static void set_fade (AboutRenderer *r, AboutState *state, double f) { GtkStyleContext *ctxt = gtk_widget_get_style_context (state->anim_area); PangoAttrList *attrlist = pango_layout_get_attributes (r->layout); GdkRGBA col, bg, fg; PangoAttribute *attr; gtk_style_context_get_color (ctxt, GTK_STATE_FLAG_NORMAL, &fg); gtk_style_context_get_background_color (ctxt, GTK_STATE_FLAG_NORMAL, &bg); col = blend_colors (&bg, &fg, f); attr = pango_attr_foreground_new (col.red * 65535., col.green * 65535., col.blue * 65535.); pango_attr_list_change (attrlist, attr); pango_layout_set_attributes (r->layout, attrlist); }
static void _mt_draw_string(MT_WINDOW *win, MT_STRING *str, int x_offset, int y_offset, MT_COLOR *color) { MT_GTK_STRING *s = str; PangoLayout *layout = s->layout; int state_type = s->state_type; if (!color && s->color) color = s->color; if (color && !pango_layout_get_text(layout)) color = NULL; if (color) { PangoAttrList *attrlist; PangoAttribute *attr; layout = pango_layout_copy(layout); attrlist = pango_layout_get_attributes(layout); if (attrlist) { pango_attr_list_ref(attrlist); } else { attrlist = pango_attr_list_new(); } if (color) { attr = pango_attr_foreground_new(color->r << 8, color->g << 8, color->b << 8); attr->start_index = 0; attr->end_index = strlen(pango_layout_get_text(layout)); pango_attr_list_insert_before(attrlist, attr); } pango_layout_set_attributes(layout, attrlist); pango_attr_list_unref(attrlist); state_type = GTK_STATE_NORMAL; } s->parent_class->draw_layout(s->style, (GdkWindow *)win, state_type, s->use_text, s->area, s->widget, s->detail, s->x + x_offset, s->y + y_offset, layout); if (color) { g_object_unref(layout); } }
/* * This function is used by gail_text_cell_get_offset_at_point() * and gail_text_cell_get_character_extents(). There is no * cached PangoLayout for gailtextcell so we must create a temporary * one using this function. */ static PangoLayout* create_pango_layout(GtkCellRendererText *gtk_renderer, GtkWidget *widget) { PangoAttrList *attr_list; PangoLayout *layout; PangoUnderline uline; PangoFontMask mask; layout = gtk_widget_create_pango_layout (widget, gtk_renderer->text); if (gtk_renderer->extra_attrs) attr_list = pango_attr_list_copy (gtk_renderer->extra_attrs); else attr_list = pango_attr_list_new (); if (gtk_renderer->foreground_set) { PangoColor color; color = gtk_renderer->foreground; add_attr (attr_list, pango_attr_foreground_new (color.red, color.green, color.blue)); } if (gtk_renderer->strikethrough_set) add_attr (attr_list, pango_attr_strikethrough_new (gtk_renderer->strikethrough)); mask = pango_font_description_get_set_fields (gtk_renderer->font); if (mask & PANGO_FONT_MASK_FAMILY) add_attr (attr_list, pango_attr_family_new (pango_font_description_get_family (gtk_renderer->font))); if (mask & PANGO_FONT_MASK_STYLE) add_attr (attr_list, pango_attr_style_new (pango_font_description_get_style (gtk_renderer->font))); if (mask & PANGO_FONT_MASK_VARIANT) add_attr (attr_list, pango_attr_variant_new (pango_font_description_get_variant (gtk_renderer->font))); if (mask & PANGO_FONT_MASK_WEIGHT) add_attr (attr_list, pango_attr_weight_new (pango_font_description_get_weight (gtk_renderer->font))); if (mask & PANGO_FONT_MASK_STRETCH) add_attr (attr_list, pango_attr_stretch_new (pango_font_description_get_stretch (gtk_renderer->font))); if (mask & PANGO_FONT_MASK_SIZE) add_attr (attr_list, pango_attr_size_new (pango_font_description_get_size (gtk_renderer->font))); if (gtk_renderer->scale_set && gtk_renderer->font_scale != 1.0) add_attr (attr_list, pango_attr_scale_new (gtk_renderer->font_scale)); if (gtk_renderer->underline_set) uline = gtk_renderer->underline_style; else uline = PANGO_UNDERLINE_NONE; if (uline != PANGO_UNDERLINE_NONE) add_attr (attr_list, pango_attr_underline_new (gtk_renderer->underline_style)); if (gtk_renderer->rise_set) add_attr (attr_list, pango_attr_rise_new (gtk_renderer->rise)); pango_layout_set_attributes (layout, attr_list); pango_layout_set_width (layout, -1); pango_attr_list_unref (attr_list); return layout; }
static gint line_numbers_expose (GtkWidget *widget, GdkEventExpose *event) { GtkTextView *text_view; GdkWindow *win; // GtkStyle *style; PangoLayout *layout; PangoAttrList *alist; PangoAttribute *attr; GArray *numbers; GArray *pixels; gint y1, y2; gint count; gint layout_width; gint justify_width = 0; gint i; // gchar *str; gchar str [8]; /* we don't expect more than ten million lines */ GdkGC *gc; gint height; if (line_number_visible){{{{{ // omit calculation text_view = GTK_TEXT_VIEW (widget); /* See if this expose is on the line numbers window */ /* left_win = gtk_text_view_get_window (text_view, GTK_TEXT_WINDOW_LEFT); right_win = gtk_text_view_get_window (text_view, GTK_TEXT_WINDOW_RIGHT); if (event->window == left_win) { type = GTK_TEXT_WINDOW_LEFT; target = event->window; } else if (event->window == right_win) { type = GTK_TEXT_WINDOW_RIGHT; target = right_win; } else return FALSE; */ win = gtk_text_view_get_window (text_view, GTK_TEXT_WINDOW_LEFT); if (event->window != win) return FALSE; // style = gtk_style_copy (widget->style); // style = gtk_style_copy (gtk_widget_get_default_style()); y1 = event->area.y; y2 = y1 + event->area.height; gtk_text_view_window_to_buffer_coords (text_view, GTK_TEXT_WINDOW_LEFT, 0, y1, NULL, &y1); gtk_text_view_window_to_buffer_coords (text_view, GTK_TEXT_WINDOW_LEFT, 0, y2, NULL, &y2); numbers = g_array_new (FALSE, FALSE, sizeof (gint)); pixels = g_array_new (FALSE, FALSE, sizeof (gint)); get_lines (text_view, y1, y2, pixels, numbers, &count); /* a zero-lined document should display a "1"; we don't need to worry about scrolling effects of the text widget in this special case */ if (count == 0) { gint y = 0; gint n = 0; count = 1; g_array_append_val (pixels, y); g_array_append_val (numbers, n); } DV({g_print("Painting line numbers %d - %d\n", g_array_index(numbers, gint, 0), g_array_index(numbers, gint, count - 1)); }); layout = gtk_widget_create_pango_layout (widget, ""); // str = g_strdup_printf ("%d", gtk_text_buffer_get_line_count(text_view->buffer)); g_snprintf (str, sizeof (str), "%d", MAX (99, gtk_text_buffer_get_line_count(text_view->buffer))); pango_layout_set_text (layout, str, -1); // g_free (str); pango_layout_get_pixel_size (layout, &layout_width, NULL); min_number_window_width = calculate_min_number_window_width(widget); if (layout_width > min_number_window_width) gtk_text_view_set_border_window_size (text_view, GTK_TEXT_WINDOW_LEFT, layout_width + margin + submargin); else { // if ((gtk_text_view_get_border_window_size (text_view, GTK_TEXT_WINDOW_LEFT) - 5) > layout_width) { gtk_text_view_set_border_window_size (text_view, GTK_TEXT_WINDOW_LEFT, min_number_window_width + margin + submargin); // } justify_width = min_number_window_width - layout_width; } pango_layout_set_width (layout, layout_width); pango_layout_set_alignment (layout, PANGO_ALIGN_RIGHT); alist = pango_attr_list_new(); attr = pango_attr_foreground_new( widget->style->text_aa->red, widget->style->text_aa->green, widget->style->text_aa->blue); attr->start_index = 0; attr->end_index = G_MAXUINT; pango_attr_list_insert(alist, attr); pango_layout_set_attributes(layout, alist); pango_attr_list_unref(alist); /* Draw fully internationalized numbers! */ i = 0; while (i < count) { gint pos; gtk_text_view_buffer_to_window_coords (text_view, GTK_TEXT_WINDOW_LEFT, 0, g_array_index (pixels, gint, i), NULL, &pos); // str = g_strdup_printf ("%d", g_array_index (numbers, gint, i) + 1); g_snprintf (str, sizeof (str), "%d", g_array_index (numbers, gint, i) + 1); pango_layout_set_text (layout, str, -1); gtk_paint_layout (widget->style, win, GTK_WIDGET_STATE (widget), FALSE, NULL, widget, NULL, #if GTK_CHECK_VERSION(2, 6, 0) // Is this solution??? layout_width + justify_width + margin / 2 + 1, #else layout_width + justify_width + margin / 2, #endif pos, layout); // g_free (str); ++i; } g_array_free (pixels, TRUE); g_array_free (numbers, TRUE); g_object_unref (G_OBJECT (layout)); // g_object_ref (G_OBJECT (style)); /* don't stop emission, need to draw children */ }}}}}
void scim_bridge_client_imcontext_set_preedit_attributes (ScimBridgeClientIMContext *imcontext, ScimBridgeAttribute** const preedit_attributes, int attribute_count) { if (imcontext->preedit_attributes != NULL) pango_attr_list_unref (imcontext->preedit_attributes); imcontext->preedit_attributes = pango_attr_list_new (); int preedit_string_length = 0; int preedit_wstring_length = 0; if (imcontext->preedit_string != NULL) { preedit_string_length = strlen (imcontext->preedit_string); preedit_wstring_length = g_utf8_strlen (imcontext->preedit_string, -1); } boolean *has_attribute = alloca (sizeof (boolean) * preedit_string_length); int i; for (i = 0; i < preedit_string_length; ++i) { has_attribute[i] = FALSE; } for (i = 0; i < attribute_count; ++i) { const ScimBridgeAttribute *attr = preedit_attributes[i]; const int begin_pos = scim_bridge_attribute_get_begin (attr); const int end_pos = scim_bridge_attribute_get_end (attr); if (begin_pos <= end_pos && 0 <= begin_pos && end_pos <= preedit_wstring_length) { const int start_index = g_utf8_offset_to_pointer (imcontext->preedit_string, begin_pos) - imcontext->preedit_string; const int end_index = g_utf8_offset_to_pointer (imcontext->preedit_string, end_pos) - imcontext->preedit_string; const scim_bridge_attribute_type_t attr_type = scim_bridge_attribute_get_type (attr); const scim_bridge_attribute_value_t attr_value = scim_bridge_attribute_get_value (attr); boolean valid_attribute = FALSE; if (attr_type == ATTRIBUTE_DECORATE) { if (attr_value == SCIM_BRIDGE_ATTRIBUTE_DECORATE_UNDERLINE) { valid_attribute = TRUE; PangoAttribute *pango_attr = pango_attr_underline_new (PANGO_UNDERLINE_SINGLE); pango_attr->start_index = start_index; pango_attr->end_index = end_index; pango_attr_list_insert (imcontext->preedit_attributes, pango_attr); } else if (attr_value == SCIM_BRIDGE_ATTRIBUTE_DECORATE_REVERSE) { valid_attribute = TRUE; PangoAttribute *pango_attr0 = pango_attr_foreground_new (preedit_normal_background.red, preedit_normal_background.green, preedit_normal_background.blue); pango_attr0->start_index = start_index; pango_attr0->end_index = end_index; pango_attr_list_insert (imcontext->preedit_attributes, pango_attr0); PangoAttribute *pango_attr1 = pango_attr_background_new (preedit_normal_foreground.red, preedit_normal_foreground.green, preedit_normal_foreground.blue); pango_attr1->start_index = start_index; pango_attr1->end_index = end_index; pango_attr_list_insert (imcontext->preedit_attributes, pango_attr1); } else if (attr_value == SCIM_BRIDGE_ATTRIBUTE_DECORATE_HIGHLIGHT) { valid_attribute = TRUE; PangoAttribute *pango_attr0 = pango_attr_foreground_new (preedit_active_foreground.red, preedit_active_foreground.green, preedit_active_foreground.blue); pango_attr0->start_index = start_index; pango_attr0->end_index = end_index; pango_attr_list_insert (imcontext->preedit_attributes, pango_attr0); PangoAttribute *pango_attr1 = pango_attr_background_new (preedit_active_background.red, preedit_active_background.green, preedit_active_background.blue); pango_attr1->start_index = start_index; pango_attr1->end_index = end_index; pango_attr_list_insert (imcontext->preedit_attributes, pango_attr1); } else { scim_bridge_perrorln ("Unknown preedit decoration!"); } } else if (attr_type == ATTRIBUTE_FOREGROUND) { valid_attribute = TRUE; const unsigned int red = scim_bridge_attribute_get_red (attr) * 256; const unsigned int green = scim_bridge_attribute_get_green (attr) * 256; const unsigned int blue = scim_bridge_attribute_get_blue (attr) * 256; PangoAttribute *pango_attr = pango_attr_foreground_new (red, green, blue); pango_attr->start_index = start_index; pango_attr->end_index = end_index; pango_attr_list_insert (imcontext->preedit_attributes, pango_attr); } else if (attr_type == ATTRIBUTE_BACKGROUND) { valid_attribute = TRUE; const unsigned int red = scim_bridge_attribute_get_red (attr) * 256; const unsigned int green = scim_bridge_attribute_get_green (attr) * 256; const unsigned int blue = scim_bridge_attribute_get_blue (attr) * 256; PangoAttribute *pango_attr = pango_attr_background_new (red, green, blue); pango_attr->start_index = start_index; pango_attr->end_index = end_index; pango_attr_list_insert (imcontext->preedit_attributes, pango_attr); } if (valid_attribute) { int j; for (j = start_index; j < end_index; ++j) { has_attribute[j] = TRUE; } } } } // Add underlines for the all characters without attributes. for (i = 0; i < preedit_string_length; ++i) { if (has_attribute[i] == FALSE) { PangoAttribute *pango_attr = pango_attr_underline_new (PANGO_UNDERLINE_SINGLE); pango_attr->start_index = i; for (; i < preedit_string_length && has_attribute[i] == FALSE; ++i); pango_attr->end_index = i; pango_attr_list_insert (imcontext->preedit_attributes, pango_attr); } } }
void init_attr_list() { letter_label_attr_list = pango_attr_list_new(); PangoAttribute *fcolor = pango_attr_foreground_new(0xffff, 0, 0); pango_attr_list_insert(letter_label_attr_list, fcolor); }
static void gm_cell_renderer_bitext_update_text (GmCellRendererBitext *renderer, GtkWidget *widget, gboolean is_selected) { GtkStyle *style = NULL; PangoAttrList *attr_list = NULL; GdkColor color; PangoAttribute *attr_color = NULL; PangoAttribute *attr_style = NULL; PangoAttribute *attr_size = NULL; gchar *str = NULL; if (renderer->priv->is_valid && renderer->priv->is_selected == is_selected) return; style = gtk_widget_get_style (widget); attr_list = pango_attr_list_new (); /* secondary text will be in italic */ attr_style = pango_attr_style_new (PANGO_STYLE_NORMAL); attr_style->start_index = strlen (renderer->priv->primary_text) + 1; attr_style->end_index = (guint) - 1; pango_attr_list_insert (attr_list, attr_style); if (!is_selected) { color = style->text_aa[GTK_STATE_NORMAL]; attr_color = pango_attr_foreground_new (color.red, color.green, color.blue); attr_color->start_index = attr_style->start_index; attr_color->end_index = (guint) - 1; pango_attr_list_insert (attr_list, attr_color); } attr_size = pango_attr_size_new ((int) (pango_font_description_get_size (style->font_desc) * 0.8)); /* we want the secondary text smaller */ attr_size->start_index = attr_style->start_index; attr_size->end_index = (guint) - 1; pango_attr_list_insert (attr_list, attr_size); if (renderer->priv->secondary_text && strcmp (renderer->priv->secondary_text, "")) str = g_strdup_printf ("%s\n%s", renderer->priv->primary_text, renderer->priv->secondary_text); else str = g_strdup_printf ("%s", renderer->priv->primary_text); g_object_set (renderer, "visible", TRUE, "weight", PANGO_WEIGHT_NORMAL, "text", str, "attributes", attr_list, NULL); g_free (str); pango_attr_list_unref (attr_list); renderer->priv->is_selected = is_selected; renderer->priv->is_valid = TRUE; }
bool wxFont::GTKSetPangoAttrs(PangoLayout* layout) const { if (!IsOk() || !(GetUnderlined() || GetStrikethrough())) return false; PangoAttrList* attrs = pango_attr_list_new(); PangoAttribute* a; if (wx_pango_version_check(1,16,0)) { // a PangoLayout which has leading/trailing spaces with underlined font // is not correctly drawn by this pango version: Pango won't underline the spaces. // This can be a problem; e.g. wxHTML rendering of underlined text relies on // this behaviour. To workaround this problem, we use a special hack here // suggested by pango maintainer Behdad Esfahbod: we prepend and append two // empty space characters and give them a dummy colour attribute. // This will force Pango to underline the leading/trailing spaces, too. const char* text = pango_layout_get_text(layout); const size_t n = strlen(text); if ((n > 0 && text[0] == ' ') || (n > 1 && text[n - 1] == ' ')) { wxCharBuffer buf(n + 6); // copy the leading U+200C ZERO WIDTH NON-JOINER encoded in UTF8 format memcpy(buf.data(), "\342\200\214", 3); // copy the user string memcpy(buf.data() + 3, text, n); // copy the trailing U+200C ZERO WIDTH NON-JOINER encoded in UTF8 format memcpy(buf.data() + 3 + n, "\342\200\214", 3); pango_layout_set_text(layout, buf, n + 6); // Add dummy attributes (use colour as it's invisible anyhow for 0 // width spaces) to ensure that the spaces in the beginning/end of the // string are underlined too. a = pango_attr_foreground_new(0x0057, 0x52A9, 0xD614); a->start_index = 0; a->end_index = 3; pango_attr_list_insert(attrs, a); a = pango_attr_foreground_new(0x0057, 0x52A9, 0xD614); a->start_index = n + 3; a->end_index = n + 6; pango_attr_list_insert(attrs, a); } } if (GetUnderlined()) { a = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE); pango_attr_list_insert(attrs, a); } if (GetStrikethrough()) { a = pango_attr_strikethrough_new(true); pango_attr_list_insert(attrs, a); } pango_layout_set_attributes(layout, attrs); pango_attr_list_unref(attrs); return true; }
static void cell_renderer_text_update_text (EmpathyCellRendererText *cell, GtkWidget *widget, gboolean selected) { EmpathyCellRendererTextPriv *priv; PangoAttrList *attr_list; PangoAttribute *attr_color, *attr_size; GtkStyle *style; gchar *str; priv = GET_PRIV (cell); if (priv->is_valid && priv->is_selected == selected) { return; } if (priv->is_group) { g_object_set (cell, "visible", TRUE, "weight", PANGO_WEIGHT_BOLD, "text", priv->name, "attributes", NULL, "xpad", 1, "ypad", 1, NULL); priv->is_selected = selected; priv->is_valid = TRUE; return; } style = gtk_widget_get_style (widget); attr_list = pango_attr_list_new (); attr_size = pango_attr_size_new (pango_font_description_get_size (style->font_desc) / 1.2); attr_size->start_index = strlen (priv->name) + 1; attr_size->end_index = -1; pango_attr_list_insert (attr_list, attr_size); if (!selected) { GdkColor color; color = style->text_aa[GTK_STATE_NORMAL]; attr_color = pango_attr_foreground_new (color.red, color.green, color.blue); attr_color->start_index = attr_size->start_index; attr_color->end_index = -1; pango_attr_list_insert (attr_list, attr_color); } if (!priv->status || !priv->status[0] || !priv->show_status) { str = g_strdup (priv->name); } else { str = g_strdup_printf ("%s\n%s", priv->name, priv->status); } g_object_set (cell, "visible", TRUE, "weight", PANGO_WEIGHT_NORMAL, "text", str, "attributes", attr_list, "xpad", 0, "ypad", 1, NULL); g_free (str); pango_attr_list_unref (attr_list); priv->is_selected = selected; priv->is_valid = TRUE; }
static void draw_page(GtkPrintOperation *operation, GtkPrintContext *context, gint page_nr, gpointer user_data) { DocInfo *dinfo = user_data; GeanyEditor *editor; cairo_t *cr; gdouble width, height; gdouble x = 0.0, y = 0.0; /*gint layout_h;*/ gint count; GString *str; if (dinfo == NULL || page_nr >= dinfo->n_pages) return; editor = dinfo->doc->editor; if (dinfo->n_pages > 0) { gdouble fraction = (page_nr + 1) / (gdouble) dinfo->n_pages; gchar *text = g_strdup_printf(_("Page %d of %d"), page_nr, dinfo->n_pages); gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(main_widgets.progressbar), fraction); gtk_progress_bar_set_text(GTK_PROGRESS_BAR(main_widgets.progressbar), text); g_free(text); } #ifdef GEANY_PRINT_DEBUG geany_debug("draw_page = %d, pages = %d, (real) lines_per_page = %d", page_nr, dinfo->n_pages, dinfo->lines_per_page); #endif str = g_string_sized_new(256); cr = gtk_print_context_get_cairo_context(context); width = gtk_print_context_get_width(context); height = gtk_print_context_get_height(context); cairo_set_source_rgb(cr, 0, 0, 0); #ifdef GEANY_PRINT_DEBUG cairo_set_line_width(cr, 0.2); cairo_rectangle(cr, 0, 0, width, height); cairo_stroke(cr); #endif cairo_move_to(cr, 0, 0); pango_layout_set_width(dinfo->layout, width * PANGO_SCALE); pango_layout_set_alignment(dinfo->layout, PANGO_ALIGN_LEFT); pango_layout_set_ellipsize(dinfo->layout, FALSE); pango_layout_set_justify(dinfo->layout, FALSE); if (printing_prefs.print_page_header) add_page_header(dinfo, cr, width, page_nr); count = 0; /* the actual line counter for the current page, might be different from * dinfo->cur_line due to possible line breaks */ while (count < dinfo->lines_per_page) { gchar c = 'a'; gint style = -1; PangoAttrList *layout_attr; PangoAttribute *attr; gint colours[3] = { 0 }; gboolean add_linenumber = TRUE; gboolean at_eol; while (count < dinfo->lines_per_page && c != '\0') { at_eol = FALSE; g_string_erase(str, 0, str->len); /* clear the string */ /* line numbers */ if (printing_prefs.print_line_numbers && add_linenumber) { /* if we had a wrapped line on the last page which needs to be continued, don't * add a line number */ if (dinfo->long_line) { add_linenumber = FALSE; } else { gchar *line_number = NULL; gint cur_line_number_margin = get_line_numbers_arity(dinfo->cur_line + 1); gchar *fill = g_strnfill( dinfo->max_line_number_margin - cur_line_number_margin - 1, ' '); line_number = g_strdup_printf("%s%d ", fill, dinfo->cur_line + 1); g_string_append(str, line_number); dinfo->cur_line++; /* increase document line */ add_linenumber = FALSE; style = STYLE_LINENUMBER; c = 'a'; /* dummy value */ g_free(fill); g_free(line_number); } } /* data */ else { style = sci_get_style_at(dinfo->doc->editor->sci, dinfo->cur_pos); c = sci_get_char_at(dinfo->doc->editor->sci, dinfo->cur_pos); if (c == '\0' || style == -1) { /* if c gets 0, we are probably out of document boundaries, * so stop to break out of outer loop */ count = dinfo->lines_per_page; break; } dinfo->cur_pos++; /* convert tabs to spaces which seems to be better than using Pango tabs */ if (c == '\t') { gint tab_width = sci_get_tab_width(editor->sci); gchar *s = g_strnfill(tab_width, ' '); g_string_append(str, s); g_free(s); } /* don't add line breaks, they are handled manually below */ else if (c == '\r' || c == '\n') { gchar c_next = sci_get_char_at(dinfo->doc->editor->sci, dinfo->cur_pos); at_eol = TRUE; if (c == '\r' && c_next == '\n') dinfo->cur_pos++; /* skip LF part of CR/LF */ } else { g_string_append_c(str, c); /* finally add the character */ /* handle UTF-8: since we add char by char (better: byte by byte), we need to * keep UTF-8 characters together(e.g. two bytes for one character) * the input is always UTF-8 and c is signed, so all non-Ascii * characters are less than 0 and consist of all bytes less than 0. * style doesn't change since it is only one character with multiple bytes. */ while (c < 0) { c = sci_get_char_at(dinfo->doc->editor->sci, dinfo->cur_pos); if (c < 0) { /* only add the byte when it is part of the UTF-8 character * otherwise we could add e.g. a '\n' and it won't be visible in the * printed document */ g_string_append_c(str, c); dinfo->cur_pos++; } } } } if (! at_eol) { /* set text */ pango_layout_set_text(dinfo->layout, str->str, -1); /* attributes */ layout_attr = pango_attr_list_new(); /* foreground colour */ get_rgb_values(dinfo->styles[style][FORE], &colours[0], &colours[1], &colours[2]); attr = pango_attr_foreground_new(colours[0], colours[1], colours[2]); ADD_ATTR(layout_attr, attr); /* background colour */ get_rgb_values(dinfo->styles[style][BACK], &colours[0], &colours[1], &colours[2]); attr = pango_attr_background_new(colours[0], colours[1], colours[2]); ADD_ATTR(layout_attr, attr); /* bold text */ if (dinfo->styles[style][BOLD]) { attr = pango_attr_weight_new(PANGO_WEIGHT_BOLD); ADD_ATTR(layout_attr, attr); } /* italic text */ if (dinfo->styles[style][ITALIC]) { attr = pango_attr_style_new(PANGO_STYLE_ITALIC); ADD_ATTR(layout_attr, attr); } pango_layout_set_attributes(dinfo->layout, layout_attr); pango_layout_context_changed(dinfo->layout); pango_attr_list_unref(layout_attr); } cairo_get_current_point(cr, &x, &y); /* normal line break at eol character in document */ if (at_eol) { /*pango_layout_get_size(dinfo->layout, NULL, &layout_h);*/ /*cairo_move_to(cr, 0, y + (gdouble)layout_h / PANGO_SCALE);*/ cairo_move_to(cr, 0, y + dinfo->line_height); count++; /* we added a new document line so request a new line number */ add_linenumber = TRUE; } else { gint x_offset = 0; /* maybe we need to force a line break because of too long line */ if (x >= (width - dinfo->font_width)) { /* don't start the line at horizontal origin because we need to skip the * line number margin */ if (printing_prefs.print_line_numbers) { x_offset = (dinfo->max_line_number_margin + 1) * dinfo->font_width; } /*pango_layout_get_size(dinfo->layout, NULL, &layout_h);*/ /*cairo_move_to(cr, x_offset, y + (gdouble)layout_h / PANGO_SCALE);*/ /* this is faster but not exactly the same as above */ cairo_move_to(cr, x_offset, y + dinfo->line_height); cairo_get_current_point(cr, &x, &y); count++; } if (count < dinfo->lines_per_page) { /* str->len is counted in bytes not characters, so use g_utf8_strlen() */ x_offset = (g_utf8_strlen(str->str, -1) * dinfo->font_width); if (dinfo->long_line && count == 0) { x_offset = (dinfo->max_line_number_margin + 1) * dinfo->font_width; dinfo->long_line = FALSE; } pango_cairo_show_layout(cr, dinfo->layout); cairo_move_to(cr, x + x_offset, y); } else /* we are on a wrapped line but we are out of lines on this page, so continue * the current line on the next page and remember to continue in current line */ dinfo->long_line = TRUE; } } } if (printing_prefs.print_line_numbers) { /* print a thin line between the line number margin and the data */ gint y_start = 0; if (printing_prefs.print_page_header) y_start = (dinfo->line_height * 3) - 2; /* "- 2": to connect the line number line to * the page header frame */ cairo_set_line_width(cr, 0.3); cairo_move_to(cr, (dinfo->max_line_number_margin * dinfo->font_width) + 1, y_start); cairo_line_to(cr, (dinfo->max_line_number_margin * dinfo->font_width) + 1, y + dinfo->line_height); /* y is last added line, we reuse it */ cairo_stroke(cr); } if (printing_prefs.print_page_numbers) { gchar *line = g_strdup_printf("<small>- %d -</small>", page_nr + 1); pango_layout_set_markup(dinfo->layout, line, -1); pango_layout_set_alignment(dinfo->layout, PANGO_ALIGN_CENTER); cairo_move_to(cr, 0, height - dinfo->line_height); pango_cairo_show_layout(cr, dinfo->layout); g_free(line); #ifdef GEANY_PRINT_DEBUG cairo_set_line_width(cr, 0.3); cairo_move_to(cr, 0, height - (1.25 * dinfo->line_height)); cairo_line_to(cr, width - 1, height - (1.25 * dinfo->line_height)); cairo_stroke(cr); #endif } g_string_free(str, TRUE); }
static gboolean span_parse_func (MarkupData *md, OpenTag *tag, const gchar **names, const gchar **values, GMarkupParseContext *context, GError **error) { int line_number, char_number; int i; const char *family = NULL; const char *size = NULL; const char *style = NULL; const char *weight = NULL; const char *variant = NULL; const char *stretch = NULL; const char *desc = NULL; const char *foreground = NULL; const char *background = NULL; const char *underline = NULL; const char *underline_color = NULL; const char *strikethrough = NULL; const char *strikethrough_color = NULL; const char *rise = NULL; const char *letter_spacing = NULL; const char *lang = NULL; const char *fallback = NULL; const char *gravity = NULL; const char *gravity_hint = NULL; g_markup_parse_context_get_position (context, &line_number, &char_number); #define CHECK_DUPLICATE(var) G_STMT_START{ \ if ((var) != NULL) { \ g_set_error (error, G_MARKUP_ERROR, \ G_MARKUP_ERROR_INVALID_CONTENT, \ _("Attribute '%s' occurs twice on <span> tag " \ "on line %d char %d, may only occur once"), \ names[i], line_number, char_number); \ return FALSE; \ }}G_STMT_END #define CHECK_ATTRIBUTE2(var, name) \ if (attr_strcmp (names[i], (name)) == 0) { \ CHECK_DUPLICATE (var); \ (var) = values[i]; \ found = TRUE; \ break; \ } #define CHECK_ATTRIBUTE(var) CHECK_ATTRIBUTE2 (var, G_STRINGIFY (var)) i = 0; while (names[i]) { gboolean found = FALSE; switch (names[i][0]) { case 'f': CHECK_ATTRIBUTE (fallback); CHECK_ATTRIBUTE2(desc, "font"); CHECK_ATTRIBUTE2(desc, "font_desc"); CHECK_ATTRIBUTE2(family, "face"); CHECK_ATTRIBUTE2(family, "font_family"); CHECK_ATTRIBUTE2(size, "font_size"); CHECK_ATTRIBUTE2(stretch, "font_stretch"); CHECK_ATTRIBUTE2(style, "font_style"); CHECK_ATTRIBUTE2(variant, "font_variant"); CHECK_ATTRIBUTE2(weight, "font_weight"); CHECK_ATTRIBUTE (foreground); CHECK_ATTRIBUTE2 (foreground, "fgcolor"); break; case 's': CHECK_ATTRIBUTE (size); CHECK_ATTRIBUTE (stretch); CHECK_ATTRIBUTE (strikethrough); CHECK_ATTRIBUTE (strikethrough_color); CHECK_ATTRIBUTE (style); break; case 'g': CHECK_ATTRIBUTE (gravity); CHECK_ATTRIBUTE (gravity_hint); break; case 'l': CHECK_ATTRIBUTE (lang); CHECK_ATTRIBUTE (letter_spacing); break; case 'u': CHECK_ATTRIBUTE (underline); CHECK_ATTRIBUTE (underline_color); break; default: CHECK_ATTRIBUTE (background); CHECK_ATTRIBUTE2 (background, "bgcolor"); CHECK_ATTRIBUTE2(foreground, "color"); CHECK_ATTRIBUTE (rise); CHECK_ATTRIBUTE (variant); CHECK_ATTRIBUTE (weight); break; } if (!found) { g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE, _("Attribute '%s' is not allowed on the <span> tag " "on line %d char %d"), names[i], line_number, char_number); return FALSE; } ++i; } /* Parse desc first, then modify it with other font-related attributes. */ if (G_UNLIKELY (desc)) { PangoFontDescription *parsed; parsed = pango_font_description_from_string (desc); if (parsed) { add_attribute (tag, pango_attr_font_desc_new (parsed)); if (tag) open_tag_set_absolute_font_size (tag, pango_font_description_get_size (parsed)); pango_font_description_free (parsed); } } if (G_UNLIKELY (family)) { add_attribute (tag, pango_attr_family_new (family)); } if (G_UNLIKELY (size)) { if (g_ascii_isdigit (*size)) { const char *end; gint n; /* cap size from the top at an arbitrary 2048 */ #define MAX_SIZE (2048 * PANGO_SCALE) if ((end = size, !pango_scan_int (&end, &n)) || *end != '\0' || n < 0 || n > MAX_SIZE) { g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, _("Value of 'size' attribute on <span> tag on line %d " "could not be parsed; should be an integer less than %d, or a " "string such as 'small', not '%s'"), line_number, MAX_SIZE+1, size); goto error; } add_attribute (tag, pango_attr_size_new (n)); if (tag) open_tag_set_absolute_font_size (tag, n); } else if (strcmp (size, "smaller") == 0) { if (tag) { tag->scale_level_delta -= 1; tag->scale_level -= 1; } } else if (strcmp (size, "larger") == 0) { if (tag) { tag->scale_level_delta += 1; tag->scale_level += 1; } } else if (parse_absolute_size (tag, size)) ; /* nothing */ else { g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, _("Value of 'size' attribute on <span> tag on line %d " "could not be parsed; should be an integer, or a " "string such as 'small', not '%s'"), line_number, size); goto error; } } if (G_UNLIKELY (style)) { PangoStyle pango_style; if (pango_parse_style (style, &pango_style, FALSE)) add_attribute (tag, pango_attr_style_new (pango_style)); else { g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, _("'%s' is not a valid value for the 'style' attribute " "on <span> tag, line %d; valid values are " "'normal', 'oblique', 'italic'"), style, line_number); goto error; } } if (G_UNLIKELY (weight)) { PangoWeight pango_weight; if (pango_parse_weight (weight, &pango_weight, FALSE)) add_attribute (tag, pango_attr_weight_new (pango_weight)); else { g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, _("'%s' is not a valid value for the 'weight' " "attribute on <span> tag, line %d; valid " "values are for example 'light', 'ultrabold' or a number"), weight, line_number); goto error; } } if (G_UNLIKELY (variant)) { PangoVariant pango_variant; if (pango_parse_variant (variant, &pango_variant, FALSE)) add_attribute (tag, pango_attr_variant_new (pango_variant)); else { g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, _("'%s' is not a valid value for the 'variant' " "attribute on <span> tag, line %d; valid values are " "'normal', 'smallcaps'"), variant, line_number); goto error; } } if (G_UNLIKELY (stretch)) { PangoStretch pango_stretch; if (pango_parse_stretch (stretch, &pango_stretch, FALSE)) add_attribute (tag, pango_attr_stretch_new (pango_stretch)); else { g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, _("'%s' is not a valid value for the 'stretch' " "attribute on <span> tag, line %d; valid " "values are for example 'condensed', " "'ultraexpanded', 'normal'"), stretch, line_number); goto error; } } if (G_UNLIKELY (foreground)) { PangoColor color; if (!span_parse_color ("foreground", foreground, &color, line_number, error)) goto error; add_attribute (tag, pango_attr_foreground_new (color.red, color.green, color.blue)); } if (G_UNLIKELY (background)) { PangoColor color; if (!span_parse_color ("background", background, &color, line_number, error)) goto error; add_attribute (tag, pango_attr_background_new (color.red, color.green, color.blue)); } if (G_UNLIKELY (underline)) { PangoUnderline ul = PANGO_UNDERLINE_NONE; if (!span_parse_enum ("underline", underline, PANGO_TYPE_UNDERLINE, &ul, line_number, error)) goto error; add_attribute (tag, pango_attr_underline_new (ul)); } if (G_UNLIKELY (underline_color)) { PangoColor color; if (!span_parse_color ("underline_color", underline_color, &color, line_number, error)) goto error; add_attribute (tag, pango_attr_underline_color_new (color.red, color.green, color.blue)); } if (G_UNLIKELY (gravity)) { PangoGravity gr = PANGO_GRAVITY_SOUTH; if (!span_parse_enum ("gravity", gravity, PANGO_TYPE_GRAVITY, &gr, line_number, error)) goto error; add_attribute (tag, pango_attr_gravity_new (gr)); } if (G_UNLIKELY (gravity_hint)) { PangoGravityHint hint = PANGO_GRAVITY_HINT_NATURAL; if (!span_parse_enum ("gravity_hint", gravity_hint, PANGO_TYPE_GRAVITY_HINT, &hint, line_number, error)) goto error; add_attribute (tag, pango_attr_gravity_hint_new (hint)); } if (G_UNLIKELY (strikethrough)) { gboolean b = FALSE; if (!span_parse_boolean ("strikethrough", strikethrough, &b, line_number, error)) goto error; add_attribute (tag, pango_attr_strikethrough_new (b)); } if (G_UNLIKELY (strikethrough_color)) { PangoColor color; if (!span_parse_color ("strikethrough_color", strikethrough_color, &color, line_number, error)) goto error; add_attribute (tag, pango_attr_strikethrough_color_new (color.red, color.green, color.blue)); } if (G_UNLIKELY (fallback)) { gboolean b = FALSE; if (!span_parse_boolean ("fallback", fallback, &b, line_number, error)) goto error; add_attribute (tag, pango_attr_fallback_new (b)); } if (G_UNLIKELY (rise)) { gint n = 0; if (!span_parse_int ("rise", rise, &n, line_number, error)) goto error; add_attribute (tag, pango_attr_rise_new (n)); } if (G_UNLIKELY (letter_spacing)) { gint n = 0; if (!span_parse_int ("letter_spacing", letter_spacing, &n, line_number, error)) goto error; add_attribute (tag, pango_attr_letter_spacing_new (n)); } if (G_UNLIKELY (lang)) { add_attribute (tag, pango_attr_language_new (pango_language_from_string (lang))); } return TRUE; error: return FALSE; }
static void text_entry_update_layout(struct text_entry *entry) { char *text; PangoAttrList *attr_list; assert(entry->cursor <= (strlen(entry->text) + (entry->preedit.text ? strlen(entry->preedit.text) : 0))); if (entry->preedit.text) { text = malloc(strlen(entry->text) + strlen(entry->preedit.text) + 1); strncpy(text, entry->text, entry->cursor); strcpy(text + entry->cursor, entry->preedit.text); strcpy(text + entry->cursor + strlen(entry->preedit.text), entry->text + entry->cursor); } else { text = strdup(entry->text); } if (entry->cursor != entry->anchor) { int start_index = MIN(entry->cursor, entry->anchor); int end_index = MAX(entry->cursor, entry->anchor); PangoAttribute *attr; attr_list = pango_attr_list_copy(entry->preedit.attr_list); if (!attr_list) attr_list = pango_attr_list_new(); attr = pango_attr_background_new(0.3 * 65535, 0.3 * 65535, 65535); attr->start_index = start_index; attr->end_index = end_index; pango_attr_list_insert(attr_list, attr); attr = pango_attr_foreground_new(65535, 65535, 65535); attr->start_index = start_index; attr->end_index = end_index; pango_attr_list_insert(attr_list, attr); } else { attr_list = pango_attr_list_ref(entry->preedit.attr_list); } if (entry->preedit.text && !entry->preedit.attr_list) { PangoAttribute *attr; if (!attr_list) attr_list = pango_attr_list_new(); attr = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE); attr->start_index = entry->cursor; attr->end_index = entry->cursor + strlen(entry->preedit.text); pango_attr_list_insert(attr_list, attr); } if (entry->layout) { pango_layout_set_text(entry->layout, text, -1); pango_layout_set_attributes(entry->layout, attr_list); } free(text); pango_attr_list_unref(attr_list); }
static PangoAttrList* hildon_font_selection_dialog_create_attrlist (HildonFontSelectionDialog *fontsel, guint start_index, guint len) { PangoAttrList *list; PangoAttribute *attr; gint size, position; gboolean family_set, size_set, color_set, bold, bold_set, italic, italic_set, underline, underline_set, strikethrough, strikethrough_set, position_set; GdkColor *color = NULL; gchar *family = NULL; gdouble font_scaling = 1.0; list = pango_attr_list_new (); g_object_get (G_OBJECT (fontsel), "family", &family, "family-set", &family_set, "size", &size, "size-set", &size_set, "color", &color, "color-set", &color_set, "bold", &bold, "bold-set", &bold_set, "italic", &italic, "italic-set", &italic_set, "underline", &underline, "underline-set", &underline_set, "strikethrough", &strikethrough, "strikethrough-set", &strikethrough_set, "position", &position, "position-set", &position_set, "font-scaling", &font_scaling, NULL); /* family */ if (family_set) { attr = pango_attr_family_new (family); add_preview_text_attr (list, attr, start_index, len); } g_free (family); /* size */ if (size_set) { attr = pango_attr_size_new (size * PANGO_SCALE); add_preview_text_attr (list, attr, start_index, len); } /*color*/ if (color_set) { attr = pango_attr_foreground_new (color->red, color->green, color->blue); add_preview_text_attr (list, attr, start_index, len); } if (color != NULL) gdk_color_free (color); /*weight*/ if (bold_set) { if (bold) attr = pango_attr_weight_new (PANGO_WEIGHT_BOLD); else attr = pango_attr_weight_new (PANGO_WEIGHT_NORMAL); add_preview_text_attr(list, attr, start_index, len); } /* style */ if (italic_set) { if (italic) attr = pango_attr_style_new (PANGO_STYLE_ITALIC); else attr = pango_attr_style_new (PANGO_STYLE_NORMAL); add_preview_text_attr(list, attr, start_index, len); } /* underline */ if (underline_set) { if (underline) attr = pango_attr_underline_new (PANGO_UNDERLINE_SINGLE); else attr = pango_attr_underline_new (PANGO_UNDERLINE_NONE); add_preview_text_attr(list, attr, start_index, len); } /* strikethrough */ if (strikethrough_set) { if (strikethrough) attr = pango_attr_strikethrough_new (TRUE); else attr = pango_attr_strikethrough_new (FALSE); add_preview_text_attr(list, attr, start_index, len); } /* position */ if (position_set) { switch (position) { case 1: /*super*/ attr = pango_attr_rise_new (SUPERSCRIPT_RISE); break; case -1: /*sub*/ attr = pango_attr_rise_new (SUBSCRIPT_LOW); break; default: /*normal*/ attr = pango_attr_rise_new (0); break; } add_preview_text_attr (list, attr, start_index, len); } /* font scaling for preview */ if (font_scaling) { attr = pango_attr_scale_new(font_scaling); add_preview_text_attr(list, attr, 0, len + start_index); } return list; }
/** * gimp_label_set_attributes: * @label: a #GtkLabel * @...: a list of PangoAttrType and value pairs terminated by -1. * * Sets Pango attributes on a #GtkLabel in a more convenient way than * gtk_label_set_attributes(). * * This function is useful if you want to change the font attributes * of a #GtkLabel. This is an alternative to using PangoMarkup which * is slow to parse and akward to handle in an i18n-friendly way. * * The attributes are set on the complete label, from start to end. If * you need to set attributes on part of the label, you will have to * use the PangoAttributes API directly. * * Since: 2.2 **/ void gimp_label_set_attributes (GtkLabel *label, ...) { PangoAttribute *attr = NULL; PangoAttrList *attrs; va_list args; g_return_if_fail (GTK_IS_LABEL (label)); attrs = pango_attr_list_new (); va_start (args, label); do { PangoAttrType attr_type = va_arg (args, PangoAttrType); if (attr_type == -1) attr_type = PANGO_ATTR_INVALID; switch (attr_type) { case PANGO_ATTR_LANGUAGE: attr = pango_attr_language_new (va_arg (args, PangoLanguage *)); break; case PANGO_ATTR_FAMILY: attr = pango_attr_family_new (va_arg (args, const gchar *)); break; case PANGO_ATTR_STYLE: attr = pango_attr_style_new (va_arg (args, PangoStyle)); break; case PANGO_ATTR_WEIGHT: attr = pango_attr_weight_new (va_arg (args, PangoWeight)); break; case PANGO_ATTR_VARIANT: attr = pango_attr_variant_new (va_arg (args, PangoVariant)); break; case PANGO_ATTR_STRETCH: attr = pango_attr_stretch_new (va_arg (args, PangoStretch)); break; case PANGO_ATTR_SIZE: attr = pango_attr_size_new (va_arg (args, gint)); break; case PANGO_ATTR_FONT_DESC: attr = pango_attr_font_desc_new (va_arg (args, const PangoFontDescription *)); break; case PANGO_ATTR_FOREGROUND: { const PangoColor *color = va_arg (args, const PangoColor *); attr = pango_attr_foreground_new (color->red, color->green, color->blue); } break; case PANGO_ATTR_BACKGROUND: { const PangoColor *color = va_arg (args, const PangoColor *); attr = pango_attr_background_new (color->red, color->green, color->blue); } break; case PANGO_ATTR_UNDERLINE: attr = pango_attr_underline_new (va_arg (args, PangoUnderline)); break; case PANGO_ATTR_STRIKETHROUGH: attr = pango_attr_strikethrough_new (va_arg (args, gboolean)); break; case PANGO_ATTR_RISE: attr = pango_attr_rise_new (va_arg (args, gint)); break; case PANGO_ATTR_SCALE: attr = pango_attr_scale_new (va_arg (args, gdouble)); break; default: g_warning ("%s: invalid PangoAttribute type %d", G_STRFUNC, attr_type); case PANGO_ATTR_INVALID: attr = NULL; break; } if (attr) { attr->start_index = 0; attr->end_index = -1; pango_attr_list_insert (attrs, attr); } } while (attr); va_end (args); gtk_label_set_attributes (label, attrs); pango_attr_list_unref (attrs); }
static void decorate_text (GimpAboutDialog *dialog, gint anim_type, gdouble time) { GtkStyle *style = gtk_widget_get_style (dialog->anim_area); const gchar *text; const gchar *ptr; gint letter_count = 0; gint text_length = 0; gint text_bytelen = 0; gint cluster_start, cluster_end; gunichar unichr; PangoAttrList *attrlist = NULL; PangoAttribute *attr; PangoRectangle irect = {0, 0, 0, 0}; PangoRectangle lrect = {0, 0, 0, 0}; GdkColor mix; mix_colors (style->bg + GTK_STATE_NORMAL, style->fg + GTK_STATE_NORMAL, &mix, time); text = pango_layout_get_text (dialog->layout); g_return_if_fail (text != NULL); text_length = g_utf8_strlen (text, -1); text_bytelen = strlen (text); attrlist = pango_attr_list_new (); dialog->textrange[0] = 0; dialog->textrange[1] = text_bytelen; switch (anim_type) { case 0: /* Fade in */ attr = pango_attr_foreground_new (mix.red, mix.green, mix.blue); attr->start_index = 0; attr->end_index = text_bytelen; pango_attr_list_insert (attrlist, attr); break; case 1: /* Fade in, spread */ attr = pango_attr_foreground_new (mix.red, mix.green, mix.blue); attr->start_index = 0; attr->end_index = text_bytelen; pango_attr_list_change (attrlist, attr); ptr = text; cluster_start = 0; while ((unichr = g_utf8_get_char (ptr))) { ptr = g_utf8_next_char (ptr); cluster_end = (ptr - text); if (unichr == 0x200b) { lrect.width = (1.0 - time) * 15.0 * PANGO_SCALE + 0.5; attr = pango_attr_shape_new (&irect, &lrect); attr->start_index = cluster_start; attr->end_index = cluster_end; pango_attr_list_change (attrlist, attr); } cluster_start = cluster_end; } break; case 2: /* Fade in, sinewave */ attr = pango_attr_foreground_new (mix.red, mix.green, mix.blue); attr->start_index = 0; attr->end_index = text_bytelen; pango_attr_list_change (attrlist, attr); ptr = text; cluster_start = 0; while ((unichr = g_utf8_get_char (ptr))) { if (unichr == 0x200b) { cluster_end = ptr - text; attr = pango_attr_rise_new ((1.0 -time) * 18000 * sin (4.0 * time + (float) letter_count * 0.7)); attr->start_index = cluster_start; attr->end_index = cluster_end; pango_attr_list_change (attrlist, attr); letter_count++; cluster_start = cluster_end; } ptr = g_utf8_next_char (ptr); } break; case 3: /* letterwise Fade in */ ptr = text; letter_count = 0; cluster_start = 0; while ((unichr = g_utf8_get_char (ptr))) { gint border = (text_length + 15) * time - 15; gdouble pos; if (letter_count < border) pos = 0; else if (letter_count > border + 15) pos = 1; else pos = ((gdouble) (letter_count - border)) / 15; mix_colors (style->fg + GTK_STATE_NORMAL, style->bg + GTK_STATE_NORMAL, &mix, pos); ptr = g_utf8_next_char (ptr); cluster_end = ptr - text; attr = pango_attr_foreground_new (mix.red, mix.green, mix.blue); attr->start_index = cluster_start; attr->end_index = cluster_end; pango_attr_list_change (attrlist, attr); if (pos < 1.0) dialog->textrange[1] = cluster_end; letter_count++; cluster_start = cluster_end; } break; default: g_printerr ("Unknown animation type %d\n", anim_type); } pango_layout_set_attributes (dialog->layout, attrlist); pango_attr_list_unref (attrlist); }
/* This function is used by gtk_text_cell_accessible_get_offset_at_point() * and gtk_text_cell_accessible_get_character_extents(). There is no * cached PangoLayout so we must create a temporary one using this function. */ static PangoLayout * create_pango_layout (GtkTextCellAccessible *text) { GdkRGBA *foreground_rgba; PangoAttrList *attr_list, *attributes; PangoLayout *layout; PangoUnderline uline, underline; PangoFontMask mask; PangoFontDescription *font_desc; gboolean foreground_set, strikethrough_set, strikethrough; gboolean scale_set, underline_set, rise_set; gchar *renderer_text; gdouble scale; gint rise; GtkRendererCellAccessible *gail_renderer; GtkCellRendererText *gtk_renderer; gail_renderer = GTK_RENDERER_CELL_ACCESSIBLE (text); gtk_renderer = GTK_CELL_RENDERER_TEXT (gail_renderer->renderer); g_object_get (gtk_renderer, "text", &renderer_text, "attributes", &attributes, "foreground-set", &foreground_set, "foreground-rgba", &foreground_rgba, "strikethrough-set", &strikethrough_set, "strikethrough", &strikethrough, "font-desc", &font_desc, "scale-set", &scale_set, "scale", &scale, "underline-set", &underline_set, "underline", &underline, "rise-set", &rise_set, "rise", &rise, NULL); layout = gtk_widget_create_pango_layout (get_widget (text), renderer_text); if (attributes) attr_list = pango_attr_list_copy (attributes); else attr_list = pango_attr_list_new (); if (foreground_set) { add_attr (attr_list, pango_attr_foreground_new (foreground_rgba->red * 65535, foreground_rgba->green * 65535, foreground_rgba->blue * 65535)); } if (strikethrough_set) add_attr (attr_list, pango_attr_strikethrough_new (strikethrough)); mask = pango_font_description_get_set_fields (font_desc); if (mask & PANGO_FONT_MASK_FAMILY) add_attr (attr_list, pango_attr_family_new (pango_font_description_get_family (font_desc))); if (mask & PANGO_FONT_MASK_STYLE) add_attr (attr_list, pango_attr_style_new (pango_font_description_get_style (font_desc))); if (mask & PANGO_FONT_MASK_VARIANT) add_attr (attr_list, pango_attr_variant_new (pango_font_description_get_variant (font_desc))); if (mask & PANGO_FONT_MASK_WEIGHT) add_attr (attr_list, pango_attr_weight_new (pango_font_description_get_weight (font_desc))); if (mask & PANGO_FONT_MASK_STRETCH) add_attr (attr_list, pango_attr_stretch_new (pango_font_description_get_stretch (font_desc))); if (mask & PANGO_FONT_MASK_SIZE) add_attr (attr_list, pango_attr_size_new (pango_font_description_get_size (font_desc))); if (scale_set && scale != 1.0) add_attr (attr_list, pango_attr_scale_new (scale)); if (underline_set) uline = underline; else uline = PANGO_UNDERLINE_NONE; if (uline != PANGO_UNDERLINE_NONE) add_attr (attr_list, pango_attr_underline_new (underline)); if (rise_set) add_attr (attr_list, pango_attr_rise_new (rise)); pango_layout_set_attributes (layout, attr_list); pango_layout_set_width (layout, -1); pango_attr_list_unref (attr_list); pango_font_description_free (font_desc); pango_attr_list_unref (attributes); g_free (renderer_text); gdk_rgba_free (foreground_rgba); return layout; }
static void _fcitx_im_context_update_formatted_preedit_cb(FcitxClient* im, GPtrArray* array, int cursor_pos, void* user_data) { FcitxLog(LOG_LEVEL, "_fcitx_im_context_commit_string_cb"); FcitxIMContext* context = FCITX_IM_CONTEXT(user_data); gboolean visible = false; if (context->preedit_string != NULL) { if (strlen(context->preedit_string) != 0) visible = true; g_free(context->preedit_string); context->preedit_string = NULL; } if (context->attrlist != NULL) { pango_attr_list_unref(context->attrlist); } context->attrlist = pango_attr_list_new(); GString* gstr = g_string_new(NULL); int i = 0; for (i = 0; i < array->len; i++) { size_t bytelen = strlen(gstr->str); FcitxPreeditItem* preedit = g_ptr_array_index(array, i); const gchar* s = preedit->string; gint type = preedit->type; PangoAttribute *pango_attr = NULL; if ((type & MSG_NOUNDERLINE) == 0) { pango_attr = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE); pango_attr->start_index = bytelen; pango_attr->end_index = bytelen + strlen(s); pango_attr_list_insert(context->attrlist, pango_attr); } if (type & MSG_HIGHLIGHT) { gboolean hasColor; GdkColor fg; GdkColor bg; if (context->client_window) { GtkWidget *widget; gdk_window_get_user_data (context->client_window, (gpointer *)&widget); if (GTK_IS_WIDGET(widget)) { hasColor = true; GtkStyle* style = gtk_widget_get_style(widget); fg = style->text[GTK_STATE_SELECTED]; bg = style->bg[GTK_STATE_SELECTED]; } } if (!hasColor) { fg.red = 0xffff; fg.green = 0xffff; fg.blue = 0xffff; bg.red = 0x43ff; bg.green = 0xacff; bg.blue = 0xe8ff; } pango_attr = pango_attr_foreground_new(fg.red, fg.green, fg.blue); pango_attr->start_index = bytelen; pango_attr->end_index = bytelen + strlen(s); pango_attr_list_insert(context->attrlist, pango_attr); pango_attr = pango_attr_background_new(bg.red, bg.green, bg.blue); pango_attr->start_index = bytelen; pango_attr->end_index = bytelen + strlen(s); pango_attr_list_insert(context->attrlist, pango_attr); } gstr = g_string_append(gstr, s); } gchar* str = g_string_free(gstr, FALSE); context->preedit_string = g_strdup(str); char* tempstr = g_strndup(str, cursor_pos); context->cursor_pos = fcitx_utf8_strlen(tempstr); g_free(tempstr); gboolean new_visible = false; if (context->preedit_string != NULL) { if (strlen(context->preedit_string) != 0) new_visible = true; } gboolean flag = new_visible != visible; if (new_visible) { if (flag) { /* invisible => visible */ g_signal_emit(context, _signal_preedit_start_id, 0); } g_signal_emit(context, _signal_preedit_changed_id, 0); } else { if (flag) { /* visible => invisible */ g_signal_emit(context, _signal_preedit_changed_id, 0); g_signal_emit(context, _signal_preedit_end_id, 0); } else { /* still invisible */ /* do nothing */ } } g_signal_emit(context, _signal_preedit_changed_id, 0); }