From 43ce6f94b349fca234abdc3c3b1cbd4ca45cc752 Mon Sep 17 00:00:00 2001 From: Carlos Lopez Date: Jun 16 2013 17:45:35 +0000 Subject: Layer_FreeType: add support for Cairo render using cairo_t*. --- diff --git a/synfig-core/src/modules/lyr_freetype/lyr_freetype.cpp b/synfig-core/src/modules/lyr_freetype/lyr_freetype.cpp index 53d94a9..eb4fde7 100644 --- a/synfig-core/src/modules/lyr_freetype/lyr_freetype.cpp +++ b/synfig-core/src/modules/lyr_freetype/lyr_freetype.cpp @@ -41,7 +41,7 @@ #include "lyr_freetype.h" #endif - +#include #include using namespace std; @@ -1091,6 +1091,182 @@ Layer_Freetype::accelerated_cairorender(Context context,cairo_surface_t *surface return true; } //// +//// +bool +Layer_Freetype::accelerated_cairorender(Context context, cairo_t *cr, int quality, const RendDesc &renddesc, ProgressCallback *cb)const +{ + if(!is_solid_color()) + { + // Initially render what's behind us + if(!context.accelerated_cairorender(cr,quality,renddesc,cb)) + { + if(cb)cb->error(strprintf(__FILE__"%d: Accelerated Cairo Renderer Failure",__LINE__)); + return false; + } + } + + RendDesc workdesc(renddesc); + + // Untransform the render desc + if(!cairo_renddesc_untransform(cr, workdesc)) + return false; + + // New expanded workdesc values + const int ww=workdesc.get_w(); + const int wh=workdesc.get_h(); + const double wtlx=workdesc.get_tl()[0]; + const double wtly=workdesc.get_tl()[1]; + const double wpw=workdesc.get_pw(); + const double wph=workdesc.get_ph(); + const double wsx=1/wpw; + const double wsy=1/wph; + const double wtx=(-wtlx+origin[0])*wsx; + const double wty=(-wtly+origin[1])*wsy; + + // Cairo context + cairo_surface_t* subimage; + cairo_surface_t* inverted; + subimage=cairo_surface_create_similar(cairo_get_target(cr), CAIRO_CONTENT_COLOR_ALPHA, ww, wh); + cairo_t* subcr=cairo_create(subimage); + cairo_t* invertcr; + if(invert) + { + inverted=cairo_surface_create_similar(cairo_get_target(cr), CAIRO_CONTENT_COLOR_ALPHA, ww, wh); + invertcr=cairo_create(inverted); + cairo_set_source_rgba(invertcr, color.get_r(), color.get_g(), color.get_b(), color.get_a()); + cairo_paint_with_alpha(invertcr, get_amount()); + } + + // Pango + PangoLayout *layout; + PangoFontDescription *font_description; + // Pango Font + font_description = pango_font_description_new (); + pango_font_description_set_family (font_description, font.c_str()); + pango_font_description_set_weight (font_description, PangoWeight(weight)); + pango_font_description_set_style (font_description, PangoStyle(style)); + // The size is scaled to match Software render size (remove the scale?) + float sizex=1.75*fabs(size[0])*fabs(wsx); + float sizey=1.75*fabs(size[1])*fabs(wsy); + float vscale=sizey/sizex; + pango_font_description_set_absolute_size (font_description, sizex * PANGO_SCALE ); + + //Pango Layout + layout = pango_cairo_create_layout (subcr); + + pango_layout_set_font_description (layout, font_description); + pango_layout_set_text (layout, text.c_str(), -1); + if(orient[0]<0.4) + pango_layout_set_alignment(layout, PANGO_ALIGN_LEFT); + else if(orient[0]>0.6) + pango_layout_set_alignment(layout, PANGO_ALIGN_RIGHT); + else + pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER); + + pango_layout_set_single_paragraph_mode(layout, false); + + // Calculate the logical and ink rectangles of the layout before add spacing + PangoRectangle ink_layout, logical_layout; + PangoRectangle ink_rect, logical_rect; + pango_layout_get_pixel_extents(layout, &ink_layout, &logical_layout); + + // Spacing + // Horizontal + PangoAttrList* attrlist=pango_attr_list_new(); + float hspace=compress>1.0?0.4*sizex*(compress-1.0):(compress<1.0)?0.5*sizex*(compress-1.0):0; + PangoAttribute* spacing=pango_attr_letter_spacing_new(hspace*PANGO_SCALE); + pango_attr_list_insert_before(attrlist, spacing); + pango_layout_set_attributes(layout, attrlist); + + // Vertical + int total_lines=pango_layout_get_line_count(layout); + float vspace_total=vcompress>1.0?0.4*logical_layout.height*(vcompress-1.0):(vcompress<1.0)?0.6*logical_layout.height*(vcompress-1.0):0; + float vspace; + if(total_lines>1) + vspace=vspace_total/(total_lines-1); + pango_layout_set_spacing(layout, vspace*PANGO_SCALE); + + // Recalculate extents due to spacing changes + pango_layout_get_pixel_extents(layout, &ink_layout, &logical_layout); + + // Render text + cairo_save(subcr); + cairo_set_source_rgba(subcr, color.get_r(), color.get_g(), color.get_b(), color.get_a()); + cairo_scale(subcr, 1.0, vscale); + pango_cairo_update_layout(subcr, layout); + cairo_move_to(subcr, wtx-logical_layout.width*orient[0], (wty-(logical_layout.height+vspace_total)*vscale*orient[1])/vscale); + pango_cairo_show_layout(subcr, layout); + + // Debug ink and logical lines + if(0) + { + pango_layout_get_pixel_extents(layout, &ink_rect, &logical_rect); + // Render logical and ink rectangles + cairo_save(subcr); + cairo_set_source_rgb(subcr, 0.0, 1.0, 0.0); + cairo_set_line_width(subcr, 1.0); + cairo_rectangle(subcr, wtx+ink_rect.x-0.5-logical_layout.width*orient[0], + wty+ink_rect.y-0.5-(logical_layout.height+vspace_total)*orient[1], + ink_rect.width, + ink_rect.height); + cairo_stroke(subcr); + cairo_restore(subcr); + + cairo_save(subcr); + cairo_set_line_width(subcr, 1.0); + cairo_set_source_rgb(subcr, 0.0, 0.0, 1.0); + cairo_rectangle(subcr, wtx+logical_rect.x-0.5-logical_layout.width*orient[0], + wty+logical_rect.y-0.5-(logical_layout.height+vspace_total)*orient[1], + logical_rect.width, + logical_rect.height); + cairo_stroke(subcr); + cairo_move_to(subcr, wtx+2, wty); + cairo_arc(subcr, wtx, wty, 2.0, 0, 2*3.141516); + cairo_fill(subcr); + cairo_restore(subcr); + } + cairo_restore(subcr); + + // Render the text on the target surface with the proper operator + if(invert) + { + cairo_set_source_surface(invertcr, subimage, 0,0); + cairo_set_operator(invertcr, CAIRO_OPERATOR_DEST_OUT); + cairo_paint_with_alpha(invertcr, get_amount()); + } + cairo_save(cr); + // Need to scale down to user coordinates before pass to cr + cairo_translate(cr, wtlx, wtly); + cairo_scale(cr, wpw, wph); + if(invert) + cairo_set_source_surface(cr, inverted, 0, 0); + else + cairo_set_source_surface(cr, subimage, 0, 0); + if(is_solid_color()) + { + cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); + cairo_paint(cr); + } + else + { + cairo_paint_with_alpha_operator(cr, get_amount(), get_blend_method()); + } + cairo_restore(cr); + + // Destroy and return + cairo_surface_destroy(subimage); + cairo_destroy(subcr); + if(invert) + { + cairo_surface_destroy(inverted); + cairo_destroy(invertcr); + } + pango_attr_list_unref(attrlist); + g_object_unref (layout); + pango_font_description_free (font_description); + return true; +} +//// synfig::Rect diff --git a/synfig-core/src/modules/lyr_freetype/lyr_freetype.h b/synfig-core/src/modules/lyr_freetype/lyr_freetype.h index 3c29cc6..0155da1 100644 --- a/synfig-core/src/modules/lyr_freetype/lyr_freetype.h +++ b/synfig-core/src/modules/lyr_freetype/lyr_freetype.h @@ -148,6 +148,7 @@ public: virtual Color get_color(Context context, const synfig::Point &pos)const; virtual bool accelerated_render(Context context,Surface *surface,int quality, const RendDesc &renddesc, ProgressCallback *cb)const; virtual bool accelerated_cairorender(Context context,cairo_surface_t *surface,int quality, const RendDesc &renddesc, ProgressCallback *cb)const; + virtual bool accelerated_cairorender(Context context,cairo_t *cr, int quality, const RendDesc &renddesc, ProgressCallback *cb)const; virtual Vocab get_param_vocab()const;