Bug 1123019 - In DrawTargetTiled::StrokeRect and StrokeLine, skip tiles that don't intersect the stroke. r=jrmuizel
This commit is contained in:
@@ -3,11 +3,9 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#define _USE_MATH_DEFINES
|
|
||||||
#include <cmath>
|
|
||||||
|
|
||||||
#include "DrawTargetTiled.h"
|
#include "DrawTargetTiled.h"
|
||||||
#include "Logging.h"
|
#include "Logging.h"
|
||||||
|
#include "PathHelpers.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
@@ -107,8 +105,6 @@ TILED_COMMAND(Flush)
|
|||||||
TILED_COMMAND4(DrawFilter, FilterNode*, const Rect&, const Point&, const DrawOptions&)
|
TILED_COMMAND4(DrawFilter, FilterNode*, const Rect&, const Point&, const DrawOptions&)
|
||||||
TILED_COMMAND1(ClearRect, const Rect&)
|
TILED_COMMAND1(ClearRect, const Rect&)
|
||||||
TILED_COMMAND4(MaskSurface, const Pattern&, SourceSurface*, Point, const DrawOptions&)
|
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_COMMAND5(FillGlyphs, ScaledFont*, const GlyphBuffer&, const Pattern&, const DrawOptions&, const GlyphRenderingOptions*)
|
||||||
TILED_COMMAND3(Mask, const Pattern&, const Pattern&, const DrawOptions&)
|
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
|
void
|
||||||
DrawTargetTiled::Stroke(const Path* aPath, const Pattern& aPattern, const StrokeOptions& aStrokeOptions, const DrawOptions& aDrawOptions)
|
DrawTargetTiled::Stroke(const Path* aPath, const Pattern& aPattern, const StrokeOptions& aStrokeOptions, const DrawOptions& aDrawOptions)
|
||||||
{
|
{
|
||||||
// Approximate the stroke extents, since Path::GetStrokeExtents can be slow
|
// Approximate the stroke extents, since Path::GetStrokeExtents can be slow
|
||||||
Rect deviceRect = PathExtentsToMaxStrokeExtents(aStrokeOptions,
|
Rect deviceRect = aPath->GetBounds(mTransform);
|
||||||
aPath->GetBounds(mTransform),
|
deviceRect.Inflate(MaxStrokeExtents(aStrokeOptions, mTransform));
|
||||||
mTransform);
|
|
||||||
for (size_t i = 0; i < mTiles.size(); i++) {
|
for (size_t i = 0; i < mTiles.size(); i++) {
|
||||||
if (!mTiles[i].mClippedOut &&
|
if (!mTiles[i].mClippedOut &&
|
||||||
deviceRect.Intersects(Rect(mTiles[i].mTileOrigin.x,
|
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
|
void
|
||||||
DrawTargetTiled::Fill(const Path* aPath, const Pattern& aPattern, const DrawOptions& aDrawOptions)
|
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
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#define _USE_MATH_DEFINES
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
#include "PathHelpers.h"
|
#include "PathHelpers.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
@@ -238,6 +241,29 @@ StrokeSnappedEdgesOfRect(const Rect& aRect, DrawTarget& aDrawTarget,
|
|||||||
aDrawTarget.StrokeLine(p1, p2, aColor, aStrokeOptions);
|
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 gfx
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
||||||
|
|||||||
@@ -283,6 +283,16 @@ GFX2D_API void StrokeSnappedEdgesOfRect(const Rect& aRect,
|
|||||||
const ColorPattern& aColor,
|
const ColorPattern& aColor,
|
||||||
const StrokeOptions& aStrokeOptions);
|
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;
|
extern UserDataKey sDisablePixelSnapping;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -109,6 +109,7 @@ UNIFIED_SOURCES += [
|
|||||||
'DrawTargetCapture.cpp',
|
'DrawTargetCapture.cpp',
|
||||||
'DrawTargetDual.cpp',
|
'DrawTargetDual.cpp',
|
||||||
'DrawTargetRecording.cpp',
|
'DrawTargetRecording.cpp',
|
||||||
|
'DrawTargetTiled.cpp',
|
||||||
'Factory.cpp',
|
'Factory.cpp',
|
||||||
'FilterNodeSoftware.cpp',
|
'FilterNodeSoftware.cpp',
|
||||||
'FilterProcessing.cpp',
|
'FilterProcessing.cpp',
|
||||||
@@ -117,7 +118,6 @@ UNIFIED_SOURCES += [
|
|||||||
'Matrix.cpp',
|
'Matrix.cpp',
|
||||||
'Path.cpp',
|
'Path.cpp',
|
||||||
'PathCairo.cpp',
|
'PathCairo.cpp',
|
||||||
'PathHelpers.cpp',
|
|
||||||
'PathRecording.cpp',
|
'PathRecording.cpp',
|
||||||
'RecordedEvent.cpp',
|
'RecordedEvent.cpp',
|
||||||
'Scale.cpp',
|
'Scale.cpp',
|
||||||
@@ -128,7 +128,7 @@ UNIFIED_SOURCES += [
|
|||||||
]
|
]
|
||||||
|
|
||||||
SOURCES += [
|
SOURCES += [
|
||||||
'DrawTargetTiled.cpp',
|
'PathHelpers.cpp', # Uses _USE_MATH_DEFINES
|
||||||
]
|
]
|
||||||
|
|
||||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
|
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
|
||||||
|
|||||||
Reference in New Issue
Block a user