2 * Copyright (C) 2003, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
3 * Copyright (C) 2008-2009 Torch Mobile, Inc.
4 * Copyright (C) 2013 Google Inc. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
16 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #ifndef GraphicsContext_h
29 #define GraphicsContext_h
31 #include "platform/PlatformExport.h"
32 #include "platform/fonts/Font.h"
33 #include "platform/geometry/FloatRect.h"
34 #include "platform/graphics/DashArray.h"
35 #include "platform/graphics/DrawLooperBuilder.h"
36 #include "platform/graphics/ImageBufferSurface.h"
37 #include "platform/graphics/ImageOrientation.h"
38 #include "platform/graphics/GraphicsContextAnnotation.h"
39 #include "platform/graphics/GraphicsContextState.h"
40 #include "platform/graphics/RegionTracker.h"
41 #include "wtf/FastAllocBase.h"
42 #include "wtf/Forward.h"
43 #include "wtf/Noncopyable.h"
44 #include "wtf/PassOwnPtr.h"
58 typedef SkImageFilter ImageFilter;
60 class PLATFORM_EXPORT GraphicsContext {
61 WTF_MAKE_NONCOPYABLE(GraphicsContext); WTF_MAKE_FAST_ALLOCATED;
63 enum AntiAliasingMode {
73 NothingDisabled = 0, // Run as normal.
74 FullyDisabled = 1 // Do absolutely minimal work to remove the cost of the context from performance tests.
77 explicit GraphicsContext(SkCanvas*, DisabledMode = NothingDisabled);
80 // Returns the canvas used for painting. Must not be called if painting is disabled.
81 // Accessing the backing canvas this way flushes all queued save ops,
82 // so it should be avoided. Use the corresponding draw/matrix/clip methods instead.
85 // Flush any pending saves.
90 const SkCanvas* canvas() const
95 void resetCanvas(SkCanvas*);
97 bool contextDisabled() const { return m_disabledState; }
99 // ---------- State management methods -----------------
102 unsigned saveCount() { return m_canvasStateStack.size(); }
104 void disableDestructionChecks() { m_disableDestructionChecks = true; }
107 void saveLayer(const SkRect* bounds, const SkPaint*);
110 bool hasStroke() const { return strokeStyle() != NoStroke && strokeThickness() > 0; }
112 float strokeThickness() const { return immutableState()->strokeData().thickness(); }
113 void setStrokeThickness(float thickness) { mutableState()->setStrokeThickness(thickness); }
115 StrokeStyle strokeStyle() const { return immutableState()->strokeData().style(); }
116 void setStrokeStyle(StrokeStyle style) { mutableState()->setStrokeStyle(style); }
118 Color strokeColor() const { return immutableState()->strokeData().color(); }
119 void setStrokeColor(const Color& color) { mutableState()->setStrokeColor(color); }
120 SkColor effectiveStrokeColor() const { return immutableState()->effectiveStrokeColor(); }
122 Pattern* strokePattern() const { return immutableState()->strokeData().pattern(); }
123 void setStrokePattern(PassRefPtr<Pattern>);
125 Gradient* strokeGradient() const { return immutableState()->strokeData().gradient(); }
126 void setStrokeGradient(PassRefPtr<Gradient>);
128 void setLineCap(LineCap cap) { mutableState()->setLineCap(cap); }
129 void setLineDash(const DashArray& dashes, float dashOffset) { mutableState()->setLineDash(dashes, dashOffset); }
130 void setLineJoin(LineJoin join) { mutableState()->setLineJoin(join); }
131 void setMiterLimit(float limit) { mutableState()->setMiterLimit(limit); }
133 WindRule fillRule() const { return immutableState()->fillRule(); }
134 void setFillRule(WindRule fillRule) { mutableState()->setFillRule(fillRule); }
136 Color fillColor() const { return immutableState()->fillColor(); }
137 void setFillColor(const Color& color) { mutableState()->setFillColor(color); }
138 SkColor effectiveFillColor() const { return immutableState()->effectiveFillColor(); }
140 void setFillPattern(PassRefPtr<Pattern>);
141 Pattern* fillPattern() const { return immutableState()->fillPattern(); }
143 void setFillGradient(PassRefPtr<Gradient>);
144 Gradient* fillGradient() const { return immutableState()->fillGradient(); }
146 SkDrawLooper* drawLooper() const { return immutableState()->drawLooper(); }
148 bool getTransformedClipBounds(FloatRect* bounds) const;
149 SkMatrix getTotalMatrix() const;
151 void setShouldAntialias(bool antialias) { mutableState()->setShouldAntialias(antialias); }
152 bool shouldAntialias() const { return immutableState()->shouldAntialias(); }
154 // Disable the anti-aliasing optimization for scales/multiple-of-90-degrees
155 // rotations of thin ("hairline") images.
156 // Note: This will only be reliable when the device pixel scale/ratio is
157 // fixed (e.g. when drawing to context backed by an ImageBuffer).
158 void disableAntialiasingOptimizationForHairlineImages() { ASSERT(!isRecording()); m_antialiasHairlineImages = true; }
159 bool shouldAntialiasHairlineImages() const { return m_antialiasHairlineImages; }
161 void setShouldClampToSourceRect(bool clampToSourceRect) { mutableState()->setShouldClampToSourceRect(clampToSourceRect); }
162 bool shouldClampToSourceRect() const { return immutableState()->shouldClampToSourceRect(); }
164 void setShouldSmoothFonts(bool smoothFonts) { mutableState()->setShouldSmoothFonts(smoothFonts); }
165 bool shouldSmoothFonts() const { return immutableState()->shouldSmoothFonts(); }
167 // Turn off LCD text for the paint if not supported on this context.
168 void adjustTextRenderMode(SkPaint*);
169 bool couldUseLCDRenderedText();
171 void setTextDrawingMode(TextDrawingModeFlags mode) { mutableState()->setTextDrawingMode(mode); }
172 TextDrawingModeFlags textDrawingMode() const { return immutableState()->textDrawingMode(); }
174 void setAlphaAsFloat(float alpha) { mutableState()->setAlphaAsFloat(alpha);}
175 int getNormalizedAlpha() const
177 int alpha = immutableState()->alpha();
178 return alpha > 255 ? 255 : alpha;
181 void setImageInterpolationQuality(InterpolationQuality quality) { mutableState()->setInterpolationQuality(quality); }
182 InterpolationQuality imageInterpolationQuality() const { return immutableState()->interpolationQuality(); }
184 void setCompositeOperation(CompositeOperator, WebBlendMode = WebBlendModeNormal);
185 CompositeOperator compositeOperation() const { return immutableState()->compositeOperator(); }
186 WebBlendMode blendModeOperation() const { return immutableState()->blendMode(); }
188 // Speicy the device scale factor which may change the way document markers
189 // and fonts are rendered.
190 void setDeviceScaleFactor(float factor) { m_deviceScaleFactor = factor; }
191 float deviceScaleFactor() const { return m_deviceScaleFactor; }
193 // If true we are (most likely) rendering to a web page and the
194 // canvas has been prepared with an opaque background. If false,
195 // the canvas may have transparency (as is the case when rendering
196 // to a canvas object).
197 void setCertainlyOpaque(bool isOpaque) { m_isCertainlyOpaque = isOpaque; }
198 bool isCertainlyOpaque() const { return m_isCertainlyOpaque; }
200 // Returns if the context is a printing context instead of a display
201 // context. Bitmap shouldn't be resampled when printing to keep the best
203 bool printing() const { return m_printing; }
204 void setPrinting(bool printing) { m_printing = printing; }
206 bool isAccelerated() const { return m_accelerated; }
207 void setAccelerated(bool accelerated) { m_accelerated = accelerated; }
209 // The opaque region is empty until tracking is turned on.
210 // It is never clerared by the context.
211 enum RegionTrackingMode {
212 RegionTrackingDisabled = 0,
213 RegionTrackingOpaque,
214 RegionTrackingOverwrite
216 void setRegionTrackingMode(RegionTrackingMode);
217 bool regionTrackingEnabled() { return m_regionTrackingMode != RegionTrackingDisabled; }
218 const RegionTracker& opaqueRegion() const { return m_trackedRegion; }
220 // The text region is empty until tracking is turned on.
221 // It is never clerared by the context.
222 void setTrackTextRegion(bool track) { m_trackTextRegion = track; }
223 const SkRect& textRegion() const { return m_textRegion; }
225 AnnotationModeFlags annotationMode() const { return m_annotationMode; }
226 void setAnnotationMode(const AnnotationModeFlags mode) { m_annotationMode = mode; }
228 SkColorFilter* colorFilter() const;
229 void setColorFilter(ColorFilter);
230 // ---------- End state management methods -----------------
232 // Get the contents of the image buffer
233 bool readPixels(const SkImageInfo&, void* pixels, size_t rowBytes, int x, int y);
235 // Get the current fill style.
236 const SkPaint& fillPaint() const { return immutableState()->fillPaint(); }
238 // Get the current stroke style.
239 const SkPaint& strokePaint() const { return immutableState()->strokePaint(); }
241 // These draw methods will do both stroking and filling.
242 // FIXME: ...except drawRect(), which fills properly but always strokes
243 // using a 1-pixel stroke inset from the rect borders (of the correct
245 void drawRect(const IntRect&);
246 void drawLine(const IntPoint&, const IntPoint&);
247 void drawConvexPolygon(size_t numPoints, const FloatPoint*, bool shouldAntialias = false);
249 void fillPath(const Path&);
250 void strokePath(const Path&);
252 void fillEllipse(const FloatRect&);
253 void strokeEllipse(const FloatRect&);
255 void fillRect(const FloatRect&);
256 void fillRect(const FloatRect&, const Color&);
257 void fillRect(const FloatRect&, const Color&, CompositeOperator);
258 void fillRoundedRect(const IntRect&, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color&);
259 void fillRoundedRect(const RoundedRect&, const Color&);
261 void clearRect(const FloatRect&);
263 void strokeRect(const FloatRect&);
264 void strokeRect(const FloatRect&, float lineWidth);
266 void fillBetweenRoundedRects(const IntRect&, const IntSize& outerTopLeft, const IntSize& outerTopRight, const IntSize& outerBottomLeft, const IntSize& outerBottomRight,
267 const IntRect&, const IntSize& innerTopLeft, const IntSize& innerTopRight, const IntSize& innerBottomLeft, const IntSize& innerBottomRight, const Color&);
268 void fillBetweenRoundedRects(const RoundedRect&, const RoundedRect&, const Color&);
270 void drawDisplayList(DisplayList*);
272 void drawImage(Image*, const IntPoint&, CompositeOperator = CompositeSourceOver, RespectImageOrientationEnum = DoNotRespectImageOrientation);
273 void drawImage(Image*, const IntRect&, CompositeOperator = CompositeSourceOver, RespectImageOrientationEnum = DoNotRespectImageOrientation);
274 void drawImage(Image*, const FloatRect& destRect);
275 void drawImage(Image*, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator = CompositeSourceOver, RespectImageOrientationEnum = DoNotRespectImageOrientation);
276 void drawImage(Image*, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator, WebBlendMode, RespectImageOrientationEnum = DoNotRespectImageOrientation);
278 void drawTiledImage(Image*, const IntRect& destRect, const IntPoint& srcPoint, const IntSize& tileSize,
279 CompositeOperator = CompositeSourceOver, WebBlendMode = WebBlendModeNormal, const IntSize& repeatSpacing = IntSize());
280 void drawTiledImage(Image*, const IntRect& destRect, const IntRect& srcRect,
281 const FloatSize& tileScaleFactor, Image::TileRule hRule = Image::StretchTile, Image::TileRule vRule = Image::StretchTile,
282 CompositeOperator = CompositeSourceOver);
284 void drawImageBuffer(ImageBuffer*, const FloatRect& destRect, const FloatRect* srcRect = 0, CompositeOperator = CompositeSourceOver, WebBlendMode = WebBlendModeNormal);
286 void drawPicture(PassRefPtr<SkPicture>, const FloatRect& dest, const FloatRect& src, CompositeOperator, WebBlendMode);
288 // These methods write to the canvas and modify the opaque region, if tracked.
289 // Also drawLine(const IntPoint& point1, const IntPoint& point2) and fillRoundedRect
290 void writePixels(const SkImageInfo&, const void* pixels, size_t rowBytes, int x, int y);
291 void writePixels(const SkBitmap&, int x, int y);
292 void drawBitmap(const SkBitmap&, SkScalar, SkScalar, const SkPaint* = 0);
293 void drawBitmapRect(const SkBitmap&, const SkRect*, const SkRect&, const SkPaint* = 0);
294 void drawOval(const SkRect&, const SkPaint&);
295 void drawPath(const SkPath&, const SkPaint&);
296 // After drawing directly to the context's canvas, use this function to notify the context so
297 // it can track the opaque region.
298 // FIXME: this is still needed only because ImageSkia::paintSkBitmap() may need to notify for a
299 // smaller rect than the one drawn to, due to its clipping logic.
300 void didDrawRect(const SkRect&, const SkPaint&, const SkBitmap* = 0);
301 void drawRect(const SkRect&, const SkPaint&);
302 void drawPosText(const void* text, size_t byteLength, const SkPoint pos[], const SkRect& textRect, const SkPaint&);
303 void drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], SkScalar constY, const SkRect& textRect, const SkPaint&);
305 void clip(const IntRect& rect) { clipRect(rect); }
306 void clip(const FloatRect& rect) { clipRect(rect); }
307 void clipRoundedRect(const RoundedRect&, SkRegion::Op = SkRegion::kIntersect_Op);
308 void clipOut(const IntRect& rect) { clipRect(rect, NotAntiAliased, SkRegion::kDifference_Op); }
309 void clipOutRoundedRect(const RoundedRect&);
310 void clipPath(const Path&, WindRule = RULE_EVENODD);
311 void clipConvexPolygon(size_t numPoints, const FloatPoint*, bool antialias = true);
312 void clipRect(const SkRect&, AntiAliasingMode = NotAntiAliased, SkRegion::Op = SkRegion::kIntersect_Op);
314 void drawText(const Font&, const TextRunPaintInfo&, const FloatPoint&);
315 void drawEmphasisMarks(const Font&, const TextRunPaintInfo&, const AtomicString& mark, const FloatPoint&);
316 void drawBidiText(const Font&, const TextRunPaintInfo&, const FloatPoint&, Font::CustomFontNotReadyAction = Font::DoNotPaintIfFontNotReady);
317 void drawHighlightForText(const Font&, const TextRun&, const FloatPoint&, int h, const Color& backgroundColor, int from = 0, int to = -1);
319 void drawLineForText(const FloatPoint&, float width, bool printing);
320 enum DocumentMarkerLineStyle {
321 DocumentMarkerSpellingLineStyle,
322 DocumentMarkerGrammarLineStyle
324 void drawLineForDocumentMarker(const FloatPoint&, float width, DocumentMarkerLineStyle);
326 void beginTransparencyLayer(float opacity, const FloatRect* = 0);
327 void beginLayer(float opacity, CompositeOperator, const FloatRect* = 0, ColorFilter = ColorFilterNone, ImageFilter* = 0);
330 void beginCull(const FloatRect&);
333 // Instead of being dispatched to the active canvas, draw commands following beginRecording()
334 // are stored in a display list that can be replayed at a later time.
335 void beginRecording(const FloatRect& bounds);
336 PassRefPtr<DisplayList> endRecording();
338 bool hasShadow() const;
339 void setShadow(const FloatSize& offset, float blur, const Color&,
340 DrawLooperBuilder::ShadowTransformMode = DrawLooperBuilder::ShadowRespectsTransforms,
341 DrawLooperBuilder::ShadowAlphaMode = DrawLooperBuilder::ShadowRespectsAlpha);
342 void clearShadow() { clearDrawLooper(); }
344 // It is assumed that this draw looper is used only for shadows
345 // (i.e. a draw looper is set if and only if there is a shadow).
346 // The builder passed into this method will be destroyed.
347 void setDrawLooper(PassOwnPtr<DrawLooperBuilder>);
348 void clearDrawLooper();
350 void drawFocusRing(const Vector<IntRect>&, int width, int offset, const Color&);
351 void drawFocusRing(const Path&, int width, int offset, const Color&);
360 typedef unsigned Edges;
361 void drawInnerShadow(const RoundedRect&, const Color& shadowColor, const IntSize shadowOffset, int shadowBlur, int shadowSpread, Edges clippedEdges = NoEdge);
363 // This clip function is used only by <canvas> code. It allows
364 // implementations to handle clipping on the canvas differently since
365 // the discipline is different.
366 void canvasClip(const Path&, WindRule = RULE_EVENODD);
367 void clipOut(const Path&);
369 // ---------- Transformation methods -----------------
370 // Note that the getCTM method returns only the current transform from Blink's perspective,
371 // which is not the final transform used to place content on screen. It cannot be relied upon
372 // for testing where a point will appear on screen or how large it will be.
373 AffineTransform getCTM() const;
374 void concatCTM(const AffineTransform& affine) { concat(affineTransformToSkMatrix(affine)); }
375 void setCTM(const AffineTransform& affine) { setMatrix(affineTransformToSkMatrix(affine)); }
376 void setMatrix(const SkMatrix&);
378 void scale(float x, float y);
379 void rotate(float angleInRadians);
380 void translate(float x, float y);
382 // This function applies the device scale factor to the context, making the context capable of
383 // acting as a base-level context for a HiDPI environment.
384 void applyDeviceScaleFactor(float deviceScaleFactor) { scale(deviceScaleFactor, deviceScaleFactor); }
385 // ---------- End transformation methods -----------------
388 void setURLForRect(const KURL&, const IntRect&);
389 void setURLFragmentForRect(const String& name, const IntRect&);
390 void addURLTargetAtPoint(const String& name, const IntPoint&);
391 bool supportsURLFragments() { return printing(); }
393 // Create an image buffer compatible with this context, with suitable resolution
394 // for drawing into the buffer and then into this context.
395 PassOwnPtr<ImageBuffer> createRasterBuffer(const IntSize&, OpacityMode = NonOpaque) const;
397 static void adjustLineToPixelBoundaries(FloatPoint& p1, FloatPoint& p2, float strokeWidth, StrokeStyle);
399 void beginAnnotation(const AnnotationList&);
400 void endAnnotation();
402 void preparePaintForDrawRectToRect(
404 const SkRect& srcRect,
405 const SkRect& destRect,
408 bool isLazyDecoded = false,
409 bool isDataComplete = true) const;
411 static int focusRingOutsetExtent(int offset, int width)
413 return focusRingOutset(offset) + (focusRingWidth(width) + 1) / 2;
417 const GraphicsContextState* immutableState() const { return m_paintState; }
419 GraphicsContextState* mutableState()
425 static void setPathFromConvexPoints(SkPath*, size_t, const FloatPoint*);
426 static void setRadii(SkVector*, IntSize, IntSize, IntSize, IntSize);
428 static PassRefPtr<SkColorFilter> WebCoreColorFilterToSkiaColorFilter(ColorFilter);
431 static inline int focusRingOutset(int offset) { return offset + 2; }
432 static inline int focusRingWidth(int width) { return width; }
434 static inline int focusRingOutset(int offset) { return 0; }
435 static inline int focusRingWidth(int width) { return 1; }
436 static const SkPMColor lineColors(int);
437 static const SkPMColor antiColors1(int);
438 static const SkPMColor antiColors2(int);
439 static void draw1xMarker(SkBitmap*, int);
440 static void draw2xMarker(SkBitmap*, int);
443 // Helpers for drawing a focus ring (drawFocusRing)
444 float prepareFocusRingPaint(SkPaint&, const Color&, int width) const;
445 void drawFocusRingPath(const SkPath&, const Color&, int width);
446 void drawFocusRingRect(const SkRect&, const Color&, int width);
449 // SkCanvas wrappers.
450 void clipPath(const SkPath&, AntiAliasingMode = NotAntiAliased, SkRegion::Op = SkRegion::kIntersect_Op);
451 void clipRRect(const SkRRect&, AntiAliasingMode = NotAntiAliased, SkRegion::Op = SkRegion::kIntersect_Op);
452 void concat(const SkMatrix&);
453 void drawRRect(const SkRRect&, const SkPaint&);
455 // Apply deferred paint state saves
456 void realizePaintSave()
458 if (contextDisabled())
461 if (m_paintState->saveCount()) {
462 m_paintState->decrementSaveCount();
464 if (m_paintStateStack.size() == m_paintStateIndex) {
465 m_paintStateStack.append(GraphicsContextState::createAndCopy(*m_paintState));
466 m_paintState = m_paintStateStack[m_paintStateIndex].get();
468 GraphicsContextState* priorPaintState = m_paintState;
469 m_paintState = m_paintStateStack[m_paintStateIndex].get();
470 m_paintState->copy(*priorPaintState);
475 // Apply deferred canvas state saves
476 void realizeCanvasSave()
478 if (!m_pendingCanvasSave || contextDisabled())
482 m_pendingCanvasSave = false;
485 void didDrawTextInRect(const SkRect& textRect);
487 void fillRectWithRoundedHole(const IntRect&, const RoundedRect& roundedHoleRect, const Color&);
489 bool isRecording() const;
491 // null indicates painting is contextDisabled. Never delete this object.
494 // Paint states stack. Enables local drawing state change with save()/restore() calls.
495 // This state controls the appearance of drawn content.
496 // We do not delete from this stack to avoid memory churn.
497 Vector<OwnPtr<GraphicsContextState> > m_paintStateStack;
498 // Current index on the stack. May not be the last thing on the stack.
499 unsigned m_paintStateIndex;
500 // Raw pointer to the current state.
501 GraphicsContextState* m_paintState;
503 // Currently pending save flags for Skia Canvas state.
504 // Canvas state includes the canavs, it's matrix and clips. Think of it as _where_
505 // the draw operations will happen.
506 struct CanvasSaveState;
507 Vector<CanvasSaveState> m_canvasStateStack;
508 bool m_pendingCanvasSave;
510 AnnotationModeFlags m_annotationMode;
512 struct RecordingState;
513 Vector<RecordingState> m_recordingStateStack;
516 unsigned m_annotationCount;
517 unsigned m_layerCount;
518 bool m_disableDestructionChecks;
520 // Tracks the region painted opaque via the GraphicsContext.
521 RegionTracker m_trackedRegion;
523 // Tracks the region where text is painted via the GraphicsContext.
526 unsigned m_disabledState;
528 float m_deviceScaleFactor;
530 // Activation for the above region tracking features
531 unsigned m_regionTrackingMode : 2;
532 bool m_trackTextRegion : 1;
534 bool m_accelerated : 1;
535 bool m_isCertainlyOpaque : 1;
537 bool m_antialiasHairlineImages : 1;
542 #endif // GraphicsContext_h