Bug 1083101 - Part 3: Extend DrawCommand storage functionality and fix a bug with dashed stroke patterns. r=jrmuizel
☠☠ backed out by fd0134809e69 ☠ ☠
authorNicolas Silva <nsilva@mozilla.com>
Wed, 10 Jun 2015 19:57:08 +0200
changeset 260315 86f55d9695f0839a92022ee1eab8fcf792e3e2d3
parent 260314 6b8940305079f31decace15e770f8d56b823dd63
child 260316 78f3c70cf1cb85f8a68aabfdea5161d65616e9a2
push id29307
push userryanvm@gmail.com
push dateWed, 02 Sep 2015 01:01:53 +0000
treeherdermozilla-central@e2eb0442ece9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel
bugs1083101
milestone43.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 1083101 - Part 3: Extend DrawCommand storage functionality and fix a bug with dashed stroke patterns. r=jrmuizel
gfx/2d/DrawCommand.h
--- a/gfx/2d/DrawCommand.h
+++ b/gfx/2d/DrawCommand.h
@@ -1,16 +1,20 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * 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/. */
 
 #ifndef MOZILLA_GFX_DRAWCOMMAND_H_
 #define MOZILLA_GFX_DRAWCOMMAND_H_
 
+
+#define _USE_MATH_DEFINES
+#include <math.h>
+
 #include "2D.h"
 #include "Filters.h"
 #include <vector>
 
 namespace mozilla {
 namespace gfx {
 
 enum class CommandType : int8_t {
@@ -26,26 +30,29 @@ enum class CommandType : int8_t {
   STROKE,
   FILL,
   FILLGLYPHS,
   MASK,
   MASKSURFACE,
   PUSHCLIP,
   PUSHCLIPRECT,
   POPCLIP,
-  SETTRANSFORM
+  SETTRANSFORM,
+  FLUSH
 };
 
 class DrawingCommand
 {
 public:
   virtual ~DrawingCommand() {}
 
   virtual void ExecuteOnDT(DrawTarget* aDT, const Matrix* aTransform = nullptr) = 0;
 
+  virtual bool GetAffectedRect(Rect& aDeviceRect, const Matrix& aTransform) { return false; }
+
 protected:
   explicit DrawingCommand(CommandType aType)
     : mType(aType)
   {
   }
 
   CommandType GetType() { return mType; }
 
@@ -226,16 +233,22 @@ public:
   {
   }
 
   virtual void ExecuteOnDT(DrawTarget* aDT, const Matrix*)
   {
     aDT->FillRect(mRect, mPattern, mOptions);
   }
 
+  bool GetAffectedRect(Rect& aDeviceRect, const Matrix& aTransform)
+  {
+    aDeviceRect = aTransform.TransformBounds(mRect);
+    return true;
+  }
+
 private:
   Rect mRect;
   StoredPattern mPattern;
   DrawOptions mOptions;
 };
 
 class StrokeRectCommand : public DrawingCommand
 {
@@ -245,28 +258,34 @@ public:
                     const StrokeOptions& aStrokeOptions,
                     const DrawOptions& aOptions)
     : DrawingCommand(CommandType::STROKERECT)
     , mRect(aRect)
     , mPattern(aPattern)
     , mStrokeOptions(aStrokeOptions)
     , mOptions(aOptions)
   {
+    if (aStrokeOptions.mDashLength) {
+      mDashes.resize(aStrokeOptions.mDashLength);
+      mStrokeOptions.mDashPattern = &mDashes.front();
+      memcpy(&mDashes.front(), aStrokeOptions.mDashPattern, mStrokeOptions.mDashLength * sizeof(Float));
+    }
   }
 
   virtual void ExecuteOnDT(DrawTarget* aDT, const Matrix*)
   {
     aDT->StrokeRect(mRect, mPattern, mStrokeOptions, mOptions);
   }
 
 private:
   Rect mRect;
   StoredPattern mPattern;
   StrokeOptions mStrokeOptions;
   DrawOptions mOptions;
+  std::vector<Float> mDashes;
 };
 
 class StrokeLineCommand : public DrawingCommand
 {
 public:
   StrokeLineCommand(const Point& aStart,
                     const Point& aEnd,
                     const Pattern& aPattern,
@@ -307,47 +326,100 @@ public:
   {
   }
 
   virtual void ExecuteOnDT(DrawTarget* aDT, const Matrix*)
   {
     aDT->Fill(mPath, mPattern, mOptions);
   }
 
+  bool GetAffectedRect(Rect& aDeviceRect, const Matrix& aTransform)
+  {
+    aDeviceRect = mPath->GetBounds(aTransform);
+    return true;
+  }
+
 private:
   RefPtr<Path> mPath;
   StoredPattern mPattern;
   DrawOptions mOptions;
 };
 
+#ifndef M_SQRT2
+#define M_SQRT2 1.41421356237309504880
+#endif
+
+#ifndef M_SQRT1_2
+#define M_SQRT1_2 0.707106781186547524400844362104849039
+#endif
+
+// The logic for this comes from _cairo_stroke_style_max_distance_from_path
+static Rect
+PathExtentsToMaxStrokeExtents(const StrokeOptions &aStrokeOptions,
+                              const Rect &aRect,
+                              const Matrix &aTransform)
+{
+  double styleExpansionFactor = 0.5f;
+
+  if (aStrokeOptions.mLineCap == CapStyle::SQUARE) {
+    styleExpansionFactor = M_SQRT1_2;
+  }
+
+  if (aStrokeOptions.mLineJoin == JoinStyle::MITER &&
+      styleExpansionFactor < M_SQRT2 * aStrokeOptions.mMiterLimit) {
+    styleExpansionFactor = M_SQRT2 * aStrokeOptions.mMiterLimit;
+  }
+
+  styleExpansionFactor *= aStrokeOptions.mLineWidth;
+
+  double dx = styleExpansionFactor * hypot(aTransform._11, aTransform._21);
+  double dy = styleExpansionFactor * hypot(aTransform._22, aTransform._12);
+
+  Rect result = aRect;
+  result.Inflate(dx, dy);
+  return result;
+}
+
 class StrokeCommand : public DrawingCommand
 {
 public:
   StrokeCommand(const Path* aPath,
                 const Pattern& aPattern,
                 const StrokeOptions& aStrokeOptions,
                 const DrawOptions& aOptions)
     : DrawingCommand(CommandType::STROKE)
     , mPath(const_cast<Path*>(aPath))
     , mPattern(aPattern)
     , mStrokeOptions(aStrokeOptions)
     , mOptions(aOptions)
   {
+    if (aStrokeOptions.mDashLength) {
+      mDashes.resize(aStrokeOptions.mDashLength);
+      mStrokeOptions.mDashPattern = &mDashes.front();
+      memcpy(&mDashes.front(), aStrokeOptions.mDashPattern, mStrokeOptions.mDashLength * sizeof(Float));
+    }
   }
 
   virtual void ExecuteOnDT(DrawTarget* aDT, const Matrix*)
   {
     aDT->Stroke(mPath, mPattern, mStrokeOptions, mOptions);
   }
 
+  bool GetAffectedRect(Rect& aDeviceRect, const Matrix& aTransform)
+  {
+    aDeviceRect = PathExtentsToMaxStrokeExtents(mStrokeOptions, mPath->GetBounds(aTransform), aTransform);
+    return true;
+  }
+
 private:
   RefPtr<Path> mPath;
   StoredPattern mPattern;
   StrokeOptions mStrokeOptions;
   DrawOptions mOptions;
+  std::vector<Float> mDashes;
 };
 
 class FillGlyphsCommand : public DrawingCommand
 {
 public:
   FillGlyphsCommand(ScaledFont* aFont,
                     const GlyphBuffer& aBuffer,
                     const Pattern& aPattern,
@@ -497,14 +569,28 @@ public:
       aDT->SetTransform(mTransform);
     }
   }
 
 private:
   Matrix mTransform;
 };
 
+class FlushCommand : public DrawingCommand
+{
+public:
+  explicit FlushCommand()
+    : DrawingCommand(CommandType::FLUSH)
+  {
+  }
+
+  virtual void ExecuteOnDT(DrawTarget* aDT, const Matrix*)
+  {
+    aDT->Flush();
+  }
+};
+
 } // namespace gfx
 
 } // namespace mozilla
 
 
 #endif /* MOZILLA_GFX_DRAWCOMMAND_H_ */