diff --git a/src/extension/internal/cairo-render-context.cpp b/src/extension/internal/cairo-render-context.cpp
index ec0df0cdccf87cbe5301a852d4378385c0f6aa2f..a040d5c099c387a9f0bce9ccc2d59abc1f52675c 100644 (file)
* Miklos Erdelyi <erdelyim@gmail.com>
*
* Copyright (C) 2006 Miklos Erdelyi
- *
+ *
* Licensed under GNU GPL
*/
# include "config.h"
#endif
-#ifdef HAVE_CAIRO_PDF
-
#ifndef PANGO_ENABLE_BACKEND
#define PANGO_ENABLE_BACKEND
#endif
#include <libnr/n-art-bpath.h>
#include <libnr/nr-matrix-ops.h>
#include <libnr/nr-matrix-fns.h>
+#include <libnr/nr-matrix-scale-ops.h>
#include <libnr/nr-matrix-translate-ops.h>
#include <libnr/nr-scale-matrix-ops.h>
#include <cairo-ps.h>
#endif
+
+#ifdef CAIRO_HAS_FT_FONT
#include <cairo-ft.h>
+#endif
#include <pango/pangofc-fontmap.h>
//#define TRACE(_args) g_printf _args
-#define TRACE
+#define TRACE(_args)
//#define TEST(_args) _args
-#define TEST
+#define TEST(_args)
// FIXME: expose these from sp-clippath/mask.cpp
struct SPClipPathView {
static cairo_status_t _write_callback(void *closure, const unsigned char *data, unsigned int length);
CairoRenderContext::CairoRenderContext(CairoRenderer *parent) :
- _renderer(parent),
- _is_valid(FALSE),
- _vector_based_target(FALSE),
- _target(CAIRO_SURFACE_TYPE_IMAGE),
- _target_format(CAIRO_FORMAT_ARGB32),
- _clip_mode(CLIP_MODE_MASK),
- _render_mode(RENDER_MODE_NORMAL),
_dpi(72),
+ _pdf_level(0),
+ _ps_level(1),
+ _is_texttopath(FALSE),
+ _is_filtertobitmap(FALSE),
+ _bitmapresolution(72),
_stream(NULL),
+ _is_valid(FALSE),
+ _vector_based_target(FALSE),
_cr(NULL),
_surface(NULL),
+ _target(CAIRO_SURFACE_TYPE_IMAGE),
+ _target_format(CAIRO_FORMAT_ARGB32),
_layout(NULL),
- _state(NULL)
+ _state(NULL),
+ _renderer(parent),
+ _render_mode(RENDER_MODE_NORMAL),
+ _clip_mode(CLIP_MODE_MASK)
{}
CairoRenderContext::~CairoRenderContext(void)
// only opacity & overflow is stored for now
_state->opacity = SP_SCALE24_TO_FLOAT(style->opacity.value);
_state->has_overflow = (style->overflow.set && style->overflow.value != SP_CSS_OVERFLOW_VISIBLE);
+ _state->has_filtereffect = (style->filter.set != 0) ? TRUE : FALSE;
- if (style->fill.type == SP_PAINT_TYPE_PAINTSERVER || style->stroke.type == SP_PAINT_TYPE_PAINTSERVER)
+ if (style->fill.isPaintserver() || style->stroke.isPaintserver())
_state->merge_opacity = FALSE;
// disable rendering of opacity if there's a stroke on the fill
if (_state->merge_opacity
- && style->fill.type != SP_PAINT_TYPE_NONE
- && style->stroke.type != SP_PAINT_TYPE_NONE)
+ && !style->fill.isNone()
+ && !style->stroke.isNone())
_state->merge_opacity = FALSE;
}
/**
* \brief Creates a new render context which will be compatible with the given context's Cairo surface
- *
+ *
* \param width width of the surface to be created
* \param height height of the surface to be created
*/
gchar *local_fn = g_filename_from_utf8(utf8_fn,
-1, &bytesRead, &bytesWritten, &error);
gchar const *fn = local_fn;
-
+
+ /* TODO: Replace the below fprintf's with something that does the right thing whether in
+ * gui or batch mode (e.g. --print=blah). Consider throwing an exception: currently one of
+ * the callers (sp_print_document_to_file, "ret = mod->begin(doc)") wrongly ignores the
+ * return code.
+ */
+ if (fn != NULL) {
+ if (*fn == '|') {
+ fn += 1;
+ while (isspace(*fn)) fn += 1;
+#ifndef WIN32
+ osp = popen(fn, "w");
+#else
+ osp = _popen(fn, "w");
+#endif
+ if (!osp) {
+ fprintf(stderr, "inkscape: popen(%s): %s\n",
+ fn, strerror(errno));
+ return false;
+ }
+ _stream = osp;
+ } else if (*fn == '>') {
+ fn += 1;
+ while (isspace(*fn)) fn += 1;
+ Inkscape::IO::dump_fopen_call(fn, "K");
+ osf = Inkscape::IO::fopen_utf8name(fn, "w+");
+ if (!osf) {
+ fprintf(stderr, "inkscape: fopen(%s): %s\n",
+ fn, strerror(errno));
+ return false;
+ }
+ _stream = osf;
+ } else {
+ /* put cwd stuff in here */
+ gchar *qn = ( *fn
+ ? g_strdup_printf("lpr -P %s", fn) /* FIXME: quote fn */
+ : g_strdup("lpr") );
+#ifndef WIN32
+ osp = popen(qn, "w");
+#else
+ osp = _popen(qn, "w");
+#endif
+ if (!osp) {
+ fprintf(stderr, "inkscape: popen(%s): %s\n",
+ qn, strerror(errno));
+ return false;
+ }
+ g_free(qn);
+ _stream = osp;
+ }
+ }
+
+ g_free(local_fn);
+
+ if (_stream) {
+ /* fixme: this is kinda icky */
+#if !defined(_WIN32) && !defined(__WIN32__)
+ (void) signal(SIGPIPE, SIG_IGN);
+#endif
+ }
+
+ return true;
+}
+
+bool
+CairoRenderContext::setPsTarget(gchar const *utf8_fn)
+{
+#ifndef CAIRO_HAS_PS_SURFACE
+ return false;
+#else
+ _target = CAIRO_SURFACE_TYPE_PS;
+ _vector_based_target = TRUE;
+#endif
+
+ FILE *osf = NULL;
+ FILE *osp = NULL;
+
+ gsize bytesRead = 0;
+ gsize bytesWritten = 0;
+ GError *error = NULL;
+ gchar *local_fn = g_filename_from_utf8(utf8_fn,
+ -1, &bytesRead, &bytesWritten, &error);
+ gchar const *fn = local_fn;
+
/* TODO: Replace the below fprintf's with something that does the right thing whether in
* gui or batch mode (e.g. --print=blah). Consider throwing an exception: currently one of
* the callers (sp_print_document_to_file, "ret = mod->begin(doc)") wrongly ignores the
(void) signal(SIGPIPE, SIG_IGN);
#endif
}
-
+
return true;
}
+void CairoRenderContext::setPSLevel(unsigned int level)
+{
+ _ps_level = level;
+}
+
+unsigned int CairoRenderContext::getPSLevel(void)
+{
+ return _ps_level;
+}
+
+void CairoRenderContext::setPDFLevel(unsigned int level)
+{
+ _pdf_level = level;
+}
+
+void CairoRenderContext::setTextToPath(bool texttopath)
+{
+ _is_texttopath = texttopath;
+}
+
+void CairoRenderContext::setFilterToBitmap(bool filtertobitmap)
+{
+ _is_filtertobitmap = filtertobitmap;
+}
+
+bool CairoRenderContext::getFilterToBitmap(void)
+{
+ return _is_filtertobitmap;
+}
+
+void CairoRenderContext::setBitmapResolution(int resolution)
+{
+ _bitmapresolution = resolution;
+}
+
+int CairoRenderContext::getBitmapResolution(void)
+{
+ return _bitmapresolution;
+}
+
cairo_surface_t*
CairoRenderContext::getSurface(void)
{
g_assert( _is_valid );
-
+
return _surface;
}
CairoRenderState *state = (CairoRenderState*)g_malloc(sizeof(CairoRenderState));
g_assert( state != NULL );
+ state->has_filtereffect = FALSE;
state->merge_opacity = TRUE;
state->opacity = 1.0;
state->need_layer = FALSE;
TRACE(("--pushLayer\n"));
cairo_push_group(_cr);
-
+
// clear buffer
if (!_vector_based_target) {
cairo_save(_cr);
SPMask *mask = _state->mask;
if (clip_path || mask) {
- CairoRenderContext *clip_ctx;
- cairo_surface_t *clip_mask;
+ CairoRenderContext *clip_ctx = 0;
+ cairo_surface_t *clip_mask = 0;
if (clip_path) {
if (_render_mode == RENDER_MODE_CLIP)
guint32 *pixel = (guint32 *)row_data + i;
*pixel = ((((*pixel & 0x00ff0000) >> 16) * 13817 +
((*pixel & 0x0000ff00) >> 8) * 46518 +
- ((*pixel & 0x000000ff) ) * 4688) *
+ ((*pixel & 0x000000ff) ) * 4688) *
int_opacity);
}
}
@@ -563,6 +695,10 @@ CairoRenderContext::addClippingRect(double x, double y, double width, double hei
bool
CairoRenderContext::setupSurface(double width, double height)
{
+ // Is the surface already set up?
+ if (_is_valid)
+ return true;
+
if (_vector_based_target && _stream == NULL)
return false;
#ifdef CAIRO_HAS_PS_SURFACE
case CAIRO_SURFACE_TYPE_PS:
surface = cairo_ps_surface_create_for_stream(Inkscape::Extension::Internal::_write_callback, _stream, width, height);
+#if (CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 5, 2))
+ if(CAIRO_STATUS_SUCCESS != cairo_surface_status(surface)) {
+ return FALSE;
+ }
+ cairo_ps_surface_restrict_to_level (surface, (cairo_ps_level_t)_ps_level);
+#endif
break;
#endif
default:
break;
}
+ return _finishSurfaceSetup (surface);
+}
+
+bool
+CairoRenderContext::setSurfaceTarget(cairo_surface_t *surface, bool is_vector)
+{
+ if (_is_valid || !surface)
+ return false;
+
+ _vector_based_target = is_vector;
+ bool ret = _finishSurfaceSetup (surface);
+ if (ret)
+ cairo_surface_reference (surface);
+ return ret;
+}
+
+bool
+CairoRenderContext::_finishSurfaceSetup(cairo_surface_t *surface)
+{
+ if(surface == NULL) {
+ return FALSE;
+ }
+ if(CAIRO_STATUS_SUCCESS != cairo_surface_status(surface)) {
+ return FALSE;
+ }
+
_cr = cairo_create(surface);
_surface = surface;
CairoRenderContext::finish(void)
{
g_assert( _is_valid );
-
+
if (_vector_based_target)
cairo_show_page(_cr);
-
+
cairo_destroy(_cr);
cairo_surface_destroy(_surface);
_cr = NULL;
_surface = NULL;
-
+
if (_layout)
g_object_unref(_layout);
-
+
_is_valid = FALSE;
-
- if (_vector_based_target) {
+
+ if (_vector_based_target && _stream) {
/* Flush stream to be sure. */
(void) fflush(_stream);
-
+
fclose(_stream);
_stream = NULL;
}
}
void
-CairoRenderContext::transform(NRMatrix const *transform)
+CairoRenderContext::transform(NR::Matrix const *transform)
{
g_assert( _is_valid );
cairo_matrix_t matrix;
_initCairoMatrix(&matrix, transform);
cairo_transform(_cr, &matrix);
-
+
// store new CTM
getTransform(&_state->transform);
}
void
-CairoRenderContext::setTransform(NRMatrix const *transform)
+CairoRenderContext::setTransform(NR::Matrix const *transform)
{
g_assert( _is_valid );
-
+
cairo_matrix_t matrix;
_initCairoMatrix(&matrix, transform);
cairo_set_matrix(_cr, &matrix);
}
void
-CairoRenderContext::getTransform(NRMatrix *copy) const
+CairoRenderContext::getTransform(NR::Matrix *copy) const
{
g_assert( _is_valid );
}
void
-CairoRenderContext::getParentTransform(NRMatrix *copy) const
+CairoRenderContext::getParentTransform(NR::Matrix *copy) const
{
g_assert( _is_valid );
CairoRenderState *parent_state = getParentState();
- memcpy(copy, &parent_state->transform, sizeof(NRMatrix));
+ memcpy(copy, &parent_state->transform, sizeof(NR::Matrix));
}
void
CairoRenderContext::popState(void)
{
g_assert( _is_valid );
-
+
cairo_restore(_cr);
-
+
g_free(_state_stack->data);
_state_stack = g_slist_remove_link(_state_stack, _state_stack);
_state = (CairoRenderState*)_state_stack->data;
CairoRenderContext::_createPatternPainter(SPPaintServer const *const paintserver, NRRect const *pbox)
{
g_assert( SP_IS_PATTERN(paintserver) );
-
+
SPPattern *pat = SP_PATTERN (paintserver);
-
- NRMatrix ps2user, pcs2dev;
- nr_matrix_set_identity(&ps2user);
- nr_matrix_set_identity(&pcs2dev);
-
+
+ NR::Matrix ps2user, pcs2dev;
+ ps2user.set_identity();
+ pcs2dev.set_identity();
+
double x = pattern_x(pat);
double y = pattern_y(pat);
double width = pattern_width(pat);
@@ -738,7 +906,7 @@ CairoRenderContext::_createPatternPainter(SPPaintServer const *const paintserver
double bbox_height_scaler;
TRACE(("%f x %f pattern\n", width, height));
-
+
if (pbox && pattern_patternUnits(pat) == SP_PATTERN_UNITS_OBJECTBOUNDINGBOX) {
//NR::Matrix bbox2user (pbox->x1 - pbox->x0, 0.0, 0.0, pbox->y1 - pbox->y0, pbox->x0, pbox->y0);
bbox_width_scaler = pbox->x1 - pbox->x0;
@@ -751,15 +919,15 @@ CairoRenderContext::_createPatternPainter(SPPaintServer const *const paintserver
ps2user[4] = x;
ps2user[5] = y;
}
-
+
// apply pattern transformation
- NRMatrix pattern_transform(pattern_patternTransform(pat));
- nr_matrix_multiply(&ps2user, &ps2user, &pattern_transform);
+ NR::Matrix pattern_transform(pattern_patternTransform(pat));
+ ps2user *= pattern_transform;
// create pattern contents coordinate system
if (pat->viewBox_set) {
NRRect *view_box = pattern_viewBox(pat);
-
+
double x, y, w, h;
double view_width, view_height;
x = 0;
@@ -779,11 +947,11 @@ CairoRenderContext::_createPatternPainter(SPPaintServer const *const paintserver
pcs2dev[0] = pbox->x1 - pbox->x0;
pcs2dev[3] = pbox->y1 - pbox->y0;
}
-
+
// calculate the size of the surface which has to be created
// the scaling needs to be taken into account in the ctm after the pattern transformation
- NRMatrix temp;
- nr_matrix_multiply(&temp, &pattern_transform, &_state->transform);
+ NR::Matrix temp;
+ temp = pattern_transform * _state->transform;
double width_scaler = sqrt(temp[0] * temp[0] + temp[2] * temp[2]);
double height_scaler = sqrt(temp[1] * temp[1] + temp[3] * temp[3]);
@@ -804,21 +972,17 @@ CairoRenderContext::_createPatternPainter(SPPaintServer const *const paintserver
double scale_height = surface_height / (bbox_height_scaler * height);
if (scale_width != 1.0 || scale_height != 1.0 || _vector_based_target) {
TRACE(("needed to scale with %f %f\n", scale_width, scale_height));
- NRMatrix scale;
- nr_matrix_set_scale(&scale, 1.0 / scale_width, 1.0 / scale_height);
- nr_matrix_multiply(&pcs2dev, &pcs2dev, &scale);
-
- nr_matrix_set_scale(&scale, scale_width, scale_height);
- nr_matrix_multiply(&ps2user, &ps2user, &scale);
+ pcs2dev *= NR::scale(1.0 / scale_width, 1.0 / scale_height);
+ ps2user *= NR::scale(scale_width, scale_height);
}
pattern_ctx->setTransform(&pcs2dev);
pattern_ctx->pushState();
-
+
// create arena and group
NRArena *arena = NRArena::create();
unsigned dkey = sp_item_display_key_new(1);
-
+
// show items and render them
for (SPPattern *pat_i = pat; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) {
if (pat_i && SP_IS_OBJECT (pat_i) && pattern_hasItemChildren(pat_i)) { // find the first one with item children
@@ -831,9 +995,9 @@ CairoRenderContext::_createPatternPainter(SPPaintServer const *const paintserver
break; // do not go further up the chain if children are found
}
}
-
+
pattern_ctx->popState();
-
+
// setup a cairo_pattern_t
cairo_surface_t *pattern_surface = pattern_ctx->getSurface();
TEST(pattern_ctx->saveAsPng("pattern.png"));
@@ -845,9 +1009,9 @@ CairoRenderContext::_createPatternPainter(SPPaintServer const *const paintserver
_initCairoMatrix(&pattern_matrix, &ps2user);
cairo_matrix_invert(&pattern_matrix);
cairo_pattern_set_matrix(result, &pattern_matrix);
-
+
delete pattern_ctx;
-
+
// hide all items
for (SPPattern *pat_i = pat; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) {
if (pat_i && SP_IS_OBJECT (pat_i) && pattern_hasItemChildren(pat_i)) { // find the first one with item children
@@ -859,7 +1023,7 @@ CairoRenderContext::_createPatternPainter(SPPaintServer const *const paintserver
break; // do not go further up the chain if children are found
}
}
-
+
return result;
}
@@ -869,11 +1033,11 @@ CairoRenderContext::_createPatternForPaintServer(SPPaintServer const *const pain
{
cairo_pattern_t *pattern = NULL;
bool apply_bbox2user = FALSE;
-
+
if (SP_IS_LINEARGRADIENT (paintserver)) {
SPLinearGradient *lg=SP_LINEARGRADIENT(paintserver);
-
+
sp_gradient_ensure_vector(SP_GRADIENT(lg)); // when exporting from commandline, vector is not built
NR::Point p1 (lg->x1.computed, lg->y1.computed);
@@ -884,10 +1048,10 @@ CairoRenderContext::_createPatternForPaintServer(SPPaintServer const *const pain
p1 *= bbox2user;
p2 *= bbox2user;
}
-
+
// create linear gradient pattern
pattern = cairo_pattern_create_linear(p1[NR::X], p1[NR::Y], p2[NR::X], p2[NR::Y]);
-
+
// add stops
for (gint i = 0; unsigned(i) < lg->vector.stops.size(); i++) {
float rgb[3];
@@ -905,7 +1069,7 @@ CairoRenderContext::_createPatternForPaintServer(SPPaintServer const *const pain
double r = rg->r.computed;
if (pbox && SP_GRADIENT(rg)->units == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX)
apply_bbox2user = true;
-
+
// create radial gradient pattern
pattern = cairo_pattern_create_radial(f[NR::X], f[NR::Y], 0, c[NR::X], c[NR::Y], r);
@@ -921,7 +1085,7 @@ CairoRenderContext::_createPatternForPaintServer(SPPaintServer const *const pain
} else {
return NULL;
}
-
+
if (pattern && SP_IS_GRADIENT (paintserver)) {
SPGradient *g = SP_GRADIENT(paintserver);
@@ -966,34 +1130,34 @@ CairoRenderContext::_createPatternForPaintServer(SPPaintServer const *const pain
cairo_matrix_invert(&pattern_matrix); // because Cairo expects a userspace->patternspace matrix
cairo_pattern_set_matrix(pattern, &pattern_matrix);
}
-
+
return pattern;
}
void
CairoRenderContext::_setFillStyle(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() );
+
float alpha = SP_SCALE24_TO_FLOAT(style->fill_opacity.value);
if (_state->merge_opacity) {
alpha *= _state->opacity;
TRACE(("merged op=%f\n", alpha));
}
-
- 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);
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))
|| SP_IS_PATTERN(SP_STYLE_FILL_SERVER(style)) );
-
+
cairo_pattern_t *pattern = _createPatternForPaintServer(SP_STYLE_FILL_SERVER(style), pbox, alpha);
-
+
if (pattern) {
cairo_set_source(_cr, pattern);
cairo_pattern_destroy(pattern);
@@ -1007,19 +1171,19 @@ CairoRenderContext::_setStrokeStyle(SPStyle const *style, NRRect const *pbox)
float alpha = SP_SCALE24_TO_FLOAT(style->stroke_opacity.value);
if (_state->merge_opacity)
alpha *= _state->opacity;
-
- 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 {
- g_assert( style->fill.type == SP_PAINT_TYPE_PAINTSERVER
+ g_assert( style->fill.isPaintserver()
|| SP_IS_GRADIENT(SP_STYLE_STROKE_SERVER(style))
|| SP_IS_PATTERN(SP_STYLE_STROKE_SERVER(style)) );
-
+
cairo_pattern_t *pattern = _createPatternForPaintServer(SP_STYLE_STROKE_SERVER(style), pbox, alpha);
-
+
if (pattern) {
cairo_set_source(_cr, pattern);
cairo_pattern_destroy(pattern);
} else {
cairo_set_dash(_cr, NULL, 0, 0.0); // disable dashing
}
-
+
cairo_set_line_width(_cr, style->stroke_width.computed);
// set line join type
case SP_STROKE_LINEJOIN_BEVEL:
join = CAIRO_LINE_JOIN_BEVEL;
break;
- }
+ }
cairo_set_line_join(_cr, join);
-
+
// set line cap type
cairo_line_cap_t cap = CAIRO_LINE_CAP_BUTT;
switch (style->stroke_linecap.computed) {
case SP_STROKE_LINECAP_SQUARE:
cap = CAIRO_LINE_CAP_SQUARE;
break;
- }
+ }
cairo_set_line_cap(_cr, cap);
cairo_set_miter_limit(_cr, MAX(1, style->stroke_miterlimit.value));
}
@@ -1084,12 +1248,12 @@ CairoRenderContext::renderPath(NRBPath const *bpath, SPStyle const *style, NRRec
cairo_set_fill_rule(_cr, CAIRO_FILL_RULE_WINDING);
}
cairo_fill(_cr);
- cairo_surface_write_to_png (_surface, "gtar2.png");
+ TEST(cairo_surface_write_to_png (_surface, "pathmask.png"));
}
return true;
}
- if (style->fill.type == SP_PAINT_TYPE_NONE && style->stroke.type == SP_PAINT_TYPE_NONE)
+ if (style->fill.isNone() && style->stroke.isNone())
return true;
bool need_layer = ( !_state->merge_opacity && !_state->need_layer &&
@@ -1100,30 +1264,30 @@ CairoRenderContext::renderPath(NRBPath const *bpath, SPStyle const *style, NRRec
else
pushLayer();
- if (style->fill.type != SP_PAINT_TYPE_NONE) {
+ if (!style->fill.isNone()) {
_setFillStyle(style, pbox);
setBpath(bpath->path);
-
+
if (style->fill_rule.value == 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 (style->stroke.type == SP_PAINT_TYPE_NONE)
+
+ if (style->stroke.isNone())
cairo_fill(_cr);
else
cairo_fill_preserve(_cr);
}
-
- if (style->stroke.type != SP_PAINT_TYPE_NONE) {
+
+ if (!style->stroke.isNone()) {
_setStrokeStyle(style, pbox);
- if (style->fill.type == SP_PAINT_TYPE_NONE)
+ if (style->fill.isNone())
setBpath(bpath->path);
- cairo_stroke(_cr);
+ cairo_stroke(_cr);
}
-
+
if (need_layer)
popLayer();
else
@@ -1134,23 +1298,23 @@ CairoRenderContext::renderPath(NRBPath const *bpath, SPStyle const *style, NRRec
bool
CairoRenderContext::renderImage(guchar *px, unsigned int w, unsigned int h, unsigned int rs,
- NRMatrix const *image_transform, SPStyle const *style)
+ NR::Matrix const *image_transform, SPStyle const *style)
{
g_assert( _is_valid );
-
+
if (_render_mode == RENDER_MODE_CLIP)
return true;
-
+
guchar* px_rgba = (guchar*)g_malloc(4 * w * h);
if (!px_rgba)
return false;
-
+
float opacity;
if (_state->merge_opacity)
opacity = _state->opacity;
else
opacity = 1.0;
-
+
// make a copy of the original pixbuf with premultiplied alpha
// if we pass the original pixbuf it will get messed up
for (unsigned i = 0; i < h; i++) {
@@ -1158,7 +1322,7 @@ CairoRenderContext::renderImage(guchar *px, unsigned int w, unsigned int h, unsi
guchar const *src = px + i * rs + j * 4;
guint32 *dst = (guint32 *)(px_rgba + i * rs + j * 4);
guchar r, g, b, alpha_dst;
-
+
// calculate opacity-modified alpha
alpha_dst = src[3];
if (opacity != 1.0 && _vector_based_target)
@@ -1168,23 +1332,23 @@ CairoRenderContext::renderImage(guchar *px, unsigned int w, unsigned int h, unsi
r = src[0]*alpha_dst/255;
g = src[1]*alpha_dst/255;
b = src[2]*alpha_dst/255;
-
+
*dst = (((alpha_dst) << 24) | (((r)) << 16) | (((g)) << 8) | (b));
}
}
-
+
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)) {
TRACE(("Image surface creation failed:\n%s\n", cairo_status_to_string(cairo_surface_status(image_surface))));
return false;
}
-
+
// setup automatic freeing of the image data when destroying the surface
static cairo_user_data_key_t key;
cairo_surface_set_user_data(image_surface, &key, px_rgba, (cairo_destroy_func_t)g_free);
cairo_save(_cr);
-
+
// scaling by width & height is not needed because it will be done by Cairo
if (image_transform)
transform(image_transform);
@@ -1202,11 +1366,11 @@ CairoRenderContext::renderImage(guchar *px, unsigned int w, unsigned int h, unsi
cairo_paint(_cr);
else
cairo_paint_with_alpha(_cr, opacity);
-
+
cairo_restore(_cr);
cairo_surface_destroy(image_surface);
-
+
return true;
}
@@ -1224,8 +1388,9 @@ CairoRenderContext::_showGlyphs(cairo_t *cr, PangoFont *font, std::vector<CairoG
unsigned int num_invalid_glyphs = 0;
unsigned int i = 0;
for (std::vector<CairoGlyphInfo>::const_iterator it_info = glyphtext.begin() ; it_info != glyphtext.end() ; it_info++) {
- // skip empty or unknown glyphs
- if (it_info->index == PANGO_GLYPH_EMPTY || it_info->index & PANGO_GLYPH_UNKNOWN_FLAG) {
+ // skip glyphs which are PANGO_GLYPH_EMPTY (0x0FFFFFFF)
+ // or have the PANGO_GLYPH_UNKNOWN_FLAG (0x10000000) set
+ if (it_info->index == 0x0FFFFFFF || it_info->index & 0x10000000) {
TRACE(("INVALID GLYPH found\n"));
num_invalid_glyphs++;
continue;
@@ -1236,7 +1401,7 @@ CairoRenderContext::_showGlyphs(cairo_t *cr, PangoFont *font, std::vector<CairoG
i++;
}
- if (is_stroke)
+ if (is_stroke || _is_texttopath)
cairo_glyph_path(cr, glyphs, num_glyphs - num_invalid_glyphs);
else
cairo_show_glyphs(cr, glyphs, num_glyphs - num_invalid_glyphs);
@@ -1248,22 +1413,23 @@ CairoRenderContext::_showGlyphs(cairo_t *cr, PangoFont *font, std::vector<CairoG
}
bool
-CairoRenderContext::renderGlyphtext(PangoFont *font, NRMatrix const *font_matrix,
+CairoRenderContext::renderGlyphtext(PangoFont *font, NR::Matrix const *font_matrix,
std::vector<CairoGlyphInfo> const &glyphtext, SPStyle const *style)
{
// create a cairo_font_face from PangoFont
double size = style->font_size.computed;
PangoFcFont *fc_font = PANGO_FC_FONT(font);
FcPattern *fc_pattern = fc_font->font_pattern;
-
+
cairo_save(_cr);
+#ifdef CAIRO_HAS_FT_FONT
cairo_font_face_t *font_face = cairo_ft_font_face_create_for_pattern(fc_pattern);
cairo_set_font_face(_cr, font_face);
-
+
if (FcPatternGetDouble(fc_pattern, FC_PIXEL_SIZE, 0, &size) != FcResultMatch)
size = 12.0;
-
+
// set the given font matrix
cairo_matrix_t matrix;
_initCairoMatrix(&matrix, font_matrix);
@@ -1276,25 +1442,21 @@ CairoRenderContext::renderGlyphtext(PangoFont *font, NRMatrix const *font_matrix
} else {
cairo_set_fill_rule(_cr, CAIRO_FILL_RULE_WINDING);
}
- cairo_set_source_rgba (_cr, 1.0, 1.0, 1.0, 1.0);
- cairo_rectangle (_cr, 0, 0, 30, 40);
- cairo_fill (_cr);
_showGlyphs(_cr, font, glyphtext, FALSE);
- //cairo_fill(_cr);
} else {
// just add the glyph paths to the current context
_showGlyphs(_cr, font, glyphtext, TRUE);
}
} else {
- if (style->fill.type == SP_PAINT_TYPE_COLOR || style->fill.type == SP_PAINT_TYPE_PAINTSERVER) {
+ if (style->fill.isColor() || style->fill.isPaintserver()) {
// set fill style
_setFillStyle(style, NULL);
_showGlyphs(_cr, font, glyphtext, FALSE);
}
- if (style->stroke.type == SP_PAINT_TYPE_COLOR || style->stroke.type == SP_PAINT_TYPE_PAINTSERVER) {
+ if (style->stroke.isColor() || style->stroke.isPaintserver()) {
// set stroke style
_setStrokeStyle(style, NULL);
@@ -1307,7 +1469,13 @@ CairoRenderContext::renderGlyphtext(PangoFont *font, NRMatrix const *font_matrix
cairo_restore(_cr);
cairo_font_face_destroy(font_face);
-
+#else
+ (void)size;
+ (void)fc_pattern;
+
+ cairo_restore(_cr);
+#endif
+
return true;
}
@@ -1362,12 +1530,12 @@ CairoRenderContext::_concatTransform(cairo_t *cr, double xx, double yx, double x
{
cairo_matrix_t matrix;
- cairo_matrix_init(&matrix, xx, yx, xy, yy, x0, y0);
+ cairo_matrix_init(&matrix, xx, yx, xy, yy, x0, y0);
cairo_transform(cr, &matrix);
}
void
-CairoRenderContext::_initCairoMatrix(cairo_matrix_t *matrix, NRMatrix const *transform)
+CairoRenderContext::_initCairoMatrix(cairo_matrix_t *matrix, NR::Matrix const *transform)
{
matrix->xx = (*transform)[0];
matrix->yx = (*transform)[1];
@@ -1378,7 +1546,7 @@ CairoRenderContext::_initCairoMatrix(cairo_matrix_t *matrix, NRMatrix const *tra
}
void
-CairoRenderContext::_concatTransform(cairo_t *cr, NRMatrix const *transform)
+CairoRenderContext::_concatTransform(cairo_t *cr, NR::Matrix const *transform)
{
_concatTransform(cr, (*transform)[0], (*transform)[1],
(*transform)[2], (*transform)[3],
@@ -1410,8 +1578,6 @@ _write_callback(void *closure, const unsigned char *data, unsigned int length)
/* End of GNU GPL code */
-#endif /* HAVE_CAIRO_PDF */
-
/*
Local Variables: