static void gtk_switch_get_preferred_width (GtkWidget *widget, gint *minimum, gint *natural) { GtkStyleContext *context; GtkStateFlags state; GtkBorder padding; gint width, slider_width, focus_width, focus_pad; PangoLayout *layout; PangoRectangle logical_rect; context = gtk_widget_get_style_context (widget); state = gtk_style_context_get_state (context); gtk_style_context_save (context); gtk_style_context_add_class (context, GTK_STYLE_CLASS_SLIDER); gtk_style_context_get_padding (context, state, &padding); width = padding.left + padding.right; gtk_style_context_restore (context); gtk_widget_style_get (widget, "slider-width", &slider_width, "focus-line-width", &focus_width, "focus-padding", &focus_pad, NULL); slider_width = MAX (slider_width, 3 * (focus_width + focus_pad)); /* Translators: if the "on" state label requires more than three * glyphs then use MEDIUM VERTICAL BAR (U+2759) as the text for * the state */ layout = gtk_widget_create_pango_layout (widget, C_("switch", "ON")); pango_layout_get_extents (layout, NULL, &logical_rect); pango_extents_to_pixels (&logical_rect, NULL); width += MAX (logical_rect.width, slider_width); /* Translators: if the "off" state label requires more than three * glyphs then use WHITE CIRCLE (U+25CB) as the text for the state */ pango_layout_set_text (layout, C_("switch", "OFF"), -1); pango_layout_get_extents (layout, NULL, &logical_rect); pango_extents_to_pixels (&logical_rect, NULL); width += MAX (logical_rect.width, slider_width); g_object_unref (layout); if (minimum) *minimum = width; if (natural) *natural = width; }
static void font_measure_full(const RrFont *f, const gchar *str, gint *x, gint *y, gint shadow_x, gint shadow_y, gboolean flow, gint maxwidth) { PangoRectangle rect; pango_layout_set_text(f->layout, str, -1); if (flow) { pango_layout_set_single_paragraph_mode(f->layout, FALSE); pango_layout_set_width(f->layout, maxwidth * PANGO_SCALE); pango_layout_set_ellipsize(f->layout, PANGO_ELLIPSIZE_NONE); } else { /* single line mode */ pango_layout_set_single_paragraph_mode(f->layout, TRUE); pango_layout_set_width(f->layout, -1); pango_layout_set_ellipsize(f->layout, PANGO_ELLIPSIZE_MIDDLE); } /* pango_layout_get_pixel_extents lies! this is the right way to get the size of the text's area */ pango_layout_get_extents(f->layout, NULL, &rect); #if PANGO_VERSION_MAJOR > 1 || \ (PANGO_VERSION_MAJOR == 1 && PANGO_VERSION_MINOR >= 16) /* pass the logical rect as the ink rect, this is on purpose so we get the full area for the text */ pango_extents_to_pixels(&rect, NULL); #else rect.width = (rect.width + PANGO_SCALE - 1) / PANGO_SCALE; rect.height = (rect.height + PANGO_SCALE - 1) / PANGO_SCALE; #endif *x = rect.width + ABS(shadow_x) + 4 /* we put a 2 px edge on each side */; *y = rect.height + ABS(shadow_y); }
void ge_cairo_transform_for_layout (cairo_t *cr, PangoLayout *layout, int x, int y) { const PangoMatrix *matrix; matrix = pango_context_get_matrix (pango_layout_get_context (layout)); if (matrix) { cairo_matrix_t cairo_matrix; PangoRectangle rect; cairo_matrix_init (&cairo_matrix, matrix->xx, matrix->yx, matrix->xy, matrix->yy, matrix->x0, matrix->y0); pango_layout_get_extents (layout, NULL, &rect); pango_matrix_transform_rectangle (matrix, &rect); pango_extents_to_pixels (&rect, NULL); cairo_matrix.x0 += x - rect.x; cairo_matrix.y0 += y - rect.y; cairo_set_matrix (cr, &cairo_matrix); } else cairo_translate (cr, x, y); }
/* Draws a rounded rectangle with text inside. */ static gboolean numbers_draw_cb (GtkWidget *widget, cairo_t *ctx, gpointer data) { double x, y, w, h; PangoLayout * layout; gint font_size = gtk_widget_get_font_size (widget); #if (INDICATOR_MESSAGES_HAS_LOZENGE == 1) gboolean is_lozenge = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "is-lozenge")); /* let the label handle the drawing if it's not a lozenge */ if (!is_lozenge) return FALSE; #endif if (!GTK_IS_WIDGET (widget)) return FALSE; /* get style + arrow position / dimensions */ double red, green, blue; GtkStyleContext *style = gtk_widget_get_style_context (widget); GdkRGBA color; gtk_style_context_get_color (style, gtk_widget_get_state(widget), &color); red = color.red; green = color.green; blue = color.blue; GtkAllocation allocation; gtk_widget_get_allocation (widget, &allocation); w = allocation.width; h = allocation.height; x = y = 0; layout = gtk_label_get_layout (GTK_LABEL(widget)); PangoRectangle layout_extents; pango_layout_get_extents (layout, NULL, &layout_extents); pango_extents_to_pixels (&layout_extents, NULL); if (layout_extents.width == 0) return TRUE; cairo_set_line_width (ctx, 1.0); cairo_set_fill_rule (ctx, CAIRO_FILL_RULE_EVEN_ODD); /* cairo drawing code */ custom_cairo_rounded_rectangle (ctx, x - font_size/2.0, y, w + font_size, h); cairo_set_source_rgba (ctx, red, green, blue, 0.5); x += (allocation.width - layout_extents.width) / 2.0; y += (allocation.height - layout_extents.height) / 2.0; cairo_move_to (ctx, floor (x), floor (y)); pango_cairo_layout_path (ctx, layout); cairo_fill (ctx); return TRUE; }
static void ensure_measurements (GcrDisplayView *self) { PangoLayout *layout; PangoRectangle extents; gint icon_width; gint icon_height; GHashTableIter iter; GcrDisplayItem *item; gpointer value; gboolean expanded; if (self->pv->have_measurements) return; /* See if anything is expanded? */ expanded = FALSE; g_hash_table_iter_init (&iter, self->pv->items); while (g_hash_table_iter_next (&iter, NULL, &value)) { item = value; if (item->expanded) { expanded = TRUE; break; } } /* * We use a string in our widget font as the basis for our measurements. * These are just estimates of what we need, and what looks goodish. * There's room here for improvement. If this is causes problems for * you or bothers you, scratch that itch: */ layout = gtk_widget_create_pango_layout (GTK_WIDGET (self), "0123456789"); pango_layout_get_extents (layout, NULL, &extents); pango_extents_to_pixels (&extents, NULL); g_object_unref (layout); if (!gtk_icon_size_lookup (GTK_ICON_SIZE_DIALOG, &icon_width, &icon_height)) { icon_width = 48; icon_height = 48; } if (expanded) { /* If expanded, display more 10 lines at least */ self->pv->minimal_height = extents.height * 14; self->pv->natural_height = extents.height * 25; } else { /* If not expanded we can get by with 9 lines */ self->pv->minimal_height = extents.height * 8; self->pv->natural_height = extents.height * 9; } self->pv->minimal_width = icon_width + (extents.width * 5); self->pv->natural_width = icon_width + (extents.width * 8); self->pv->have_measurements = TRUE; }
void _gcr_display_view_append_value (GcrDisplayView *self, GcrRenderer *renderer, const gchar *field, const gchar *value, gboolean monospace) { GcrDisplayItem *item; PangoRectangle extents; PangoTabArray *tabs; PangoLayout *layout; GtkTextIter iter; gchar *text; g_return_if_fail (GCR_IS_DISPLAY_VIEW (self)); g_return_if_fail (field); item = lookup_display_item (self, renderer); g_return_if_fail (item); if (item->details && !item->expanded) return; text = g_strdup_printf ("%s:", field); if (value == NULL) value = ""; /* Measure the width of the field */ layout = gtk_widget_create_pango_layout (GTK_WIDGET (self), text); pango_layout_get_extents (layout, NULL, &extents); pango_extents_to_pixels (&extents, NULL); g_object_unref (layout); /* Make the tab wide enough to accomodate */ if (extents.width > item->field_width) { item->field_width = extents.width + COLUMN_MARGIN; tabs = pango_tab_array_new (1, TRUE); pango_tab_array_set_tab (tabs, 0, PANGO_TAB_LEFT, item->field_width); g_object_set (item->field_tag, "left-margin", FIELD_MARGIN, "indent", 0 - item->field_width, "tabs", tabs, NULL); pango_tab_array_free (tabs); } gtk_text_buffer_get_iter_at_mark (self->pv->buffer, &iter, item->ending); gtk_text_buffer_insert_with_tags (self->pv->buffer, &iter, text, -1, item->field_tag, item->extra_tag, NULL); gtk_text_buffer_insert_with_tags (self->pv->buffer, &iter, "\t", 1, item->extra_tag, NULL); gtk_text_buffer_insert_with_tags (self->pv->buffer, &iter, value, -1, item->field_tag, monospace ? self->pv->monospace_tag : item->extra_tag, monospace ? item->extra_tag : NULL, NULL); gtk_text_buffer_insert_with_tags (self->pv->buffer, &iter, "\n", 1, item->extra_tag, NULL); g_free (text); }
static void gtk_switch_get_preferred_height (GtkWidget *widget, gint *minimum, gint *natural) { GtkSwitchPrivate *priv = GTK_SWITCH (widget)->priv; GtkStyleContext *context; GtkStateFlags state; GtkBorder padding; gint height, focus_width, focus_pad; PangoLayout *layout; PangoRectangle logical_rect; gchar *str; context = gtk_widget_get_style_context (widget); state = gtk_widget_get_state_flags (widget); if (priv->is_active) state |= GTK_STATE_FLAG_ACTIVE; gtk_style_context_save (context); gtk_style_context_set_state (context, state); gtk_style_context_add_class (context, GTK_STYLE_CLASS_SLIDER); gtk_style_context_get_padding (context, state, &padding); height = padding.top + padding.bottom; gtk_style_context_restore (context); gtk_widget_style_get (widget, "focus-line-width", &focus_width, "focus-padding", &focus_pad, NULL); height += 2 * (focus_width + focus_pad); str = g_strdup_printf ("%s%s", C_("switch", "ON"), C_("switch", "OFF")); layout = gtk_widget_create_pango_layout (widget, str); pango_layout_get_extents (layout, NULL, &logical_rect); pango_extents_to_pixels (&logical_rect, NULL); height += MAX (DEFAULT_SLIDER_HEIGHT, logical_rect.height); g_object_unref (layout); g_free (str); if (minimum) *minimum = height; if (natural) *natural = height; }
Rect TextRenderer::RawCursorPos() { Pango::Rectangle w_rct, s_rct; panLay->get_cursor_pos(ByteCursorPos(), w_rct, s_rct); pango_extents_to_pixels(0, w_rct.gobj()); double curs_rat = CursAspectRatio(); int curs_wdh = int(w_rct.get_height()*curs_rat + 1); int curs_lft = w_rct.get_x() - curs_wdh/2; return Rect(curs_lft, w_rct.get_y(), curs_lft + curs_wdh, w_rct.get_y() + w_rct.get_height()); }
static void gtk_switch_get_preferred_height (GtkWidget *widget, gint *minimum, gint *natural) { GtkStyleContext *context; GtkStateFlags state; GtkBorder padding; gint height, focus_width, focus_pad, slider_width, min_height; PangoLayout *layout; PangoRectangle logical_rect; gchar *str; context = gtk_widget_get_style_context (widget); state = gtk_style_context_get_state (context); gtk_style_context_save (context); gtk_style_context_add_class (context, GTK_STYLE_CLASS_SLIDER); gtk_style_context_get_padding (context, state, &padding); height = padding.top + padding.bottom; gtk_style_context_restore (context); gtk_widget_style_get (widget, "slider-width", &slider_width, "focus-line-width", &focus_width, "focus-padding", &focus_pad, NULL); min_height = MAX (slider_width * 0.6, 3 * (focus_width + focus_pad)); str = g_strdup_printf ("%s%s", C_("switch", "ON"), C_("switch", "OFF")); layout = gtk_widget_create_pango_layout (widget, str); pango_layout_get_extents (layout, NULL, &logical_rect); pango_extents_to_pixels (&logical_rect, NULL); height += MAX (min_height, logical_rect.height); g_object_unref (layout); g_free (str); if (minimum) *minimum = height; if (natural) *natural = height; }
bool PangoFontInfo::GetSpacingProperties(const string& utf8_char, int* x_bearing, int* x_advance) const { // Convert to equivalent PangoFont structure PangoFont* font = ToPangoFont(); // Find the glyph index in the font for the supplied utf8 character. int total_advance = 0; int min_bearing = 0; // Handle multi-unicode strings by reporting the left-most position of the // x-bearing, and right-most position of the x-advance if the string were to // be rendered. const UNICHAR::const_iterator it_begin = UNICHAR::begin(utf8_char.c_str(), utf8_char.length()); const UNICHAR::const_iterator it_end = UNICHAR::end(utf8_char.c_str(), utf8_char.length()); for (UNICHAR::const_iterator it = it_begin; it != it_end; ++it) { PangoGlyph glyph_index = pango_fc_font_get_glyph( reinterpret_cast<PangoFcFont*>(font), *it); if (!glyph_index) { // Glyph for given unicode character doesn't exist in font. return false; } // Find the ink glyph extents for the glyph PangoRectangle ink_rect, logical_rect; pango_font_get_glyph_extents(font, glyph_index, &ink_rect, &logical_rect); pango_extents_to_pixels(&ink_rect, NULL); pango_extents_to_pixels(&logical_rect, NULL); int bearing = total_advance + PANGO_LBEARING(ink_rect); if (it == it_begin || bearing < min_bearing) { min_bearing = bearing; } total_advance += PANGO_RBEARING(logical_rect); } *x_bearing = min_bearing; *x_advance = total_advance; return true; }
static void gtk_label_accessible_get_character_extents (AtkText *text, gint offset, gint *x, gint *y, gint *width, gint *height, AtkCoordType coords) { GtkWidget *widget; GtkLabel *label; PangoRectangle char_rect; const gchar *label_text; gint index, x_layout, y_layout; GdkWindow *window; gint x_window, y_window; widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text)); if (widget == NULL) return; label = GTK_LABEL (widget); gtk_label_get_layout_offsets (label, &x_layout, &y_layout); label_text = gtk_label_get_text (label); index = g_utf8_offset_to_pointer (label_text, offset) - label_text; pango_layout_index_to_pos (gtk_label_get_layout (label), index, &char_rect); pango_extents_to_pixels (&char_rect, NULL); window = gtk_widget_get_window (widget); gdk_window_get_origin (window, &x_window, &y_window); *x = x_window + x_layout + char_rect.x; *y = x_window + y_layout + char_rect.y; *width = char_rect.width; *height = char_rect.height; if (coords == ATK_XY_WINDOW) { window = gdk_window_get_toplevel (window); gdk_window_get_origin (window, &x_window, &y_window); *x -= x_window; *y -= y_window; } }
static void append_field_and_value (GcrCertificateDetailsWidget *self, const gchar *field, const gchar *value, gboolean monospace) { PangoRectangle extents; PangoTabArray *tabs; PangoLayout *layout; GtkTextIter iter; gchar *text; text = g_strdup_printf ("%s:", field); if (value == NULL) value = ""; /* Measure the width of the field */ layout = gtk_widget_create_pango_layout (GTK_WIDGET (self), text); pango_layout_get_extents (layout, NULL, &extents); pango_extents_to_pixels (&extents, NULL); g_object_unref (layout); /* Make the tab wide enough to accomodate */ if (extents.width > self->pv->field_width) { self->pv->field_width = extents.width + COLUMN_MARGIN; tabs = pango_tab_array_new (1, TRUE); pango_tab_array_set_tab (tabs, 0, PANGO_TAB_LEFT, self->pv->field_width); g_object_set (self->pv->field_tag, "left-margin", FIELD_MARGIN, "indent", 0 - self->pv->field_width, "tabs", tabs, NULL); pango_tab_array_free (tabs); } gtk_text_buffer_get_end_iter (self->pv->buffer, &iter); gtk_text_buffer_insert_with_tags_by_name (self->pv->buffer, &iter, text, -1, "field", NULL); gtk_text_buffer_insert (self->pv->buffer, &iter, "\t", 1); gtk_text_buffer_insert_with_tags_by_name (self->pv->buffer, &iter, value, -1, "field", monospace ? "monospace" : NULL, NULL); gtk_text_buffer_insert (self->pv->buffer, &iter, "\n", 1); g_free (text); }
static gboolean gtk_switch_draw (GtkWidget *widget, cairo_t *cr) { GtkSwitchPrivate *priv = GTK_SWITCH (widget)->priv; GtkStyleContext *context; GdkRectangle handle; PangoLayout *layout; PangoRectangle rect; gint label_x, label_y; GtkBorder padding; GtkStateFlags state; gint x, y, width, height; context = gtk_widget_get_style_context (widget); state = gtk_widget_get_state_flags (widget); gtk_style_context_save (context); gtk_style_context_add_class (context, GTK_STYLE_CLASS_SLIDER); gtk_style_context_get_padding (context, state, &padding); gtk_style_context_restore (context); x = 0; y = 0; width = gtk_widget_get_allocated_width (widget); height = gtk_widget_get_allocated_height (widget); gtk_style_context_save (context); gtk_style_context_add_class (context, GTK_STYLE_CLASS_TROUGH); gtk_render_background (context, cr, x, y, width, height); gtk_render_frame (context, cr, x, y, width, height); width -= padding.left + padding.right; height -= padding.top + padding.bottom; x += padding.left; y += padding.top; handle.y = y; handle.width = width / 2; handle.height = height; /* Translators: if the "on" state label requires more than three * glyphs then use MEDIUM VERTICAL BAR (U+2759) as the text for * the state */ layout = gtk_widget_create_pango_layout (widget, C_("switch", "ON")); pango_layout_get_extents (layout, NULL, &rect); pango_extents_to_pixels (&rect, NULL); label_x = x + ((width / 2) - rect.width) / 2; label_y = y + (height - rect.height) / 2; gtk_render_layout (context, cr, label_x, label_y, layout); g_object_unref (layout); /* Translators: if the "off" state label requires more than three * glyphs then use WHITE CIRCLE (U+25CB) as the text for the state */ layout = gtk_widget_create_pango_layout (widget, C_("switch", "OFF")); pango_layout_get_extents (layout, NULL, &rect); pango_extents_to_pixels (&rect, NULL); label_x = x + (width / 2) + ((width / 2) - rect.width) / 2; label_y = y + (height - rect.height) / 2; gtk_render_layout (context, cr, label_x, label_y, layout); g_object_unref (layout); if (priv->is_dragging) handle.x = x + priv->handle_x; else if (priv->is_active) handle.x = x + width - handle.width; else handle.x = x; gtk_style_context_restore (context); gtk_switch_paint_handle (widget, cr, &handle); if (gtk_widget_has_visible_focus (widget)) { gint focus_width, focus_pad, pad; gtk_widget_style_get (widget, "focus-line-width", &focus_width, "focus-padding", &focus_pad, NULL); pad = focus_pad + focus_width; gtk_render_focus (context, cr, handle.x + pad, handle.y + pad, handle.width - pad*2, handle.height - pad*2); } return FALSE; }
static void draw_text (Cairo::RefPtr<Cairo::Context> cr, int wdh, int hgt) { RefPtr<Pango::Layout> layout = Pango::Layout::create(cr); //layout->set_single_paragraph_mode(true); layout->set_text("MTextTextM\nAbc\nff"); Pango::FontDescription dsc(FONT); layout->set_font_description(dsc); int t_wdh, t_hgt; layout->get_size(t_wdh, t_hgt); double t_sz = (double)dsc.get_size()/t_wdh; double new_sz = wdh * t_sz ; io::cout << "new_sz " << new_sz << io::endl; io::cout << "wdh " << wdh << io::endl; dsc.set_size( int(new_sz*PANGO_SCALE) ); layout->set_font_description(dsc); layout->get_size(t_wdh, t_hgt); io::cout << "t_wdh " << t_wdh/(double)PANGO_SCALE << io::endl; // для наглядности cr->set_line_width(1.0); cr->rectangle(0, 0, wdh, hgt); cr->stroke(); cr->save(); cr->move_to(0, 0); cr->scale( 1.0, hgt / ((double)t_hgt/PANGO_SCALE) ); //cr->scale( wdh / ((double)t_wdh/PANGO_SCALE), hgt / ((double)t_hgt/PANGO_SCALE) ); layout->update_from_cairo_context(cr); pango_cairo_show_layout(cr->cobj(), layout->gobj()); { Pango::Rectangle w_rct, s_rct; int cur_pos; cur_pos = 1; layout->get_cursor_pos(cur_pos, w_rct, s_rct); pango_extents_to_pixels(0, w_rct.gobj()); io::cout << "curs - x, y, hgt " << w_rct.get_x() << " " << w_rct.get_y() << " " << w_rct.get_height() << io::endl; cr->move_to(w_rct.get_x()+5, w_rct.get_y()); cr->line_to(w_rct.get_x()+5, w_rct.get_y()+w_rct.get_height()); cr->stroke(); cur_pos = 11; layout->get_cursor_pos(cur_pos, w_rct, s_rct); pango_extents_to_pixels(0, w_rct.gobj()); io::cout << "curs - x, y, hgt " << w_rct.get_x() << " " << w_rct.get_y() << " " << w_rct.get_height() << io::endl; cr->move_to(w_rct.get_x()+5, w_rct.get_y()); cr->line_to(w_rct.get_x()+5, w_rct.get_y()+w_rct.get_height()); cr->stroke(); } cr->restore(); }
static gboolean gtk_switch_draw (GtkWidget *widget, cairo_t *cr) { GtkSwitchPrivate *priv = GTK_SWITCH (widget)->priv; GtkStyleContext *context; GdkRectangle handle; PangoLayout *layout; PangoFontDescription *desc; const PangoFontDescription *style_desc; PangoRectangle rect; gint label_x, label_y; GtkStateFlags state; GtkBorder padding; gint focus_width, focus_pad; gint x, y, width, height; gint font_size, style_font_size; gtk_widget_style_get (widget, "focus-line-width", &focus_width, "focus-padding", &focus_pad, NULL); context = gtk_widget_get_style_context (widget); state = gtk_widget_get_state_flags (widget); if (priv->is_active) state |= GTK_STATE_FLAG_ACTIVE; gtk_style_context_save (context); gtk_style_context_set_state (context, state); gtk_style_context_add_class (context, GTK_STYLE_CLASS_SLIDER); gtk_style_context_get_padding (context, state, &padding); gtk_style_context_restore (context); x = 0; y = 0; width = gtk_widget_get_allocated_width (widget); height = gtk_widget_get_allocated_height (widget); if (gtk_widget_has_focus (widget)) gtk_render_focus (context, cr, x, y, width, height); x += focus_width + focus_pad; y += focus_width + focus_pad; width -= 2 * (focus_width + focus_pad); height -= 2 * (focus_width + focus_pad); gtk_style_context_save (context); gtk_style_context_add_class (context, GTK_STYLE_CLASS_TROUGH); gtk_style_context_set_state (context, state); gtk_render_background (context, cr, x, y, width, height); gtk_render_frame (context, cr, x, y, width, height); width -= padding.left + padding.right; height -= padding.top + padding.bottom; x += padding.left; y += padding.top; handle.y = y; handle.width = width / 2; handle.height = height; /* Translators: if the "on" state label requires more than three * glyphs then use MEDIUM VERTICAL BAR (U+2759) as the text for * the state */ layout = gtk_widget_create_pango_layout (widget, C_("switch", "ON")); /* FIXME: this should be really done in the theme, but overriding font size * from it doesn't currently work. So we have to hardcode this here and * below for the "OFF" label. */ desc = pango_font_description_new (); style_desc = gtk_style_context_get_font (context, state); style_font_size = pango_font_description_get_size (style_desc); font_size = MAX (style_font_size - 1 * PANGO_SCALE, ceil (style_font_size * PANGO_SCALE_SMALL)); pango_font_description_set_size (desc, font_size); pango_layout_set_font_description (layout, desc); pango_layout_get_extents (layout, NULL, &rect); pango_extents_to_pixels (&rect, NULL); label_x = x + ((width / 2) - rect.width) / 2; label_y = y + (height - rect.height) / 2; gtk_render_layout (context, cr, label_x, label_y, layout); g_object_unref (layout); /* Translators: if the "off" state label requires more than three * glyphs then use WHITE CIRCLE (U+25CB) as the text for the state */ layout = gtk_widget_create_pango_layout (widget, C_("switch", "OFF")); pango_layout_set_font_description (layout, desc); pango_layout_get_extents (layout, NULL, &rect); pango_extents_to_pixels (&rect, NULL); label_x = x + (width / 2) + ((width / 2) - rect.width) / 2; label_y = y + (height - rect.height) / 2; gtk_render_layout (context, cr, label_x, label_y, layout); g_object_unref (layout); if (priv->is_dragging) handle.x = x + priv->handle_x; else if (priv->is_active) handle.x = x + width - handle.width; else handle.x = x; gtk_style_context_restore (context); gtk_switch_paint_handle (widget, cr, &handle); pango_font_description_free (desc); return FALSE; }
static gboolean gtk_switch_draw (GtkWidget *widget, cairo_t *cr) { GtkSwitchPrivate *priv = GTK_SWITCH (widget)->priv; GtkStyleContext *context; GdkRectangle handle; PangoLayout *layout; PangoRectangle rect; gint label_x, label_y; GtkStateFlags state; GtkBorder padding; gint focus_width, focus_pad; gint x, y, width, height; gtk_widget_style_get (widget, "focus-line-width", &focus_width, "focus-padding", &focus_pad, NULL); context = gtk_widget_get_style_context (widget); state = gtk_widget_get_state_flags (widget); if (priv->is_active) state |= GTK_STATE_FLAG_ACTIVE; gtk_style_context_get_padding (context, state, &padding); x = 0; y = 0; width = gtk_widget_get_allocated_width (widget); height = gtk_widget_get_allocated_height (widget); if (gtk_widget_has_focus (widget)) gtk_render_focus (context, cr, x, y, width, height); gtk_style_context_save (context); gtk_style_context_set_state (context, state); x += focus_width + focus_pad; y += focus_width + focus_pad; width -= 2 * (focus_width + focus_pad); height -= 2 * (focus_width + focus_pad); gtk_style_context_add_class (context, GTK_STYLE_CLASS_TROUGH); gtk_render_background (context, cr, x, y, width, height); gtk_render_frame (context, cr, x, y, width, height); /* XXX the +1/-1 it's pixel wriggling after checking with the default * theme and xmag */ handle.y = y + padding.top + 1; handle.width = (width - padding.left - padding.right) / 2; handle.height = (height - padding.top - padding.bottom) - 1; /* Translators: if the "on" state label requires more than three * glyphs then use MEDIUM VERTICAL BAR (U+2759) as the text for * the state */ layout = gtk_widget_create_pango_layout (widget, C_("switch", "ON")); pango_layout_get_extents (layout, NULL, &rect); pango_extents_to_pixels (&rect, NULL); label_x = x + padding.left + ((width / 2) - rect.width - padding.left - padding.right) / 2; label_y = y + padding.top + (height - rect.height - padding.top - padding.bottom) / 2; gtk_render_layout (context, cr, label_x, label_y, layout); g_object_unref (layout); /* Translators: if the "off" state label requires more than three * glyphs then use WHITE CIRCLE (U+25CB) as the text for the state */ layout = gtk_widget_create_pango_layout (widget, C_("switch", "OFF")); pango_layout_get_extents (layout, NULL, &rect); pango_extents_to_pixels (&rect, NULL); label_x = x + padding.left + (width / 2) + ((width / 2) - rect.width - padding.left - padding.right) / 2; label_y = y + padding.top + (height - rect.height - padding.top - padding.bottom) / 2; gtk_render_layout (context, cr, label_x, label_y, layout); g_object_unref (layout); if (priv->is_dragging) handle.x = x + priv->handle_x; else if (priv->is_active) handle.x = x + width - handle.width - padding.right; else handle.x = x + padding.left; gtk_style_context_restore (context); gtk_switch_paint_handle (widget, cr, &handle); return FALSE; }
void doDrawGlyphs(PangoRenderer* renderer, PangoFont* font, PangoGlyphString* glyphs, int px, int py) { Renderer* ren = RENDERER(renderer); if (!ren->m_runs) return; std::vector<ViewdoTextRun>& runs = *(ren->m_runs); const float s = ren->m_scale; PangoColor* fg = pango_renderer_get_color(renderer, PANGO_RENDER_PART_FOREGROUND); //PangoColor* bg = pango_renderer_get_color(renderer, PANGO_RENDER_PART_BACKGROUND); float red = !fg ? 0.0f : fg->red / 65536.0f; float green = !fg ? 0.0f : fg->green / 65536.0f; float blue = !fg ? 0.0f : fg->blue / 65536.0f; PangoFontDescription* desc = pango_font_describe(font); unsigned int fontHash = pango_font_description_hash(desc); pango_font_description_free(desc); FT_Face face = pango_fc_font_lock_face((PangoFcFont*) font); PangoGlyphUnit layoutX = px; PangoGlyphUnit layoutY = py; ViewdoGlyphCache& cache = ViewdoGlyphCache::instance(); for (int i = 0; i < glyphs->num_glyphs; i++) { PangoGlyphInfo* gi = glyphs->glyphs + i; if (gi->glyph & PANGO_GLYPH_UNKNOWN_FLAG) { // XXX: Draw the fallback square. continue; } unsigned int glyph = gi->glyph; PangoRectangle r; pango_font_get_glyph_extents(font, glyph, &r, 0); pango_extents_to_pixels(&r, 0); float w = r.width; float h = r.height; if (w <= 0.f && h <= 0.f) { // Space. layoutX += gi->geometry.width; continue; } // Load and render the glyph. We probably need to just tell the font to cache it // and then grab the coordinates of it. const ViewdoGlyph& cachedGlyph = cache.findOrCreate(gi->glyph, fontHash, face); // Walk our existing runs and try to find one with the same color and page. // XXX: Fastpath try and use the run from the last glyph. ViewdoTextRun* run = nullptr; for (auto i = runs.begin(); i != runs.end(); i++) { if (i->m_page == cachedGlyph.m_page && i->m_red == red && i->m_green == green && i->m_blue == blue) { run = &(*i); break; } } if (!run) { runs.push_back(ViewdoTextRun(cachedGlyph.m_page, red, green, blue)); run = &(runs[runs.size() - 1]); } float x = PANGO_PIXELS(layoutX + gi->geometry.x_offset) + cachedGlyph.m_offsetLeft; float y = PANGO_PIXELS(layoutY + gi->geometry.y_offset) - cachedGlyph.m_offsetTop; // Append ourselves onto this run. addPoint(run->m_geometry, x, y, cachedGlyph.m_x0, cachedGlyph.m_y0, s); addPoint(run->m_geometry, x + cachedGlyph.m_width, y, cachedGlyph.m_x1, cachedGlyph.m_y0, s); addPoint(run->m_geometry, x, y + cachedGlyph.m_height, cachedGlyph.m_x0, cachedGlyph.m_y1, s); // Triangle 2. addPoint(run->m_geometry, x + cachedGlyph.m_width, y, cachedGlyph.m_x1, cachedGlyph.m_y0, s); addPoint(run->m_geometry, x, y + cachedGlyph.m_height, cachedGlyph.m_x0, cachedGlyph.m_y1, s); addPoint(run->m_geometry, x + cachedGlyph.m_width, y + cachedGlyph.m_height, cachedGlyph.m_x1, cachedGlyph.m_y1, s); layoutX += gi->geometry.width; } pango_fc_font_unlock_face((PangoFcFont*) font); }
CoglPangoGlyphCacheValue * cogl_pango_glyph_cache_lookup (CoglPangoGlyphCache *cache, CoglBool create, PangoFont *font, PangoGlyph glyph) { CoglPangoGlyphCacheKey lookup_key; CoglPangoGlyphCacheValue *value; lookup_key.font = font; lookup_key.glyph = glyph; value = g_hash_table_lookup (cache->hash_table, &lookup_key); if (create && value == NULL) { CoglPangoGlyphCacheKey *key; PangoRectangle ink_rect; value = g_slice_new (CoglPangoGlyphCacheValue); value->texture = NULL; pango_font_get_glyph_extents (font, glyph, &ink_rect, NULL); pango_extents_to_pixels (&ink_rect, NULL); value->draw_x = ink_rect.x; value->draw_y = ink_rect.y; value->draw_width = ink_rect.width; value->draw_height = ink_rect.height; /* If the glyph is zero-sized then we don't need to reserve any space for it and we can just avoid painting anything */ if (ink_rect.width < 1 || ink_rect.height < 1) value->dirty = FALSE; else { /* Try adding the glyph to the global atlas... */ if (!cogl_pango_glyph_cache_add_to_global_atlas (cache, font, glyph, value) && /* If it fails try the local atlas */ !cogl_pango_glyph_cache_add_to_local_atlas (cache, font, glyph, value)) { cogl_pango_glyph_cache_value_free (value); return NULL; } value->dirty = TRUE; cache->has_dirty_glyphs = TRUE; } key = g_slice_new (CoglPangoGlyphCacheKey); key->font = g_object_ref (font); key->glyph = glyph; g_hash_table_insert (cache->hash_table, key, value); } return value; }
static PangoClutterGlyphCacheValue * pango_clutter_renderer_get_cached_glyph (PangoRenderer *renderer, PangoFont *font, PangoGlyph glyph) { PangoClutterRenderer *priv = PANGO_CLUTTER_RENDERER (renderer); PangoClutterGlyphCacheValue *value; PangoClutterGlyphCache *glyph_cache; glyph_cache = priv->use_mipmapping ? priv->mipmapped_glyph_cache : priv->glyph_cache; if ((value = pango_clutter_glyph_cache_lookup (glyph_cache, font, glyph)) == NULL) { cairo_surface_t *surface; cairo_t *cr; cairo_scaled_font_t *scaled_font; PangoRectangle ink_rect; cairo_glyph_t cairo_glyph; pango_font_get_glyph_extents (font, glyph, &ink_rect, NULL); pango_extents_to_pixels (&ink_rect, NULL); surface = cairo_image_surface_create (CAIRO_FORMAT_A8, ink_rect.width, ink_rect.height); cr = cairo_create (surface); scaled_font = pango_cairo_font_get_scaled_font (PANGO_CAIRO_FONT (font)); cairo_set_scaled_font (cr, scaled_font); cairo_glyph.x = -ink_rect.x; cairo_glyph.y = -ink_rect.y; /* The PangoCairo glyph numbers directly map to Cairo glyph numbers */ cairo_glyph.index = glyph; cairo_show_glyphs (cr, &cairo_glyph, 1); cairo_destroy (cr); cairo_surface_flush (surface); /* Copy the glyph to the cache */ value = pango_clutter_glyph_cache_set (glyph_cache, font, glyph, cairo_image_surface_get_data (surface), cairo_image_surface_get_width (surface), cairo_image_surface_get_height (surface), cairo_image_surface_get_stride (surface), ink_rect.x, ink_rect.y); cairo_surface_destroy (surface); CLUTTER_NOTE (PANGO, "cache fail %i", glyph); } else CLUTTER_NOTE (PANGO, "cache success %i", glyph); return value; }