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); }
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); }
/** 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; } }
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); }
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); }
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); }
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); }
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); }
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; } }
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); }
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); }
static VALUE layout_iter_get_line(VALUE self) { return BOXED2RVAL(pango_layout_iter_get_line(_SELF(self)), PANGO_TYPE_LAYOUT_LINE); }