Skip to content

Commit

Permalink
Layer_FreeType: add support for Cairo render using cairo_t*.
Browse files Browse the repository at this point in the history
  • Loading branch information
genete committed Jun 16, 2013
1 parent f585aad commit 43ce6f9
Show file tree
Hide file tree
Showing 2 changed files with 178 additions and 1 deletion.
178 changes: 177 additions & 1 deletion synfig-core/src/modules/lyr_freetype/lyr_freetype.cpp
Expand Up @@ -41,7 +41,7 @@

#include "lyr_freetype.h"
#endif

#include <synfig/cairo_renddesc.h>
#include <pango/pangocairo.h>

using namespace std;
Expand Down Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions synfig-core/src/modules/lyr_freetype/lyr_freetype.h
Expand Up @@ -148,6 +148,7 @@ class Layer_Freetype : public synfig::Layer_Composite, public synfig::Layer_NoDe
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;

Expand Down

0 comments on commit 43ce6f9

Please sign in to comment.