Bug 307708 � filters should operate in linearRGB color space by default r=dbaron,r=tor,sr=roc

This commit is contained in:
longsonr%gmail.com 2007-01-30 13:19:55 +00:00
Родитель bb79257e15
Коммит 84928d38d8
31 изменённых файлов: 420 добавлений и 125 удалений

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

@ -908,7 +908,9 @@ GK_ATOM(clip_rule, "clip-rule")
GK_ATOM(clipPath, "clipPath")
GK_ATOM(clipPathUnits, "clipPathUnits")
GK_ATOM(cm, "cm")
GK_ATOM(colorProfile,"color-profile")
GK_ATOM(colorInterpolation, "color-interpolation")
GK_ATOM(colorInterpolationFilters, "color-interpolation-filters")
GK_ATOM(colorProfile, "color-profile")
GK_ATOM(cursor, "cursor")
GK_ATOM(cx, "cx")
GK_ATOM(cy, "cy")
@ -1004,6 +1006,7 @@ GK_ATOM(letter_spacing, "letter-spacing")
GK_ATOM(lighten, "lighten")
GK_ATOM(linear, "linear")
GK_ATOM(linearGradient, "linearGradient")
GK_ATOM(linearRGB, "linearRGB")
GK_ATOM(magnify, "magnify")
GK_ATOM(marker, "marker")
GK_ATOM(marker_end, "marker-end")
@ -1073,6 +1076,7 @@ GK_ATOM(skewY, "skewY")
GK_ATOM(slope, "slope")
GK_ATOM(spacing, "spacing")
GK_ATOM(spreadMethod, "spreadMethod")
GK_ATOM(sRGB, "sRGB")
GK_ATOM(startOffset, "startOffset")
GK_ATOM(stdDeviation, "stdDeviation")
GK_ATOM(stitch, "stitch")

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

