示例#1
0
static void font_measure_full(const RrFont *f, const gchar *str,
                              gint *x, gint *y, gint shadow_x, gint shadow_y,
                              gboolean flow, gint maxwidth)
{
    PangoRectangle rect;

    pango_layout_set_text(f->layout, str, -1);
    if (flow) {
        pango_layout_set_single_paragraph_mode(f->layout, FALSE);
        pango_layout_set_width(f->layout, maxwidth * PANGO_SCALE);
        pango_layout_set_ellipsize(f->layout, PANGO_ELLIPSIZE_NONE);
    }
    else {
        /* single line mode */
        pango_layout_set_single_paragraph_mode(f->layout, TRUE);
        pango_layout_set_width(f->layout, -1);
        pango_layout_set_ellipsize(f->layout, PANGO_ELLIPSIZE_MIDDLE);
    }

    /* pango_layout_get_pixel_extents lies! this is the right way to get the
       size of the text's area */
    pango_layout_get_extents(f->layout, NULL, &rect);
#if PANGO_VERSION_MAJOR > 1 || \
    (PANGO_VERSION_MAJOR == 1 && PANGO_VERSION_MINOR >= 16)
    /* pass the logical rect as the ink rect, this is on purpose so we get the
       full area for the text */
    pango_extents_to_pixels(&rect, NULL);
#else
    rect.width = (rect.width + PANGO_SCALE - 1) / PANGO_SCALE;
    rect.height = (rect.height + PANGO_SCALE - 1) / PANGO_SCALE;
#endif
    *x = rect.width + ABS(shadow_x) + 4 /* we put a 2 px edge on each side */;
    *y = rect.height + ABS(shadow_y);
}
示例#2
0
text_wrapper::text_wrapper(void)
{
    // voids everything
    utf8_text = NULL;
    uni32_text = NULL;
    glyph_text = NULL;
    utf8_length = 0;
    uni32_length = 0;
    glyph_length = 0;
    utf8_codepoint = NULL;
    uni32_codepoint = NULL;
    default_font = NULL;
    bounds = NULL;
    nbBound = maxBound = 0;
    boxes = NULL;
    nbBox = maxBox = 0;
    paras = NULL;
    nbPara = maxPara = 0;
    kern_x = kern_y = NULL;
    last_addition = -1;
    // inits the pangolayout with default params
    font_factory *font_src = font_factory::Default();
    pLayout = pango_layout_new(font_src->fontContext);
    pango_layout_set_single_paragraph_mode(pLayout, true);
    pango_layout_set_width(pLayout, -1);
}
示例#3
0
void ZDrawSongInfo(IDirectFB *dfb, IDirectFBSurface *dfbsurface, const gchar *title, const gchar *artist, 
		gint w, gint h, DFBColor *color, DFBColor *strokeColor, double strokeWidth, const PangoFontDescription *desc)
{
	cairo_t *cr = NULL;
	cairo_surface_t *surface = NULL;
	cairo_surface_t *cairosurface = NULL;
	PangoLayout *layout = NULL;
	
	if(!dfb || !dfbsurface)
		return;
	
	/* prepare layout */
	layout = pango_layout_new(gdk_pango_context_get());
	pango_layout_set_single_paragraph_mode (layout, TRUE);
	pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER);
	pango_layout_set_width(layout, w* PANGO_SCALE);
	pango_layout_set_font_description(layout, desc);
	
	surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w, h);
	cr = cairo_create(surface);
	
	/* Draw title */
	if(title) {
		pango_layout_set_text(layout, title, -1);
		cairo_move_to(cr, 0, 0);
		pango_cairo_layout_path(cr, layout);
		ZCairoSetDFBColor(cr, strokeColor);
		cairo_set_line_width(cr, strokeWidth);
		cairo_stroke_preserve(cr);
		
		ZCairoSetDFBColor(cr, color);
		cairo_fill(cr);
	}
	
	/* Draw artist */
	if(artist) {
		pango_layout_set_text(layout, artist, -1);
		cairo_move_to(cr, 0, h/2);
		pango_cairo_layout_path(cr, layout);
		ZCairoSetDFBColor(cr, strokeColor);
		cairo_set_line_width(cr, strokeWidth);
		cairo_stroke_preserve(cr);
		
		ZCairoSetDFBColor(cr, color);
		cairo_fill(cr);
	}
	
	g_object_unref(layout);
	cairo_destroy(cr);
	
	/* Draw cairo_surface to dfbsurface */
	/* create surface */
	cairosurface = cairo_directfb_surface_create(dfb, dfbsurface);
	cr = cairo_create(cairosurface);
	cairo_set_source_surface(cr, surface, 0, 0);
	cairo_paint(cr);
	cairo_destroy(cr);
	cairo_surface_destroy(surface);
	cairo_surface_destroy(cairosurface);
}
示例#4
0
文件: pango.c 项目: thejan2009/sway
PangoLayout *get_pango_layout(cairo_t *cairo, const char *font,
		const char *text, double scale, bool markup) {
	PangoLayout *layout = pango_cairo_create_layout(cairo);
	PangoAttrList *attrs;
	if (markup) {
		char *buf;
		GError *error = NULL;
		if (pango_parse_markup(text, -1, 0, &attrs, &buf, NULL, &error)) {
			pango_layout_set_text(layout, buf, -1);
			free(buf);
		} else {
			sway_log(SWAY_ERROR, "pango_parse_markup '%s' -> error %s", text,
					error->message);
			g_error_free(error);
			markup = false; // fallback to plain text
		}
	}
	if (!markup) {
		attrs = pango_attr_list_new();
		pango_layout_set_text(layout, text, -1);
	}

	pango_attr_list_insert(attrs, pango_attr_scale_new(scale));
	PangoFontDescription *desc = pango_font_description_from_string(font);
	pango_layout_set_font_description(layout, desc);
	pango_layout_set_single_paragraph_mode(layout, 1);
	pango_layout_set_attributes(layout, attrs);
	pango_attr_list_unref(attrs);
	pango_font_description_free(desc);
	return layout;
}
示例#5
0
PangoLayout * VwGraphicsCairo::GetPangoLayoutHelper()
{
	if (m_fontMap == NULL)
		m_fontMap = pango_cairo_font_map_get_default();

	if (m_context == NULL)
	{	m_context = pango_context_new();
		pango_context_set_font_map(m_context, m_fontMap);
	}

	if (m_layout == NULL)
	{
		m_layout = pango_layout_new(m_context);

		PangoAttrList* list = pango_attr_list_new();
		PangoAttribute * fallbackAttrib = pango_attr_fallback_new(true);
		pango_attr_list_insert(list, fallbackAttrib);
		pango_layout_set_attributes(m_layout, list);
		pango_attr_list_unref(list);

		pango_layout_set_single_paragraph_mode(m_layout, true);
	}

	return m_layout;
}
示例#6
0
void ZCairoDrawLyric(cairo_t *cr, gboolean isUpLine, 
				gint space, gint w, gint h, 
				DFBColor *bgColor, const gchar *text, gint fullWidth, 
				DFBColor *color1, DFBColor *strokeColor1, double strokeWidth1, 
				DFBColor *color2, DFBColor *strokeColor2, double strokeWidth2, 
				const PangoFontDescription *desc)
{
	PangoLayout *layout = NULL;
	gint x, y;
	
	/* Prepare layout */
	layout = pango_layout_new(gdk_pango_context_get());
	pango_layout_set_single_paragraph_mode (layout, TRUE);
	pango_layout_set_alignment(layout, isUpLine ? PANGO_ALIGN_LEFT : PANGO_ALIGN_RIGHT);
	pango_layout_set_font_description(layout, desc);
	pango_layout_set_text(layout, text, -1);
	
	/* Clear background */
	cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
	cairo_paint(cr);
	cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
	
	/* Draw background */
	if(bgColor) {
		ZCairoSetDFBColor(cr, bgColor);
		cairo_paint(cr);
	}
	
	/* Draw original text */
	x = isUpLine ? space : w - fullWidth - space;
	y = 0;
	cairo_move_to(cr, x, y);
	pango_cairo_layout_path(cr, layout);
	ZCairoSetDFBColor(cr, strokeColor1);
	cairo_set_line_width(cr, strokeWidth1);
	cairo_stroke_preserve(cr);
	
	ZCairoSetDFBColor(cr, color1);
	cairo_fill(cr);
	
	/* Draw effect text */
	y = h/2;
	cairo_move_to(cr, x, y);
	pango_cairo_layout_path(cr, layout);
	ZCairoSetDFBColor(cr, strokeColor2);
	cairo_set_line_width(cr, strokeWidth2);
	cairo_stroke_preserve(cr);
	
	ZCairoSetDFBColor(cr, color2);
	cairo_fill(cr);
	
	g_object_unref(layout);
}
示例#7
0
/**
 * Find where to split a string to make it fit a width.
 *
 * \param[in] fstyle       style for this text
 * \param[in] string       UTF-8 string to measure
 * \param[in] length       length of string, in bytes
 * \param[in] x            width available
 * \param[out] char_offset updated to offset in string of actual_x, [1..length]
 * \param[out] actual_x updated to x coordinate of character closest to x
 * \return NSERROR_OK or appropriate error code on faliure
 *
 * On exit, char_offset indicates first character after split point.
 *
 * \note char_offset of 0 must never be returned.
 *
 *   Returns:
 *     char_offset giving split point closest to x, where actual_x <= x
 *   else
 *     char_offset giving split point closest to x, where actual_x > x
 *
 * Returning char_offset == length means no split possible
 */
