Bug 719286 - Add support for -moz-objectFillOpacity and -moz-objectStrokeOpacity to SVG *-opacity fields in SVG glyphs r=roc

This commit is contained in:
Edwin Flores 2012-09-06 16:58:47 +12:00
parent f5a2675bcf
commit 1b4129c7f5
7 changed files with 111 additions and 21 deletions

View File

@ -70,6 +70,8 @@ mozilla::gfx::UserDataKey gfxTextObjectPaint::sUserDataKey;
const float gfxSVGGlyphs::SVG_UNITS_PER_EM = 1000.0f;
const gfxRGBA SimpleTextObjectPaint::sZero = gfxRGBA(0.0f, 0.0f, 0.0f, 0.0f);
/* static */ gfxSVGGlyphs*
gfxSVGGlyphs::ParseFromBuffer(uint8_t *aBuffer, uint32_t aBufLen)
{

View File

@ -117,11 +117,20 @@ public:
* Get outer text object pattern with the specified opacity value.
* This lets us inherit paints and paint opacities (i.e. fill/stroke and
* fill-opacity/stroke-opacity) separately.
*
* Deferred opacity to be actually implemented in a later patch
*/
virtual already_AddRefed<gfxPattern> GetFillPattern(float aOpacity = 1.0f) = 0;
virtual already_AddRefed<gfxPattern> GetStrokePattern(float aOpacity = 1.0f) = 0;
virtual already_AddRefed<gfxPattern> GetFillPattern(float aOpacity) = 0;
virtual already_AddRefed<gfxPattern> GetStrokePattern(float aOpacity) = 0;
virtual float GetFillOpacity() { return 1.0f; }
virtual float GetStrokeOpacity() { return 1.0f; }
already_AddRefed<gfxPattern> GetFillPattern() {
return GetFillPattern(GetFillOpacity());
}
already_AddRefed<gfxPattern> GetStrokePattern() {
return GetStrokePattern(GetStrokeOpacity());
}
virtual ~gfxTextObjectPaint() { }
};
@ -132,9 +141,13 @@ public:
*/
class SimpleTextObjectPaint : public gfxTextObjectPaint
{
private:
static const gfxRGBA sZero;
public:
SimpleTextObjectPaint(gfxPattern *aFillPattern, gfxPattern *aStrokePattern) :
mFillPattern(aFillPattern), mStrokePattern(aStrokePattern),
mFillPattern(aFillPattern ? aFillPattern : new gfxPattern(sZero)),
mStrokePattern(aStrokePattern ? aStrokePattern : new gfxPattern(sZero)),
mFillMatrix(aFillPattern ? aFillPattern->GetMatrix() : gfxMatrix()),
mStrokeMatrix(aStrokePattern ? aStrokePattern->GetMatrix() : gfxMatrix())
{
@ -156,6 +169,14 @@ public:
return strokePattern.forget();
}
float GetFillOpacity() {
return mFillPattern ? 1.0f : 0.0f;
}
float GetStrokeOpacity() {
return mStrokePattern ? 1.0f : 0.0f;
}
private:
nsRefPtr<gfxPattern> mFillPattern;
nsRefPtr<gfxPattern> mStrokePattern;

View File

@ -955,8 +955,7 @@ nsSVGGlyphFrame::SetupCairoState(gfxContext *aContext,
DrawMode toDraw = DrawMode(0);
SVGTextObjectPaint *thisObjectPaint = new SVGTextObjectPaint();
if (nsSVGUtils::HasStroke(this)) {
SetupCairoStroke(aContext, aOuterObjectPaint, thisObjectPaint);
if (SetupCairoStroke(aContext, aOuterObjectPaint, thisObjectPaint)) {
toDraw = DrawMode(toDraw | gfxFont::GLYPH_STROKE);
}
@ -969,22 +968,32 @@ nsSVGGlyphFrame::SetupCairoState(gfxContext *aContext,
return toDraw;
}
void
bool
nsSVGGlyphFrame::SetupCairoStroke(gfxContext *aContext,
gfxTextObjectPaint *aOuterObjectPaint,
SVGTextObjectPaint *aThisObjectPaint)
{
const nsStyleSVG *style = GetStyleSVG();
if (style->mStroke.mType == eStyleSVGPaintType_None) {
aThisObjectPaint->SetStrokeOpacity(0.0f);
return false;
}
gfxContextMatrixAutoSaveRestore matrixRestore(aContext);
aContext->IdentityMatrix();
SetupCairoStrokeHitGeometry(aContext);
float opacity = style->mStrokeOpacity;
nsSVGUtils::SetupCairoStrokeHitGeometry(this, aContext);
float opacity = nsSVGUtils::GetOpacity(style->mStrokeOpacitySource,
style->mStrokeOpacity,
aOuterObjectPaint);
SetupInheritablePaint(aContext, opacity, aOuterObjectPaint,
aThisObjectPaint->mStrokePaint, &nsStyleSVG::mStroke,
nsSVGEffects::StrokeProperty());
aThisObjectPaint->SetStrokeOpacity(opacity);
return opacity != 0.0f;
}
bool
@ -994,21 +1003,26 @@ nsSVGGlyphFrame::SetupCairoFill(gfxContext *aContext,
{
const nsStyleSVG *style = GetStyleSVG();
if (style->mFill.mType == eStyleSVGPaintType_None) {
aThisObjectPaint->SetFillOpacity(0.0f);
return false;
}
float opacity = style->mFillOpacity;
float opacity = nsSVGUtils::GetOpacity(style->mFillOpacitySource,
style->mFillOpacity,
aOuterObjectPaint);
SetupInheritablePaint(aContext, opacity, aOuterObjectPaint,
aThisObjectPaint->mFillPaint, &nsStyleSVG::mFill,
nsSVGEffects::FillProperty());
aThisObjectPaint->SetFillOpacity(opacity);
return true;
}
void
nsSVGGlyphFrame::SetupInheritablePaint(gfxContext *aContext,
float aOpacity,
float& aOpacity,
gfxTextObjectPaint *aOuterObjectPaint,
SVGTextObjectPaint::Paint& aTargetPaint,
nsStyleSVGPaint nsStyleSVG::*aFillOrStroke,
@ -1038,7 +1052,7 @@ nsSVGGlyphFrame::SetupInheritablePaint(gfxContext *aContext,
bool
nsSVGGlyphFrame::SetupObjectPaint(gfxContext *aContext,
nsStyleSVGPaint nsStyleSVG::*aFillOrStroke,
float aOpacity,
float& aOpacity,
gfxTextObjectPaint *aOuterObjectPaint)
{
const nsStyleSVG *style = GetStyleSVG();

View File

@ -275,6 +275,12 @@ private:
already_AddRefed<gfxPattern> GetFillPattern(float opacity);
already_AddRefed<gfxPattern> GetStrokePattern(float opacity);
void SetFillOpacity(float aOpacity) { mFillOpacity = aOpacity; }
float GetFillOpacity() { return mFillOpacity; }
void SetStrokeOpacity(float aOpacity) { mStrokeOpacity = aOpacity; }
float GetStrokeOpacity() { return mStrokeOpacity; }
struct Paint {
Paint() {
mPatternCache.Init();
@ -321,13 +327,16 @@ private:
Paint mFillPaint;
Paint mStrokePaint;
float mFillOpacity;
float mStrokeOpacity;
};
/**
* Sets up the stroke style in |aContext| and stores stroke pattern
* information in |aThisObjectPaint|.
*/
void SetupCairoStroke(gfxContext *aContext,
bool SetupCairoStroke(gfxContext *aContext,
gfxTextObjectPaint *aOuterObjectPaint,
SVGTextObjectPaint *aThisObjectPaint);
@ -341,7 +350,8 @@ private:
/**
* Sets the current pattern to the fill or stroke style of the outer text
* object.
* object. Will also set the paint opacity to transparent if the paint is set
* to "none".
*/
bool SetupObjectPaint(gfxContext *aContext,
nsStyleSVGPaint nsStyleSVG::*aFillOrStroke,
@ -350,7 +360,8 @@ private:
/**
* Stores in |aTargetPaint| information on how to reconstruct the current
* fill or stroke pattern.
* fill or stroke pattern. Will also set the paint opacity to transparent if
* the paint is set to "none".
* @param aOuterObjectPaint pattern information from the outer text object
* @param aTargetPaint where to store the current pattern information
* @param aFillOrStroke member pointer to the paint we are setting up
@ -358,7 +369,7 @@ private:
* server frame
*/
void SetupInheritablePaint(gfxContext *aContext,
float aOpacity,
float& aOpacity,
gfxTextObjectPaint *aOuterObjectPaint,
SVGTextObjectPaint::Paint& aTargetPaint,
nsStyleSVGPaint nsStyleSVG::*aFillOrStroke,

View File

@ -1905,10 +1905,10 @@ nsSVGUtils::SetupObjectPaint(gfxContext *aContext,
switch (aPaint.mType) {
case eStyleSVGPaintType_ObjectFill:
pattern = aObjectPaint->GetFillPattern();
pattern = aObjectPaint->GetFillPattern(aOpacity);
break;
case eStyleSVGPaintType_ObjectStroke:
pattern = aObjectPaint->GetStrokePattern();
pattern = aObjectPaint->GetStrokePattern(aOpacity);
break;
default:
return false;
@ -1939,7 +1939,10 @@ nsSVGUtils::SetupCairoFillPaint(nsIFrame *aFrame, gfxContext* aContext,
else
aContext->SetFillRule(gfxContext::FILL_RULE_WINDING);
float opacity = MaybeOptimizeOpacity(aFrame, style->mFillOpacity);
float opacity = MaybeOptimizeOpacity(aFrame,
GetOpacity(style->mFillOpacitySource,
style->mFillOpacity,
aObjectPaint));
nsSVGPaintServerFrame *ps =
nsSVGEffects::GetPaintServer(aFrame, &style->mFill, nsSVGEffects::FillProperty());
if (ps && ps->SetupPaintServer(aContext, aFrame, &nsStyleSVG::mFill, opacity))
@ -1966,7 +1969,10 @@ nsSVGUtils::SetupCairoStrokePaint(nsIFrame *aFrame, gfxContext* aContext,
if (style->mStroke.mType == eStyleSVGPaintType_None)
return false;
float opacity = MaybeOptimizeOpacity(aFrame, style->mStrokeOpacity);
float opacity = MaybeOptimizeOpacity(aFrame,
GetOpacity(style->mStrokeOpacitySource,
style->mStrokeOpacity,
aObjectPaint));
nsSVGPaintServerFrame *ps =
nsSVGEffects::GetPaintServer(aFrame, &style->mStroke, nsSVGEffects::StrokeProperty());
@ -1986,6 +1992,36 @@ nsSVGUtils::SetupCairoStrokePaint(nsIFrame *aFrame, gfxContext* aContext,
return true;
}
/* static */ float
nsSVGUtils::GetOpacity(nsStyleSVGOpacitySource aOpacityType,
const float& aOpacity,
gfxTextObjectPaint *aOuterObjectPaint)
{
float opacity = 1.0f;
switch (aOpacityType) {
case eStyleSVGOpacitySource_Normal:
opacity = aOpacity;
break;
case eStyleSVGOpacitySource_ObjectFillOpacity:
if (aOuterObjectPaint) {
opacity = aOuterObjectPaint->GetFillOpacity();
} else {
NS_WARNING("objectFillOpacity used outside of an SVG glyph");
}
break;
case eStyleSVGOpacitySource_ObjectStrokeOpacity:
if (aOuterObjectPaint) {
opacity = aOuterObjectPaint->GetStrokeOpacity();
} else {
NS_WARNING("objectStrokeOpacity used outside of an SVG glyph");
}
break;
default:
NS_NOTREACHED("Unknown object opacity inheritance type for SVG glyph");
}
return opacity;
}
bool
nsSVGUtils::HasStroke(nsIFrame* aFrame)
{

View File

@ -702,6 +702,10 @@ public:
static bool SetupCairoStrokePaint(nsIFrame* aFrame, gfxContext* aContext,
gfxTextObjectPaint *aObjectPaint = nullptr);
static float GetOpacity(nsStyleSVGOpacitySource aOpacityType,
const float& aOpacity,
gfxTextObjectPaint *aOuterObjectPaint);
/*
* @return false if there is no stroke
*/

View File

@ -21,7 +21,9 @@ svg:not(:root), symbol, image, marker, pattern, foreignObject {
@media all and (-moz-is-glyph) {
:root {
fill: -moz-objectfill;
fill-opacity: -moz-objectfillopacity;
stroke: -moz-objectstroke;
stroke-opacity: -moz-objectstrokeopacity;
}
}