mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 03:15:11 +00:00
Bug 719286 - Add support for -moz-objectFillOpacity and -moz-objectStrokeOpacity to SVG *-opacity fields in SVG glyphs r=roc
This commit is contained in:
parent
f5a2675bcf
commit
1b4129c7f5
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user