Bug 1074294, part 2 - Convert nsSVGPathGeometryFrame::Render() to render directly using the Moz2D DrawTarget. r=longsonr

This commit is contained in:
Jonathan Watt 2014-09-30 18:08:13 +01:00
Родитель 12ea292678
Коммит 2a246892c9
5 изменённых файлов: 86 добавлений и 61 удалений

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

@ -183,9 +183,9 @@ SVGContentUtils::GetStrokeOptions(AutoStrokeOptions* aStrokeOptions,
aStrokeOptions->mLineWidth = 0;
return;
}
if (dashState == eContinuousStroke) {
// Prevent our caller from wasting time looking at the dash array:
aStrokeOptions->mDashLength = 0;
if (dashState == eContinuousStroke && aStrokeOptions->mDashPattern) {
// Prevent our caller from wasting time looking at a pattern without gaps:
aStrokeOptions->DiscardDashPattern();
}
aStrokeOptions->mLineWidth =

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

@ -116,6 +116,13 @@ public:
mDashPattern = nonConstArray;
return nonConstArray;
}
void DiscardDashPattern() {
if (mDashPattern && mDashPattern != mSmallArray) {
delete [] mDashPattern;
}
mDashLength = 0;
mDashPattern = nullptr;
}
private:
// Most dasharrays will fit in this and save us allocating
Float mSmallArray[16];

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

@ -326,7 +326,7 @@ fuzzy-if(cocoaWidget&&layersGPUAccelerated,1,3) == text-layout-06.svg text-layou
HTTP(..) == text-scale-02.svg text-scale-02-ref.svg
HTTP(..) == text-scale-03.svg text-scale-03-ref.svg
== text-stroke-scaling-01.svg text-stroke-scaling-01-ref.svg
fails-if(OSX==10.8) == stroke-dasharray-01.svg stroke-dasharray-01-ref.svg # bug 896487
== stroke-dasharray-01.svg stroke-dasharray-01-ref.svg
== stroke-dasharray-02.svg pass.svg
== stroke-dasharray-and-pathLength-01.svg pass.svg
== stroke-dasharray-and-text-01.svg stroke-dasharray-and-text-01-ref.svg

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

