static void gd_two_lines_renderer_prepare_layouts (GdTwoLinesRenderer *self, const GdkRectangle *cell_area, GtkWidget *widget, PangoLayout **layout_one, PangoLayout **layout_two) { PangoLayout *line_one; PangoLayout *line_two = NULL; gchar *text = NULL; g_object_get (self, "text", &text, NULL); line_one = create_layout_with_attrs (widget, cell_area, self, PANGO_ELLIPSIZE_MIDDLE); if (self->priv->line_two == NULL || g_strcmp0 (self->priv->line_two, "") == 0) { pango_layout_set_height (line_one, - (self->priv->text_lines)); if (text != NULL) pango_layout_set_text (line_one, text, -1); } else { GtkStyleContext *context; line_two = create_layout_with_attrs (widget, cell_area, self, PANGO_ELLIPSIZE_END); context = gtk_widget_get_style_context (widget); gtk_style_context_save (context); apply_subtitle_style_to_layout (context, line_two, GTK_STATE_FLAG_NORMAL); gtk_style_context_restore (context); pango_layout_set_height (line_one, - (self->priv->text_lines - 1)); pango_layout_set_height (line_two, -1); pango_layout_set_text (line_two, self->priv->line_two, -1); if (text != NULL) pango_layout_set_text (line_one, text, -1); } if (layout_one) *layout_one = line_one; if (layout_two) *layout_two = line_two; g_free (text); }
TextAsset::Size TextAsset::computeSizeOfText(cairo_t* cairoContext, const std::string textString, int bounds, PangoFontDescription* font, Rect* tight, float* lineHeightOut) { PangoLayout* layout = pango_cairo_create_layout(cairoContext); // Kerning PangoAttrList* attr_list = pango_attr_list_new(); PangoAttribute* spacing_attr = pango_attr_letter_spacing_new(pango_units_from_double(_kern)); pango_attr_list_insert(attr_list, spacing_attr); pango_layout_set_attributes(layout, attr_list); pango_cairo_context_set_resolution(pango_layout_get_context(layout), DISPLAY_RESOLUTION); pango_layout_set_text(layout, textString.c_str(), (int)textString.length()); pango_layout_set_alignment(layout, _alignment); pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR); const Size maxTextureSize(bounds, 1024); pango_layout_set_width(layout, pango_units_from_double(maxTextureSize.width)); pango_layout_set_height(layout, pango_units_from_double(maxTextureSize.height)); pango_layout_set_font_description(layout, font); applyLeading(cairoContext, layout, font); PangoRectangle estimateSize; PangoRectangle ink; pango_layout_get_pixel_extents(layout, &ink, &estimateSize); // If the text is right or center aligned the offsets will contain all the // leading space. We ignore that for the size because drawText will draw // in the larger box. The tight box below will get the offsets so we know // where to draw so the text lands in the same tight box. Size res(estimateSize.width, estimateSize.height); if (tight != NULL) { float lineHeight; float xHeight = charHeight(cairoContext, font, 'x', &lineHeight); if (lineHeightOut != NULL) { *lineHeightOut = lineHeight; } const float capHeight = charHeight(cairoContext, font, 'Y'); const float ascender = pango_units_to_double(pango_layout_get_baseline(layout)); const float topSpace = ascender - capHeight; const float bottomSpace = MAX(lineHeight - ascender - (capHeight - xHeight), 0); if (res.height > topSpace + bottomSpace) { *tight = Rect(estimateSize.x, estimateSize.y + topSpace, res.width, res.height - topSpace - bottomSpace); } else { *tight = Rect(0, 0, res.width, res.height); } } g_object_unref(layout); return res; }
void tooltip_update() { if (!g_tooltip.tooltip_text) { tooltip_hide(0); return; } tooltip_update_geometry(); if (just_shown) { if (!panel_horizontal) y -= height / 2; // center vertically just_shown = FALSE; } tooltip_adjust_geometry(); XMoveResizeWindow(server.display, g_tooltip.window, x, y, width, height); // Stuff for drawing the tooltip cairo_surface_t *cs = cairo_xlib_surface_create(server.display, g_tooltip.window, server.visual, width, height); cairo_t *c = cairo_create(cs); Color bc = g_tooltip.bg->fill_color; Border b = g_tooltip.bg->border; if (server.real_transparency) { clear_pixmap(g_tooltip.window, 0, 0, width, height); draw_rect(c, b.width, b.width, width - 2 * b.width, height - 2 * b.width, b.radius - b.width / 1.571); cairo_set_source_rgba(c, bc.rgb[0], bc.rgb[1], bc.rgb[2], bc.alpha); } else { cairo_rectangle(c, 0., 0, width, height); cairo_set_source_rgb(c, bc.rgb[0], bc.rgb[1], bc.rgb[2]); } cairo_fill(c); cairo_set_line_width(c, b.width); if (server.real_transparency) draw_rect(c, b.width / 2.0, b.width / 2.0, width - b.width, height - b.width, b.radius); else cairo_rectangle(c, b.width / 2.0, b.width / 2.0, width - b.width, height - b.width); cairo_set_source_rgba(c, b.color.rgb[0], b.color.rgb[1], b.color.rgb[2], b.color.alpha); cairo_stroke(c); Color fc = g_tooltip.font_color; cairo_set_source_rgba(c, fc.rgb[0], fc.rgb[1], fc.rgb[2], fc.alpha); PangoLayout *layout = pango_cairo_create_layout(c); pango_layout_set_font_description(layout, g_tooltip.font_desc); pango_layout_set_wrap(layout, PANGO_WRAP_WORD); pango_layout_set_text(layout, g_tooltip.tooltip_text, -1); PangoRectangle r1, r2; pango_layout_get_pixel_extents(layout, &r1, &r2); pango_layout_set_width(layout, width * PANGO_SCALE); pango_layout_set_height(layout, height * PANGO_SCALE); pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END); // I do not know why this is the right way, but with the below cairo_move_to it seems to be centered (horiz. and // vert.) cairo_move_to(c, -r1.x / 2 + g_tooltip.bg->border.width + g_tooltip.paddingx, -r1.y / 2 + 1 + g_tooltip.bg->border.width + g_tooltip.paddingy); pango_cairo_show_layout(c, layout); g_object_unref(layout); cairo_destroy(c); cairo_surface_destroy(cs); }
struct TEXT_WIDGET_HANDLE text_widget_init ( float x_mm, float y_mm, float width_mm, float height_mm, float dpmm_x, float dpmm_y ) { struct TEXT_WIDGET_HANDLE handle; handle.d = malloc( sizeof( struct TEXT_WIDGET_PRIVATE ) ); handle.d->x_mm = x_mm; handle.d->y_mm = y_mm; handle.d->dpmm_x = dpmm_x; handle.d->dpmm_y = dpmm_y; handle.d->font_map = pango_ft2_font_map_new(); // Note: FreeType works in DPI. pango_ft2_font_map_set_resolution( (PangoFT2FontMap*)handle.d->font_map, dpmm_x * 25.4, dpmm_y * 25.4 ); handle.d->context = pango_font_map_create_context( handle.d->font_map ); handle.d->layout = pango_layout_new( handle.d->context ); // Pango works in Pango Units. Not exactly clear how the resolution of // the font and the size of the rendering box fit together. int width = pango_units_from_double( dpmm_x * width_mm ); int height = pango_units_from_double( dpmm_y * height_mm ); pango_layout_set_width( handle.d->layout, width ); pango_layout_set_height( handle.d->layout, height ); handle.d->foreground = vgCreatePaint(); vgSetParameterfv( handle.d->foreground, VG_PAINT_COLOR, 4, DEFAULT_FOREGROUND ); return handle; }
static void gd_two_lines_renderer_prepare_layouts (GdTwoLinesRenderer *self, GtkWidget *widget, PangoLayout **layout_one, PangoLayout **layout_two) { PangoLayout *line_one; PangoLayout *line_two = NULL; gchar *text = NULL; g_object_get (self, "text", &text, NULL); line_one = create_layout_with_attrs (widget, self, PANGO_ELLIPSIZE_MIDDLE); if (self->priv->line_two == NULL || g_strcmp0 (self->priv->line_two, "") == 0) { pango_layout_set_height (line_one, - (self->priv->text_lines)); if (text != NULL) pango_layout_set_text (line_one, text, -1); } else { line_two = create_layout_with_attrs (widget, self, PANGO_ELLIPSIZE_END); pango_layout_set_height (line_one, - (self->priv->text_lines - 1)); pango_layout_set_height (line_two, -1); pango_layout_set_text (line_two, self->priv->line_two, -1); if (text != NULL) pango_layout_set_text (line_one, text, -1); } if (layout_one) *layout_one = line_one; if (layout_two) *layout_two = line_two; g_free (text); }
static void gnm_so_path_draw_cairo (SheetObject const *so, cairo_t *cr, double width, double height) { GnmSOPath *sop = GNM_SO_PATH (so); GOStyle const *style = sop->style; cairo_new_path (cr); cairo_save (cr); cairo_move_to (cr, -sop->x_offset, -sop->y_offset); cairo_scale (cr, width / sop->width, height / sop->height); go_path_to_cairo (sop->path, GO_PATH_DIRECTION_FORWARD, cr); cairo_restore (cr); /* Fill the shape */ cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD); /* might be an option */ go_style_fill (style, cr, TRUE); /* Draw the line */ if (go_style_set_cairo_line (style, cr)) cairo_stroke (cr); else cairo_new_path (cr); /* Draw the text. */ if (sop->text != NULL && *(sop->text) != '\0') { PangoLayout *pl = pango_cairo_create_layout (cr); double const scale_h = 72. / gnm_app_display_dpi_get (TRUE); double const scale_v = 72. / gnm_app_display_dpi_get (FALSE); double pl_height = (height - sop->margin_pts.top - sop->margin_pts.bottom) * PANGO_SCALE / scale_v; double pl_width = (width - sop->margin_pts.left - sop->margin_pts.right) * PANGO_SCALE / scale_h; /* set a font, a very bad solution, but will do until we move to GOString */ PangoFontDescription *desc = pango_font_description_from_string ("Sans 10"); PangoRectangle r; pango_layout_set_font_description (pl, desc); pango_layout_set_text (pl, sop->text, -1); pango_layout_set_attributes (pl, sop->markup); pango_layout_set_width (pl, pl_width); pango_layout_set_height (pl, pl_height); cairo_save (cr); pango_layout_get_extents (pl, NULL, &r); cairo_move_to (cr, (width - r.width / PANGO_SCALE * scale_h) / 2., (height - r.height / PANGO_SCALE * scale_v) / 2.); cairo_scale (cr, scale_h, scale_v); cairo_set_source_rgba (cr, GO_COLOR_TO_CAIRO (style->font.color)); pango_cairo_show_layout (cr, pl); cairo_new_path (cr); cairo_restore (cr); g_object_unref (pl); } }
static PyObject * _pango_layout_set_width_height(PyObject *self, PyObject *args) { PangoLayout *layout; int width, height; if (!PyArg_ParseTuple(args, "lii", &layout, &width, &height)) return NULL; pango_layout_set_width(layout, pango_units_from_double(width)); pango_layout_set_height(layout, pango_units_from_double(height)); Py_RETURN_NONE; }
void TextAsset::drawText(cairo_t* cairoContext, const std::string& textString, const Rect& rect, PangoFontDescription* inFontDescription, bool outlineEnabled) { cairo_move_to(cairoContext, rect.x, rect.y); PangoLayout* layout = pango_cairo_create_layout(cairoContext); // Kerning PangoAttrList* attr_list = pango_attr_list_new(); PangoAttribute* spacing_attr = pango_attr_letter_spacing_new(pango_units_from_double(_kern)); pango_attr_list_insert(attr_list, spacing_attr); pango_layout_set_attributes(layout, attr_list); pango_cairo_context_set_resolution(pango_layout_get_context(layout), DISPLAY_RESOLUTION); pango_layout_set_text(layout, textString.c_str(), textString.length()); pango_layout_set_font_description(layout, inFontDescription); pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR); pango_layout_set_width(layout, pango_units_from_double(rect.size.width + WIDTH_PADDING)); pango_layout_set_height(layout, pango_units_from_double(rect.size.height + HEIGHT_PADDING)); pango_layout_set_alignment(layout, _alignment); applyLeading(cairoContext, layout, inFontDescription); pango_cairo_show_layout(cairoContext, layout); // Core Text defines positive outline width values as stroke only if (_outlineThickness <= 0.0f) { cairo_fill_preserve(cairoContext); } // Outline if (outlineEnabled && _outlineThickness != 0.0f) { const float outlineThickness = (fabsf(_outlineThickness) / 100.0f) * _fontSize * CLIENT_TO_SERVER_SCALE; cairo_set_source_rgba(cairoContext, _outlineColor.red, _outlineColor.green, _outlineColor.blue, _outlineColor.alpha); pango_cairo_layout_path(cairoContext, layout); cairo_set_line_width(cairoContext, outlineThickness); cairo_stroke(cairoContext); } else { cairo_new_path(cairoContext); } g_object_unref(layout); }
static void _draw_page_results (GtkPrintContext *context, GwPageInfo *page, GwPrintData *data) { //Declarations GtkTextView *view; GtkTextBuffer *buffer; PangoLayout *layout; char *text; PangoFontDescription *desc; int width; int height; gdouble drawable_width, drawable_height; cairo_t *cr; gint line_start; gint line_end; //Initializations view = gw_searchwindow_get_current_textview (data->window); buffer = gtk_text_view_get_buffer (view); text = gtk_text_buffer_get_text (buffer, &(page->start), &(page->end), FALSE); layout = gtk_print_context_create_pango_layout (context); desc = pango_font_description_from_string ("sans 10"); drawable_width = gtk_print_context_get_width (context); drawable_height = gtk_print_context_get_height (context); cr = gtk_print_context_get_cairo_context (context); line_start = 0; line_end = 0; //Draw if (text != NULL) { cairo_move_to (cr, 5, 10); pango_layout_set_font_description (layout, desc); pango_layout_set_markup (layout, text, -1); pango_layout_set_width (layout, drawable_width * PANGO_SCALE); pango_layout_set_alignment (layout, PANGO_ALIGN_LEFT); pango_layout_set_height (layout, drawable_height * PANGO_SCALE); pango_layout_get_size (layout, &width, &height); pango_cairo_show_layout (cr, layout); //Adjust the end GtkTextIter to the cutoff in the visible cairo context line_start = gtk_text_iter_get_line (&page->start); line_end = line_start + pango_layout_get_line_count (layout) - 1; gtk_text_buffer_get_iter_at_line (buffer, &(page->end), line_end); } //Cleanup if (text != NULL) g_free (text); if (layout != NULL) g_object_unref (layout); if (desc != NULL) pango_font_description_free (desc); }
static PangoLayout * make_new_page (PangoContext * context, PangoFontDescription * desc, gdouble height, gdouble width) { PangoLayout *layout; layout = pango_layout_new (context); pango_layout_set_justify (layout, TRUE); pango_layout_set_spacing (layout, 1.5 * PANGO_SCALE); pango_layout_set_width (layout, pango_units_from_double(width - SIDE_MARGIN)); pango_layout_set_height (layout, pango_units_from_double(height - EDGE_MARGIN)); pango_layout_set_wrap (layout, PANGO_WRAP_WORD_CHAR); pango_layout_set_font_description (layout, desc); return layout; }
ttext& ttext::set_maximum_height(int height, bool multiline) { if(height <= 0) { height = -1; multiline = false; } if(height != maximum_height_) { assert(context_); pango_layout_set_height(layout_, !multiline ? -1 : height * PANGO_SCALE); maximum_height_ = height; calculation_dirty_ = true; surface_dirty_ = true; } return *this; }
void draw_task (void *obj, cairo_t *c) { Task *tsk = obj; tsk->state_pix[tsk->current_state] = tsk->area.pixmap; PangoLayout *layout; int width=0, height; Panel *panel = (Panel*)tsk->area.panel; //printf("draw_task %d %d\n", tsk->area.posx, tsk->area.posy); if (panel->g_task.text) { /* Layout */ layout = pango_cairo_create_layout (c); pango_layout_set_font_description (layout, panel->g_task.font_desc); pango_layout_set_text(layout, tsk->title, -1); /* Drawing width and Cut text */ // pango use U+22EF or U+2026 pango_layout_set_width(layout, ((Taskbar*)tsk->area.parent)->text_width * PANGO_SCALE); pango_layout_set_height(layout, panel->g_task.text_height * PANGO_SCALE); pango_layout_set_wrap(layout, PANGO_WRAP_CHAR); pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END); /* Center text */ if (panel->g_task.centered) pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER); else pango_layout_set_alignment (layout, PANGO_ALIGN_LEFT); pango_layout_get_pixel_size (layout, &width, &height); color_rgba_t text_color = panel->g_task.font_colors[tsk->current_state]; double text_posy = (panel->g_task.area.bounds.height - height) / 2.0; draw_text (layout, c, panel->g_task.text_posx, text_posy, &text_color, panel->font_shadow); g_object_unref (layout); } if (panel->g_task.icon) { draw_task_icon (tsk, width); } }
static gboolean configure_text_layout(GtkExperimentTranscript *trans, ExperimentReaderContrib *contrib, gint64 current_time, gint y, gint last_contrib_y, int *logical_height) { PangoAttrList *attrib_list; if (contrib->start_time > current_time) return FALSE; attrib_list = pango_attr_list_new(); for (GSList *cur = trans->priv->formats; cur != NULL; cur = cur->next) { GtkExperimentTranscriptFormat *fmt = (GtkExperimentTranscriptFormat *)cur->data; gtk_experiment_transcript_apply_format(fmt, contrib->text, attrib_list); } gtk_experiment_transcript_apply_format(&trans->priv->interactive_format, contrib->text, attrib_list); pango_layout_set_attributes(trans->priv->layer_text_layout, attrib_list); pango_attr_list_unref(attrib_list); pango_layout_set_text(trans->priv->layer_text_layout, contrib->text, -1); pango_layout_set_height(trans->priv->layer_text_layout, last_contrib_y == -1 ? G_MAXINT : ABS(last_contrib_y - y)*PANGO_SCALE); pango_layout_get_pixel_size(trans->priv->layer_text_layout, NULL, logical_height); return TRUE; }
ttext& ttext::set_maximum_height(int height, bool multiline) { if(height <= 0) { height = -1; multiline = false; } if(height != maximum_height_) { assert(context_); /** * @todo See whether we can make pango 1.20 mandatory before Wesnoth 1.6 is * released. */ #if PANGO_VERSION_CHECK(1,20,0) pango_layout_set_height(layout_, !multiline ? -1 : height * PANGO_SCALE); #endif maximum_height_ = height; calculation_dirty_ = true; surface_dirty_ = true; } return *this; }
void pango_render_text(char* message) { cairo_surface_t *surface; surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 640, 480); cairo_t *context; context = cairo_create(surface); cairo_set_source_rgb(context, 1.0, 0.8, 0.4); cairo_paint(context); PangoLayout *layout; layout = pango_cairo_create_layout(context); pango_layout_set_text(layout, message, -1); PangoFontDescription *desc; desc = pango_font_description_from_string("Arial Bold 36"); pango_layout_set_font_description(layout, desc); pango_font_description_free(desc); pango_layout_set_width(layout, 600 * PANGO_SCALE); pango_layout_set_height(layout, 400 * PANGO_SCALE); pango_cairo_update_layout(context, layout); //pango_render_text_simple(context, layout); //pango_render_text_border(context, layout); pango_render_text_shadow(context, layout); cairo_status_t status = cairo_surface_write_to_png(surface, "pango-text-effects.png"); g_object_unref(layout); cairo_destroy(context); cairo_surface_destroy(surface); }
static void marlin_text_renderer_render (GtkCellRenderer *cell, cairo_t *cr, GtkWidget *widget, const GdkRectangle *background_area, const GdkRectangle *cell_area, GtkCellRendererState flags) { MarlinTextRenderer *text_renderer = MARLIN_TEXT_RENDERER (cell); GtkStyleContext *context; GtkStateFlags state; gint x0, x1, y0, y1; gint text_width; gint text_height; gint x_offset; gint y_offset; gint xpad, ypad; gfloat xalign, yalign; gboolean selected; /* setup the new widget */ marlin_text_renderer_set_widget (text_renderer, widget); state = gtk_widget_get_state_flags (widget); if ((flags & GTK_CELL_RENDERER_SELECTED) == GTK_CELL_RENDERER_SELECTED) { state |= GTK_STATE_FLAG_SELECTED; } else if ((flags & GTK_CELL_RENDERER_PRELIT) == GTK_CELL_RENDERER_PRELIT && gtk_widget_get_state (widget) == GTK_STATE_PRELIGHT) { state = GTK_STATE_PRELIGHT; } else { state = gtk_widget_get_sensitive (widget) ? GTK_STATE_FLAG_NORMAL : GTK_STATE_INSENSITIVE; } /* render small/normal text depending on the zoom_level */ if (text_renderer->zoom_level < MARLIN_ZOOM_LEVEL_NORMAL) { if (text_renderer->follow_prelit && (flags & GTK_CELL_RENDERER_PRELIT) != 0) pango_layout_set_attributes (text_renderer->layout, eel_pango_attr_list_small_underline_single ()); else pango_layout_set_attributes (text_renderer->layout, eel_pango_attr_list_small ()); } else { if (text_renderer->follow_prelit && (flags & GTK_CELL_RENDERER_PRELIT) != 0) pango_layout_set_attributes (text_renderer->layout, eel_pango_attr_list_underline_single ()); else pango_layout_set_attributes (text_renderer->layout, NULL); } /* setup the wrapping */ if (text_renderer->wrap_width < 0) { pango_layout_set_width (text_renderer->layout, -1); pango_layout_set_wrap (text_renderer->layout, PANGO_WRAP_CHAR); } else { pango_layout_set_width (text_renderer->layout, text_renderer->wrap_width * PANGO_SCALE); pango_layout_set_wrap (text_renderer->layout, text_renderer->wrap_mode); } /* ellipsize to max lines except for selected or prelit items */ pango_layout_set_ellipsize (text_renderer->layout, PANGO_ELLIPSIZE_END); pango_layout_set_height (text_renderer->layout, -3); if ((flags & GTK_CELL_RENDERER_SELECTED) == GTK_CELL_RENDERER_SELECTED || (flags & GTK_CELL_RENDERER_PRELIT) == GTK_CELL_RENDERER_PRELIT) { pango_layout_set_ellipsize (text_renderer->layout, PANGO_ELLIPSIZE_NONE); } gtk_cell_renderer_get_alignment (cell, &xalign, &yalign); if (xalign == 0.5f) pango_layout_set_alignment (text_renderer->layout, PANGO_ALIGN_CENTER); pango_layout_set_text (text_renderer->layout, text_renderer->text, -1); /* calculate the real text dimension */ pango_layout_get_pixel_size (text_renderer->layout, &text_width, &text_height); /* take into account the state indicator (required for calculation) */ if (text_renderer->follow_state) { text_width += 2 * text_renderer->focus_width; text_height += 2 * text_renderer->focus_width; } gtk_cell_renderer_get_padding (cell, &xpad, &ypad); /* calculate the real x-offset */ x_offset = ((gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) ? (1.0 - xalign) : xalign) * (cell_area->width - text_width - (2 * xpad)); x_offset = MAX (x_offset, 0); /* calculate the real y-offset */ y_offset = yalign * (cell_area->height - text_height - (2 * ypad)); y_offset = MAX (y_offset, 0); context = gtk_widget_get_style_context (gtk_widget_get_parent (widget)); gtk_style_context_save (context); gtk_style_context_set_state (context, state); selected = ((flags & GTK_CELL_RENDERER_SELECTED) == GTK_CELL_RENDERER_SELECTED && text_renderer->follow_state); /* render the state indicator */ if (selected || text_renderer->background != NULL) { /* calculate the text bounding box (including the focus padding/width) */ x0 = cell_area->x + x_offset; y0 = cell_area->y + y_offset; x1 = x0 + text_width; y1 = y0 + text_height; cairo_move_to (cr, x0 + 5, y0); cairo_line_to (cr, x1 - 5, y0); cairo_curve_to (cr, x1 - 5, y0, x1, y0, x1, y0 + 5); cairo_line_to (cr, x1, y1 - 5); cairo_curve_to (cr, x1, y1 - 5, x1, y1, x1 - 5, y1); cairo_line_to (cr, x0 + 5, y1); cairo_curve_to (cr, x0 + 5, y1, x0, y1, x0, y1 - 5); cairo_line_to (cr, x0, y0 + 5); cairo_curve_to (cr, x0, y0 + 5, x0, y0, x0 + 5, y0); GdkRGBA color; if(text_renderer->background != NULL && !selected) { if(!gdk_rgba_parse(&color, text_renderer->background)) { g_critical("Can't parse this color value: %s", text_renderer->background); gtk_style_context_get_background_color (context, state, &color); } } else { gtk_style_context_get_background_color (context, state, &color); } gdk_cairo_set_source_rgba (cr, &color); cairo_fill (cr); } /* draw the focus indicator */ if (text_renderer->follow_state && (flags & GTK_CELL_RENDERER_FOCUSED) != 0) { gtk_render_focus (context, cr, cell_area->x + x_offset, cell_area->y + y_offset, text_width, text_height); } /* get proper sizing for the layout drawing */ if (text_renderer->follow_state) { text_width -= 2 * text_renderer->focus_width; text_height -= 2 * text_renderer->focus_width; x_offset += text_renderer->focus_width; y_offset += text_renderer->focus_width; } /* draw the text */ if (xalign == 0.5f) x_offset = (cell_area->width - text_renderer->wrap_width)/2; gtk_render_layout (context, cr, cell_area->x + x_offset + xpad, cell_area->y + y_offset + ypad, text_renderer->layout); gtk_style_context_restore (context); }
static VALUE rg_set_height(VALUE self, VALUE width) { pango_layout_set_height(_SELF(self), NUM2INT(width)); return self; }
static void fm_cell_renderer_text_render(GtkCellRenderer *cell, GdkDrawable *window, GtkWidget *widget, GdkRectangle *background_area, GdkRectangle *cell_area, GdkRectangle *expose_area, GtkCellRendererState flags) #endif { FmCellRendererText *self = FM_CELL_RENDERER_TEXT(cell); #if GTK_CHECK_VERSION(3, 0, 0) GtkStyleContext* style; GtkStateFlags state; #else GtkStyle* style; GtkStateType state; #endif gchar* text; gint text_width; gint text_height; gint x_offset; gint y_offset; gint x_align_offset; GdkRectangle rect; PangoWrapMode wrap_mode; gint wrap_width; PangoAlignment alignment; gfloat xalign, yalign; gint xpad, ypad; /* FIXME: this is time-consuming since it invokes pango_layout. * if we want to fix this, we must implement the whole cell * renderer ourselves instead of derived from GtkCellRendererText. */ PangoContext* context = gtk_widget_get_pango_context(widget); PangoLayout* layout = pango_layout_new(context); g_object_get(G_OBJECT(cell), "wrap-mode" , &wrap_mode, "wrap-width", &wrap_width, "alignment" , &alignment, "text", &text, NULL); pango_layout_set_alignment(layout, alignment); /* Setup the wrapping. */ if (wrap_width < 0) { pango_layout_set_width(layout, -1); pango_layout_set_wrap(layout, PANGO_WRAP_CHAR); } else { pango_layout_set_width(layout, wrap_width * PANGO_SCALE); pango_layout_set_wrap(layout, wrap_mode); if(self->height > 0) { /* FIXME: add custom ellipsize from object? */ pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END); pango_layout_set_height(layout, self->height * PANGO_SCALE); } else pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_NONE); } pango_layout_set_text(layout, text, -1); pango_layout_set_auto_dir(layout, TRUE); pango_layout_get_pixel_size(layout, &text_width, &text_height); gtk_cell_renderer_get_alignment(cell, &xalign, &yalign); gtk_cell_renderer_get_padding(cell, &xpad, &ypad); /* Calculate the real x and y offsets. */ x_offset = ((gtk_widget_get_direction(widget) == GTK_TEXT_DIR_RTL) ? (1.0 - xalign) : xalign) * (cell_area->width - text_width - (2 * xpad)); x_offset = MAX(x_offset, 0); y_offset = yalign * (cell_area->height - text_height - (2 * ypad)); y_offset = MAX (y_offset, 0); if(flags & (GTK_CELL_RENDERER_SELECTED|GTK_CELL_RENDERER_FOCUSED)) { rect.x = cell_area->x + x_offset; rect.y = cell_area->y + y_offset; rect.width = text_width + (2 * xpad); rect.height = text_height + (2 * ypad); } #if GTK_CHECK_VERSION(3, 0, 0) style = gtk_widget_get_style_context(widget); #else style = gtk_widget_get_style(widget); #endif if(flags & GTK_CELL_RENDERER_SELECTED) /* item is selected */ { #if GTK_CHECK_VERSION(3, 0, 0) GdkRGBA clr; if(flags & GTK_CELL_RENDERER_INSENSITIVE) /* insensitive */ state = GTK_STATE_FLAG_INSENSITIVE; else state = GTK_STATE_FLAG_SELECTED; gtk_style_context_get_background_color(style, state, &clr); gdk_cairo_rectangle(cr, &rect); gdk_cairo_set_source_rgba(cr, &clr); #else cairo_t *cr = gdk_cairo_create (window); GdkColor clr; if(flags & GTK_CELL_RENDERER_INSENSITIVE) /* insensitive */ state = GTK_STATE_INSENSITIVE; else state = GTK_STATE_SELECTED; clr = style->bg[state]; /* paint the background */ if(expose_area) { gdk_cairo_rectangle(cr, expose_area); cairo_clip(cr); } gdk_cairo_rectangle(cr, &rect); cairo_set_source_rgb(cr, clr.red / 65535., clr.green / 65535., clr.blue / 65535.); #endif cairo_fill (cr); #if !GTK_CHECK_VERSION(3, 0, 0) cairo_destroy (cr); #endif } #if !GTK_CHECK_VERSION(3, 0, 0) else state = GTK_STATE_NORMAL; #endif x_align_offset = (alignment == PANGO_ALIGN_CENTER) ? (wrap_width - text_width) / 2 : 0; #if GTK_CHECK_VERSION(3, 0, 0) gtk_render_layout(style, cr, cell_area->x + x_offset + xpad - x_align_offset, cell_area->y + y_offset + ypad, layout); #else gtk_paint_layout(style, window, state, TRUE, expose_area, widget, "cellrenderertext", cell_area->x + x_offset + xpad - x_align_offset, cell_area->y + y_offset + ypad, layout); #endif g_object_unref(layout); if(G_UNLIKELY( flags & GTK_CELL_RENDERER_FOCUSED) ) /* focused */ { #if GTK_CHECK_VERSION(3, 0, 0) gtk_render_focus(style, cr, rect.x, rect.y, rect.width, rect.height); #else gtk_paint_focus(style, window, state, background_area, widget, "cellrenderertext", rect.x, rect.y, rect.width, rect.height); #endif } if(flags & GTK_CELL_RENDERER_PRELIT) /* hovered */ g_object_set(G_OBJECT(widget), "tooltip-text", text, NULL); else g_object_set(G_OBJECT(widget), "tooltip-text", NULL, NULL); g_free(text); }
static Image *ReadCAPTIONImage(const ImageInfo *image_info, ExceptionInfo *exception) { char *caption, *property; const char *option; DrawInfo *draw_info; FT_Bitmap *canvas; Image *image; PangoAlignment align; PangoContext *context; PangoFontDescription *description; PangoFontMap *fontmap; PangoGravity gravity; PangoLayout *layout; PangoRectangle extent; PixelPacket fill_color; RectangleInfo page; register PixelPacket *q; register unsigned char *p; ssize_t y; /* Initialize Image structure. */ assert(image_info != (const ImageInfo *) NULL); assert(image_info->signature == MagickSignature); if (image_info->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", image_info->filename); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickSignature); image=AcquireImage(image_info); (void) ResetImagePage(image,"0x0+0+0"); /* Get context. */ fontmap=(PangoFontMap *) pango_ft2_font_map_new(); pango_ft2_font_map_set_resolution((PangoFT2FontMap *) fontmap, image->x_resolution,image->y_resolution); option=GetImageOption(image_info,"caption:hinting"); pango_ft2_font_map_set_default_substitute((PangoFT2FontMap *) fontmap, PangoSubstitute,(char *) option,NULL); context=pango_font_map_create_context(fontmap); option=GetImageOption(image_info,"caption:language"); if (option != (const char *) NULL) pango_context_set_language(context,pango_language_from_string(option)); draw_info=CloneDrawInfo(image_info,(DrawInfo *) NULL); pango_context_set_base_dir(context,draw_info->direction == RightToLeftDirection ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR); switch (draw_info->gravity) { case NorthGravity: gravity=PANGO_GRAVITY_NORTH; break; case WestGravity: gravity=PANGO_GRAVITY_WEST; break; case EastGravity: gravity=PANGO_GRAVITY_EAST; break; case SouthGravity: gravity=PANGO_GRAVITY_SOUTH; break; default: gravity=PANGO_GRAVITY_AUTO; break; } pango_context_set_base_gravity(context,gravity); option=GetImageOption(image_info,"caption:gravity-hint"); if (option != (const char *) NULL) { if (LocaleCompare(option,"line") == 0) pango_context_set_gravity_hint(context,PANGO_GRAVITY_HINT_LINE); if (LocaleCompare(option,"natural") == 0) pango_context_set_gravity_hint(context,PANGO_GRAVITY_HINT_NATURAL); if (LocaleCompare(option,"strong") == 0) pango_context_set_gravity_hint(context,PANGO_GRAVITY_HINT_STRONG); } /* Configure layout. */ layout=pango_layout_new(context); option=GetImageOption(image_info,"caption:auto-dir"); if (option != (const char *) NULL) pango_layout_set_auto_dir(layout,1); option=GetImageOption(image_info,"caption:ellipsize"); if (option != (const char *) NULL) { if (LocaleCompare(option,"end") == 0) pango_layout_set_ellipsize(layout,PANGO_ELLIPSIZE_END); if (LocaleCompare(option,"middle") == 0) pango_layout_set_ellipsize(layout,PANGO_ELLIPSIZE_MIDDLE); if (LocaleCompare(option,"none") == 0) pango_layout_set_ellipsize(layout,PANGO_ELLIPSIZE_NONE); if (LocaleCompare(option,"start") == 0) pango_layout_set_ellipsize(layout,PANGO_ELLIPSIZE_START); } option=GetImageOption(image_info,"caption:justify"); if ((option != (const char *) NULL) && (IsMagickTrue(option) != MagickFalse)) pango_layout_set_justify(layout,1); option=GetImageOption(image_info,"caption:single-paragraph"); if ((option != (const char *) NULL) && (IsMagickTrue(option) != MagickFalse)) pango_layout_set_single_paragraph_mode(layout,1); option=GetImageOption(image_info,"caption:wrap"); if (option != (const char *) NULL) { if (LocaleCompare(option,"char") == 0) pango_layout_set_wrap(layout,PANGO_WRAP_CHAR); if (LocaleCompare(option,"word") == 0) pango_layout_set_wrap(layout,PANGO_WRAP_WORD); if (LocaleCompare(option,"word-char") == 0) pango_layout_set_wrap(layout,PANGO_WRAP_WORD_CHAR); } option=GetImageOption(image_info,"caption:indent"); if (option != (const char *) NULL) pango_layout_set_indent(layout,(StringToLong(option)*image->x_resolution* PANGO_SCALE+36)/72); switch (draw_info->align) { case CenterAlign: align=PANGO_ALIGN_CENTER; break; case RightAlign: align=PANGO_ALIGN_RIGHT; break; case LeftAlign: default: align=PANGO_ALIGN_LEFT; break; } if ((align != PANGO_ALIGN_CENTER) && (draw_info->direction == RightToLeftDirection)) align=(PangoAlignment) (PANGO_ALIGN_LEFT+PANGO_ALIGN_RIGHT-align); pango_layout_set_alignment(layout,align); description=pango_font_description_from_string(draw_info->font == (char *) NULL ? "helvetica" : draw_info->font); pango_font_description_set_size(description,PANGO_SCALE*draw_info->pointsize); pango_layout_set_font_description(layout,description); pango_font_description_free(description); property=InterpretImageProperties(image_info,image,image_info->filename); (void) SetImageProperty(image,"caption",property); property=DestroyString(property); caption=ConstantString(GetImageProperty(image,"caption")); /* Render caption. */ option=GetImageOption(image_info,"caption:markup"); if ((option != (const char *) NULL) && (IsMagickTrue(option) != MagickFalse)) pango_layout_set_markup(layout,caption,-1); else pango_layout_set_text(layout,caption,-1); pango_layout_context_changed(layout); page.x=0; page.y=0; if (image_info->page != (char *) NULL) (void) ParseAbsoluteGeometry(image_info->page,&page); if (image->columns == 0) { pango_layout_get_pixel_extents(layout,NULL,&extent); image->columns=extent.x+extent.width; } else { image->columns-=2*page.x; pango_layout_set_width(layout,(PANGO_SCALE*image->columns* image->x_resolution+36.0)/72.0); } if (image->rows == 0) { pango_layout_get_pixel_extents(layout,NULL,&extent); image->rows=extent.y+extent.height; } else { image->rows-=2*page.y; pango_layout_set_height(layout,(PANGO_SCALE*image->rows* image->y_resolution+36.0)/72.0); } /* Create canvas. */ canvas=(FT_Bitmap *) AcquireMagickMemory(sizeof(*canvas)); if (canvas == (FT_Bitmap *) NULL) { draw_info=DestroyDrawInfo(draw_info); ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); } canvas->width=image->columns; canvas->pitch=(canvas->width+3) & ~3; canvas->rows=image->rows; canvas->buffer=(unsigned char *) AcquireQuantumMemory(canvas->pitch, canvas->rows*sizeof(*canvas->buffer)); if (canvas->buffer == (unsigned char *) NULL) { draw_info=DestroyDrawInfo(draw_info); canvas=(FT_Bitmap *) RelinquishMagickMemory(canvas); ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); } canvas->num_grays=256; canvas->pixel_mode=ft_pixel_mode_grays; ResetMagickMemory(canvas->buffer,0x00,canvas->pitch*canvas->rows); pango_ft2_render_layout(canvas,layout,0,0); /* Convert caption to image. */ image->columns+=2*page.x; image->rows+=2*page.y; if (SetImageBackgroundColor(image) == MagickFalse) { draw_info=DestroyDrawInfo(draw_info); canvas->buffer=(unsigned char *) RelinquishMagickMemory(canvas->buffer); canvas=(FT_Bitmap *) RelinquishMagickMemory(canvas); caption=DestroyString(caption); image=DestroyImageList(image); return((Image *) NULL); } p=canvas->buffer; for (y=page.y; y < (ssize_t) (image->rows-page.y); y++) { register ssize_t x; q=GetAuthenticPixels(image,0,y,image->columns,1,exception); if (q == (PixelPacket *) NULL) break; q+=page.x; for (x=page.x; x < (ssize_t) (image->columns-page.x); x++) { MagickRealType fill_opacity; (void) GetFillColor(draw_info,x,y,&fill_color); fill_opacity=QuantumRange-(*p)/canvas->num_grays*(QuantumRange- fill_color.opacity); if (draw_info->text_antialias == MagickFalse) fill_opacity=fill_opacity >= 0.5 ? 1.0 : 0.0; MagickCompositeOver(&fill_color,fill_opacity,q,q->opacity,q); p++; q++; } for ( ; x < (ssize_t) ((canvas->width+3) & ~3); x++) p++; } /* Relinquish resources. */ draw_info=DestroyDrawInfo(draw_info); canvas->buffer=(unsigned char *) RelinquishMagickMemory(canvas->buffer); canvas=(FT_Bitmap *) RelinquishMagickMemory(canvas); caption=DestroyString(caption); return(GetFirstImageInList(image)); }
static GdkPixbuf * biji_note_obj_get_icon (BijiItem *item) { GdkRGBA note_color; const gchar *text; cairo_t *cr; PangoLayout *layout; PangoFontDescription *desc; GdkPixbuf *ret = NULL; cairo_surface_t *surface = NULL; GtkBorder frame_slice = { 4, 3, 3, 6 }; BijiNoteObj *note = BIJI_NOTE_OBJ (item); if (note->priv->icon) return note->priv->icon; /* Create & Draw surface */ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, BIJI_ICON_WIDTH, BIJI_ICON_HEIGHT) ; cr = cairo_create (surface); /* Background */ cairo_rectangle (cr, 0, 0, BIJI_ICON_WIDTH, BIJI_ICON_HEIGHT); if (biji_note_obj_get_rgba (note, ¬e_color)) gdk_cairo_set_source_rgba (cr, ¬e_color); cairo_fill (cr); /* Text */ text = biji_note_id_get_content (note->priv->id); if (text != NULL) { cairo_translate (cr, 10, 10); layout = pango_cairo_create_layout (cr); pango_layout_set_width (layout, 180000 ); pango_layout_set_wrap (layout, PANGO_WRAP_WORD_CHAR); pango_layout_set_height (layout, 180000 ) ; pango_layout_set_text (layout, text, -1); desc = pango_font_description_from_string (BIJI_ICON_FONT); pango_layout_set_font_description (layout, desc); pango_font_description_free (desc); cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); pango_cairo_update_layout (cr, layout); pango_cairo_show_layout (cr, layout); g_object_unref (layout); } cairo_destroy (cr); ret = gdk_pixbuf_get_from_surface (surface, 0, 0, BIJI_ICON_WIDTH, BIJI_ICON_HEIGHT); cairo_surface_destroy (surface); note->priv->icon = gd_embed_image_in_frame (ret, "resource:///org/gnome/bijiben/thumbnail-frame.png", &frame_slice, &frame_slice); g_clear_object (&ret); return note->priv->icon; }
cairo_surface_t* render_text_to_surface (gchar* text, gint width, gint height, const cairo_font_options_t* font_opts, gdouble dpi) { cairo_surface_t* surface; cairo_t* cr; PangoFontDescription* desc; PangoLayout* layout; // sanity check if (!text || width <= 0 || height <= 0) return NULL; // create surface surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); if (cairo_surface_status (surface) != CAIRO_STATUS_SUCCESS) return NULL; // create context cr = cairo_create (surface); if (cairo_status (cr) != CAIRO_STATUS_SUCCESS) { cairo_surface_destroy (surface); return NULL; } // clear context cairo_scale (cr, 1.0f, 1.0f); cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); cairo_paint (cr); // layout = pango_cairo_create_layout (cr); desc = pango_font_description_new (); pango_font_description_set_size (desc, 12 * PANGO_SCALE); pango_font_description_set_family_static (desc, "Candara"); pango_font_description_set_weight (desc, PANGO_WEIGHT_NORMAL); pango_font_description_set_style (desc, PANGO_STYLE_NORMAL); pango_layout_set_wrap (layout, PANGO_WRAP_WORD); pango_layout_set_font_description (layout, desc); pango_font_description_free (desc); pango_layout_set_width (layout, width * PANGO_SCALE); pango_layout_set_height (layout, height * PANGO_SCALE); pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER); pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END); // print and layout string (pango-wise) pango_layout_set_text (layout, text, -1); // make sure system-wide font-options like hinting, antialiasing etc. // are taken into account pango_cairo_context_set_font_options (pango_layout_get_context (layout), font_opts); pango_cairo_context_set_resolution (pango_layout_get_context (layout), dpi); pango_layout_context_changed (layout); // draw pango-text to our cairo-context cairo_move_to (cr, 0.0f, 0.0f); cairo_set_operator (cr, CAIRO_OPERATOR_OVER); cairo_set_source_rgba (cr, 1.0f, 1.0f, 1.0f, 1.0f); // this call leaks 3803 bytes, I've no idea how to fix that pango_cairo_show_layout (cr, layout); // clean up g_object_unref (layout); cairo_destroy (cr); return surface; }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d P A N G O I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ReadPANGOImage() reads an image in the Pango Markup Language Format. % % The format of the ReadPANGOImage method is: % % Image *ReadPANGOImage(const ImageInfo *image_info, % ExceptionInfo *exception) % % A description of each parameter follows: % % o image_info: the image info. % % o exception: return any errors or warnings in this structure. % */ static Image *ReadPANGOImage(const ImageInfo *image_info, ExceptionInfo *exception) { cairo_font_options_t *font_options; cairo_surface_t *surface; char *caption, *property; cairo_t *cairo_image; const char *option; DrawInfo *draw_info; Image *image; MagickBooleanType status; PangoAlignment align; PangoContext *context; PangoFontMap *fontmap; PangoGravity gravity; PangoLayout *layout; PangoRectangle extent; PixelInfo fill_color; RectangleInfo page; register unsigned char *p; size_t stride; ssize_t y; unsigned char *pixels; /* Initialize Image structure. */ assert(image_info != (const ImageInfo *) NULL); assert(image_info->signature == MagickSignature); if (image_info->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", image_info->filename); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickSignature); image=AcquireImage(image_info,exception); (void) ResetImagePage(image,"0x0+0+0"); /* Format caption. */ option=GetImageArtifact(image,"filename"); if (option == (const char *) NULL) property=InterpretImageProperties(image_info,image,image_info->filename, exception); else if (LocaleNCompare(option,"pango:",6) == 0) property=InterpretImageProperties(image_info,image,option+6,exception); else property=InterpretImageProperties(image_info,image,option,exception); (void) SetImageProperty(image,"caption",property,exception); property=DestroyString(property); caption=ConstantString(GetImageProperty(image,"caption",exception)); /* Get context. */ fontmap=pango_cairo_font_map_new(); pango_cairo_font_map_set_resolution(PANGO_CAIRO_FONT_MAP(fontmap), image->resolution.x == 0.0 ? 90.0 : image->resolution.x); font_options=cairo_font_options_create(); option=GetImageArtifact(image,"pango:hinting"); if (option != (const char *) NULL) { if (LocaleCompare(option,"none") != 0) cairo_font_options_set_hint_style(font_options,CAIRO_HINT_STYLE_NONE); if (LocaleCompare(option,"full") != 0) cairo_font_options_set_hint_style(font_options,CAIRO_HINT_STYLE_FULL); } context=pango_font_map_create_context(fontmap); pango_cairo_context_set_font_options(context,font_options); cairo_font_options_destroy(font_options); option=GetImageArtifact(image,"pango:language"); if (option != (const char *) NULL) pango_context_set_language(context,pango_language_from_string(option)); draw_info=CloneDrawInfo(image_info,(DrawInfo *) NULL); pango_context_set_base_dir(context,draw_info->direction == RightToLeftDirection ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR); switch (draw_info->gravity) { case NorthGravity: { gravity=PANGO_GRAVITY_NORTH; break; } case NorthWestGravity: case WestGravity: case SouthWestGravity: { gravity=PANGO_GRAVITY_WEST; break; } case NorthEastGravity: case EastGravity: case SouthEastGravity: { gravity=PANGO_GRAVITY_EAST; break; } case SouthGravity: { gravity=PANGO_GRAVITY_SOUTH; break; } default: { gravity=PANGO_GRAVITY_AUTO; break; } } pango_context_set_base_gravity(context,gravity); option=GetImageArtifact(image,"pango:gravity-hint"); if (option != (const char *) NULL) { if (LocaleCompare(option,"line") == 0) pango_context_set_gravity_hint(context,PANGO_GRAVITY_HINT_LINE); if (LocaleCompare(option,"natural") == 0) pango_context_set_gravity_hint(context,PANGO_GRAVITY_HINT_NATURAL); if (LocaleCompare(option,"strong") == 0) pango_context_set_gravity_hint(context,PANGO_GRAVITY_HINT_STRONG); } /* Configure layout. */ layout=pango_layout_new(context); option=GetImageArtifact(image,"pango:auto-dir"); if (option != (const char *) NULL) pango_layout_set_auto_dir(layout,1); option=GetImageArtifact(image,"pango:ellipsize"); if (option != (const char *) NULL) { if (LocaleCompare(option,"end") == 0) pango_layout_set_ellipsize(layout,PANGO_ELLIPSIZE_END); if (LocaleCompare(option,"middle") == 0) pango_layout_set_ellipsize(layout,PANGO_ELLIPSIZE_MIDDLE); if (LocaleCompare(option,"none") == 0) pango_layout_set_ellipsize(layout,PANGO_ELLIPSIZE_NONE); if (LocaleCompare(option,"start") == 0) pango_layout_set_ellipsize(layout,PANGO_ELLIPSIZE_START); } option=GetImageArtifact(image,"pango:justify"); if (IfMagickTrue(IsStringTrue(option))) pango_layout_set_justify(layout,1); option=GetImageArtifact(image,"pango:single-paragraph"); if (IfMagickTrue(IsStringTrue(option))) pango_layout_set_single_paragraph_mode(layout,1); option=GetImageArtifact(image,"pango:wrap"); if (option != (const char *) NULL) { if (LocaleCompare(option,"char") == 0) pango_layout_set_wrap(layout,PANGO_WRAP_CHAR); if (LocaleCompare(option,"word") == 0) pango_layout_set_wrap(layout,PANGO_WRAP_WORD); if (LocaleCompare(option,"word-char") == 0) pango_layout_set_wrap(layout,PANGO_WRAP_WORD_CHAR); } option=GetImageArtifact(image,"pango:indent"); if (option != (const char *) NULL) pango_layout_set_indent(layout,(int) ((StringToLong(option)* (image->resolution.x == 0.0 ? 90.0 : image->resolution.x)*PANGO_SCALE+36)/ 90.0+0.5)); switch (draw_info->align) { case CenterAlign: align=PANGO_ALIGN_CENTER; break; case RightAlign: align=PANGO_ALIGN_RIGHT; break; case LeftAlign: align=PANGO_ALIGN_LEFT; break; default: { if (draw_info->gravity == CenterGravity) { align=PANGO_ALIGN_CENTER; break; } align=PANGO_ALIGN_LEFT; break; } } if ((align != PANGO_ALIGN_CENTER) && (draw_info->direction == RightToLeftDirection)) align=(PangoAlignment) (PANGO_ALIGN_LEFT+PANGO_ALIGN_RIGHT-align); pango_layout_set_alignment(layout,align); if (draw_info->font != (char *) NULL) { PangoFontDescription *description; /* Set font. */ description=pango_font_description_from_string(draw_info->font); pango_font_description_set_size(description,(int) (PANGO_SCALE* draw_info->pointsize+0.5)); pango_layout_set_font_description(layout,description); pango_font_description_free(description); } option=GetImageArtifact(image,"pango:markup"); if ((option != (const char *) NULL) && (IsStringTrue(option) == MagickFalse)) pango_layout_set_text(layout,caption,-1); else { GError *error; error=(GError *) NULL; if (pango_parse_markup(caption,-1,0,NULL,NULL,NULL,&error) == 0) (void) ThrowMagickException(exception,GetMagickModule(),CoderError, error->message,"`%s'",image_info->filename); pango_layout_set_markup(layout,caption,-1); } pango_layout_context_changed(layout); page.x=0; page.y=0; if (image_info->page != (char *) NULL) (void) ParseAbsoluteGeometry(image_info->page,&page); if (image->columns == 0) { pango_layout_get_extents(layout,NULL,&extent); image->columns=(extent.x+extent.width+PANGO_SCALE/2)/PANGO_SCALE+2*page.x; } else { image->columns-=2*page.x; pango_layout_set_width(layout,(int) ((PANGO_SCALE*image->columns* (image->resolution.x == 0.0 ? 90.0 : image->resolution.x)+45.0)/90.0+ 0.5)); } if (image->rows == 0) { pango_layout_get_extents(layout,NULL,&extent); image->rows=(extent.y+extent.height+PANGO_SCALE/2)/PANGO_SCALE+2*page.y; } else { image->rows-=2*page.y; pango_layout_set_height(layout,(int) ((PANGO_SCALE*image->rows* (image->resolution.y == 0.0 ? 90.0 : image->resolution.y)+45.0)/90.0+ 0.5)); } /* Render markup. */ stride=(size_t) cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, image->columns); pixels=(unsigned char *) AcquireQuantumMemory(image->rows,stride* sizeof(*pixels)); if (pixels == (unsigned char *) NULL) { draw_info=DestroyDrawInfo(draw_info); caption=DestroyString(caption); ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); } surface=cairo_image_surface_create_for_data(pixels,CAIRO_FORMAT_ARGB32, image->columns,image->rows,stride); cairo_image=cairo_create(surface); cairo_set_operator(cairo_image,CAIRO_OPERATOR_CLEAR); cairo_paint(cairo_image); cairo_set_operator(cairo_image,CAIRO_OPERATOR_OVER); cairo_translate(cairo_image,page.x,page.y); pango_cairo_show_layout(cairo_image,layout); cairo_destroy(cairo_image); cairo_surface_destroy(surface); g_object_unref(layout); g_object_unref(fontmap); /* Convert surface to image. */ (void) SetImageBackgroundColor(image,exception); p=pixels; GetPixelInfo(image,&fill_color); for (y=0; y < (ssize_t) image->rows; y++) { register Quantum *q; register ssize_t x; q=GetAuthenticPixels(image,0,y,image->columns,1,exception); if (q == (Quantum *) NULL) break; for (x=0; x < (ssize_t) image->columns; x++) { double gamma; fill_color.blue=(double) ScaleCharToQuantum(*p++); fill_color.green=(double) ScaleCharToQuantum(*p++); fill_color.red=(double) ScaleCharToQuantum(*p++); fill_color.alpha=(double) ScaleCharToQuantum(*p++); /* Disassociate alpha. */ gamma=1.0-QuantumScale*fill_color.alpha; gamma=PerceptibleReciprocal(gamma); fill_color.blue*=gamma; fill_color.green*=gamma; fill_color.red*=gamma; CompositePixelOver(image,&fill_color,fill_color.alpha,q,(double) GetPixelAlpha(image,q),q); q+=GetPixelChannels(image); } if (SyncAuthenticPixels(image,exception) == MagickFalse) break; if (image->previous == (Image *) NULL) { status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y, image->rows); if (status == MagickFalse) break; } } /* Relinquish resources. */ pixels=(unsigned char *) RelinquishMagickMemory(pixels); draw_info=DestroyDrawInfo(draw_info); caption=DestroyString(caption); return(GetFirstImageInList(image)); }
void text_rsrc::updatePixels_setup( text_update_context* context ) { // Set up Cairo then Pango with initial values ///////////////////////////////////////////////////////////////////////////////////////////////////////// context -> c_surf = cairo_image_surface_create( CAIRO_FORMAT_A8, // We only need alpha, coloring is handled by OpenGL dimensions[ 0 ], dimensions[ 1 ] ); context -> c_status = cairo_surface_status( context -> c_surf ); if( context -> c_status ) { exception e; ff::write( *e, "text_rsrc::updatePixels(): Error creating Cairo surface: ", cairo_status_to_string( context -> c_status ) ); throw e; } context -> c_context = cairo_create( context -> c_surf ); context -> c_status = cairo_status( context -> c_context ); if( context -> c_status ) { exception e; ff::write( *e, "text_rsrc::updatePixels(): Error creating Cairo context: ", cairo_status_to_string( context -> c_status ) ); throw e; } cairo_surface_destroy( context -> c_surf ); // Dereference surface context -> p_layout = pango_cairo_create_layout( context -> c_context ); // Customize Pango layout & font /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// if( max_dimensions[ 0 ] < 0 ) pango_layout_set_width( context -> p_layout, -1 ); else pango_layout_set_width( context -> p_layout, max_dimensions[ 0 ] * PANGO_SCALE ); if( max_dimensions[ 1 ] < 0 ) pango_layout_set_height( context -> p_layout, -1 ); else pango_layout_set_height( context -> p_layout, max_dimensions[ 1 ] * PANGO_SCALE ); context -> c_fontops = cairo_font_options_create(); if( hinting_enabled ) cairo_font_options_set_hint_style( context -> c_fontops, CAIRO_HINT_STYLE_DEFAULT ); else cairo_font_options_set_hint_style( context -> c_fontops, CAIRO_HINT_STYLE_NONE ); if( antialiasing_enabled ) cairo_font_options_set_antialias( context -> c_fontops, CAIRO_ANTIALIAS_DEFAULT ); else cairo_font_options_set_antialias( context -> c_fontops, CAIRO_ANTIALIAS_NONE ); // TODO: Potentially set subpixel rendering pango_cairo_context_set_font_options( pango_layout_get_context( context -> p_layout ), context -> c_fontops ); // Many thanks to ui/gfc/pango_util.cc from the Chromium project, which appears // to be the only online example of setting PangoCairo font options context -> p_fontd = pango_font_description_from_string( font.c_str() ); pango_font_description_set_absolute_size( context -> p_fontd, point_size * PANGO_SCALE ); pango_layout_set_font_description( context -> p_layout, context -> p_fontd ); pango_font_description_free( context -> p_fontd ); // Dereference font description switch( ellipsize ) { case NONE: pango_layout_set_ellipsize( context -> p_layout, PANGO_ELLIPSIZE_NONE ); break; case BEGINNING: pango_layout_set_ellipsize( context -> p_layout, PANGO_ELLIPSIZE_START ); break; case MIDDLE: pango_layout_set_ellipsize( context -> p_layout, PANGO_ELLIPSIZE_MIDDLE ); break; case END: pango_layout_set_ellipsize( context -> p_layout, PANGO_ELLIPSIZE_END ); break; default: throw exception( "text_rsrc::updatePixels(): Unknown ellipsize mode" ); } pango_layout_set_text( context -> p_layout, string.c_str(), -1 ); pango_cairo_update_layout( context -> c_context, context -> p_layout ); }
void iupdrvDrawText(IdrawCanvas* dc, const char* text, int len, int x, int y, int w, int h, long color, const char* font, int flags, double text_orientation) { PangoLayout* fontlayout = (PangoLayout*)iupgtkGetPangoLayout(font); PangoAlignment alignment = PANGO_ALIGN_LEFT; GdkColor c; PangoContext* fontcontext = NULL; int layout_w = w, layout_h = h; int layout_center = flags & IUP_DRAW_LAYOUTCENTER; if (text_orientation && layout_center) iupDrawGetTextInnerBounds(w, h, text_orientation, &layout_w, &layout_h); iupgdkColorSet(&c, color); gdk_gc_set_rgb_fg_color(dc->pixmap_gc, &c); text = iupgtkStrConvertToSystemLen(text, &len); pango_layout_set_text(fontlayout, text, len); if (flags & IUP_DRAW_RIGHT) alignment = PANGO_ALIGN_RIGHT; else if (flags & IUP_DRAW_CENTER) alignment = PANGO_ALIGN_CENTER; if (flags & IUP_DRAW_WRAP) { pango_layout_set_width(fontlayout, iupGTK_PIXELS2PANGOUNITS(layout_w)); #ifdef PANGO_VERSION_CHECK #if PANGO_VERSION_CHECK(1,2,0) pango_layout_set_height(fontlayout, iupGTK_PIXELS2PANGOUNITS(layout_h)); #endif #endif } else if (flags & IUP_DRAW_ELLIPSIS) { pango_layout_set_width(fontlayout, iupGTK_PIXELS2PANGOUNITS(layout_w)); #ifdef PANGO_VERSION_CHECK #if PANGO_VERSION_CHECK(1,2,0) pango_layout_set_height(fontlayout, iupGTK_PIXELS2PANGOUNITS(layout_h)); #endif #endif pango_layout_set_ellipsize(fontlayout, PANGO_ELLIPSIZE_END); } pango_layout_set_alignment(fontlayout, alignment); if (flags & IUP_DRAW_CLIP) { GdkRectangle rect; rect.x = x; rect.y = y; rect.width = w; rect.height = h; gdk_gc_set_clip_rectangle(dc->pixmap_gc, &rect); } if (text_orientation) { PangoRectangle rect; PangoMatrix fontmatrix = PANGO_MATRIX_INIT; fontcontext = pango_layout_get_context(fontlayout); pango_matrix_rotate(&fontmatrix, text_orientation); pango_context_set_matrix(fontcontext, &fontmatrix); pango_layout_context_changed(fontlayout); pango_layout_get_pixel_extents(fontlayout, NULL, &rect); #ifdef PANGO_VERSION_CHECK #if PANGO_VERSION_CHECK(1,16,0) pango_matrix_transform_pixel_rectangle(&fontmatrix, &rect); #endif #endif /* Adjust the position considering the Pango rectangle transformed */ if (layout_center) { x += (w - rect.width) / 2; y += (h - rect.height) / 2; } else { x += (int)rect.x; y += (int)rect.y; } } gdk_draw_layout(dc->pixmap, dc->pixmap_gc, x, y, fontlayout); /* restore settings */ if ((flags & IUP_DRAW_WRAP) || (flags & IUP_DRAW_ELLIPSIS)) { pango_layout_set_width(fontlayout, -1); #ifdef PANGO_VERSION_CHECK #if PANGO_VERSION_CHECK(1,2,0) pango_layout_set_height(fontlayout, -1); #endif #endif } if (flags & IUP_DRAW_ELLIPSIS) pango_layout_set_ellipsize(fontlayout, PANGO_ELLIPSIZE_NONE); if (flags & IUP_DRAW_CLIP) gdk_gc_set_clip_region(dc->pixmap_gc, NULL); if (text_orientation) pango_context_set_matrix(fontcontext, NULL); }
PangoLayout* gdip_pango_setup_layout (GpGraphics *graphics, GDIPCONST WCHAR *stringUnicode, int length, GDIPCONST GpFont *font, GDIPCONST RectF *rc, RectF *box, GDIPCONST GpStringFormat *format, int **charsRemoved) { GpStringFormat *fmt; PangoLayout *layout; PangoContext *context; PangoRectangle logical; /* logical size of text (used for alignment) */ PangoRectangle ink; /* ink size of text (to pixel boundaries) */ PangoAttrList *list = NULL; GString *ftext; PangoTabArray *tabs; PangoLayoutIter *iter; int i; int FrameWidth; /* rc->Width (or rc->Height if vertical) */ int FrameHeight; /* rc->Height (or rc->Width if vertical) */ int FrameX; /* rc->X (or rc->Y if vertical) */ int FrameY; /* rc->Y (or rc->X if vertical) */ int y0; /* y0,y1,clipNN used for checking line positions vs. clip rectangle */ int y1; double clipx1; double clipx2; double clipy1; double clipy2; int trimSpace; /* whether or not to trim the space */ gchar *text = ucs2_to_utf8 (stringUnicode, length); if (!text) return NULL; length = strlen(text); if (charsRemoved) { (*charsRemoved) = GdipAlloc (sizeof (int) * length); if (!*charsRemoved) { GdipFree (text); return NULL; } memset (*charsRemoved, 0, sizeof (int) * length); } /* TODO - Digit substitution */ // g_warning ("layout >%s< (%d) [x %g, y %g, w %g, h %g] [font %s, %g points]", text, length, rc->X, rc->Y, rc->Width, FrameHeight, font->face, font->emSize); /* a NULL format is valid, it means get the generic default values (and free them later) */ if (!format) { GpStatus status = GdipStringFormatGetGenericDefault ((GpStringFormat **)&fmt); if (status != Ok) { GdipFree (text); return NULL; } } else { fmt = (GpStringFormat *)format; } layout = pango_cairo_create_layout (graphics->ct); /* context is owned by Pango (i.e. not referenced counted) do not free */ context = pango_layout_get_context (layout); pango_layout_set_font_description (layout, gdip_get_pango_font_description ((GpFont*) font)); if (fmt->formatFlags & StringFormatFlagsDirectionVertical) { FrameWidth = MAKE_SAFE_FOR_PANGO (SAFE_FLOAT_TO_UINT32 (rc->Height)); FrameHeight = MAKE_SAFE_FOR_PANGO (SAFE_FLOAT_TO_UINT32 (rc->Width)); FrameX = SAFE_FLOAT_TO_UINT32 (rc->Y); FrameY = SAFE_FLOAT_TO_UINT32 (rc->X); } else { FrameWidth = MAKE_SAFE_FOR_PANGO (SAFE_FLOAT_TO_UINT32 (rc->Width)); FrameHeight = MAKE_SAFE_FOR_PANGO (SAFE_FLOAT_TO_UINT32 (rc->Height)); FrameX = SAFE_FLOAT_TO_UINT32 (rc->X); FrameY = SAFE_FLOAT_TO_UINT32 (rc->Y); } //g_warning("FW: %d\tFH: %d", FrameWidth, FrameHeight); if ((FrameWidth <= 0) || (fmt->formatFlags & StringFormatFlagsNoWrap)) { pango_layout_set_width (layout, -1); //g_warning ("Setting width: %d", -1); } else { pango_layout_set_width (layout, FrameWidth * PANGO_SCALE); //g_warning ("Setting width: %d", FrameWidth * PANGO_SCALE); } if ((rc->Width != 0) && (rc->Height != 0) && ((fmt->formatFlags & StringFormatFlagsNoClip) == 0)) { // g_warning ("\tclip [%g %g %g %g]", rc->X, rc->Y, rc->Width, rc->Height); /* We do not call cairo_reset_clip because we want to take previous clipping into account */ /* Use rc instead of frame variables because this is pre-transform */ gdip_cairo_rectangle (graphics, rc->X, rc->Y, rc->Width, rc->Height, TRUE); cairo_clip (graphics->ct); } /* with GDI+ the API not the renderer makes the direction decision */ pango_layout_set_auto_dir (layout, FALSE); if (!(fmt->formatFlags & StringFormatFlagsDirectionRightToLeft) != !(fmt->formatFlags & StringFormatFlagsDirectionVertical)) { pango_context_set_base_dir (context, PANGO_DIRECTION_WEAK_RTL); pango_layout_context_changed (layout); /* horizontal alignment */ switch (fmt->alignment) { case StringAlignmentNear: pango_layout_set_alignment (layout, PANGO_ALIGN_RIGHT); break; case StringAlignmentCenter: pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER); break; case StringAlignmentFar: pango_layout_set_alignment (layout, PANGO_ALIGN_LEFT); break; } } else { /* pango default base dir is WEAK_LTR, which is what we want */ /* horizontal alignment */ switch (fmt->alignment) { case StringAlignmentNear: pango_layout_set_alignment (layout, PANGO_ALIGN_LEFT); break; case StringAlignmentCenter: pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER); break; case StringAlignmentFar: pango_layout_set_alignment (layout, PANGO_ALIGN_RIGHT); break; } } #ifdef PANGO_VERSION_CHECK #if PANGO_VERSION_CHECK(1,16,0) if (fmt->formatFlags & StringFormatFlagsDirectionVertical) { if (fmt->formatFlags & StringFormatFlagsDirectionRightToLeft) { cairo_rotate (graphics->ct, M_PI/2.0); cairo_translate (graphics->ct, 0, -FrameHeight); pango_cairo_update_context (graphics->ct, context); } else { cairo_rotate (graphics->ct, 3.0*M_PI/2.0); cairo_translate (graphics->ct, -FrameWidth, 0); pango_cairo_update_context (graphics->ct, context); } /* only since Pango 1.16 */ pango_context_set_base_gravity (context, PANGO_GRAVITY_AUTO); pango_context_set_gravity_hint (context, PANGO_GRAVITY_HINT_LINE); pango_layout_context_changed (layout); } #endif #endif /* TODO - StringFormatFlagsDisplayFormatControl scan and replace them ??? */ /* Trimming options seem to apply only to the end of the string - gdi+ will still wrap * with preference to word first, then character. Unfortunately, pango doesn't have * any way to differentiate wrapping behavior from trimming behavior that I could find */ pango_layout_set_wrap (layout, PANGO_WRAP_WORD_CHAR); switch (fmt->trimming) { case StringTrimmingNone: pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_NONE); break; case StringTrimmingCharacter: pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_NONE); break; case StringTrimmingWord: pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_NONE); break; case StringTrimmingEllipsisCharacter: pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END); if (!(fmt->formatFlags & StringFormatFlagsNoWrap)) pango_layout_set_height (layout, FrameHeight == 0 ? G_MAXINT32 : FrameHeight * PANGO_SCALE); break; case StringTrimmingEllipsisWord: pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END); if (!(fmt->formatFlags & StringFormatFlagsNoWrap)) pango_layout_set_height (layout, FrameHeight == 0 ? G_MAXINT32 : FrameHeight * PANGO_SCALE); break; case StringTrimmingEllipsisPath: pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_MIDDLE); if (!(fmt->formatFlags & StringFormatFlagsNoWrap)) pango_layout_set_height (layout, FrameHeight == 0 ? G_MAXINT32 : FrameHeight * PANGO_SCALE); break; } /* some stuff can only be done by manipulating the attributes (but we can avoid this most of the time) */ if ((fmt->formatFlags & StringFormatFlagsNoFontFallback) || (font->style & (FontStyleUnderline | FontStyleStrikeout))) { list = gdip_get_layout_attributes (layout); /* StringFormatFlagsNoFontFallback */ if (fmt->formatFlags & StringFormatFlagsNoFontFallback) { PangoAttribute *attr = pango_attr_fallback_new (FALSE); attr->start_index = 0; attr->end_index = length; pango_attr_list_insert (list, attr); } if (font->style & FontStyleUnderline) { PangoAttribute *attr = pango_attr_underline_new (PANGO_UNDERLINE_SINGLE); attr->start_index = 0; attr->end_index = length; pango_attr_list_insert (list, attr); } if (font->style & FontStyleStrikeout) { PangoAttribute *attr = pango_attr_strikethrough_new (TRUE); attr->start_index = 0; attr->end_index = length; pango_attr_list_insert (list, attr); } } if (fmt->numtabStops > 0) { float tabPosition; tabs = pango_tab_array_new (fmt->numtabStops, FALSE); tabPosition = fmt->firstTabOffset; for (i = 0; i < fmt->numtabStops; i++) { tabPosition += fmt->tabStops[i]; pango_tab_array_set_tab (tabs, i, PANGO_TAB_LEFT, (gint)min (tabPosition, PANGO_MAX) * PANGO_SCALE); } pango_layout_set_tabs (layout, tabs); pango_tab_array_free (tabs); } //g_warning ("length before ws removal: %d", length); trimSpace = (fmt->formatFlags & StringFormatFlagsMeasureTrailingSpaces) == 0; switch (fmt->hotkeyPrefix) { case HotkeyPrefixHide: /* we need to remove any accelerator from the string */ ftext = gdip_process_string (text, length, 1, trimSpace, NULL, charsRemoved); break; case HotkeyPrefixShow: /* optimization: is seems that we never see the hotkey when using an underline font */ if (font->style & FontStyleUnderline) { /* so don't bother drawing it (and simply add the '&' character) */ ftext = gdip_process_string (text, length, 1, trimSpace, NULL, charsRemoved); } else { /* find accelerator and add attribute to the next character (unless it's the prefix too) */ if (!list) list = gdip_get_layout_attributes (layout); ftext = gdip_process_string (text, length, 1, trimSpace, list, charsRemoved); } break; default: ftext = gdip_process_string (text, length, 0, trimSpace, NULL, charsRemoved); break; } length = ftext->len; //g_warning ("length after ws removal: %d", length); if (list) { pango_layout_set_attributes (layout, list); pango_attr_list_unref (list); } // g_warning("\tftext>%s< (%d)", ftext->str, -1); pango_layout_set_text (layout, ftext->str, ftext->len); GdipFree (text); g_string_free(ftext, TRUE); /* Trim the text after the last line for ease of counting lines/characters */ /* Also prevents drawing whole lines outside the boundaries if NoClip was specified */ /* In case of pre-existing clipping, use smaller of clip rectangle or our specified height */ if (FrameHeight > 0) { cairo_clip_extents (graphics->ct, &clipx1, &clipy1, &clipx2, &clipy2); if (clipy2 > 0 && !(fmt->formatFlags & StringFormatFlagsNoClip)) clipy2 = min (clipy2, FrameHeight + FrameY); else clipy2 = FrameHeight + FrameY; iter = pango_layout_get_iter (layout); do { if (iter == NULL) break; pango_layout_iter_get_line_yrange (iter, &y0, &y1); //g_warning("yrange: %d %d clipy2: %f", y0 / PANGO_SCALE, y1 / PANGO_SCALE, clipy2); /* StringFormatFlagsLineLimit */ if (((fmt->formatFlags & StringFormatFlagsLineLimit) && y1 / PANGO_SCALE > clipy2) || (y0 / PANGO_SCALE > clipy2)) { PangoLayoutLine *line = pango_layout_iter_get_line_readonly (iter); pango_layout_set_text (layout, pango_layout_get_text (layout), line->start_index); break; } } while (pango_layout_iter_next_line (iter)); pango_layout_iter_free (iter); } pango_layout_get_pixel_extents (layout, &ink, &logical); // g_warning ("\tlogical\t[x %d, y %d, w %d, h %d][x %d, y %d, w %d, h %d]", logical.x, logical.y, logical.width, logical.height, ink.x, ink.y, ink.width, ink.height); if ((fmt->formatFlags & StringFormatFlagsNoFitBlackBox) == 0) { /* By default don't allow overhang - ink space may be larger than logical space */ if (fmt->formatFlags & StringFormatFlagsDirectionVertical) { box->X = min (ink.y, logical.y); box->Y = min (ink.x, logical.x); box->Height = max (ink.width, logical.width); box->Width = max (ink.height, logical.height); } else { box->X = min (ink.x, logical.x); box->Y = min (ink.y, logical.y); box->Height = max (ink.height, logical.height); box->Width = max (ink.width, logical.width); } } else { /* Allow overhang */ if (fmt->formatFlags & StringFormatFlagsDirectionVertical) { box->X = logical.y; box->Y = logical.x; box->Height = logical.width; box->Width = logical.height; } else { box->X = logical.x; box->Y = logical.y; box->Height = logical.height; box->Width = logical.width; } } // g_warning ("\tbox\t[x %g, y %g, w %g, h %g]", box->X, box->Y, box->Width, box->Height); /* vertical alignment*/ if (fmt->formatFlags & StringFormatFlagsDirectionVertical) { switch (fmt->lineAlignment) { case StringAlignmentNear: break; case StringAlignmentCenter: box->X += (rc->Width - box->Width) / 2; break; case StringAlignmentFar: box->X += (rc->Width - box->Width); break; } } else { switch (fmt->lineAlignment) { case StringAlignmentNear: break; case StringAlignmentCenter: box->Y += (rc->Height - box->Height) / 2; break; case StringAlignmentFar: box->Y += (rc->Height - box->Height); break; } } // g_warning ("va-box\t[x %g, y %g, w %g, h %g]", box->X, box->Y, box->Width, box->Height); pango_cairo_update_layout (graphics->ct, layout); return layout; }
void calendar_draw_page (GtkPrintOperation *operation, GtkPrintContext *context, gint npage, gpointer user_data) { PangoLayout *layout; PangoFontDescription *month_name_font, *day_name_font, *day_num_font, *event_font; cairo_t *cr; GDate *date; gdouble page_width, page_height, day_width, day_height; gint text_width, text_height, header_height, event_height, mnf_height, dnf_height, duf_height; gint day, month, i, j; guint32 julian; gboolean monday, actual; gchar buffer[BUFFER_SIZE]; gint padding = config.cal_print_padding; GUI *appGUI = (GUI *) user_data; date = g_date_new_julian (g_date_get_julian (appGUI->cal->date)); g_return_if_fail (date != NULL); cr = gtk_print_context_get_cairo_context (context); layout = gtk_print_context_create_pango_layout (context); month_name_font = pango_font_description_from_string (config.cal_print_month_name_font); day_name_font = pango_font_description_from_string (config.cal_print_day_name_font); day_num_font = pango_font_description_from_string (config.cal_print_day_num_font); event_font = pango_font_description_from_string (config.cal_print_event_font); pango_layout_set_text (layout, "Aj", -1); pango_layout_set_font_description (layout, month_name_font); pango_layout_get_pixel_size (layout, NULL, &mnf_height); mnf_height *= 1.2; pango_layout_set_font_description (layout, day_name_font); pango_layout_get_pixel_size (layout, NULL, &dnf_height); dnf_height *= 1.2; pango_layout_set_font_description (layout, day_num_font); pango_layout_get_pixel_size (layout, NULL, &duf_height); page_width = gtk_print_context_get_width (context); day_width = page_width / 7; page_height = gtk_print_context_get_height (context); header_height = mnf_height + dnf_height; day_height = (page_height - header_height) / 6; event_height = day_height - duf_height - padding * 3; cairo_set_line_width (cr, 1); monday = (config.display_options & GUI_CALENDAR_WEEK_START_MONDAY) ? TRUE : FALSE; /* Month and year */ pango_layout_set_font_description (layout, month_name_font); g_date_strftime (buffer, BUFFER_SIZE, "%B %Y", date); pango_layout_set_text (layout, buffer, -1); pango_layout_get_pixel_size (layout, &text_width, NULL); cairo_move_to (cr, (page_width - text_width) / 2, 0); pango_cairo_show_layout (cr, layout); /* Day names */ pango_layout_set_font_description (layout, day_name_font); for (i = 0; i < 7; i++) { g_snprintf (buffer, BUFFER_SIZE, "%s", utl_get_day_name (i + 7 + monday, FALSE)); pango_layout_set_text (layout, buffer, -1); pango_layout_get_pixel_size (layout, &text_width, NULL); cairo_move_to (cr, day_width * i + (day_width - text_width) / 2, mnf_height); pango_cairo_show_layout (cr, layout); } /* Day */ g_date_set_day (date, 1); day = g_date_get_weekday (date); month = g_date_get_month (date); day = monday ? day - 1 : day % 7; if (day > 0) g_date_subtract_days (date, day); day = g_date_get_day (date); julian = g_date_get_julian (date); pango_layout_set_wrap (layout, PANGO_WRAP_WORD_CHAR); pango_layout_set_width (layout, (day_width - padding * 2) * PANGO_SCALE); pango_layout_set_height (layout, event_height * PANGO_SCALE); pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END); pango_layout_set_indent (layout, -4 * PANGO_SCALE); for (i = 0; i < 6; i++) { for (j = 0; j < 7; j++) { actual = (month == g_date_get_month (date)) ? TRUE : FALSE; day = g_date_get_day (date); cairo_rectangle (cr, day_width * j, header_height + day_height * i, day_width, day_height); if (actual) { cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); } else { cairo_set_source_rgb (cr, 0.8, 0.8, 0.8); } cairo_fill_preserve (cr); cairo_set_source_rgb (cr, 0, 0, 0); cairo_stroke (cr); pango_layout_set_font_description (layout, day_num_font); if (actual) { cairo_move_to (cr, day_width * j + padding, header_height + day_height * i + padding); if ((j == 0 && !monday) || (j == 5 && monday) || j == 6) { g_snprintf (buffer, BUFFER_SIZE, "<span color=\"red\">%d</span>", day); } else { g_snprintf (buffer, BUFFER_SIZE, "%d", day); } pango_layout_set_markup (layout, buffer, -1); pango_cairo_show_layout (cr, layout); cal_print_get_events (buffer, julian, appGUI); pango_layout_set_markup (layout, "", -1); pango_layout_set_text (layout, buffer, -1); pango_layout_set_font_description (layout, event_font); pango_layout_get_pixel_size (layout, NULL, &text_height); cairo_move_to (cr, day_width * j + padding, header_height + day_height * (i + 1) - text_height - padding); pango_cairo_show_layout (cr, layout); } else { cairo_move_to (cr, day_width * j + padding, header_height + day_height * i + padding); g_snprintf (buffer, BUFFER_SIZE, "<span color=\"white\">%d</span>", day); pango_layout_set_markup (layout, buffer, -1); pango_cairo_show_layout (cr, layout); } g_date_add_days (date, 1); julian++; } } g_date_free (date); pango_font_description_free (month_name_font); pango_font_description_free (day_name_font); pango_font_description_free (day_num_font); pango_font_description_free (event_font); g_object_unref (layout); }
/** * Sends the given character to the terminal at the given row and column, * rendering the character immediately. This bypasses the guac_terminal_display * mechanism and is intended for flushing of updates only. */ int __guac_terminal_set(guac_terminal_display* display, int row, int col, int codepoint) { int width; int bytes; char utf8[4]; /* Use foreground color */ const guac_terminal_color* color = &guac_terminal_palette[display->glyph_foreground]; /* Use background color */ const guac_terminal_color* background = &guac_terminal_palette[display->glyph_background]; cairo_surface_t* surface; cairo_t* cairo; int surface_width, surface_height; PangoLayout* layout; int layout_width, layout_height; int ideal_layout_width, ideal_layout_height; /* Calculate width in columns */ width = wcwidth(codepoint); if (width < 0) width = 1; /* Do nothing if glyph is empty */ if (width == 0) return 0; /* Convert to UTF-8 */ bytes = guac_terminal_encode_utf8(codepoint, utf8); surface_width = width * display->char_width; surface_height = display->char_height; ideal_layout_width = surface_width * PANGO_SCALE; ideal_layout_height = surface_height * PANGO_SCALE; /* Prepare surface */ surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, surface_width, surface_height); cairo = cairo_create(surface); /* Fill background */ cairo_set_source_rgb(cairo, background->red / 255.0, background->green / 255.0, background->blue / 255.0); cairo_rectangle(cairo, 0, 0, surface_width, surface_height); cairo_fill(cairo); /* Get layout */ layout = pango_cairo_create_layout(cairo); pango_layout_set_font_description(layout, display->font_desc); pango_layout_set_text(layout, utf8, bytes); pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER); pango_layout_get_size(layout, &layout_width, &layout_height); /* If layout bigger than available space, scale it back */ if (layout_width > ideal_layout_width || layout_height > ideal_layout_height) { double scale = fmin(ideal_layout_width / (double) layout_width, ideal_layout_height / (double) layout_height); cairo_scale(cairo, scale, scale); /* Update layout to reflect scaled surface */ pango_layout_set_width(layout, ideal_layout_width / scale); pango_layout_set_height(layout, ideal_layout_height / scale); pango_cairo_update_layout(cairo, layout); } /* Draw */ cairo_set_source_rgb(cairo, color->red / 255.0, color->green / 255.0, color->blue / 255.0); cairo_move_to(cairo, 0.0, 0.0); pango_cairo_show_layout(cairo, layout); /* Draw */ guac_common_surface_draw(display->display_surface, display->char_width * col, display->char_height * row, surface); /* Free all */ g_object_unref(layout); cairo_destroy(cairo); cairo_surface_destroy(surface); return 0; }
static uint32_t render_detailed(cairo_t *cairo, struct swaynag *swaynag, uint32_t y) { uint32_t width = swaynag->width * swaynag->scale; int border = swaynag->type->details_border_thickness * swaynag->scale; int padding = swaynag->type->message_padding * swaynag->scale; int decor = padding + border; swaynag->details.x = decor; swaynag->details.y = y * swaynag->scale + decor; swaynag->details.width = width - decor * 2; PangoLayout *layout = get_pango_layout(cairo, swaynag->type->font, swaynag->details.message, swaynag->scale, false); pango_layout_set_width(layout, (swaynag->details.width - padding * 2) * PANGO_SCALE); pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR); pango_layout_set_single_paragraph_mode(layout, false); pango_cairo_update_layout(cairo, layout); swaynag->details.total_lines = pango_layout_get_line_count(layout); PangoLayoutLine *line; line = pango_layout_get_line_readonly(layout, swaynag->details.offset); gint offset = line->start_index; const char *text = pango_layout_get_text(layout); pango_layout_set_text(layout, text + offset, strlen(text) - offset); int text_width, text_height; pango_cairo_update_layout(cairo, layout); pango_layout_get_pixel_size(layout, &text_width, &text_height); bool show_buttons = swaynag->details.offset > 0; int button_width = get_detailed_scroll_button_width(cairo, swaynag); if (show_buttons) { swaynag->details.width -= button_width; pango_layout_set_width(layout, (swaynag->details.width - padding * 2) * PANGO_SCALE); } uint32_t ideal_height; do { ideal_height = swaynag->details.y + text_height + decor + padding * 2; if (ideal_height > SWAYNAG_MAX_HEIGHT) { ideal_height = SWAYNAG_MAX_HEIGHT; if (!show_buttons) { show_buttons = true; swaynag->details.width -= button_width; pango_layout_set_width(layout, (swaynag->details.width - padding * 2) * PANGO_SCALE); } } swaynag->details.height = ideal_height - swaynag->details.y - decor; pango_layout_set_height(layout, (swaynag->details.height - padding * 2) * PANGO_SCALE); pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END); pango_cairo_update_layout(cairo, layout); pango_layout_get_pixel_size(layout, &text_width, &text_height); } while (text_height != (swaynag->details.height - padding * 2)); swaynag->details.visible_lines = pango_layout_get_line_count(layout); if (show_buttons) { swaynag->details.button_up.x = swaynag->details.x + swaynag->details.width; swaynag->details.button_up.y = swaynag->details.y; swaynag->details.button_up.width = button_width; swaynag->details.button_up.height = swaynag->details.height / 2; render_details_scroll_button(cairo, swaynag, &swaynag->details.button_up); swaynag->details.button_down.x = swaynag->details.x + swaynag->details.width; swaynag->details.button_down.y = swaynag->details.button_up.y + swaynag->details.button_up.height; swaynag->details.button_down.width = button_width; swaynag->details.button_down.height = swaynag->details.height / 2; render_details_scroll_button(cairo, swaynag, &swaynag->details.button_down); } cairo_set_source_u32(cairo, swaynag->type->border); cairo_rectangle(cairo, swaynag->details.x, swaynag->details.y, swaynag->details.width, swaynag->details.height); cairo_fill(cairo); cairo_move_to(cairo, swaynag->details.x + padding, swaynag->details.y + padding); cairo_set_source_u32(cairo, swaynag->type->text); pango_cairo_show_layout(cairo, layout); g_object_unref(layout); return ideal_height / swaynag->scale; }
static void marlin_text_renderer_get_size (GtkCellRenderer *cell, GtkWidget *widget, const GdkRectangle *cell_area, gint *x_offset, gint *y_offset, gint *width, gint *height) { MarlinTextRenderer *text_renderer = MARLIN_TEXT_RENDERER (cell); gint text_length; gint text_width; gint text_height; gint xpad, ypad; /* setup the new widget */ marlin_text_renderer_set_widget (text_renderer, widget); gfloat xalign, yalign; gtk_cell_renderer_get_alignment (cell, &xalign, &yalign); /* we can guess the dimensions if we don't wrap */ if (text_renderer->wrap_width < 0) { /* determine the text_length in characters */ text_length = g_utf8_strlen (text_renderer->text, -1); /* the approximation is usually 1-2 chars wrong, so wth */ text_length += 2; /* calculate the appromixate text width/height */ text_width = text_renderer->char_width * text_length; text_height = text_renderer->char_height; } else { /* calculate the real text dimension */ pango_layout_set_ellipsize (text_renderer->layout, PANGO_ELLIPSIZE_END); pango_layout_set_height (text_renderer->layout, -3); pango_layout_set_width (text_renderer->layout, text_renderer->wrap_width * PANGO_SCALE); pango_layout_set_wrap (text_renderer->layout, text_renderer->wrap_mode); pango_layout_set_text (text_renderer->layout, text_renderer->text, -1); if (xalign == 0.5f) pango_layout_set_alignment (text_renderer->layout, PANGO_ALIGN_CENTER); pango_layout_get_pixel_size (text_renderer->layout, &text_width, &text_height); } /* if we have to follow the state manually, we'll need * to reserve some space to render the indicator to. */ if (text_renderer->follow_state) { text_width += 2 * text_renderer->focus_width; text_height += 2 * text_renderer->focus_width; } gtk_cell_renderer_get_padding (cell, &xpad, &ypad); /* update width/height */ if (G_LIKELY (width != NULL)) *width = text_width + 2 * xpad; if (G_LIKELY (height != NULL)) *height = text_height + 2 * ypad; /* update the x/y offsets */ if (G_LIKELY (cell_area != NULL)) { /*gfloat xalign, yalign; gtk_cell_renderer_get_alignment (cell, &xalign, &yalign);*/ if (G_LIKELY (x_offset != NULL)) { *x_offset = ((gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) ? (1.0 - xalign) : xalign) * (cell_area->width - text_width - (2 * xpad)); *x_offset = MAX (*x_offset, 0); } if (G_LIKELY (y_offset != NULL)) { *y_offset = yalign * (cell_area->height - text_height - (2 * ypad)); *y_offset = MAX (*y_offset, 0); } } }