示例#1
0
static void 
print_pango_layout (GnomePrintContext *gpc, PangoLayout *layout)
{
	PangoLayoutIter *iter;
	
	gnome_print_gsave (gpc);
	
	current_point_to_origin (gpc);
	
	iter = pango_layout_get_iter (layout);
	
	do {
		PangoRectangle   logical_rect;
		PangoLayoutLine *line;
		int              baseline;
		
		line = pango_layout_iter_get_line (iter);
		
		pango_layout_iter_get_line_extents (iter, NULL, &logical_rect);
		baseline = pango_layout_iter_get_baseline (iter);
		
		moveto (gpc, logical_rect.x, - baseline);
		print_pango_layout_line (gpc, line);

	} while (pango_layout_iter_next_line (iter));

	pango_layout_iter_free (iter);
	
	gnome_print_grestore (gpc);
}
示例#2
0
static PyObject *
pango_GetLayoutLinePos(PyObject *self, PyObject *args) {

	int i, len;
	double baseline, dy;
	void *LayoutObj;
	PangoLayout *layout;
	PangoLayoutIter *iter;
	PyObject *ret;

	if (!PyArg_ParseTuple(args, "O", &LayoutObj)) {
		return NULL;
	}

	layout = PyCObject_AsVoidPtr(LayoutObj);

	len = pango_layout_get_line_count(layout);
	ret = PyTuple_New(len);
	iter = pango_layout_get_iter(layout);
	dy = ((double) pango_layout_iter_get_baseline(iter)) / PANGO_SCALE;

	for (i = 0; i < len; i++) {
		baseline = -1.0 * ((double) pango_layout_iter_get_baseline(iter))
				/ PANGO_SCALE + dy;
		PyTuple_SetItem(ret, i, PyFloat_FromDouble(baseline));
		pango_layout_iter_next_line(iter);
	}

	pango_layout_iter_free(iter);

	return ret;
}
示例#3
0
void
x11_draw_layout_with_colors( Drawable      drawable,
                             GC            gc,
                             int           x,
                             int           y,
                             PangoLayout  *layout,
                             wxColour       &colour )
{
    PangoLayoutIter *iter = pango_layout_get_iter (layout);

    do
    {
        PangoLayoutLine *line = pango_layout_iter_get_line (iter);

        PangoRectangle logical_rect;
        pango_layout_iter_get_line_extents (iter, NULL, &logical_rect);

        int baseline = pango_layout_iter_get_baseline (iter);

        x11_draw_layout_line_with_colors( drawable, gc,
                                          x + logical_rect.x / PANGO_SCALE,
                                          y + baseline / PANGO_SCALE,
                                          line,
                                          colour );

    } while (pango_layout_iter_next_line (iter));

    pango_layout_iter_free (iter);
}
示例#4
0
文件: print-editor.c 项目: GYGit/gtk
static void
draw_page (GtkPrintOperation *operation,
	   GtkPrintContext *context,
	   int page_nr,
	   PrintData *print_data)
{
  cairo_t *cr;
  GList *pagebreak;
  int start, end, i;
  PangoLayoutIter *iter;
  double start_pos;

  if (page_nr == 0)
    start = 0;
  else
    {
      pagebreak = g_list_nth (print_data->page_breaks, page_nr - 1);
      start = GPOINTER_TO_INT (pagebreak->data);
    }

  pagebreak = g_list_nth (print_data->page_breaks, page_nr);
  if (pagebreak == NULL)
    end = pango_layout_get_line_count (print_data->layout);
  else
    end = GPOINTER_TO_INT (pagebreak->data);
    
  cr = gtk_print_context_get_cairo_context (context);

  cairo_set_source_rgb (cr, 0, 0, 0);
  
  i = 0;
  start_pos = 0;
  iter = pango_layout_get_iter (print_data->layout);
  do
    {
      PangoRectangle   logical_rect;
      PangoLayoutLine *line;
      int              baseline;

      if (i >= start)
	{
	  line = pango_layout_iter_get_line (iter);

	  pango_layout_iter_get_line_extents (iter, NULL, &logical_rect);
	  baseline = pango_layout_iter_get_baseline (iter);
	  
	  if (i == start)
	    start_pos = logical_rect.y / 1024.0;
	  
	  cairo_move_to (cr, logical_rect.x / 1024.0, baseline / 1024.0 - start_pos);
	  
	  pango_cairo_show_layout_line  (cr, line);
	}
      i++;
    }
  while (i < end &&
	 pango_layout_iter_next_line (iter));

  pango_layout_iter_free (iter);
}
示例#5
0
/** Get size information for the given string, font and height.
 *
 * @returns an array of offsets of the individual glyphs in the layout.
 */
real*
dia_font_get_sizes(const char* string, DiaFont *font, real height,
		   real *width, real *ascent, real *descent, int *n_offsets,
		   PangoLayoutLine **layout_offsets)
{
  PangoLayout* layout;
  PangoLayoutIter* iter;
  real top, bline, bottom;
  const gchar* non_empty_string;
  PangoRectangle ink_rect,logical_rect;
  real* offsets = NULL; /* avoid: 'offsets' may be used uninitialized in this function */

  /* We need some reasonable ascent/descent values even for empty strings. */
  if (string == NULL || string[0] == '\0') {
    non_empty_string = "XjgM149";
  } else {
    non_empty_string = string;
  }
  layout = dia_font_build_layout(non_empty_string, font, height * global_zoom_factor);

  /* Only one line here ? */
  iter = pango_layout_get_iter(layout);

  pango_layout_iter_get_line_extents(iter, &ink_rect, &logical_rect);

  top = pdu_to_dcm(logical_rect.y) / global_zoom_factor;
  bottom = pdu_to_dcm(logical_rect.y + logical_rect.height) / global_zoom_factor;
  bline = pdu_to_dcm(pango_layout_iter_get_baseline(iter)) / global_zoom_factor;

  get_string_offsets(iter, &offsets, n_offsets);
  get_layout_offsets(pango_layout_get_line(layout, 0), layout_offsets);

  /* FIXME: the above assumption of 'one line' is wrong. At least calculate the overall width correctly
   * to avoid text overflowing its box, like in bug #482585 */
  while (pango_layout_iter_next_line (iter)) {
    PangoRectangle more_ink_rect, more_logical_rect;

    pango_layout_iter_get_line_extents(iter, &more_ink_rect, &more_logical_rect);
    if (more_logical_rect.width > logical_rect.width)
      logical_rect.width = more_logical_rect.width;
    /* also calculate for the ink rect (true space needed for drawing the glyphs) */
    if (more_ink_rect.width > ink_rect.width)
      ink_rect.width = more_ink_rect.width;
  }

  pango_layout_iter_free(iter);
  g_object_unref(G_OBJECT(layout));

  *ascent = bline-top;
  *descent = bottom-bline;
  if (non_empty_string != string) {
    *width = 0.0;
  } else {
    /* take the bigger rectangle to avoid cutting of any part of the string */
    *width = pdu_to_dcm(logical_rect.width > ink_rect.width ? logical_rect.width : ink_rect.width) / global_zoom_factor;
  }
  return offsets;
}
示例#6
0
static void
fo_doc_cairo_do_callbacks (cairo_t     *cr,
			   PangoLayout *layout,
			   gint         line_first,
			   gint         line_last,
			   gint         x,
			   gint         y)
{
  PangoLayoutIter *iter;
  
  g_return_if_fail (cr != NULL);
  g_return_if_fail (PANGO_IS_LAYOUT (layout));
  g_return_if_fail (line_first >= 0);
  /*g_return_if_fail (line_last >= line_first &&
    line_last <= g_slist_length (pango_layout_get_lines (layout)) - 1);*/

  iter = pango_layout_get_iter (layout);

  gint line_number = -1;
  do
    {
      PangoRectangle   logical_rect;
      PangoLayoutLine *line;
      int              baseline;
      
      line_number++;

      if (line_number < line_first)
	{
	  continue;
	}

      line = pango_layout_iter_get_line (iter);
      
      pango_layout_iter_get_line_extents (iter, NULL, &logical_rect);
      baseline = pango_layout_iter_get_baseline (iter);
      
      fo_doc_cairo_do_line_callbacks (cr,
				      line,
				      x + logical_rect.x,
				      y - baseline);

      if (line_number >= line_last)
	{
	  break;
	}
    }
  while (pango_layout_iter_next_line (iter));

  pango_layout_iter_free (iter);
}
void
pango_clutter_ensure_glyph_cache_for_layout (PangoLayout *layout)
{
  PangoContext    *context;
  PangoFontMap    *fontmap;
  PangoRenderer   *renderer;
  PangoLayoutIter *iter;
 
  g_return_if_fail (PANGO_IS_LAYOUT (layout));
 
  context = pango_layout_get_context (layout);
  fontmap = pango_context_get_font_map (context);
  g_return_if_fail (PANGO_CLUTTER_IS_FONT_MAP (fontmap));
  renderer = _pango_clutter_font_map_get_renderer
    (PANGO_CLUTTER_FONT_MAP (fontmap));
 
  if ((iter = pango_layout_get_iter (layout)) == NULL)
    return;
 
  do
    {
      PangoLayoutLine *line;
      GSList *l;
 
      line = pango_layout_iter_get_line_readonly (iter);
 
      for (l = line->runs; l; l = l->next)
        {
          PangoLayoutRun *run = l->data;
          PangoGlyphString *glyphs = run->glyphs;
	  int i;
 
          for (i = 0; i < glyphs->num_glyphs; i++)
            {
              PangoGlyphInfo *gi = &glyphs->glyphs[i];
 
              if (!run->item->analysis.font)
                /* Font not found */
                continue;
	      pango_clutter_renderer_get_cached_glyph (renderer,
						       run->item->analysis.font,
						       gi->glyph);
            }
        }
    }
  while (pango_layout_iter_next_line (iter));
 
  pango_layout_iter_free (iter);
}
示例#8
0
/**
 * pango_renderer_draw_layout:
 * @renderer: a #PangoRenderer
 * @layout: a #PangoLayout
 * @x: X position of left edge of baseline, in user space coordinates
 *   in Pango units.
 * @y: Y position of left edge of baseline, in user space coordinates
 *    in Pango units.
 *
 * Draws @layout with the specified #PangoRenderer.
 *
 * Since: 1.8
 **/
