Bug 1342571 - shrink dashed DrawTargetSkia::StrokeRect where possible. r=mstange

MozReview-Commit-ID: 7vu9j8jCwQn
This commit is contained in:
Lee Salzman 2017-02-28 15:47:46 -05:00
Родитель c834f9ba25
Коммит 4dfd1b6ac1
2 изменённых файлов: 88 добавлений и 1 удалений

Просмотреть файл

@ -24,6 +24,7 @@
#include "Logging.h"
#include "Tools.h"
#include "DataSurfaceHelpers.h"
#include "PathHelpers.h"
#include "Swizzle.h"
#include <algorithm>
@ -805,19 +806,99 @@ DrawTargetSkia::Stroke(const Path *aPath,
mCanvas->drawPath(skiaPath->GetPath(), paint.mPaint);
}
static Float
DashPeriodLength(const StrokeOptions& aStrokeOptions)
{
Float length = 0;
for (size_t i = 0; i < aStrokeOptions.mDashLength; i++) {
length += aStrokeOptions.mDashPattern[i];
}
if (aStrokeOptions.mDashLength & 1) {
// "If an odd number of values is provided, then the list of values is
// repeated to yield an even number of values."
// Double the length.
length += length;
}
return length;
}
static inline Float
RoundDownToMultiple(Float aValue, Float aFactor)
{
return floorf(aValue / aFactor) * aFactor;
}
static Rect
UserSpaceStrokeClip(const IntRect &aDeviceClip,
const Matrix &aTransform,
const StrokeOptions &aStrokeOptions)
{
Matrix inverse = aTransform;
if (!inverse.Invert()) {
return Rect();
}
Rect deviceClip(aDeviceClip);
deviceClip.Inflate(MaxStrokeExtents(aStrokeOptions, aTransform));
return inverse.TransformBounds(deviceClip);
}
static Rect
ShrinkClippedStrokedRect(const Rect &aStrokedRect, const IntRect &aDeviceClip,
const Matrix &aTransform,
const StrokeOptions &aStrokeOptions)
{
Rect userSpaceStrokeClip =
UserSpaceStrokeClip(aDeviceClip, aTransform, aStrokeOptions);
Rect intersection = aStrokedRect.Intersect(userSpaceStrokeClip);
Float dashPeriodLength = DashPeriodLength(aStrokeOptions);
if (intersection.IsEmpty() || dashPeriodLength == 0.0f) {
return intersection;
}
// Reduce the rectangle side lengths in multiples of the dash period length
// so that the visible dashes stay in the same place.
Margin insetBy = aStrokedRect - intersection;
insetBy.top = RoundDownToMultiple(insetBy.top, dashPeriodLength);
insetBy.right = RoundDownToMultiple(insetBy.right, dashPeriodLength);
insetBy.bottom = RoundDownToMultiple(insetBy.bottom, dashPeriodLength);
insetBy.left = RoundDownToMultiple(insetBy.left, dashPeriodLength);
Rect shrunkRect = aStrokedRect;
shrunkRect.Deflate(insetBy);
return shrunkRect;
}
void
DrawTargetSkia::StrokeRect(const Rect &aRect,
const Pattern &aPattern,
const StrokeOptions &aStrokeOptions,
const DrawOptions &aOptions)
{
// Stroking large rectangles with dashes is expensive with Skia (fixed
// overhead based on the number of dashes, regardless of whether the dashes
// are visible), so we try to reduce the size of the stroked rectangle as
// much as possible before passing it on to Skia.
Rect rect = aRect;
if (aStrokeOptions.mDashLength > 0 && !rect.IsEmpty()) {
IntRect deviceClip(IntPoint(0, 0), mSize);
SkIRect clipBounds;
if (mCanvas->getClipDeviceBounds(&clipBounds)) {
deviceClip = SkIRectToIntRect(clipBounds);
}
rect = ShrinkClippedStrokedRect(rect, deviceClip, mTransform, aStrokeOptions);
if (rect.IsEmpty()) {
return;
}
}
MarkChanged();
AutoPaintSetup paint(mCanvas.get(), aOptions, aPattern);
if (!StrokeOptionsToPaint(paint.mPaint, aStrokeOptions)) {
return;
}
mCanvas->drawRect(RectToSkRect(aRect), paint.mPaint);
mCanvas->drawRect(RectToSkRect(rect), paint.mPaint);
}
void

Просмотреть файл

@ -297,6 +297,12 @@ IntRectToSkIRect(const IntRect& aRect)
return SkIRect::MakeXYWH(aRect.x, aRect.y, aRect.width, aRect.height);
}
static inline IntRect
SkIRectToIntRect(const SkIRect& aRect)
{
return IntRect(aRect.x(), aRect.y(), aRect.width(), aRect.height());
}
static inline Point
SkPointToPoint(const SkPoint &aPoint)
{