Esempio n. 1
0
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);
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
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);
}
Esempio n. 4
0
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);
}
Esempio n. 6
0
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);
	}
}
Esempio n. 7
0
File: cawc.c Progetto: Roger/caw
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;
}
Esempio n. 8
0
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);
}
Esempio n. 9
0
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);
}
Esempio n. 10
0
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;
}
Esempio n. 11
0
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;
}
Esempio n. 12
0
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;
}
Esempio n. 14
0
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);
}
Esempio n. 16
0
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);
}
Esempio n. 17
0
static VALUE
rg_set_height(VALUE self, VALUE width)
{
    pango_layout_set_height(_SELF(self), NUM2INT(width));
    return self;
}
Esempio n. 18
0
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);
}
Esempio n. 19
0
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));
}
Esempio n. 20
0
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, &note_color))
    gdk_cairo_set_source_rgba (cr, &note_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;	
}
Esempio n. 22
0
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   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));
}
Esempio n. 23
0
 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 );
 }
Esempio n. 24
0
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);
}
Esempio n. 25
0
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;
}
Esempio n. 26
0
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);
}
Esempio n. 27
0
/**
 * 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;

}
Esempio n. 28
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;
}
Esempio n. 29
0
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);
        }
    }
}