| OLD | NEW |
| (Empty) |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #ifndef BaseRenderingContext2D_h | |
| 6 #define BaseRenderingContext2D_h | |
| 7 | |
| 8 #include "bindings/core/v8/UnionTypesCore.h" | |
| 9 #include "bindings/modules/v8/UnionTypesModules.h" | |
| 10 #include "core/html/canvas/CanvasRenderingContext.h" | |
| 11 #include "modules/ModulesExport.h" | |
| 12 #include "modules/canvas2d/CanvasGradient.h" | |
| 13 #include "modules/canvas2d/CanvasPathMethods.h" | |
| 14 #include "modules/canvas2d/CanvasRenderingContext2DState.h" | |
| 15 #include "modules/canvas2d/CanvasStyle.h" | |
| 16 #include "third_party/skia/include/core/SkCanvas.h" | |
| 17 | |
| 18 namespace blink { | |
| 19 | |
| 20 class CanvasImageSource; | |
| 21 class Color; | |
| 22 class Image; | |
| 23 class ImageBuffer; | |
| 24 class Path2D; | |
| 25 class SVGMatrixTearOff; | |
| 26 | |
| 27 typedef HTMLImageElementOrHTMLVideoElementOrHTMLCanvasElementOrImageBitmap Canva
sImageSourceUnion; | |
| 28 | |
| 29 class MODULES_EXPORT BaseRenderingContext2D : public WillBeGarbageCollectedMixin
, public CanvasPathMethods { | |
| 30 public: | |
| 31 ~BaseRenderingContext2D() override; | |
| 32 | |
| 33 void strokeStyle(StringOrCanvasGradientOrCanvasPattern&) const; | |
| 34 void setStrokeStyle(const StringOrCanvasGradientOrCanvasPattern&); | |
| 35 | |
| 36 void fillStyle(StringOrCanvasGradientOrCanvasPattern&) const; | |
| 37 void setFillStyle(const StringOrCanvasGradientOrCanvasPattern&); | |
| 38 | |
| 39 double lineWidth() const; | |
| 40 void setLineWidth(double); | |
| 41 | |
| 42 String lineCap() const; | |
| 43 void setLineCap(const String&); | |
| 44 | |
| 45 String lineJoin() const; | |
| 46 void setLineJoin(const String&); | |
| 47 | |
| 48 double miterLimit() const; | |
| 49 void setMiterLimit(double); | |
| 50 | |
| 51 const Vector<double>& getLineDash() const; | |
| 52 void setLineDash(const Vector<double>&); | |
| 53 | |
| 54 double lineDashOffset() const; | |
| 55 void setLineDashOffset(double); | |
| 56 | |
| 57 double shadowOffsetX() const; | |
| 58 void setShadowOffsetX(double); | |
| 59 | |
| 60 double shadowOffsetY() const; | |
| 61 void setShadowOffsetY(double); | |
| 62 | |
| 63 double shadowBlur() const; | |
| 64 void setShadowBlur(double); | |
| 65 | |
| 66 String shadowColor() const; | |
| 67 void setShadowColor(const String&); | |
| 68 | |
| 69 double globalAlpha() const; | |
| 70 void setGlobalAlpha(double); | |
| 71 | |
| 72 String globalCompositeOperation() const; | |
| 73 void setGlobalCompositeOperation(const String&); | |
| 74 | |
| 75 String filter() const; | |
| 76 void setFilter(const String&); | |
| 77 | |
| 78 void save(); | |
| 79 void restore(); | |
| 80 | |
| 81 PassRefPtrWillBeRawPtr<SVGMatrixTearOff> currentTransform() const; | |
| 82 void setCurrentTransform(PassRefPtrWillBeRawPtr<SVGMatrixTearOff>); | |
| 83 | |
| 84 void scale(double sx, double sy); | |
| 85 void rotate(double angleInRadians); | |
| 86 void translate(double tx, double ty); | |
| 87 void transform(double m11, double m12, double m21, double m22, double dx, do
uble dy); | |
| 88 void setTransform(double m11, double m12, double m21, double m22, double dx,
double dy); | |
| 89 void resetTransform(); | |
| 90 | |
| 91 void beginPath(); | |
| 92 | |
| 93 void fill(const String& winding = "nonzero"); | |
| 94 void fill(Path2D*, const String& winding = "nonzero"); | |
| 95 void stroke(); | |
| 96 void stroke(Path2D*); | |
| 97 void clip(const String& winding = "nonzero"); | |
| 98 void clip(Path2D*, const String& winding = "nonzero"); | |
| 99 | |
| 100 bool isPointInPath(const double x, const double y, const String& winding = "
nonzero"); | |
| 101 bool isPointInPath(Path2D*, const double x, const double y, const String& wi
nding = "nonzero"); | |
| 102 bool isPointInStroke(const double x, const double y); | |
| 103 bool isPointInStroke(Path2D*, const double x, const double y); | |
| 104 | |
| 105 void clearRect(double x, double y, double width, double height); | |
| 106 void fillRect(double x, double y, double width, double height); | |
| 107 void strokeRect(double x, double y, double width, double height); | |
| 108 | |
| 109 void drawImage(const CanvasImageSourceUnion&, double x, double y, ExceptionS
tate&); | |
| 110 void drawImage(const CanvasImageSourceUnion&, double x, double y, double wid
th, double height, ExceptionState&); | |
| 111 void drawImage(const CanvasImageSourceUnion&, double sx, double sy, double s
w, double sh, double dx, double dy, double dw, double dh, ExceptionState&); | |
| 112 void drawImage(CanvasImageSource*, double sx, double sy, double sw, double s
h, double dx, double dy, double dw, double dh, ExceptionState&); | |
| 113 | |
| 114 CanvasGradient* createLinearGradient(double x0, double y0, double x1, double
y1); | |
| 115 CanvasGradient* createRadialGradient(double x0, double y0, double r0, double
x1, double y1, double r1, ExceptionState&); | |
| 116 CanvasPattern* createPattern(const CanvasImageSourceUnion&, const String& re
petitionType, ExceptionState&); | |
| 117 | |
| 118 ImageData* createImageData(ImageData*) const; | |
| 119 ImageData* createImageData(double width, double height, ExceptionState&) con
st; | |
| 120 ImageData* getImageData(double sx, double sy, double sw, double sh, Exceptio
nState&) const; | |
| 121 void putImageData(ImageData*, double dx, double dy, ExceptionState&); | |
| 122 void putImageData(ImageData*, double dx, double dy, double dirtyX, double di
rtyY, double dirtyWidth, double dirtyHeight, ExceptionState&); | |
| 123 | |
| 124 bool imageSmoothingEnabled() const; | |
| 125 void setImageSmoothingEnabled(bool); | |
| 126 String imageSmoothingQuality() const; | |
| 127 void setImageSmoothingQuality(const String&); | |
| 128 | |
| 129 virtual bool originClean() const = 0; | |
| 130 virtual void setOriginTainted() = 0; | |
| 131 virtual bool wouldTaintOrigin(CanvasImageSource*) = 0; | |
| 132 | |
| 133 virtual int width() const = 0; | |
| 134 virtual int height() const = 0; | |
| 135 | |
| 136 virtual bool hasImageBuffer() const = 0; | |
| 137 virtual ImageBuffer* imageBuffer() const = 0; | |
| 138 | |
| 139 virtual bool parseColorOrCurrentColor(Color&, const String& colorString) con
st = 0; | |
| 140 | |
| 141 virtual SkCanvas* drawingCanvas() const = 0; | |
| 142 virtual SkCanvas* existingDrawingCanvas() const = 0; | |
| 143 virtual void disableDeferral(DisableDeferralReason) = 0; | |
| 144 | |
| 145 virtual AffineTransform baseTransform() const = 0; | |
| 146 | |
| 147 virtual void didDraw(const SkIRect& dirtyRect) = 0; | |
| 148 | |
| 149 virtual bool stateHasFilter() = 0; | |
| 150 virtual SkImageFilter* stateGetFilter() = 0; | |
| 151 | |
| 152 virtual void validateStateStack() = 0; | |
| 153 | |
| 154 virtual bool hasAlpha() const = 0; | |
| 155 | |
| 156 virtual bool isContextLost() const = 0; | |
| 157 | |
| 158 DECLARE_VIRTUAL_TRACE(); | |
| 159 | |
| 160 protected: | |
| 161 BaseRenderingContext2D(); | |
| 162 | |
| 163 CanvasRenderingContext2DState& modifiableState(); | |
| 164 const CanvasRenderingContext2DState& state() const { return *m_stateStack.la
st(); } | |
| 165 | |
| 166 bool computeDirtyRect(const FloatRect& localBounds, SkIRect*); | |
| 167 bool computeDirtyRect(const FloatRect& localBounds, const SkIRect& transform
edClipBounds, SkIRect*); | |
| 168 | |
| 169 template<typename DrawFunc, typename ContainsFunc> | |
| 170 bool draw(const DrawFunc&, const ContainsFunc&, const SkRect& bounds, Canvas
RenderingContext2DState::PaintType, CanvasRenderingContext2DState::ImageType = C
anvasRenderingContext2DState::NoImage); | |
| 171 | |
| 172 void inflateStrokeRect(FloatRect&) const; | |
| 173 | |
| 174 enum DrawType { | |
| 175 ClipFill, // Fill that is already known to cover the current clip | |
| 176 UntransformedUnclippedFill | |
| 177 }; | |
| 178 | |
| 179 void checkOverdraw(const SkRect&, const SkPaint*, CanvasRenderingContext2DSt
ate::ImageType, DrawType); | |
| 180 | |
| 181 WillBeHeapVector<OwnPtrWillBeMember<CanvasRenderingContext2DState>> m_stateS
tack; | |
| 182 AntiAliasingMode m_clipAntialiasing; | |
| 183 | |
| 184 private: | |
| 185 void realizeSaves(); | |
| 186 | |
| 187 bool shouldDrawImageAntialiased(const FloatRect& destRect) const; | |
| 188 | |
| 189 void drawPathInternal(const Path&, CanvasRenderingContext2DState::PaintType,
SkPath::FillType = SkPath::kWinding_FillType); | |
| 190 void drawImageInternal(SkCanvas*, CanvasImageSource*, Image*, const FloatRec
t& srcRect, const FloatRect& dstRect, const SkPaint*); | |
| 191 void clipInternal(const Path&, const String& windingRuleString); | |
| 192 | |
| 193 bool isPointInPathInternal(const Path&, const double x, const double y, cons
t String& windingRuleString); | |
| 194 bool isPointInStrokeInternal(const Path&, const double x, const double y); | |
| 195 | |
| 196 static bool isFullCanvasCompositeMode(SkXfermode::Mode); | |
| 197 | |
| 198 template<typename DrawFunc> | |
| 199 void compositedDraw(const DrawFunc&, SkCanvas*, CanvasRenderingContext2DStat
e::PaintType, CanvasRenderingContext2DState::ImageType); | |
| 200 | |
| 201 void clearCanvas(); | |
| 202 bool rectContainsTransformedRect(const FloatRect&, const SkIRect&) const; | |
| 203 }; | |
| 204 | |
| 205 template<typename DrawFunc, typename ContainsFunc> | |
| 206 bool BaseRenderingContext2D::draw(const DrawFunc& drawFunc, const ContainsFunc&
drawCoversClipBounds, const SkRect& bounds, CanvasRenderingContext2DState::Paint
Type paintType, CanvasRenderingContext2DState::ImageType imageType) | |
| 207 { | |
| 208 if (!state().isTransformInvertible()) | |
| 209 return false; | |
| 210 | |
| 211 SkIRect clipBounds; | |
| 212 if (!drawingCanvas() || !drawingCanvas()->getClipDeviceBounds(&clipBounds)) | |
| 213 return false; | |
| 214 | |
| 215 // If gradient size is zero, then paint nothing. | |
| 216 CanvasStyle* style = state().style(paintType); | |
| 217 if (style) { | |
| 218 CanvasGradient* gradient = style->canvasGradient(); | |
| 219 if (gradient && gradient->gradient()->isZeroSize()) | |
| 220 return false; | |
| 221 } | |
| 222 | |
| 223 if (isFullCanvasCompositeMode(state().globalComposite()) || stateHasFilter()
) { | |
| 224 compositedDraw(drawFunc, drawingCanvas(), paintType, imageType); | |
| 225 didDraw(clipBounds); | |
| 226 } else if (state().globalComposite() == SkXfermode::kSrc_Mode) { | |
| 227 clearCanvas(); // takes care of checkOverdraw() | |
| 228 const SkPaint* paint = state().getPaint(paintType, DrawForegroundOnly, i
mageType); | |
| 229 drawFunc(drawingCanvas(), paint); | |
| 230 didDraw(clipBounds); | |
| 231 } else { | |
| 232 SkIRect dirtyRect; | |
| 233 if (computeDirtyRect(bounds, clipBounds, &dirtyRect)) { | |
| 234 const SkPaint* paint = state().getPaint(paintType, DrawShadowAndFore
ground, imageType); | |
| 235 if (paintType != CanvasRenderingContext2DState::StrokePaintType && d
rawCoversClipBounds(clipBounds)) | |
| 236 checkOverdraw(bounds, paint, imageType, ClipFill); | |
| 237 drawFunc(drawingCanvas(), paint); | |
| 238 didDraw(dirtyRect); | |
| 239 } | |
| 240 } | |
| 241 return true; | |
| 242 } | |
| 243 | |
| 244 template<typename DrawFunc> | |
| 245 void BaseRenderingContext2D::compositedDraw(const DrawFunc& drawFunc, SkCanvas*
c, CanvasRenderingContext2DState::PaintType paintType, CanvasRenderingContext2DS
tate::ImageType imageType) | |
| 246 { | |
| 247 SkImageFilter* filter = stateGetFilter(); | |
| 248 ASSERT(isFullCanvasCompositeMode(state().globalComposite()) || filter); | |
| 249 SkMatrix ctm = c->getTotalMatrix(); | |
| 250 c->resetMatrix(); | |
| 251 SkPaint compositePaint; | |
| 252 compositePaint.setXfermodeMode(state().globalComposite()); | |
| 253 if (state().shouldDrawShadows()) { | |
| 254 // unroll into two independently composited passes if drawing shadows | |
| 255 SkPaint shadowPaint = *state().getPaint(paintType, DrawShadowOnly, image
Type); | |
| 256 int saveCount = c->getSaveCount(); | |
| 257 if (filter) { | |
| 258 SkPaint filterPaint; | |
| 259 filterPaint.setImageFilter(filter); | |
| 260 // TODO(junov): crbug.com/502921 We could use primitive bounds if we
knew that the filter | |
| 261 // does not affect transparent black regions. | |
| 262 c->saveLayer(nullptr, &shadowPaint); | |
| 263 c->saveLayer(nullptr, &filterPaint); | |
| 264 SkPaint foregroundPaint = *state().getPaint(paintType, DrawForegroun
dOnly, imageType); | |
| 265 c->setMatrix(ctm); | |
| 266 drawFunc(c, &foregroundPaint); | |
| 267 } else { | |
| 268 ASSERT(isFullCanvasCompositeMode(state().globalComposite())); | |
| 269 c->saveLayer(nullptr, &compositePaint); | |
| 270 shadowPaint.setXfermodeMode(SkXfermode::kSrcOver_Mode); | |
| 271 c->setMatrix(ctm); | |
| 272 drawFunc(c, &shadowPaint); | |
| 273 } | |
| 274 c->restoreToCount(saveCount); | |
| 275 } | |
| 276 | |
| 277 compositePaint.setImageFilter(filter); | |
| 278 // TODO(junov): crbug.com/502921 We could use primitive bounds if we knew th
at the filter | |
| 279 // does not affect transparent black regions *and* !isFullCanvasCompositeMod
e | |
| 280 c->saveLayer(nullptr, &compositePaint); | |
| 281 SkPaint foregroundPaint = *state().getPaint(paintType, DrawForegroundOnly, i
mageType); | |
| 282 foregroundPaint.setXfermodeMode(SkXfermode::kSrcOver_Mode); | |
| 283 c->setMatrix(ctm); | |
| 284 drawFunc(c, &foregroundPaint); | |
| 285 c->restore(); | |
| 286 c->setMatrix(ctm); | |
| 287 } | |
| 288 | |
| 289 } // namespace blink | |
| 290 | |
| 291 #endif // BaseRenderingContext2D_h | |
| OLD | NEW |