@ -110,6 +110,7 @@ nsSVGDefsElement::IsAttributeMapped(const nsIAtom* name) const
{
static const MappedAttributeEntry* const map[] = {
sFEFloodMap,
sFiltersMap,
sFontSpecificationMap,
sGradientStopMap,
sMarkersMap,

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

@ -420,6 +420,7 @@ nsSVGElement::sFillStrokeMap[] = {
nsSVGElement::sGraphicsMap[] = {
{ &nsGkAtoms::clip_path },
{ &nsGkAtoms::clip_rule },
{ &nsGkAtoms::colorInterpolation },
{ &nsGkAtoms::cursor },
{ &nsGkAtoms::display },
{ &nsGkAtoms::filter },
@ -496,6 +497,13 @@ nsSVGElement::sColorMap[] = {
{ nsnull }
};
// PresentationAttributes-Filters
/* static */ const nsGenericElement::MappedAttributeEntry
nsSVGElement::sFiltersMap[] = {
{ &nsGkAtoms::colorInterpolationFilters },
{ nsnull }
};
// PresentationAttributes-feFlood
/* static */ const nsGenericElement::MappedAttributeEntry
nsSVGElement::sFEFloodMap[] = {

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

@ -98,6 +98,7 @@ public:
static const MappedAttributeEntry sViewportsMap[];
static const MappedAttributeEntry sMarkersMap[];
static const MappedAttributeEntry sColorMap[];
static const MappedAttributeEntry sFiltersMap[];
static const MappedAttributeEntry sFEFloodMap[];
// nsIDOMNode

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

@ -267,6 +267,7 @@ nsSVGFilterElement::IsAttributeMapped(const nsIAtom* name) const
{
static const MappedAttributeEntry* const map[] = {
sFEFloodMap,
sFiltersMap,
sFontSpecificationMap,
sGradientStopMap,
sMarkersMap,

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

@ -165,6 +165,25 @@ nsSVGFE::ScanDualValueAttribute(const nsAString& aValue, nsIAtom* aAttribute,
return PR_TRUE;
}
nsSVGFilterInstance::ColorModel
nsSVGFE::GetColorModel(nsSVGFilterInstance::ColorModel::AlphaChannel aAlphaChannel)
{
nsSVGFilterInstance::ColorModel
colorModel(nsSVGFilterInstance::ColorModel::LINEAR_RGB,
aAlphaChannel);
nsIFrame* frame = GetPrimaryFrame();
if (!frame)
return colorModel;
nsStyleContext* style = frame->GetStyleContext();
if (style->GetStyleSVG()->mColorInterpolationFilters ==
NS_STYLE_COLOR_INTERPOLATION_SRGB)
colorModel.mColorSpace = nsSVGFilterInstance::ColorModel::SRGB;
return colorModel;
}
//----------------------------------------------------------------------
// nsIDOMSVGFilterPrimitiveStandardAttributes methods
@ -246,7 +265,8 @@ class nsSVGFilterResource
{
public:
nsSVGFilterResource(nsSVGFilterInstance* aInstance);
nsSVGFilterResource(nsSVGFilterInstance* aInstance,
const nsSVGFilterInstance::ColorModel &aColorModel);
~nsSVGFilterResource();
/*
@ -316,16 +336,19 @@ private:
PRUint8 *mSourceData, *mTargetData;
PRUint32 mWidth, mHeight;
PRInt32 mStride;
nsSVGFilterInstance::ColorModel mColorModel;
};
nsSVGFilterResource::nsSVGFilterResource(nsSVGFilterInstance* aInstance):
nsSVGFilterResource::nsSVGFilterResource(nsSVGFilterInstance* aInstance,
const nsSVGFilterInstance::ColorModel &aColorModel) :
mTargetImage(nsnull),
mInstance(aInstance),
mSourceData(nsnull),
mTargetData(nsnull),
mWidth(0),
mHeight(0),
mStride(0)
mStride(0),
mColorModel(aColorModel)
{
}
@ -343,7 +366,7 @@ nsSVGFilterResource::AcquireSourceImage(nsIDOMSVGAnimatedString* aIn,
nsRect defaultRect;
cairo_surface_t *surface;
mInstance->LookupImage(mInput, &surface, &defaultRect);
mInstance->LookupImage(mInput, &surface, &defaultRect, mColorModel);
if (!surface) {
return NS_ERROR_FAILURE;
}
@ -390,7 +413,7 @@ nsSVGFilterResource::ReleaseTarget()
return;
}
FixupTarget();
mInstance->DefineImage(mResult, mTargetImage, mRect);
mInstance->DefineImage(mResult, mTargetImage, mRect, mColorModel);
// filter instance now owns the image
cairo_surface_destroy(mTargetImage);
@ -740,7 +763,8 @@ nsSVGFEGaussianBlurElement::Filter(nsSVGFilterInstance *instance)
{
nsresult rv;
PRUint8 *sourceData, *targetData;
nsSVGFilterResource fr(instance);
nsSVGFilterResource fr(instance,
GetColorModel(nsSVGFilterInstance::ColorModel::PREMULTIPLIED));
rv = fr.AcquireSourceImage(mIn1, this, &sourceData);
NS_ENSURE_SUCCESS(rv, rv);
@ -962,7 +986,8 @@ nsSVGFEBlendElement::Filter(nsSVGFilterInstance *instance)
{
nsresult rv;
PRUint8 *sourceData, *targetData;
nsSVGFilterResource fr(instance);
nsSVGFilterResource fr(instance,
GetColorModel(nsSVGFilterInstance::ColorModel::PREMULTIPLIED));
rv = fr.AcquireSourceImage(mIn1, this, &sourceData);
NS_ENSURE_SUCCESS(rv, rv);
@ -1237,7 +1262,8 @@ nsSVGFECompositeElement::Filter(nsSVGFilterInstance *instance)
PRUint8 *sourceData, *targetData;
cairo_surface_t *sourceSurface, *targetSurface;
nsSVGFilterResource fr(instance);
nsSVGFilterResource fr(instance,
GetColorModel(nsSVGFilterInstance::ColorModel::PREMULTIPLIED));
rv = fr.AcquireSourceImage(mIn2, this, &sourceData, &sourceSurface);
NS_ENSURE_SUCCESS(rv, rv);
rv = fr.AcquireTargetImage(mResult, &targetData, &targetSurface);
@ -1446,7 +1472,8 @@ nsSVGFEComponentTransferElement::Filter(nsSVGFilterInstance *instance)
{
nsresult rv;
PRUint8 *sourceData, *targetData;
nsSVGFilterResource fr(instance);
nsSVGFilterResource fr(instance,
GetColorModel(nsSVGFilterInstance::ColorModel::UNPREMULTIPLIED));
rv = fr.AcquireSourceImage(mIn1, this, &sourceData);
NS_ENSURE_SUCCESS(rv, rv);
@ -1483,20 +1510,10 @@ nsSVGFEComponentTransferElement::Filter(nsSVGFilterInstance *instance)
for (PRInt32 y = rect.y; y < rect.y + rect.height; y++)
for (PRInt32 x = rect.x; x < rect.x + rect.width; x++) {
PRInt32 targIndex = y * stride + x * 4;
PRUint8 r, g, b, a;
a = sourceData[targIndex + 3];
if (a) {
b = tableB[(255 * (PRUint32)sourceData[targIndex]) / a];
g = tableG[(255 * (PRUint32)sourceData[targIndex + 1]) / a];
r = tableR[(255 * (PRUint32)sourceData[targIndex + 2]) / a];
} else {
b = g = r = 0;
}
a = tableA[a];
FAST_DIVIDE_BY_255(targetData[targIndex], b * a);
FAST_DIVIDE_BY_255(targetData[targIndex + 1], g * a);
FAST_DIVIDE_BY_255(targetData[targIndex + 2], r * a);
targetData[targIndex + 3] = a;
targetData[targIndex] = tableB[sourceData[targIndex]];
targetData[targIndex + 1] = tableG[sourceData[targIndex + 1]];
targetData[targIndex + 2] = tableR[sourceData[targIndex + 2]];
targetData[targIndex + 3] = tableA[sourceData[targIndex + 3]];
}
return NS_OK;
}
@ -2084,7 +2101,8 @@ nsSVGFEMergeElement::Filter(nsSVGFilterInstance *instance)
PRUint8 *sourceData, *targetData;
cairo_surface_t *sourceSurface, *targetSurface;
nsSVGFilterResource fr(instance);
nsSVGFilterResource fr(instance,
GetColorModel(nsSVGFilterInstance::ColorModel::PREMULTIPLIED));
rv = fr.AcquireTargetImage(mResult, &targetData, &targetSurface);
NS_ENSURE_SUCCESS(rv, rv);
@ -2420,7 +2438,8 @@ nsSVGFEOffsetElement::Filter(nsSVGFilterInstance *instance)
{
nsresult rv;
PRUint8 *sourceData, *targetData;
nsSVGFilterResource fr(instance);
nsSVGFilterResource fr(instance,
GetColorModel(nsSVGFilterInstance::ColorModel::PREMULTIPLIED));
rv = fr.AcquireSourceImage(mIn1, this, &sourceData);
NS_ENSURE_SUCCESS(rv, rv);
@ -2588,7 +2607,11 @@ nsSVGFEFloodElement::Filter(nsSVGFilterInstance *instance)
nsresult rv;
PRUint8 *sourceData, *targetData;
cairo_surface_t *targetSurface;
nsSVGFilterResource fr(instance);
// flood colour is sRGB
nsSVGFilterInstance::ColorModel
colorModel(nsSVGFilterInstance::ColorModel::SRGB,
nsSVGFilterInstance::ColorModel::PREMULTIPLIED);
nsSVGFilterResource fr(instance, colorModel);
rv = fr.AcquireSourceImage(mIn1, this, &sourceData);
NS_ENSURE_SUCCESS(rv, rv);
@ -2633,7 +2656,8 @@ NS_IMETHODIMP_(PRBool)
nsSVGFEFloodElement::IsAttributeMapped(const nsIAtom* name) const
{
static const MappedAttributeEntry* const map[] = {
sFEFloodMap
sFEFloodMap,
sFiltersMap
};
return FindAttributeDependence(name, map, NS_ARRAY_LENGTH(map)) ||
@ -2918,7 +2942,8 @@ nsSVGFETurbulenceElement::Filter(nsSVGFilterInstance *instance)
{
nsresult rv;
PRUint8 *sourceData, *targetData;
nsSVGFilterResource fr(instance);
nsSVGFilterResource fr(instance,
GetColorModel(nsSVGFilterInstance::ColorModel::PREMULTIPLIED));
nsIDOMSVGAnimatedString* sourceGraphic = nsnull;
rv = NS_NewSVGAnimatedString(&sourceGraphic);
@ -3383,7 +3408,8 @@ nsSVGFEMorphologyElement::Filter(nsSVGFilterInstance *instance)
{
nsresult rv;
PRUint8 *sourceData, *targetData;
nsSVGFilterResource fr(instance);
nsSVGFilterResource fr(instance,
GetColorModel(nsSVGFilterInstance::ColorModel::PREMULTIPLIED));
rv = fr.AcquireSourceImage(mIn1, this, &sourceData);
NS_ENSURE_SUCCESS(rv, rv);

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

@ -61,6 +61,9 @@ protected:
NumberInfo* aInfo1, NumberInfo* aInfo2,
nsAttrValue& aResult);
nsSVGFilterInstance::ColorModel
GetColorModel(nsSVGFilterInstance::ColorModel::AlphaChannel aAlphaChannel);
public:
// interfaces:
NS_DECL_ISUPPORTS_INHERITED

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

@ -114,6 +114,7 @@ nsSVGForeignObjectElement::IsAttributeMapped(const nsIAtom* name) const
{
static const MappedAttributeEntry* const map[] = {
sFEFloodMap,
sFiltersMap,
sFontSpecificationMap,
sGradientStopMap,
sMarkersMap,

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

@ -111,10 +111,11 @@ NS_IMETHODIMP_(PRBool)
nsSVGGElement::IsAttributeMapped(const nsIAtom* name) const
{
static const MappedAttributeEntry* const map[] = {
sTextContentElementsMap,
sFontSpecificationMap,
sColorMap,
sFEFloodMap
sFEFloodMap,
sFiltersMap,
sFontSpecificationMap,
sTextContentElementsMap,
};
return FindAttributeDependence(name, map, NS_ARRAY_LENGTH(map)) ||

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

@ -290,6 +290,7 @@ nsSVGMarkerElement::IsAttributeMapped(const nsIAtom* name) const
{
static const MappedAttributeEntry* const map[] = {
sFEFloodMap,
sFiltersMap,
sFontSpecificationMap,
sGradientStopMap,
sMarkersMap,

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

@ -184,6 +184,7 @@ nsSVGMaskElement::IsAttributeMapped(const nsIAtom* name) const
{
static const MappedAttributeEntry* const map[] = {
sFEFloodMap,
sFiltersMap,
sFontSpecificationMap,
sGradientStopMap,
sMarkersMap,

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

@ -280,6 +280,7 @@ nsSVGPatternElement::IsAttributeMapped(const nsIAtom* name) const
{
static const MappedAttributeEntry* const map[] = {
sFEFloodMap,
sFiltersMap,
sFontSpecificationMap,
sGradientStopMap,
sMarkersMap,

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

@ -1114,6 +1114,7 @@ nsSVGSVGElement::IsAttributeMapped(const nsIAtom* name) const
static const MappedAttributeEntry* const map[] = {
sColorMap,
sFEFloodMap,
sFiltersMap,
sFillStrokeMap,
sFontSpecificationMap,
sGradientStopMap,

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

@ -174,6 +174,7 @@ nsSVGSymbolElement::IsAttributeMapped(const nsIAtom* name) const
{
static const MappedAttributeEntry* const map[] = {
sFEFloodMap,
sFiltersMap,
sFontSpecificationMap,
sGradientStopMap,
sMarkersMap,

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

@ -578,6 +578,7 @@ nsSVGUseElement::IsAttributeMapped(const nsIAtom* name) const
{
static const MappedAttributeEntry* const map[] = {
sFEFloodMap,
sFiltersMap,
sFontSpecificationMap,
sGradientStopMap,
sMarkersMap,

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

@ -637,11 +637,7 @@
#define NS_STYLE_COLUMN_COUNT_UNLIMITED (-1)
#ifdef MOZ_SVG
// Some of our constants must map to the same values as those defined in
// nsISVG{,Path,Glyph}GeometrySource.idl/
// I don't want to add a dependency on the SVG module
// everywhere by #include'ing nsISVG{,Path,Glyph}GeometrySource.h, so these consts
// have to be kept in sync manually.
// See nsStyleSVG
// dominant-baseline
#define NS_STYLE_DOMINANT_BASELINE_AUTO 0
@ -658,8 +654,8 @@
#define NS_STYLE_DOMINANT_BASELINE_TEXT_BEFORE_EDGE 11
// fill-rule
#define NS_STYLE_FILL_RULE_NONZERO 0 /* == nsISVGGeometrySource::FILL_RULE_NONZERO */
#define NS_STYLE_FILL_RULE_EVENODD 1 /* == nsISVGGeometrySource::FILL_RULE_EVENODD */
#define NS_STYLE_FILL_RULE_NONZERO 0
#define NS_STYLE_FILL_RULE_EVENODD 1
// pointer-events
#define NS_STYLE_POINTER_EVENTS_NONE 0
@ -673,21 +669,20 @@
#define NS_STYLE_POINTER_EVENTS_ALL 8
// shape-rendering
#define NS_STYLE_SHAPE_RENDERING_AUTO 0 /* == nsISVGPathGeometrySource::SHAPE_RENDERING_AUTO */
#define NS_STYLE_SHAPE_RENDERING_OPTIMIZESPEED 1 /* == nsISVGPathGeometrySource::SHAPE_RENDERING_OPTIMIZESPEED */
#define NS_STYLE_SHAPE_RENDERING_CRISPEDGES 2 /* == nsISVGPathGeometrySource::SHAPE_RENDERING_CRISPEDGES */
#define NS_STYLE_SHAPE_RENDERING_GEOMETRICPRECISION 3 /* == nsISVGPathGeometrySource::SHAPE_RENDERING_GEOMETRICPRECISION */
#define NS_STYLE_SHAPE_RENDERING_AUTO 0
#define NS_STYLE_SHAPE_RENDERING_OPTIMIZESPEED 1
#define NS_STYLE_SHAPE_RENDERING_CRISPEDGES 2
#define NS_STYLE_SHAPE_RENDERING_GEOMETRICPRECISION 3
// stroke-linecap
#define NS_STYLE_STROKE_LINECAP_BUTT 0 /* == nsISVGGeometrySource::STROKE_LINECAP_BUTT */
#define NS_STYLE_STROKE_LINECAP_ROUND 1 /* == nsISVGGeometrySource::STROKE_LINECAP_ROUND */
#define NS_STYLE_STROKE_LINECAP_SQUARE 2 /* == nsISVGGeometrySource::STROKE_LINECAP_SQUARE */
#define NS_STYLE_STROKE_LINECAP_BUTT 0
#define NS_STYLE_STROKE_LINECAP_ROUND 1
#define NS_STYLE_STROKE_LINECAP_SQUARE 2
// stroke-linejoin
#define NS_STYLE_STROKE_LINEJOIN_MITER 0 /* == nsISVGGeometrySource::STROKE_LINEJOIN_MITER */
#define NS_STYLE_STROKE_LINEJOIN_ROUND 1 /* == nsISVGGeometrySource::STROKE_LINEJOIN_ROUND */
#define NS_STYLE_STROKE_LINEJOIN_BEVEL 2 /* == nsISVGGeometrySource::STROKE_LINEJOIN_BEVEL */
#define NS_STYLE_STROKE_LINEJOIN_MITER 0
#define NS_STYLE_STROKE_LINEJOIN_ROUND 1
#define NS_STYLE_STROKE_LINEJOIN_BEVEL 2
// text-anchor
#define NS_STYLE_TEXT_ANCHOR_START 0
@ -695,10 +690,15 @@
#define NS_STYLE_TEXT_ANCHOR_END 2
// text-rendering
#define NS_STYLE_TEXT_RENDERING_AUTO 0 /* == nsISVGGlyphGeometrySource::TEXT_RENDERING_AUTO */
#define NS_STYLE_TEXT_RENDERING_OPTIMIZESPEED 1 /* == nsISVGG.G.S.::TEXT_RENDERING_OPTIMIZESPEED */
#define NS_STYLE_TEXT_RENDERING_OPTIMIZELEGIBILITY 2 /* == nsISVGG.G.S.::TEXT_RENDERING_OPTIMIZELEGIBILITY */
#define NS_STYLE_TEXT_RENDERING_GEOMETRICPRECISION 3 /* == nsISVGG.G.S.::TEXT_RENDERING_GEOMETRICPRECISION */
#define NS_STYLE_TEXT_RENDERING_AUTO 0
#define NS_STYLE_TEXT_RENDERING_OPTIMIZESPEED 1
#define NS_STYLE_TEXT_RENDERING_OPTIMIZELEGIBILITY 2
#define NS_STYLE_TEXT_RENDERING_GEOMETRICPRECISION 3
// color-interpolation and color-interpolation-filters
#define NS_STYLE_COLOR_INTERPOLATION_AUTO 0
#define NS_STYLE_COLOR_INTERPOLATION_SRGB 1
#define NS_STYLE_COLOR_INTERPOLATION_LINEARRGB 2
#endif // MOZ_SVG

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

@ -549,6 +549,7 @@ CSS_KEY(fill, fill)
CSS_KEY(geometricprecision, geometricprecision)
CSS_KEY(hanging, hanging)
CSS_KEY(ideographic, ideographic)
CSS_KEY(linearrgb, linearrgb)
CSS_KEY(mathematical, mathematical)
//CSS_KEY(middle, middle)
CSS_KEY(miter, miter)
@ -562,6 +563,7 @@ CSS_KEY(reset-size, reset_size)
CSS_KEY(round, round)
//CSS_KEY(square, square)
//CSS_KEY(start, start)
CSS_KEY(srgb, srgb)
CSS_KEY(stroke, stroke)
CSS_KEY(text-after-edge, text_after_edge)
CSS_KEY(text-before-edge, text_before_edge)

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

@ -4525,6 +4525,10 @@ PRBool CSSParserImpl::ParseSingleValueProperty(nsresult& aErrorCode,
case eCSSProperty_clip_rule:
return ParseVariant(aErrorCode, aValue, VARIANT_HK,
nsCSSProps::kFillRuleKTable);
case eCSSProperty_color_interpolation:
case eCSSProperty_color_interpolation_filters:
return ParseVariant(aErrorCode, aValue, VARIANT_AHK,
nsCSSProps::kColorInterpolationKTable);
case eCSSProperty_dominant_baseline:
return ParseVariant(aErrorCode, aValue, VARIANT_AHK,
nsCSSProps::kDominantBaselineKTable);

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

@ -471,6 +471,8 @@ CSS_PROP_XUL(-moz-box-ordinal-group, box_ordinal_group, MozBoxOrdinalGroup, XUL,
#ifndef CSS_PROP_LIST_EXCLUDE_INTERNAL
CSS_PROP_SVGRESET(clip-path, clip_path, ClipPath, SVG, mClipPath, eCSSType_Value, nsnull)
CSS_PROP_SVG(clip-rule, clip_rule, ClipRule, SVG, mClipRule, eCSSType_Value, kFillRuleKTable)
CSS_PROP_SVG(color-interpolation, color_interpolation, ColorInterpolation, SVG, mColorInterpolation, eCSSType_Value, kColorInterpolationKTable)
CSS_PROP_SVG(color-interpolation-filters, color_interpolation_filters, ColorInterpolationFilters, SVG, mColorInterpolationFilters, eCSSType_Value, kColorInterpolationKTable)
CSS_PROP_SVGRESET(dominant-baseline, dominant_baseline, DominantBaseline, SVG, mDominantBaseline, eCSSType_Value, kDominantBaselineKTable)
CSS_PROP_SVG(fill, fill, Fill, SVG, mFill, eCSSType_ValuePair, nsnull)
CSS_PROP_SVG(fill-opacity, fill_opacity, FillOpacity, SVG, mFillOpacity, eCSSType_Value, nsnull)

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

@ -1048,6 +1048,12 @@ const PRInt32 nsCSSProps::kTextRenderingKTable[] = {
eCSSKeyword_UNKNOWN, -1
};
const PRInt32 nsCSSProps::kColorInterpolationKTable[] = {
eCSSKeyword_srgb, NS_STYLE_COLOR_INTERPOLATION_SRGB,
eCSSKeyword_linearrgb, NS_STYLE_COLOR_INTERPOLATION_LINEARRGB,
eCSSKeyword_UNKNOWN, -1
};
#endif
PRBool

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

@ -138,6 +138,7 @@ public:
static const PRInt32 kStrokeLinejoinKTable[];
static const PRInt32 kTextAnchorKTable[];
static const PRInt32 kTextRenderingKTable[];
static const PRInt32 kColorInterpolationKTable[];
#endif
static const PRInt32 kBoxPropSourceKTable[];
static const PRInt32 kBoxSizingKTable[];

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

@ -496,6 +496,8 @@ struct nsCSSSVG : public nsCSSStruct {
nsCSSValue mClipPath;
nsCSSValue mClipRule;
nsCSSValue mColorInterpolation;
nsCSSValue mColorInterpolationFilters;
nsCSSValue mDominantBaseline;
nsCSSValuePair mFill;
nsCSSValue mFillOpacity;

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

@ -4069,6 +4069,36 @@ nsRuleNode::ComputeSVGData(nsStyleStruct* aStartStruct,
svg->mClipRule = parentSVG->mClipRule;
}
// color-interpolation: auto, sRGB, linearRGB, inherit
if (eCSSUnit_Enumerated == SVGData.mColorInterpolation.GetUnit()) {
svg->mColorInterpolation = SVGData.mColorInterpolation.GetIntValue();
}
else if (eCSSUnit_Auto == SVGData.mColorInterpolation.GetUnit()) {
svg->mColorInterpolation = NS_STYLE_COLOR_INTERPOLATION_AUTO;
}
else if (eCSSUnit_Inherit == SVGData.mColorInterpolation.GetUnit()) {
inherited = PR_TRUE;
svg->mColorInterpolation = parentSVG->mColorInterpolation;
}
else if (eCSSUnit_Initial == SVGData.mColorInterpolation.GetUnit()) {
svg->mColorInterpolation = NS_STYLE_COLOR_INTERPOLATION_SRGB;
}
// color-interpolation-filters: auto, sRGB, linearRGB, inherit
if (eCSSUnit_Enumerated == SVGData.mColorInterpolationFilters.GetUnit()) {
svg->mColorInterpolationFilters = SVGData.mColorInterpolationFilters.GetIntValue();
}
else if (eCSSUnit_Auto == SVGData.mColorInterpolationFilters.GetUnit()) {
svg->mColorInterpolationFilters = NS_STYLE_COLOR_INTERPOLATION_AUTO;
}
else if (eCSSUnit_Inherit == SVGData.mColorInterpolationFilters.GetUnit()) {
inherited = PR_TRUE;
svg->mColorInterpolationFilters = parentSVG->mColorInterpolationFilters;
}
else if (eCSSUnit_Initial == SVGData.mColorInterpolation.GetUnit()) {
svg->mColorInterpolation = NS_STYLE_COLOR_INTERPOLATION_LINEARRGB;
}
// fill:
SetSVGPaint(SVGData.mFill, parentSVG->mFill, mPresContext, aContext, svg->mFill, inherited);

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

@ -884,10 +884,12 @@ void nsStyleContext::DumpRegressionData(nsPresContext* aPresContext, FILE* out,
svg->mStrokeMiterlimit,
svg->mStrokeOpacity);
svg->mStrokeWidth.ToString(str);
fprintf(out, "%s %d %d %d %d %d %d %d %d %d\" />\n",
fprintf(out, "%s %d %d %d %d %d %d %d %d %d %d %d\" />\n",
NS_ConvertUTF16toUTF8(str).get(),
(int)svg->mStrokeDasharrayLength,
(int)svg->mClipRule,
(int)svg->mColorInterpolation,
(int)svg->mColorInterpolationFilters,
(int)svg->mFillRule,
(int)svg->mPointerEvents,
(int)svg->mShapeRendering,

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

@ -652,6 +652,8 @@ nsStyleSVG::nsStyleSVG()
mStrokeDasharrayLength = 0;
mClipRule = NS_STYLE_FILL_RULE_NONZERO;
mColorInterpolation = NS_STYLE_COLOR_INTERPOLATION_SRGB;
mColorInterpolationFilters = NS_STYLE_COLOR_INTERPOLATION_LINEARRGB;
mFillRule = NS_STYLE_FILL_RULE_NONZERO;
mPointerEvents = NS_STYLE_POINTER_EVENTS_VISIBLEPAINTED;
mShapeRendering = NS_STYLE_SHAPE_RENDERING_AUTO;
@ -698,6 +700,8 @@ nsStyleSVG::nsStyleSVG(const nsStyleSVG& aSource)
mStrokeOpacity = aSource.mStrokeOpacity;
mClipRule = aSource.mClipRule;
mColorInterpolation = aSource.mColorInterpolation;
mColorInterpolationFilters = aSource.mColorInterpolationFilters;
mFillRule = aSource.mFillRule;
mPointerEvents = aSource.mPointerEvents;
mShapeRendering = aSource.mShapeRendering;
@ -724,6 +728,8 @@ nsChangeHint nsStyleSVG::CalcDifference(const nsStyleSVG& aOther) const
mStrokeOpacity != aOther.mStrokeOpacity ||
mClipRule != aOther.mClipRule ||
mColorInterpolation != aOther.mColorInterpolation ||
mColorInterpolationFilters != aOther.mColorInterpolationFilters ||
mFillRule != aOther.mFillRule ||
mPointerEvents != aOther.mPointerEvents ||
mShapeRendering != aOther.mShapeRendering ||

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

@ -1285,6 +1285,8 @@ struct nsStyleSVG : public nsStyleStruct {
PRUint32 mStrokeDasharrayLength;
PRUint8 mClipRule; // [inherited]
PRUint8 mColorInterpolation; // [inherited] see nsStyleConsts.h
PRUint8 mColorInterpolationFilters; // [inherited] see nsStyleConsts.h
PRUint8 mFillRule; // [inherited] see nsStyleConsts.h
PRUint8 mPointerEvents; // [inherited] see nsStyleConsts.h
PRUint8 mShapeRendering; // [inherited] see nsStyleConsts.h

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

@ -379,6 +379,9 @@ nsSVGFilterFrame::FilterPaint(nsSVGRenderState *aContext,
x, y, width, height,
filterResX, filterResY,
type);
nsSVGFilterInstance::ColorModel
colorModel(nsSVGFilterInstance::ColorModel::SRGB,
nsSVGFilterInstance::ColorModel::PREMULTIPLIED);
if (requirements & NS_FE_SOURCEALPHA) {
cairo_surface_t *alpha =
@ -403,14 +406,14 @@ nsSVGFilterFrame::FilterPaint(nsSVGRenderState *aContext,
}
instance.DefineImage(NS_LITERAL_STRING("SourceAlpha"), alpha,
nsRect(0, 0, filterResX, filterResY));
nsRect(0, 0, filterResX, filterResY), colorModel);
}
// this always needs to be defined last because the default image
// for the first filter element is supposed to be SourceGraphic
instance.DefineImage(NS_LITERAL_STRING("SourceGraphic"),
tmpSurface->CairoSurface(),
nsRect(0, 0, filterResX, filterResY));
nsRect(0, 0, filterResX, filterResY), colorModel);
for (PRUint32 k=0; k<count; ++k) {
nsIContent* child = mContent->GetChildAt(k);
@ -426,7 +429,8 @@ nsSVGFilterFrame::FilterPaint(nsSVGRenderState *aContext,
nsRect filterRect;
nsRefPtr<gfxASurface> resultSurface;
instance.LookupImage(NS_LITERAL_STRING(""), &filterResult, &filterRect);
instance.LookupImage(NS_LITERAL_STRING(""),
&filterResult, &filterRect, colorModel);
if (filterResult)
resultSurface = gfxASurface::Wrap(filterResult);
@ -648,7 +652,8 @@ nsSVGFilterInstance::GetImage()
void
nsSVGFilterInstance::LookupImage(const nsAString &aName,
cairo_surface_t **aImage,
nsRect *aRegion)
nsRect *aRegion,
const ColorModel &aRequiredColorModel)
{
ImageEntry *entry;
@ -660,6 +665,29 @@ nsSVGFilterInstance::LookupImage(const nsAString &aName,
if (entry) {
*aImage = entry->mImage;
*aRegion = entry->mRegion;
if (aRequiredColorModel == entry->mColorModel)
return;
// convert image to desired format
PRUint8 *data = cairo_image_surface_get_data(entry->mImage);
PRInt32 stride = cairo_image_surface_get_stride(entry->mImage);
if (entry->mColorModel.mAlphaChannel == ColorModel::PREMULTIPLIED)
nsSVGUtils::UnPremultiplyImageDataAlpha(data, stride, entry->mRegion);
if (aRequiredColorModel.mColorSpace != entry->mColorModel.mColorSpace) {
if (aRequiredColorModel.mColorSpace == ColorModel::LINEAR_RGB)
nsSVGUtils::ConvertImageDataToLinearRGB(data, stride, entry->mRegion);
else
nsSVGUtils::ConvertImageDataFromLinearRGB(data, stride, entry->mRegion);
}
if (aRequiredColorModel.mAlphaChannel == ColorModel::PREMULTIPLIED)
nsSVGUtils::PremultiplyImageDataAlpha(data, stride, entry->mRegion);
entry->mColorModel = aRequiredColorModel;
} else {
*aImage = nsnull;
aRegion->Empty();
@ -669,9 +697,10 @@ nsSVGFilterInstance::LookupImage(const nsAString &aName,
void
nsSVGFilterInstance::DefineImage(const nsAString &aName,
cairo_surface_t *aImage,
nsRect aRegion)
const nsRect &aRegion,
const ColorModel &aColorModel)
{
ImageEntry *entry = new ImageEntry(aImage, aRegion);
ImageEntry *entry = new ImageEntry(aImage, aRegion, aColorModel);
if (entry)
mImageDictionary.Put(aName, entry);

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

@ -55,6 +55,21 @@ class nsSVGElement;
class nsSVGFilterInstance
{
public:
class ColorModel {
public:
enum ColorSpace { SRGB, LINEAR_RGB };
enum AlphaChannel { UNPREMULTIPLIED, PREMULTIPLIED };
ColorModel(ColorSpace aColorSpace, AlphaChannel aAlphaChannel) :
mColorSpace(aColorSpace), mAlphaChannel(aAlphaChannel) {}
PRBool operator==(const ColorModel& aOther) const {
return mColorSpace == aOther.mColorSpace &&
mAlphaChannel == aOther.mAlphaChannel;
}
ColorSpace mColorSpace;
PRPackedBool mAlphaChannel;
};
float GetPrimitiveLength(nsSVGLength2 *aLength);
void GetFilterSubregion(nsIContent *aFilter,
@ -63,9 +78,13 @@ public:
cairo_surface_t *GetImage();
void LookupImage(const nsAString &aName,
cairo_surface_t **aImage, nsRect *aRegion);
cairo_surface_t **aImage,
nsRect *aRegion,
const ColorModel &aColorModel);
void DefineImage(const nsAString &aName,
cairo_surface_t *aImage, nsRect aRegion);
cairo_surface_t *aImage,
const nsRect &aRegion,
const ColorModel &aColorModel);
void GetFilterBox(float *x, float *y, float *width, float *height) {
*x = mFilterX;
*y = mFilterY;
@ -92,12 +111,19 @@ public:
private:
class ImageEntry {
public:
ImageEntry(cairo_surface_t *aImage, nsRect aRegion) :
mImage(aImage), mRegion(aRegion) { cairo_surface_reference(aImage); }
~ImageEntry() { cairo_surface_destroy(mImage); }
ImageEntry(cairo_surface_t *aImage,
const nsRect &aRegion,
const ColorModel &aColorModel) :
mImage(aImage), mRegion(aRegion), mColorModel(aColorModel) {
cairo_surface_reference(aImage);
}
~ImageEntry() {
cairo_surface_destroy(mImage);
}
cairo_surface_t *mImage;
nsRect mRegion;
ColorModel mColorModel;
};
nsClassHashtable<nsStringHashKey,ImageEntry> mImageDictionary;

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

@ -98,42 +98,6 @@ nsSVGMaskFrame::InitSVG()
}
/* sRGB -> linearRGB mapping table */
static unsigned char rgb2lin[256] = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1, 1, 1,
1, 1, 1, 1, 1, 1, 2, 2,
2, 2, 2, 2, 2, 3, 3, 3,
3, 3, 4, 4, 4, 4, 4, 5,
5, 5, 5, 6, 6, 6, 6, 7,
7, 7, 8, 8, 8, 9, 9, 9,
10, 10, 10, 11, 11, 11, 12, 12,
13, 13, 13, 14, 14, 15, 15, 16,
16, 16, 17, 17, 18, 18, 19, 19,
20, 20, 21, 22, 22, 23, 23, 24,
24, 25, 26, 26, 27, 27, 28, 29,
29, 30, 31, 31, 32, 33, 33, 34,
35, 36, 36, 37, 38, 38, 39, 40,
41, 42, 42, 43, 44, 45, 46, 47,
47, 48, 49, 50, 51, 52, 53, 54,
55, 55, 56, 57, 58, 59, 60, 61,
62, 63, 64, 65, 66, 67, 68, 70,
71, 72, 73, 74, 75, 76, 77, 78,
80, 81, 82, 83, 84, 85, 87, 88,
89, 90, 92, 93, 94, 95, 97, 98,
99, 101, 102, 103, 105, 106, 107, 109,
110, 112, 113, 114, 116, 117, 119, 120,
122, 123, 125, 126, 128, 129, 131, 132,
134, 135, 137, 139, 140, 142, 144, 145,
147, 148, 150, 152, 153, 155, 157, 159,
160, 162, 164, 166, 167, 169, 171, 173,
175, 176, 178, 180, 182, 184, 186, 188,
190, 192, 193, 195, 197, 199, 201, 203,
205, 207, 209, 211, 213, 215, 218, 220,
222, 224, 226, 228, 230, 232, 235, 237,
239, 241, 243, 245, 248, 250, 252, 255
};
cairo_pattern_t *
nsSVGMaskFrame::ComputeMaskAlpha(nsSVGRenderState *aContext,
nsISVGChildFrame* aParent,
@ -250,37 +214,27 @@ nsSVGMaskFrame::ComputeMaskAlpha(nsSVGRenderState *aContext,
cairo_destroy(transferCtx);
cairo_pattern_destroy(pattern);
/* Now convert to intensity (sRGB -> linearRGB -> intensity) and
store in alpha channel. Reuse the transfer image instead of
allocating another CAIRO_FORMAT_A8 image. */
PRUint32 width = cairo_image_surface_get_width(image);
PRUint32 height = cairo_image_surface_get_height(image);
PRUint8 *data = cairo_image_surface_get_data(image);
PRInt32 stride = cairo_image_surface_get_stride(image);
nsRect rect(0, 0, width, height);
nsSVGUtils::UnPremultiplyImageDataAlpha(data, stride, rect);
nsSVGUtils::ConvertImageDataToLinearRGB(data, stride, rect);
for (PRUint32 y = 0; y < height; y++)
for (PRUint32 x = 0; x < width; x++) {
PRUint32 a;
float r, g, b, intensity;
/* un-premultiply and sRGB -> linearRGB conversion */
a = data[stride * y + 4 * x + 3];
if (a) {
b = rgb2lin[(255 * (PRUint32)data[stride * y + 4 * x]) / a] / 255.0;
g = rgb2lin[(255 * (PRUint32)data[stride * y + 4 * x + 1]) / a] / 255.0;
r = rgb2lin[(255 * (PRUint32)data[stride * y + 4 * x + 2]) / a] / 255.0;
} else {
b = g = r = 0.0f;
}
PRUint8 *pixel = data + stride * y + 4 * x;
/* linearRGB -> intensity */
intensity = (r * 0.2125 + g * 0.7154 + b * 0.0721) * (a / 255.0) * aOpacity;
data[stride * y + 4 * x] = 255;
data[stride * y + 4 * x + 1] = 255;
data[stride * y + 4 * x + 2] = 255;
data[stride * y + 4 * x + 3] = (unsigned char)(intensity * 255);
pixel[3] = (PRUint8)((pixel[2] * 0.2125 +
pixel[1] * 0.7154 +
pixel[0] * 0.0721) *
(pixel[3] / 255.0) * aOpacity);
pixel[0] = 255;
pixel[1] = 255;
pixel[2] = 255;
}
cairo_pattern_t *retval = cairo_pattern_create_for_surface(image);

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

@ -88,6 +88,80 @@ struct nsSVGFilterProperty {
cairo_surface_t *nsSVGUtils::mCairoComputationalSurface = nsnull;
gfxASurface *nsSVGUtils::mThebesComputationalSurface = nsnull;
// c = n / 255
// (c <= 0.0031308 ? c * 12.92 : 1.055 * pow(c, 1 / 2.4) - 0.055) * 255 + 0.5
static const PRUint8 glinearRGBTosRGBMap[256] = {
0, 13, 22, 28, 34, 38, 42, 46,
50, 53, 56, 59, 61, 64, 66, 69,
71, 73, 75, 77, 79, 81, 83, 85,
86, 88, 90, 92, 93, 95, 96, 98,
99, 101, 102, 104, 105, 106, 108, 109,
110, 112, 113, 114, 115, 117, 118, 119,
120, 121, 122, 124, 125, 126, 127, 128,
129, 130, 131, 132, 133, 134, 135, 136,
137, 138, 139, 140, 141, 142, 143, 144,
145, 146, 147, 148, 148, 149, 150, 151,
152, 153, 154, 155, 155, 156, 157, 158,
159, 159, 160, 161, 162, 163, 163, 164,
165, 166, 167, 167, 168, 169, 170, 170,
171, 172, 173, 173, 174, 175, 175, 176,
177, 178, 178, 179, 180, 180, 181, 182,
182, 183, 184, 185, 185, 186, 187, 187,
188, 189, 189, 190, 190, 191, 192, 192,
193, 194, 194, 195, 196, 196, 197, 197,
198, 199, 199, 200, 200, 201, 202, 202,
203, 203, 204, 205, 205, 206, 206, 207,
208, 208, 209, 209, 210, 210, 211, 212,
212, 213, 213, 214, 214, 215, 215, 216,
216, 217, 218, 218, 219, 219, 220, 220,
221, 221, 222, 222, 223, 223, 224, 224,
225, 226, 226, 227, 227, 228, 228, 229,
229, 230, 230, 231, 231, 232, 232, 233,
233, 234, 234, 235, 235, 236, 236, 237,
237, 238, 238, 238, 239, 239, 240, 240,
241, 241, 242, 242, 243, 243, 244, 244,
245, 245, 246, 246, 246, 247, 247, 248,
248, 249, 249, 250, 250, 251, 251, 251,
252, 252, 253, 253, 254, 254, 255, 255
};
// c = n / 255
// c <= 0.04045 ? c / 12.92 : pow((c + 0.055) / 1.055, 2.4)) * 255 + 0.5
static const PRUint8 gsRGBToLinearRGBMap[256] = {
0, 0, 0, 0, 0, 0, 0, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 2, 2, 2, 2, 2, 2,
2, 2, 3, 3, 3, 3, 3, 3,
4, 4, 4, 4, 4, 5, 5, 5,
5, 6, 6, 6, 6, 7, 7, 7,
8, 8, 8, 8, 9, 9, 9, 10,
10, 10, 11, 11, 12, 12, 12, 13,
13, 13, 14, 14, 15, 15, 16, 16,
17, 17, 17, 18, 18, 19, 19, 20,
20, 21, 22, 22, 23, 23, 24, 24,
25, 25, 26, 27, 27, 28, 29, 29,
30, 30, 31, 32, 32, 33, 34, 35,
35, 36, 37, 37, 38, 39, 40, 41,
41, 42, 43, 44, 45, 45, 46, 47,
48, 49, 50, 51, 51, 52, 53, 54,
55, 56, 57, 58, 59, 60, 61, 62,
63, 64, 65, 66, 67, 68, 69, 70,
71, 72, 73, 74, 76, 77, 78, 79,
80, 81, 82, 84, 85, 86, 87, 88,
90, 91, 92, 93, 95, 96, 97, 99,
100, 101, 103, 104, 105, 107, 108, 109,
111, 112, 114, 115, 116, 118, 119, 121,
122, 124, 125, 127, 128, 130, 131, 133,
134, 136, 138, 139, 141, 142, 144, 146,
147, 149, 151, 152, 154, 156, 157, 159,
161, 163, 164, 166, 168, 170, 171, 173,
175, 177, 179, 181, 183, 184, 186, 188,
190, 192, 194, 196, 198, 200, 202, 204,
206, 208, 210, 212, 214, 216, 218, 220,
222, 224, 226, 229, 231, 233, 235, 237,
239, 242, 244, 246, 248, 250, 253, 255
};
static PRBool gSVGEnabled;
static const char SVG_PREF_STR[] = "svg.enabled";
@ -123,6 +197,84 @@ NS_SVGEnabled()
return gSVGEnabled;
}
void
nsSVGUtils::UnPremultiplyImageDataAlpha(PRUint8 *data,
PRInt32 stride,
const nsRect &rect)
{
for (PRInt32 y = rect.y; y < rect.YMost(); y++) {
for (PRInt32 x = rect.x; x < rect.XMost(); x++) {
PRUint8 *pixel = data + stride * y + 4 * x;
PRUint8 a = pixel[3];
if (a == 255)
continue;
if (a) {
pixel[0] = (255 * pixel[0]) / a;
pixel[1] = (255 * pixel[1]) / a;
pixel[2] = (255 * pixel[2]) / a;
} else {
pixel[0] = 0;
pixel[1] = 0;
pixel[2] = 0;
}
}
}
}
void
nsSVGUtils::PremultiplyImageDataAlpha(PRUint8 *data,
PRInt32 stride,
const nsRect &rect)
{
for (PRInt32 y = rect.y; y < rect.YMost(); y++) {
for (PRInt32 x = rect.x; x < rect.XMost(); x++) {
PRUint8 *pixel = data + stride * y + 4 * x;
PRUint8 a = pixel[3];
if (a == 255)
continue;
FAST_DIVIDE_BY_255(pixel[0], pixel[0] * a);
FAST_DIVIDE_BY_255(pixel[1], pixel[1] * a);
FAST_DIVIDE_BY_255(pixel[2], pixel[2] * a);
}
}
}
void
nsSVGUtils::ConvertImageDataToLinearRGB(PRUint8 *data,
PRInt32 stride,
const nsRect &rect)
{
for (PRInt32 y = rect.y; y < rect.YMost(); y++) {
for (PRInt32 x = rect.x; x < rect.XMost(); x++) {
PRUint8 *pixel = data + stride * y + 4 * x;
pixel[0] = gsRGBToLinearRGBMap[pixel[0]];
pixel[1] = gsRGBToLinearRGBMap[pixel[1]];
pixel[2] = gsRGBToLinearRGBMap[pixel[2]];
}
}
}
void
nsSVGUtils::ConvertImageDataFromLinearRGB(PRUint8 *data,
PRInt32 stride,
const nsRect &rect)
{
for (PRInt32 y = rect.y; y < rect.YMost(); y++) {
for (PRInt32 x = rect.x; x < rect.XMost(); x++) {
PRUint8 *pixel = data + stride * y + 4 * x;
pixel[0] = glinearRGBTosRGBMap[pixel[0]];
pixel[1] = glinearRGBTosRGBMap[pixel[1]];
pixel[2] = glinearRGBTosRGBMap[pixel[2]];
}
}
}
nsresult
nsSVGUtils::ReportToConsole(nsIDocument* doc,
const char* aWarning,

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

@ -142,6 +142,31 @@ private:
class nsSVGUtils
{
public:
/*
* Converts image data from premultipled to unpremultiplied alpha
*/
static void UnPremultiplyImageDataAlpha(PRUint8 *data,
PRInt32 stride,
const nsRect &rect);
/*
* Converts image data from unpremultipled to premultiplied alpha
*/
static void PremultiplyImageDataAlpha(PRUint8 *data,
PRInt32 stride,
const nsRect &rect);
/*
* Converts image data from premultiplied sRGB to Linear RGB
*/
static void ConvertImageDataToLinearRGB(PRUint8 *data,
PRInt32 stride,
const nsRect &rect);
/*
* Converts image data from LinearRGB to premultiplied sRGB
*/
static void ConvertImageDataFromLinearRGB(PRUint8 *data,
PRInt32 stride,
const nsRect &rect);
/*
* Report a localized error message to the error console.
*/