void
pango_renderer_draw_layout (PangoRenderer    *renderer,
			    PangoLayout      *layout,
			    int               x,
			    int               y)
{
  PangoLayoutIter *iter;

  g_return_if_fail (PANGO_IS_RENDERER (renderer));
  g_return_if_fail (PANGO_IS_LAYOUT (layout));

  /* We only change the matrix if the renderer isn't already
   * active.
   */
  if (!renderer->active_count)
    {
      PangoContext *context = pango_layout_get_context (layout);
      pango_renderer_set_matrix (renderer,
				 pango_context_get_matrix (context));
    }

  pango_renderer_activate (renderer);

  iter = pango_layout_get_iter (layout);

  do
    {
      PangoRectangle   logical_rect;
      PangoLayoutLine *line;
      int              baseline;

      line = pango_layout_iter_get_line_readonly (iter);

      pango_layout_iter_get_line_extents (iter, NULL, &logical_rect);
      baseline = pango_layout_iter_get_baseline (iter);

      pango_renderer_draw_layout_line (renderer,
				       line,
				       x + logical_rect.x,
				       y + baseline);
    }
  while (pango_layout_iter_next_line (iter));

  pango_layout_iter_free (iter);

  pango_renderer_deactivate (renderer);
}
示例#9
0
gui2::tpoint ttext::get_cursor_position(
		const unsigned column, const unsigned line) const
{
	recalculate();

	// First we need to determine the byte offset, if more routines need it it
	// would be a good idea to make it a separate function.
	titor itor(layout_);

	// Go the wanted line.
	if(line != 0) {
		if(pango_layout_get_line_count(layout_) >= static_cast<int>(line)) {
			return gui2::tpoint(0, 0);
		}

		for(size_t i = 0; i < line; ++i) {
			pango_layout_iter_next_line(itor);
		}
	}

	// Go the wanted column.
	for(size_t i = 0; i < column; ++i) {
		if(!pango_layout_iter_next_char(itor)) {
			// It seems that the documentation is wrong and causes and off by
			// one error... the result should be false if already at the end of
			// the data when started.
			if(i + 1 == column) {
				break;
			}
			// We are beyond data.
			return gui2::tpoint(0, 0);
		}
	}

	// Get the byte offset
	const int offset = pango_layout_iter_get_index(itor);

	// Convert the byte offset in a position.
	PangoRectangle rect;
	pango_layout_get_cursor_pos(layout_, offset, &rect, nullptr);

	return gui2::tpoint(PANGO_PIXELS(rect.x), PANGO_PIXELS(rect.y));
}
示例#10
0
static void
dump_lines (PangoLayout *layout, GString *string)
{
  PangoLayoutIter *iter;
  const gchar *text;
  gint index, index2;
  gboolean has_more;
  gchar *char_str;
  gint i;
  PangoLayoutLine *line;

  text = pango_layout_get_text (layout);
  iter = pango_layout_get_iter (layout);

  has_more = TRUE;
  index = pango_layout_iter_get_index (iter);
  i = 0;
  while (has_more)
    {
      line = pango_layout_iter_get_line (iter);
      has_more = pango_layout_iter_next_line (iter);
      i++;

      if (has_more)
        {
          index2 = pango_layout_iter_get_index (iter);
          char_str = g_strndup (text + index, index2 - index);          
        }
      else
        {
          char_str = g_strdup (text + index);
        }

      g_string_append_printf (string, "i=%d, index=%d, paragraph-start=%d, dir=%s '%s'\n",
                              i, index, line->is_paragraph_start, direction_name (line->resolved_dir), 
                              char_str);
      g_free (char_str);

      index = index2;
    }
  pango_layout_iter_free (iter);
}
示例#11
0
/**
 * gdk_pango_layout_get_clip_region: (skip)
 * @layout: a #PangoLayout 
 * @x_origin: X pixel where you intend to draw the layout with this clip
 * @y_origin: Y pixel where you intend to draw the layout with this clip
 * @index_ranges: array of byte indexes into the layout, where even members of array are start indexes and odd elements are end indexes
 * @n_ranges: number of ranges in @index_ranges, i.e. half the size of @index_ranges
 * 
 * Obtains a clip region which contains the areas where the given ranges
 * of text would be drawn. @x_origin and @y_origin are the top left point
 * to center the layout. @index_ranges should contain
 * ranges of bytes in the layout's text.
 * 
 * Note that the regions returned correspond to logical extents of the text
 * ranges, not ink extents. So the drawn layout may in fact touch areas out of
 * the clip region.  The clip region is mainly useful for highlightling parts
 * of text, such as when text is selected.
 * 
 * Return value: a clip region containing the given ranges
 **/
