Code

No more NRMatrix or NRPoint.
[inkscape.git] / src / extension / internal / cairo-render-context.cpp
index 4ade7fbaebf912521af39e947d35394d787a3b31..a040d5c099c387a9f0bce9ccc2d59abc1f52675c 100644 (file)
@@ -8,7 +8,7 @@
  *   Miklos Erdelyi <erdelyim@gmail.com>
  *
  * Copyright (C) 2006 Miklos Erdelyi
- * 
+ *
  * Licensed under GNU GPL
  */
 
@@ -16,8 +16,6 @@
 # include "config.h"
 #endif
 
-#ifdef HAVE_CAIRO_PDF
-
 #ifndef PANGO_ENABLE_BACKEND
 #define PANGO_ENABLE_BACKEND
 #endif
@@ -33,6 +31,7 @@
 #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>
 
@@ -72,7 +71,7 @@
 #endif
 
 
-#ifndef PANGO_ENABLE_BACKEND
+#ifdef CAIRO_HAS_FT_FONT
 #include <cairo-ft.h>
 #endif
 
@@ -106,6 +105,11 @@ static cairo_status_t _write_callback(void *closure, const unsigned char *data,
 
 CairoRenderContext::CairoRenderContext(CairoRenderer *parent) :
     _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),
@@ -156,20 +160,21 @@ CairoRenderContext::setStateForStyle(SPStyle const *style)
     // 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
  */
@@ -239,7 +244,7 @@ CairoRenderContext::setPdfTarget(gchar const *utf8_fn)
     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
@@ -299,15 +304,138 @@ CairoRenderContext::setPdfTarget(gchar const *utf8_fn)
         (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
+    * 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;
+}
+
+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;
 }
 
@@ -367,6 +495,7 @@ CairoRenderContext::_createState(void)
     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;
@@ -385,7 +514,7 @@ CairoRenderContext::pushLayer(void)
 
     TRACE(("--pushLayer\n"));
     cairo_push_group(_cr);
-                
+
     // clear buffer
     if (!_vector_based_target) {
         cairo_save(_cr);
@@ -408,8 +537,8 @@ CairoRenderContext::popLayer(void)
     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)
@@ -515,7 +644,7 @@ CairoRenderContext::popLayer(void)
                         guint32 *pixel = (guint32 *)row_data + i;
                         *pixel = ((((*pixel & 0x00ff0000) >> 16) * 13817 +
                                 ((*pixel & 0x0000ff00) >>  8) * 46518 +
-                                ((*pixel & 0x000000ff)      ) * 4688) * 
+                                ((*pixel & 0x000000ff)      ) * 4688) *
                                 int_opacity);
                     }
                 }
@@ -566,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;
 
@@ -582,6 +715,12 @@ CairoRenderContext::setupSurface(double width, double height)
 #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:
@@ -589,6 +728,32 @@ CairoRenderContext::setupSurface(double width, double height)
             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;
 
@@ -611,24 +776,24 @@ bool
 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;
     }
@@ -637,23 +802,23 @@ CairoRenderContext::finish(void)
 }
 
 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);
@@ -661,7 +826,7 @@ CairoRenderContext::setTransform(NRMatrix const *transform)
 }
 
 void
-CairoRenderContext::getTransform(NRMatrix *copy) const
+CairoRenderContext::getTransform(NR::Matrix *copy) const
 {
     g_assert( _is_valid );
 
@@ -676,12 +841,12 @@ CairoRenderContext::getTransform(NRMatrix *copy) const
 }
 
 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
@@ -702,9 +867,9 @@ 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;
@@ -726,13 +891,13 @@ cairo_pattern_t*
 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);
@@ -741,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;
@@ -754,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;
@@ -782,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]);
 
@@ -807,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
@@ -834,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"));
@@ -848,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
@@ -862,7 +1023,7 @@ CairoRenderContext::_createPatternPainter(SPPaintServer const *const paintserver
             break; // do not go further up the chain if children are found
         }
     }
-    
+
     return result;
 }
 
@@ -872,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);
@@ -887,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];
@@ -908,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);
 
@@ -924,7 +1085,7 @@ CairoRenderContext::_createPatternForPaintServer(SPPaintServer const *const pain
     } else {
         return NULL;
     }
-        
+
     if (pattern && SP_IS_GRADIENT (paintserver)) {
         SPGradient *g = SP_GRADIENT(paintserver);
 
@@ -969,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);
@@ -1010,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);
@@ -1036,7 +1197,7 @@ CairoRenderContext::_setStrokeStyle(SPStyle const *style, NRRect const *pbox)
     } else {
        cairo_set_dash(_cr, NULL, 0, 0.0);      // disable dashing
     }
-    
+
     cairo_set_line_width(_cr, style->stroke_width.computed);
 
     // set line join type
@@ -1051,9 +1212,9 @@ CairoRenderContext::_setStrokeStyle(SPStyle const *style, NRRect const *pbox)
        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) {
@@ -1066,7 +1227,7 @@ CairoRenderContext::_setStrokeStyle(SPStyle const *style, NRRect const *pbox)
        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));
 }
@@ -1087,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 &&
@@ -1103,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
@@ -1137,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++) {
@@ -1161,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)
@@ -1171,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);
@@ -1205,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;
 }
 
@@ -1240,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);
@@ -1252,24 +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);
 
-#ifndef PANGO_ENABLE_BACKEND
+    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);
@@ -1282,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);
 
@@ -1313,7 +1469,13 @@ CairoRenderContext::renderGlyphtext(PangoFont *font, NRMatrix const *font_matrix
     cairo_restore(_cr);
 
     cairo_font_face_destroy(font_face);
-#endif    
+#else
+    (void)size;
+    (void)fc_pattern;
+
+    cairo_restore(_cr);
+#endif
+
     return true;
 }
 
@@ -1368,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];
@@ -1384,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],
@@ -1416,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: