tenfourfox/gfx/src/FilterSupport.h

480 lines
15 KiB
C++

/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* 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