зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1074294, part 2 - Convert nsSVGPathGeometryFrame::Render() to render directly using the Moz2D DrawTarget. r=longsonr
This commit is contained in:
Родитель
12ea292678
Коммит
2a246892c9
|
@ -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);
|
||||
|
||||
/**
|
||||
|
|
Загрузка…
Ссылка в новой задаче