Пример #1
0
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);
}
Пример #2
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);
}
Пример #3
0
/** Find the offsets of the individual letters in the iter and place them
 * in an array.
 * This currently assumes only one run per iter, which is all we can input.
 * @param iter The PangoLayoutIter to count characters in.
 * @param offsets The place to return the offsets
 * @param n_offsets The place to return the number of offsets
 */
static void
get_string_offsets(PangoLayoutIter *iter, real** offsets, int* n_offsets)
{
  int i;
  PangoLayoutLine*   line = pango_layout_iter_get_line(iter);
  PangoGlyphItem* item;
  PangoGlyphString* string;

  if(0 == line->length)
  {
    *n_offsets = 0;
    return;
  }
  item = (PangoGlyphItem*)line->runs->data;
  string = item->glyphs;

  *n_offsets = string->num_glyphs;
  *offsets = g_new(real, *n_offsets);

  for (i = 0; i < string->num_glyphs; i++) {
    PangoGlyphGeometry geom = string->glyphs[i].geometry;

    (*offsets)[i] = pdu_to_dcm(geom.width) / global_zoom_factor;
  }
}
Пример #4
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);
}
Пример #5
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);
}
Пример #6
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);
}
Пример #7
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);
}
Пример #8
0
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);
}
Пример #9
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;
    }
}
Пример #10
0
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);
}
Пример #11
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);
}
Пример #12
0
static VALUE
layout_iter_get_line(VALUE self)
{
    return BOXED2RVAL(pango_layout_iter_get_line(_SELF(self)), PANGO_TYPE_LAYOUT_LINE);
}