2012-06-13 08:14:15 -07:00
|
|
|
/* 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/. */
|
|
|
|
|
2012-10-12 02:42:52 -07:00
|
|
|
#ifndef CanvasRenderingContext2D_h
|
|
|
|
#define CanvasRenderingContext2D_h
|
2012-06-13 08:14:15 -07:00
|
|
|
|
|
|
|
#include <vector>
|
|
|
|
#include "nsIDOMCanvasRenderingContext2D.h"
|
|
|
|
#include "nsICanvasRenderingContextInternal.h"
|
|
|
|
#include "mozilla/RefPtr.h"
|
|
|
|
#include "nsColor.h"
|
|
|
|
#include "nsHTMLCanvasElement.h"
|
|
|
|
#include "CanvasUtils.h"
|
|
|
|
#include "nsHTMLImageElement.h"
|
|
|
|
#include "nsHTMLVideoElement.h"
|
|
|
|
#include "gfxFont.h"
|
|
|
|
#include "mozilla/ErrorResult.h"
|
|
|
|
#include "mozilla/dom/ImageData.h"
|
|
|
|
#include "mozilla/dom/UnionTypes.h"
|
|
|
|
|
2012-10-12 02:42:52 -07:00
|
|
|
#define NS_CANVASGRADIENTAZURE_PRIVATE_IID \
|
|
|
|
{0x28425a6a, 0x90e0, 0x4d42, {0x9c, 0x75, 0xff, 0x60, 0x09, 0xb3, 0x10, 0xa8}}
|
|
|
|
#define NS_CANVASPATTERNAZURE_PRIVATE_IID \
|
|
|
|
{0xc9bacc25, 0x28da, 0x421e, {0x9a, 0x4b, 0xbb, 0xd6, 0x93, 0x05, 0x12, 0xbc}}
|
|
|
|
|
2012-06-13 08:14:15 -07:00
|
|
|
namespace mozilla {
|
|
|
|
namespace gfx {
|
|
|
|
struct Rect;
|
|
|
|
class SourceSurface;
|
|
|
|
}
|
|
|
|
|
2012-10-12 02:42:52 -07:00
|
|
|
namespace dom {
|
2012-06-13 08:14:15 -07:00
|
|
|
extern const mozilla::gfx::Float SIGMA_MAX;
|
|
|
|
|
2012-10-12 02:42:52 -07:00
|
|
|
template<typename T> class Optional;
|
|
|
|
|
2012-06-13 08:14:15 -07:00
|
|
|
/**
|
2012-10-12 02:42:52 -07:00
|
|
|
** CanvasGradient
|
2012-06-13 08:14:15 -07:00
|
|
|
**/
|
2012-10-12 02:42:52 -07:00
|
|
|
class CanvasGradient : public nsIDOMCanvasGradient
|
2012-06-13 08:14:15 -07:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
NS_DECLARE_STATIC_IID_ACCESSOR(NS_CANVASGRADIENTAZURE_PRIVATE_IID)
|
|
|
|
|
|
|
|
enum Type
|
|
|
|
{
|
|
|
|
LINEAR = 0,
|
|
|
|
RADIAL
|
|
|
|
};
|
|
|
|
|
|
|
|
Type GetType()
|
|
|
|
{
|
|
|
|
return mType;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
mozilla::gfx::GradientStops *
|
|
|
|
GetGradientStopsForTarget(mozilla::gfx::DrawTarget *aRT)
|
|
|
|
{
|
|
|
|
if (mStops && mStops->GetBackendType() == aRT->GetType()) {
|
|
|
|
return mStops;
|
|
|
|
}
|
|
|
|
|
|
|
|
mStops = aRT->CreateGradientStops(mRawStops.Elements(), mRawStops.Length());
|
|
|
|
|
|
|
|
return mStops;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_DECL_ISUPPORTS
|
|
|
|
|
|
|
|
/* nsIDOMCanvasGradient */
|
|
|
|
NS_IMETHOD AddColorStop(float offset, const nsAString& colorstr);
|
|
|
|
|
|
|
|
protected:
|
2012-10-12 02:42:52 -07:00
|
|
|
CanvasGradient(Type aType) : mType(aType)
|
2012-06-13 08:14:15 -07:00
|
|
|
{}
|
|
|
|
|
|
|
|
nsTArray<mozilla::gfx::GradientStop> mRawStops;
|
|
|
|
mozilla::RefPtr<mozilla::gfx::GradientStops> mStops;
|
|
|
|
Type mType;
|
2012-10-12 02:42:52 -07:00
|
|
|
virtual ~CanvasGradient() {}
|
2012-06-13 08:14:15 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
2012-10-12 02:42:52 -07:00
|
|
|
** CanvasPattern
|
2012-06-13 08:14:15 -07:00
|
|
|
**/
|
2012-10-12 02:42:52 -07:00
|
|
|
class CanvasPattern MOZ_FINAL : public nsIDOMCanvasPattern
|
2012-06-13 08:14:15 -07:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
NS_DECLARE_STATIC_IID_ACCESSOR(NS_CANVASPATTERNAZURE_PRIVATE_IID)
|
|
|
|
|
|
|
|
enum RepeatMode
|
|
|
|
{
|
|
|
|
REPEAT,
|
|
|
|
REPEATX,
|
|
|
|
REPEATY,
|
|
|
|
NOREPEAT
|
|
|
|
};
|
|
|
|
|
2012-10-12 02:42:52 -07:00
|
|
|
CanvasPattern(mozilla::gfx::SourceSurface* aSurface,
|
2012-10-12 02:42:53 -07:00
|
|
|
RepeatMode aRepeat,
|
|
|
|
nsIPrincipal* principalForSecurityCheck,
|
|
|
|
bool forceWriteOnly,
|
|
|
|
bool CORSUsed)
|
2012-06-13 08:14:15 -07:00
|
|
|
: mSurface(aSurface)
|
|
|
|
, mRepeat(aRepeat)
|
|
|
|
, mPrincipal(principalForSecurityCheck)
|
|
|
|
, mForceWriteOnly(forceWriteOnly)
|
|
|
|
, mCORSUsed(CORSUsed)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_DECL_ISUPPORTS
|
|
|
|
|
|
|
|
mozilla::RefPtr<mozilla::gfx::SourceSurface> mSurface;
|
|
|
|
const RepeatMode mRepeat;
|
|
|
|
nsCOMPtr<nsIPrincipal> mPrincipal;
|
|
|
|
const bool mForceWriteOnly;
|
|
|
|
const bool mCORSUsed;
|
|
|
|
};
|
|
|
|
|
2012-10-12 02:42:52 -07:00
|
|
|
struct CanvasBidiProcessor;
|
|
|
|
class CanvasRenderingContext2DUserData;
|
2012-06-13 08:14:15 -07:00
|
|
|
|
|
|
|
/**
|
2012-10-12 02:42:52 -07:00
|
|
|
** CanvasRenderingContext2D
|
2012-06-13 08:14:15 -07:00
|
|
|
**/
|
2012-10-12 02:42:52 -07:00
|
|
|
class CanvasRenderingContext2D :
|
2012-06-13 08:14:15 -07:00
|
|
|
public nsIDOMCanvasRenderingContext2D,
|
|
|
|
public nsICanvasRenderingContextInternal,
|
|
|
|
public nsWrapperCache
|
|
|
|
{
|
|
|
|
typedef mozilla::dom::HTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement
|
|
|
|
HTMLImageOrCanvasOrVideoElement;
|
|
|
|
|
|
|
|
public:
|
2012-10-12 02:42:52 -07:00
|
|
|
CanvasRenderingContext2D();
|
|
|
|
virtual ~CanvasRenderingContext2D();
|
2012-06-13 08:14:15 -07:00
|
|
|
|
2012-05-21 14:30:07 -07:00
|
|
|
virtual JSObject* WrapObject(JSContext *cx, JSObject *scope,
|
|
|
|
bool *triedToWrap);
|
|
|
|
|
2012-06-13 08:14:15 -07:00
|
|
|
nsHTMLCanvasElement* GetCanvas() const
|
|
|
|
{
|
|
|
|
return mCanvasElement;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Save();
|
|
|
|
void Restore();
|
|
|
|
void Scale(double x, double y, mozilla::ErrorResult& error);
|
|
|
|
void Rotate(double angle, mozilla::ErrorResult& error);
|
|
|
|
void Translate(double x, double y, mozilla::ErrorResult& error);
|
|
|
|
void Transform(double m11, double m12, double m21, double m22, double dx,
|
|
|
|
double dy, mozilla::ErrorResult& error);
|
|
|
|
void SetTransform(double m11, double m12, double m21, double m22, double dx,
|
|
|
|
double dy, mozilla::ErrorResult& error);
|
|
|
|
|
2012-09-11 12:08:24 -07:00
|
|
|
double GlobalAlpha()
|
2012-06-13 08:14:15 -07:00
|
|
|
{
|
|
|
|
return CurrentState().globalAlpha;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetGlobalAlpha(double globalAlpha)
|
|
|
|
{
|
|
|
|
if (mozilla::CanvasUtils::FloatValidate(globalAlpha) &&
|
|
|
|
globalAlpha >= 0.0 && globalAlpha <= 1.0) {
|
|
|
|
CurrentState().globalAlpha = globalAlpha;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void GetGlobalCompositeOperation(nsAString& op, mozilla::ErrorResult& error);
|
|
|
|
void SetGlobalCompositeOperation(const nsAString& op,
|
|
|
|
mozilla::ErrorResult& error);
|
|
|
|
JS::Value GetStrokeStyle(JSContext* cx, mozilla::ErrorResult& error);
|
|
|
|
|
|
|
|
void SetStrokeStyle(JSContext* cx, JS::Value& value)
|
|
|
|
{
|
|
|
|
SetStyleFromJSValue(cx, value, STYLE_STROKE);
|
|
|
|
}
|
|
|
|
|
|
|
|
JS::Value GetFillStyle(JSContext* cx, mozilla::ErrorResult& error);
|
|
|
|
|
|
|
|
void SetFillStyle(JSContext* cx, JS::Value& value)
|
|
|
|
{
|
|
|
|
SetStyleFromJSValue(cx, value, STYLE_FILL);
|
|
|
|
}
|
|
|
|
|
|
|
|
already_AddRefed<nsIDOMCanvasGradient>
|
|
|
|
CreateLinearGradient(double x0, double y0, double x1, double y1,
|
|
|
|
mozilla::ErrorResult& aError);
|
|
|
|
already_AddRefed<nsIDOMCanvasGradient>
|
|
|
|
CreateRadialGradient(double x0, double y0, double r0, double x1, double y1,
|
|
|
|
double r1, mozilla::ErrorResult& aError);
|
|
|
|
already_AddRefed<nsIDOMCanvasPattern>
|
|
|
|
CreatePattern(const HTMLImageOrCanvasOrVideoElement& element,
|
|
|
|
const nsAString& repeat, mozilla::ErrorResult& error);
|
|
|
|
|
2012-09-11 12:08:24 -07:00
|
|
|
double ShadowOffsetX()
|
2012-06-13 08:14:15 -07:00
|
|
|
{
|
|
|
|
return CurrentState().shadowOffset.x;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetShadowOffsetX(double shadowOffsetX)
|
|
|
|
{
|
|
|
|
if (mozilla::CanvasUtils::FloatValidate(shadowOffsetX)) {
|
|
|
|
CurrentState().shadowOffset.x = shadowOffsetX;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-11 12:08:24 -07:00
|
|
|
double ShadowOffsetY()
|
2012-06-13 08:14:15 -07:00
|
|
|
{
|
|
|
|
return CurrentState().shadowOffset.y;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetShadowOffsetY(double shadowOffsetY)
|
|
|
|
{
|
|
|
|
if (mozilla::CanvasUtils::FloatValidate(shadowOffsetY)) {
|
|
|
|
CurrentState().shadowOffset.y = shadowOffsetY;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-11 12:08:24 -07:00
|
|
|
double ShadowBlur()
|
2012-06-13 08:14:15 -07:00
|
|
|
{
|
|
|
|
return CurrentState().shadowBlur;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetShadowBlur(double shadowBlur)
|
|
|
|
{
|
|
|
|
if (mozilla::CanvasUtils::FloatValidate(shadowBlur) && shadowBlur >= 0.0) {
|
|
|
|
CurrentState().shadowBlur = shadowBlur;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void GetShadowColor(nsAString& shadowColor)
|
|
|
|
{
|
|
|
|
StyleColorToString(CurrentState().shadowColor, shadowColor);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetShadowColor(const nsAString& shadowColor);
|
|
|
|
void ClearRect(double x, double y, double w, double h);
|
|
|
|
void FillRect(double x, double y, double w, double h);
|
|
|
|
void StrokeRect(double x, double y, double w, double h);
|
|
|
|
void BeginPath();
|
|
|
|
void Fill();
|
|
|
|
void Stroke();
|
|
|
|
void Clip();
|
|
|
|
bool IsPointInPath(double x, double y);
|
|
|
|
void FillText(const nsAString& text, double x, double y,
|
|
|
|
const mozilla::dom::Optional<double>& maxWidth,
|
|
|
|
mozilla::ErrorResult& error);
|
|
|
|
void StrokeText(const nsAString& text, double x, double y,
|
|
|
|
const mozilla::dom::Optional<double>& maxWidth,
|
|
|
|
mozilla::ErrorResult& error);
|
|
|
|
already_AddRefed<nsIDOMTextMetrics>
|
|
|
|
MeasureText(const nsAString& rawText, mozilla::ErrorResult& error);
|
|
|
|
|
|
|
|
void DrawImage(const HTMLImageOrCanvasOrVideoElement& image,
|
|
|
|
double dx, double dy, mozilla::ErrorResult& error)
|
|
|
|
{
|
|
|
|
if (!mozilla::CanvasUtils::FloatValidate(dx, dy)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
DrawImage(image, 0.0, 0.0, 0.0, 0.0, dx, dy, 0.0, 0.0, 0, error);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DrawImage(const HTMLImageOrCanvasOrVideoElement& image,
|
|
|
|
double dx, double dy, double dw, double dh,
|
|
|
|
mozilla::ErrorResult& error)
|
|
|
|
{
|
|
|
|
if (!mozilla::CanvasUtils::FloatValidate(dx, dy, dw, dh)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
DrawImage(image, 0.0, 0.0, 0.0, 0.0, dx, dy, dw, dh, 2, error);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DrawImage(const HTMLImageOrCanvasOrVideoElement& image,
|
|
|
|
double sx, double sy, double sw, double sh, double dx,
|
|
|
|
double dy, double dw, double dh, mozilla::ErrorResult& error)
|
|
|
|
{
|
|
|
|
if (!mozilla::CanvasUtils::FloatValidate(sx, sy, sw, sh) ||
|
|
|
|
!mozilla::CanvasUtils::FloatValidate(dx, dy, dw, dh)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
DrawImage(image, sx, sy, sw, sh, dx, dy, dw, dh, 6, error);
|
|
|
|
}
|
|
|
|
|
|
|
|
already_AddRefed<mozilla::dom::ImageData>
|
|
|
|
CreateImageData(JSContext* cx, double sw, double sh,
|
|
|
|
mozilla::ErrorResult& error);
|
|
|
|
already_AddRefed<mozilla::dom::ImageData>
|
|
|
|
CreateImageData(JSContext* cx, mozilla::dom::ImageData* imagedata,
|
|
|
|
mozilla::ErrorResult& error);
|
|
|
|
already_AddRefed<mozilla::dom::ImageData>
|
|
|
|
GetImageData(JSContext* cx, double sx, double sy, double sw, double sh,
|
|
|
|
mozilla::ErrorResult& error);
|
|
|
|
void PutImageData(JSContext* cx, mozilla::dom::ImageData* imageData,
|
|
|
|
double dx, double dy, mozilla::ErrorResult& error);
|
|
|
|
void PutImageData(JSContext* cx, mozilla::dom::ImageData* imageData,
|
|
|
|
double dx, double dy, double dirtyX, double dirtyY,
|
|
|
|
double dirtyWidth, double dirtyHeight,
|
|
|
|
mozilla::ErrorResult& error);
|
|
|
|
|
2012-09-11 12:08:24 -07:00
|
|
|
double LineWidth()
|
2012-06-13 08:14:15 -07:00
|
|
|
{
|
|
|
|
return CurrentState().lineWidth;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetLineWidth(double width)
|
|
|
|
{
|
|
|
|
if (mozilla::CanvasUtils::FloatValidate(width) && width > 0.0) {
|
|
|
|
CurrentState().lineWidth = width;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void GetLineCap(nsAString& linecap);
|
|
|
|
void SetLineCap(const nsAString& linecap);
|
|
|
|
void GetLineJoin(nsAString& linejoin, mozilla::ErrorResult& error);
|
|
|
|
void SetLineJoin(const nsAString& linejoin);
|
|
|
|
|
2012-09-11 12:08:24 -07:00
|
|
|
double MiterLimit()
|
2012-06-13 08:14:15 -07:00
|
|
|
{
|
|
|
|
return CurrentState().miterLimit;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetMiterLimit(double miter)
|
|
|
|
{
|
|
|
|
if (mozilla::CanvasUtils::FloatValidate(miter) && miter > 0.0) {
|
|
|
|
CurrentState().miterLimit = miter;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void GetFont(nsAString& font)
|
|
|
|
{
|
|
|
|
font = GetFont();
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetFont(const nsAString& font, mozilla::ErrorResult& error);
|
|
|
|
void GetTextAlign(nsAString& textAlign);
|
|
|
|
void SetTextAlign(const nsAString& textAlign);
|
|
|
|
void GetTextBaseline(nsAString& textBaseline);
|
|
|
|
void SetTextBaseline(const nsAString& textBaseline);
|
|
|
|
|
|
|
|
void ClosePath()
|
|
|
|
{
|
|
|
|
EnsureWritablePath();
|
|
|
|
|
|
|
|
if (mPathBuilder) {
|
|
|
|
mPathBuilder->Close();
|
|
|
|
} else {
|
|
|
|
mDSPathBuilder->Close();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void MoveTo(double x, double y)
|
|
|
|
{
|
|
|
|
if (mozilla::CanvasUtils::FloatValidate(x, y)) {
|
|
|
|
EnsureWritablePath();
|
|
|
|
|
|
|
|
if (mPathBuilder) {
|
|
|
|
mPathBuilder->MoveTo(mozilla::gfx::Point(x, y));
|
|
|
|
} else {
|
|
|
|
mDSPathBuilder->MoveTo(mTarget->GetTransform() *
|
|
|
|
mozilla::gfx::Point(x, y));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void LineTo(double x, double y)
|
|
|
|
{
|
|
|
|
if (mozilla::CanvasUtils::FloatValidate(x, y)) {
|
|
|
|
EnsureWritablePath();
|
|
|
|
|
|
|
|
LineTo(mozilla::gfx::Point(x, y));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void QuadraticCurveTo(double cpx, double cpy, double x, double y)
|
|
|
|
{
|
|
|
|
if (mozilla::CanvasUtils::FloatValidate(cpx, cpy, x, y)) {
|
|
|
|
EnsureWritablePath();
|
|
|
|
|
|
|
|
if (mPathBuilder) {
|
|
|
|
mPathBuilder->QuadraticBezierTo(mozilla::gfx::Point(cpx, cpy),
|
|
|
|
mozilla::gfx::Point(x, y));
|
|
|
|
} else {
|
|
|
|
mozilla::gfx::Matrix transform = mTarget->GetTransform();
|
|
|
|
mDSPathBuilder->QuadraticBezierTo(transform *
|
|
|
|
mozilla::gfx::Point(cpx, cpy),
|
|
|
|
transform *
|
|
|
|
mozilla::gfx::Point(x, y));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void BezierCurveTo(double cp1x, double cp1y, double cp2x, double cp2y, double x, double y)
|
|
|
|
{
|
|
|
|
if (mozilla::CanvasUtils::FloatValidate(cp1x, cp1y, cp2x, cp2y, x, y)) {
|
|
|
|
EnsureWritablePath();
|
|
|
|
|
|
|
|
BezierTo(mozilla::gfx::Point(cp1x, cp1y),
|
|
|
|
mozilla::gfx::Point(cp2x, cp2y),
|
|
|
|
mozilla::gfx::Point(x, y));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ArcTo(double x1, double y1, double x2, double y2, double radius,
|
|
|
|
mozilla::ErrorResult& error);
|
|
|
|
void Rect(double x, double y, double w, double h);
|
|
|
|
void Arc(double x, double y, double radius, double startAngle,
|
|
|
|
double endAngle, bool anticlockwise, mozilla::ErrorResult& error);
|
|
|
|
|
|
|
|
JSObject* GetMozCurrentTransform(JSContext* cx,
|
|
|
|
mozilla::ErrorResult& error) const;
|
|
|
|
void SetMozCurrentTransform(JSContext* cx, JSObject& currentTransform,
|
|
|
|
mozilla::ErrorResult& error);
|
|
|
|
JSObject* GetMozCurrentTransformInverse(JSContext* cx,
|
|
|
|
mozilla::ErrorResult& error) const;
|
|
|
|
void SetMozCurrentTransformInverse(JSContext* cx, JSObject& currentTransform,
|
|
|
|
mozilla::ErrorResult& error);
|
|
|
|
void GetFillRule(nsAString& fillRule);
|
|
|
|
void SetFillRule(const nsAString& fillRule);
|
|
|
|
JS::Value GetMozDash(JSContext* cx, mozilla::ErrorResult& error);
|
|
|
|
void SetMozDash(JSContext* cx, const JS::Value& mozDash,
|
|
|
|
mozilla::ErrorResult& error);
|
|
|
|
|
2012-09-11 12:08:24 -07:00
|
|
|
double MozDashOffset()
|
2012-06-13 08:14:15 -07:00
|
|
|
{
|
|
|
|
return CurrentState().dashOffset;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetMozDashOffset(double mozDashOffset, mozilla::ErrorResult& error);
|
|
|
|
|
|
|
|
void GetMozTextStyle(nsAString& mozTextStyle)
|
|
|
|
{
|
|
|
|
GetFont(mozTextStyle);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetMozTextStyle(const nsAString& mozTextStyle,
|
|
|
|
mozilla::ErrorResult& error)
|
|
|
|
{
|
|
|
|
SetFont(mozTextStyle, error);
|
|
|
|
}
|
|
|
|
|
2012-09-11 12:08:24 -07:00
|
|
|
bool ImageSmoothingEnabled()
|
2012-06-13 08:14:15 -07:00
|
|
|
{
|
|
|
|
return CurrentState().imageSmoothingEnabled;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetImageSmoothingEnabled(bool imageSmoothingEnabled)
|
|
|
|
{
|
|
|
|
if (imageSmoothingEnabled != CurrentState().imageSmoothingEnabled) {
|
|
|
|
CurrentState().imageSmoothingEnabled = imageSmoothingEnabled;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DrawWindow(nsIDOMWindow* window, double x, double y, double w, double h,
|
|
|
|
const nsAString& bgColor, uint32_t flags,
|
|
|
|
mozilla::ErrorResult& error);
|
|
|
|
void AsyncDrawXULElement(nsIDOMXULElement* elem, double x, double y, double w,
|
|
|
|
double h, const nsAString& bgColor, uint32_t flags,
|
|
|
|
mozilla::ErrorResult& error);
|
|
|
|
|
|
|
|
nsresult Redraw();
|
|
|
|
|
|
|
|
// nsICanvasRenderingContextInternal
|
2012-08-22 08:56:38 -07:00
|
|
|
NS_IMETHOD SetDimensions(int32_t width, int32_t height);
|
|
|
|
NS_IMETHOD InitializeWithSurface(nsIDocShell *shell, gfxASurface *surface, int32_t width, int32_t height);
|
2012-06-13 08:14:15 -07:00
|
|
|
|
|
|
|
NS_IMETHOD Render(gfxContext *ctx,
|
|
|
|
gfxPattern::GraphicsFilter aFilter,
|
2012-08-22 08:56:38 -07:00
|
|
|
uint32_t aFlags = RenderFlagPremultAlpha);
|
2012-06-13 08:14:15 -07:00
|
|
|
NS_IMETHOD GetInputStream(const char* aMimeType,
|
|
|
|
const PRUnichar* aEncoderOptions,
|
|
|
|
nsIInputStream **aStream);
|
|
|
|
NS_IMETHOD GetThebesSurface(gfxASurface **surface);
|
|
|
|
|
|
|
|
mozilla::TemporaryRef<mozilla::gfx::SourceSurface> GetSurfaceSnapshot()
|
2012-09-29 09:32:57 -07:00
|
|
|
{ EnsureTarget(); return mTarget->Snapshot(); }
|
2012-06-13 08:14:15 -07:00
|
|
|
|
|
|
|
NS_IMETHOD SetIsOpaque(bool isOpaque);
|
|
|
|
NS_IMETHOD Reset();
|
|
|
|
already_AddRefed<CanvasLayer> GetCanvasLayer(nsDisplayListBuilder* aBuilder,
|
2012-10-12 02:42:53 -07:00
|
|
|
CanvasLayer *aOldLayer,
|
|
|
|
LayerManager *aManager);
|
2012-04-09 18:18:53 -07:00
|
|
|
virtual bool ShouldForceInactiveLayer(LayerManager *aManager);
|
2012-06-13 08:14:15 -07:00
|
|
|
void MarkContextClean();
|
|
|
|
NS_IMETHOD SetIsIPC(bool isIPC);
|
|
|
|
// this rect is in canvas device space
|
|
|
|
void Redraw(const mozilla::gfx::Rect &r);
|
|
|
|
NS_IMETHOD Redraw(const gfxRect &r) { Redraw(ToRect(r)); return NS_OK; }
|
|
|
|
|
|
|
|
// this rect is in mTarget's current user space
|
|
|
|
void RedrawUser(const gfxRect &r);
|
|
|
|
|
|
|
|
// nsISupports interface + CC
|
|
|
|
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
|
|
|
|
2012-10-12 02:42:52 -07:00
|
|
|
NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_AMBIGUOUS(CanvasRenderingContext2D,
|
2012-06-13 08:14:15 -07:00
|
|
|
nsIDOMCanvasRenderingContext2D)
|
|
|
|
|
|
|
|
// nsIDOMCanvasRenderingContext2D interface
|
|
|
|
NS_DECL_NSIDOMCANVASRENDERINGCONTEXT2D
|
|
|
|
|
|
|
|
enum Style {
|
|
|
|
STYLE_STROKE = 0,
|
|
|
|
STYLE_FILL,
|
|
|
|
STYLE_MAX
|
|
|
|
};
|
|
|
|
|
|
|
|
nsINode* GetParentObject()
|
|
|
|
{
|
|
|
|
return mCanvasElement;
|
|
|
|
}
|
|
|
|
|
|
|
|
void LineTo(const mozilla::gfx::Point& aPoint)
|
|
|
|
{
|
|
|
|
if (mPathBuilder) {
|
|
|
|
mPathBuilder->LineTo(aPoint);
|
|
|
|
} else {
|
|
|
|
mDSPathBuilder->LineTo(mTarget->GetTransform() * aPoint);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void BezierTo(const mozilla::gfx::Point& aCP1,
|
|
|
|
const mozilla::gfx::Point& aCP2,
|
|
|
|
const mozilla::gfx::Point& aCP3)
|
|
|
|
{
|
|
|
|
if (mPathBuilder) {
|
|
|
|
mPathBuilder->BezierTo(aCP1, aCP2, aCP3);
|
|
|
|
} else {
|
|
|
|
mozilla::gfx::Matrix transform = mTarget->GetTransform();
|
|
|
|
mDSPathBuilder->BezierTo(transform * aCP1,
|
|
|
|
transform * aCP2,
|
|
|
|
transform * aCP3);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-12 02:42:52 -07:00
|
|
|
friend class CanvasRenderingContext2DUserData;
|
2012-06-13 08:14:15 -07:00
|
|
|
|
|
|
|
protected:
|
|
|
|
nsresult GetImageDataArray(JSContext* aCx, int32_t aX, int32_t aY,
|
|
|
|
uint32_t aWidth, uint32_t aHeight,
|
|
|
|
JSObject** aRetval);
|
|
|
|
|
2012-07-24 03:18:39 -07:00
|
|
|
/**
|
|
|
|
* Internal method to complete initialisation, expects mTarget to have been set
|
|
|
|
*/
|
2012-08-22 08:56:38 -07:00
|
|
|
nsresult Initialize(int32_t width, int32_t height);
|
2012-07-24 03:18:39 -07:00
|
|
|
|
2012-06-13 08:14:15 -07:00
|
|
|
nsresult InitializeWithTarget(mozilla::gfx::DrawTarget *surface,
|
2012-08-22 08:56:38 -07:00
|
|
|
int32_t width, int32_t height);
|
2012-06-13 08:14:15 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* The number of living nsCanvasRenderingContexts. When this goes down to
|
|
|
|
* 0, we free the premultiply and unpremultiply tables, if they exist.
|
|
|
|
*/
|
2012-08-22 08:56:38 -07:00
|
|
|
static uint32_t sNumLivingContexts;
|
2012-06-13 08:14:15 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Lookup table used to speed up GetImageData().
|
|
|
|
*/
|
2012-08-22 08:56:38 -07:00
|
|
|
static uint8_t (*sUnpremultiplyTable)[256];
|
2012-06-13 08:14:15 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Lookup table used to speed up PutImageData().
|
|
|
|
*/
|
2012-08-22 08:56:38 -07:00
|
|
|
static uint8_t (*sPremultiplyTable)[256];
|
2012-06-13 08:14:15 -07:00
|
|
|
|
2012-05-30 17:47:27 -07:00
|
|
|
static mozilla::gfx::DrawTarget* sErrorTarget;
|
|
|
|
|
2012-06-13 08:14:15 -07:00
|
|
|
// Some helpers. Doesn't modify a color on failure.
|
|
|
|
void SetStyleFromJSValue(JSContext* cx, JS::Value& value, Style whichStyle);
|
|
|
|
void SetStyleFromString(const nsAString& str, Style whichStyle);
|
|
|
|
|
2012-10-12 02:42:52 -07:00
|
|
|
void SetStyleFromGradient(CanvasGradient *gradient, Style whichStyle)
|
2012-06-13 08:14:15 -07:00
|
|
|
{
|
|
|
|
CurrentState().SetGradientStyle(whichStyle, gradient);
|
|
|
|
}
|
|
|
|
|
2012-10-12 02:42:52 -07:00
|
|
|
void SetStyleFromPattern(CanvasPattern *pattern, Style whichStyle)
|
2012-06-13 08:14:15 -07:00
|
|
|
{
|
|
|
|
CurrentState().SetPatternStyle(whichStyle, pattern);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetStyleFromStringOrInterface(const nsAString& aStr, nsISupports *aInterface, Style aWhichStyle);
|
|
|
|
nsISupports* GetStyleAsStringOrInterface(nsAString& aStr, CanvasMultiGetterType& aType, Style aWhichStyle);
|
|
|
|
|
|
|
|
// Returns whether a color was successfully parsed.
|
|
|
|
bool ParseColor(const nsAString& aString, nscolor* aColor);
|
|
|
|
|
|
|
|
static void StyleColorToString(const nscolor& aColor, nsAString& aStr);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates the unpremultiply lookup table, if it doesn't exist.
|
|
|
|
*/
|
|
|
|
void EnsureUnpremultiplyTable();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates the premultiply lookup table, if it doesn't exist.
|
|
|
|
*/
|
|
|
|
void EnsurePremultiplyTable();
|
|
|
|
|
2012-05-30 17:47:27 -07:00
|
|
|
/**
|
|
|
|
* Creates the error target, if it doesn't exist
|
|
|
|
*/
|
|
|
|
static void EnsureErrorTarget();
|
|
|
|
|
2012-06-13 08:14:15 -07:00
|
|
|
/* This function ensures there is a writable pathbuilder available, this
|
|
|
|
* pathbuilder may be working in user space or in device space or
|
|
|
|
* device space.
|
2012-07-24 03:18:38 -07:00
|
|
|
* After calling this function mPathTransformWillUpdate will be false
|
2012-06-13 08:14:15 -07:00
|
|
|
*/
|
|
|
|
void EnsureWritablePath();
|
|
|
|
|
|
|
|
// Ensures a path in UserSpace is available.
|
2012-07-24 03:18:38 -07:00
|
|
|
// If aCommitTransform is true, then any transform on the context will be
|
|
|
|
// used for the path.
|
|
|
|
void EnsureUserSpacePath(bool aCommitTransform = true);
|
2012-06-13 08:14:15 -07:00
|
|
|
|
2012-05-30 17:47:27 -07:00
|
|
|
/**
|
|
|
|
* Needs to be called before updating the transform. This makes a call to
|
|
|
|
* EnsureTarget() so you don't have to.
|
|
|
|
*/
|
2012-06-13 08:14:15 -07:00
|
|
|
void TransformWillUpdate();
|
|
|
|
|
|
|
|
// Report the fillRule has changed.
|
|
|
|
void FillRuleChanged();
|
|
|
|
|
2012-05-30 17:47:27 -07:00
|
|
|
/**
|
|
|
|
* Create the backing surfacing, if it doesn't exist. If there is an error
|
|
|
|
* in creating the target then it will put sErrorTarget in place. If there
|
|
|
|
* is in turn an error in creating the sErrorTarget then they would both
|
|
|
|
* be null so IsTargetValid() would still return null.
|
|
|
|
*/
|
|
|
|
void EnsureTarget();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Disposes an old target and prepares to lazily create a new target.
|
|
|
|
*/
|
|
|
|
void ClearTarget();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Check if the target is valid after calling EnsureTarget.
|
|
|
|
*/
|
|
|
|
bool IsTargetValid() { return mTarget != sErrorTarget; }
|
|
|
|
|
2012-06-13 08:14:15 -07:00
|
|
|
/**
|
|
|
|
* Returns the surface format this canvas should be allocated using. Takes
|
|
|
|
* into account mOpaque, platform requirements, etc.
|
|
|
|
*/
|
|
|
|
mozilla::gfx::SurfaceFormat GetSurfaceFormat() const;
|
|
|
|
|
|
|
|
void DrawImage(const HTMLImageOrCanvasOrVideoElement &imgElt,
|
|
|
|
double sx, double sy, double sw, double sh,
|
|
|
|
double dx, double dy, double dw, double dh,
|
2012-08-22 08:56:38 -07:00
|
|
|
uint8_t optional_argc, mozilla::ErrorResult& error);
|
2012-06-13 08:14:15 -07:00
|
|
|
|
|
|
|
nsString& GetFont()
|
|
|
|
{
|
|
|
|
/* will initilize the value if not set, else does nothing */
|
|
|
|
GetCurrentFontStyle();
|
|
|
|
|
|
|
|
return CurrentState().font;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool
|
|
|
|
ToHTMLImageOrCanvasOrVideoElement(nsIDOMElement* html,
|
|
|
|
HTMLImageOrCanvasOrVideoElement& element)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIContent> content = do_QueryInterface(html);
|
|
|
|
if (content) {
|
|
|
|
if (content->IsHTML(nsGkAtoms::canvas)) {
|
|
|
|
element.SetAsHTMLCanvasElement() =
|
|
|
|
static_cast<nsHTMLCanvasElement*>(html);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (content->IsHTML(nsGkAtoms::img)) {
|
|
|
|
element.SetAsHTMLImageElement() =
|
|
|
|
static_cast<nsHTMLImageElement*>(html);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (content->IsHTML(nsGkAtoms::video)) {
|
|
|
|
element.SetAsHTMLVideoElement() =
|
|
|
|
static_cast<nsHTMLVideoElement*>(html);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Member vars
|
2012-08-22 08:56:38 -07:00
|
|
|
int32_t mWidth, mHeight;
|
2012-06-13 08:14:15 -07:00
|
|
|
|
|
|
|
// This is true when the canvas is valid, but of zero size, this requires
|
|
|
|
// specific behavior on some operations.
|
|
|
|
bool mZero;
|
|
|
|
|
|
|
|
bool mOpaque;
|
|
|
|
|
|
|
|
// This is true when the next time our layer is retrieved we need to
|
|
|
|
// recreate it (i.e. our backing surface changed)
|
|
|
|
bool mResetLayer;
|
|
|
|
// This is needed for drawing in drawAsyncXULElement
|
|
|
|
bool mIPC;
|
|
|
|
|
2012-10-12 02:42:52 -07:00
|
|
|
nsTArray<CanvasRenderingContext2DUserData*> mUserDatas;
|
2012-06-13 08:14:15 -07:00
|
|
|
|
|
|
|
// If mCanvasElement is not provided, then a docshell is
|
|
|
|
nsCOMPtr<nsIDocShell> mDocShell;
|
|
|
|
|
2012-05-30 17:47:27 -07:00
|
|
|
// This is created lazily so it is necessary to call EnsureTarget before
|
|
|
|
// accessing it. In the event of an error it will be equal to
|
|
|
|
// sErrorTarget.
|
2012-06-13 08:14:15 -07:00
|
|
|
mozilla::RefPtr<mozilla::gfx::DrawTarget> mTarget;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Flag to avoid duplicate calls to InvalidateFrame. Set to true whenever
|
|
|
|
* Redraw is called, reset to false when Render is called.
|
|
|
|
*/
|
|
|
|
bool mIsEntireFrameInvalid;
|
|
|
|
/**
|
|
|
|
* When this is set, the first call to Redraw(gfxRect) should set
|
|
|
|
* mIsEntireFrameInvalid since we expect it will be followed by
|
|
|
|
* many more Redraw calls.
|
|
|
|
*/
|
|
|
|
bool mPredictManyRedrawCalls;
|
|
|
|
|
|
|
|
// This is stored after GetThebesSurface has been called once to avoid
|
|
|
|
// excessive ThebesSurface initialization overhead.
|
|
|
|
nsRefPtr<gfxASurface> mThebesSurface;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* We also have a device space pathbuilder. The reason for this is as
|
|
|
|
* follows, when a path is being built, but the transform changes, we
|
|
|
|
* can no longer keep a single path in userspace, considering there's
|
|
|
|
* several 'user spaces' now. We therefore transform the current path
|
|
|
|
* into device space, and add all operations to this path in device
|
|
|
|
* space.
|
|
|
|
*
|
|
|
|
* When then finally executing a render, the Azure drawing API expects
|
|
|
|
* the path to be in userspace. We could then set an identity transform
|
|
|
|
* on the DrawTarget and do all drawing in device space. This is
|
|
|
|
* undesirable because it requires transforming patterns, gradients,
|
|
|
|
* clips, etc. into device space and it would not work for stroking.
|
|
|
|
* What we do instead is convert the path back to user space when it is
|
|
|
|
* drawn, and draw it with the current transform. This makes all drawing
|
|
|
|
* occur correctly.
|
|
|
|
*
|
|
|
|
* There's never both a device space path builder and a user space path
|
|
|
|
* builder present at the same time. There is also never a path and a
|
|
|
|
* path builder present at the same time. When writing proceeds on an
|
|
|
|
* existing path the Path is cleared and a new builder is created.
|
|
|
|
*
|
|
|
|
* mPath is always in user-space.
|
|
|
|
*/
|
|
|
|
mozilla::RefPtr<mozilla::gfx::Path> mPath;
|
|
|
|
mozilla::RefPtr<mozilla::gfx::PathBuilder> mDSPathBuilder;
|
|
|
|
mozilla::RefPtr<mozilla::gfx::PathBuilder> mPathBuilder;
|
|
|
|
bool mPathTransformWillUpdate;
|
|
|
|
mozilla::gfx::Matrix mPathToDS;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Number of times we've invalidated before calling redraw
|
|
|
|
*/
|
2012-08-22 08:56:38 -07:00
|
|
|
uint32_t mInvalidateCount;
|
|
|
|
static const uint32_t kCanvasMaxInvalidateCount = 100;
|
2012-06-13 08:14:15 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns true if a shadow should be drawn along with a
|
|
|
|
* drawing operation.
|
|
|
|
*/
|
|
|
|
bool NeedToDrawShadow()
|
|
|
|
{
|
|
|
|
const ContextState& state = CurrentState();
|
|
|
|
|
|
|
|
// The spec says we should not draw shadows if the operator is OVER.
|
|
|
|
// If it's over and the alpha value is zero, nothing needs to be drawn.
|
|
|
|
return NS_GET_A(state.shadowColor) != 0 &&
|
|
|
|
(state.shadowBlur != 0 || state.shadowOffset.x != 0 || state.shadowOffset.y != 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
mozilla::gfx::CompositionOp UsedOperation()
|
|
|
|
{
|
|
|
|
if (NeedToDrawShadow()) {
|
|
|
|
// In this case the shadow rendering will use the operator.
|
|
|
|
return mozilla::gfx::OP_OVER;
|
|
|
|
}
|
|
|
|
|
|
|
|
return CurrentState().op;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets the pres shell from either the canvas element or the doc shell
|
|
|
|
*/
|
|
|
|
nsIPresShell *GetPresShell() {
|
|
|
|
if (mCanvasElement) {
|
|
|
|
return mCanvasElement->OwnerDoc()->GetShell();
|
|
|
|
}
|
|
|
|
if (mDocShell) {
|
|
|
|
nsCOMPtr<nsIPresShell> shell;
|
|
|
|
mDocShell->GetPresShell(getter_AddRefs(shell));
|
|
|
|
return shell.get();
|
|
|
|
}
|
2012-07-30 07:20:58 -07:00
|
|
|
return nullptr;
|
2012-06-13 08:14:15 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// text
|
|
|
|
enum TextAlign {
|
|
|
|
TEXT_ALIGN_START,
|
|
|
|
TEXT_ALIGN_END,
|
|
|
|
TEXT_ALIGN_LEFT,
|
|
|
|
TEXT_ALIGN_RIGHT,
|
|
|
|
TEXT_ALIGN_CENTER
|
|
|
|
};
|
|
|
|
|
|
|
|
enum TextBaseline {
|
|
|
|
TEXT_BASELINE_TOP,
|
|
|
|
TEXT_BASELINE_HANGING,
|
|
|
|
TEXT_BASELINE_MIDDLE,
|
|
|
|
TEXT_BASELINE_ALPHABETIC,
|
|
|
|
TEXT_BASELINE_IDEOGRAPHIC,
|
|
|
|
TEXT_BASELINE_BOTTOM
|
|
|
|
};
|
|
|
|
|
|
|
|
gfxFontGroup *GetCurrentFontStyle();
|
|
|
|
|
|
|
|
enum TextDrawOperation {
|
|
|
|
TEXT_DRAW_OPERATION_FILL,
|
|
|
|
TEXT_DRAW_OPERATION_STROKE,
|
|
|
|
TEXT_DRAW_OPERATION_MEASURE
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Implementation of the fillText, strokeText, and measure functions with
|
|
|
|
* the operation abstracted to a flag.
|
|
|
|
*/
|
|
|
|
nsresult DrawOrMeasureText(const nsAString& text,
|
2012-10-12 02:42:53 -07:00
|
|
|
float x,
|
|
|
|
float y,
|
|
|
|
const mozilla::dom::Optional<double>& maxWidth,
|
|
|
|
TextDrawOperation op,
|
|
|
|
float* aWidth);
|
2012-06-13 08:14:15 -07:00
|
|
|
|
|
|
|
// state stack handling
|
|
|
|
class ContextState {
|
|
|
|
public:
|
2012-10-12 02:42:53 -07:00
|
|
|
ContextState() : textAlign(TEXT_ALIGN_START),
|
|
|
|
textBaseline(TEXT_BASELINE_ALPHABETIC),
|
|
|
|
lineWidth(1.0f),
|
|
|
|
miterLimit(10.0f),
|
|
|
|
globalAlpha(1.0f),
|
|
|
|
shadowBlur(0.0),
|
|
|
|
dashOffset(0.0f),
|
|
|
|
op(mozilla::gfx::OP_OVER),
|
|
|
|
fillRule(mozilla::gfx::FILL_WINDING),
|
|
|
|
lineCap(mozilla::gfx::CAP_BUTT),
|
|
|
|
lineJoin(mozilla::gfx::JOIN_MITER_OR_BEVEL),
|
|
|
|
imageSmoothingEnabled(true)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
ContextState(const ContextState& other)
|
|
|
|
: fontGroup(other.fontGroup),
|
|
|
|
font(other.font),
|
|
|
|
textAlign(other.textAlign),
|
|
|
|
textBaseline(other.textBaseline),
|
|
|
|
shadowColor(other.shadowColor),
|
|
|
|
transform(other.transform),
|
|
|
|
shadowOffset(other.shadowOffset),
|
|
|
|
lineWidth(other.lineWidth),
|
|
|
|
miterLimit(other.miterLimit),
|
|
|
|
globalAlpha(other.globalAlpha),
|
|
|
|
shadowBlur(other.shadowBlur),
|
|
|
|
dash(other.dash),
|
|
|
|
dashOffset(other.dashOffset),
|
|
|
|
op(other.op),
|
|
|
|
fillRule(other.fillRule),
|
|
|
|
lineCap(other.lineCap),
|
|
|
|
lineJoin(other.lineJoin),
|
|
|
|
imageSmoothingEnabled(other.imageSmoothingEnabled)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < STYLE_MAX; i++) {
|
|
|
|
colorStyles[i] = other.colorStyles[i];
|
|
|
|
gradientStyles[i] = other.gradientStyles[i];
|
|
|
|
patternStyles[i] = other.patternStyles[i];
|
2012-06-13 08:14:15 -07:00
|
|
|
}
|
2012-10-12 02:42:53 -07:00
|
|
|
}
|
2012-06-13 08:14:15 -07:00
|
|
|
|
2012-10-12 02:42:53 -07:00
|
|
|
void SetColorStyle(Style whichStyle, nscolor color)
|
|
|
|
{
|
|
|
|
colorStyles[whichStyle] = color;
|
|
|
|
gradientStyles[whichStyle] = nullptr;
|
|
|
|
patternStyles[whichStyle] = nullptr;
|
|
|
|
}
|
2012-06-13 08:14:15 -07:00
|
|
|
|
2012-10-12 02:42:53 -07:00
|
|
|
void SetPatternStyle(Style whichStyle, CanvasPattern* pat)
|
|
|
|
{
|
|
|
|
gradientStyles[whichStyle] = nullptr;
|
|
|
|
patternStyles[whichStyle] = pat;
|
|
|
|
}
|
2012-06-13 08:14:15 -07:00
|
|
|
|
2012-10-12 02:42:53 -07:00
|
|
|
void SetGradientStyle(Style whichStyle, CanvasGradient* grad)
|
|
|
|
{
|
|
|
|
gradientStyles[whichStyle] = grad;
|
|
|
|
patternStyles[whichStyle] = nullptr;
|
|
|
|
}
|
2012-06-13 08:14:15 -07:00
|
|
|
|
2012-10-12 02:42:53 -07:00
|
|
|
/**
|
|
|
|
* returns true iff the given style is a solid color.
|
|
|
|
*/
|
|
|
|
bool StyleIsColor(Style whichStyle) const
|
|
|
|
{
|
|
|
|
return !(patternStyles[whichStyle] || gradientStyles[whichStyle]);
|
|
|
|
}
|
2012-06-13 08:14:15 -07:00
|
|
|
|
|
|
|
|
2012-10-12 02:42:53 -07:00
|
|
|
std::vector<mozilla::RefPtr<mozilla::gfx::Path> > clipsPushed;
|
2012-06-13 08:14:15 -07:00
|
|
|
|
2012-10-12 02:42:53 -07:00
|
|
|
nsRefPtr<gfxFontGroup> fontGroup;
|
|
|
|
nsRefPtr<CanvasGradient> gradientStyles[STYLE_MAX];
|
|
|
|
nsRefPtr<CanvasPattern> patternStyles[STYLE_MAX];
|
2012-06-13 08:14:15 -07:00
|
|
|
|
2012-10-12 02:42:53 -07:00
|
|
|
nsString font;
|
|
|
|
TextAlign textAlign;
|
|
|
|
TextBaseline textBaseline;
|
2012-06-13 08:14:15 -07:00
|
|
|
|
2012-10-12 02:42:53 -07:00
|
|
|
nscolor colorStyles[STYLE_MAX];
|
|
|
|
nscolor shadowColor;
|
2012-06-13 08:14:15 -07:00
|
|
|
|
2012-10-12 02:42:53 -07:00
|
|
|
mozilla::gfx::Matrix transform;
|
|
|
|
mozilla::gfx::Point shadowOffset;
|
|
|
|
mozilla::gfx::Float lineWidth;
|
|
|
|
mozilla::gfx::Float miterLimit;
|
|
|
|
mozilla::gfx::Float globalAlpha;
|
|
|
|
mozilla::gfx::Float shadowBlur;
|
|
|
|
FallibleTArray<mozilla::gfx::Float> dash;
|
|
|
|
mozilla::gfx::Float dashOffset;
|
2012-06-13 08:14:15 -07:00
|
|
|
|
2012-10-12 02:42:53 -07:00
|
|
|
mozilla::gfx::CompositionOp op;
|
|
|
|
mozilla::gfx::FillRule fillRule;
|
|
|
|
mozilla::gfx::CapStyle lineCap;
|
|
|
|
mozilla::gfx::JoinStyle lineJoin;
|
2012-06-13 08:14:15 -07:00
|
|
|
|
2012-10-12 02:42:53 -07:00
|
|
|
bool imageSmoothingEnabled;
|
2012-06-13 08:14:15 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
nsAutoTArray<ContextState, 3> mStyleStack;
|
|
|
|
|
|
|
|
inline ContextState& CurrentState() {
|
|
|
|
return mStyleStack[mStyleStack.Length() - 1];
|
|
|
|
}
|
|
|
|
|
2012-06-29 11:20:13 -07:00
|
|
|
friend class CanvasGeneralPattern;
|
2012-06-13 08:14:15 -07:00
|
|
|
friend class AdjustedTarget;
|
|
|
|
|
|
|
|
// other helpers
|
2012-10-12 02:42:53 -07:00
|
|
|
void GetAppUnitsValues(uint32_t *perDevPixel, uint32_t *perCSSPixel)
|
|
|
|
{
|
2012-06-13 08:14:15 -07:00
|
|
|
// If we don't have a canvas element, we just return something generic.
|
2012-08-22 08:56:38 -07:00
|
|
|
uint32_t devPixel = 60;
|
|
|
|
uint32_t cssPixel = 60;
|
2012-06-13 08:14:15 -07:00
|
|
|
|
|
|
|
nsIPresShell *ps = GetPresShell();
|
|
|
|
nsPresContext *pc;
|
|
|
|
|
|
|
|
if (!ps) goto FINISH;
|
|
|
|
pc = ps->GetPresContext();
|
|
|
|
if (!pc) goto FINISH;
|
|
|
|
devPixel = pc->AppUnitsPerDevPixel();
|
|
|
|
cssPixel = pc->AppUnitsPerCSSPixel();
|
|
|
|
|
|
|
|
FINISH:
|
|
|
|
if (perDevPixel)
|
|
|
|
*perDevPixel = devPixel;
|
|
|
|
if (perCSSPixel)
|
|
|
|
*perCSSPixel = cssPixel;
|
|
|
|
}
|
|
|
|
|
2012-10-12 02:42:52 -07:00
|
|
|
friend struct CanvasBidiProcessor;
|
2012-06-13 08:14:15 -07:00
|
|
|
};
|
|
|
|
|
2012-10-12 02:42:52 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* CanvasRenderingContext2D_h */
|