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); }
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); }
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 ); }
/* Get a clip region to draw only part of a layout. index_ranges * contains alternating range starts/stops. The region is the * region which contains the given ranges, i.e. if you draw with the * region as clip, only the given ranges are drawn. */ static cairo_region_t* layout_iter_get_line_clip_region (PangoLayoutIter *iter, gint x_origin, gint y_origin, const gint *index_ranges, gint n_ranges) { PangoLayoutLine *line; cairo_region_t *clip_region; PangoRectangle logical_rect; gint baseline; gint i; line = pango_layout_iter_get_line_readonly (iter); clip_region = cairo_region_create (); pango_layout_iter_get_line_extents (iter, NULL, &logical_rect); baseline = pango_layout_iter_get_baseline (iter); i = 0; while (i < n_ranges) { gint *pixel_ranges = NULL; gint n_pixel_ranges = 0; gint j; /* Note that get_x_ranges returns layout coordinates */ if (index_ranges[i*2+1] >= line->start_index && index_ranges[i*2] < line->start_index + line->length) pango_layout_line_get_x_ranges (line, index_ranges[i*2], index_ranges[i*2+1], &pixel_ranges, &n_pixel_ranges); for (j = 0; j < n_pixel_ranges; j++) { GdkRectangle rect; int x_off, y_off; x_off = PANGO_PIXELS (pixel_ranges[2*j] - logical_rect.x); y_off = PANGO_PIXELS (baseline - logical_rect.y); rect.x = x_origin + x_off; rect.y = y_origin - y_off; rect.width = PANGO_PIXELS (pixel_ranges[2*j + 1] - logical_rect.x) - x_off; rect.height = PANGO_PIXELS (baseline - logical_rect.y + logical_rect.height) - y_off; cairo_region_union_rectangle (clip_region, &rect); } g_free (pixel_ranges); ++i; } return clip_region; }
// 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; } }
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 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; }
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); }
/** * 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 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; }
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); }
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); }
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
static void draw_string(DiaRenderer *self, const char *text, Point *pos, Alignment alignment, Color *color) { DiaCairoRenderer *renderer = DIA_CAIRO_RENDERER (self); int len = strlen(text); DIAG_NOTE(g_message("draw_string(%d) %f,%f %s", len, pos->x, pos->y, text)); if (len < 1) return; /* shouldn't this be handled by Dia's core ? */ cairo_set_source_rgba (renderer->cr, color->red, color->green, color->blue, 1.0); #ifdef HAVE_PANGOCAIRO_H cairo_save (renderer->cr); /* alignment calculation done by pangocairo? */ pango_layout_set_alignment (renderer->layout, alignment == ALIGN_CENTER ? PANGO_ALIGN_CENTER : alignment == ALIGN_RIGHT ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT); pango_layout_set_text (renderer->layout, text, len); { PangoLayoutIter *iter = pango_layout_get_iter(renderer->layout); int bline = pango_layout_iter_get_baseline(iter); /* although we give the alignment above we need to adjust the start point */ PangoRectangle extents; int shift; pango_layout_iter_get_line_extents (iter, NULL, &extents); shift = alignment == ALIGN_CENTER ? PANGO_RBEARING(extents)/2 : alignment == ALIGN_RIGHT ? PANGO_RBEARING(extents) : 0; cairo_move_to (renderer->cr, pos->x - (double)shift / PANGO_SCALE, pos->y - (double)bline / PANGO_SCALE); pango_layout_iter_free (iter); } /* does this hide bug #341481? */ pango_cairo_update_context (renderer->cr, pango_layout_get_context (renderer->layout)); pango_layout_context_changed (renderer->layout); pango_cairo_show_layout (renderer->cr, renderer->layout); cairo_restore (renderer->cr); #else /* using the 'toy API' */ { cairo_text_extents_t extents; double x = 0, y = 0; cairo_set_source_rgba (renderer->cr, color->red, color->green, color->blue, 1.0); cairo_text_extents (renderer->cr, text, &extents); y = pos->y; /* ?? */ switch (alignment) { case ALIGN_LEFT: x = pos->x; break; case ALIGN_CENTER: x = pos->x - extents.width / 2 + +extents.x_bearing; break; case ALIGN_RIGHT: x = pos->x - extents.width + extents.x_bearing; break; } cairo_move_to (renderer->cr, x, y); cairo_show_text (renderer->cr, text); } #endif DIAG_STATE(renderer->cr) }
static boolean pango_textlayout(textspan_t * span, char **fontpath) { static char buf[1024]; /* returned in fontpath, only good until next call */ static PangoFontMap *fontmap; static PangoContext *context; static PangoFontDescription *desc; static char *fontname; static double fontsize; static gv_font_map* gv_fmap; char *fnt, *psfnt = NULL; PangoLayout *layout; PangoRectangle logical_rect; cairo_font_options_t* options; PangoFont *font; #ifdef ENABLE_PANGO_MARKUP PangoAttrList *attrs; GError *error = NULL; int flags; #endif char *text; double textlayout_scale; PostscriptAlias *pA; if (!context) { fontmap = pango_cairo_font_map_new(); gv_fmap = get_font_mapping(fontmap); #ifdef HAVE_PANGO_FONT_MAP_CREATE_CONTEXT context = pango_font_map_create_context (fontmap); #else context = pango_cairo_font_map_create_context (PANGO_CAIRO_FONT_MAP(fontmap)); #endif options=cairo_font_options_create(); cairo_font_options_set_antialias(options,CAIRO_ANTIALIAS_GRAY); cairo_font_options_set_hint_style(options,CAIRO_HINT_STYLE_FULL); cairo_font_options_set_hint_metrics(options,CAIRO_HINT_METRICS_ON); cairo_font_options_set_subpixel_order(options,CAIRO_SUBPIXEL_ORDER_BGR); pango_cairo_context_set_font_options(context, options); pango_cairo_context_set_resolution(context, FONT_DPI); cairo_font_options_destroy(options); g_object_unref(fontmap); } if (!fontname || strcmp(fontname, span->font->name) != 0 || fontsize != span->font->size) { fontname = span->font->name; fontsize = span->font->size; pango_font_description_free (desc); pA = span->font->postscript_alias; if (pA) { psfnt = fnt = gv_fmap[pA->xfig_code].gv_font; if(!psfnt) psfnt = fnt = pango_psfontResolve (pA); } else fnt = fontname; desc = pango_font_description_from_string(fnt); /* all text layout is done at a scale of FONT_DPI (nominaly 96.) */ pango_font_description_set_size (desc, (gint)(fontsize * PANGO_SCALE)); if (fontpath && (font = pango_font_map_load_font(fontmap, context, desc))) { /* -v support */ const char *fontclass; fontclass = G_OBJECT_CLASS_NAME(G_OBJECT_GET_CLASS(font)); buf[0] = '\0'; if (psfnt) { strcat(buf, "(ps:pango "); strcat(buf, psfnt); strcat(buf, ") "); } strcat(buf, "("); strcat(buf, fontclass); strcat(buf, ") "); #ifdef HAVE_PANGO_FC_FONT_LOCK_FACE if (strcmp(fontclass, "PangoCairoFcFont") == 0) { FT_Face face; PangoFcFont *fcfont; FT_Stream stream; FT_StreamDesc streamdesc; fcfont = PANGO_FC_FONT(font); face = pango_fc_font_lock_face(fcfont); if (face) { strcat(buf, "\""); strcat(buf, face->family_name); strcat(buf, ", "); strcat(buf, face->style_name); strcat(buf, "\" "); stream = face->stream; if (stream) { streamdesc = stream->pathname; if (streamdesc.pointer) strcat(buf, (char*)streamdesc.pointer); else strcat(buf, "*no pathname available*"); } else strcat(buf, "*no stream available*"); } pango_fc_font_unlock_face(fcfont); } else #endif { PangoFontDescription *tdesc; char *tfont; tdesc = pango_font_describe(font); tfont = pango_font_description_to_string(tdesc); strcat(buf, "\""); strcat(buf, tfont); strcat(buf, "\" "); g_free(tfont); } *fontpath = buf; } } #ifdef ENABLE_PANGO_MARKUP if ((span->font) && (flags = span->font->flags)) { unsigned char buf[BUFSIZ]; agxbuf xb; agxbinit(&xb, BUFSIZ, buf); agxbput(&xb,"<span"); if (flags & HTML_BF) agxbput(&xb," weight=\"bold\""); if (flags & HTML_IF) agxbput(&xb," style=\"italic\""); if (flags & HTML_UL) agxbput(&xb," underline=\"single\""); if (flags & HTML_S) agxbput(&xb," strikethrough=\"true\""); agxbput (&xb,">"); if (flags & HTML_SUP) agxbput(&xb,"<sup>"); if (flags & HTML_SUB) agxbput(&xb,"<sub>"); agxbput (&xb,xml_string0(span->str, TRUE)); if (flags & HTML_SUB) agxbput(&xb,"</sub>"); if (flags & HTML_SUP) agxbput(&xb,"</sup>"); agxbput (&xb,"</span>"); if (!pango_parse_markup (agxbuse(&xb), -1, 0, &attrs, &text, NULL, &error)) { fprintf (stderr, "Error - pango_parse_markup: %s\n", error->message); text = span->str; attrs = NULL; } agxbfree (&xb); } else { text = span->str; attrs = NULL; } #else text = span->str; #endif layout = pango_layout_new (context); span->layout = (void *)layout; /* layout free with textspan - see labels.c */ span->free_layout = pango_free_layout; /* function for freeing pango layout */ pango_layout_set_text (layout, text, -1); pango_layout_set_font_description (layout, desc); #ifdef ENABLE_PANGO_MARKUP if (attrs) pango_layout_set_attributes (layout, attrs); #endif pango_layout_get_extents (layout, NULL, &logical_rect); /* if pango doesn't like the font then it sets width=0 but height = garbage */ if (logical_rect.width == 0) logical_rect.height = 0; textlayout_scale = POINTS_PER_INCH / (FONT_DPI * PANGO_SCALE); span->size.x = (int)(logical_rect.width * textlayout_scale + 1); /* round up so that width/height are never too small */ span->size.y = (int)(logical_rect.height * textlayout_scale + 1); /* FIXME -- Horrible kluge !!! */ /* For now we are using pango for single line blocks only. * The logical_rect.height seems to be too high from the font metrics on some platforms. * Use an assumed height based on the point size. */ span->size.y = (int)(span->font->size * 1.1 + .5); /* The y offset from baseline to 0,0 of the bitmap representation */ #if !defined(WIN32) && defined PANGO_VERSION_MAJOR && (PANGO_VERSION_MAJOR >= 1) span->yoffset_layout = pango_layout_get_baseline (layout) * textlayout_scale; #else { /* do it the hard way on rhel5/centos5 */ PangoLayoutIter *iter = pango_layout_get_iter (layout); span->yoffset_layout = pango_layout_iter_get_baseline (iter) * textlayout_scale; } #endif /* The distance below midline for y centering of text strings */ span->yoffset_centerline = 0.2 * span->font->size; if (logical_rect.width == 0) return FALSE; return TRUE; }
static void draw_str(struct gra2cairo_local *local, int draw, char *str, struct fontmap *font, int size, int space, int *fw, int *ah, int *dh) { PangoAttribute *attr; PangoAttrList *alist; PangoLayoutIter *piter; int w, h, baseline; if (size == 0 || str == NULL) { if (fw) *fw = 0; if (ah) *ah = 0; if (dh) *dh = 0; return; } if (local->layout == NULL) { local->layout = pango_cairo_create_layout(local->cairo); } alist = pango_attr_list_new(); attr = pango_attr_size_new_absolute(mxd2ph(local, size) * PANGO_SCALE); pango_attr_list_insert(alist, attr); attr = pango_attr_letter_spacing_new(mxd2ph(local, space) * PANGO_SCALE); pango_attr_list_insert(alist, attr); pango_layout_set_font_description(local->layout, font->font); pango_layout_set_attributes(local->layout, alist); pango_attr_list_unref(alist); pango_layout_set_text(local->layout, str, -1); pango_layout_get_pixel_size(local->layout, &w, &h); piter = pango_layout_get_iter(local->layout); baseline = pango_layout_iter_get_baseline(piter) / PANGO_SCALE; if (fw) *fw = w; if (ah) *ah = baseline; if (dh) *dh = h - baseline; if (draw && str) { double x, y; double cx, cy; x = - local->fontsin * baseline; y = - local->fontcos * baseline; cairo_get_current_point(local->cairo, &cx, &cy); relative_move(local->cairo, x, y); cairo_save(local->cairo); cairo_rotate(local->cairo, -local->fontdir * G_PI / 180.); pango_cairo_update_layout(local->cairo, local->layout); if (local->text2path) { pango_cairo_layout_path(local->cairo, local->layout); cairo_fill(local->cairo); cairo_restore(local->cairo); cairo_move_to(local->cairo, cx + w * local->fontcos, cy - w * local->fontsin); } else { pango_cairo_show_layout(local->cairo, local->layout); cairo_restore(local->cairo); relative_move(local->cairo, w * local->fontcos - x, - w * local->fontsin - y); } } pango_layout_iter_free(piter); }
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); }
/* {EV_FONT_IMP}.string_size */ EIF_REFERENCE F1035_13204 (EIF_REFERENCE Current, EIF_REFERENCE arg1) { GTCX EIF_REFERENCE loc1 = (EIF_REFERENCE) 0; EIF_POINTER loc2 = (EIF_POINTER) 0; EIF_POINTER loc3 = (EIF_POINTER) 0; EIF_POINTER loc4 = (EIF_POINTER) 0; EIF_POINTER loc5 = (EIF_POINTER) 0; EIF_INTEGER_32 loc6 = (EIF_INTEGER_32) 0; EIF_INTEGER_32 loc7 = (EIF_INTEGER_32) 0; EIF_INTEGER_32 loc8 = (EIF_INTEGER_32) 0; EIF_INTEGER_32 loc9 = (EIF_INTEGER_32) 0; EIF_INTEGER_32 loc10 = (EIF_INTEGER_32) 0; EIF_INTEGER_32 loc11 = (EIF_INTEGER_32) 0; EIF_INTEGER_32 loc12 = (EIF_INTEGER_32) 0; EIF_INTEGER_32 loc13 = (EIF_INTEGER_32) 0; EIF_INTEGER_32 loc14 = (EIF_INTEGER_32) 0; EIF_INTEGER_32 loc15 = (EIF_INTEGER_32) 0; EIF_INTEGER_32 loc16 = (EIF_INTEGER_32) 0; EIF_INTEGER_32 loc17 = (EIF_INTEGER_32) 0; EIF_INTEGER_32 loc18 = (EIF_INTEGER_32) 0; EIF_INTEGER_32 loc19 = (EIF_INTEGER_32) 0; EIF_INTEGER_32 loc20 = (EIF_INTEGER_32) 0; EIF_REFERENCE loc21 = (EIF_REFERENCE) 0; EIF_POINTER tp1; EIF_POINTER tp2; EIF_INTEGER_32 ti4_1; EIF_REFERENCE Result = ((EIF_REFERENCE) 0); RTLD; RTLI(5); RTLR(0,loc21); RTLR(1,Current); RTLR(2,loc1); RTLR(3,arg1); RTLR(4,Result); RTGC; loc21 = RTOSCF(13229,F1035_13229,(Current)); loc1 = F1049_13651(RTCV(loc21), arg1); loc2 = RTOSCF(8093,F791_8093,(RTCV(loc21))); tp1 = *(EIF_POINTER *)(RTCV(loc1)+ _PTROFF_0_1_0_1_0_0_); ti4_1 = *(EIF_INTEGER_32 *)(RTCV(loc1)+ _LNGOFF_0_1_0_0_); pango_layout_set_text((PangoLayout*) loc2, (char*) tp1, (int) ti4_1); tp1 = *(EIF_POINTER *)(Current+ _PTROFF_3_2_0_8_0_0_); pango_layout_set_font_description((PangoLayout*) loc2, (PangoFontDescription*) tp1); loc4 = (EIF_POINTER) calloc (sizeof(PangoRectangle), 1); loc5 = RTOSCF(13207,F1035_13207,(Current)); pango_layout_get_pixel_extents((PangoLayout*) loc2, (PangoRectangle*) loc4, (PangoRectangle*) loc5); loc3 = F791_8094(RTCV(loc21)); loc20 = (EIF_INTEGER_32) pango_layout_iter_get_baseline((PangoLayoutIter*) loc3); ti4_1 = (EIF_INTEGER_32) PANGO_SCALE; loc20 = (EIF_INTEGER_32) (EIF_INTEGER_32) (loc20 / ti4_1); pango_layout_iter_free((PangoLayoutIter*) loc3); loc6 = (EIF_INTEGER_32) (((PangoRectangle *)loc5)->x); loc7 = (EIF_INTEGER_32) (((PangoRectangle *)loc5)->y); loc8 = (EIF_INTEGER_32) (((PangoRectangle *)loc5)->width); loc9 = (EIF_INTEGER_32) (((PangoRectangle *)loc5)->height); loc10 = (EIF_INTEGER_32) (((PangoRectangle *)loc4)->x); loc11 = (EIF_INTEGER_32) (((PangoRectangle *)loc4)->y); loc12 = (EIF_INTEGER_32) (((PangoRectangle *)loc4)->width); loc13 = (EIF_INTEGER_32) (((PangoRectangle *)loc4)->height); loc14 = (EIF_INTEGER_32) loc8; loc15 = (EIF_INTEGER_32) loc9; if ((EIF_BOOLEAN) (loc12 > ((EIF_INTEGER_32) 0L))) { loc16 = (EIF_INTEGER_32) loc10; loc17 = (EIF_INTEGER_32) (EIF_INTEGER_32) ((EIF_INTEGER_32) (loc16 + loc12) - loc8); } if ((EIF_BOOLEAN) (loc13 > ((EIF_INTEGER_32) 0L))) { loc18 = (EIF_INTEGER_32) loc11; loc19 = (EIF_INTEGER_32) (EIF_INTEGER_32) ((EIF_INTEGER_32) (loc18 + loc13) - loc9); } Result = RTOSCF(13205,F1035_13205,(Current)); ti4_1 = eif_max_int32 (loc14,((EIF_INTEGER_32) 1L)); F842_8563(RTCV(Result), ti4_1, ((EIF_INTEGER_32) 1L)); ti4_1 = eif_max_int32 (loc15,((EIF_INTEGER_32) 1L)); F842_8563(RTCV(Result), ti4_1, ((EIF_INTEGER_32) 2L)); F842_8563(RTCV(Result), loc16, ((EIF_INTEGER_32) 3L)); F842_8563(RTCV(Result), loc17, ((EIF_INTEGER_32) 4L)); F842_8563(RTCV(Result), loc20, ((EIF_INTEGER_32) 5L)); F842_8563(RTCV(Result), loc18, ((EIF_INTEGER_32) 6L)); F842_8563(RTCV(Result), loc19, ((EIF_INTEGER_32) 7L)); free(loc4); { /* INLINED CODE (default_pointer) */ tp1 = (EIF_POINTER) 0; /* END INLINED CODE */ } tp2 = tp1; pango_layout_set_font_description((PangoLayout*) loc2, (PangoFontDescription*) tp2); RTLE; return Result; }
static VALUE layout_iter_get_baseline(VALUE self) { return INT2NUM(pango_layout_iter_get_baseline(_SELF(self))); }
void text_widget_draw_text ( struct TEXT_WIDGET_HANDLE handle ) { if ( handle.d == NULL || handle.d->layout == NULL ) return; vgSetPaint( handle.d->foreground, VG_FILL_PATH ); vgSeti( VG_MATRIX_MODE, VG_MATRIX_GLYPH_USER_TO_SURFACE ); vgLoadIdentity(); #if 0 // Overscan (in dots, evidently). vgTranslate( 14.f, 8.f ); #endif // Offset in mm. vgScale( handle.d->dpmm_x, handle.d->dpmm_y ); // Move to the corner. vgTranslate( handle.d->x_mm, handle.d->y_mm ); // Back to dots. vgScale( 1.f/handle.d->dpmm_x, 1.f/handle.d->dpmm_y ); int height = PANGO_PIXELS( pango_layout_get_height( handle.d->layout ) ); PangoLayoutIter* li = pango_layout_get_iter( handle.d->layout ); do { PangoLayoutRun* run = pango_layout_iter_get_run( li ); if ( run == NULL ) continue; PangoRectangle logical_rect; int baseline_pango = pango_layout_iter_get_baseline( li ); int baseline_pixel = PANGO_PIXELS( baseline_pango ); pango_layout_iter_get_run_extents( li, NULL, &logical_rect ); int x_pixel = PANGO_PIXELS( logical_rect.x ); PangoFont* pg_font = run->item->analysis.font; FT_Face face = pango_fc_font_lock_face( (PangoFcFont*)pg_font ); if ( face != NULL ) { struct VG_DATA* vg_data = face->size->generic.data; if ( vg_data != NULL ) { // About the only extra attribute we can manage is the foreground // color. But, it might be nice to render a background color // to see just how badly the text is fitted into the widget // box. GSList* attr_item = run->item->analysis.extra_attrs; while ( attr_item ) { PangoAttribute* attr = attr_item->data; switch ( attr->klass->type ) { case PANGO_ATTR_FOREGROUND: { PangoColor color = ((PangoAttrColor*)attr)->color; VGfloat new_color[] = { (float)color.red / 65535.f, (float)color.green / 65535.f, (float)color.blue / 65535.f, 1.f }; VGPaint new_paint = vgCreatePaint(); vgSetParameterfv( new_paint, VG_PAINT_COLOR, 4, new_color ); vgSetPaint( new_paint, VG_FILL_PATH ); vgDestroyPaint( new_paint ); } break; default: printf( "\tHmm. Unknown attribute: %d\n", attr->klass->type ); } attr_item = attr_item->next; } // Note: inverted Y coordinate VGfloat point[2] = { x_pixel, height - baseline_pixel }; vgSetfv( VG_GLYPH_ORIGIN, 2, point ); VGFont vg_font = vg_data->font; int g; for ( g = 0; g < run->glyphs->num_glyphs; g++ ) { vgDrawGlyph( vg_font, run->glyphs->glyphs[g].glyph, VG_FILL_PATH, VG_TRUE ); } if ( vgGetPaint( VG_FILL_PATH ) != handle.d->foreground ) { vgSetPaint( handle.d->foreground, VG_FILL_PATH ); } } pango_fc_font_unlock_face( (PangoFcFont*)pg_font ); } } while ( pango_layout_iter_next_run( li ) ); // Iterators are not free. pango_layout_iter_free( li); }
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 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 PyObject * pango_GetLayoutCharPos(PyObject *self, PyObject *args) { int i, len, w, h; double baseline, x, y, width, height, dx, dy; void *LayoutObj; PangoLayout *layout; PangoLayoutIter *iter; PangoRectangle rect; PyObject *ret; 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(len); iter = pango_layout_get_iter(layout); dy = ((double) pango_layout_iter_get_baseline(iter)) / PANGO_SCALE; for (i = 0; i < len; i++) { glyph_data = PyTuple_New(5); 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)); pango_layout_iter_next_char(iter); PyTuple_SetItem(ret, i, glyph_data); } pango_layout_iter_free(iter); return ret; }
static void _vte_pango_x_set_text_font(struct _vte_draw *draw, const PangoFontDescription *fontdesc, VteTerminalAntiAlias antialias) { PangoContext *ctx; Display *display; PangoLayout *layout; PangoLayoutIter *iter; PangoRectangle ink, logical; gunichar full_codepoints[] = {VTE_DRAW_DOUBLE_WIDE_IDEOGRAPHS}; GString *full_string; gint full_width; guint i; struct _vte_pango_x_data *data; data = (struct _vte_pango_x_data*) draw->impl_data; display = gdk_x11_display_get_xdisplay(gtk_widget_get_display(draw->widget)); if (data->ctx != NULL) { g_object_unref(data->ctx); } ctx = pango_x_get_context(display); layout = pango_layout_new(ctx); if (data->font != NULL) { pango_font_description_free(data->font); } data->font = pango_font_description_copy(fontdesc); pango_layout_set_font_description(layout, data->font); /* Estimate for ASCII characters. */ pango_layout_set_text(layout, VTE_DRAW_SINGLE_WIDE_CHARACTERS, strlen(VTE_DRAW_SINGLE_WIDE_CHARACTERS)); pango_layout_get_extents(layout, &ink, &logical); draw->width = logical.width; draw->width = howmany(draw->width, strlen(VTE_DRAW_SINGLE_WIDE_CHARACTERS)); iter = pango_layout_get_iter(layout); draw->height = PANGO_PIXELS(logical.height); draw->ascent = PANGO_PIXELS(pango_layout_iter_get_baseline(iter)); pango_layout_iter_free(iter); /* Estimate for CJK characters. */ full_string = g_string_new(NULL); for (i = 0; i < G_N_ELEMENTS(full_codepoints); i++) { g_string_append_unichar(full_string, full_codepoints[i]); } pango_layout_set_text(layout, full_string->str, full_string->len); pango_layout_get_extents(layout, &ink, &logical); full_width = howmany(logical.width, G_N_ELEMENTS(full_codepoints)); g_string_free(full_string, TRUE); /* If they're the same, then we have a screwy font. */ if (full_width == draw->width) { /* add 1 to round up when dividing by 2 */ draw->width = (draw->width + 1) / 2; } draw->width = PANGO_PIXELS(draw->width); iter = pango_layout_get_iter(layout); if (draw->height == 0) { draw->height = PANGO_PIXELS(logical.height); } if (draw->ascent == 0) { draw->ascent = PANGO_PIXELS(pango_layout_iter_get_baseline(iter)); } pango_layout_iter_free(iter); _vte_debug_print(VTE_DEBUG_MISC, "VtePangoX font metrics = %dx%d (%d).\n", draw->width, draw->height, draw->ascent); g_object_unref(layout); g_object_unref(ctx); }
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; }