- text_width += (double)slot->metrics.horiAdvance / 64.0;
- }
- text_width -= (double)slot->metrics.horiAdvance / 64.0; /* remove last step */
- text_width += (double)slot->metrics.width / 64.0; /* add just char width */
- text_width += (double)slot->metrics.horiBearingX / 64.0; /* add just char width */
- FT_Done_FreeType(library);
- return text_width;
-}
-
-
-
-
-static int gfx_save_png (art_u8 *buffer, FILE *fp,
- long width, long height, long bytes_per_pixel);
-/* render grafics into png image */
-int gfx_render_png (gfx_canvas_t *canvas,
- art_u32 width, art_u32 height,
- gfx_color_t background, FILE *fp){
-
-
- FT_Library library;
- gfx_node_t *node = canvas->firstnode;
- art_u8 red = background >> 24, green = (background >> 16) & 0xff;
- art_u8 blue = (background >> 8) & 0xff, alpha = ( background & 0xff );
- unsigned long pys_width = width * canvas->zoom;
- unsigned long pys_height = height * canvas->zoom;
- const int bytes_per_pixel = 3;
- unsigned long rowstride = pys_width*bytes_per_pixel; /* bytes per pixel */
- art_u8 *buffer = art_new (art_u8, rowstride*pys_height);
- art_rgb_run_alpha (buffer, red, green, blue, alpha, pys_width*pys_height);
- FT_Init_FreeType( &library );
- while(node){
- switch (node->type) {
- case GFX_LINE:
- case GFX_AREA: {
- ArtVpath *vec;
- double dst[6];
- ArtSVP *svp;
- if (node->closed_path) {
- /* libart uses end==start for closed as indicator of closed path */
- gfx_add_point(node, node->path[0].x, node->path[0].y);
- node->closed_path = 0;
- }
- art_affine_scale(dst,canvas->zoom,canvas->zoom);
- vec = art_vpath_affine_transform(node->path,dst);
- if(node->type == GFX_LINE){
- svp = art_svp_vpath_stroke ( vec, ART_PATH_STROKE_JOIN_ROUND,
- ART_PATH_STROKE_CAP_ROUND,
- node->size*canvas->zoom,1,1);
- } else {
- svp = art_svp_from_vpath ( vec );
- }
- art_free(vec);
- art_rgb_svp_alpha (svp ,0,0, pys_width, pys_height,
- node->color, buffer, rowstride, NULL);
- art_free(svp);
- break;
- }
- case GFX_TEXT: {
- int error;
- float text_width=0.0, text_height = 0.0;
- unsigned char *text;
- art_u8 fcolor[3],falpha;
- FT_Face face;
- FT_GlyphSlot slot;
- FT_UInt previous=0;
- FT_UInt glyph_index=0;
- FT_Bool use_kerning;
-
- float pen_x = 0.0 , pen_y = 0.0;
- /* double x,y; */
- long ix,iy,iz;
-
- fcolor[0] = node->color >> 24;
- fcolor[1] = (node->color >> 16) & 0xff;
- fcolor[2] = (node->color >> 8) & 0xff;
- falpha = node->color & 0xff;
- error = FT_New_Face( library,
- (char *)node->filename,
- 0,
- &face );
- if ( error ) break;
- use_kerning = FT_HAS_KERNING(face);
-
- error = FT_Set_Char_Size(face, /* handle to face object */
- (long)(node->size*64),
- (long)(node->size*64),
- (long)(100*canvas->zoom),
- (long)(100*canvas->zoom));
- if ( error ) break;
- pen_x = node->x * canvas->zoom;
- pen_y = node->y * canvas->zoom;
- slot = face->glyph;
-
- for(text=(unsigned char *)node->text;*text;text++) {
- previous = glyph_index;
- glyph_index = FT_Get_Char_Index( face, *text);
-
- if (use_kerning && previous && glyph_index){
- FT_Vector delta;
- FT_Get_Kerning( face, previous, glyph_index,
- 0, &delta );
- text_width += (double)delta.x / 64.0;
-
- }
- error = FT_Load_Glyph( face, glyph_index, 0 );
- if ( error ) break;
- if (previous == 0){
- pen_x -= (double)slot->metrics.horiBearingX / 64.0; /* adjust pos for first char */
- text_width -= (double)slot->metrics.horiBearingX / 64.0; /* add just char width */
- }
- if ( text_height < (double)slot->metrics.horiBearingY / 64.0 ) {
- text_height = (double)slot->metrics.horiBearingY / 64.0;
- }
- text_width += (double)slot->metrics.horiAdvance / 64.0;
- }
- text_width -= (double)slot->metrics.horiAdvance / 64.0; /* remove last step */
- text_width += (double)slot->metrics.width / 64.0; /* add just char width */
- text_width += (double)slot->metrics.horiBearingX / 64.0; /* add just char width */
-
- switch(node->halign){
- case GFX_H_RIGHT: pen_x -= text_width; break;
- case GFX_H_CENTER: pen_x -= text_width / 2.0; break;
- case GFX_H_LEFT: break;
- }
-
- switch(node->valign){
- case GFX_V_TOP: pen_y += text_height; break;
- case GFX_V_CENTER: pen_y += text_height / 2.0; break;
- case GFX_V_BOTTOM: break;
- }
-
- glyph_index=0;
- for(text=(unsigned char *)node->text;*text;text++) {
- int gr;
- previous = glyph_index;
- glyph_index = FT_Get_Char_Index( face, *text);
-
- if (use_kerning && previous && glyph_index){
- FT_Vector delta;
- FT_Get_Kerning( face, previous, glyph_index,
- 0, &delta );
- pen_x += (double)delta.x / 64.0;
-
- }
- error = FT_Load_Glyph( face, glyph_index, FT_LOAD_RENDER );
- if ( error ) break;
- gr = slot->bitmap.num_grays -1;
- for (iy=0; iy < slot->bitmap.rows; iy++){
- long buf_y = iy+(pen_y+0.5)-slot->bitmap_top;
- if (buf_y < 0 || buf_y >= pys_height) continue;
- buf_y *= rowstride;
- for (ix=0;ix < slot->bitmap.width;ix++){
- long buf_x = ix + (pen_x + 0.5) + (double)slot->bitmap_left ;
- art_u8 font_alpha;
-
- if (buf_x < 0 || buf_x >= pys_width) continue;
- buf_x *= bytes_per_pixel ;
- font_alpha = *(slot->bitmap.buffer + iy * slot->bitmap.width + ix);
- font_alpha = (art_u8)((double)font_alpha / gr * falpha);
- for (iz = 0; iz < 3; iz++){
- art_u8 *orig = buffer + buf_y + buf_x + iz;
- *orig = (art_u8)((double)*orig / gr * ( gr - font_alpha) +
- (double)fcolor[iz] / gr * (font_alpha));
- }
- }
- }
- pen_x += (double)slot->metrics.horiAdvance / 64.0;
- }
- }
- }
- node = node->next;
- }
- gfx_save_png(buffer,fp , pys_width,pys_height,bytes_per_pixel);
- art_free(buffer);
- FT_Done_FreeType( library );
- return 0;
-}
-
-/* free memory used by nodes this will also remove memory required for
- associated paths and svcs ... but not for text strings */
-int
-gfx_destroy (gfx_canvas_t *canvas){
- gfx_node_t *next,*node = canvas->firstnode;
- while(node){
- next = node->next;
- art_free(node->path);
- art_free(node->svp);
- free(node->text);
- free(node->filename);
- art_free(node);
- node = next;
- }
- return 0;
-}
-
-static int gfx_save_png (art_u8 *buffer, FILE *fp, long width, long height, long bytes_per_pixel){
- png_structp png_ptr = NULL;
- png_infop info_ptr = NULL;
- int i;
- png_bytep *row_pointers;
- int rowstride = width * bytes_per_pixel;
- png_text text[2];
-
- if (fp == NULL)
- return (1);
-
- png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL);
- if (png_ptr == NULL)
- {
- return (1);
- }
- row_pointers = (png_bytepp)png_malloc(png_ptr,
- height*sizeof(png_bytep));
-
- info_ptr = png_create_info_struct(png_ptr);
-
- if (info_ptr == NULL)
- {
- png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
- return (1);
+ layout = gfx_prep_text(im, start, color, font, size, tabwidth, text);
+ pango_layout_get_pixel_extents(layout, NULL, &log_rect);
+ pango_tab_array_free(pango_layout_get_tabs(layout));
+ g_object_unref(layout);
+ return log_rect.width;
+}
+
+void gfx_text(
+ image_desc_t *im,
+ double x,
+ double y,
+ gfx_color_t color,
+ char *font,
+ double size,
+ double tabwidth,
+ double angle,
+ enum gfx_h_align_en h_align,
+ enum gfx_v_align_en v_align,
+ const char *text)
+{
+ PangoLayout *layout;
+ PangoRectangle log_rect;
+ PangoRectangle ink_rect;
+ cairo_t *cr = im->cr;
+ double sx = 0;
+ double sy = 0;
+
+ cairo_save(cr);
+ cairo_translate(cr, x, y);
+/* gfx_line(cr,-2,0,2,0,1,color);
+ gfx_line(cr,0,-2,0,2,1,color); */
+ layout = gfx_prep_text(im, x, color, font, size, tabwidth, text);
+ pango_layout_get_pixel_extents(layout, &ink_rect, &log_rect);
+ cairo_rotate(cr, -angle * G_PI / 180.0);
+ sx = log_rect.x;
+ switch (h_align) {
+ case GFX_H_RIGHT:
+ sx -= log_rect.width;
+ break;
+ case GFX_H_CENTER:
+ sx -= log_rect.width / 2;
+ break;
+ case GFX_H_LEFT:
+ break;
+ case GFX_H_NULL:
+ break;