cairo_region_t*
gdk_pango_layout_get_clip_region (PangoLayout *layout,
                                  gint         x_origin,
                                  gint         y_origin,
                                  const gint  *index_ranges,
                                  gint         n_ranges)
{
  PangoLayoutIter *iter;  
  cairo_region_t *clip_region;
  
  g_return_val_if_fail (PANGO_IS_LAYOUT (layout), NULL);
  g_return_val_if_fail (index_ranges != NULL, NULL);
  
  clip_region = cairo_region_create ();
  
  iter = pango_layout_get_iter (layout);
  
  do
    {
      PangoRectangle logical_rect;
      cairo_region_t *line_region;
      gint baseline;
      
      pango_layout_iter_get_line_extents (iter, NULL, &logical_rect);
      baseline = pango_layout_iter_get_baseline (iter);      

      line_region = layout_iter_get_line_clip_region(iter, 
						     x_origin + PANGO_PIXELS (logical_rect.x),
						     y_origin + PANGO_PIXELS (baseline),
						     index_ranges,
						     n_ranges);

      cairo_region_union (clip_region, line_region);
      cairo_region_destroy (line_region);
    }
  while (pango_layout_iter_next_line (iter));

  pango_layout_iter_free (iter);

  return clip_region;
}
示例#12
0
void
x11_draw_layout_with_colors( Drawable      drawable,
                             GC            gc,
                             int           x,
                             int           y,
                             PangoLayout  *layout,
                             wxColour       &colour )
{
    PangoLayoutIter *iter = pango_layout_get_iter (layout);

#if defined(__INTEL_COMPILER) && 1 /* VDM auto patch */
#   pragma ivdep
#   pragma swp
#   pragma unroll
#   pragma prefetch
#   if 0
#       pragma simd noassert
#   endif
#endif /* VDM auto patch */
    do
    {
        PangoLayoutLine *line = pango_layout_iter_get_line (iter);

        PangoRectangle logical_rect;
        pango_layout_iter_get_line_extents (iter, NULL, &logical_rect);

        int baseline = pango_layout_iter_get_baseline (iter);

        x11_draw_layout_line_with_colors( drawable, gc,
                                          x + logical_rect.x / PANGO_SCALE,
                                          y + baseline / PANGO_SCALE,
                                          line,
                                          colour );

    } while (pango_layout_iter_next_line (iter));

    pango_layout_iter_free (iter);
}
示例#13
0
/**
 * gdk_pango_layout_line_get_clip_region: (skip)
 * @line: a #PangoLayoutLine 
 * @x_origin: X pixel where you intend to draw the layout line with this clip
 * @y_origin: baseline pixel where you intend to draw the layout line with this clip
 * @index_ranges: (array): array of byte indexes into the layout,
 *     where even members of array are start indexes and odd elements
 *     are end indexes
 * @n_ranges: number of ranges in @index_ranges, i.e. half the size of @index_ranges
 * 
 * Obtains a clip region which contains the areas where the given
 * ranges of text would be drawn. @x_origin and @y_origin are the top left
 * position of the layout. @index_ranges
 * should contain ranges of bytes in the layout's text. The clip
 * region will include space to the left or right of the line (to the
 * layout bounding box) if you have indexes above or below the indexes
 * contained inside the line. This is to draw the selection all the way
 * to the side of the layout. However, the clip region is in line coordinates,
 * not layout coordinates.
 *
 * Note that the regions returned correspond to logical extents of the text
 * ranges, not ink extents. So the drawn line may in fact touch areas out of
 * the clip region.  The clip region is mainly useful for highlightling parts
 * of text, such as when text is selected.
 * 
 * Return value: a clip region containing the given ranges
 **/
