real dia_font_ascent(const char* string, DiaFont* font, real height) { if (font->metrics) { real ascent = pdu_to_dcm(pango_font_metrics_get_ascent (font->metrics)); return ascent * (height / font->height); } else { /* previous, _expensive_ but string specific way */ TextLine *text_line = text_line_new(string, font, height); real result = text_line_get_ascent(text_line); text_line_destroy(text_line); return result; } }
static void calc_ascent_descent(Text *text) { real sig_a = 0.0,sig_d = 0.0; gint i; for ( i = 0; i < text->numlines; i++) { sig_a += text_line_get_ascent(text->lines[i]); sig_d += text_line_get_descent(text->lines[i]); } text->ascent = sig_a / (real)text->numlines; text->descent = sig_d / (real)text->numlines; }
/** Draw a TextLine object. * @param object The renderer object to use for transform and output * @param text_line The TextLine to render, including font and height. * @param pos The position to render it at. * @param color The color to render it with. */ static void draw_text_line (DiaRenderer *object, TextLine *text_line, Point *pos, Alignment alignment, Color *color) { DiaGdkRenderer *renderer = DIA_GDK_RENDERER (object); GdkColor gdkcolor; int x,y; Point start_pos; PangoLayout* layout = NULL; const gchar *text = text_line_get_string(text_line); int height_pixels; real font_height = text_line_get_height(text_line); real scale = dia_transform_length(renderer->transform, 1.0); if (text == NULL || *text == '\0') return; /* Don't render empty strings. */ point_copy(&start_pos,pos); renderer_color_convert(renderer, color, &gdkcolor); height_pixels = dia_transform_length(renderer->transform, font_height); if (height_pixels < 2) { /* "Greeking" instead of making tiny font */ int width_pixels = dia_transform_length(renderer->transform, text_line_get_width(text_line)); gdk_gc_set_foreground(renderer->gc, &gdkcolor); gdk_gc_set_dashes(renderer->gc, 0, (gint8*)"\1\2", 2); dia_transform_coords(renderer->transform, start_pos.x, start_pos.y, &x, &y); gdk_draw_line(renderer->pixmap, renderer->gc, x, y, x + width_pixels, y); return; } else { start_pos.y -= text_line_get_ascent(text_line); start_pos.x -= text_line_get_alignment_adjustment (text_line, alignment); dia_transform_coords(renderer->transform, start_pos.x, start_pos.y, &x, &y); layout = dia_font_build_layout(text, text_line->font, dia_transform_length(renderer->transform, text_line->height)/20.0); #if defined(PANGO_VERSION_ENCODE) # if (PANGO_VERSION >= PANGO_VERSION_ENCODE(1,16,0)) /* I'd say the former Pango API was broken, i.e. leaky */ # define HAVE_pango_layout_get_line_readonly # endif #endif text_line_adjust_layout_line (text_line, #if defined(HAVE_pango_layout_get_line_readonly) pango_layout_get_line_readonly(layout, 0), #else pango_layout_get_line(layout, 0), #endif scale/20.0); if (renderer->highlight_color != NULL) { draw_highlighted_string(renderer, layout, x, y, &gdkcolor); } else { #if defined HAVE_FREETYPE { FT_Bitmap ftbitmap; int width, height; GdkPixbuf *rgba = NULL; width = dia_transform_length(renderer->transform, text_line_get_width(text_line)); height = dia_transform_length(renderer->transform, text_line_get_height(text_line)); if (width > 0) { int stride; guchar* pixels; int i,j; guint8 *graybitmap; initialize_ft_bitmap(&ftbitmap, width, height); pango_ft2_render_layout(&ftbitmap, layout, 0, 0); graybitmap = ftbitmap.buffer; rgba = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, width, height); stride = gdk_pixbuf_get_rowstride(rgba); pixels = gdk_pixbuf_get_pixels(rgba); for (i = 0; i < height; i++) { for (j = 0; j < width; j++) { pixels[i*stride+j*4] = gdkcolor.red>>8; pixels[i*stride+j*4+1] = gdkcolor.green>>8; pixels[i*stride+j*4+2] = gdkcolor.blue>>8; pixels[i*stride+j*4+3] = graybitmap[i*ftbitmap.pitch+j]; } } g_free(graybitmap); gdk_draw_pixbuf(renderer->pixmap, renderer->gc, rgba, 0, 0, x, y, width, height, GDK_RGB_DITHER_NONE, 0, 0); g_object_unref(G_OBJECT(rgba)); } } #else gdk_gc_set_foreground(renderer->gc, &gdkcolor); gdk_draw_layout(renderer->pixmap, renderer->gc, x, y, layout); #endif } /* !higlight_color */ g_object_unref(G_OBJECT(layout)); } /* !greeking */