зеркало из https://github.com/mozilla/gecko-dev.git
Bug 666097 - Fix radial gradient drawing in Azure. r=jrmuizel
* * * Part 2: Adjust tests to properly confirm passing. r=jrmuizel
This commit is contained in:
Родитель
460091a3b1
Коммит
371b57bace
|
@ -194,79 +194,6 @@ public:
|
||||||
|
|
||||||
NS_DECL_ISUPPORTS
|
NS_DECL_ISUPPORTS
|
||||||
|
|
||||||
protected:
|
|
||||||
nsCanvasGradientAzure(Type aType) : mType(aType)
|
|
||||||
{}
|
|
||||||
|
|
||||||
nsTArray<GradientStop> mRawStops;
|
|
||||||
RefPtr<GradientStops> mStops;
|
|
||||||
Type mType;
|
|
||||||
};
|
|
||||||
|
|
||||||
class nsCanvasRadialGradientAzure : public nsCanvasGradientAzure
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
nsCanvasRadialGradientAzure(const Point &aBeginOrigin, Float aBeginRadius,
|
|
||||||
const Point &aEndOrigin, Float aEndRadius)
|
|
||||||
: nsCanvasGradientAzure(RADIAL)
|
|
||||||
, mCenter(aEndOrigin)
|
|
||||||
, mRadius(aEndRadius)
|
|
||||||
{
|
|
||||||
mOffsetStart = aBeginRadius / mRadius;
|
|
||||||
|
|
||||||
mOffsetRatio = 1 - mOffsetStart;
|
|
||||||
mOrigin = ((mCenter * aBeginRadius) - (aBeginOrigin * mRadius)) /
|
|
||||||
(aBeginRadius - mRadius);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* nsIDOMCanvasGradient */
|
|
||||||
NS_IMETHOD AddColorStop (float offset,
|
|
||||||
const nsAString& colorstr)
|
|
||||||
{
|
|
||||||
if (!FloatValidate(offset) || offset < 0.0 || offset > 1.0) {
|
|
||||||
return NS_ERROR_DOM_INDEX_SIZE_ERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
nscolor color;
|
|
||||||
nsCSSParser parser;
|
|
||||||
nsresult rv = parser.ParseColorString(nsString(colorstr),
|
|
||||||
nsnull, 0, &color);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return NS_ERROR_DOM_SYNTAX_ERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
mStops = nsnull;
|
|
||||||
|
|
||||||
GradientStop newStop;
|
|
||||||
|
|
||||||
newStop.offset = offset * mOffsetRatio + mOffsetStart;
|
|
||||||
newStop.color = Color::FromABGR(color);
|
|
||||||
|
|
||||||
mRawStops.AppendElement(newStop);
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// XXX - Temporary gradient code, this will be fixed soon as per bug 666097
|
|
||||||
Point mCenter;
|
|
||||||
Float mRadius;
|
|
||||||
Point mOrigin;
|
|
||||||
|
|
||||||
Float mOffsetStart;
|
|
||||||
Float mOffsetRatio;
|
|
||||||
};
|
|
||||||
|
|
||||||
class nsCanvasLinearGradientAzure : public nsCanvasGradientAzure
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
nsCanvasLinearGradientAzure(const Point &aBegin, const Point &aEnd)
|
|
||||||
: nsCanvasGradientAzure(LINEAR)
|
|
||||||
, mBegin(aBegin)
|
|
||||||
, mEnd(aEnd)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/* nsIDOMCanvasGradient */
|
/* nsIDOMCanvasGradient */
|
||||||
NS_IMETHOD AddColorStop (float offset,
|
NS_IMETHOD AddColorStop (float offset,
|
||||||
const nsAString& colorstr)
|
const nsAString& colorstr)
|
||||||
|
@ -295,6 +222,44 @@ public:
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
nsCanvasGradientAzure(Type aType) : mType(aType)
|
||||||
|
{}
|
||||||
|
|
||||||
|
nsTArray<GradientStop> mRawStops;
|
||||||
|
RefPtr<GradientStops> mStops;
|
||||||
|
Type mType;
|
||||||
|
};
|
||||||
|
|
||||||
|
class nsCanvasRadialGradientAzure : public nsCanvasGradientAzure
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
nsCanvasRadialGradientAzure(const Point &aBeginOrigin, Float aBeginRadius,
|
||||||
|
const Point &aEndOrigin, Float aEndRadius)
|
||||||
|
: nsCanvasGradientAzure(RADIAL)
|
||||||
|
, mCenter1(aBeginOrigin)
|
||||||
|
, mCenter2(aEndOrigin)
|
||||||
|
, mRadius1(aBeginRadius)
|
||||||
|
, mRadius2(aEndRadius)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Point mCenter1;
|
||||||
|
Point mCenter2;
|
||||||
|
Float mRadius1;
|
||||||
|
Float mRadius2;
|
||||||
|
};
|
||||||
|
|
||||||
|
class nsCanvasLinearGradientAzure : public nsCanvasGradientAzure
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
nsCanvasLinearGradientAzure(const Point &aBegin, const Point &aEnd)
|
||||||
|
: nsCanvasGradientAzure(LINEAR)
|
||||||
|
, mBegin(aBegin)
|
||||||
|
, mEnd(aEnd)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class nsCanvasRenderingContext2DAzure;
|
friend class nsCanvasRenderingContext2DAzure;
|
||||||
|
|
||||||
|
@ -827,8 +792,8 @@ protected:
|
||||||
static_cast<nsCanvasRadialGradientAzure*>(state.gradientStyles[aStyle].get());
|
static_cast<nsCanvasRadialGradientAzure*>(state.gradientStyles[aStyle].get());
|
||||||
|
|
||||||
mPattern = new (mRadialGradientPattern.addr())
|
mPattern = new (mRadialGradientPattern.addr())
|
||||||
RadialGradientPattern(gradient->mCenter, gradient->mOrigin, gradient->mRadius,
|
RadialGradientPattern(gradient->mCenter1, gradient->mCenter2, gradient->mRadius1,
|
||||||
gradient->GetGradientStopsForTarget(aRT));
|
gradient->mRadius2, gradient->GetGradientStopsForTarget(aRT));
|
||||||
} else if (state.patternStyles[aStyle]) {
|
} else if (state.patternStyles[aStyle]) {
|
||||||
if (aCtx->mCanvasElement) {
|
if (aCtx->mCanvasElement) {
|
||||||
CanvasUtils::DoDrawImageSecurityCheck(aCtx->HTMLCanvasElement(),
|
CanvasUtils::DoDrawImageSecurityCheck(aCtx->HTMLCanvasElement(),
|
||||||
|
|
|
@ -6,17 +6,6 @@
|
||||||
<body>
|
<body>
|
||||||
<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
|
<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
function IsAzureEnabled() {
|
|
||||||
var enabled = false;
|
|
||||||
|
|
||||||
try {
|
|
||||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
|
||||||
enabled = Components.classes["@mozilla.org/gfx/info;1"].getService(Components.interfaces.nsIGfxInfo).AzureEnabled;
|
|
||||||
} catch (e) { }
|
|
||||||
|
|
||||||
return enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
function isPixel(ctx, x,y, r,g,b,a, pos, colour, d) {
|
function isPixel(ctx, x,y, r,g,b,a, pos, colour, d) {
|
||||||
var pixel = ctx.getImageData(x, y, 1, 1);
|
var pixel = ctx.getImageData(x, y, 1, 1);
|
||||||
|
@ -59,28 +48,15 @@ g.addColorStop(1, '#0f0');
|
||||||
ctx.fillStyle = g;
|
ctx.fillStyle = g;
|
||||||
ctx.fillRect(0, 0, 100, 50);
|
ctx.fillRect(0, 0, 100, 50);
|
||||||
|
|
||||||
if (IsAzureEnabled()) {
|
isPixel(ctx, 1,1, 0,255,0,255, "1,1", "0,255,0,255", 0);
|
||||||
// XXX - See Bug 666097.
|
isPixel(ctx, 50,1, 0,255,0,255, "50,1", "0,255,0,255", 0);
|
||||||
todo_isPixel(ctx, 1,1, 0,255,0,255, "1,1", "0,255,0,255", 0);
|
isPixel(ctx, 98,1, 0,255,0,255, "98,1", "0,255,0,255", 0);
|
||||||
todo_isPixel(ctx, 50,1, 0,255,0,255, "50,1", "0,255,0,255", 0);
|
isPixel(ctx, 1,25, 0,255,0,255, "1,25", "0,255,0,255", 0);
|
||||||
todo_isPixel(ctx, 98,1, 0,255,0,255, "98,1", "0,255,0,255", 0);
|
isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 0);
|
||||||
todo_isPixel(ctx, 1,25, 0,255,0,255, "1,25", "0,255,0,255", 0);
|
isPixel(ctx, 98,25, 0,255,0,255, "98,25", "0,255,0,255", 0);
|
||||||
todo_isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 0);
|
isPixel(ctx, 1,48, 0,255,0,255, "1,48", "0,255,0,255", 0);
|
||||||
todo_isPixel(ctx, 98,25, 0,255,0,255, "98,25", "0,255,0,255", 0);
|
isPixel(ctx, 50,48, 0,255,0,255, "50,48", "0,255,0,255", 0);
|
||||||
todo_isPixel(ctx, 1,48, 0,255,0,255, "1,48", "0,255,0,255", 0);
|
isPixel(ctx, 98,48, 0,255,0,255, "98,48", "0,255,0,255", 0);
|
||||||
todo_isPixel(ctx, 50,48, 0,255,0,255, "50,48", "0,255,0,255", 0);
|
|
||||||
todo_isPixel(ctx, 98,48, 0,255,0,255, "98,48", "0,255,0,255", 0);
|
|
||||||
} else {
|
|
||||||
isPixel(ctx, 1,1, 0,255,0,255, "1,1", "0,255,0,255", 0);
|
|
||||||
isPixel(ctx, 50,1, 0,255,0,255, "50,1", "0,255,0,255", 0);
|
|
||||||
isPixel(ctx, 98,1, 0,255,0,255, "98,1", "0,255,0,255", 0);
|
|
||||||
isPixel(ctx, 1,25, 0,255,0,255, "1,25", "0,255,0,255", 0);
|
|
||||||
isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 0);
|
|
||||||
isPixel(ctx, 98,25, 0,255,0,255, "98,25", "0,255,0,255", 0);
|
|
||||||
isPixel(ctx, 1,48, 0,255,0,255, "1,48", "0,255,0,255", 0);
|
|
||||||
isPixel(ctx, 50,48, 0,255,0,255, "50,48", "0,255,0,255", 0);
|
|
||||||
isPixel(ctx, 98,48, 0,255,0,255, "98,48", "0,255,0,255", 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
SimpleTest.finish();
|
SimpleTest.finish();
|
||||||
|
|
||||||
|
|
|
@ -6399,28 +6399,15 @@ g.addColorStop(1, '#f00');
|
||||||
ctx.fillStyle = g;
|
ctx.fillStyle = g;
|
||||||
ctx.fillRect(0, 0, 100, 50);
|
ctx.fillRect(0, 0, 100, 50);
|
||||||
|
|
||||||
if (IsAzureEnabled()) {
|
isPixel(ctx, 1, 1, 0, 255, 0, 255, 0);
|
||||||
// XXX - See Bug 666097.
|
isPixel(ctx, 50, 1, 0, 255, 0, 255, 0);
|
||||||
todo_isPixel(ctx, 1, 1, 0, 255, 0, 255, 0);
|
isPixel(ctx, 98, 1, 0, 255, 0, 255, 0);
|
||||||
todo_isPixel(ctx, 50, 1, 0, 255, 0, 255, 0);
|
isPixel(ctx, 1, 25, 0, 255, 0, 255, 0);
|
||||||
todo_isPixel(ctx, 98, 1, 0, 255, 0, 255, 0);
|
isPixel(ctx, 50, 25, 0, 255, 0, 255, 0);
|
||||||
todo_isPixel(ctx, 1, 25, 0, 255, 0, 255, 0);
|
isPixel(ctx, 98, 25, 0, 255, 0, 255, 0);
|
||||||
todo_isPixel(ctx, 50, 25, 0, 255, 0, 255, 0);
|
isPixel(ctx, 1, 48, 0, 255, 0, 255, 0);
|
||||||
todo_isPixel(ctx, 98, 25, 0, 255, 0, 255, 0);
|
isPixel(ctx, 50, 48, 0, 255, 0, 255, 0);
|
||||||
todo_isPixel(ctx, 1, 48, 0, 255, 0, 255, 0);
|
isPixel(ctx, 98, 48, 0, 255, 0, 255, 0);
|
||||||
todo_isPixel(ctx, 50, 48, 0, 255, 0, 255, 0);
|
|
||||||
todo_isPixel(ctx, 98, 48, 0, 255, 0, 255, 0);
|
|
||||||
} else {
|
|
||||||
isPixel(ctx, 1, 1, 0, 255, 0, 255, 0);
|
|
||||||
isPixel(ctx, 50, 1, 0, 255, 0, 255, 0);
|
|
||||||
isPixel(ctx, 98, 1, 0, 255, 0, 255, 0);
|
|
||||||
isPixel(ctx, 1, 25, 0, 255, 0, 255, 0);
|
|
||||||
isPixel(ctx, 50, 25, 0, 255, 0, 255, 0);
|
|
||||||
isPixel(ctx, 98, 25, 0, 255, 0, 255, 0);
|
|
||||||
isPixel(ctx, 1, 48, 0, 255, 0, 255, 0);
|
|
||||||
isPixel(ctx, 50, 48, 0, 255, 0, 255, 0);
|
|
||||||
isPixel(ctx, 98, 48, 0, 255, 0, 255, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -6570,29 +6557,15 @@ g.addColorStop(1, '#0f0');
|
||||||
ctx.fillStyle = g;
|
ctx.fillStyle = g;
|
||||||
ctx.fillRect(0, 0, 100, 50);
|
ctx.fillRect(0, 0, 100, 50);
|
||||||
|
|
||||||
|
isPixel(ctx, 1, 1, 0, 255, 0, 255, 0);
|
||||||
if (IsAzureEnabled()) {
|
isPixel(ctx, 50, 1, 0, 255, 0, 255, 0);
|
||||||
// XXX - See Bug 666097.
|
isPixel(ctx, 98, 1, 0, 255, 0, 255, 0);
|
||||||
todo_isPixel(ctx, 1, 1, 0, 255, 0, 255, 0);
|
isPixel(ctx, 1, 25, 0, 255, 0, 255, 0);
|
||||||
todo_isPixel(ctx, 50, 1, 0, 255, 0, 255, 0);
|
isPixel(ctx, 50, 25, 0, 255, 0, 255, 0);
|
||||||
todo_isPixel(ctx, 98, 1, 0, 255, 0, 255, 0);
|
isPixel(ctx, 98, 25, 0, 255, 0, 255, 0);
|
||||||
todo_isPixel(ctx, 1, 25, 0, 255, 0, 255, 0);
|
isPixel(ctx, 1, 48, 0, 255, 0, 255, 0);
|
||||||
todo_isPixel(ctx, 50, 25, 0, 255, 0, 255, 0);
|
isPixel(ctx, 50, 48, 0, 255, 0, 255, 0);
|
||||||
todo_isPixel(ctx, 98, 25, 0, 255, 0, 255, 0);
|
isPixel(ctx, 98, 48, 0, 255, 0, 255, 0);
|
||||||
todo_isPixel(ctx, 1, 48, 0, 255, 0, 255, 0);
|
|
||||||
todo_isPixel(ctx, 50, 48, 0, 255, 0, 255, 0);
|
|
||||||
todo_isPixel(ctx, 98, 48, 0, 255, 0, 255, 0);
|
|
||||||
} else {
|
|
||||||
isPixel(ctx, 1, 1, 0, 255, 0, 255, 0);
|
|
||||||
isPixel(ctx, 50, 1, 0, 255, 0, 255, 0);
|
|
||||||
isPixel(ctx, 98, 1, 0, 255, 0, 255, 0);
|
|
||||||
isPixel(ctx, 1, 25, 0, 255, 0, 255, 0);
|
|
||||||
isPixel(ctx, 50, 25, 0, 255, 0, 255, 0);
|
|
||||||
isPixel(ctx, 98, 25, 0, 255, 0, 255, 0);
|
|
||||||
isPixel(ctx, 1, 48, 0, 255, 0, 255, 0);
|
|
||||||
isPixel(ctx, 50, 48, 0, 255, 0, 255, 0);
|
|
||||||
isPixel(ctx, 98, 48, 0, 255, 0, 255, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
21
gfx/2d/2D.h
21
gfx/2d/2D.h
|
@ -246,22 +246,25 @@ public:
|
||||||
* aStops GradientStops object for this gradient, this should match the
|
* aStops GradientStops object for this gradient, this should match the
|
||||||
* backend type of the draw target this pattern will be used with.
|
* backend type of the draw target this pattern will be used with.
|
||||||
*/
|
*/
|
||||||
RadialGradientPattern(const Point &aCenter,
|
RadialGradientPattern(const Point &aCenter1,
|
||||||
const Point &aOrigin,
|
const Point &aCenter2,
|
||||||
Float aRadius,
|
Float aRadius1,
|
||||||
|
Float aRadius2,
|
||||||
GradientStops *aStops)
|
GradientStops *aStops)
|
||||||
: mCenter(aCenter)
|
: mCenter1(aCenter1)
|
||||||
, mOrigin(aOrigin)
|
, mCenter2(aCenter2)
|
||||||
, mRadius(aRadius)
|
, mRadius1(aRadius1)
|
||||||
|
, mRadius2(aRadius2)
|
||||||
, mStops(aStops)
|
, mStops(aStops)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual PatternType GetType() const { return PATTERN_RADIAL_GRADIENT; }
|
virtual PatternType GetType() const { return PATTERN_RADIAL_GRADIENT; }
|
||||||
|
|
||||||
Point mCenter;
|
Point mCenter1;
|
||||||
Point mOrigin;
|
Point mCenter2;
|
||||||
Float mRadius;
|
Float mRadius1;
|
||||||
|
Float mRadius2;
|
||||||
RefPtr<GradientStops> mStops;
|
RefPtr<GradientStops> mStops;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -229,7 +229,7 @@ DrawTargetD2D::DrawSurface(SourceSurface *aSurface,
|
||||||
{
|
{
|
||||||
RefPtr<ID2D1Bitmap> bitmap;
|
RefPtr<ID2D1Bitmap> bitmap;
|
||||||
|
|
||||||
ID2D1RenderTarget *rt = GetRTForOperator(aOptions.mCompositionOp);
|
ID2D1RenderTarget *rt = GetRTForOperation(aOptions.mCompositionOp, ColorPattern(Color()));
|
||||||
|
|
||||||
PrepareForDrawing(rt);
|
PrepareForDrawing(rt);
|
||||||
|
|
||||||
|
@ -279,7 +279,7 @@ DrawTargetD2D::DrawSurface(SourceSurface *aSurface,
|
||||||
|
|
||||||
rt->DrawBitmap(bitmap, D2DRect(aDest), aOptions.mAlpha, D2DFilter(aSurfOptions.mFilter), D2DRect(srcRect));
|
rt->DrawBitmap(bitmap, D2DRect(aDest), aOptions.mAlpha, D2DFilter(aSurfOptions.mFilter), D2DRect(srcRect));
|
||||||
|
|
||||||
FinalizeRTForOperator(aOptions.mCompositionOp, aDest);
|
FinalizeRTForOperation(aOptions.mCompositionOp, ColorPattern(Color()), aDest);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -693,7 +693,7 @@ DrawTargetD2D::FillRect(const Rect &aRect,
|
||||||
const Pattern &aPattern,
|
const Pattern &aPattern,
|
||||||
const DrawOptions &aOptions)
|
const DrawOptions &aOptions)
|
||||||
{
|
{
|
||||||
ID2D1RenderTarget *rt = GetRTForOperator(aOptions.mCompositionOp);
|
ID2D1RenderTarget *rt = GetRTForOperation(aOptions.mCompositionOp, aPattern);
|
||||||
|
|
||||||
PrepareForDrawing(rt);
|
PrepareForDrawing(rt);
|
||||||
|
|
||||||
|
@ -703,7 +703,7 @@ DrawTargetD2D::FillRect(const Rect &aRect,
|
||||||
rt->FillRectangle(D2DRect(aRect), brush);
|
rt->FillRectangle(D2DRect(aRect), brush);
|
||||||
}
|
}
|
||||||
|
|
||||||
FinalizeRTForOperator(aOptions.mCompositionOp, aRect);
|
FinalizeRTForOperation(aOptions.mCompositionOp, aPattern, aRect);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -712,7 +712,7 @@ DrawTargetD2D::StrokeRect(const Rect &aRect,
|
||||||
const StrokeOptions &aStrokeOptions,
|
const StrokeOptions &aStrokeOptions,
|
||||||
const DrawOptions &aOptions)
|
const DrawOptions &aOptions)
|
||||||
{
|
{
|
||||||
ID2D1RenderTarget *rt = GetRTForOperator(aOptions.mCompositionOp);
|
ID2D1RenderTarget *rt = GetRTForOperation(aOptions.mCompositionOp, aPattern);
|
||||||
|
|
||||||
PrepareForDrawing(rt);
|
PrepareForDrawing(rt);
|
||||||
|
|
||||||
|
@ -724,7 +724,7 @@ DrawTargetD2D::StrokeRect(const Rect &aRect,
|
||||||
rt->DrawRectangle(D2DRect(aRect), brush, aStrokeOptions.mLineWidth, strokeStyle);
|
rt->DrawRectangle(D2DRect(aRect), brush, aStrokeOptions.mLineWidth, strokeStyle);
|
||||||
}
|
}
|
||||||
|
|
||||||
FinalizeRTForOperator(aOptions.mCompositionOp, aRect);
|
FinalizeRTForOperation(aOptions.mCompositionOp, aPattern, aRect);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -734,7 +734,7 @@ DrawTargetD2D::StrokeLine(const Point &aStart,
|
||||||
const StrokeOptions &aStrokeOptions,
|
const StrokeOptions &aStrokeOptions,
|
||||||
const DrawOptions &aOptions)
|
const DrawOptions &aOptions)
|
||||||
{
|
{
|
||||||
ID2D1RenderTarget *rt = GetRTForOperator(aOptions.mCompositionOp);
|
ID2D1RenderTarget *rt = GetRTForOperation(aOptions.mCompositionOp, aPattern);
|
||||||
|
|
||||||
PrepareForDrawing(rt);
|
PrepareForDrawing(rt);
|
||||||
|
|
||||||
|
@ -746,7 +746,7 @@ DrawTargetD2D::StrokeLine(const Point &aStart,
|
||||||
rt->DrawLine(D2DPoint(aStart), D2DPoint(aEnd), brush, aStrokeOptions.mLineWidth, strokeStyle);
|
rt->DrawLine(D2DPoint(aStart), D2DPoint(aEnd), brush, aStrokeOptions.mLineWidth, strokeStyle);
|
||||||
}
|
}
|
||||||
|
|
||||||
FinalizeRTForOperator(aOptions.mCompositionOp, Rect(0, 0, Float(mSize.width), Float(mSize.height)));
|
FinalizeRTForOperation(aOptions.mCompositionOp, aPattern, Rect(0, 0, Float(mSize.width), Float(mSize.height)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -762,7 +762,7 @@ DrawTargetD2D::Stroke(const Path *aPath,
|
||||||
|
|
||||||
const PathD2D *d2dPath = static_cast<const PathD2D*>(aPath);
|
const PathD2D *d2dPath = static_cast<const PathD2D*>(aPath);
|
||||||
|
|
||||||
ID2D1RenderTarget *rt = GetRTForOperator(aOptions.mCompositionOp);
|
ID2D1RenderTarget *rt = GetRTForOperation(aOptions.mCompositionOp, aPattern);
|
||||||
|
|
||||||
PrepareForDrawing(rt);
|
PrepareForDrawing(rt);
|
||||||
|
|
||||||
|
@ -774,7 +774,7 @@ DrawTargetD2D::Stroke(const Path *aPath,
|
||||||
rt->DrawGeometry(d2dPath->mGeometry, brush, aStrokeOptions.mLineWidth, strokeStyle);
|
rt->DrawGeometry(d2dPath->mGeometry, brush, aStrokeOptions.mLineWidth, strokeStyle);
|
||||||
}
|
}
|
||||||
|
|
||||||
FinalizeRTForOperator(aOptions.mCompositionOp, Rect(0, 0, Float(mSize.width), Float(mSize.height)));
|
FinalizeRTForOperation(aOptions.mCompositionOp, aPattern, Rect(0, 0, Float(mSize.width), Float(mSize.height)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -789,7 +789,7 @@ DrawTargetD2D::Fill(const Path *aPath,
|
||||||
|
|
||||||
const PathD2D *d2dPath = static_cast<const PathD2D*>(aPath);
|
const PathD2D *d2dPath = static_cast<const PathD2D*>(aPath);
|
||||||
|
|
||||||
ID2D1RenderTarget *rt = GetRTForOperator(aOptions.mCompositionOp);
|
ID2D1RenderTarget *rt = GetRTForOperation(aOptions.mCompositionOp, aPattern);
|
||||||
|
|
||||||
PrepareForDrawing(rt);
|
PrepareForDrawing(rt);
|
||||||
|
|
||||||
|
@ -805,7 +805,7 @@ DrawTargetD2D::Fill(const Path *aPath,
|
||||||
d2dPath->mGeometry->GetBounds(D2D1::IdentityMatrix(), &d2dbounds);
|
d2dPath->mGeometry->GetBounds(D2D1::IdentityMatrix(), &d2dbounds);
|
||||||
bounds = ToRect(d2dbounds);
|
bounds = ToRect(d2dbounds);
|
||||||
}
|
}
|
||||||
FinalizeRTForOperator(aOptions.mCompositionOp, bounds);
|
FinalizeRTForOperation(aOptions.mCompositionOp, aPattern, bounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -821,7 +821,7 @@ DrawTargetD2D::FillGlyphs(ScaledFont *aFont,
|
||||||
|
|
||||||
ScaledFontDWrite *font = static_cast<ScaledFontDWrite*>(aFont);
|
ScaledFontDWrite *font = static_cast<ScaledFontDWrite*>(aFont);
|
||||||
|
|
||||||
ID2D1RenderTarget *rt = GetRTForOperator(aOptions.mCompositionOp);
|
ID2D1RenderTarget *rt = GetRTForOperation(aOptions.mCompositionOp, aPattern);
|
||||||
|
|
||||||
PrepareForDrawing(rt);
|
PrepareForDrawing(rt);
|
||||||
|
|
||||||
|
@ -857,7 +857,7 @@ DrawTargetD2D::FillGlyphs(ScaledFont *aFont,
|
||||||
rt->DrawGlyphRun(D2D1::Point2F(), &glyphRun, brush);
|
rt->DrawGlyphRun(D2D1::Point2F(), &glyphRun, brush);
|
||||||
}
|
}
|
||||||
|
|
||||||
FinalizeRTForOperator(aOptions.mCompositionOp, Rect(0, 0, (Float)mSize.width, (Float)mSize.height));
|
FinalizeRTForOperation(aOptions.mCompositionOp, aPattern, Rect(0, 0, (Float)mSize.width, (Float)mSize.height));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -986,13 +986,13 @@ DrawTargetD2D::CreatePathBuilder(FillRule aFillRule) const
|
||||||
}
|
}
|
||||||
|
|
||||||
TemporaryRef<GradientStops>
|
TemporaryRef<GradientStops>
|
||||||
DrawTargetD2D::CreateGradientStops(GradientStop *aStops, uint32_t aNumStops) const
|
DrawTargetD2D::CreateGradientStops(GradientStop *rawStops, uint32_t aNumStops) const
|
||||||
{
|
{
|
||||||
D2D1_GRADIENT_STOP *stops = new D2D1_GRADIENT_STOP[aNumStops];
|
D2D1_GRADIENT_STOP *stops = new D2D1_GRADIENT_STOP[aNumStops];
|
||||||
|
|
||||||
for (uint32_t i = 0; i < aNumStops; i++) {
|
for (uint32_t i = 0; i < aNumStops; i++) {
|
||||||
stops[i].position = aStops[i].offset;
|
stops[i].position = rawStops[i].offset;
|
||||||
stops[i].color = D2DColor(aStops[i].color);
|
stops[i].color = D2DColor(rawStops[i].color);
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<ID2D1GradientStopCollection> stopCollection;
|
RefPtr<ID2D1GradientStopCollection> stopCollection;
|
||||||
|
@ -1290,9 +1290,9 @@ DrawTargetD2D::GetBlendStateForOperator(CompositionOp aOperator)
|
||||||
* drawing operation other than OVER is required.
|
* drawing operation other than OVER is required.
|
||||||
*/
|
*/
|
||||||
ID2D1RenderTarget*
|
ID2D1RenderTarget*
|
||||||
DrawTargetD2D::GetRTForOperator(CompositionOp aOperator)
|
DrawTargetD2D::GetRTForOperation(CompositionOp aOperator, const Pattern &aPattern)
|
||||||
{
|
{
|
||||||
if (aOperator == OP_OVER) {
|
if (aOperator == OP_OVER && !IsPatternSupportedByD2D(aPattern)) {
|
||||||
return mRT;
|
return mRT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1331,9 +1331,9 @@ DrawTargetD2D::GetRTForOperator(CompositionOp aOperator)
|
||||||
* to the surface.
|
* to the surface.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
DrawTargetD2D::FinalizeRTForOperator(CompositionOp aOperator, const Rect &aBounds)
|
DrawTargetD2D::FinalizeRTForOperation(CompositionOp aOperator, const Pattern &aPattern, const Rect &aBounds)
|
||||||
{
|
{
|
||||||
if (aOperator == OP_OVER) {
|
if (aOperator == OP_OVER && !IsPatternSupportedByD2D(aPattern)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1377,13 +1377,26 @@ DrawTargetD2D::FinalizeRTForOperator(CompositionOp aOperator, const Rect &aBound
|
||||||
viewport.TopLeftY = 0;
|
viewport.TopLeftY = 0;
|
||||||
|
|
||||||
mDevice->RSSetViewports(1, &viewport);
|
mDevice->RSSetViewports(1, &viewport);
|
||||||
mPrivateData->mEffect->GetVariableByName("tex")->AsShaderResource()->SetResource(mSRView);
|
|
||||||
mPrivateData->mEffect->GetVariableByName("QuadDesc")->AsVector()->
|
mPrivateData->mEffect->GetVariableByName("QuadDesc")->AsVector()->
|
||||||
SetFloatVector(ShaderConstantRectD3D10(-1.0f, 1.0f, 2.0f, -2.0f));
|
SetFloatVector(ShaderConstantRectD3D10(-1.0f, 1.0f, 2.0f, -2.0f));
|
||||||
mPrivateData->mEffect->GetVariableByName("TexCoords")->AsVector()->
|
|
||||||
SetFloatVector(ShaderConstantRectD3D10(0, 0, 1.0f, 1.0f));
|
|
||||||
|
|
||||||
mPrivateData->mEffect->GetTechniqueByName("SampleTexture")->GetPassByIndex(0)->Apply(0);
|
if (!IsPatternSupportedByD2D(aPattern)) {
|
||||||
|
mPrivateData->mEffect->GetVariableByName("TexCoords")->AsVector()->
|
||||||
|
SetFloatVector(ShaderConstantRectD3D10(0, 0, 1.0f, 1.0f));
|
||||||
|
mPrivateData->mEffect->GetVariableByName("tex")->AsShaderResource()->SetResource(mSRView);
|
||||||
|
mPrivateData->mEffect->GetTechniqueByName("SampleTexture")->GetPassByIndex(0)->Apply(0);
|
||||||
|
} else if (aPattern.GetType() == PATTERN_RADIAL_GRADIENT) {
|
||||||
|
const RadialGradientPattern *pat = static_cast<const RadialGradientPattern*>(&aPattern);
|
||||||
|
|
||||||
|
if (pat->mCenter1 == pat->mCenter2 && pat->mRadius1 == pat->mRadius2) {
|
||||||
|
// Draw nothing!
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mPrivateData->mEffect->GetVariableByName("mask")->AsShaderResource()->SetResource(mSRView);
|
||||||
|
|
||||||
|
SetupEffectForRadialGradient(pat);
|
||||||
|
}
|
||||||
|
|
||||||
mDevice->OMSetBlendState(GetBlendStateForOperator(aOperator), NULL, 0xffffffff);
|
mDevice->OMSetBlendState(GetBlendStateForOperator(aOperator), NULL, 0xffffffff);
|
||||||
|
|
||||||
|
@ -1504,6 +1517,12 @@ DrawTargetD2D::PopAllClips()
|
||||||
TemporaryRef<ID2D1Brush>
|
TemporaryRef<ID2D1Brush>
|
||||||
DrawTargetD2D::CreateBrushForPattern(const Pattern &aPattern, Float aAlpha)
|
DrawTargetD2D::CreateBrushForPattern(const Pattern &aPattern, Float aAlpha)
|
||||||
{
|
{
|
||||||
|
if (IsPatternSupportedByD2D(aPattern)) {
|
||||||
|
RefPtr<ID2D1SolidColorBrush> colBrush;
|
||||||
|
mRT->CreateSolidColorBrush(D2D1::ColorF(1.0f, 1.0f, 1.0f, 1.0f), byRef(colBrush));
|
||||||
|
return colBrush;
|
||||||
|
}
|
||||||
|
|
||||||
if (aPattern.GetType() == PATTERN_COLOR) {
|
if (aPattern.GetType() == PATTERN_COLOR) {
|
||||||
RefPtr<ID2D1SolidColorBrush> colBrush;
|
RefPtr<ID2D1SolidColorBrush> colBrush;
|
||||||
Color color = static_cast<const ColorPattern*>(&aPattern)->mColor;
|
Color color = static_cast<const ColorPattern*>(&aPattern)->mColor;
|
||||||
|
@ -1542,13 +1561,15 @@ DrawTargetD2D::CreateBrushForPattern(const Pattern &aPattern, Float aAlpha)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
mRT->CreateRadialGradientBrush(D2D1::RadialGradientBrushProperties(D2DPoint(pat->mCenter),
|
// This will not be a complex radial gradient brush.
|
||||||
D2DPoint(pat->mOrigin - pat->mCenter),
|
mRT->CreateRadialGradientBrush(
|
||||||
pat->mRadius,
|
D2D1::RadialGradientBrushProperties(D2DPoint(pat->mCenter1),
|
||||||
pat->mRadius),
|
D2D1::Point2F(),
|
||||||
D2D1::BrushProperties(aAlpha),
|
pat->mRadius2, pat->mRadius2),
|
||||||
stops->mStopCollection,
|
D2D1::BrushProperties(aAlpha),
|
||||||
byRef(gradBrush));
|
stops->mStopCollection,
|
||||||
|
byRef(gradBrush));
|
||||||
|
|
||||||
return gradBrush;
|
return gradBrush;
|
||||||
} else if (aPattern.GetType() == PATTERN_SURFACE) {
|
} else if (aPattern.GetType() == PATTERN_SURFACE) {
|
||||||
RefPtr<ID2D1BitmapBrush> bmBrush;
|
RefPtr<ID2D1BitmapBrush> bmBrush;
|
||||||
|
@ -1687,6 +1708,133 @@ DrawTargetD2D::CreateStrokeStyleForOptions(const StrokeOptions &aStrokeOptions)
|
||||||
return style;
|
return style;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TemporaryRef<ID3D10Texture1D>
|
||||||
|
DrawTargetD2D::CreateGradientTexture(const GradientStopsD2D *aStops)
|
||||||
|
{
|
||||||
|
CD3D10_TEXTURE1D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, 4096, 1, 1);
|
||||||
|
|
||||||
|
std::vector<D2D1_GRADIENT_STOP> rawStops;
|
||||||
|
rawStops.resize(aStops->mStopCollection->GetGradientStopCount());
|
||||||
|
aStops->mStopCollection->GetGradientStops(&rawStops.front(), rawStops.size());
|
||||||
|
|
||||||
|
std::vector<unsigned char> textureData;
|
||||||
|
textureData.resize(4096 * 4);
|
||||||
|
unsigned char *texData = &textureData.front();
|
||||||
|
|
||||||
|
float prevColorPos = 0;
|
||||||
|
float nextColorPos = 1.0f;
|
||||||
|
D2D1_COLOR_F prevColor = rawStops[0].color;
|
||||||
|
D2D1_COLOR_F nextColor = prevColor;
|
||||||
|
|
||||||
|
if (rawStops.size() >= 2) {
|
||||||
|
nextColor = rawStops[1].color;
|
||||||
|
nextColorPos = rawStops[1].position;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t stopPosition = 2;
|
||||||
|
|
||||||
|
// Not the most optimized way but this will do for now.
|
||||||
|
for (int i = 0; i < 4096; i++) {
|
||||||
|
// The 4095 seems a little counter intuitive, but we want the gradient
|
||||||
|
// color at offset 0 at the first pixel, and at offset 1.0f at the last
|
||||||
|
// pixel.
|
||||||
|
float pos = float(i) / 4095;
|
||||||
|
|
||||||
|
if (pos > nextColorPos) {
|
||||||
|
prevColor = nextColor;
|
||||||
|
prevColorPos = nextColorPos;
|
||||||
|
if (rawStops.size() > stopPosition) {
|
||||||
|
nextColor = rawStops[stopPosition].color;
|
||||||
|
nextColorPos = rawStops[stopPosition++].position;
|
||||||
|
} else {
|
||||||
|
nextColorPos = 1.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float interp = (pos - prevColorPos) / (nextColorPos - prevColorPos);
|
||||||
|
|
||||||
|
Color newColor(prevColor.r + (nextColor.r - prevColor.r) * interp,
|
||||||
|
prevColor.g + (nextColor.g - prevColor.g) * interp,
|
||||||
|
prevColor.b + (nextColor.b - prevColor.b) * interp,
|
||||||
|
prevColor.a + (nextColor.a - prevColor.a) * interp);
|
||||||
|
|
||||||
|
texData[i * 4] = (char)(255.0f * newColor.b);
|
||||||
|
texData[i * 4 + 1] = (char)(255.0f * newColor.g);
|
||||||
|
texData[i * 4 + 2] = (char)(255.0f * newColor.r);
|
||||||
|
texData[i * 4 + 3] = (char)(255.0f * newColor.a);
|
||||||
|
}
|
||||||
|
|
||||||
|
D3D10_SUBRESOURCE_DATA data;
|
||||||
|
data.pSysMem = &textureData.front();
|
||||||
|
|
||||||
|
RefPtr<ID3D10Texture1D> tex;
|
||||||
|
mDevice->CreateTexture1D(&desc, &data, byRef(tex));
|
||||||
|
|
||||||
|
return tex;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DrawTargetD2D::SetupEffectForRadialGradient(const RadialGradientPattern *aPattern)
|
||||||
|
{
|
||||||
|
mPrivateData->mEffect->GetTechniqueByName("SampleRadialGradient")->GetPassByIndex(0)->Apply(0);
|
||||||
|
mPrivateData->mEffect->GetVariableByName("MaskTexCoords")->AsVector()->
|
||||||
|
SetFloatVector(ShaderConstantRectD3D10(0, 0, 1.0f, 1.0f));
|
||||||
|
|
||||||
|
float dimensions[] = { float(mSize.width), float(mSize.height), 0, 0 };
|
||||||
|
mPrivateData->mEffect->GetVariableByName("dimensions")->AsVector()->
|
||||||
|
SetFloatVector(dimensions);
|
||||||
|
|
||||||
|
const GradientStopsD2D *stops =
|
||||||
|
static_cast<const GradientStopsD2D*>(aPattern->mStops.get());
|
||||||
|
|
||||||
|
RefPtr<ID3D10Texture1D> tex = CreateGradientTexture(stops);
|
||||||
|
|
||||||
|
RefPtr<ID3D10ShaderResourceView> srView;
|
||||||
|
mDevice->CreateShaderResourceView(tex, NULL, byRef(srView));
|
||||||
|
|
||||||
|
mPrivateData->mEffect->GetVariableByName("tex")->AsShaderResource()->SetResource(srView);
|
||||||
|
|
||||||
|
Point dc = aPattern->mCenter2 - aPattern->mCenter1;
|
||||||
|
float dr = aPattern->mRadius2 - aPattern->mRadius1;
|
||||||
|
|
||||||
|
float diffv[] = { dc.x, dc.y, dr, 0 };
|
||||||
|
mPrivateData->mEffect->GetVariableByName("diff")->AsVector()->
|
||||||
|
SetFloatVector(diffv);
|
||||||
|
|
||||||
|
float center1[] = { aPattern->mCenter1.x, aPattern->mCenter1.y, dr, 0 };
|
||||||
|
mPrivateData->mEffect->GetVariableByName("center1")->AsVector()->
|
||||||
|
SetFloatVector(center1);
|
||||||
|
|
||||||
|
mPrivateData->mEffect->GetVariableByName("radius1")->AsScalar()->
|
||||||
|
SetFloat(aPattern->mRadius1);
|
||||||
|
mPrivateData->mEffect->GetVariableByName("sq_radius1")->AsScalar()->
|
||||||
|
SetFloat(pow(aPattern->mRadius1, 2));
|
||||||
|
|
||||||
|
Matrix invTransform = mTransform;
|
||||||
|
|
||||||
|
if (!invTransform.Invert()) {
|
||||||
|
// Bail if the matrix is singular.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
float matrix[] = { invTransform._11, invTransform._12, 0, 0,
|
||||||
|
invTransform._21, invTransform._22, 0, 0,
|
||||||
|
invTransform._31, invTransform._32, 1.0f, 0,
|
||||||
|
0, 0, 0, 1.0f };
|
||||||
|
|
||||||
|
mPrivateData->mEffect->GetVariableByName("DeviceSpaceToUserSpace")->
|
||||||
|
AsMatrix()->SetMatrix(matrix);
|
||||||
|
|
||||||
|
float A = dc.x * dc.x + dc.y * dc.y - dr * dr;
|
||||||
|
if (A == 0) {
|
||||||
|
mPrivateData->mEffect->GetTechniqueByName("SampleRadialGradient")->
|
||||||
|
GetPassByIndex(1)->Apply(0);
|
||||||
|
} else {
|
||||||
|
mPrivateData->mEffect->GetVariableByName("A")->AsScalar()->SetFloat(A);
|
||||||
|
mPrivateData->mEffect->GetTechniqueByName("SampleRadialGradient")->
|
||||||
|
GetPassByIndex(0)->Apply(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ID2D1Factory*
|
ID2D1Factory*
|
||||||
DrawTargetD2D::factory()
|
DrawTargetD2D::factory()
|
||||||
{
|
{
|
||||||
|
|
|
@ -50,6 +50,7 @@ namespace mozilla {
|
||||||
namespace gfx {
|
namespace gfx {
|
||||||
|
|
||||||
class SourceSurfaceD2DTarget;
|
class SourceSurfaceD2DTarget;
|
||||||
|
class GradientStopsD2D;
|
||||||
|
|
||||||
struct PrivateD3D10DataD2D
|
struct PrivateD3D10DataD2D
|
||||||
{
|
{
|
||||||
|
@ -154,9 +155,8 @@ private:
|
||||||
void MarkChanged();
|
void MarkChanged();
|
||||||
|
|
||||||
ID3D10BlendState *GetBlendStateForOperator(CompositionOp aOperator);
|
ID3D10BlendState *GetBlendStateForOperator(CompositionOp aOperator);
|
||||||
ID2D1RenderTarget *GetRTForOperator(CompositionOp aOperator);
|
ID2D1RenderTarget *GetRTForOperation(CompositionOp aOperator, const Pattern &aPattern);
|
||||||
void FinalizeRTForOperator(CompositionOp aOperator, const Rect &aBounds);
|
void FinalizeRTForOperation(CompositionOp aOperator, const Pattern &aPattern, const Rect &aBounds); void EnsureViews();
|
||||||
void EnsureViews();
|
|
||||||
void PopAllClips();
|
void PopAllClips();
|
||||||
|
|
||||||
TemporaryRef<ID2D1RenderTarget> CreateRTForTexture(ID3D10Texture2D *aTexture);
|
TemporaryRef<ID2D1RenderTarget> CreateRTForTexture(ID3D10Texture2D *aTexture);
|
||||||
|
@ -165,6 +165,12 @@ private:
|
||||||
TemporaryRef<ID2D1Brush> CreateBrushForPattern(const Pattern &aPattern, Float aAlpha = 1.0f);
|
TemporaryRef<ID2D1Brush> CreateBrushForPattern(const Pattern &aPattern, Float aAlpha = 1.0f);
|
||||||
TemporaryRef<ID2D1StrokeStyle> CreateStrokeStyleForOptions(const StrokeOptions &aStrokeOptions);
|
TemporaryRef<ID2D1StrokeStyle> CreateStrokeStyleForOptions(const StrokeOptions &aStrokeOptions);
|
||||||
|
|
||||||
|
TemporaryRef<ID3D10Texture1D> CreateGradientTexture(const GradientStopsD2D *aStops);
|
||||||
|
|
||||||
|
void SetupEffectForRadialGradient(const RadialGradientPattern *aPattern);
|
||||||
|
|
||||||
|
static const uint32_t test = 4;
|
||||||
|
|
||||||
IntSize mSize;
|
IntSize mSize;
|
||||||
|
|
||||||
RefPtr<ID3D10Device1> mDevice;
|
RefPtr<ID3D10Device1> mDevice;
|
||||||
|
|
|
@ -151,6 +151,29 @@ static inline int BytesPerPixel(SurfaceFormat aFormat)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool IsPatternSupportedByD2D(const Pattern &aPattern)
|
||||||
|
{
|
||||||
|
if (aPattern.GetType() != PATTERN_RADIAL_GRADIENT) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const RadialGradientPattern *pat =
|
||||||
|
static_cast<const RadialGradientPattern*>(&aPattern);
|
||||||
|
|
||||||
|
if (pat->mRadius1 != 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Point diff = pat->mCenter2 - pat->mCenter1;
|
||||||
|
|
||||||
|
if (sqrt(diff.x * diff.x + diff.y * diff.y) >= pat->mRadius2) {
|
||||||
|
// Inner point lies outside the circle.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This structure is used to pass rectangles to our shader constant. We can use
|
* This structure is used to pass rectangles to our shader constant. We can use
|
||||||
* this for passing rectangular areas to SetVertexShaderConstant. In the format
|
* this for passing rectangular areas to SetVertexShaderConstant. In the format
|
||||||
|
|
|
@ -24,6 +24,18 @@ cbuffer cb1
|
||||||
float4 ShadowColor;
|
float4 ShadowColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cbuffer cb2
|
||||||
|
{
|
||||||
|
float3x3 DeviceSpaceToUserSpace;
|
||||||
|
float2 dimensions;
|
||||||
|
// Precalculate as much as we can!
|
||||||
|
float3 diff;
|
||||||
|
float2 center1;
|
||||||
|
float A;
|
||||||
|
float radius1;
|
||||||
|
float sq_radius1;
|
||||||
|
}
|
||||||
|
|
||||||
struct VS_OUTPUT
|
struct VS_OUTPUT
|
||||||
{
|
{
|
||||||
float4 Position : SV_Position;
|
float4 Position : SV_Position;
|
||||||
|
@ -31,6 +43,13 @@ struct VS_OUTPUT
|
||||||
float2 MaskTexCoord : TEXCOORD1;
|
float2 MaskTexCoord : TEXCOORD1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct VS_RADIAL_OUTPUT
|
||||||
|
{
|
||||||
|
float4 Position : SV_Position;
|
||||||
|
float2 MaskTexCoord : TEXCOORD0;
|
||||||
|
float2 PixelCoord : TEXCOORD1;
|
||||||
|
};
|
||||||
|
|
||||||
Texture2D tex;
|
Texture2D tex;
|
||||||
Texture2D mask;
|
Texture2D mask;
|
||||||
|
|
||||||
|
@ -94,6 +113,25 @@ VS_OUTPUT SampleTextureVS(float3 pos : POSITION)
|
||||||
return Output;
|
return Output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VS_RADIAL_OUTPUT SampleRadialVS(float3 pos : POSITION)
|
||||||
|
{
|
||||||
|
VS_RADIAL_OUTPUT Output;
|
||||||
|
Output.Position.w = 1.0f;
|
||||||
|
Output.Position.x = pos.x * QuadDesc.z + QuadDesc.x;
|
||||||
|
Output.Position.y = pos.y * QuadDesc.w + QuadDesc.y;
|
||||||
|
Output.Position.z = 0;
|
||||||
|
Output.MaskTexCoord.x = pos.x * MaskTexCoords.z + MaskTexCoords.x;
|
||||||
|
Output.MaskTexCoord.y = pos.y * MaskTexCoords.w + MaskTexCoords.y;
|
||||||
|
|
||||||
|
// For the radial gradient pixel shader we need to pass in the pixel's
|
||||||
|
// coordinates in user space for the color to be correctly determined.
|
||||||
|
|
||||||
|
Output.PixelCoord.x = ((Output.Position.x + 1.0f) / 2.0f) * dimensions.x;
|
||||||
|
Output.PixelCoord.y = ((1.0f - Output.Position.y) / 2.0f) * dimensions.y;
|
||||||
|
Output.PixelCoord.xy = mul(float3(Output.PixelCoord.x, Output.PixelCoord.y, 1.0f), DeviceSpaceToUserSpace).xy;
|
||||||
|
return Output;
|
||||||
|
}
|
||||||
|
|
||||||
float4 SampleTexturePS( VS_OUTPUT In) : SV_Target
|
float4 SampleTexturePS( VS_OUTPUT In) : SV_Target
|
||||||
{
|
{
|
||||||
return tex.Sample(sSampler, In.TexCoord);
|
return tex.Sample(sSampler, In.TexCoord);
|
||||||
|
@ -104,6 +142,68 @@ float4 SampleMaskTexturePS( VS_OUTPUT In) : SV_Target
|
||||||
return tex.Sample(sSampler, In.TexCoord) * mask.Sample(sMaskSampler, In.MaskTexCoord).a;
|
return tex.Sample(sSampler, In.TexCoord) * mask.Sample(sMaskSampler, In.MaskTexCoord).a;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
float4 SampleRadialGradientPS( VS_RADIAL_OUTPUT In) : SV_Target
|
||||||
|
{
|
||||||
|
// Radial gradient painting is defined as the set of circles whose centers
|
||||||
|
// are described by C(t) = (C2 - C1) * t + C1; with radii
|
||||||
|
// R(t) = (R2 - R1) * t + R1; for R(t) > 0. This shader solves the
|
||||||
|
// quadratic equation that arises when calculating t for pixel (x, y).
|
||||||
|
//
|
||||||
|
// A more extensive derrivation can be found in the pixman radial gradient
|
||||||
|
// code.
|
||||||
|
|
||||||
|
float2 p = In.PixelCoord;
|
||||||
|
float3 dp = float3(p - center1, radius1);
|
||||||
|
|
||||||
|
// dpx * dcx + dpy * dcy + r * dr
|
||||||
|
float B = dot(dp, diff);
|
||||||
|
|
||||||
|
float C = pow(dp.x, 2) + pow(dp.y, 2) - sq_radius1;
|
||||||
|
|
||||||
|
float det = pow(B, 2) - A * C;
|
||||||
|
|
||||||
|
if (det < 0) {
|
||||||
|
return float4(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
float sqrt_det = sqrt(abs(det));
|
||||||
|
|
||||||
|
float2 t = (B + float2(sqrt_det, -sqrt_det)) / A;
|
||||||
|
|
||||||
|
float2 isValid = step(float2(-radius1, -radius1), t * diff.z);
|
||||||
|
|
||||||
|
if (max(isValid.x, isValid.y) <= 0) {
|
||||||
|
return float4(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
float upper_t = lerp(t.y, t.x, isValid.x);
|
||||||
|
|
||||||
|
// Multiply the output color by the input mask for the operation.
|
||||||
|
return tex.Sample(sSampler, float2(upper_t, 0.5)) * mask.Sample(sMaskSampler, In.MaskTexCoord).a;
|
||||||
|
};
|
||||||
|
|
||||||
|
float4 SampleRadialGradientA0PS( VS_RADIAL_OUTPUT In) : SV_Target
|
||||||
|
{
|
||||||
|
// This simpler shader is used for the degenerate case where A is 0,
|
||||||
|
// i.e. we're actually solving a linear equation.
|
||||||
|
|
||||||
|
float2 p = In.PixelCoord;
|
||||||
|
float3 dp = float3(p - center1, radius1);
|
||||||
|
|
||||||
|
// dpx * dcx + dpy * dcy + r * dr
|
||||||
|
float B = dot(dp, diff);
|
||||||
|
|
||||||
|
float C = pow(dp.x, 2) + pow(dp.y, 2) - pow(radius1, 2);
|
||||||
|
|
||||||
|
float t = 0.5 * C / B;
|
||||||
|
|
||||||
|
if (-radius1 >= t * diff.z) {
|
||||||
|
return float4(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return tex.Sample(sSampler, float2(t, 0.5)) * mask.Sample(sMaskSampler, In.MaskTexCoord).a;
|
||||||
|
};
|
||||||
|
|
||||||
float4 SampleShadowHPS( VS_OUTPUT In) : SV_Target
|
float4 SampleShadowHPS( VS_OUTPUT In) : SV_Target
|
||||||
{
|
{
|
||||||
float outputStrength = 0;
|
float outputStrength = 0;
|
||||||
|
@ -166,6 +266,24 @@ technique10 SampleTexture
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
technique10 SampleRadialGradient
|
||||||
|
{
|
||||||
|
pass P0
|
||||||
|
{
|
||||||
|
SetRasterizerState(TextureRast);
|
||||||
|
SetVertexShader(CompileShader(vs_4_0_level_9_3, SampleRadialVS()));
|
||||||
|
SetGeometryShader(NULL);
|
||||||
|
SetPixelShader(CompileShader(ps_4_0_level_9_3, SampleRadialGradientPS()));
|
||||||
|
}
|
||||||
|
pass P1
|
||||||
|
{
|
||||||
|
SetRasterizerState(TextureRast);
|
||||||
|
SetVertexShader(CompileShader(vs_4_0_level_9_3, SampleRadialVS()));
|
||||||
|
SetGeometryShader(NULL);
|
||||||
|
SetPixelShader(CompileShader(ps_4_0_level_9_3, SampleRadialGradientA0PS()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
technique10 SampleMaskedTexture
|
technique10 SampleMaskedTexture
|
||||||
{
|
{
|
||||||
pass P0
|
pass P0
|
||||||
|
|
6492
gfx/2d/ShadersD2D.h
6492
gfx/2d/ShadersD2D.h
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Загрузка…
Ссылка в новой задаче