#include "platform/graphics/DashArray.h"
#include "platform/graphics/DrawLooperBuilder.h"
#include "platform/graphics/ImageBufferSurface.h"
+#include "platform/graphics/ImageFilter.h"
#include "platform/graphics/ImageOrientation.h"
#include "platform/graphics/GraphicsContextAnnotation.h"
#include "platform/graphics/GraphicsContextState.h"
-#include "platform/graphics/skia/OpaqueRegionSkia.h"
+#include "platform/graphics/RegionTracker.h"
+#include "platform/graphics/skia/SkiaUtils.h"
#include "wtf/FastAllocBase.h"
#include "wtf/Forward.h"
#include "wtf/Noncopyable.h"
class SkPaint;
class SkPath;
class SkRRect;
+class SkTextBlob;
struct SkRect;
-namespace WebCore {
+namespace blink {
class DisplayList;
class ImageBuffer;
class KURL;
-typedef SkImageFilter ImageFilter;
-
class PLATFORM_EXPORT GraphicsContext {
WTF_MAKE_NONCOPYABLE(GraphicsContext); WTF_MAKE_FAST_ALLOCATED;
public:
enum DisabledMode {
NothingDisabled = 0, // Run as normal.
- PaintingDisabled = 1, // Do not issue painting calls to the canvas but maintain state correctly.
- FullyDisabled = 2 // Do absolutely minimal work to remove the cost of the context from performance tests.
+ FullyDisabled = 1 // Do absolutely minimal work to remove the cost of the context from performance tests.
};
+ // A 0 canvas is allowed, but in such cases the context must only have canvas
+ // related commands called when within a beginRecording/endRecording block.
+ // Furthermore, save/restore calls must be balanced any time the canvas is 0.
explicit GraphicsContext(SkCanvas*, DisabledMode = NothingDisabled);
+
~GraphicsContext();
// Returns the canvas used for painting. Must not be called if painting is disabled.
// so it should be avoided. Use the corresponding draw/matrix/clip methods instead.
SkCanvas* canvas()
{
- ASSERT(!paintingDisabled());
-
// Flush any pending saves.
realizeCanvasSave();
}
const SkCanvas* canvas() const
{
- ASSERT(!paintingDisabled());
return m_canvas;
}
- bool paintingDisabled() const { return m_disabledState & PaintingDisabled; }
- bool contextDisabled() const { return m_disabledState; }
- // This is just a heuristic that currently happens to work. We need either
- // a more reliable way to know that we are recording, or (better) we need
- // to obviate the need for this query, and address whatever the caller
- // needed in some other way.
- // See bug# 372110
- bool isRecordingCanvas() const
- {
- return m_canvas->imageInfo().colorType() == kUnknown_SkColorType;
- }
+ void resetCanvas(SkCanvas*);
+
+ bool contextDisabled() const { return m_disabledState; }
// ---------- State management methods -----------------
void save();
void restore();
unsigned saveCount() { return m_canvasStateStack.size(); }
-#if ASSERT_ENABLED
+#if ENABLE(ASSERT)
void disableDestructionChecks() { m_disableDestructionChecks = true; }
#endif
void saveLayer(const SkRect* bounds, const SkPaint*);
void restoreLayer();
+ bool hasStroke() const { return strokeStyle() != NoStroke && strokeThickness() > 0; }
+
float strokeThickness() const { return immutableState()->strokeData().thickness(); }
void setStrokeThickness(float thickness) { mutableState()->setStrokeThickness(thickness); }
StrokeStyle strokeStyle() const { return immutableState()->strokeData().style(); }
void setStrokeStyle(StrokeStyle style) { mutableState()->setStrokeStyle(style); }
- Color strokeColor() const { return immutableState()->strokeData().color(); }
+ Color strokeColor() const { return immutableState()->strokeColor(); }
void setStrokeColor(const Color& color) { mutableState()->setStrokeColor(color); }
SkColor effectiveStrokeColor() const { return immutableState()->effectiveStrokeColor(); }
- Pattern* strokePattern() const { return immutableState()->strokeData().pattern(); }
+ Pattern* strokePattern() const { return immutableState()->strokePattern(); }
void setStrokePattern(PassRefPtr<Pattern>);
- Gradient* strokeGradient() const { return immutableState()->strokeData().gradient(); }
+ Gradient* strokeGradient() const { return immutableState()->strokeGradient(); }
void setStrokeGradient(PassRefPtr<Gradient>);
void setLineCap(LineCap cap) { mutableState()->setLineCap(cap); }
void setShouldClampToSourceRect(bool clampToSourceRect) { mutableState()->setShouldClampToSourceRect(clampToSourceRect); }
bool shouldClampToSourceRect() const { return immutableState()->shouldClampToSourceRect(); }
- void setShouldSmoothFonts(bool smoothFonts) { mutableState()->setShouldSmoothFonts(smoothFonts); }
- bool shouldSmoothFonts() const { return immutableState()->shouldSmoothFonts(); }
+ // FIXME: the setter is only used once, at construction time; convert to a constructor param,
+ // and possibly consolidate with other flags (paintDisabled, isPrinting, ...)
+ void setShouldSmoothFonts(bool smoothFonts) { m_shouldSmoothFonts = smoothFonts; }
+ bool shouldSmoothFonts() const { return m_shouldSmoothFonts; }
// Turn off LCD text for the paint if not supported on this context.
- void adjustTextRenderMode(SkPaint*);
- bool couldUseLCDRenderedText();
+ void adjustTextRenderMode(SkPaint*) const;
+ bool couldUseLCDRenderedText() const;
void setTextDrawingMode(TextDrawingModeFlags mode) { mutableState()->setTextDrawingMode(mode); }
TextDrawingModeFlags textDrawingMode() const { return immutableState()->textDrawingMode(); }
void setImageInterpolationQuality(InterpolationQuality quality) { mutableState()->setInterpolationQuality(quality); }
InterpolationQuality imageInterpolationQuality() const { return immutableState()->interpolationQuality(); }
- void setCompositeOperation(CompositeOperator, blink::WebBlendMode = blink::WebBlendModeNormal);
+ void setCompositeOperation(CompositeOperator, WebBlendMode = WebBlendModeNormal);
CompositeOperator compositeOperation() const { return immutableState()->compositeOperator(); }
- blink::WebBlendMode blendModeOperation() const { return immutableState()->blendMode(); }
+ WebBlendMode blendModeOperation() const { return immutableState()->blendMode(); }
- // Change the way document markers are rendered.
- // Any deviceScaleFactor higher than 1.5 is enough to justify setting this flag.
- void setUseHighResMarkers(bool isHighRes) { m_useHighResMarker = isHighRes; }
+ // Speicy the device scale factor which may change the way document markers
+ // and fonts are rendered.
+ void setDeviceScaleFactor(float factor) { m_deviceScaleFactor = factor; }
+ float deviceScaleFactor() const { return m_deviceScaleFactor; }
// If true we are (most likely) rendering to a web page and the
// canvas has been prepared with an opaque background. If false,
// The opaque region is empty until tracking is turned on.
// It is never clerared by the context.
- void setTrackOpaqueRegion(bool track) { m_trackOpaqueRegion = track; }
- const OpaqueRegionSkia& opaqueRegion() const { return m_opaqueRegion; }
+ enum RegionTrackingMode {
+ RegionTrackingDisabled = 0,
+ RegionTrackingOpaque,
+ RegionTrackingOverwrite
+ };
+ void setRegionTrackingMode(RegionTrackingMode);
+ bool regionTrackingEnabled() { return m_regionTrackingMode != RegionTrackingDisabled; }
+ const RegionTracker& opaqueRegion() const { return m_trackedRegion; }
// The text region is empty until tracking is turned on.
// It is never clerared by the context.
void setTrackTextRegion(bool track) { m_trackTextRegion = track; }
const SkRect& textRegion() const { return m_textRegion; }
- bool updatingControlTints() const { return m_updatingControlTints; }
- void setUpdatingControlTints(bool updatingTints) { m_updatingControlTints = updatingTints; }
-
AnnotationModeFlags annotationMode() const { return m_annotationMode; }
void setAnnotationMode(const AnnotationModeFlags mode) { m_annotationMode = mode; }
- SkColorFilter* colorFilter();
+ SkColorFilter* colorFilter() const;
void setColorFilter(ColorFilter);
// ---------- End state management methods -----------------
void drawImage(Image*, const IntRect&, CompositeOperator = CompositeSourceOver, RespectImageOrientationEnum = DoNotRespectImageOrientation);
void drawImage(Image*, const FloatRect& destRect);
void drawImage(Image*, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator = CompositeSourceOver, RespectImageOrientationEnum = DoNotRespectImageOrientation);
- void drawImage(Image*, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator, blink::WebBlendMode, RespectImageOrientationEnum = DoNotRespectImageOrientation);
+ void drawImage(Image*, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator, WebBlendMode, RespectImageOrientationEnum = DoNotRespectImageOrientation);
void drawTiledImage(Image*, const IntRect& destRect, const IntPoint& srcPoint, const IntSize& tileSize,
- CompositeOperator = CompositeSourceOver, blink::WebBlendMode = blink::WebBlendModeNormal, const IntSize& repeatSpacing = IntSize());
+ CompositeOperator = CompositeSourceOver, WebBlendMode = WebBlendModeNormal, const IntSize& repeatSpacing = IntSize());
void drawTiledImage(Image*, const IntRect& destRect, const IntRect& srcRect,
const FloatSize& tileScaleFactor, Image::TileRule hRule = Image::StretchTile, Image::TileRule vRule = Image::StretchTile,
CompositeOperator = CompositeSourceOver);
- void drawImageBuffer(ImageBuffer*, const FloatRect& destRect, const FloatRect* srcRect = 0, CompositeOperator = CompositeSourceOver);
+ void drawImageBuffer(ImageBuffer*, const FloatRect& destRect, const FloatRect* srcRect = 0, CompositeOperator = CompositeSourceOver, WebBlendMode = WebBlendModeNormal);
+
+ void drawPicture(PassRefPtr<SkPicture>, const FloatRect& dest, const FloatRect& src, CompositeOperator, WebBlendMode);
// These methods write to the canvas and modify the opaque region, if tracked.
// Also drawLine(const IntPoint& point1, const IntPoint& point2) and fillRoundedRect
void didDrawRect(const SkRect&, const SkPaint&, const SkBitmap* = 0);
void drawRect(const SkRect&, const SkPaint&);
void drawPosText(const void* text, size_t byteLength, const SkPoint pos[], const SkRect& textRect, const SkPaint&);
+ void drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], SkScalar constY, const SkRect& textRect, const SkPaint&);
+ void drawTextBlob(const SkTextBlob*, const SkPoint& origin, const SkPaint&);
void clip(const IntRect& rect) { clipRect(rect); }
void clip(const FloatRect& rect) { clipRect(rect); }
void clipRoundedRect(const RoundedRect&, SkRegion::Op = SkRegion::kIntersect_Op);
void clipOut(const IntRect& rect) { clipRect(rect, NotAntiAliased, SkRegion::kDifference_Op); }
+ void clipOut(const Path&);
void clipOutRoundedRect(const RoundedRect&);
void clipPath(const Path&, WindRule = RULE_EVENODD);
void clipConvexPolygon(size_t numPoints, const FloatPoint*, bool antialias = true);
void clipRect(const SkRect&, AntiAliasingMode = NotAntiAliased, SkRegion::Op = SkRegion::kIntersect_Op);
+ // This clip function is used only by <canvas> code. It allows
+ // implementations to handle clipping on the canvas differently since
+ // the discipline is different.
+ void canvasClip(const Path&, WindRule = RULE_EVENODD);
void drawText(const Font&, const TextRunPaintInfo&, const FloatPoint&);
void drawEmphasisMarks(const Font&, const TextRunPaintInfo&, const AtomicString& mark, const FloatPoint&);
void endCull();
// Instead of being dispatched to the active canvas, draw commands following beginRecording()
- // are stored in a display list that can be replayed at a later time.
- void beginRecording(const FloatRect& bounds);
+ // are stored in a display list that can be replayed at a later time. Pass in the bounding
+ // rectangle for the content in the list.
+ void beginRecording(const FloatRect&, uint32_t = 0);
PassRefPtr<DisplayList> endRecording();
bool hasShadow() const;
typedef unsigned Edges;
void drawInnerShadow(const RoundedRect&, const Color& shadowColor, const IntSize shadowOffset, int shadowBlur, int shadowSpread, Edges clippedEdges = NoEdge);
- // This clip function is used only by <canvas> code. It allows
- // implementations to handle clipping on the canvas differently since
- // the discipline is different.
- void canvasClip(const Path&, WindRule = RULE_EVENODD);
- void clipOut(const Path&);
-
// ---------- Transformation methods -----------------
// Note that the getCTM method returns only the current transform from Blink's perspective,
// which is not the final transform used to place content on screen. It cannot be relied upon
void setURLForRect(const KURL&, const IntRect&);
void setURLFragmentForRect(const String& name, const IntRect&);
void addURLTargetAtPoint(const String& name, const IntPoint&);
- bool supportsURLFragments() { return printing(); }
// Create an image buffer compatible with this context, with suitable resolution
// for drawing into the buffer and then into this context.
- PassOwnPtr<ImageBuffer> createCompatibleBuffer(const IntSize&, OpacityMode = NonOpaque) const;
+ PassOwnPtr<ImageBuffer> createRasterBuffer(const IntSize&, OpacityMode = NonOpaque) const;
static void adjustLineToPixelBoundaries(FloatPoint& p1, FloatPoint& p2, float strokeWidth, StrokeStyle);
- void beginAnnotation(const char*, const char*, const String&, const String&, const String&);
+ void beginAnnotation(const AnnotationList&);
void endAnnotation();
+ void preparePaintForDrawRectToRect(
+ SkPaint*,
+ const SkRect& srcRect,
+ const SkRect& destRect,
+ CompositeOperator,
+ WebBlendMode,
+ bool isLazyDecoded = false,
+ bool isDataComplete = true) const;
+
+ static int focusRingOutsetExtent(int offset, int width)
+ {
+ return focusRingOutset(offset) + (focusRingWidth(width) + 1) / 2;
+ }
+
private:
const GraphicsContextState* immutableState() const { return m_paintState; }
static PassRefPtr<SkColorFilter> WebCoreColorFilterToSkiaColorFilter(ColorFilter);
#if OS(MACOSX)
- static inline int getFocusRingOutset(int offset) { return offset + 2; }
+ static inline int focusRingOutset(int offset) { return offset + 2; }
+ static inline int focusRingWidth(int width) { return width; }
#else
- static inline int getFocusRingOutset(int offset) { return 0; }
- static const SkPMColor lineColors(int);
- static const SkPMColor antiColors1(int);
- static const SkPMColor antiColors2(int);
+ static inline int focusRingOutset(int offset) { return 0; }
+ static inline int focusRingWidth(int width) { return 1; }
+ static SkPMColor lineColors(int);
+ static SkPMColor antiColors1(int);
+ static SkPMColor antiColors2(int);
static void draw1xMarker(SkBitmap*, int);
static void draw2xMarker(SkBitmap*, int);
#endif
// Helpers for drawing a focus ring (drawFocusRing)
- void drawOuterPath(const SkPath&, SkPaint&, int);
- void drawInnerPath(const SkPath&, SkPaint&, int);
+ float prepareFocusRingPaint(SkPaint&, const Color&, int width) const;
+ void drawFocusRingPath(const SkPath&, const Color&, int width);
+ void drawFocusRingRect(const SkRect&, const Color&, int width);
// SkCanvas wrappers.
void clipPath(const SkPath&, AntiAliasingMode = NotAntiAliased, SkRegion::Op = SkRegion::kIntersect_Op);
void clipRRect(const SkRRect&, AntiAliasingMode = NotAntiAliased, SkRegion::Op = SkRegion::kIntersect_Op);
-
void concat(const SkMatrix&);
+ void drawRRect(const SkRRect&, const SkPaint&);
// Apply deferred paint state saves
void realizePaintSave()
if (!m_pendingCanvasSave || contextDisabled())
return;
+ ASSERT(m_canvas); // m_pendingCanvasSave should never be true when no canvas.
m_canvas->save();
m_pendingCanvasSave = false;
}
struct RecordingState;
Vector<RecordingState> m_recordingStateStack;
-#if ASSERT_ENABLED
+#if ENABLE(ASSERT)
unsigned m_annotationCount;
unsigned m_layerCount;
bool m_disableDestructionChecks;
#endif
// Tracks the region painted opaque via the GraphicsContext.
- OpaqueRegionSkia m_opaqueRegion;
+ RegionTracker m_trackedRegion;
// Tracks the region where text is painted via the GraphicsContext.
SkRect m_textRegion;
unsigned m_disabledState;
+ float m_deviceScaleFactor;
+
// Activation for the above region tracking features
- bool m_trackOpaqueRegion : 1;
+ unsigned m_regionTrackingMode : 2;
bool m_trackTextRegion : 1;
- // Are we on a high DPI display? If so, spelling and grammar markers are larger.
- bool m_useHighResMarker : 1;
- // FIXME: Make this go away: crbug.com/236892
- bool m_updatingControlTints : 1;
bool m_accelerated : 1;
bool m_isCertainlyOpaque : 1;
bool m_printing : 1;
bool m_antialiasHairlineImages : 1;
+ bool m_shouldSmoothFonts : 1;
};
-} // namespace WebCore
+} // namespace blink
#endif // GraphicsContext_h