@ -12,6 +12,7 @@
#include "gfxPlatform.h"
#include "gfxSVGGlyphs.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/gfx/Helpers.h"
#include "mozilla/RefPtr.h"
#include "nsDisplayList.h"
#include "nsGkAtoms.h"
@ -107,11 +108,9 @@ nsDisplaySVGPathGeometry::Paint(nsDisplayListBuilder* aBuilder,
gfxPoint devPixelOffset =
nsLayoutUtils::PointToGfxPoint(offset, appUnitsPerDevPixel);
aCtx->ThebesContext()->Save();
gfxMatrix tm = nsSVGIntegrationUtils::GetCSSPxToDevPxMatrix(mFrame) *
gfxMatrix::Translation(devPixelOffset);
static_cast<nsSVGPathGeometryFrame*>(mFrame)->PaintSVG(aCtx, tm);
aCtx->ThebesContext()->Restore();
}
//----------------------------------------------------------------------
@ -219,9 +218,18 @@ nsSVGPathGeometryFrame::PaintSVG(nsRenderingContext *aContext,
if (!StyleVisibility()->IsVisible())
return NS_OK;
gfxContext* gfx = aContext->ThebesContext();
// Matrix to the geometry's user space:
gfxMatrix newMatrix =
gfx->CurrentMatrix().PreMultiply(aTransform).NudgeToIntegers();
if (newMatrix.IsSingular()) {
return NS_OK;
}
uint32_t paintOrder = StyleSVG()->mPaintOrder;
if (paintOrder == NS_STYLE_PAINT_ORDER_NORMAL) {
Render(aContext, eRenderFill | eRenderStroke, aTransform);
Render(gfx, eRenderFill | eRenderStroke, newMatrix);
PaintMarkers(aContext, aTransform);
} else {
while (paintOrder) {
@ -229,10 +237,10 @@ nsSVGPathGeometryFrame::PaintSVG(nsRenderingContext *aContext,
paintOrder & ((1 << NS_STYLE_PAINT_ORDER_BITWIDTH) - 1);
switch (component) {
case NS_STYLE_PAINT_ORDER_FILL:
Render(aContext, eRenderFill, aTransform);
Render(gfx, eRenderFill, newMatrix);
break;
case NS_STYLE_PAINT_ORDER_STROKE:
Render(aContext, eRenderStroke, aTransform);
Render(gfx, eRenderStroke, newMatrix);
break;
case NS_STYLE_PAINT_ORDER_MARKERS:
PaintMarkers(aContext, aTransform);
@ -608,25 +616,24 @@ nsSVGPathGeometryFrame::MarkerProperties::GetMarkerEndFrame()
}
void
nsSVGPathGeometryFrame::Render(nsRenderingContext *aContext,
nsSVGPathGeometryFrame::Render(gfxContext* aContext,
uint32_t aRenderComponents,
const gfxMatrix& aTransform)
const gfxMatrix& aNewTransform)
{
gfxContext *gfx = aContext->ThebesContext();
MOZ_ASSERT(!aNewTransform.IsSingular());
gfxMatrix newMatrix =
gfx->CurrentMatrix().PreMultiply(aTransform).NudgeToIntegers();
if (newMatrix.IsSingular()) {
return;
}
DrawTarget* drawTarget = aContext->GetDrawTarget();
uint16_t renderMode = SVGAutoRenderState::GetRenderMode(drawTarget);
MOZ_ASSERT(renderMode == SVGAutoRenderState::NORMAL ||
renderMode == SVGAutoRenderState::CLIP_MASK,
"Unknown render mode");
uint16_t renderMode = SVGAutoRenderState::GetRenderMode(aContext->GetDrawTarget());
FillRule fillRule =
nsSVGUtils::ToFillRule(renderMode == SVGAutoRenderState::CLIP_MASK ?
StyleSVG()->mClipRule : StyleSVG()->mFillRule);
nsSVGUtils::ToFillRule(renderMode == SVGAutoRenderState::NORMAL ?
StyleSVG()->mFillRule : StyleSVG()->mClipRule);
RefPtr<PathBuilder> builder =
aContext->GetDrawTarget()->CreatePathBuilder(fillRule);
RefPtr<PathBuilder> builder = drawTarget->CreatePathBuilder(fillRule);
if (!builder) {
return;
}
@ -637,62 +644,65 @@ nsSVGPathGeometryFrame::Render(nsRenderingContext *aContext,
return;
}
switch (StyleSVG()->mShapeRendering) {
case NS_STYLE_SHAPE_RENDERING_OPTIMIZESPEED:
case NS_STYLE_SHAPE_RENDERING_CRISPEDGES:
gfx->SetAntialiasMode(AntialiasMode::NONE);
break;
default:
gfx->SetAntialiasMode(AntialiasMode::SUBPIXEL);
break;
}
AntialiasMode aaMode =
(StyleSVG()->mShapeRendering == NS_STYLE_SHAPE_RENDERING_OPTIMIZESPEED ||
StyleSVG()->mShapeRendering == NS_STYLE_SHAPE_RENDERING_CRISPEDGES) ?
AntialiasMode::NONE : AntialiasMode::SUBPIXEL;
// We wait as late as possible before setting the transform so that we don't
// set it unnecessarily if we return early (it's an expensive operation for
// some backends).
gfxContextMatrixAutoSaveRestore autoRestoreTransform(aContext);
aContext->SetMatrix(aNewTransform);
if (renderMode == SVGAutoRenderState::CLIP_MASK) {
FillRule oldFillRule = gfx->CurrentFillRule();
gfxContextMatrixAutoSaveRestore autoSaveRestore(gfx);
gfx->SetMatrix(newMatrix);
gfx->SetFillRule(fillRule);
gfx->SetColor(gfxRGBA(1.0f, 1.0f, 1.0f, 1.0f));
gfx->SetPath(path);
gfx->Fill();
gfx->SetFillRule(oldFillRule);
gfx->NewPath();
drawTarget->Fill(path, ColorPattern(Color(1.0f, 1.0f, 1.0f, 1.0f)),
DrawOptions(1.0f, CompositionOp::OP_OVER, aaMode));
return;
}
NS_ABORT_IF_FALSE(renderMode == SVGAutoRenderState::NORMAL,
"Unknown render mode");
gfxContextAutoSaveRestore autoSaveRestore(gfx);
gfx->SetMatrix(newMatrix);
gfxTextContextPaint *contextPaint =
(gfxTextContextPaint*)aContext->GetDrawTarget()->GetUserData(&gfxTextContextPaint::sUserDataKey);
(gfxTextContextPaint*)drawTarget->
GetUserData(&gfxTextContextPaint::sUserDataKey);
if ((aRenderComponents & eRenderFill)) {
if (aRenderComponents & eRenderFill) {
GeneralPattern fillPattern;
nsSVGUtils::MakeFillPatternFor(this, gfx, &fillPattern, contextPaint);
nsSVGUtils::MakeFillPatternFor(this, aContext, &fillPattern, contextPaint);
if (fillPattern.GetPattern()) {
gfx->SetPath(path);
gfx->SetFillRule(fillRule);
gfx->Fill(fillPattern);
drawTarget->Fill(path, fillPattern,
DrawOptions(1.0f, CompositionOp::OP_OVER, aaMode));
}
}
if ((aRenderComponents & eRenderStroke) &&
nsSVGUtils::HasStroke(this, contextPaint)) {
// Account for vector-effect:non-scaling-stroke:
gfxMatrix strokeTransform = nsSVGUtils::GetStrokeTransform(this);
if (!strokeTransform.IsIdentity()) {
// We need to transform the path back into the appropriate ancestor
// coordinate system, and paint it it that coordinate system, in order
// for non-scaled stroke to paint correctly.
aContext->Multiply(strokeTransform);
Matrix moz2DstrokeTransform = ToMatrix(strokeTransform); // inverse of Thebes
moz2DstrokeTransform.Invert();
builder = path->TransformedCopyToBuilder(moz2DstrokeTransform, fillRule);
path = builder->Finish();
}
GeneralPattern strokePattern;
nsSVGUtils::MakeStrokePatternFor(this, gfx, &strokePattern, contextPaint);
nsSVGUtils::MakeStrokePatternFor(this, aContext, &strokePattern, contextPaint);
if (strokePattern.GetPattern()) {
gfx->SetPath(path);
nsSVGUtils::SetupCairoStrokeGeometry(this, gfx, contextPaint);
gfx->Stroke(strokePattern);
SVGContentUtils::AutoStrokeOptions strokeOptions;
SVGContentUtils::GetStrokeOptions(&strokeOptions,
static_cast<nsSVGElement*>(mContent),
StyleContext(), contextPaint);
// GetStrokeOptions may set the line width to zero as an optimization
if (strokeOptions.mLineWidth <= 0) {
return;
}
drawTarget->Stroke(path, strokePattern, strokeOptions,
DrawOptions(1.0f, CompositionOp::OP_OVER, aaMode));
}
}
gfx->NewPath();
}
void

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

@ -15,6 +15,12 @@
#include "nsQueryFrame.h"
#include "nsSVGUtils.h"
namespace mozilla {
namespace gfx {
class DrawTarget;
}
}
class gfxContext;
class nsDisplaySVGPathGeometry;
class nsIAtom;
@ -34,6 +40,8 @@ typedef nsFrame nsSVGPathGeometryFrameBase;
class nsSVGPathGeometryFrame : public nsSVGPathGeometryFrameBase,
public nsISVGChildFrame
{
typedef mozilla::gfx::DrawTarget DrawTarget;
friend nsIFrame*
NS_NewSVGPathGeometryFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
@ -113,7 +121,7 @@ protected:
virtual uint16_t GetHitTestFlags();
private:
enum { eRenderFill = 1, eRenderStroke = 2 };
void Render(nsRenderingContext *aContext, uint32_t aRenderComponents,
void Render(gfxContext* aContext, uint32_t aRenderComponents,
const gfxMatrix& aTransform);
/**