Code

finally got the pattern transform right
authorbuliabyak <buliabyak@users.sourceforge.net>
Sat, 6 Sep 2008 22:18:00 +0000 (22:18 +0000)
committerbuliabyak <buliabyak@users.sourceforge.net>
Sat, 6 Sep 2008 22:18:00 +0000 (22:18 +0000)
src/extension/internal/cairo-render-context.cpp

index 0c3c469c2bf22b25335b2a2f58859163e2297119..e2e154791a4462ecb7e4cb70c00bd84b87765d4e 100644 (file)
@@ -937,6 +937,7 @@ CairoRenderContext::_createPatternPainter(SPPaintServer const *const paintserver
     // apply pattern transformation
     Geom::Matrix pattern_transform(pattern_patternTransform(pat));
     ps2user *= pattern_transform;
+    Geom::Point ori (ps2user[4], ps2user[5]);
 
     // create pattern contents coordinate system
     if (pat->viewBox_set) {
@@ -960,30 +961,16 @@ CairoRenderContext::_createPatternPainter(SPPaintServer const *const paintserver
     } else if (pbox && pattern_patternContentUnits(pat) == SP_PATTERN_UNITS_OBJECTBOUNDINGBOX) {
         pcs2dev[0] = pbox->x1 - pbox->x0;
         pcs2dev[3] = pbox->y1 - pbox->y0;
-    }
-
-    // Calculate the size of the surface which has to be created so that the pattern resolution
-    // matches the output resolution (i.e., if the pattern is scaled up by a factor of two,
-    // the surface width should be scaled by a factor of two).
-    // The scaling needs to be taken into account in the ctm after the pattern transformation.
-    Geom::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]);
 
-    if (_vector_based_target) {
-        // eliminate PT_PER_PX mul from these
-        width_scaler *= 1.25;
-        height_scaler *= 1.25;
     }
 
+    // Calculate the size of the surface which has to be created 
 #define SUBPIX_SCALE 100
-
     // Cairo requires an integer pattern surface width/height.
     // Subtract 0.5 to prevent small rounding errors from increasing pattern size by one pixel.
     // Multiply by SUBPIX_SCALE to allow for less than a pixel precision
-    double surface_width = MAX(ceil(SUBPIX_SCALE * bbox_width_scaler * width_scaler * width - 0.5), 1);
-    double surface_height = MAX(ceil(SUBPIX_SCALE * bbox_height_scaler * height_scaler * height - 0.5), 1);
+    double surface_width = MAX(ceil(SUBPIX_SCALE * bbox_width_scaler * width - 0.5), 1);
+    double surface_height = MAX(ceil(SUBPIX_SCALE * bbox_height_scaler * height - 0.5), 1);
     TRACE(("surface size: %f x %f\n", surface_width, surface_height));
     // create new rendering context
     CairoRenderContext *pattern_ctx = cloneMe(surface_width, surface_height);
@@ -994,10 +981,14 @@ 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));
-        pcs2dev *= Geom::Scale(scale_width, scale_height);
-        ps2user *= Geom::Scale(1.0 / scale_width, 1.0 / scale_height);
+        pcs2dev *= Geom::Scale(SUBPIX_SCALE,SUBPIX_SCALE);
+        ps2user *= Geom::Scale(1.0/SUBPIX_SCALE,1.0/SUBPIX_SCALE);
     }
 
+    // despite scaling up/down by subpixel scaler, the origin point of the pattern must be the same
+    ps2user[4] = ori[Geom::X];
+    ps2user[5] = ori[Geom::Y];
+
     pattern_ctx->setTransform(&pcs2dev);
     pattern_ctx->pushState();