static nserror
nsfont_split(const plot_font_style_t *fstyle,
	     const char *string,
	     size_t length,
	     int x,
	     size_t *char_offset,
	     int *actual_x)
{
	int index = length;
	PangoFontDescription *desc;
	PangoContext *context;
	PangoLayout *layout;
	PangoLayoutLine *line;

	context = gdk_pango_context_get();
	layout = pango_layout_new(context);

	desc = nsfont_style_to_description(fstyle);
	pango_layout_set_font_description(layout, desc);
	pango_font_description_free(desc);

	pango_layout_set_text(layout, string, length);

	/* Limit width of layout to the available width */
	pango_layout_set_width(layout, x * PANGO_SCALE);

	/* Request word wrapping */
	pango_layout_set_wrap(layout, PANGO_WRAP_WORD);

	/* Prevent pango treating linebreak characters as line breaks */
	pango_layout_set_single_paragraph_mode(layout, TRUE);

	/* Obtain the second line of the layout (if there is one) */
	line = pango_layout_get_line(layout, 1);
	if (line != NULL) {
		/* Pango split the text. The line's start_index indicates the 
		 * start of the character after the line break. */
		index = line->start_index;
	}

	g_object_unref(layout);
	g_object_unref(context);

	*char_offset = index;
	/* Obtain the pixel offset of the split character */
	nsfont_width(fstyle, string, index, actual_x);

	return NSERROR_OK;
}
static void
ensure_title_and_icon_pixbuf (GdlDockItemGrip *grip)
{
    gchar *stock_id;
    GdkPixbuf *pixbuf;
    
    g_return_if_fail (GDL_IS_DOCK_ITEM_GRIP (grip));
    
    /* get long name property from the dock object */
    if (!grip->_priv->title) {
        g_object_get (G_OBJECT (grip->item), "long-name", &grip->_priv->title, NULL);
        if (!grip->_priv->title)
            grip->_priv->title = g_strdup ("");
    }

    /* retrieve stock pixbuf, if any */
    if (!grip->_priv->icon_pixbuf_valid) {
        g_object_get (G_OBJECT (grip->item), "stock-id", &stock_id, NULL);
        
        if (stock_id) {
            grip->_priv->icon_pixbuf = gtk_widget_render_icon (GTK_WIDGET (grip),
                                                               stock_id,
                                                               GTK_ICON_SIZE_MENU, "");
            g_free (stock_id);
            grip->_priv->icon_pixbuf_valid = TRUE;
        }
    }

    /* retrieve pixbuf icon, if any */
    if (!grip->_priv->icon_pixbuf_valid) {
        g_object_get (G_OBJECT (grip->item), "pixbuf-icon", &pixbuf, NULL);
        
        if (pixbuf) {
            grip->_priv->icon_pixbuf = pixbuf;
            grip->_priv->icon_pixbuf_valid = TRUE;
        }
    }

    /* create layout: the actual text is reset at size_allocate */
    if (!grip->_priv->title_layout) {
        grip->_priv->title_layout = gtk_widget_create_pango_layout (GTK_WIDGET (grip),
                                                                    grip->_priv->title);
        pango_layout_set_single_paragraph_mode (grip->_priv->title_layout, TRUE);
    }
}
示例#9
0
文件: pango.c 项目: SirCmpwn/sway
PangoLayout *get_pango_layout(cairo_t *cairo, const char *font, const char *text,
		int32_t scale, bool markup) {
	PangoLayout *layout = pango_cairo_create_layout(cairo);
	PangoAttrList *attrs;
	if (markup) {
		char *buf;
		pango_parse_markup(text, -1, 0, &attrs, &buf, NULL, NULL);
		pango_layout_set_markup(layout, buf, -1);
		free(buf);
	} else {
		attrs = pango_attr_list_new();
		pango_layout_set_text(layout, text, -1);
	}
	pango_attr_list_insert(attrs, pango_attr_scale_new(scale));
	PangoFontDescription *desc = pango_font_description_from_string(font);
	pango_layout_set_font_description(layout, desc);
	pango_layout_set_single_paragraph_mode(layout, 1);
	pango_layout_set_attributes(layout, attrs);
	pango_attr_list_unref(attrs);
	pango_font_description_free(desc);
	return layout;
}
static void
thunar_text_renderer_set_widget (ThunarTextRenderer *text_renderer,
                                 GtkWidget          *widget)
{
  PangoFontMetrics *metrics;
  PangoContext     *context;
  gint              focus_padding;
  gint              focus_line_width;

  if (G_LIKELY (widget == text_renderer->widget))
    return;

  /* disconnect from the previously set widget */
  if (G_UNLIKELY (text_renderer->widget != NULL))
    {
      g_signal_handlers_disconnect_by_func (G_OBJECT (text_renderer->widget), thunar_text_renderer_invalidate, text_renderer);
      g_object_unref (G_OBJECT (text_renderer->layout));
      g_object_unref (G_OBJECT (text_renderer->widget));
    }

  /* activate the new widget */
  text_renderer->widget = widget;

  /* connect to the new widget */
  if (G_LIKELY (widget != NULL))
    {
      /* take a reference on the widget */
      g_object_ref (G_OBJECT (widget));

      /* we need to recalculate the metrics when a new style (and thereby a new font) is set */
      g_signal_connect_swapped (G_OBJECT (text_renderer->widget), "destroy", G_CALLBACK (thunar_text_renderer_invalidate), text_renderer);
      g_signal_connect_swapped (G_OBJECT (text_renderer->widget), "style-set", G_CALLBACK (thunar_text_renderer_invalidate), text_renderer);

      /* allocate a new pango layout for this widget */
      context = gtk_widget_get_pango_context (widget);
      text_renderer->layout = pango_layout_new (context);

      /* disable automatic text direction, but use the direction specified by Gtk+ */
      pango_layout_set_auto_dir (text_renderer->layout, FALSE);

      /* we don't want to interpret line separators in file names */
      pango_layout_set_single_paragraph_mode (text_renderer->layout, TRUE);

      /* calculate the average character dimensions */
      metrics = pango_context_get_metrics (context, widget->style->font_desc, pango_context_get_language (context));
      text_renderer->char_width = PANGO_PIXELS (pango_font_metrics_get_approximate_char_width (metrics));
      text_renderer->char_height = PANGO_PIXELS (pango_font_metrics_get_ascent (metrics) + pango_font_metrics_get_descent (metrics));
      pango_font_metrics_unref (metrics);

      /* tell the cell renderer about the fixed height if we're not wrapping text */
      if (G_LIKELY (text_renderer->wrap_width < 0))
        gtk_cell_renderer_set_fixed_size (GTK_CELL_RENDERER (text_renderer), -1, text_renderer->char_height);

      /* determine the focus-padding and focus-line-width style properties from the widget */
      gtk_widget_style_get (widget, "focus-padding", &focus_padding, "focus-line-width", &focus_line_width, NULL);
      text_renderer->focus_width = focus_padding + focus_line_width;
    }
  else
    {
      text_renderer->layout = NULL;
      text_renderer->char_width = 0;
      text_renderer->char_height = 0;
    }
}
示例#11
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));
}
示例#12
0
文件: pango.c 项目: epu/ImageMagick
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   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));
}
示例#13
0
static VALUE
rg_set_single_paragraph_mode(VALUE self, VALUE setting)
{
    pango_layout_set_single_paragraph_mode(_SELF(self), RVAL2CBOOL(setting));
    return self;
}
示例#14
0
static PangoLayout*
create_layout(HippoCanvasText *text,
              int              allocation_width)
{
    HippoCanvasBox *box = HIPPO_CANVAS_BOX(text);
    PangoLayout *layout;
    HippoCanvasStyle *style = hippo_canvas_context_get_style(HIPPO_CANVAS_CONTEXT(text));

    g_return_val_if_fail(box->context != NULL, NULL);
    
    layout = hippo_canvas_context_create_layout(box->context);

    if (box->font_desc) {
        PangoFontDescription *merged = pango_font_description_copy(hippo_canvas_style_get_font(style));
        pango_font_description_merge(merged, box->font_desc, TRUE);
        pango_layout_set_font_description(layout, merged);
        pango_font_description_free(merged);
    } else {
        pango_layout_set_font_description(layout, hippo_canvas_style_get_font(style));
    }
    
    {
        PangoAttrList *attrs;
        HippoTextDecoration decoration = hippo_canvas_style_get_text_decoration(style);
        
        if (text->attributes)
            attrs = pango_attr_list_copy(text->attributes);
        else
            attrs = pango_attr_list_new();

        
        if (ABS(1.0 - text->font_scale) > .000001) {
            PangoAttribute *attr = pango_attr_scale_new(text->font_scale);
            attr->start_index = 0;
            attr->end_index = G_MAXUINT;
            pango_attr_list_insert(attrs, attr);
        }

        if ((decoration & HIPPO_TEXT_DECORATION_UNDERLINE) != 0) {
            PangoAttribute *attr = pango_attr_underline_new(TRUE);
            attr->start_index = 0;
            attr->end_index = G_MAXUINT;
            pango_attr_list_insert(attrs, attr);
        }

        if ((decoration & HIPPO_TEXT_DECORATION_LINE_THROUGH) != 0) {
            PangoAttribute *attr = pango_attr_strikethrough_new(TRUE);
            attr->start_index = 0;
            attr->end_index = G_MAXUINT;
            pango_attr_list_insert(attrs, attr);
        }

        pango_layout_set_attributes(layout, attrs);
        pango_attr_list_unref(attrs);
    }
    
    if (text->text != NULL) {
        pango_layout_set_text(layout, text->text, -1);
    }

    if (allocation_width >= 0) {
        int layout_width, layout_height;
        pango_layout_get_size(layout, &layout_width, &layout_height);
        layout_width /= PANGO_SCALE;
        layout_height /= PANGO_SCALE;
        
        /* Force layout smaller if required, but we don't want to make
         * the layout _wider_ because it breaks alignment, so only do
         * this if required.
         */
        if (layout_width > allocation_width) {
            pango_layout_set_width(layout, allocation_width * PANGO_SCALE);

            /* If we set ellipsize, then it overrides wrapping. If we get
             * too-small allocation for HIPPO_CANVAS_SIZE_FULL_WIDTH, then
             * we want to ellipsize instead of wrapping.
             */
            if (text->size_mode == HIPPO_CANVAS_SIZE_WRAP_WORD) {
                pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_NONE);
            } else {
                pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END);
            }

            /* For now if we say ellipsize end, we always just want one line.
             * Maybe this should be an orthogonal property?
             */
            if (text->size_mode == HIPPO_CANVAS_SIZE_ELLIPSIZE_END) {
                pango_layout_set_single_paragraph_mode(layout, TRUE);

                /* Pango's line separator character in this case is ugly, so we
                 * fix it. Not a very efficient approach, but oh well.
                 */
                if (text->text != NULL) {
                    char *new_text = remove_newlines(text->text);
                    /* avoid making the layout recompute everything
                     * if we didn't have newlines anyhow
                     */
                    if (strcmp(text->text, new_text) != 0) {
                        pango_layout_set_text(layout, new_text, -1);
                    }
                    g_free(new_text);
                }
            }
        }
    }
    
    return layout;
}
示例#15
0
void RrFontDraw(XftDraw *d, RrTextureText *t, RrRect *area)
{
    gint x,y,w;
    XftColor c;
    gint mw;
    PangoRectangle rect;
    PangoAttrList *attrlist;
    PangoEllipsizeMode ell;

    g_assert(!t->flow || t->maxwidth > 0);

    y = area->y;
    if (!t->flow)
        /* center the text vertically
           We do this centering based on the 'baseline' since different fonts
           have different top edges. It looks bad when the whole string is
           moved when 1 character from a non-default language is included in
           the string */
        y += font_calculate_baseline(t->font, area->height);

    /* the +2 and -4 leave a small blank edge on the sides */
    x = area->x + 2;
    w = area->width;
    if (t->flow) w = MAX(w, t->maxwidth);
    w -= 4;
    /* h = area->height; */

    if (t->flow)
        ell = PANGO_ELLIPSIZE_NONE;
    else {
        switch (t->ellipsize) {
        case RR_ELLIPSIZE_NONE:
            ell = PANGO_ELLIPSIZE_NONE;
            break;
        case RR_ELLIPSIZE_START:
            ell = PANGO_ELLIPSIZE_START;
            break;
        case RR_ELLIPSIZE_MIDDLE:
            ell = PANGO_ELLIPSIZE_MIDDLE;
            break;
        case RR_ELLIPSIZE_END:
            ell = PANGO_ELLIPSIZE_END;
            break;
        default:
            g_assert_not_reached();
        }
    }

    pango_layout_set_text(t->font->layout, t->string, -1);
    pango_layout_set_width(t->font->layout, w * PANGO_SCALE);
    pango_layout_set_ellipsize(t->font->layout, ell);
    pango_layout_set_single_paragraph_mode(t->font->layout, !t->flow);

    /* * * end of setting up the layout * * */

    pango_layout_get_pixel_extents(t->font->layout, NULL, &rect);
    mw = rect.width;

    /* pango_layout_set_alignment doesn't work with
       pango_xft_render_layout_line */
    switch (t->justify) {
    case RR_JUSTIFY_LEFT:
        break;
    case RR_JUSTIFY_RIGHT:
        x += (w - mw);
        break;
    case RR_JUSTIFY_CENTER:
        x += (w - mw) / 2;
        break;
    case RR_JUSTIFY_NUM_TYPES:
        g_assert_not_reached();
    }

    if (t->shadow_offset_x || t->shadow_offset_y) {
        /* From nvidia's readme (chapter 23):

           When rendering to a 32-bit window, keep in mind that the X RENDER
           extension, used by most composite managers, expects "premultiplied
           alpha" colors. This means that if your color has components (r,g,b)
           and alpha value a, then you must render (a*r, a*g, a*b, a) into the
           target window.
        */
        c.color.red = (t->shadow_color->r | t->shadow_color->r << 8) *
            t->shadow_alpha / 255;
        c.color.green = (t->shadow_color->g | t->shadow_color->g << 8) *
            t->shadow_alpha / 255;
        c.color.blue = (t->shadow_color->b | t->shadow_color->b << 8) *
            t->shadow_alpha / 255;
        c.color.alpha = 0xffff * t->shadow_alpha / 255;
        c.pixel = t->shadow_color->pixel;

        /* see below... */
        if (!t->flow) {
            pango_xft_render_layout_line
                (d, &c,
#if PANGO_VERSION_MAJOR > 1 || \
    (PANGO_VERSION_MAJOR == 1 && PANGO_VERSION_MINOR >= 16)
                 pango_layout_get_line_readonly(t->font->layout, 0),
#else
                 pango_layout_get_line(t->font->layout, 0),
#endif
                 (x + t->shadow_offset_x) * PANGO_SCALE,
                 (y + t->shadow_offset_y) * PANGO_SCALE);
        }
        else {
            pango_xft_render_layout(d, &c, t->font->layout,
                                    (x + t->shadow_offset_x) * PANGO_SCALE,
                                    (y + t->shadow_offset_y) * PANGO_SCALE);
        }
    }

    c.color.red = t->color->r | t->color->r << 8;
    c.color.green = t->color->g | t->color->g << 8;
    c.color.blue = t->color->b | t->color->b << 8;
    c.color.alpha = 0xff | 0xff << 8; /* fully opaque text */
    c.pixel = t->color->pixel;

    if (t->shortcut) {
        const gchar *s = t->string + t->shortcut_pos;

        t->font->shortcut_underline->start_index = t->shortcut_pos;
        t->font->shortcut_underline->end_index = t->shortcut_pos +
            (g_utf8_next_char(s) - s);

        /* the attributes are owned by the layout.
           re-add the attributes to the layout after changing the
           start and end index */
        attrlist = pango_layout_get_attributes(t->font->layout);
        pango_attr_list_ref(attrlist);
        pango_layout_set_attributes(t->font->layout, attrlist);
        pango_attr_list_unref(attrlist);
    }

    /* layout_line() uses y to specify the baseline
       The line doesn't need to be freed, it's a part of the layout */
    if (!t->flow) {
        pango_xft_render_layout_line
            (d, &c,
#if PANGO_VERSION_MAJOR > 1 || \
    (PANGO_VERSION_MAJOR == 1 && PANGO_VERSION_MINOR >= 16)
             pango_layout_get_line_readonly(t->font->layout, 0),
#else
             pango_layout_get_line(t->font->layout, 0),
#endif
             x * PANGO_SCALE,
             y * PANGO_SCALE);
    }
    else {
        pango_xft_render_layout(d, &c, t->font->layout,
                                x * PANGO_SCALE,
                                y * PANGO_SCALE);
    }

    if (t->shortcut) {
        t->font->shortcut_underline->start_index = 0;
        t->font->shortcut_underline->end_index = 0;
        /* the attributes are owned by the layout.
           re-add the attributes to the layout after changing the
           start and end index */
        attrlist = pango_layout_get_attributes(t->font->layout);
        pango_attr_list_ref(attrlist);
        pango_layout_set_attributes(t->font->layout, attrlist);
        pango_attr_list_unref(attrlist);
    }
}
示例#16
0
文件: render.c 项目: bakunowski/sway
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;
}