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 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; }
void rsvg_text_render_text (RsvgDrawingCtx * ctx, const char *text, gdouble * x, gdouble * y) { PangoContext *context; PangoLayout *layout; PangoLayoutIter *iter; RsvgState *state; gint w, h, baseline; state = rsvg_current_state (ctx); /* Do not render the text if the font size is zero. See bug #581491. */ if (state->font_size.length == 0) return; context = ctx->render->create_pango_context (ctx); layout = rsvg_text_create_layout (ctx, state, text, context); pango_layout_get_size (layout, &w, &h); iter = pango_layout_get_iter (layout); baseline = pango_layout_iter_get_baseline (iter) / (double)PANGO_SCALE; pango_layout_iter_free (iter); ctx->render->render_pango_layout (ctx, layout, *x, *y - baseline); *x += w / (double)PANGO_SCALE; g_object_unref (layout); g_object_unref (context); }
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); }
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); }
/** 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; }
void GetTextExtent( const wxFont& font, const wxString& str, wxCoord *width, wxCoord *height, wxCoord *descent, wxCoord *externalLeading ) { if ( width ) *width = 0; if ( height ) *height = 0; if ( descent ) *descent = 0; if ( externalLeading ) *externalLeading = 0; if (str.empty()) return; PangoContext* context = gdk_pango_context_get_for_screen( gdk_screen_get_default() ); PangoLayout* m_layout = pango_layout_new(context); // and use it if it's valid if ( font != wxNullFont ) { pango_layout_set_font_description ( m_layout, font.GetNativeFontInfo()->description ); } // Set layout's text const wxCharBuffer dataUTF8 = wxConvUTF8.cWX2MB(str); if ( !dataUTF8 ) { // hardly ideal, but what else can we do if conversion failed? return; } pango_layout_set_text( m_layout, dataUTF8, strlen(dataUTF8) ); if (descent) { int h; pango_layout_get_pixel_size( m_layout, width, &h ); PangoLayoutIter *iter = pango_layout_get_iter(m_layout); int baseline = pango_layout_iter_get_baseline(iter); pango_layout_iter_free(iter); *descent = h - PANGO_PIXELS(baseline); if (height) *height = (wxCoord) h; } else { pango_layout_get_pixel_size( m_layout, width, height ); } // Reset old font description //if (font != wxNullFont) // pango_layout_set_font_description( m_layout, m_fontdesc ); }
// Notice we don't check here the font. It is supposed to be OK before the call. void wxTextMeasure::DoGetTextExtent(const wxString& string, wxCoord *width, wxCoord *height, wxCoord *descent, wxCoord *externalLeading) { if ( !m_context ) { if ( width ) *width = 0; if ( height ) *height = 0; return; } // Set layout's text const wxCharBuffer dataUTF8 = wxGTK_CONV_FONT(string, GetFont()); if ( !dataUTF8 ) { // hardly ideal, but what else can we do if conversion failed? wxLogLastError(wxT("GetTextExtent")); return; } pango_layout_set_text(m_layout, dataUTF8, -1); if ( m_dc ) { // in device units pango_layout_get_pixel_size(m_layout, width, height); } else // win { // the logical rect bounds the ink rect PangoRectangle rect; pango_layout_get_extents(m_layout, NULL, &rect); *width = PANGO_PIXELS(rect.width); *height = PANGO_PIXELS(rect.height); } if (descent) { PangoLayoutIter *iter = pango_layout_get_iter(m_layout); int baseline = pango_layout_iter_get_baseline(iter); pango_layout_iter_free(iter); *descent = *height - PANGO_PIXELS(baseline); } if (externalLeading) { // No support for MSW-like "external leading" in Pango. *externalLeading = 0; } }
void computeLayout(PangoLayout *layout, char *utf8, int utf8Length, int *wPtr, int *hPtr, int *xOffsetPtr, int *yOffsetPtr, int *layoutDetailsPtr) { PangoRectangle inkRect, logicalRect; int left, top, right, bottom, baseline; PangoLayoutIter *iter; if (fontDescr == NULL) unicodeSetFont("Verdana", 18, 0, 0, 1); pango_cairo_context_set_font_options(pango_layout_get_context(layout), fontOptions); pango_layout_set_font_description(layout, fontDescr); pango_layout_set_text(layout, utf8, utf8Length); pango_layout_get_pixel_extents(layout, &inkRect, &logicalRect); left = (inkRect.x < logicalRect.x) ? inkRect.x : logicalRect.x; top = (inkRect.y < logicalRect.y) ? inkRect.y : logicalRect.y; right = inkRect.x + inkRect.width; if ((logicalRect.x + logicalRect.width) > right) right = logicalRect.x + logicalRect.width; bottom = inkRect.y + inkRect.height; if ((logicalRect.y + logicalRect.height) > bottom) bottom = logicalRect.y + logicalRect.height; iter = pango_layout_get_iter(layout); baseline = PANGO_PIXELS(pango_layout_iter_get_baseline(iter)); pango_layout_iter_free(iter); if (left < 0) { inkRect.x = inkRect.x - left; logicalRect.x = logicalRect.x - left; } if (top < 0) { inkRect.y = inkRect.y - top; logicalRect.y = logicalRect.y - top; baseline = baseline - top; } if (layoutDetailsPtr != NULL) { layoutDetailsPtr[0] = inkRect.x; layoutDetailsPtr[1] = inkRect.y; layoutDetailsPtr[2] = inkRect.width; layoutDetailsPtr[3] = inkRect.height; layoutDetailsPtr[4] = logicalRect.x; layoutDetailsPtr[5] = logicalRect.y; layoutDetailsPtr[6] = logicalRect.width; layoutDetailsPtr[7] = logicalRect.height; layoutDetailsPtr[8] = baseline; } *wPtr = right - left; *hPtr = bottom - top; *xOffsetPtr = left < 0 ? -left : 0; *yOffsetPtr = top < 0 ? -top : 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); }
static gint get_label_line_height (GtkWidget *label) { PangoLayout *layout; PangoLayoutIter *iter; PangoRectangle rect; layout = gtk_label_get_layout (GTK_LABEL (label)); iter = pango_layout_get_iter (layout); pango_layout_iter_get_line_extents (iter, NULL, &rect); pango_layout_iter_free (iter); return (rect.y + rect.height) / PANGO_SCALE; }
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); }
/** * 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); }
void text_widget_set_text ( struct TEXT_WIDGET_HANDLE handle, const char* text, int length ) { if ( handle.d == NULL || handle.d->layout == NULL ) return; pango_layout_set_markup( handle.d->layout, text, length ); // The idea here is to make sure that the VGFont contains // all the glyphs at the proper size so that when we want // to draw, we can can just call vgDrawGlyphs (well, maybe // not since PangoGlyphInfo is not an array of glyph // indexes; aww). PangoLayoutIter* li = pango_layout_get_iter( handle.d->layout ); do { PangoLayoutRun* run = pango_layout_iter_get_run( li ); if ( run == NULL ) continue; PangoFont* font = run->item->analysis.font; // Well, you can see how C is not the most ideal language for // abstraction. Have to read the documentation to discover // that this font is a PangoFcFont. FT_Face face = pango_fc_font_lock_face( (PangoFcFont*)font ); if ( face != NULL ) { struct VG_DATA* vg_data = face->size->generic.data; if ( vg_data == NULL ) { vg_data = vg_data_new(); face->size->generic.data = vg_data; face->size->generic.finalizer = vg_data_free; } int g; for ( g = 0; g < run->glyphs->num_glyphs; g++ ) { int byte = run->glyphs->glyphs[g].glyph / 8; int bit = 1 << ( run->glyphs->glyphs[g].glyph & 0x7 ); if ( ! ( vg_data->cmap[byte] & bit ) ) { vg_data->cmap[byte] |= bit; add_char( vg_data->font, face, run->glyphs->glyphs[g].glyph ); } } pango_fc_font_unlock_face( (PangoFcFont*)font ); } } while ( pango_layout_iter_next_run( li ) ); pango_layout_iter_free( li ); }
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 gtk_glwidget_create_font(){ PangoFontDescription *font_desc; PangoLayout *layout; PangoRectangle log_rect; int font_ascent_pango_units; int font_descent_pango_units; if ( _debug_font_created ) { Error( "Programming error: gtk_glwidget_create_font() was already called; " "you must call gtk_glwidget_destroy_font() before creating font again" ); } _debug_font_created = 1; font_map = pango_ft2_font_map_new(); pango_ft2_font_map_set_resolution( PANGO_FT2_FONT_MAP( font_map ), 72, 72 ); ft2_context = pango_font_map_create_context( PANGO_FONT_MAP( font_map )); font_desc = pango_font_description_from_string( font_string ); pango_font_description_set_size( font_desc, font_height * PANGO_SCALE ); pango_context_set_font_description( ft2_context, font_desc ); pango_font_description_free( font_desc ); layout = pango_layout_new( ft2_context ); // I don't believe that's standard preprocessor syntax? #if !PANGO_VERSION_CHECK( 1,22,0 ) PangoLayoutIter *iter; iter = pango_layout_get_iter( layout ); font_ascent_pango_units = pango_layout_iter_get_baseline( iter ); pango_layout_iter_free( iter ); #else font_ascent_pango_units = pango_layout_get_baseline( layout ); #endif pango_layout_get_extents( layout, NULL, &log_rect ); g_object_unref( G_OBJECT( layout ) ); font_descent_pango_units = log_rect.height - font_ascent_pango_units; font_ascent = PANGO_PIXELS_CEIL( font_ascent_pango_units ); font_descent = PANGO_PIXELS_CEIL( font_descent_pango_units ); y_offset_bitmap_render_pango_units = ( font_ascent * PANGO_SCALE ) - font_ascent_pango_units; }
/** * 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; }
bool wxTextMeasure::DoGetPartialTextExtents(const wxString& text, wxArrayInt& widths, double scaleX) { if ( !m_layout ) return wxTextMeasureBase::DoGetPartialTextExtents(text, widths, scaleX); // Set layout's text const wxCharBuffer dataUTF8 = wxGTK_CONV_FONT(text, GetFont()); if ( !dataUTF8 ) { // hardly ideal, but what else can we do if conversion failed? wxLogLastError(wxT("GetPartialTextExtents")); return false; } pango_layout_set_text(m_layout, dataUTF8, -1); // Calculate the position of each character based on the widths of // the previous characters // Code borrowed from Scintilla's PlatGTK PangoLayoutIter *iter = pango_layout_get_iter(m_layout); PangoRectangle pos; pango_layout_iter_get_cluster_extents(iter, NULL, &pos); size_t i = 0; while (pango_layout_iter_next_cluster(iter)) { pango_layout_iter_get_cluster_extents(iter, NULL, &pos); int position = PANGO_PIXELS(pos.x); widths[i++] = position; } const size_t len = text.length(); while (i < len) widths[i++] = PANGO_PIXELS(pos.x + pos.width); pango_layout_iter_free(iter); return true; }
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics_drawString (JNIEnv *env, jobject obj, jobject font, jstring str, jint x, jint y) { struct peerfont *pfont = NULL; struct graphics *g; const char *cstr; int baseline_y; PangoLayoutIter *iter; g = (struct graphics *) NSA_GET_PTR (env, obj); g_assert (g != NULL); pfont = (struct peerfont *)NSA_GET_FONT_PTR (env, font); g_assert (pfont != NULL); cstr = (*env)->GetStringUTFChars (env, str, NULL); gdk_threads_enter (); pango_layout_set_font_description (pfont->layout, pfont->desc); pango_layout_set_text (pfont->layout, cstr, -1); iter = pango_layout_get_iter (pfont->layout); baseline_y = pango_layout_iter_get_baseline (iter); gdk_draw_layout (g->drawable, g->gc, x + g->x_offset, y + g->y_offset - PANGO_PIXELS (baseline_y), pfont->layout); pango_layout_iter_free (iter); pango_layout_set_text (pfont->layout, "", -1); gdk_flush (); gdk_threads_leave (); (*env)->ReleaseStringUTFChars (env, str, cstr); }
static gboolean gw_spellcheck_get_line_coordinates (GwSpellcheck *spellcheck, int startindex, int endindex, int *x, int *y, int *x2, int *y2) { //Declarations GwSpellcheckPrivate *priv; int index; PangoLayout *layout; PangoRectangle rect; PangoLayoutIter *iter; int xoffset, yoffset; //Initializations priv = spellcheck->priv; layout = gtk_entry_get_layout (priv->entry); iter = pango_layout_get_iter (layout); xoffset = gw_spellcheck_get_layout_x_offset (spellcheck); yoffset = gw_spellcheck_get_layout_y_offset (spellcheck); *x = *y = *x2 = *y2 = 0; do { index = pango_layout_iter_get_index (iter); pango_layout_iter_get_char_extents (iter, &rect); if (index == startindex) { *x = PANGO_PIXELS (rect.x) + xoffset; *y = PANGO_PIXELS (rect.y + rect.height) + yoffset; } if (index == endindex - 1) { *x2 = PANGO_PIXELS (rect.width + rect.x) + xoffset + 1; *y2 = *y; } } while (pango_layout_iter_next_char (iter)); //Cleanup pango_layout_iter_free (iter); return (*x > 0 && *y > 0 && *x2 > 0 && *y2 > 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); }
/** * 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; }
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 rsvg_text_render_text (RsvgDrawingCtx * ctx, const char *text, gdouble * x, gdouble * y) { PangoContext *context; PangoLayout *layout; PangoLayoutIter *iter; RsvgState *state; gint w, h, offsetX, offsetY; state = rsvg_current_state (ctx); /* Do not render the text if the font size is zero. See bug #581491. */ if (state->font_size.length == 0) return; context = ctx->render->create_pango_context (ctx); layout = rsvg_text_create_layout (ctx, state, text, context); pango_layout_get_size (layout, &w, &h); iter = pango_layout_get_iter (layout); if (PANGO_GRAVITY_IS_VERTICAL (state->text_gravity)) { offsetX = -pango_layout_iter_get_baseline (iter) / (double)PANGO_SCALE; offsetY = 0; } else { offsetX = 0; offsetY = pango_layout_iter_get_baseline (iter) / (double)PANGO_SCALE; } pango_layout_iter_free (iter); ctx->render->render_pango_layout (ctx, layout, *x - offsetX, *y - offsetY); if (PANGO_GRAVITY_IS_VERTICAL (state->text_gravity)) *y += w / (double)PANGO_SCALE; else *x += w / (double)PANGO_SCALE; g_object_unref (layout); g_object_unref (context); }
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
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 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); } } } } }
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); } } } }
static PyObject * pango_GetLayoutClusterPos(PyObject *self, PyObject *args) { int i, len, w, h, index, prev_index; int ltr_flag, rtl_flag; double baseline, x, y, width, height, char_width, dx, dy; void *LayoutObj; PangoLayout *layout; PangoLayoutIter *iter; PangoLayoutIter *cluster_iter; PangoRectangle rect, cluster_rect; PangoDirection dir; PyObject *ret; PyObject *layout_data; PyObject *cluster_data; PyObject *cluster_range; PyObject *cluster_index_data; PyObject *cluster_index_range; PyObject *glyph_data; if (!PyArg_ParseTuple(args, "Oi", &LayoutObj, &len)) { return NULL; } layout = PyCObject_AsVoidPtr(LayoutObj); pango_layout_get_size(layout, &w, &h); dx = 0.0; if (pango_layout_get_alignment(layout) == PANGO_ALIGN_CENTER) { dx = -0.5 * ((double) w) / PANGO_SCALE; } else if (pango_layout_get_alignment(layout) == PANGO_ALIGN_RIGHT) { dx = -1.0 * ((double) w) / PANGO_SCALE; } ret = PyTuple_New(5); layout_data = PyList_New(0); cluster_data = PyList_New(0); cluster_index_data = PyList_New(0); PyTuple_SetItem(ret, 0, layout_data); PyTuple_SetItem(ret, 1, cluster_data); PyTuple_SetItem(ret, 2, cluster_index_data); iter = pango_layout_get_iter(layout); cluster_iter = pango_layout_get_iter(layout); prev_index = -1; rtl_flag = 0; ltr_flag = 0; dy = ((double) pango_layout_iter_get_baseline(iter)) / PANGO_SCALE; for (i = 0; i < len; i++) { glyph_data = PyTuple_New(6); //Processing EOL while (pango_layout_iter_get_baseline(cluster_iter) != pango_layout_iter_get_baseline(iter)) { pango_layout_iter_get_char_extents(iter, &rect); x = ((double) rect.x) / PANGO_SCALE + dx; PyTuple_SetItem(glyph_data, 0, PyFloat_FromDouble(x)); y = -1.0 * ((double) rect.y) / PANGO_SCALE + dy; PyTuple_SetItem(glyph_data, 1, PyFloat_FromDouble(y)); width = ((double) rect.width) / PANGO_SCALE; PyTuple_SetItem(glyph_data, 2, PyFloat_FromDouble(width)); height = ((double) rect.height) / PANGO_SCALE; PyTuple_SetItem(glyph_data, 3, PyFloat_FromDouble(height)); baseline = -1.0 * ((double) pango_layout_iter_get_baseline(iter)) / PANGO_SCALE + dy; PyTuple_SetItem(glyph_data, 4, PyFloat_FromDouble(baseline)); //index processing index=pango_layout_iter_get_index(iter); prev_index = index; PyTuple_SetItem(glyph_data, 5, PyInt_FromLong(index)); PyList_Append(layout_data, glyph_data); pango_layout_iter_next_char(iter); i++; glyph_data = PyTuple_New(6); } pango_layout_iter_get_char_extents(iter, &rect); pango_layout_iter_get_cluster_extents(cluster_iter, NULL, &cluster_rect); //Processing cluster data //Layout_data: (x,y,width,height,base_line,byte_index) x = ((double) cluster_rect.x) / PANGO_SCALE + dx; PyTuple_SetItem(glyph_data, 0, PyFloat_FromDouble(x)); y = -1.0 * ((double) cluster_rect.y) / PANGO_SCALE + dy; PyTuple_SetItem(glyph_data, 1, PyFloat_FromDouble(y)); width = ((double) cluster_rect.width) / PANGO_SCALE; PyTuple_SetItem(glyph_data, 2, PyFloat_FromDouble(width)); height = ((double) cluster_rect.height) / PANGO_SCALE; PyTuple_SetItem(glyph_data, 3, PyFloat_FromDouble(height)); baseline = -1.0 * ((double) pango_layout_iter_get_baseline(cluster_iter)) / PANGO_SCALE + dy; PyTuple_SetItem(glyph_data, 4, PyFloat_FromDouble(baseline)); //index processing index=pango_layout_iter_get_index(iter); if (prev_index != -1){ if(index < prev_index){ rtl_flag=1; }else if(index > prev_index){ ltr_flag=1; } } prev_index = index; PyTuple_SetItem(glyph_data, 5, PyInt_FromLong(index)); PyList_Append(layout_data, glyph_data); //Iterating over chars to next cluster if(cluster_rect.width > rect.width){ char_width = rect.width; cluster_range = PyTuple_New(2); cluster_index_range = PyTuple_New(2); PyTuple_SetItem(cluster_range, 0, PyInt_FromLong(i)); PyTuple_SetItem(cluster_index_range, 0, PyInt_FromLong(pango_layout_iter_get_index(iter))); while(cluster_rect.width > char_width){ pango_layout_iter_next_char(iter); pango_layout_iter_get_char_extents(iter, &rect); char_width = char_width + rect.width; i++; } PyTuple_SetItem(cluster_range, 1, PyInt_FromLong(i + 1)); PyTuple_SetItem(cluster_index_range, 1, PyInt_FromLong(pango_layout_iter_get_index(iter))); PyList_Append(cluster_data, cluster_range); PyList_Append(cluster_index_data, cluster_index_range); } pango_layout_iter_next_char(iter); pango_layout_iter_next_cluster(cluster_iter); } pango_layout_iter_free(iter); pango_layout_iter_free(cluster_iter); if(rtl_flag + ltr_flag == 2){ PyTuple_SetItem(ret, 3, PyBool_FromLong(1)); }else{ PyTuple_SetItem(ret, 3, PyBool_FromLong(0)); } dir = pango_find_base_dir(pango_layout_get_text(layout),-1); if(dir == PANGO_DIRECTION_RTL) { PyTuple_SetItem(ret, 4, PyBool_FromLong(1)); } else { PyTuple_SetItem(ret, 4, PyBool_FromLong(0)); } return ret; }
gboolean text_get_extents (const gchar *fontname, const gchar *text, gint *width, gint *height, gint *ascent, gint *descent) { PangoFontDescription *font_desc; PangoContext *context; PangoLayout *layout; PangoFontMap *fontmap; PangoRectangle rect; g_return_val_if_fail (fontname != NULL, FALSE); g_return_val_if_fail (text != NULL, FALSE); fontmap = pango_cairo_font_map_new_for_font_type (CAIRO_FONT_TYPE_FT); if (! fontmap) g_error ("You are using a Pango that has been built against a cairo " "that lacks the Freetype font backend"); pango_cairo_font_map_set_resolution (PANGO_CAIRO_FONT_MAP (fontmap), 72.0); /* FIXME: resolution */ context = pango_font_map_create_context (fontmap); g_object_unref (fontmap); layout = pango_layout_new (context); g_object_unref (context); font_desc = pango_font_description_from_string (fontname); pango_layout_set_font_description (layout, font_desc); pango_font_description_free (font_desc); pango_layout_set_text (layout, text, -1); pango_layout_get_pixel_extents (layout, NULL, &rect); if (width) *width = rect.width; if (height) *height = rect.height; if (ascent || descent) { PangoLayoutIter *iter; PangoLayoutLine *line; iter = pango_layout_get_iter (layout); line = pango_layout_iter_get_line_readonly (iter); pango_layout_iter_free (iter); pango_layout_line_get_pixel_extents (line, NULL, &rect); if (ascent) *ascent = PANGO_ASCENT (rect); if (descent) *descent = - PANGO_DESCENT (rect); } g_object_unref (layout); return TRUE; }