index c99e0bec88d3dbedd9742583a4c617c4c0b4a5c3..4baab1740c0f7f253d036af9a610d256082943c0 100644 (file)
# include "config.h"
#endif
+#ifdef HAVE_CAIRO_PDF
+
#ifndef PANGO_ENABLE_BACKEND
#define PANGO_ENABLE_BACKEND
#endif
#include <cairo.h>
#include <cairo-pdf.h>
-#include <cairo-ft.h>
+#include <pango/pango.h>
#include <pango/pangofc-fontmap.h>
-#ifdef HAVE_PANGO_CAIRO
+#ifdef RENDER_WITH_PANGO_CAIRO
#include <pango/pangocairo.h>
+#else
+#include <cairo-ft.h>
#endif
-
namespace Inkscape {
namespace Extension {
namespace Internal {
_dpi(72),
_bitmap(false)
{
- _num_alphas = 8;
- _alpha_stack = (float*)malloc(sizeof(float) * _num_alphas);
}
PrintCairoPDF::~PrintCairoPDF(void)
if (pdf_surface) cairo_surface_destroy(pdf_surface);
if (_layout) g_object_unref(_layout);
- free(_alpha_stack);
-
/* restore default signal handling for SIGPIPE */
#if !defined(_WIN32) && !defined(__WIN32__)
(void) signal(SIGPIPE, SIG_DFL);
FILE *osf = NULL;
FILE *osp = NULL;
- _alpha_ptr = 0;
- _alpha_stack[_alpha_ptr] = 1.0;
+ _alpha_stack.clear();
+ _alpha_stack.push_back(1.0);
gsize bytesRead = 0;
gsize bytesWritten = 0;
// printf("Page Bounding Box: %s\n", pageBoundingBox ? "TRUE" : "FALSE");
if (pageBoundingBox) {
d.x0 = d.y0 = 0;
- d.x1 = ceil(_width);
- d.y1 = ceil(_height);
+ d.x1 = _width;
+ d.y1 = _height;
} else {
SPItem* doc_item = SP_ITEM(sp_document_root(doc));
sp_item_invoke_bbox(doc_item, &d, sp_item_i2r_affine(doc_item), TRUE);
fclose(_stream);
_stream = 0;
- return 0;
+ return 1;
}
unsigned int
@@ -383,18 +382,18 @@ PrintCairoPDF::bind(Inkscape::Extension::Print *mod, NRMatrix const *transform,
if (!_stream) return 0; // XXX: fixme, returning -1 as unsigned.
if (_bitmap) return 0;
- cairo_save(cr);
+ if (opacity < 1.0) {
+ cairo_push_group(cr);
+ } else {
+ cairo_save(cr);
+ }
_concat_transform(cr, transform->c[0], transform->c[1], transform->c[2], transform->c[3], transform->c[4], transform->c[5]);
// g_printf("bind: (%f) %f %f %f %f %f %f\n", opacity, transform->c[0], transform->c[1], transform->c[2], transform->c[3], transform->c[4], transform->c[5]);
// remember these to be able to undo them when outputting text
_last_tx = transform->c[4];
_last_ty = transform->c[5];
- if (_num_alphas <= ++_alpha_ptr) {
- _num_alphas *= 2;
- _alpha_stack = (float*)realloc((void*)_alpha_stack, sizeof(float) * _num_alphas);
- }
- _alpha_stack[_alpha_ptr] = _alpha_stack[_alpha_ptr-1] * opacity;
+ _alpha_stack.push_back(opacity);
return 1;
}
{
if (!_stream) return 0; // XXX: fixme, returning -1 as unsigned.
if (_bitmap) return 0;
+
+ float opacity = _alpha_stack.back();
- cairo_restore(cr);
+ if (opacity < 1.0) {
+ cairo_pop_group_to_source(cr);
+ cairo_paint_with_alpha(cr, opacity);
+ } else {
+ cairo_restore(cr);
+ }
// g_printf("release\n");
- if (_alpha_ptr > 0)
- _alpha_ptr--;
+ _alpha_stack.pop_back();
+ g_assert(_alpha_stack.size() > 0);
return 1;
}
cairo_pattern_t*
PrintCairoPDF::create_pattern_for_paint(SPPaintServer const *const paintserver, NRRect const *pbox, float alpha)
{
- cairo_pattern_t *pattern = NULL;
+ cairo_pattern_t *pattern = NULL;
bool apply_bbox2user = false;
if (SP_IS_LINEARGRADIENT (paintserver)) {
@@ -461,6 +467,13 @@ PrintCairoPDF::create_pattern_for_paint(SPPaintServer const *const paintserver,
NR::Point c (rg->cx.computed, rg->cy.computed);
NR::Point f (rg->fx.computed, rg->fy.computed);
double r = rg->r.computed;
+
+ NR::Coord const df = hypot(f[NR::X] - c[NR::X], f[NR::Y] - c[NR::Y]);
+ if (df >= r) {
+ f[NR::X] = c[NR::X] + (f[NR::X] - c[NR::X] ) * r / (float) df;
+ f[NR::Y] = c[NR::Y] + (f[NR::Y] - c[NR::Y] ) * r / (float) df;
+ }
+
if (pbox && SP_GRADIENT(rg)->units == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX)
apply_bbox2user = true;
@@ -484,12 +497,12 @@ PrintCairoPDF::create_pattern_for_paint(SPPaintServer const *const paintserver,
case SP_GRADIENT_SPREAD_REPEAT:
cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
break;
- case SP_GRADIENT_SPREAD_REFLECT: // not supported by cairo-pdf yet
- //cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REFLECT);
- //break;
+ case SP_GRADIENT_SPREAD_REFLECT:
+ cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REFLECT);
+ break;
case SP_GRADIENT_SPREAD_PAD:
default:
- cairo_pattern_set_extend(pattern, CAIRO_EXTEND_NONE); // PAD not supported by cairo-pdf yet
+ cairo_pattern_set_extend(pattern, CAIRO_EXTEND_PAD);
break;
}
@@ -520,21 +533,19 @@ PrintCairoPDF::create_pattern_for_paint(SPPaintServer const *const paintserver,
void
PrintCairoPDF::print_fill_style(cairo_t *cr, SPStyle const *const style, NRRect const *pbox)
{
- g_return_if_fail( style->fill.type == SP_PAINT_TYPE_COLOR
- || ( style->fill.type == SP_PAINT_TYPE_PAINTSERVER
+ g_return_if_fail( style->fill.isColor()
+ || ( style->fill.isPaintserver()
&& SP_IS_GRADIENT(SP_STYLE_FILL_SERVER(style)) ) );
- if (style->fill.type == SP_PAINT_TYPE_COLOR) {
+ if (style->fill.isColor()) {
float rgb[3];
sp_color_get_rgb_floatv(&style->fill.value.color, rgb);
- float alpha = 1.0;
- alpha *= SP_SCALE24_TO_FLOAT(style->fill_opacity.value);
- alpha *= _alpha_stack[_alpha_ptr];
+ float alpha = SP_SCALE24_TO_FLOAT(style->fill_opacity.value);
cairo_set_source_rgba(cr, rgb[0], rgb[1], rgb[2], alpha);
} else {
- g_assert( style->fill.type == SP_PAINT_TYPE_PAINTSERVER
+ g_assert( style->fill.isPaintserver()
&& SP_IS_GRADIENT(SP_STYLE_FILL_SERVER(style)) );
cairo_pattern_t *pattern = create_pattern_for_paint(SP_STYLE_FILL_SERVER(style), pbox, 1.0);
@@ -553,27 +564,23 @@ PrintCairoPDF::fill(Inkscape::Extension::Print *mod, NRBPath const *bpath, NRMat
if (!_stream) return 0; // XXX: fixme, returning -1 as unsigned.
if (_bitmap) return 0;
- if ( style->fill.type == SP_PAINT_TYPE_COLOR
- || ( style->fill.type == SP_PAINT_TYPE_PAINTSERVER
- && SP_IS_GRADIENT(SP_STYLE_FILL_SERVER(style)) ) ) {
-
- float alpha = 1.0;
- alpha *= SP_SCALE24_TO_FLOAT(style->fill_opacity.value);
-if (alpha != 1.0)
-g_printf( "fa: %f a:%f fa*a = %f\n", alpha, _alpha_stack[_alpha_ptr], alpha*_alpha_stack[_alpha_ptr]);
- alpha *= _alpha_stack[_alpha_ptr];
-
+ if ( style->fill.isColor()
+ || ( style->fill.isPaintserver()
+ && SP_IS_GRADIENT(SP_STYLE_FILL_SERVER(style)) ) ) {
+
+ float alpha = SP_SCALE24_TO_FLOAT(style->fill_opacity.value);
+
cairo_save(cr);
-
+
print_fill_style(cr, style, pbox);
print_bpath(cr, bpath->path);
- if (style->fill_rule.value == SP_WIND_RULE_EVENODD) {
+ if (style->fill_rule.computed == SP_WIND_RULE_EVENODD) {
cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD);
} else {
cairo_set_fill_rule(cr, CAIRO_FILL_RULE_WINDING);
}
if (alpha != 1.0 &&
- style->fill.type != SP_PAINT_TYPE_COLOR) {
+ !style->fill.isColor()) {
cairo_clip (cr);
cairo_paint_with_alpha (cr, alpha);
@@ -590,16 +597,14 @@ g_printf( "fa: %f a:%f fa*a = %f\n", alpha, _alpha_stack[_alpha_ptr], alpha*_alp
void
PrintCairoPDF::print_stroke_style(cairo_t *cr, SPStyle const *style, NRRect const *pbox)
{
- float alpha = 1.0;
- alpha *= SP_SCALE24_TO_FLOAT(style->stroke_opacity.value);
- alpha *= _alpha_stack[_alpha_ptr];
+ float alpha = SP_SCALE24_TO_FLOAT(style->stroke_opacity.value);
- if ( style->stroke.type == SP_PAINT_TYPE_COLOR ) {
+ if ( style->stroke.isColor() ) {
float rgb[3];
sp_color_get_rgb_floatv(&style->stroke.value.color, rgb);
cairo_set_source_rgba(cr, rgb[0], rgb[1], rgb[2], alpha);
- } else if ( style->stroke.type == SP_PAINT_TYPE_PAINTSERVER
+ } else if ( style->stroke.isPaintserver()
&& SP_IS_GRADIENT(SP_STYLE_STROKE_SERVER(style)) ) {
cairo_pattern_t *pattern = create_pattern_for_paint(SP_STYLE_STROKE_SERVER(style), pbox, alpha);
@@ -659,16 +664,16 @@ PrintCairoPDF::stroke(Inkscape::Extension::Print *mod, NRBPath const *bpath, NRM
if (!_stream) return 0; // XXX: fixme, returning -1 as unsigned.
if (_bitmap) return 0;
- if ( style->stroke.type == SP_PAINT_TYPE_COLOR ||
- ( style->stroke.type == SP_PAINT_TYPE_PAINTSERVER
+ if ( style->stroke.isColor() ||
+ ( style->stroke.isPaintserver()
&& SP_IS_GRADIENT(SP_STYLE_STROKE_SERVER(style)) ) ) {
- cairo_save(cr);
-
- print_stroke_style(cr, style, pbox);
+ cairo_save(cr);
+
+ print_stroke_style(cr, style, pbox);
print_bpath(cr, bpath->path);
cairo_stroke(cr);
-
+
cairo_restore(cr);
}
@@ -685,7 +690,7 @@ PrintCairoPDF::image(Inkscape::Extension::Print *mod, guchar *px, unsigned int w
guchar* px_rgba = (guchar*)g_malloc(4 * w * h);
if (!px_rgba) return 0;
- float alpha = _alpha_stack[_alpha_ptr];
+ float alpha = _alpha_stack.back();
// make a copy of the original pixbuf with premultiplied alpha
// if we pass the original pixbuf it will get messed up
@@ -711,7 +716,7 @@ PrintCairoPDF::image(Inkscape::Extension::Print *mod, guchar *px, unsigned int w
cairo_surface_t *image_surface = cairo_image_surface_create_for_data(px_rgba, CAIRO_FORMAT_ARGB32, w, h, w * 4);
if (cairo_surface_status(image_surface)) {
- g_printf("%s\n", cairo_status_to_string(cairo_surface_status(image_surface)));
+ g_printf("Error: %s\n", cairo_status_to_string(cairo_surface_status(image_surface)));
return 0;
}
@@ -749,7 +754,7 @@ PrintCairoPDF::image(Inkscape::Extension::Print *mod, guchar *px, unsigned int w
#define GLYPH_ARRAY_SIZE 64
-#ifndef HAVE_PANGO_CAIRO
+#ifndef RENDER_WITH_PANGO_CAIRO
NR::Point
PrintCairoPDF::draw_glyphs(cairo_t *cr, NR::Point p, PangoFont *font, PangoGlyphString *glyph_string,
@@ -765,11 +770,13 @@ PrintCairoPDF::draw_glyphs(cairo_t *cr, NR::Point p, PangoFont *font, PangoGlyph
int num_invalid_glyphs = 0;
for (gint i = 0; i < glyph_string->num_glyphs; i++) {
info = &glyph_string->glyphs[i];
- // skip empty or unknown glyphs
- if (info->glyph == PANGO_GLYPH_EMPTY || info->glyph & PANGO_GLYPH_UNKNOWN_FLAG) {
+ // skip glyphs which are PANGO_GLYPH_EMPTY (0x0FFFFFFF) or have
+ // the PANGO_GLYPH_UNKNOWN_FLAG (0x10000000) set
+ if (info->glyph == 0x0FFFFFFF || info->glyph & 0x10000000) {
num_invalid_glyphs++;
continue;
}
+
glyphs[i - num_invalid_glyphs].index = info->glyph;
glyphs[i - num_invalid_glyphs].x = p[NR::X] + (x_offset + info->geometry.x_offset)/PANGO_SCALE;
glyphs[i - num_invalid_glyphs].y = p[NR::Y] + (y_offset + info->geometry.y_offset)/PANGO_SCALE;
@@ -814,7 +821,7 @@ PrintCairoPDF::text(Inkscape::Extension::Print *mod, char const *text, NR::Point
// create pango layout and context if needed
if (_layout == NULL) {
-#ifdef HAVE_PANGO_CAIRO
+#ifdef RENDER_WITH_PANGO_CAIRO
//_context = pango_cairo_font_map_create_context(PANGO_CAIRO_FONT_MAP(pango_cairo_font_map_get_default()));
_layout = pango_cairo_create_layout(cr);
#else
@@ -837,7 +844,7 @@ PrintCairoPDF::text(Inkscape::Extension::Print *mod, char const *text, NR::Point
pango_font_description_free(adjusted);
tf->Unref();
-#ifdef HAVE_PANGO_CAIRO
+#ifdef RENDER_WITH_PANGO_CAIRO
pango_cairo_update_layout(cr, _layout);
#else
pango_layout_context_changed(_layout); // is this needed?
@@ -847,7 +854,7 @@ PrintCairoPDF::text(Inkscape::Extension::Print *mod, char const *text, NR::Point
if (line == NULL)
return 0;
-#ifndef HAVE_PANGO_CAIRO
+#ifndef RENDER_WITH_PANGO_CAIRO
// apply the selected font
double size;
PangoLayoutRun *first_run = (PangoLayoutRun *)line->runs->data;
@@ -877,14 +884,14 @@ PrintCairoPDF::text(Inkscape::Extension::Print *mod, char const *text, NR::Point
cairo_set_font_matrix(cr, &matrix);
#endif
- if ( style->fill.type == SP_PAINT_TYPE_COLOR
- || ( style->fill.type == SP_PAINT_TYPE_PAINTSERVER
+ if ( style->fill.isColor()
+ || ( style->fill.isPaintserver()
&& SP_IS_GRADIENT(SP_STYLE_FILL_SERVER(style)) ) )
{
// set fill style
print_fill_style(cr, style, NULL);
-#ifndef HAVE_PANGO_CAIRO
+#ifndef RENDER_WITH_PANGO_CAIRO
NR::Point cursor(_last_tx, _last_ty);
for (GSList *tmpList = line->runs; tmpList && tmpList->data; tmpList = tmpList->next) {
PangoLayoutRun *run = (PangoLayoutRun *)tmpList->data;
@@ -897,15 +904,15 @@ PrintCairoPDF::text(Inkscape::Extension::Print *mod, char const *text, NR::Point
#endif
}
- if (style->stroke.type == SP_PAINT_TYPE_COLOR
- || ( style->stroke.type == SP_PAINT_TYPE_PAINTSERVER
+ if (style->stroke.isColor()
+ || ( style->stroke.isPaintserver()
&& SP_IS_GRADIENT(SP_STYLE_STROKE_SERVER(style)) ) )
{
// set stroke style
print_stroke_style(cr, style, NULL);
// paint stroke
-#ifndef HAVE_PANGO_CAIRO
+#ifndef RENDER_WITH_PANGO_CAIRO
NR::Point cursor(_last_tx, _last_ty);
for (GSList *tmpList = line->runs; tmpList && tmpList->data; tmpList = tmpList->next) {
PangoLayoutRun *run = (PangoLayoutRun *)tmpList->data;
@@ -922,7 +929,7 @@ PrintCairoPDF::text(Inkscape::Extension::Print *mod, char const *text, NR::Point
cairo_restore(cr);
-#ifndef HAVE_PANGO_CAIRO
+#ifndef RENDER_WITH_PANGO_CAIRO
cairo_font_face_destroy(font_face);
if (dirty_pattern) {
/* End of GNU GPL code */
+#endif /* HAVE_CAIRO_PDF */
+
/*
Local Variables: