Bug 1034399 - Use a Moz2D DrawTarget backed gfxContext for SVG bounds calculations. r=Bas
authorJonathan Watt <jwatt@jwatt.org>
Sun, 06 Jul 2014 16:30:55 +0100
changeset 192515 e91a7e542b7b3af1f921724e94ff99db2904cf62
parent 192514 5f27f634ed58d0bfaaf863abee6c3add849f8254
child 192516 6c0325ece5ce3628ee97500bafac8b768836462b
push id27088
push usercbook@mozilla.com
push dateMon, 07 Jul 2014 12:19:04 +0000
treeherdermozilla-central@699348fd356b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersBas
bugs1034399
milestone33.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1034399 - Use a Moz2D DrawTarget backed gfxContext for SVG bounds calculations. r=Bas
content/svg/content/src/SVGEllipseElement.cpp
layout/svg/nsSVGPathGeometryFrame.cpp
--- a/content/svg/content/src/SVGEllipseElement.cpp
+++ b/content/svg/content/src/SVGEllipseElement.cpp
@@ -2,16 +2,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/SVGEllipseElement.h"
 #include "mozilla/dom/SVGEllipseElementBinding.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/gfx/PathHelpers.h"
+#include "mozilla/RefPtr.h"
 #include "gfxContext.h"
 
 NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(Ellipse)
 
 using namespace mozilla::gfx;
 
 namespace mozilla {
 namespace dom {
@@ -91,17 +92,22 @@ SVGEllipseElement::GetLengthInfo()
 
 //----------------------------------------------------------------------
 // nsSVGPathGeometryElement methods
 
 void
 SVGEllipseElement::ConstructPath(gfxContext *aCtx)
 {
   if (!aCtx->IsCairo()) {
-    RefPtr<Path> path = BuildPath();
+    RefPtr<DrawTarget> dt = aCtx->GetDrawTarget();
+    FillRule fillRule =
+      aCtx->CurrentFillRule() == gfxContext::FILL_RULE_WINDING ?
+        FillRule::FILL_WINDING : FillRule::FILL_EVEN_ODD;
+    RefPtr<PathBuilder> builder = dt->CreatePathBuilder(fillRule);
+    RefPtr<Path> path = BuildPath(builder);
     if (path) {
       nsRefPtr<gfxPath> gfxpath = new gfxPath(path);
       aCtx->SetPath(gfxpath);
     }
     return;
   }
 
   float x, y, rx, ry;
--- a/layout/svg/nsSVGPathGeometryFrame.cpp
+++ b/layout/svg/nsSVGPathGeometryFrame.cpp
@@ -6,16 +6,18 @@
 // Main header first:
 #include "nsSVGPathGeometryFrame.h"
 
 // Keep others in (case-insensitive) order:
 #include "gfx2DGlue.h"
 #include "gfxContext.h"
 #include "gfxPlatform.h"
 #include "gfxSVGGlyphs.h"
+#include "mozilla/gfx/2D.h"
+#include "mozilla/RefPtr.h"
 #include "nsDisplayList.h"
 #include "nsGkAtoms.h"
 #include "nsRenderingContext.h"
 #include "nsSVGEffects.h"
 #include "nsSVGIntegrationUtils.h"
 #include "nsSVGMarkerFrame.h"
 #include "nsSVGPathGeometryElement.h"
 #include "nsSVGUtils.h"
@@ -442,18 +444,31 @@ nsSVGPathGeometryFrame::GetBBoxContribut
 {
   SVGBBox bbox;
 
   if (aToBBoxUserspace.IsSingular()) {
     // XXX ReportToConsole
     return bbox;
   }
 
-  nsRefPtr<gfxContext> tmpCtx =
-    new gfxContext(gfxPlatform::GetPlatform()->ScreenReferenceSurface());
+  RefPtr<DrawTarget> tmpDT;
+#ifdef XP_WIN
+  // Unfortunately D2D backed DrawTarget produces bounds with rounding errors
+  // when whole number results are expected, even in the case of trivial
+  // calculations. To avoid that and meet the expectations of web content we
+  // have to use a CAIRO DrawTarget. The most efficient way to do that is to
+  // wrap the cached cairo_surface_t from ScreenReferenceSurface():
+  nsRefPtr<gfxASurface> refSurf =
+    gfxPlatform::GetPlatform()->ScreenReferenceSurface();
+  tmpDT = gfxPlatform::GetPlatform()->
+    CreateDrawTargetForSurface(refSurf, IntSize(1, 1));
+#else
+  tmpDT = gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget();
+#endif
+  nsRefPtr<gfxContext> tmpCtx = new gfxContext(tmpDT);
 
   GeneratePath(tmpCtx, aToBBoxUserspace);
   tmpCtx->IdentityMatrix();
 
   // Be careful when replacing the following logic to get the fill and stroke
   // extents independently (instead of computing the stroke extents from the
   // path extents). You may think that you can just use the stroke extents if
   // there is both a fill and a stroke. In reality it's necessary to calculate