cairo_region_t*
gdk_pango_layout_line_get_clip_region (PangoLayoutLine *line,
                                       gint             x_origin,
                                       gint             y_origin,
                                       const gint      *index_ranges,
                                       gint             n_ranges)
{
  cairo_region_t *clip_region;
  PangoLayoutIter *iter;
  
  g_return_val_if_fail (line != NULL, NULL);
  g_return_val_if_fail (index_ranges != NULL, NULL);
  
  iter = pango_layout_get_iter (line->layout);
  while (pango_layout_iter_get_line_readonly (iter) != line)
    pango_layout_iter_next_line (iter);
  
  clip_region = layout_iter_get_line_clip_region(iter, x_origin, y_origin, index_ranges, n_ranges);

  pango_layout_iter_free (iter);

  return clip_region;
}
示例#14
0
文件: fonts.c 项目: tkorvola/sawfish
static void
pango_draw (Lisp_Font *f, char *string, size_t length,
	    Window id, GC gc, Lisp_Color *fg, int x, int y)
{
    static XftDraw *draw;
    XftColor xft_color;
    PangoLayout *layout;
    PangoLayoutIter *iter;

    if (draw == 0)
	draw = XftDrawCreate (dpy, id, image_visual, image_cmap);
    else
	XftDrawChange (draw, id);

    xft_color.pixel = fg->pixel;
    xft_color.color.red = fg->red;
    xft_color.color.green = fg->green;
    xft_color.color.blue = fg->blue;
    xft_color.color.alpha = fg->alpha;

    layout = pango_layout_new (pango_context);
    pango_layout_set_font_description(layout, f->font);
    pango_layout_set_text (layout, string, length);
    iter = pango_layout_get_iter (layout);

    do {
	PangoLayoutLine *line = pango_layout_iter_get_line (iter);
	PangoRectangle rect;

	pango_layout_iter_get_line_extents (iter, NULL, &rect);
	pango_draw_line (draw, id, gc, &xft_color,
			 line, x + rect.x / PANGO_SCALE, y);
    } while (pango_layout_iter_next_line (iter));

    g_object_unref (layout);
    pango_layout_iter_free (iter);
}
示例#15
0
static void
schgui_cairo_drafter_draw_text(SchGUICairoDrafter *drafter, const struct _SchText *text)
{
    if (text != NULL)
    {
        int visible;

        sch_text_get_visible(text, &visible);

        if (visible)
        {

    SchGUICairoDrafterPrivate *privat = SCHGUI_CAIRO_DRAFTER_GET_PRIVATE(drafter);

    if (privat->cairo != NULL)
    {
        PangoLayout *layout;
        SchMultiline *multiline = sch_text_get_multiline(text);
        int point_size = sch_text_get_size(text);
        float height;
        int alignment;
        cairo_font_options_t *options;
        PangoContext *context;
        int baseline;
        PangoLayoutIter *iter;
        int index;
        int show;
        SchGUIDrawingCfgColor color;
        int          enabled;

        sch_text_get_color(text, &index);

        enabled = schgui_drawing_cfg_get_color(privat->config, index, &color);

        if (enabled)
        {
            if (0) /* show ink rect */
            {
                GeomBounds bounds;
                int        success;

                success = schgui_cairo_drafter_text_bounds(drafter, text, &bounds);

                if (success)
                {
                    cairo_set_source_rgb(privat->cairo, 1.0, 0, 0);
                
                    cairo_move_to(privat->cairo, bounds.min_x, bounds.min_y);
                    cairo_line_to(privat->cairo, bounds.max_x, bounds.min_y);
                
                    cairo_stroke(privat->cairo);

                    cairo_set_source_rgb(privat->cairo, 0.75, 0, 0);
                
                    cairo_move_to(privat->cairo, bounds.max_x, bounds.min_y);
                    cairo_line_to(privat->cairo, bounds.max_x, bounds.max_y);
                    cairo_line_to(privat->cairo, bounds.min_x, bounds.max_y);
                    cairo_line_to(privat->cairo, bounds.min_x, bounds.min_y);
                    //cairo_close_path(privat->cairo);

                    cairo_stroke(privat->cairo);
                
                    cairo_set_source_rgb(privat->cairo, 0, 0, 0);
                }

                cairo_set_source_rgb(privat->cairo, 0, 0, 1.0);
                cairo_new_sub_path(privat->cairo);
                cairo_arc(privat->cairo, sch_text_get_x(text), sch_text_get_y(text), 10, 0, 2 * M_PI);
                cairo_stroke(privat->cairo);
                cairo_set_source_rgb(privat->cairo, 0, 0, 0);
            }

            cairo_save(privat->cairo);
   
            height = 1000 * point_size / 72;

            layout = pango_cairo_create_layout(privat->cairo);
            pango_cairo_context_set_resolution(pango_layout_get_context(layout), 936);

//  context = pango_layout_get_context(layout);
//  options = cairo_font_options_create ();
//  cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_OFF);
//  cairo_font_options_set_hint_style (options, CAIRO_HINT_STYLE_MEDIUM);
//  pango_cairo_context_set_font_options (context, options);
//  cairo_font_options_destroy (options);


            cairo_set_source_rgb(privat->cairo, color.red, color.green, color.blue);


            pango_font_description_set_size(privat->desc, point_size * PANGO_SCALE );
            pango_layout_set_spacing(layout, 40000);
        
            pango_layout_set_font_description(layout, privat->desc);

            sch_text_get_show(text, &show);
            pango_layout_set_markup(layout, sch_multiline_peek_markup(multiline, show), -1);


            PangoFontMetrics *metrics = pango_context_get_metrics(
                pango_layout_get_context(layout),
                privat->desc,
                NULL
                );

        
            cairo_move_to(privat->cairo, sch_text_get_x(text), sch_text_get_y(text));
        
            cairo_rotate(privat->cairo, M_PI * sch_text_get_angle(text) / 180);

            cairo_scale(privat->cairo, 1, -1);

            baseline = pango_layout_get_baseline(layout); 

            alignment = sch_text_get_alignment(text);
#if 1
            switch (alignment)
            {
                case 2:
                case 5:
                case 8: 
                /* upper */
                //cairo_rel_move_to(privat->cairo, 0, -pango_font_metrics_get_ascent(metrics)/(privat->zoom * PANGO_SCALE));
                //cairo_rel_move_to(privat->cairo, 0, height);
                break;

                case 1:
                case 4:
                case 7:
                    /* center */
                    cairo_rel_move_to(privat->cairo, 0, -pango_font_metrics_get_ascent(metrics)/(privat->zoom * PANGO_SCALE));
                    cairo_rel_move_to(privat->cairo, 0, height);
                    cairo_rel_move_to(privat->cairo, 0, -pango_font_metrics_get_ascent(metrics) * sch_multiline_lines(multiline)/(2 * privat->zoom * PANGO_SCALE));
                    cairo_rel_move_to(privat->cairo, 0, -pango_font_metrics_get_descent(metrics) * (sch_multiline_lines(multiline) - 1)/(2 * privat->zoom * PANGO_SCALE));
                    break;

                case 0:
                case 3:
                case 6:
                default:
                    /* lower */
                    //cairo_rel_move_to(privat->cairo, 0, -pango_font_metrics_get_ascent(metrics) * sch_multiline_lines(multiline)/(privat->zoom * PANGO_SCALE));
                    //cairo_rel_move_to(privat->cairo, 0, -pango_font_metrics_get_descent(metrics) * (sch_multiline_lines(multiline)-1)/(privat->zoom * PANGO_SCALE));
                    //cairo_rel_move_to(privat->cairo, 0, -pango_layout_get_spacing(layout) * (sch_multiline_lines(multiline)-1)/ PANGO_SCALE);
                    iter = pango_layout_get_iter(layout);
                    while (!pango_layout_iter_at_last_line(iter))
                    {
                        pango_layout_iter_next_line(iter);
                    }
                    cairo_rel_move_to(privat->cairo, 0, -pango_layout_iter_get_baseline(iter) / PANGO_SCALE);
                    pango_layout_iter_free(iter);
            }
#endif

            //g_debug("Ascent:    %d", pango_font_metrics_get_ascent(metrics));
            //g_debug("Descent:   %d", pango_font_metrics_get_descent(metrics));
            //g_debug("Spacing:   %d", pango_layout_get_spacing(layout));
            //g_debug("Font size: %d", pango_font_description_get_size(privat->desc));
            //g_debug("Baseline   %d", pango_layout_get_baseline(layout));            

            pango_font_metrics_unref(metrics);

            pango_cairo_show_layout(privat->cairo, layout);

            cairo_restore(privat->cairo);

            g_object_unref(layout);
        }
    }
}
}
 
}
示例#16
0
static void
schgui_cairo_text_draw(SchGUICairoDrawItem *item, cairo_t *cairo)
{
    if (cairo != NULL)
    {
        SchGUICairoTextPrivate *privat = SCHGUI_CAIRO_TEXT_GET_PRIVATE(item);

        if (privat != NULL)
        {
            PangoLayout *layout = pango_cairo_create_layout(cairo);

            if (layout != NULL)
            {
                PangoLayoutIter *iter;
                int width;

                cairo_save(cairo);

                cairo_set_source_rgba(cairo, privat->red, privat->green, privat->blue, privat->alpha);


                pango_cairo_context_set_resolution(pango_layout_get_context(layout), 936);
                pango_layout_set_spacing(layout, 40000);
                pango_layout_set_font_description(layout, privat->font_desc);

                pango_layout_set_markup(layout, privat->markup, -1);

                cairo_move_to(cairo, privat->x, privat->y);
                cairo_rotate(cairo, privat->angle);
                cairo_scale(cairo, 1, -1);

                switch (privat->alignment)
                {
                    case 2:
                    case 5:
                    case 8: 
                        /* upper */
                        break;

                    case 1:
                    case 4:
                    case 7:
                        /* center */
                        iter = pango_layout_get_iter(layout);
                        while (!pango_layout_iter_at_last_line(iter))
                        {
                            pango_layout_iter_next_line(iter);
                        }
                        cairo_rel_move_to(cairo, 0, -pango_layout_iter_get_baseline(iter) / PANGO_SCALE / 2);
                        pango_layout_iter_free(iter);
                        break;

                    case 0:
                    case 3:
                    case 6:
                    default:
                        /* lower */
                        iter = pango_layout_get_iter(layout);
                        while (!pango_layout_iter_at_last_line(iter))
                        {
                            pango_layout_iter_next_line(iter);
                        }
                        cairo_rel_move_to(cairo, 0, -pango_layout_iter_get_baseline(iter) / PANGO_SCALE);
                        pango_layout_iter_free(iter);
                }

                switch (privat->alignment)
                {

                    case 3:
                    case 4:
                    case 5:
                        /* center */
                        pango_layout_get_size(layout, &width, NULL);
                        cairo_rel_move_to(cairo, -width / PANGO_SCALE / 2, 0);
                        break;

                    case 6:
                    case 7:
                    case 8:
                        pango_layout_get_size(layout, &width, NULL);
                        cairo_rel_move_to(cairo, -width / PANGO_SCALE, 0);
                        /* right */
                        break;

                    case 0:
                    case 1:
                    case 2:
                    default:
                        /* left */
                        ;
                }

                pango_cairo_show_layout(cairo, layout);

                cairo_restore(cairo);

                g_object_unref(layout);
            }
        }
    }
}
void
gnm_rendered_value_remeasure (GnmRenderedValue *rv)
{
	if (rv->rotation) {
		GnmRenderedRotatedValue *rrv = (GnmRenderedRotatedValue *)rv;
		PangoContext *context = pango_layout_get_context (rv->layout);
		double sin_a, abs_sin_a, cos_a;
		int sdx = 0;
		int x0 = 0, x1 = 0;
		PangoLayoutIter *iter;
		int l = 0;
		int lwidth;

		sin_a = rrv->rotmat.xy;
		abs_sin_a = fabs (sin_a);
		cos_a = rrv->rotmat.xx;
		pango_context_set_matrix (context, &rrv->rotmat);
		pango_layout_context_changed (rv->layout);

		rrv->linecount = pango_layout_get_line_count (rv->layout);
		rrv->lines = g_new (struct GnmRenderedRotatedValueInfo, rrv->linecount);
		pango_layout_get_size (rv->layout, &lwidth, NULL);

		rv->layout_natural_height = 0;

		iter = pango_layout_get_iter (rv->layout);
		do {
			PangoRectangle logical;
			int x, dx, dy, indent;
			int h, ytop, ybot, baseline;

			pango_layout_iter_get_line_extents (iter, NULL, &logical);
			pango_layout_iter_get_line_yrange (iter, &ytop, &ybot);
			baseline = pango_layout_iter_get_baseline (iter);
			indent = logical.x;
			if (sin_a < 0)
				indent -= lwidth;

			if (l == 0 && rv->noborders)
				sdx = (int)(baseline * sin_a - ybot / sin_a);
			dx = sdx + (int)(ybot / sin_a + indent * cos_a);
			dy = (int)((baseline - ybot) * cos_a - indent * sin_a);

			rrv->lines[l].dx = dx;
			rrv->lines[l].dy = dy;

			/* Left edge.  */
			x = dx - (int)((baseline - ytop) * sin_a);
			x0 = MIN (x0, x);

			/* Right edge.  */
			x = dx + (int)(logical.width * cos_a + (ybot - baseline) * sin_a);
			x1 = MAX (x1, x);

			h = logical.width * abs_sin_a + logical.height * cos_a;
			if (h > rv->layout_natural_height)
				rv->layout_natural_height = h;

			l++;
		} while (pango_layout_iter_next_line (iter));
		pango_layout_iter_free (iter);

		rv->layout_natural_width = x1 - x0;
		if (sin_a < 0) {
			int dx = rv->layout_natural_width;
			for (l = 0; l < rrv->linecount; l++)
				rrv->lines[l].dx += dx;
		}
		for (l = 0; l < rrv->linecount; l++)
			rrv->lines[l].dy += rv->layout_natural_height;

#if 0
		g_print ("Natural size: %d x %d\n", rv->layout_natural_width, rv->layout_natural_height);
#endif

		pango_context_set_matrix (context, NULL);
		pango_layout_context_changed (rv->layout);
	} else
示例#18
0
static void
gimp_text_tool_move_cursor (GimpTextTool    *text_tool,
                            GtkMovementStep  step,
                            gint             count,
                            gboolean         extend_selection)
{
  GtkTextBuffer *buffer = GTK_TEXT_BUFFER (text_tool->buffer);
  GtkTextIter    cursor;
  GtkTextIter    selection;
  GtkTextIter   *sel_start;
  gboolean       cancel_selection = FALSE;
  gint           x_pos  = -1;

  GIMP_LOG (TEXT_EDITING, "%s count = %d, select = %s",
            g_enum_get_value (g_type_class_ref (GTK_TYPE_MOVEMENT_STEP),
                              step)->value_name,
            count,
            extend_selection ? "TRUE" : "FALSE");

  gtk_text_buffer_get_iter_at_mark (buffer, &cursor,
                                    gtk_text_buffer_get_insert (buffer));
  gtk_text_buffer_get_iter_at_mark (buffer, &selection,
                                    gtk_text_buffer_get_selection_bound (buffer));

  if (extend_selection)
    {
      sel_start = &selection;
    }
  else
    {
      /*  when there is a selection, moving the cursor without
       *  extending it should move the cursor to the end of the
       *  selection that is in moving direction
       */
      if (count > 0)
        gtk_text_iter_order (&selection, &cursor);
      else
        gtk_text_iter_order (&cursor, &selection);

      sel_start = &cursor;

      /* if we actually have a selection, just move *to* the beginning/end
       * of the selection and not *from* there on LOGICAL_POSITIONS
       * and VISUAL_POSITIONS movement
       */
      if (! gtk_text_iter_equal (&cursor, &selection))
        cancel_selection = TRUE;
    }

  switch (step)
    {
    case GTK_MOVEMENT_LOGICAL_POSITIONS:
      if (! cancel_selection)
        gtk_text_iter_forward_visible_cursor_positions (&cursor, count);
      break;

    case GTK_MOVEMENT_VISUAL_POSITIONS:
      if (! cancel_selection)
        {
          PangoLayout *layout;
          const gchar *text;

          if (! gimp_text_tool_ensure_layout (text_tool))
            break;

          layout = gimp_text_layout_get_pango_layout (text_tool->layout);
          text = pango_layout_get_text (layout);

          while (count != 0)
            {
              const gunichar word_joiner = 8288; /*g_utf8_get_char(WORD_JOINER);*/
              gint index;
              gint trailing = 0;
              gint new_index;

              index = gimp_text_buffer_get_iter_index (text_tool->buffer,
                                                       &cursor, TRUE);

              if (count > 0)
                {
                  if (g_utf8_get_char (text + index) == word_joiner)
                    pango_layout_move_cursor_visually (layout, TRUE,
                                                       index, 0, 1,
                                                       &new_index, &trailing);
                  else
                    new_index = index;

                  pango_layout_move_cursor_visually (layout, TRUE,
                                                     new_index, trailing, 1,
                                                     &new_index, &trailing);
                  count--;
                }
              else
                {
                  pango_layout_move_cursor_visually (layout, TRUE,
                                                     index, 0, -1,
                                                     &new_index, &trailing);

                  if (new_index != -1 && new_index != G_MAXINT &&
                      g_utf8_get_char (text + new_index) == word_joiner)
                    {
                      pango_layout_move_cursor_visually (layout, TRUE,
                                                         new_index, trailing, -1,
                                                         &new_index, &trailing);
                    }

                  count++;
                }

              if (new_index != G_MAXINT && new_index != -1)
                index = new_index;
              else
                break;

              gimp_text_buffer_get_iter_at_index (text_tool->buffer,
                                                  &cursor, index, TRUE);
              gtk_text_iter_forward_chars (&cursor, trailing);
            }
        }
      break;

    case GTK_MOVEMENT_WORDS:
      if (count < 0)
        {
          gtk_text_iter_backward_visible_word_starts (&cursor, -count);
        }
      else if (count > 0)
        {
	  if (! gtk_text_iter_forward_visible_word_ends (&cursor, count))
	    gtk_text_iter_forward_to_line_end (&cursor);
        }
      break;

    case GTK_MOVEMENT_DISPLAY_LINES:
      {
        GtkTextIter      start;
        GtkTextIter      end;
        gint             cursor_index;
        PangoLayout     *layout;
        PangoLayoutLine *layout_line;
        PangoLayoutIter *layout_iter;
        PangoRectangle   logical;
        gint             line;
        gint             trailing;
        gint             i;

        gtk_text_buffer_get_bounds (buffer, &start, &end);

        cursor_index = gimp_text_buffer_get_iter_index (text_tool->buffer,
                                                        &cursor, TRUE);

        if (! gimp_text_tool_ensure_layout (text_tool))
          break;

        layout = gimp_text_layout_get_pango_layout (text_tool->layout);

        pango_layout_index_to_line_x (layout, cursor_index, FALSE,
                                      &line, &x_pos);

        layout_iter = pango_layout_get_iter (layout);
        for (i = 0; i < line; i++)
          pango_layout_iter_next_line (layout_iter);

        pango_layout_iter_get_line_extents (layout_iter, NULL, &logical);

        x_pos += logical.x;

        pango_layout_iter_free (layout_iter);

        /*  try to go to the remembered x_pos if it exists *and* we are at
         *  the beginning or at the end of the current line
         */
        if (text_tool->x_pos != -1 && (x_pos <= logical.x ||
                                       x_pos >= logical.x + logical.width))
          x_pos = text_tool->x_pos;

        line += count;

        if (line < 0)
          {
            cursor = start;
            break;
          }
        else if (line >= pango_layout_get_line_count (layout))
          {
            cursor = end;
            break;
          }

        layout_iter = pango_layout_get_iter (layout);
        for (i = 0; i < line; i++)
          pango_layout_iter_next_line (layout_iter);

        layout_line = pango_layout_iter_get_line_readonly (layout_iter);
        pango_layout_iter_get_line_extents (layout_iter, NULL, &logical);

        pango_layout_iter_free (layout_iter);

        pango_layout_line_x_to_index (layout_line, x_pos - logical.x,
                                      &cursor_index, &trailing);

        gimp_text_buffer_get_iter_at_index (text_tool->buffer, &cursor,
                                            cursor_index, TRUE);

        while (trailing--)
          gtk_text_iter_forward_char (&cursor);
      }
      break;

    case GTK_MOVEMENT_PAGES: /* well... */
    case GTK_MOVEMENT_BUFFER_ENDS:
      if (count < 0)
        {
          gtk_text_buffer_get_start_iter (buffer, &cursor);
        }
      else if (count > 0)
        {
          gtk_text_buffer_get_end_iter (buffer, &cursor);
        }
      break;

    case GTK_MOVEMENT_PARAGRAPH_ENDS:
      if (count < 0)
        {
          gtk_text_iter_set_line_offset (&cursor, 0);
        }
      else if (count > 0)
        {
          if (! gtk_text_iter_ends_line (&cursor))
            gtk_text_iter_forward_to_line_end (&cursor);
        }
      break;

    case GTK_MOVEMENT_DISPLAY_LINE_ENDS:
      if (count < 0)
        {
          gtk_text_iter_set_line_offset (&cursor, 0);
        }
      else if (count > 0)
        {
          if (! gtk_text_iter_ends_line (&cursor))
            gtk_text_iter_forward_to_line_end (&cursor);
        }
      break;

    default:
      return;
    }

  text_tool->x_pos = x_pos;

  gimp_draw_tool_pause (GIMP_DRAW_TOOL (text_tool));

  gimp_text_tool_reset_im_context (text_tool);

  gtk_text_buffer_select_range (buffer, &cursor, sel_start);

  gimp_draw_tool_resume (GIMP_DRAW_TOOL (text_tool));
}
示例#19
0
/* split a text buffer into chunks using the passed Pango layout */
GList *
split_for_layout(PangoLayout * layout, const gchar * text,
		 PangoAttrList * attributes, BalsaPrintSetup * psetup,
		 gboolean is_header, GArray ** offsets)
{
    GList *split_list = NULL;
    PangoLayoutIter *iter;
    const gchar *start;
    gint p_offset;
    gboolean add_tab;
    gint p_y0;
    gint p_y1;
    gint p_y_pos;
    gint p_height;

    /* set the text and its attributes, then get an iter */
    pango_layout_set_text(layout, text, -1);
    if (attributes)
	pango_layout_set_attributes(layout, attributes);
    if (offsets)
	*offsets = g_array_new(FALSE, FALSE, sizeof(guint));
    iter = pango_layout_get_iter(layout);

    /* loop over lines */
    start = text;
    p_offset = 0;
    add_tab = FALSE;
    p_y_pos = C_TO_P(psetup->c_y_pos);
    p_height = C_TO_P(psetup->c_height);
    do {
	pango_layout_iter_get_line_yrange(iter, &p_y0, &p_y1);
	if (p_y_pos + p_y1 - p_offset > p_height) {
	    gint index;
	    gint tr;
	    gchar *chunk;
	    gboolean ends_with_nl;

	    if (offsets) {
		guint offs = start - text;

		*offsets = g_array_append_val(*offsets, offs);
	    }
	    pango_layout_xy_to_index(layout, 0, p_y0, &index, &tr);
	    ends_with_nl = text[index - 1] == '\n';
	    if (ends_with_nl)
		index--;
	    chunk = g_strndup(start, text + index - start);
	    if (add_tab)
		split_list =
		    g_list_append(split_list,
				  g_strconcat("\t", chunk, NULL));
	    else
		split_list = g_list_append(split_list, g_strdup(chunk));
	    add_tab = is_header && !ends_with_nl;
	    g_free(chunk);
	    start = text + index;
	    if (ends_with_nl)
		start++;
	    if (*start == '\0')
		p_y_pos = p_height;
	    else {
		p_y_pos = 0;
		psetup->page_count++;
	    }
	    p_offset = p_y0;
	}
    } while (pango_layout_iter_next_line(iter));
    pango_layout_iter_free(iter);

    /* append any remaining stuff */
    if (*start != '\0') {
	p_y_pos += p_y1 - p_offset;
	if (offsets) {
	    guint offs = start - text;

	    *offsets = g_array_append_val(*offsets, offs);
	}
	if (add_tab)
	    split_list =
		g_list_append(split_list, g_strconcat("\t", start, NULL));
	else
	    split_list = g_list_append(split_list, g_strdup(start));
    }

    /* remember the new y position in cairo units */
    psetup->c_y_pos = P_TO_C(p_y_pos);

    /* return the list */
    return split_list;
}
示例#20
0
GpStatus
pango_MeasureString (GpGraphics *graphics, GDIPCONST WCHAR *stringUnicode, int length, GDIPCONST GpFont *font, GDIPCONST RectF *rc,
	GDIPCONST GpStringFormat *format, RectF *boundingBox, int *codepointsFitted, int *linesFilled)
{
	PangoLayout *layout;
	PangoLayoutLine *line;
	PangoRectangle logical;
	PangoLayoutIter *iter;
	int *charsRemoved = NULL;

	cairo_save (graphics->ct);

	layout = gdip_pango_setup_layout (graphics, stringUnicode, length, font, rc, boundingBox, format, &charsRemoved);
	if (!layout) {
		cairo_restore (graphics->ct);
		return OutOfMemory;
	}

	if (codepointsFitted) {
		int charsFitted;
		int lastIndex;
		int y0;
		int y1;
		double min_x;
		double max_x;
		double max_y;
		const char *layoutText;
		if (boundingBox && format && (format->formatFlags & StringFormatFlagsDirectionVertical)) {
			min_x = boundingBox->Y;
			max_x = boundingBox->Y + boundingBox->Height;
			max_y = boundingBox->X + boundingBox->Width;
		} else if (boundingBox) {
			min_x = boundingBox->X;
			max_x = boundingBox->X + boundingBox->Width;
			max_y = boundingBox->Y + boundingBox->Height;
		} else if (format && (format->formatFlags & StringFormatFlagsDirectionVertical)) {
			min_x = rc->Y;
			max_x = rc->Y + rc->Height;
			max_y = rc->X + rc->Width;
		} else {
			min_x = rc->X;
			max_x = rc->X + rc->Width;
			max_y = rc->Y + rc->Height;
		}
		lastIndex = 0;
		iter = pango_layout_get_iter (layout);
		do {
			if (iter == NULL)
				break;
			pango_layout_iter_get_line_yrange (iter, &y0, &y1);
			if (y0 / PANGO_SCALE >= max_y)
				break;
			if (pango_layout_iter_at_last_line (iter)) {
				do {
					pango_layout_iter_get_char_extents (iter, &logical);
					/* check both max and min to catch right-to-left text, also width may be negative */
					if ((logical.x / PANGO_SCALE > max_x || (logical.x + logical.width) / PANGO_SCALE > max_x) || (logical.x / PANGO_SCALE < min_x || (logical.x + logical.width) / PANGO_SCALE < min_x))
						break;
					lastIndex = pango_layout_iter_get_index (iter);
				} while (pango_layout_iter_next_char (iter));
				break;
			} else {
				line = pango_layout_iter_get_line_readonly (iter);
				lastIndex = line->start_index + line->length - 1;
			}
		} while (pango_layout_iter_next_line (iter));
		pango_layout_iter_free (iter);
		layoutText = pango_layout_get_text (layout);
		/* this can happen when the string ends in a newline */
		if (lastIndex >= strlen (layoutText))
			lastIndex = strlen (layoutText) - 1;
		/* Add back in any & characters removed and the final newline characters (if any) */
		charsFitted = g_utf8_strlen (layoutText, lastIndex + 1) + charsRemoved [lastIndex];
		//g_warning("lastIndex: %d\t\tcharsRemoved: %d", lastIndex, charsRemoved[lastIndex]);
		/* safe because of null termination */
		switch (layoutText [lastIndex + 1]) {
			case '\r':
				charsFitted++;
				if (layoutText [lastIndex + 2] == '\n')
					charsFitted++;
				break;
			case '\n':
				charsFitted++;
				break;
		}
		*codepointsFitted = charsFitted;
	}

	GdipFree (charsRemoved);

	if (linesFilled) {
		*linesFilled = pango_layout_get_line_count (layout);
// g_warning ("linesFilled %d", *linesFilled);
	}
// else g_warning ("linesFilled %d", pango_layout_get_line_count (layout));

	g_object_unref (layout);
	cairo_restore (graphics->ct);
	return Ok;
}
示例#21
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;
}
示例#22
0
static void
render_para (GdkDrawable        *drawable,
             GtkTextRenderState *render_state,
             GtkTextLineDisplay *line_display,
             /* Top-left corner of paragraph including all margins */
             int                 x,
             int                 y,
             int                 selection_start_index,
             int                 selection_end_index,
             GList             **widgets)
{
  GSList *shaped_pointer = line_display->shaped_objects;
  PangoLayout *layout = line_display->layout;
  int byte_offset = 0;
  PangoLayoutIter *iter;
  PangoRectangle layout_logical;
  int screen_width;
  GdkGC *fg_gc, *bg_gc;
  gint state;
  
  gboolean first = TRUE;

  iter = pango_layout_get_iter (layout);

  pango_layout_iter_get_layout_extents (iter, NULL, &layout_logical);

  /* Adjust for margins */
  
  layout_logical.x += line_display->x_offset * PANGO_SCALE;
  layout_logical.y += line_display->top_margin * PANGO_SCALE;

  screen_width = line_display->total_width;
  
  if (GTK_WIDGET_HAS_FOCUS (render_state->widget))
    state = GTK_STATE_SELECTED;
  else
    state = GTK_STATE_ACTIVE;

  fg_gc = render_state->widget->style->text_gc [state];
  bg_gc = render_state->widget->style->base_gc [state];

  do
    {
      PangoLayoutLine *line = pango_layout_iter_get_line (iter);
      int selection_y, selection_height;
      int first_y, last_y;
      PangoRectangle line_rect;
      int baseline;
      
      pango_layout_iter_get_line_extents (iter, NULL, &line_rect);
      baseline = pango_layout_iter_get_baseline (iter);
      pango_layout_iter_get_line_yrange (iter, &first_y, &last_y);
      
      /* Adjust for margins */

      line_rect.x += line_display->x_offset * PANGO_SCALE;
      line_rect.y += line_display->top_margin * PANGO_SCALE;
      baseline += line_display->top_margin * PANGO_SCALE;

      /* Selection is the height of the line, plus top/bottom
       * margin if we're the first/last line
       */
      selection_y = y + PANGO_PIXELS (first_y) + line_display->top_margin;
      selection_height = PANGO_PIXELS (last_y) - PANGO_PIXELS (first_y);

      if (first)
        {
          selection_y -= line_display->top_margin;
          selection_height += line_display->top_margin;
        }
      
      if (pango_layout_iter_at_last_line (iter))
        selection_height += line_display->bottom_margin;
      
      first = FALSE;

      if (selection_start_index < byte_offset &&
          selection_end_index > line->length + byte_offset) /* All selected */
        {
          gdk_draw_rectangle (drawable,
                              bg_gc,
                              TRUE,
                              x + line_display->left_margin,
                              selection_y,
                              screen_width,
                              selection_height);

          render_layout_line (drawable, render_state, line, &shaped_pointer,
                              x + PANGO_PIXELS (line_rect.x),
                              y + PANGO_PIXELS (baseline),
                              TRUE,
                              widgets);
        }
      else
        {
          GSList *shaped_pointer_tmp = shaped_pointer;

          render_layout_line (drawable, render_state,
                              line, &shaped_pointer,
                              x + PANGO_PIXELS (line_rect.x),
                              y + PANGO_PIXELS (baseline),
                              FALSE,
                              widgets);

          if (selection_start_index <= byte_offset + line->length &&
              selection_end_index > byte_offset) /* Some selected */
            {
              GdkRegion *clip_region = get_selected_clip (render_state, layout, line,
                                                          x + line_display->x_offset,
                                                          selection_y,
                                                          selection_height,
                                                          selection_start_index, selection_end_index);
              gdk_gc_set_clip_region (fg_gc, clip_region);
              gdk_gc_set_clip_region (bg_gc, clip_region);

              gdk_draw_rectangle (drawable,
                                  bg_gc,
                                  TRUE,
                                  x + PANGO_PIXELS (line_rect.x),
                                  selection_y,
                                  PANGO_PIXELS (line_rect.width),
                                  selection_height);

              render_layout_line (drawable, render_state, line, &shaped_pointer_tmp,
                                  x + PANGO_PIXELS (line_rect.x),
                                  y + PANGO_PIXELS (baseline),
                                  TRUE,
                                  widgets);

              gdk_gc_set_clip_region (fg_gc, NULL);
              gdk_gc_set_clip_region (bg_gc, NULL);

              gdk_region_destroy (clip_region);

              /* Paint in the ends of the line */
              if (line_rect.x > line_display->left_margin * PANGO_SCALE &&
                  ((line_display->direction == GTK_TEXT_DIR_LTR && selection_start_index < byte_offset) ||
                   (line_display->direction == GTK_TEXT_DIR_RTL && selection_end_index > byte_offset + line->length)))
                {
                  gdk_draw_rectangle (drawable,
                                      bg_gc,
                                      TRUE,
                                      x + line_display->left_margin,
                                      selection_y,
                                      PANGO_PIXELS (line_rect.x) - line_display->left_margin,
                                      selection_height);
                }

              if (line_rect.x + line_rect.width <
                  (screen_width + line_display->left_margin) * PANGO_SCALE &&
                  ((line_display->direction == GTK_TEXT_DIR_LTR && selection_end_index > byte_offset + line->length) ||
                   (line_display->direction == GTK_TEXT_DIR_RTL && selection_start_index < byte_offset)))
                {
                  int nonlayout_width;

                  nonlayout_width =
                    line_display->left_margin + screen_width -
                    PANGO_PIXELS (line_rect.x) - PANGO_PIXELS (line_rect.width);

                  gdk_draw_rectangle (drawable,
                                      bg_gc,
                                      TRUE,
                                      x + PANGO_PIXELS (line_rect.x) + PANGO_PIXELS (line_rect.width),
                                      selection_y,
                                      nonlayout_width,
                                      selection_height);
                }
            }
        }

      byte_offset += line->length;
    }
  while (pango_layout_iter_next_line (iter));

  pango_layout_iter_free (iter);
}
示例#23
0
文件: pdf.c 项目: Debian/gpdftext
static void
create_pages (Pqueue * queue)
{
	gchar * msg;
	gdouble line_height;
	guint i, id;
	glong index;
	PangoLayoutLine * line;
	PangoRectangle ink_rect, logical_rect;

	g_return_if_fail (queue);
	g_return_if_fail (queue->pos < strlen(queue->text));
	while (queue->pos < strlen (queue->text))
	{
		while (gtk_events_pending ())
			gtk_main_iteration ();
		for (i = 0; i < queue->lines_per_page; i++)
		{
			line = pango_layout_iter_get_line (queue->iter);
			pango_layout_iter_next_line (queue->iter);
			pango_layout_iter_get_line_extents (queue->iter, &ink_rect, &logical_rect);
			index = pango_layout_iter_get_index (queue->iter);
			if (index == 0)
			{
				i = queue->lines_per_page;
				queue->pos = strlen (queue->text);
				g_message ("%s", _("Error: Pango iter index is zero."));
				continue;
			}
			line_height = logical_rect.height / PANGO_SCALE;
			if ((queue->page_height + line_height) > (queue->height - (EDGE_MARGIN/2)))
			{
				queue->pos += index;
				queue->page_height = EDGE_MARGIN;
				gtk_progress_bar_pulse (queue->progressbar);
				pango_cairo_update_layout (queue->cr, queue->layout);
				queue->layout = make_new_page (queue->context, queue->desc, queue->height, queue->width);
				i = queue->lines_per_page;
				queue->page_count++;
				pango_layout_set_text (queue->layout, (queue->text+queue->pos), -1);
				queue->iter = pango_layout_get_iter (queue->layout);
				pango_cairo_show_layout_line (queue->cr, line);
				pango_cairo_update_layout (queue->cr, queue->layout);
				cairo_show_page (queue->cr);
			}
			else
				pango_cairo_show_layout_line (queue->cr, line);
			queue->page_height += line_height;
			cairo_move_to (queue->cr, SIDE_MARGIN / 2, queue->page_height);
		}
	}
	pango_layout_iter_free (queue->iter);
	gtk_progress_bar_set_fraction (queue->progressbar, 0.0);
	cairo_surface_destroy(queue->surface);
	pango_font_description_free (queue->desc);
	g_object_unref (queue->context);
	g_object_unref (queue->layout);
	cairo_destroy (queue->cr);
	id = gtk_statusbar_get_context_id (queue->statusbar, PACKAGE);
	msg = g_strdup_printf (ngettext("Saved PDF file. (%ld page)",
		"Saved PDF file (%ld pages).", queue->page_count), queue->page_count);
	gtk_statusbar_push (queue->statusbar, id, msg);
	g_free (msg);
}
示例#24
0
void text_wrapper::DoLayout(void)
{
    // THE function
    // first some sanity checks
    if ( default_font == NULL ) return;
    if ( uni32_length <= 0 || utf8_length <= 0 ) return;
    // prepare the pangolayout object
    {
        //char *tc = pango_font_description_to_string(default_font->descr);
        //printf("layout with %s\n", tc);
        //free(tc);
    }
    pango_layout_set_font_description(pLayout, default_font->descr);
    pango_layout_set_text(pLayout, utf8_text, utf8_length);
    // reset the glyph string
    if ( glyph_text ) free(glyph_text);
    glyph_text = NULL;
    glyph_length = 0;

    double pango_to_ink = (1.0 / ((double)PANGO_SCALE)); // utility
    int max_g = 0;
    PangoLayoutIter *pIter = pango_layout_get_iter(pLayout); // and go!
    do {
        PangoLayoutLine *pLine = pango_layout_iter_get_line(pIter); // no need for unref
        int plOffset = pLine->start_index; // start of the line in the uni32_text
        PangoRectangle ink_r, log_r;
        pango_layout_iter_get_line_extents(pIter, &ink_r, &log_r);
        double plY = (1.0 / ((double)PANGO_SCALE)) * ((double)log_r.y); // start position of this line of the layout
        double plX = (1.0 / ((double)PANGO_SCALE)) * ((double)log_r.x);
        GSList *curR = pLine->runs; // get ready to iterate over the runs of this line
        while ( curR ) {
            PangoLayoutRun *pRun = (PangoLayoutRun*)curR->data;
            if ( pRun ) {
                int prOffset = pRun->item->offset; // start of the run in the line
                // a run has uniform font/directionality/etc...
                int o_g_l = glyph_length; // save the index of the first glyph we'll add
                for (int i = 0; i < pRun->glyphs->num_glyphs; i++) { // add glyph sequentially, reading them from the run
                    // realloc the structures
                    if ( glyph_length >= max_g ) {
                        max_g = 2 * glyph_length + 1;
                        one_glyph *newdata = static_cast<one_glyph*>(realloc(glyph_text, (max_g + 1) * sizeof(one_glyph)));
                        if (newdata != NULL)
                        {
                            glyph_text = newdata;
                        }
                        else
                        {
                            g_warning("Failed to reallocate glyph_text");
                        }
                    }
                    // fill the glyph info
                    glyph_text[glyph_length].font = pRun->item->analysis.font;
                    glyph_text[glyph_length].gl = pRun->glyphs->glyphs[i].glyph;
                    glyph_text[glyph_length].uni_st = plOffset + prOffset + pRun->glyphs->log_clusters[i];
                    // depending on the directionality, the last uni32 codepoint for this glyph is the first of the next char
                    // or the first of the previous
                    if ( pRun->item->analysis.level == 1 ) {
                        // rtl
                        if ( i < pRun->glyphs->num_glyphs - 1 ) {
                            glyph_text[glyph_length + 1].uni_en = glyph_text[glyph_length].uni_st;
                        }
                        glyph_text[glyph_length].uni_dir = 1;
                        glyph_text[glyph_length + 1].uni_dir = 1; // set the directionality for the next too, so that the last glyph in
                        // the array has the correct direction
                    } else {
                        // ltr
                        if ( i > 0 ) {
                            glyph_text[glyph_length - 1].uni_en = glyph_text[glyph_length].uni_st;
                        }
                        glyph_text[glyph_length].uni_dir = 0;
                        glyph_text[glyph_length + 1].uni_dir = 0;
                    }
                    // set the position
                    // the layout is an infinite line
                    glyph_text[glyph_length].x = plX + pango_to_ink * ((double)pRun->glyphs->glyphs[i].geometry.x_offset);
                    glyph_text[glyph_length].y = plY + pango_to_ink * ((double)pRun->glyphs->glyphs[i].geometry.y_offset);
                    // advance to the next glyph
                    plX += pango_to_ink * ((double)pRun->glyphs->glyphs[i].geometry.width);
                    // and set the next glyph's position, in case it's the terminating glyph
                    glyph_text[glyph_length + 1].x = plX;
                    glyph_text[glyph_length + 1].y = plY;
                    glyph_length++;
                }
                // and finish filling the info
                // notably, the uni_en of the last char in ltr text and the uni_en of the first in rtl are still not set
                if ( pRun->item->analysis.level == 1 ) {
                    // rtl
                    if ( glyph_length > o_g_l ) glyph_text[o_g_l].uni_en = plOffset + prOffset + pRun->item->length;
                } else {
                    if ( glyph_length > 0 ) glyph_text[glyph_length - 1].uni_en = plOffset + prOffset + pRun->item->length;
                }
                // the terminating glyph has glyph_id=0 because it means 'no glyph'
                glyph_text[glyph_length].gl = 0;
                // and is associated with no text (but you cannot set uni_st=uni_en=0, because the termination
                // is expected to be the glyph for the termination of the uni32_text)
                glyph_text[glyph_length].uni_st = glyph_text[glyph_length].uni_en = plOffset + prOffset + pRun->item->length;
            }
            curR = curR->next;
        }
    } while ( pango_layout_iter_next_line(pIter) );
    pango_layout_iter_free(pIter);

    // grunt work done. now some additional info for layout: computing letters, mostly (one letter = several glyphs sometimes)
    PangoLogAttr *pAttrs = NULL;
    int nbAttr = 0;
    // get the layout attrs, they hold the boundaries pango computed
    pango_layout_get_log_attrs(pLayout, &pAttrs, &nbAttr);
    // feed to MakeTextBoundaries which knows what to do with these
    MakeTextBoundaries(pAttrs, nbAttr);
    // the array of boundaries is full, but out-of-order
    SortBoundaries();
    // boundary array is ready to be used, call chunktext to fill the *_start fields of the glyphs, and compute
    // the boxed version of the text for sp-typeset
    ChunkText();
    // get rid of the attributes
    if ( pAttrs ) g_free(pAttrs);

    // cleaning up
    for (int i = 0; i < glyph_length; i++) {
        glyph_text[i].uni_st = uni32_codepoint[glyph_text[i].uni_st];
        glyph_text[i].uni_en = uni32_codepoint[glyph_text[i].uni_en];
        glyph_text[i].x /= 512; // why is this not default_font->parent->fontsize?
        glyph_text[i].y /= 512;
    }
    if ( glyph_length > 0 ) {
        glyph_text[glyph_length].x /= 512;
        glyph_text[glyph_length].y /= 512;
    }
}
示例#25
0
static VALUE
layout_iter_next_line(VALUE self)
{
    return CBOOL2RVAL(pango_layout_iter_next_line(_SELF(self)));
}