/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef __FilterSupport_h
#define __FilterSupport_h
#include "mozilla/Attributes.h"
#include "mozilla/RefPtr.h"
#include "mozilla/gfx/Rect.h"
#include "mozilla/gfx/Matrix.h"
#include "mozilla/gfx/2D.h"
#include "nsClassHashtable.h"
#include "nsTArray.h"
#include "nsRegion.h"
namespace mozilla {
namespace gfx {
// Morphology Operators
const unsigned short SVG_OPERATOR_UNKNOWN = 0;
const unsigned short SVG_OPERATOR_ERODE = 1;
const unsigned short SVG_OPERATOR_DILATE = 2;
// ColorMatrix types
const unsigned short SVG_FECOLORMATRIX_TYPE_UNKNOWN = 0;
const unsigned short SVG_FECOLORMATRIX_TYPE_MATRIX = 1;
const unsigned short SVG_FECOLORMATRIX_TYPE_SATURATE = 2;
const unsigned short SVG_FECOLORMATRIX_TYPE_HUE_ROTATE = 3;
const unsigned short SVG_FECOLORMATRIX_TYPE_LUMINANCE_TO_ALPHA = 4;
// ColorMatrix types for CSS filters
const unsigned short SVG_FECOLORMATRIX_TYPE_SEPIA = 5;
// ComponentTransfer types
const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_UNKNOWN = 0;
const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY = 1;
const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_TABLE = 2;
const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_DISCRETE = 3;
const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_LINEAR = 4;
const unsigned short SVG_FECOMPONENTTRANSFER_TYPE_GAMMA = 5;
// Blend Mode Values
const unsigned short SVG_FEBLEND_MODE_UNKNOWN = 0;
const unsigned short SVG_FEBLEND_MODE_NORMAL = 1;
const unsigned short SVG_FEBLEND_MODE_MULTIPLY = 2;
const unsigned short SVG_FEBLEND_MODE_SCREEN = 3;
const unsigned short SVG_FEBLEND_MODE_DARKEN = 4;
const unsigned short SVG_FEBLEND_MODE_LIGHTEN = 5;
const unsigned short SVG_FEBLEND_MODE_OVERLAY = 6;
const unsigned short SVG_FEBLEND_MODE_COLOR_DODGE = 7;
const unsigned short SVG_FEBLEND_MODE_COLOR_BURN = 8;
const unsigned short SVG_FEBLEND_MODE_HARD_LIGHT = 9;
const unsigned short SVG_FEBLEND_MODE_SOFT_LIGHT = 10;
const unsigned short SVG_FEBLEND_MODE_DIFFERENCE = 11;
const unsigned short SVG_FEBLEND_MODE_EXCLUSION = 12;
const unsigned short SVG_FEBLEND_MODE_HUE = 13;
const unsigned short SVG_FEBLEND_MODE_SATURATION = 14;
const unsigned short SVG_FEBLEND_MODE_COLOR = 15;
const unsigned short SVG_FEBLEND_MODE_LUMINOSITY = 16;
// Edge Mode Values
const unsigned short SVG_EDGEMODE_UNKNOWN = 0;
const unsigned short SVG_EDGEMODE_DUPLICATE = 1;
const unsigned short SVG_EDGEMODE_WRAP = 2;
const unsigned short SVG_EDGEMODE_NONE = 3;
// Channel Selectors
const unsigned short SVG_CHANNEL_UNKNOWN = 0;
const unsigned short SVG_CHANNEL_R = 1;
const unsigned short SVG_CHANNEL_G = 2;
const unsigned short SVG_CHANNEL_B = 3;
const unsigned short SVG_CHANNEL_A = 4;
// Turbulence Types
const unsigned short SVG_TURBULENCE_TYPE_UNKNOWN = 0;
const unsigned short SVG_TURBULENCE_TYPE_FRACTALNOISE = 1;
const unsigned short SVG_TURBULENCE_TYPE_TURBULENCE = 2;
// Composite Operators
const unsigned short SVG_FECOMPOSITE_OPERATOR_UNKNOWN = 0;
const unsigned short SVG_FECOMPOSITE_OPERATOR_OVER = 1;
const unsigned short SVG_FECOMPOSITE_OPERATOR_IN = 2;
const unsigned short SVG_FECOMPOSITE_OPERATOR_OUT = 3;
const unsigned short SVG_FECOMPOSITE_OPERATOR_ATOP = 4;
const unsigned short SVG_FECOMPOSITE_OPERATOR_XOR = 5;
const unsigned short SVG_FECOMPOSITE_OPERATOR_ARITHMETIC = 6;
enum AttributeName {
eBlendBlendmode = 0,
eMorphologyRadii,
eMorphologyOperator,
eColorMatrixType,
eColorMatrixValues,
eFloodColor,
eTileSourceRect,
eComponentTransferFunctionR,
eComponentTransferFunctionG,
eComponentTransferFunctionB,
eComponentTransferFunctionA,
eComponentTransferFunctionType,
eComponentTransferFunctionTableValues,
eComponentTransferFunctionSlope,
eComponentTransferFunctionIntercept,
eComponentTransferFunctionAmplitude,
eComponentTransferFunctionExponent,
eComponentTransferFunctionOffset,
eConvolveMatrixKernelSize,
eConvolveMatrixKernelMatrix,
eConvolveMatrixDivisor,
eConvolveMatrixBias,
eConvolveMatrixTarget,
eConvolveMatrixEdgeMode,
eConvolveMatrixKernelUnitLength,
eConvolveMatrixPreserveAlpha,
eOffsetOffset,
eDropShadowStdDeviation,
eDropShadowOffset,
eDropShadowColor,
eDisplacementMapScale,
eDisplacementMapXChannel,
eDisplacementMapYChannel,
eTurbulenceOffset,
eTurbulenceBaseFrequency,
eTurbulenceNumOctaves,
eTurbulenceSeed,
eTurbulenceStitchable,
eTurbulenceType,
eCompositeOperator,
eCompositeCoefficients,
eGaussianBlurStdDeviation,
eLightingLight,
eLightingSurfaceScale,
eLightingKernelUnitLength,
eLightingColor,
eDiffuseLightingDiffuseConstant,
eSpecularLightingSpecularConstant,
eSpecularLightingSpecularExponent,
eLightType,
eLightTypeNone,
eLightTypePoint,
eLightTypeSpot,
eLightTypeDistant,
ePointLightPosition,
eSpotLightPosition,
eSpotLightPointsAt,
eSpotLightFocus,
eSpotLightLimitingConeAngle,
eDistantLightAzimuth,
eDistantLightElevation,
eImageInputIndex,
eImageFilter,
eImageNativeSize,
eImageSubregion,
eImageTransform,
eLastAttributeName
};
class DrawTarget;
class SourceSurface;
struct FilterAttribute;
enum class AttributeType {
eBool,
eUint,
eFloat,
eSize,
eIntSize,
eIntPoint,
eMatrix,
eMatrix5x4,
ePoint3D,
eColor,
eAttributeMap,
eFloats,
Max
};
// Limits
const float kMaxStdDeviation = 500;
// A class that stores values of different types, keyed by an attribute name.
// The Get*() methods assert that they're called for the same type that the
// attribute was Set() with.
// AttributeMaps can be nested because AttributeMap is a valid attribute type.
class AttributeMap final {
public:
AttributeMap();
AttributeMap(const AttributeMap& aOther);
AttributeMap& operator=(const AttributeMap& aOther);
bool operator==(const AttributeMap& aOther) const;
bool operator!=(const AttributeMap& aOther) const {
return !(*this == aOther);
}
~AttributeMap();
void Set(AttributeName aName, bool aValue);
void Set(AttributeName aName, uint32_t aValue);
void Set(AttributeName aName, float aValue);
void Set(AttributeName aName, const Size& aValue);
void Set(AttributeName aName, const IntSize& aValue);
void Set(AttributeName aName, const IntPoint& aValue);
void Set(AttributeName aName, const Matrix& aValue);
void Set(AttributeName aName, const Matrix5x4& aValue);
void Set(AttributeName aName, const Point3D& aValue);
void Set(AttributeName aName, const Color& aValue);
void Set(AttributeName aName, const AttributeMap& aValue);
void Set(AttributeName aName, const float* aValues, int32_t aLength);
bool GetBool(AttributeName aName) const;
uint32_t GetUint(AttributeName aName) const;
float GetFloat(AttributeName aName) const;
Size GetSize(AttributeName aName) const;
IntSize GetIntSize(AttributeName aName) const;
IntPoint GetIntPoint(AttributeName aName) const;
Matrix GetMatrix(AttributeName aName) const;
Matrix5x4 GetMatrix5x4(AttributeName aName) const;
Point3D GetPoint3D(AttributeName aName) const;
Color GetColor(AttributeName aName) const;
AttributeMap GetAttributeMap(AttributeName aName) const;
const nsTArray<float>& GetFloats(AttributeName aName) const;
uint32_t Count() const;
nsClassHashtable<nsUint32HashKey, FilterAttribute>::Iterator ConstIter()
const;
static AttributeType GetType(FilterAttribute* aAttribute);
private:
mutable nsClassHashtable<nsUint32HashKey, FilterAttribute> mMap;
};
enum class ColorSpace { SRGB, LinearRGB, Max };
enum class AlphaModel { Unpremultiplied, Premultiplied };
class ColorModel {
public:
static ColorModel PremulSRGB() {
return ColorModel(ColorSpace::SRGB, AlphaModel::Premultiplied);
}
ColorModel(ColorSpace aColorSpace, AlphaModel aAlphaModel)
: mColorSpace(aColorSpace), mAlphaModel(aAlphaModel) {}
ColorModel()
: mColorSpace(ColorSpace::SRGB), mAlphaModel(AlphaModel::Premultiplied) {}
bool operator==(const ColorModel& aOther) const {
return mColorSpace == aOther.mColorSpace &&
mAlphaModel == aOther.mAlphaModel;
}
// Used to index FilterCachedColorModels::mFilterForColorModel.
uint8_t ToIndex() const {
return (uint8_t(mColorSpace) << 1) + uint8_t(mAlphaModel);
}
ColorSpace mColorSpace;
AlphaModel mAlphaModel;
};
enum class PrimitiveType {
Empty = 0,
Blend,
Morphology,
ColorMatrix,
Flood,
Tile,
ComponentTransfer,
ConvolveMatrix,
Offset,
DisplacementMap,
Turbulence,
Composite,
Merge,
Image,
GaussianBlur,
DropShadow,
DiffuseLighting,
SpecularLighting,
ToAlpha,
Max
};
/**
* A data structure to carry attributes for a given primitive that's part of a
* filter. Will be serializable via IPDL, so it must not contain complex
* functionality.
* Used as part of a FilterDescription.
*/
class FilterPrimitiveDescription final {
public:
enum {
kPrimitiveIndexSourceGraphic = -1,
kPrimitiveIndexSourceAlpha = -2,
kPrimitiveIndexFillPaint = -3,
kPrimitiveIndexStrokePaint = -4
};
FilterPrimitiveDescription();
explicit FilterPrimitiveDescription(PrimitiveType aType);
FilterPrimitiveDescription(const FilterPrimitiveDescription& aOther);
FilterPrimitiveDescription& operator=(
const FilterPrimitiveDescription& aOther);
PrimitiveType Type() const { return mType; }
void SetType(PrimitiveType aType) { mType = aType; }
const AttributeMap& Attributes() const { return mAttributes; }
AttributeMap& Attributes() { return mAttributes; }
IntRect PrimitiveSubregion() const { return mFilterPrimitiveSubregion; }
IntRect FilterSpaceBounds() const { return mFilterSpaceBounds; }
bool IsTainted() const { return mIsTainted; }
size_t NumberOfInputs() const { return mInputPrimitives.Length(); }
int32_t InputPrimitiveIndex(size_t aInputIndex) const {
return aInputIndex < mInputPrimitives.Length()
? mInputPrimitives[aInputIndex]
: 0;
}
ColorSpace InputColorSpace(size_t aInputIndex) const {
return aInputIndex < mInputColorSpaces.Length()
? mInputColorSpaces[aInputIndex]
: ColorSpace();
}
ColorSpace OutputColorSpace() const { return mOutputColorSpace; }
void SetPrimitiveSubregion(const IntRect& aRect) {
mFilterPrimitiveSubregion = aRect;
}
void SetFilterSpaceBounds(const IntRect& aRect) {
mFilterSpaceBounds = aRect;
}
void SetIsTainted(bool aIsTainted) { mIsTainted = aIsTainted; }
void SetInputPrimitive(size_t aInputIndex, int32_t aInputPrimitiveIndex) {
mInputPrimitives.EnsureLengthAtLeast(aInputIndex + 1);
mInputPrimitives[aInputIndex] = aInputPrimitiveIndex;
}
void SetInputColorSpace(size_t aInputIndex, ColorSpace aColorSpace) {
mInputColorSpaces.EnsureLengthAtLeast(aInputIndex + 1);
mInputColorSpaces[aInputIndex] = aColorSpace;
}
void SetOutputColorSpace(const ColorSpace& aColorSpace) {
mOutputColorSpace = aColorSpace;
}
bool operator==(const FilterPrimitiveDescription& aOther) const;
bool operator!=(const FilterPrimitiveDescription& aOther) const {
return !(*this == aOther);
}
private:
PrimitiveType mType;
AttributeMap mAttributes;
nsTArray<int32_t> mInputPrimitives;
IntRect mFilterPrimitiveSubregion;
IntRect mFilterSpaceBounds;
nsTArray<ColorSpace> mInputColorSpaces;
ColorSpace mOutputColorSpace;
bool mIsTainted;
};
/**
* A data structure that contains one or more FilterPrimitiveDescriptions.
* Designed to be serializable via IPDL, so it must not contain complex
* functionality.
*/
struct FilterDescription final {
FilterDescription() {}
explicit FilterDescription(
const nsTArray<FilterPrimitiveDescription>& aPrimitives)
: mPrimitives(aPrimitives) {}
bool operator==(const FilterDescription& aOther) const;
bool operator!=(const FilterDescription& aOther) const {
return !(*this == aOther);
}
nsTArray<FilterPrimitiveDescription> mPrimitives;
};
/**
* The methods of this class are not on FilterDescription because
* FilterDescription is designed as a simple value holder that can be used
* on any thread.
*/
class FilterSupport {
public:
/**
* Draw the filter described by aFilter. All rect parameters are in filter
* space coordinates. aRenderRect specifies the part of the filter output
* that will be drawn at (0, 0) into the draw target aDT, subject to the
* current transform on aDT but with no additional scaling.
* The source surfaces must match their corresponding rect in size.
* aAdditionalImages carries the images that are referenced by the
* eImageInputIndex attribute on any image primitives in the filter.
*/
static void RenderFilterDescription(
DrawTarget* aDT, const FilterDescription& aFilter,
const Rect& aRenderRect, SourceSurface* aSourceGraphic,
const IntRect& aSourceGraphicRect, SourceSurface* aFillPaint,
const IntRect& aFillPaintRect, SourceSurface* aStrokePaint,
const IntRect& aStrokePaintRect,
nsTArray<RefPtr<SourceSurface>>& aAdditionalImages,
const Point& aDestPoint, const DrawOptions& aOptions = DrawOptions());
/**
* Computes the region that changes in the filter output due to a change in
* input. This is primarily needed when an individual piece of content inside
* a filtered container element changes.
*/
static nsIntRegion ComputeResultChangeRegion(
const FilterDescription& aFilter, const nsIntRegion& aSourceGraphicChange,
const nsIntRegion& aFillPaintChange,
const nsIntRegion& aStrokePaintChange);
/**
* Computes the regions that need to be supplied in the filter inputs when
* painting aResultNeededRegion of the filter output.
*/
static void ComputeSourceNeededRegions(
const FilterDescription& aFilter, const nsIntRegion& aResultNeededRegion,
nsIntRegion& aSourceGraphicNeededRegion,
nsIntRegion& aFillPaintNeededRegion,
nsIntRegion& aStrokePaintNeededRegion);
/**
* Computes the size of the filter output.
*/
static nsIntRegion ComputePostFilterExtents(
const FilterDescription& aFilter,
const nsIntRegion& aSourceGraphicExtents);
/**
* Computes the size of a single FilterPrimitiveDescription's output given a
* set of input extents.
*/
static nsIntRegion PostFilterExtentsForPrimitive(
const FilterPrimitiveDescription& aDescription,
const nsTArray<nsIntRegion>& aInputExtents);
};
} // namespace gfx
} // namespace mozilla
#endif // __FilterSupport_h