#ifndef GraphicsContext_h
#define GraphicsContext_h
#include "platform/PlatformExport.h"
#include "platform/TraceEvent.h"
#include "platform/fonts/Font.h"
#include "platform/geometry/FloatRect.h"
#include "platform/graphics/DashArray.h"
#include "platform/graphics/DrawLooperBuilder.h"
#include "platform/graphics/ImageBufferSurface.h"
#include "platform/graphics/ImageOrientation.h"
#include "platform/graphics/GraphicsContextAnnotation.h"
#include "platform/graphics/GraphicsContextState.h"
#include "platform/graphics/skia/OpaqueRegionSkia.h"
#include "wtf/FastAllocBase.h"
#include "wtf/Forward.h"
#include "wtf/Noncopyable.h"
#include "wtf/PassOwnPtr.h"
class SkBitmap;
class SkPaint;
class SkPath;
class SkRRect;
struct SkRect;
namespace WebCore {
class DisplayList;
class ImageBuffer;
class KURL;
typedef SkImageFilter ImageFilter;
class PLATFORM_EXPORT GraphicsContext {
WTF_MAKE_NONCOPYABLE(GraphicsContext); WTF_MAKE_FAST_ALLOCATED;
public:
enum AntiAliasingMode {
NotAntiAliased,
AntiAliased
};
enum AccessMode {
ReadOnly,
ReadWrite
};
explicit GraphicsContext(SkCanvas*);
~GraphicsContext();
SkCanvas* canvas()
{
realizeCanvasSave();
return m_canvas;
}
const SkCanvas* canvas() const { return m_canvas; }
bool paintingDisabled() const { return !m_canvas; }
void save();
void restore();
void saveLayer(const SkRect* bounds, const SkPaint*);
void restoreLayer();
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(); }
void setStrokeColor(const Color& color) { mutableState()->setStrokeColor(color); }
SkColor effectiveStrokeColor() const { return immutableState()->effectiveStrokeColor(); }
Pattern* strokePattern() const { return immutableState()->strokeData().pattern(); }
void setStrokePattern(PassRefPtr<Pattern>);
Gradient* strokeGradient() const { return immutableState()->strokeData().gradient(); }
void setStrokeGradient(PassRefPtr<Gradient>);
void setLineCap(LineCap cap) { mutableState()->setLineCap(cap); }
void setLineDash(const DashArray& dashes, float dashOffset) { mutableState()->setLineDash(dashes, dashOffset); }
void setLineJoin(LineJoin join) { mutableState()->setLineJoin(join); }
void setMiterLimit(float limit) { mutableState()->setMiterLimit(limit); }
WindRule fillRule() const { return immutableState()->fillRule(); }
void setFillRule(WindRule fillRule) { mutableState()->setFillRule(fillRule); }
Color fillColor() const { return immutableState()->fillColor(); }
void setFillColor(const Color& color) { mutableState()->setFillColor(color); }
SkColor effectiveFillColor() const { return immutableState()->effectiveFillColor(); }
void setFillPattern(PassRefPtr<Pattern>);
Pattern* fillPattern() const { return immutableState()->fillPattern(); }
void setFillGradient(PassRefPtr<Gradient>);
Gradient* fillGradient() const { return immutableState()->fillGradient(); }
SkDrawLooper* drawLooper() const { return immutableState()->drawLooper(); }
FloatRect getClipBounds() const;
bool getTransformedClipBounds(FloatRect* bounds) const;
SkMatrix getTotalMatrix() const;
void setShouldAntialias(bool antialias) { mutableState()->setShouldAntialias(antialias); }
bool shouldAntialias() const { return immutableState()->shouldAntialias(); }
void disableAntialiasingOptimizationForHairlineImages() { ASSERT(!isRecording()); m_antialiasHairlineImages = true; }
bool shouldAntialiasHairlineImages() const { return m_antialiasHairlineImages; }
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(); }
void adjustTextRenderMode(SkPaint*);
bool couldUseLCDRenderedText();
void setTextDrawingMode(TextDrawingModeFlags mode) { mutableState()->setTextDrawingMode(mode); }
TextDrawingModeFlags textDrawingMode() const { return immutableState()->textDrawingMode(); }
void setAlphaAsFloat(float alpha) { mutableState()->setAlphaAsFloat(alpha);}
int getNormalizedAlpha() const
{
int alpha = immutableState()->alpha();
return alpha > 255 ? 255 : alpha;
}
void setImageInterpolationQuality(InterpolationQuality quality) { mutableState()->setInterpolationQuality(quality); }
InterpolationQuality imageInterpolationQuality() const { return immutableState()->interpolationQuality(); }
void setCompositeOperation(CompositeOperator, blink::WebBlendMode = blink::WebBlendModeNormal);
CompositeOperator compositeOperation() const { return immutableState()->compositeOperator(); }
blink::WebBlendMode blendModeOperation() const { return immutableState()->blendMode(); }
void setUseHighResMarkers(bool isHighRes) { m_useHighResMarker = isHighRes; }
void setCertainlyOpaque(bool isOpaque) { m_isCertainlyOpaque = isOpaque; }
bool isCertainlyOpaque() const { return m_isCertainlyOpaque; }
bool printing() const { return m_printing; }
void setPrinting(bool printing) { m_printing = printing; }
bool isAccelerated() const { return m_accelerated; }
void setAccelerated(bool accelerated) { m_accelerated = accelerated; }
void setTrackOpaqueRegion(bool track) { m_trackOpaqueRegion = track; }
const OpaqueRegionSkia& opaqueRegion() const { return m_opaqueRegion; }
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();
void setColorFilter(ColorFilter);
bool readPixels(const SkImageInfo&, void* pixels, size_t rowBytes, int x, int y);
void setupPaintForFilling(SkPaint*) const;
void setupPaintForStroking(SkPaint*) const;
void drawRect(const IntRect&);
void drawLine(const IntPoint&, const IntPoint&);
void drawEllipse(const IntRect&);
void drawConvexPolygon(size_t numPoints, const FloatPoint*, bool shouldAntialias = false);
void fillPath(const Path&);
void strokePath(const Path&);
void fillEllipse(const FloatRect&);
void strokeEllipse(const FloatRect&);
void fillRect(const FloatRect&);
void fillRect(const FloatRect&, const Color&);
void fillRect(const FloatRect&, const Color&, CompositeOperator);
void fillRoundedRect(const IntRect&, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color&);
void fillRoundedRect(const RoundedRect&, const Color&);
void clearRect(const FloatRect&);
void strokeRect(const FloatRect&, float lineWidth);
void fillBetweenRoundedRects(const IntRect&, const IntSize& outerTopLeft, const IntSize& outerTopRight, const IntSize& outerBottomLeft, const IntSize& outerBottomRight,
const IntRect&, const IntSize& innerTopLeft, const IntSize& innerTopRight, const IntSize& innerBottomLeft, const IntSize& innerBottomRight, const Color&);
void fillBetweenRoundedRects(const RoundedRect&, const RoundedRect&, const Color&);
void drawDisplayList(DisplayList*);
void drawImage(Image*, const IntPoint&, CompositeOperator = CompositeSourceOver, RespectImageOrientationEnum = DoNotRespectImageOrientation);
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 drawTiledImage(Image*, const IntRect& destRect, const IntPoint& srcPoint, const IntSize& tileSize,
CompositeOperator = CompositeSourceOver, blink::WebBlendMode = blink::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 IntPoint&, CompositeOperator = CompositeSourceOver, blink::WebBlendMode = blink::WebBlendModeNormal);
void drawImageBuffer(ImageBuffer*, const IntRect&, CompositeOperator = CompositeSourceOver, blink::WebBlendMode = blink::WebBlendModeNormal);
void drawImageBuffer(ImageBuffer*, const IntPoint& destPoint, const IntRect& srcRect, CompositeOperator = CompositeSourceOver, blink::WebBlendMode = blink::WebBlendModeNormal);
void drawImageBuffer(ImageBuffer*, const IntRect& destRect, const IntRect& srcRect, CompositeOperator = CompositeSourceOver, blink::WebBlendMode = blink::WebBlendModeNormal);
void drawImageBuffer(ImageBuffer*, const FloatRect& destRect);
void drawImageBuffer(ImageBuffer*, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator = CompositeSourceOver, blink::WebBlendMode = blink::WebBlendModeNormal);
void writePixels(const SkImageInfo&, const void* pixels, size_t rowBytes, int x, int y);
void writePixels(const SkBitmap&, int x, int y);
void drawBitmap(const SkBitmap&, SkScalar, SkScalar, const SkPaint* = 0);
void drawBitmapRect(const SkBitmap&, const SkRect*, const SkRect&, const SkPaint* = 0);
void drawOval(const SkRect&, const SkPaint&);
void drawPath(const SkPath&, const SkPaint&);
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 drawTextOnPath(const void* text, size_t byteLength, const SkPath&, const SkRect& textRect, const SkMatrix*, 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 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);
void drawText(const Font&, const TextRunPaintInfo&, const FloatPoint&);
void drawEmphasisMarks(const Font&, const TextRunPaintInfo&, const AtomicString& mark, const FloatPoint&);
void drawBidiText(const Font&, const TextRunPaintInfo&, const FloatPoint&, Font::CustomFontNotReadyAction = Font::DoNotPaintIfFontNotReady);
void drawHighlightForText(const Font&, const TextRun&, const FloatPoint&, int h, const Color& backgroundColor, int from = 0, int to = -1);
void drawLineForText(const FloatPoint&, float width, bool printing);
enum DocumentMarkerLineStyle {
DocumentMarkerSpellingLineStyle,
DocumentMarkerGrammarLineStyle
};
void drawLineForDocumentMarker(const FloatPoint&, float width, DocumentMarkerLineStyle);
void beginTransparencyLayer(float opacity, const FloatRect* = 0);
void beginLayer(float opacity, CompositeOperator, const FloatRect* = 0, ColorFilter = ColorFilterNone, ImageFilter* = 0);
void endLayer();
void beginCull(const FloatRect&);
void endCull();
void beginRecording(const FloatRect& bounds);
PassRefPtr<DisplayList> endRecording();
bool hasShadow() const;
void setShadow(const FloatSize& offset, float blur, const Color&,
DrawLooperBuilder::ShadowTransformMode = DrawLooperBuilder::ShadowRespectsTransforms,
DrawLooperBuilder::ShadowAlphaMode = DrawLooperBuilder::ShadowRespectsAlpha);
void clearShadow() { clearDrawLooper(); }
void setDrawLooper(PassOwnPtr<DrawLooperBuilder>);
void clearDrawLooper();
void drawFocusRing(const Vector<IntRect>&, int width, int offset, const Color&);
void drawFocusRing(const Path&, int width, int offset, const Color&);
enum Edge {
NoEdge = 0,
TopEdge = 1 << 1,
RightEdge = 1 << 2,
BottomEdge = 1 << 3,
LeftEdge = 1 << 4
};
typedef unsigned Edges;
void drawInnerShadow(const RoundedRect&, const Color& shadowColor, const IntSize shadowOffset, int shadowBlur, int shadowSpread, Edges clippedEdges = NoEdge);
void canvasClip(const Path&, WindRule = RULE_EVENODD);
void clipOut(const Path&);
enum IncludeDeviceScale { DefinitelyIncludeDeviceScale, PossiblyIncludeDeviceScale };
AffineTransform getCTM(IncludeDeviceScale includeScale = PossiblyIncludeDeviceScale) const;
void concatCTM(const AffineTransform& affine) { concat(affineTransformToSkMatrix(affine)); }
void setCTM(const AffineTransform& affine) { setMatrix(affineTransformToSkMatrix(affine)); }
void setMatrix(const SkMatrix&);
void scale(const FloatSize&);
void rotate(float angleInRadians);
void translate(const FloatSize& size) { translate(size.width(), size.height()); }
void translate(float x, float y);
void applyDeviceScaleFactor(float deviceScaleFactor) { scale(FloatSize(deviceScaleFactor, deviceScaleFactor)); }
void setURLForRect(const KURL&, const IntRect&);
void setURLFragmentForRect(const String& name, const IntRect&);
void addURLTargetAtPoint(const String& name, const IntPoint&);
bool supportsURLFragments() { return printing(); }
PassOwnPtr<ImageBuffer> createCompatibleBuffer(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 endAnnotation();
private:
const GraphicsContextState* immutableState() const { return m_paintState; }
GraphicsContextState* mutableState()
{
realizePaintSave();
return m_paintState;
}
static void setPathFromConvexPoints(SkPath*, size_t, const FloatPoint*);
static void setRadii(SkVector*, IntSize, IntSize, IntSize, IntSize);
static PassRefPtr<SkColorFilter> WebCoreColorFilterToSkiaColorFilter(ColorFilter);
#if OS(MACOSX)
static inline int getFocusRingOutset(int offset) { return offset + 2; }
#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 void draw1xMarker(SkBitmap*, int);
static void draw2xMarker(SkBitmap*, int);
#endif
static int fastMod(int value, int max)
{
bool isNeg = false;
if (value < 0) {
value = -value;
isNeg = true;
}
if (value >= max)
value %= max;
if (isNeg)
value = -value;
return value;
}
void drawOuterPath(const SkPath&, SkPaint&, int);
void drawInnerPath(const SkPath&, SkPaint&, int);
bool isDrawingToLayer() const { return m_canvas->isDrawingToLayer(); }
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 setupShader(SkPaint*, Gradient*, Pattern*, SkColor) const;
void realizePaintSave()
{
if (m_paintState->saveCount()) {
m_paintState->decrementSaveCount();
++m_paintStateIndex;
if (m_paintStateStack.size() == m_paintStateIndex)
m_paintStateStack.append(GraphicsContextState::create());
GraphicsContextState* priorPaintState = m_paintState;
m_paintState = m_paintStateStack[m_paintStateIndex].get();
m_paintState->copy(priorPaintState);
}
}
void realizeCanvasSave()
{
if (!m_pendingCanvasSave)
return;
m_canvas->save();
m_pendingCanvasSave = false;
}
void didDrawTextInRect(const SkRect& textRect);
void fillRectWithRoundedHole(const IntRect&, const RoundedRect& roundedHoleRect, const Color&);
bool isRecording() const;
SkCanvas* m_canvas;
Vector<OwnPtr<GraphicsContextState> > m_paintStateStack;
unsigned m_paintStateIndex;
GraphicsContextState* m_paintState;
struct CanvasSaveState;
Vector<CanvasSaveState> m_canvasStateStack;
bool m_pendingCanvasSave;
AnnotationModeFlags m_annotationMode;
struct RecordingState;
Vector<RecordingState> m_recordingStateStack;
#if !ASSERT_DISABLED
unsigned m_annotationCount;
unsigned m_layerCount;
#endif
OpaqueRegionSkia m_opaqueRegion;
bool m_trackOpaqueRegion : 1;
bool m_trackTextRegion : 1;
SkRect m_textRegion;
bool m_useHighResMarker : 1;
bool m_updatingControlTints : 1;
bool m_accelerated : 1;
bool m_isCertainlyOpaque : 1;
bool m_printing : 1;
bool m_antialiasHairlineImages : 1;
};
}
#endif