зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1342571 - shrink dashed DrawTargetSkia::StrokeRect where possible. r=mstange
MozReview-Commit-ID: 7vu9j8jCwQn
This commit is contained in:
Родитель
c834f9ba25
Коммит
4dfd1b6ac1
|
@ -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)
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче