mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 21:31:04 +00:00
Bug 1123019 - In DrawTargetTiled::StrokeRect and StrokeLine, skip tiles that don't intersect the stroke. r=jrmuizel
This commit is contained in:
parent
f46bfb2ae3
commit
a9c358600a
@ -3,11 +3,9 @@
|
||||
* 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/. */
|
||||
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <cmath>
|
||||
|
||||
#include "DrawTargetTiled.h"
|
||||
#include "Logging.h"
|
||||
#include "PathHelpers.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@ -107,8 +105,6 @@ TILED_COMMAND(Flush)
|
||||
TILED_COMMAND4(DrawFilter, FilterNode*, const Rect&, const Point&, const DrawOptions&)
|
||||
TILED_COMMAND1(ClearRect, const Rect&)
|
||||
TILED_COMMAND4(MaskSurface, const Pattern&, SourceSurface*, Point, const DrawOptions&)
|
||||
TILED_COMMAND4(StrokeRect, const Rect&, const Pattern&, const StrokeOptions&, const DrawOptions&)
|
||||
TILED_COMMAND5(StrokeLine, const Point&, const Point&, const Pattern&, const StrokeOptions&, const DrawOptions&)
|
||||
TILED_COMMAND5(FillGlyphs, ScaledFont*, const GlyphBuffer&, const Pattern&, const DrawOptions&, const GlyphRenderingOptions*)
|
||||
TILED_COMMAND3(Mask, const Pattern&, const Pattern&, const DrawOptions&)
|
||||
|
||||
@ -232,40 +228,12 @@ DrawTargetTiled::FillRect(const Rect& aRect, const Pattern& aPattern, const Draw
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetTiled::Stroke(const Path* aPath, const Pattern& aPattern, const StrokeOptions& aStrokeOptions, const DrawOptions& aDrawOptions)
|
||||
{
|
||||
// Approximate the stroke extents, since Path::GetStrokeExtents can be slow
|
||||
Rect deviceRect = PathExtentsToMaxStrokeExtents(aStrokeOptions,
|
||||
aPath->GetBounds(mTransform),
|
||||
mTransform);
|
||||
Rect deviceRect = aPath->GetBounds(mTransform);
|
||||
deviceRect.Inflate(MaxStrokeExtents(aStrokeOptions, mTransform));
|
||||
for (size_t i = 0; i < mTiles.size(); i++) {
|
||||
if (!mTiles[i].mClippedOut &&
|
||||
deviceRect.Intersects(Rect(mTiles[i].mTileOrigin.x,
|
||||
@ -277,6 +245,51 @@ DrawTargetTiled::Stroke(const Path* aPath, const Pattern& aPattern, const Stroke
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetTiled::StrokeRect(const Rect& aRect, const Pattern& aPattern, const StrokeOptions &aStrokeOptions, const DrawOptions& aDrawOptions)
|
||||
{
|
||||
Rect deviceRect = mTransform.TransformBounds(aRect);
|
||||
Margin strokeMargin = MaxStrokeExtents(aStrokeOptions, mTransform);
|
||||
Rect outerRect = deviceRect;
|
||||
outerRect.Inflate(strokeMargin);
|
||||
Rect innerRect;
|
||||
if (mTransform.IsRectilinear()) {
|
||||
// If rects are mapped to rects, we can compute the inner rect
|
||||
// of the stroked rect.
|
||||
innerRect = deviceRect;
|
||||
innerRect.Deflate(strokeMargin);
|
||||
}
|
||||
for (size_t i = 0; i < mTiles.size(); i++) {
|
||||
if (mTiles[i].mClippedOut) {
|
||||
continue;
|
||||
}
|
||||
Rect tileRect(mTiles[i].mTileOrigin.x,
|
||||
mTiles[i].mTileOrigin.y,
|
||||
mTiles[i].mDrawTarget->GetSize().width,
|
||||
mTiles[i].mDrawTarget->GetSize().height);
|
||||
if (outerRect.Intersects(tileRect) && !innerRect.Contains(tileRect)) {
|
||||
mTiles[i].mDrawTarget->StrokeRect(aRect, aPattern, aStrokeOptions, aDrawOptions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetTiled::StrokeLine(const Point& aStart, const Point& aEnd, const Pattern& aPattern, const StrokeOptions &aStrokeOptions, const DrawOptions& aDrawOptions)
|
||||
{
|
||||
Rect lineBounds = Rect(aStart, Size()).UnionEdges(Rect(aEnd, Size()));
|
||||
Rect deviceRect = mTransform.TransformBounds(lineBounds);
|
||||
deviceRect.Inflate(MaxStrokeExtents(aStrokeOptions, mTransform));
|
||||
for (size_t i = 0; i < mTiles.size(); i++) {
|
||||
if (!mTiles[i].mClippedOut &&
|
||||
deviceRect.Intersects(Rect(mTiles[i].mTileOrigin.x,
|
||||
mTiles[i].mTileOrigin.y,
|
||||
mTiles[i].mDrawTarget->GetSize().width,
|
||||
mTiles[i].mDrawTarget->GetSize().height))) {
|
||||
mTiles[i].mDrawTarget->StrokeLine(aStart, aEnd, aPattern, aStrokeOptions, aDrawOptions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetTiled::Fill(const Path* aPath, const Pattern& aPattern, const DrawOptions& aDrawOptions)
|
||||
{
|
||||
|
@ -3,6 +3,9 @@
|
||||
* 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/. */
|
||||
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <cmath>
|
||||
|
||||
#include "PathHelpers.h"
|
||||
|
||||
namespace mozilla {
|
||||
@ -238,6 +241,29 @@ StrokeSnappedEdgesOfRect(const Rect& aRect, DrawTarget& aDrawTarget,
|
||||
aDrawTarget.StrokeLine(p1, p2, aColor, aStrokeOptions);
|
||||
}
|
||||
|
||||
// The logic for this comes from _cairo_stroke_style_max_distance_from_path
|
||||
Margin
|
||||
MaxStrokeExtents(const StrokeOptions& aStrokeOptions,
|
||||
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);
|
||||
return Margin(dy, dx, dy, dx);
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace mozilla
|
||||
|
||||
|
@ -283,6 +283,16 @@ GFX2D_API void StrokeSnappedEdgesOfRect(const Rect& aRect,
|
||||
const ColorPattern& aColor,
|
||||
const StrokeOptions& aStrokeOptions);
|
||||
|
||||
/**
|
||||
* Return the margin, in device space, by which a stroke can extend beyond the
|
||||
* rendered shape.
|
||||
* @param aStrokeOptions The stroke options that the stroke is drawn with.
|
||||
* @param aTransform The user space to device space transform.
|
||||
* @return The stroke margin.
|
||||
*/
|
||||
GFX2D_API Margin MaxStrokeExtents(const StrokeOptions& aStrokeOptions,
|
||||
const Matrix& aTransform);
|
||||
|
||||
extern UserDataKey sDisablePixelSnapping;
|
||||
|
||||
/**
|
||||
|
@ -109,6 +109,7 @@ UNIFIED_SOURCES += [
|
||||
'DrawTargetCapture.cpp',
|
||||
'DrawTargetDual.cpp',
|
||||
'DrawTargetRecording.cpp',
|
||||
'DrawTargetTiled.cpp',
|
||||
'Factory.cpp',
|
||||
'FilterNodeSoftware.cpp',
|
||||
'FilterProcessing.cpp',
|
||||
@ -117,7 +118,6 @@ UNIFIED_SOURCES += [
|
||||
'Matrix.cpp',
|
||||
'Path.cpp',
|
||||
'PathCairo.cpp',
|
||||
'PathHelpers.cpp',
|
||||
'PathRecording.cpp',
|
||||
'RecordedEvent.cpp',
|
||||
'Scale.cpp',
|
||||
@ -128,7 +128,7 @@ UNIFIED_SOURCES += [
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
'DrawTargetTiled.cpp',
|
||||
'PathHelpers.cpp', # Uses _USE_MATH_DEFINES
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
|
||||
|
Loading…
Reference in New Issue
Block a user