summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicolas Roard <nicolasroard@google.com>2012-04-02 16:16:59 -0700
committerNicolas Roard <nicolasroard@google.com>2012-04-06 11:05:38 -0700
commit64e4b265f84573b97d408f7d3e5aa99a647be057 (patch)
treee349e52565c0cc487526fd68b608f8648678c1c7
parentd01f8866730e5ebe8609f82f95cf281432460607 (diff)
downloadexternal_webkit-64e4b265f84573b97d408f7d3e5aa99a647be057.zip
external_webkit-64e4b265f84573b97d408f7d3e5aa99a647be057.tar.gz
external_webkit-64e4b265f84573b97d408f7d3e5aa99a647be057.tar.bz2
Implements a recording GraphicsContext
Change-Id: I41feadb23dce25af321331c459eb159c6141831b
-rw-r--r--Android.mk1
-rw-r--r--Source/WebCore/Android.mk8
-rw-r--r--Source/WebCore/platform/android/RenderThemeAndroid.cpp18
-rw-r--r--Source/WebCore/platform/graphics/Font.h6
-rw-r--r--Source/WebCore/platform/graphics/android/FontAndroid.cpp10
-rw-r--r--Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp4
-rw-r--r--Source/WebCore/platform/graphics/android/ImageBufferAndroid.cpp5
-rw-r--r--Source/WebCore/platform/graphics/android/PlatformGraphicsContext.cpp1048
-rw-r--r--Source/WebCore/platform/graphics/android/PlatformGraphicsContext.h150
-rw-r--r--Source/WebCore/platform/graphics/android/context/GraphicsContextAndroid.cpp (renamed from Source/WebCore/platform/graphics/android/GraphicsContextAndroid.cpp)9
-rw-r--r--Source/WebCore/platform/graphics/android/context/GraphicsOperation.h809
-rw-r--r--Source/WebCore/platform/graphics/android/context/GraphicsOperationCollection.cpp63
-rw-r--r--Source/WebCore/platform/graphics/android/context/GraphicsOperationCollection.h72
-rw-r--r--Source/WebCore/platform/graphics/android/context/PlatformGraphicsContext.cpp456
-rw-r--r--Source/WebCore/platform/graphics/android/context/PlatformGraphicsContext.h204
-rw-r--r--Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.cpp373
-rw-r--r--Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.h128
-rw-r--r--Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextSkia.cpp606
-rw-r--r--Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextSkia.h115
-rw-r--r--Source/WebCore/plugins/android/PluginViewAndroid.cpp5
-rw-r--r--Source/WebKit/android/RenderSkinMediaButton.cpp3
-rw-r--r--Source/WebKit/android/WebCoreSupport/MediaPlayerPrivateAndroid.cpp4
-rw-r--r--Source/WebKit/android/jni/PictureSet.cpp38
-rw-r--r--Source/WebKit/android/jni/PictureSet.h10
-rw-r--r--Source/WebKit/android/jni/WebViewCore.cpp28
-rw-r--r--Source/WebKit/android/jni/WebViewCore.h4
26 files changed, 2962 insertions, 1215 deletions
diff --git a/Android.mk b/Android.mk
index d01ef64..6041506 100644
--- a/Android.mk
+++ b/Android.mk
@@ -127,6 +127,7 @@ LOCAL_C_INCLUDES := $(LOCAL_C_INCLUDES) \
$(WEBCORE_PATH)/platform/animation \
$(WEBCORE_PATH)/platform/graphics \
$(WEBCORE_PATH)/platform/graphics/android \
+ $(WEBCORE_PATH)/platform/graphics/android/context \
$(WEBCORE_PATH)/platform/graphics/filters \
$(WEBCORE_PATH)/platform/graphics/gpu \
$(WEBCORE_PATH)/platform/graphics/network \
diff --git a/Source/WebCore/Android.mk b/Source/WebCore/Android.mk
index de0aeab..54c7e01 100644
--- a/Source/WebCore/Android.mk
+++ b/Source/WebCore/Android.mk
@@ -654,7 +654,6 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
platform/graphics/android/GLWebViewState.cpp \
platform/graphics/android/GlyphMapAndroid.cpp \
platform/graphics/android/GradientAndroid.cpp \
- platform/graphics/android/GraphicsContextAndroid.cpp \
platform/graphics/android/GraphicsLayerAndroid.cpp \
platform/graphics/android/IFrameContentLayerAndroid.cpp \
platform/graphics/android/IFrameLayerAndroid.cpp \
@@ -673,7 +672,6 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
platform/graphics/android/PatternAndroid.cpp \
platform/graphics/android/PictureLayerContent.cpp \
platform/graphics/android/PictureSetLayerContent.cpp \
- platform/graphics/android/PlatformGraphicsContext.cpp \
platform/graphics/android/RasterRenderer.cpp \
platform/graphics/android/ScrollableLayerAndroid.cpp \
platform/graphics/android/SharedBufferStream.cpp \
@@ -693,6 +691,12 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
platform/graphics/android/VerticalTextMap.cpp \
platform/graphics/android/VideoLayerAndroid.cpp \
platform/graphics/android/VideoLayerManager.cpp \
+ \
+ platform/graphics/android/context/GraphicsContextAndroid.cpp \
+ platform/graphics/android/context/GraphicsOperationCollection.cpp \
+ platform/graphics/android/context/PlatformGraphicsContext.cpp \
+ platform/graphics/android/context/PlatformGraphicsContextRecording.cpp \
+ platform/graphics/android/context/PlatformGraphicsContextSkia.cpp
ifeq ($(ENABLE_SVG), true)
LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
diff --git a/Source/WebCore/platform/android/RenderThemeAndroid.cpp b/Source/WebCore/platform/android/RenderThemeAndroid.cpp
index ee406c2..173cfea 100644
--- a/Source/WebCore/platform/android/RenderThemeAndroid.cpp
+++ b/Source/WebCore/platform/android/RenderThemeAndroid.cpp
@@ -88,7 +88,7 @@ const float scaleFactor[RenderSkinAndroid::ResolutionCount] = {
static SkCanvas* getCanvasFromInfo(const PaintInfo& info)
{
- return info.context->platformContext()->mCanvas;
+ return info.context->platformContext()->getCanvas();
}
static android::WebFrame* getWebFrame(const Node* node)
@@ -341,6 +341,8 @@ bool RenderThemeAndroid::paintMediaFullscreenButton(RenderObject* o, const Paint
bool translucent = false;
if (o && toParentMediaElement(o) && toParentMediaElement(o)->hasTagName(HTMLNames::videoTag))
translucent = true;
+ if (!getCanvasFromInfo(paintInfo))
+ return true;
RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect, RenderSkinMediaButton::FULLSCREEN, translucent);
return false;
}
@@ -350,6 +352,8 @@ bool RenderThemeAndroid::paintMediaMuteButton(RenderObject* o, const PaintInfo&
bool translucent = false;
if (o && toParentMediaElement(o) && toParentMediaElement(o)->hasTagName(HTMLNames::videoTag))
translucent = true;
+ if (!getCanvasFromInfo(paintInfo))
+ return true;
RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect, RenderSkinMediaButton::MUTE, translucent);
return false;
}
@@ -360,6 +364,8 @@ bool RenderThemeAndroid::paintMediaPlayButton(RenderObject* o, const PaintInfo&
if (o && toParentMediaElement(o) && toParentMediaElement(o)->hasTagName(HTMLNames::videoTag))
translucent = true;
if (MediaControlPlayButtonElement* btn = static_cast<MediaControlPlayButtonElement*>(o->node())) {
+ if (!getCanvasFromInfo(paintInfo))
+ return true;
if (btn->displayType() == MediaPlayButton)
RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect, RenderSkinMediaButton::PLAY, translucent);
else
@@ -374,6 +380,8 @@ bool RenderThemeAndroid::paintMediaSeekBackButton(RenderObject* o, const PaintIn
bool translucent = false;
if (o && toParentMediaElement(o) && toParentMediaElement(o)->hasTagName(HTMLNames::videoTag))
translucent = true;
+ if (!getCanvasFromInfo(paintInfo))
+ return true;
RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect, RenderSkinMediaButton::REWIND, translucent);
return false;
}
@@ -383,6 +391,8 @@ bool RenderThemeAndroid::paintMediaSeekForwardButton(RenderObject* o, const Pain
bool translucent = false;
if (o && toParentMediaElement(o) && toParentMediaElement(o)->hasTagName(HTMLNames::videoTag))
translucent = true;
+ if (!getCanvasFromInfo(paintInfo))
+ return true;
RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect, RenderSkinMediaButton::FORWARD, translucent);
return false;
}
@@ -392,6 +402,8 @@ bool RenderThemeAndroid::paintMediaControlsBackground(RenderObject* o, const Pai
bool translucent = false;
if (o && toParentMediaElement(o) && toParentMediaElement(o)->hasTagName(HTMLNames::videoTag))
translucent = true;
+ if (!getCanvasFromInfo(paintInfo))
+ return true;
RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect,
RenderSkinMediaButton::BACKGROUND_SLIDER,
translucent, 0, false);
@@ -403,6 +415,8 @@ bool RenderThemeAndroid::paintMediaSliderTrack(RenderObject* o, const PaintInfo&
bool translucent = false;
if (o && toParentMediaElement(o) && toParentMediaElement(o)->hasTagName(HTMLNames::videoTag))
translucent = true;
+ if (!getCanvasFromInfo(paintInfo))
+ return true;
RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect,
RenderSkinMediaButton::SLIDER_TRACK, translucent, o);
return false;
@@ -413,6 +427,8 @@ bool RenderThemeAndroid::paintMediaSliderThumb(RenderObject* o, const PaintInfo&
bool translucent = false;
if (o && toParentMediaElement(o) && toParentMediaElement(o)->hasTagName(HTMLNames::videoTag))
translucent = true;
+ if (!getCanvasFromInfo(paintInfo))
+ return true;
RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect,
RenderSkinMediaButton::SLIDER_THUMB,
translucent, 0, false);
diff --git a/Source/WebCore/platform/graphics/Font.h b/Source/WebCore/platform/graphics/Font.h
index beafdc7..664c3af 100644
--- a/Source/WebCore/platform/graphics/Font.h
+++ b/Source/WebCore/platform/graphics/Font.h
@@ -171,7 +171,13 @@ private:
float getGlyphsAndAdvancesForSimpleText(const TextRun&, int from, int to, GlyphBuffer&, ForTextEmphasisOrNot = NotForTextEmphasis) const;
void drawSimpleText(GraphicsContext*, const TextRun&, const FloatPoint&, int from, int to) const;
void drawEmphasisMarksForSimpleText(GraphicsContext*, const TextRun&, const AtomicString& mark, const FloatPoint&, int from, int to) const;
+#if PLATFORM(ANDROID)
+public:
+#endif
void drawGlyphs(GraphicsContext*, const SimpleFontData*, const GlyphBuffer&, int from, int to, const FloatPoint&) const;
+#if PLATFORM(ANDROID)
+private:
+#endif
void drawGlyphBuffer(GraphicsContext*, const GlyphBuffer&, const FloatPoint&) const;
void drawEmphasisMarks(GraphicsContext* context, const GlyphBuffer&, const AtomicString&, const FloatPoint&) const;
float floatWidthForSimpleText(const TextRun&, GlyphBuffer*, HashSet<const SimpleFontData*>* fallbackFonts = 0, GlyphOverflow* = 0) const;
diff --git a/Source/WebCore/platform/graphics/android/FontAndroid.cpp b/Source/WebCore/platform/graphics/android/FontAndroid.cpp
index c8b9488..3146612 100644
--- a/Source/WebCore/platform/graphics/android/FontAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/FontAndroid.cpp
@@ -27,6 +27,8 @@
#include "config.h"
#include "EmojiFont.h"
+#include "GraphicsOperationCollection.h"
+#include "GraphicsOperation.h"
#include "Font.h"
#include "FontData.h"
#include "FontFallbackList.h"
@@ -196,7 +198,7 @@ void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font,
SkAutoSTMalloc<32, SkPoint> storage(numGlyphs), storage2(numGlyphs), storage3(numGlyphs);
SkPoint* pos = storage.get();
- SkCanvas* canvas = gc->platformContext()->mCanvas;
+ SkCanvas* canvas = gc->platformContext()->recordingCanvas();
/* We need an array of [x,y,x,y,x,y,...], but webkit is giving us
point.xy + [width, height, width, height, ...], so we have to convert
@@ -254,6 +256,7 @@ void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font,
if (font->platformData().orientation() == Vertical)
canvas->restore();
}
+ gc->platformContext()->endRecording();
}
void Font::drawEmphasisMarksForComplexText(WebCore::GraphicsContext*, WebCore::TextRun const&, WTF::AtomicString const&, WebCore::FloatPoint const&, int, int) const
@@ -1054,7 +1057,8 @@ void Font::drawComplexText(GraphicsContext* gc, TextRun const& run,
if (stroke)
setupStroke(&strokePaint, gc, primaryFont());
- SkCanvas* canvas = gc->platformContext()->mCanvas;
+ SkCanvas* canvas = gc->platformContext()->recordingCanvas();
+
bool haveMultipleLayers = isCanvasMultiLayered(canvas);
TextRunWalker walker(run, point.x(), point.y(), this);
walker.setWordAndLetterSpacing(wordSpacing(), letterSpacing());
@@ -1074,6 +1078,8 @@ void Font::drawComplexText(GraphicsContext* gc, TextRun const& run,
walker.positions(), strokePaint);
}
}
+
+ gc->platformContext()->endRecording();
}
float Font::floatWidthForComplexText(const TextRun& run,
diff --git a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp
index d62f88b..253f1a6 100644
--- a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp
@@ -39,7 +39,7 @@
#include "MediaLayer.h"
#include "PictureLayerContent.h"
#include "PlatformBridge.h"
-#include "PlatformGraphicsContext.h"
+#include "PlatformGraphicsContextSkia.h"
#include "RenderLayerBacking.h"
#include "RenderView.h"
#include "RotateTransformOperation.h"
@@ -715,7 +715,7 @@ bool GraphicsLayerAndroid::paintContext(LayerAndroid* layer,
return false;
}
- PlatformGraphicsContext platformContext(canvas);
+ PlatformGraphicsContextSkia platformContext(canvas);
GraphicsContext graphicsContext(&platformContext);
paintGraphicsLayerContents(graphicsContext, rect);
diff --git a/Source/WebCore/platform/graphics/android/ImageBufferAndroid.cpp b/Source/WebCore/platform/graphics/android/ImageBufferAndroid.cpp
index f148881..e56f424 100644
--- a/Source/WebCore/platform/graphics/android/ImageBufferAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/ImageBufferAndroid.cpp
@@ -82,7 +82,10 @@ PassRefPtr<Image> ImageBuffer::copyImage() const
{
ASSERT(context());
- SkCanvas* canvas = context()->platformContext()->mCanvas;
+ SkCanvas* canvas = context()->platformContext()->getCanvas();
+ if (!canvas)
+ return 0;
+
SkDevice* device = canvas->getDevice();
const SkBitmap& orig = device->accessBitmap(false);
diff --git a/Source/WebCore/platform/graphics/android/PlatformGraphicsContext.cpp b/Source/WebCore/platform/graphics/android/PlatformGraphicsContext.cpp
deleted file mode 100644
index 3c8ea3c..0000000
--- a/Source/WebCore/platform/graphics/android/PlatformGraphicsContext.cpp
+++ /dev/null
@@ -1,1048 +0,0 @@
-/*
- * Copyright 2006, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "PlatformGraphicsContext.h"
-
-#include "AffineTransform.h"
-#include "Font.h"
-#include "Gradient.h"
-#include "GraphicsContext.h"
-#include "Node.h"
-#include "NotImplemented.h"
-#include "Path.h"
-#include "Pattern.h"
-#include "SkBitmapRef.h"
-#include "SkBlurDrawLooper.h"
-#include "SkBlurMaskFilter.h"
-#include "SkCanvas.h"
-#include "SkColorPriv.h"
-#include "SkCornerPathEffect.h"
-#include "SkDashPathEffect.h"
-#include "SkDevice.h"
-#include "SkGradientShader.h"
-#include "SkPaint.h"
-#include "SkString.h"
-#include "SkiaUtils.h"
-#include "TransformationMatrix.h"
-#include "android_graphics.h"
-
-namespace WebCore {
-
-// These are the flags we need when we call saveLayer for transparency.
-// Since it does not appear that webkit intends this to also save/restore
-// the matrix or clip, I do not give those flags (for performance)
-#define TRANSPARENCY_SAVEFLAGS \
- (SkCanvas::SaveFlags)(SkCanvas::kHasAlphaLayer_SaveFlag | \
- SkCanvas::kFullColorLayer_SaveFlag)
-
-//**************************************
-// Helper functions
-//**************************************
-
-static int RoundToInt(float x)
-{
- return (int)roundf(x);
-}
-
-template <typename T> T* deepCopyPtr(const T* src)
-{
- return src ? new T(*src) : 0;
-}
-
-// Set a bitmap shader that mimics dashing by width-on, width-off.
-// Returns false if it could not succeed (e.g. there was an existing shader)
-static bool setBitmapDash(SkPaint* paint, int width) {
- if (width <= 0 || paint->getShader())
- return false;
-
- SkColor c = paint->getColor();
-
- SkBitmap bm;
- bm.setConfig(SkBitmap::kARGB_8888_Config, 2, 1);
- bm.allocPixels();
- bm.lockPixels();
-
- // set the ON pixel
- *bm.getAddr32(0, 0) = SkPreMultiplyARGB(0xFF, SkColorGetR(c),
- SkColorGetG(c), SkColorGetB(c));
- // set the OFF pixel
- *bm.getAddr32(1, 0) = 0;
- bm.unlockPixels();
-
- SkMatrix matrix;
- matrix.setScale(SkIntToScalar(width), SK_Scalar1);
-
- SkShader* s = SkShader::CreateBitmapShader(bm, SkShader::kRepeat_TileMode,
- SkShader::kClamp_TileMode);
- s->setLocalMatrix(matrix);
-
- paint->setShader(s)->unref();
- return true;
-}
-
-static void setrectForUnderline(SkRect* r, float lineThickness,
- const FloatPoint& point, int yOffset, float width)
-{
-#if 0
- if (lineThickness < 1) // Do we really need/want this?
- lineThickness = 1;
-#endif
- r->fLeft = point.x();
- r->fTop = point.y() + yOffset;
- r->fRight = r->fLeft + width;
- r->fBottom = r->fTop + lineThickness;
-}
-
-static inline int fastMod(int value, int max)
-{
- int sign = SkExtractSign(value);
-
- value = SkApplySign(value, sign);
- if (value >= max)
- value %= max;
- return SkApplySign(value, sign);
-}
-
-static inline void fixPaintForBitmapsThatMaySeam(SkPaint* paint) {
- /* Bitmaps may be drawn to seem next to other images. If we are drawn
- zoomed, or at fractional coordinates, we may see cracks/edges if
- we antialias, because that will cause us to draw the same pixels
- more than once (e.g. from the left and right bitmaps that share
- an edge).
-
- Disabling antialiasing fixes this, and since so far we are never
- rotated at non-multiple-of-90 angles, this seems to do no harm
- */
- paint->setAntiAlias(false);
-}
-
-//**************************************
-// State structs
-//**************************************
-
-struct ShadowRec {
- SkScalar blur;
- SkScalar dx;
- SkScalar dy;
- SkColor color; // alpha>0 means valid shadow
- ShadowRec(SkScalar b = 0,
- SkScalar x = 0,
- SkScalar y = 0,
- SkColor c = 0) // by default, alpha=0, so no shadow
- : blur(b), dx(x), dy(y), color(c)
- {};
-};
-
-struct PlatformGraphicsContext::State {
- SkPathEffect* pathEffect;
- float miterLimit;
- float alpha;
- float strokeThickness;
- SkPaint::Cap lineCap;
- SkPaint::Join lineJoin;
- SkXfermode::Mode mode;
- int dashRatio; // Ratio of the length of a dash to its width
- ShadowRec shadow;
- SkColor fillColor;
- SkShader* fillShader;
- SkColor strokeColor;
- SkShader* strokeShader;
- bool useAA;
- StrokeStyle strokeStyle;
-
- State()
- : pathEffect(0)
- , miterLimit(4)
- , alpha(1)
- , strokeThickness(0) // Same as default in GraphicsContextPrivate.h
- , lineCap(SkPaint::kDefault_Cap)
- , lineJoin(SkPaint::kDefault_Join)
- , mode(SkXfermode::kSrcOver_Mode)
- , dashRatio(3)
- , fillColor(SK_ColorBLACK)
- , fillShader(0)
- , strokeColor(SK_ColorBLACK)
- , strokeShader(0)
- , useAA(true)
- , strokeStyle(SolidStroke)
- {
- }
-
- State(const State& other)
- : pathEffect(other.pathEffect)
- , miterLimit(other.miterLimit)
- , alpha(other.alpha)
- , strokeThickness(other.strokeThickness)
- , lineCap(other.lineCap)
- , lineJoin(other.lineJoin)
- , mode(other.mode)
- , dashRatio(other.dashRatio)
- , shadow(other.shadow)
- , fillColor(other.fillColor)
- , fillShader(other.fillShader)
- , strokeColor(other.strokeColor)
- , strokeShader(other.strokeShader)
- , useAA(other.useAA)
- , strokeStyle(other.strokeStyle)
- {
- SkSafeRef(pathEffect);
- SkSafeRef(fillShader);
- SkSafeRef(strokeShader);
- }
-
- ~State()
- {
- SkSafeUnref(pathEffect);
- SkSafeUnref(fillShader);
- SkSafeUnref(strokeShader);
- }
-
- void setShadow(int radius, int dx, int dy, SkColor c)
- {
- // Cut the radius in half, to visually match the effect seen in
- // safari browser
- shadow.blur = SkScalarHalf(SkIntToScalar(radius));
- shadow.dx = SkIntToScalar(dx);
- shadow.dy = SkIntToScalar(dy);
- shadow.color = c;
- }
-
- bool setupShadowPaint(SkPaint* paint, SkPoint* offset,
- bool shadowsIgnoreTransforms)
- {
- paint->setAntiAlias(true);
- paint->setDither(true);
- paint->setXfermodeMode(mode);
- paint->setColor(shadow.color);
- offset->set(shadow.dx, shadow.dy);
-
- // Currently, only GraphicsContexts associated with the
- // HTMLCanvasElement have shadows ignore transforms set. This
- // allows us to distinguish between CSS and Canvas shadows which
- // have different rendering specifications.
- uint32_t flags = SkBlurMaskFilter::kHighQuality_BlurFlag;
- if (shadowsIgnoreTransforms) {
- offset->fY = -offset->fY;
- flags |= SkBlurMaskFilter::kIgnoreTransform_BlurFlag;
- }
-
- if (shadow.blur > 0) {
- paint->setMaskFilter(SkBlurMaskFilter::Create(shadow.blur,
- SkBlurMaskFilter::kNormal_BlurStyle))->unref();
- }
- return SkColorGetA(shadow.color) && (shadow.blur || shadow.dx || shadow.dy);
- }
-
- SkColor applyAlpha(SkColor c) const
- {
- int s = RoundToInt(alpha * 256);
- if (s >= 256)
- return c;
- if (s < 0)
- return 0;
-
- int a = SkAlphaMul(SkColorGetA(c), s);
- return (c & 0x00FFFFFF) | (a << 24);
- }
-
- PlatformGraphicsContext::State cloneInheritedProperties();
-private:
- // Not supported.
- void operator=(const State&);
-};
-
-// Returns a new State with all of this object's inherited properties copied.
-PlatformGraphicsContext::State PlatformGraphicsContext::State::cloneInheritedProperties()
-{
- return PlatformGraphicsContext::State(*this);
-}
-
-//**************************************
-// PlatformGraphicsContext
-//**************************************
-
-PlatformGraphicsContext::PlatformGraphicsContext(SkCanvas* canvas,
- bool takeCanvasOwnership)
- : mCanvas(canvas)
- , m_deleteCanvas(takeCanvasOwnership)
- , m_stateStack(sizeof(State))
- , m_gc(0)
-{
- m_stateStack.append(State());
- m_state = &m_stateStack.last();
-}
-
-PlatformGraphicsContext::~PlatformGraphicsContext()
-{
- if (m_deleteCanvas)
- delete mCanvas;
-}
-
-//**************************************
-// State management
-//**************************************
-
-void PlatformGraphicsContext::beginTransparencyLayer(float opacity)
-{
- SkCanvas* canvas = mCanvas;
- canvas->saveLayerAlpha(0, (int)(opacity * 255), TRANSPARENCY_SAVEFLAGS);
-}
-
-void PlatformGraphicsContext::endTransparencyLayer()
-{
- mCanvas->restore();
-}
-
-void PlatformGraphicsContext::save()
-{
- m_stateStack.append(m_state->cloneInheritedProperties());
- m_state = &m_stateStack.last();
-
- // Save our native canvas.
- mCanvas->save();
-}
-
-void PlatformGraphicsContext::restore()
-{
- m_stateStack.removeLast();
- m_state = &m_stateStack.last();
-
- // Restore our native canvas.
- mCanvas->restore();
-}
-
-//**************************************
-// State setters
-//**************************************
-
-void PlatformGraphicsContext::setAlpha(float alpha)
-{
- m_state->alpha = alpha;
-}
-
-void PlatformGraphicsContext::setCompositeOperation(CompositeOperator op)
-{
- m_state->mode = WebCoreCompositeToSkiaComposite(op);
-}
-
-void PlatformGraphicsContext::setFillColor(const Color& c)
-{
- m_state->fillColor = c.rgb();
- setFillShader(0);
-}
-
-void PlatformGraphicsContext::setFillShader(SkShader* fillShader)
-{
- if (fillShader)
- m_state->fillColor = Color::black;
-
- if (fillShader != m_state->fillShader) {
- SkSafeUnref(m_state->fillShader);
- m_state->fillShader = fillShader;
- SkSafeRef(m_state->fillShader);
- }
-}
-
-void PlatformGraphicsContext::setLineCap(LineCap cap)
-{
- switch (cap) {
- case ButtCap:
- m_state->lineCap = SkPaint::kButt_Cap;
- break;
- case RoundCap:
- m_state->lineCap = SkPaint::kRound_Cap;
- break;
- case SquareCap:
- m_state->lineCap = SkPaint::kSquare_Cap;
- break;
- default:
- SkDEBUGF(("PlatformGraphicsContext::setLineCap: unknown LineCap %d\n", cap));
- break;
- }
-}
-
-void PlatformGraphicsContext::setLineDash(const DashArray& dashes, float dashOffset)
-{
- size_t dashLength = dashes.size();
- if (!dashLength)
- return;
-
- size_t count = !(dashLength % 2) ? dashLength : dashLength * 2;
- SkScalar* intervals = new SkScalar[count];
-
- for (unsigned int i = 0; i < count; i++)
- intervals[i] = SkFloatToScalar(dashes[i % dashLength]);
- SkPathEffect **effectPtr = &m_state->pathEffect;
- SkSafeUnref(*effectPtr);
- *effectPtr = new SkDashPathEffect(intervals, count, SkFloatToScalar(dashOffset));
-
- delete[] intervals;
-}
-
-void PlatformGraphicsContext::setLineJoin(LineJoin join)
-{
- switch (join) {
- case MiterJoin:
- m_state->lineJoin = SkPaint::kMiter_Join;
- break;
- case RoundJoin:
- m_state->lineJoin = SkPaint::kRound_Join;
- break;
- case BevelJoin:
- m_state->lineJoin = SkPaint::kBevel_Join;
- break;
- default:
- SkDEBUGF(("PlatformGraphicsContext::setLineJoin: unknown LineJoin %d\n", join));
- break;
- }
-}
-
-void PlatformGraphicsContext::setMiterLimit(float limit)
-{
- m_state->miterLimit = limit;
-}
-
-void PlatformGraphicsContext::setShadow(int radius, int dx, int dy, SkColor c)
-{
- m_state->setShadow(radius, dx, dy, c);
-}
-
-void PlatformGraphicsContext::setShouldAntialias(bool useAA)
-{
- m_state->useAA = useAA;
-}
-
-void PlatformGraphicsContext::setStrokeColor(const Color& c)
-{
- m_state->strokeColor = c.rgb();
- setStrokeShader(0);
-}
-
-void PlatformGraphicsContext::setStrokeShader(SkShader* strokeShader)
-{
- if (strokeShader)
- m_state->strokeColor = Color::black;
-
- if (strokeShader != m_state->strokeShader) {
- SkSafeUnref(m_state->strokeShader);
- m_state->strokeShader = strokeShader;
- SkSafeRef(m_state->strokeShader);
- }
-}
-
-void PlatformGraphicsContext::setStrokeStyle(StrokeStyle style)
-{
- m_state->strokeStyle = style;
-}
-
-void PlatformGraphicsContext::setStrokeThickness(float f)
-{
- m_state->strokeThickness = f;
-}
-
-//**************************************
-// Paint setup
-//**************************************
-
-void PlatformGraphicsContext::setupPaintCommon(SkPaint* paint) const
-{
- paint->setAntiAlias(m_state->useAA);
- paint->setDither(true);
- paint->setXfermodeMode(m_state->mode);
- if (SkColorGetA(m_state->shadow.color) > 0) {
-
- // Currently, only GraphicsContexts associated with the
- // HTMLCanvasElement have shadows ignore transforms set. This
- // allows us to distinguish between CSS and Canvas shadows which
- // have different rendering specifications.
- SkScalar dy = m_state->shadow.dy;
- uint32_t flags = SkBlurDrawLooper::kHighQuality_BlurFlag;
- if (shadowsIgnoreTransforms()) {
- dy = -dy;
- flags |= SkBlurDrawLooper::kIgnoreTransform_BlurFlag;
- flags |= SkBlurDrawLooper::kOverrideColor_BlurFlag;
- }
-
- SkDrawLooper* looper = new SkBlurDrawLooper(m_state->shadow.blur,
- m_state->shadow.dx,
- dy,
- m_state->shadow.color,
- flags);
- paint->setLooper(looper)->unref();
- }
- paint->setFilterBitmap(true);
-}
-
-void PlatformGraphicsContext::setupPaintFill(SkPaint* paint) const
-{
- this->setupPaintCommon(paint);
- paint->setColor(m_state->applyAlpha(m_state->fillColor));
- paint->setShader(m_state->fillShader);
-}
-
-bool PlatformGraphicsContext::setupPaintShadow(SkPaint* paint, SkPoint* offset) const
-{
- return m_state->setupShadowPaint(paint, offset, shadowsIgnoreTransforms());
-}
-
-bool PlatformGraphicsContext::setupPaintStroke(SkPaint* paint, SkRect* rect,
- bool isHLine)
-{
- this->setupPaintCommon(paint);
- paint->setColor(m_state->applyAlpha(m_state->strokeColor));
- paint->setShader(m_state->strokeShader);
-
- float width = m_state->strokeThickness;
-
- // This allows dashing and dotting to work properly for hairline strokes
- // FIXME: Should we only do this for dashed and dotted strokes?
- if (!width)
- width = 1;
-
- paint->setStyle(SkPaint::kStroke_Style);
- paint->setStrokeWidth(SkFloatToScalar(width));
- paint->setStrokeCap(m_state->lineCap);
- paint->setStrokeJoin(m_state->lineJoin);
- paint->setStrokeMiter(SkFloatToScalar(m_state->miterLimit));
-
- if (rect && (RoundToInt(width) & 1))
- rect->inset(-SK_ScalarHalf, -SK_ScalarHalf);
-
- SkPathEffect* pe = m_state->pathEffect;
- if (pe) {
- paint->setPathEffect(pe);
- return false;
- }
- switch (m_state->strokeStyle) {
- case NoStroke:
- case SolidStroke:
- width = 0;
- break;
- case DashedStroke:
- width = m_state->dashRatio * width;
- break;
- // No break
- case DottedStroke:
- break;
- }
-
- if (width > 0) {
- // Return true if we're basically a dotted dash of squares
- bool justSqrs = RoundToInt(width) == RoundToInt(paint->getStrokeWidth());
-
- if (justSqrs || !isHLine || !setBitmapDash(paint, width)) {
-#if 0
- // this is slow enough that we just skip it for now
- // see http://b/issue?id=4163023
- SkScalar intervals[] = { width, width };
- pe = new SkDashPathEffect(intervals, 2, 0);
- paint->setPathEffect(pe)->unref();
-#endif
- }
- return justSqrs;
- }
- return false;
-}
-
-//**************************************
-// Matrix operations
-//**************************************
-
-void PlatformGraphicsContext::concatCTM(const AffineTransform& affine)
-{
- mCanvas->concat(affine);
-}
-
-void PlatformGraphicsContext::rotate(float angleInRadians)
-{
- mCanvas->rotate(SkFloatToScalar(angleInRadians * (180.0f / 3.14159265f)));
-}
-
-void PlatformGraphicsContext::scale(const FloatSize& size)
-{
- mCanvas->scale(SkFloatToScalar(size.width()), SkFloatToScalar(size.height()));
-}
-
-void PlatformGraphicsContext::translate(float x, float y)
-{
- mCanvas->translate(SkFloatToScalar(x), SkFloatToScalar(y));
-}
-
-//**************************************
-// Clipping
-//**************************************
-
-void PlatformGraphicsContext::addInnerRoundedRectClip(const IntRect& rect,
- int thickness)
-{
- SkPath path;
- SkRect r(rect);
-
- path.addOval(r, SkPath::kCW_Direction);
- // Only perform the inset if we won't invert r
- if (2 * thickness < rect.width() && 2 * thickness < rect.height()) {
- // Adding one to the thickness doesn't make the border too thick as
- // it's painted over afterwards. But without this adjustment the
- // border appears a little anemic after anti-aliasing.
- r.inset(SkIntToScalar(thickness + 1), SkIntToScalar(thickness + 1));
- path.addOval(r, SkPath::kCCW_Direction);
- }
- mCanvas->clipPath(path, SkRegion::kIntersect_Op, true);
-}
-
-void PlatformGraphicsContext::canvasClip(const Path& path)
-{
- clip(path);
-}
-
-void PlatformGraphicsContext::clip(const FloatRect& rect)
-{
- mCanvas->clipRect(rect);
-}
-
-void PlatformGraphicsContext::clip(const Path& path)
-{
- mCanvas->clipPath(*path.platformPath(), SkRegion::kIntersect_Op, true);
-}
-
-void PlatformGraphicsContext::clipConvexPolygon(size_t numPoints,
- const FloatPoint*, bool antialias)
-{
- if (numPoints <= 1)
- return;
-
- // This is only used if HAVE_PATH_BASED_BORDER_RADIUS_DRAWING is defined
- // in RenderObject.h which it isn't for us. TODO: Support that :)
-}
-
-void PlatformGraphicsContext::clipOut(const IntRect& r)
-{
- mCanvas->clipRect(r, SkRegion::kDifference_Op);
-}
-
-void PlatformGraphicsContext::clipOut(const Path& p)
-{
- mCanvas->clipPath(*p.platformPath(), SkRegion::kDifference_Op);
-}
-
-void PlatformGraphicsContext::clipPath(const Path& pathToClip, WindRule clipRule)
-{
- SkPath path = *pathToClip.platformPath();
- path.setFillType(clipRule == RULE_EVENODD
- ? SkPath::kEvenOdd_FillType : SkPath::kWinding_FillType);
- mCanvas->clipPath(path);
-}
-void PlatformGraphicsContext::clearRect(const FloatRect& rect)
-{
- SkPaint paint;
-
- setupPaintFill(&paint);
- paint.setXfermodeMode(SkXfermode::kClear_Mode);
- mCanvas->drawRect(rect, paint);
-}
-
-//**************************************
-// Drawing
-//**************************************
-
-void PlatformGraphicsContext::drawBitmapPattern(
- const SkBitmap& bitmap, const SkMatrix& matrix,
- CompositeOperator compositeOp, const FloatRect& destRect)
-{
- SkShader* shader = SkShader::CreateBitmapShader(bitmap,
- SkShader::kRepeat_TileMode,
- SkShader::kRepeat_TileMode);
- shader->setLocalMatrix(matrix);
- SkPaint paint;
- setupPaintFill(&paint);
- paint.setShader(shader);
- paint.setXfermodeMode(WebCoreCompositeToSkiaComposite(compositeOp));
- fixPaintForBitmapsThatMaySeam(&paint);
- mCanvas->drawRect(destRect, paint);
-}
-
-void PlatformGraphicsContext::drawBitmapRect(const SkBitmap& bitmap,
- const SkIRect* src, const SkRect& dst,
- CompositeOperator op)
-{
- SkPaint paint;
- setupPaintFill(&paint);
- paint.setXfermodeMode(WebCoreCompositeToSkiaComposite(op));
- fixPaintForBitmapsThatMaySeam(&paint);
- mCanvas->drawBitmapRect(bitmap, src, dst, &paint);
-}
-
-void PlatformGraphicsContext::drawConvexPolygon(size_t numPoints,
- const FloatPoint* points,
- bool shouldAntialias)
-{
- if (numPoints <= 1)
- return;
-
- SkPaint paint;
- SkPath path;
-
- path.incReserve(numPoints);
- path.moveTo(SkFloatToScalar(points[0].x()), SkFloatToScalar(points[0].y()));
- for (size_t i = 1; i < numPoints; i++)
- path.lineTo(SkFloatToScalar(points[i].x()), SkFloatToScalar(points[i].y()));
-
- if (mCanvas->quickReject(path, shouldAntialias ?
- SkCanvas::kAA_EdgeType : SkCanvas::kBW_EdgeType)) {
- return;
- }
-
- if (m_state->fillColor & 0xFF000000) {
- setupPaintFill(&paint);
- paint.setAntiAlias(shouldAntialias);
- mCanvas->drawPath(path, paint);
- }
-
- if (m_state->strokeStyle != NoStroke) {
- paint.reset();
- setupPaintStroke(&paint, 0);
- paint.setAntiAlias(shouldAntialias);
- mCanvas->drawPath(path, paint);
- }
-}
-
-void PlatformGraphicsContext::drawEllipse(const IntRect& rect)
-{
- SkPaint paint;
- SkRect oval(rect);
-
- if (m_state->fillColor & 0xFF000000) {
- setupPaintFill(&paint);
- mCanvas->drawOval(oval, paint);
- }
- if (m_state->strokeStyle != NoStroke) {
- paint.reset();
- setupPaintStroke(&paint, &oval);
- mCanvas->drawOval(oval, paint);
- }
-}
-
-void PlatformGraphicsContext::drawFocusRing(const Vector<IntRect>& rects,
- int /* width */, int /* offset */,
- const Color& color)
-{
- unsigned rectCount = rects.size();
- if (!rectCount)
- return;
-
- SkRegion focusRingRegion;
- const SkScalar focusRingOutset = WebCoreFloatToSkScalar(0.8);
- for (unsigned i = 0; i < rectCount; i++) {
- SkIRect r = rects[i];
- r.inset(-focusRingOutset, -focusRingOutset);
- focusRingRegion.op(r, SkRegion::kUnion_Op);
- }
-
- SkPath path;
- SkPaint paint;
- paint.setAntiAlias(true);
- paint.setStyle(SkPaint::kStroke_Style);
-
- paint.setColor(color.rgb());
- paint.setStrokeWidth(focusRingOutset * 2);
- paint.setPathEffect(new SkCornerPathEffect(focusRingOutset * 2))->unref();
- focusRingRegion.getBoundaryPath(&path);
- mCanvas->drawPath(path, paint);
-}
-
-void PlatformGraphicsContext::drawHighlightForText(
- const Font& font, const TextRun& run, const FloatPoint& point, int h,
- const Color& backgroundColor, ColorSpace colorSpace, int from,
- int to, bool isActive)
-{
- IntRect rect = (IntRect)font.selectionRectForText(run, point, h, from, to);
- if (isActive)
- fillRect(rect, backgroundColor, colorSpace);
- else {
- int x = rect.x(), y = rect.y(), w = rect.width(), h = rect.height();
- const int t = 3, t2 = t * 2;
-
- fillRect(IntRect(x, y, w, t), backgroundColor, colorSpace);
- fillRect(IntRect(x, y+h-t, w, t), backgroundColor, colorSpace);
- fillRect(IntRect(x, y+t, t, h-t2), backgroundColor, colorSpace);
- fillRect(IntRect(x+w-t, y+t, t, h-t2), backgroundColor, colorSpace);
- }
-}
-
-void PlatformGraphicsContext::drawLine(const IntPoint& point1,
- const IntPoint& point2)
-{
- StrokeStyle style = m_state->strokeStyle;
- if (style == NoStroke)
- return;
-
- SkPaint paint;
- SkCanvas* canvas = mCanvas;
- const int idx = SkAbs32(point2.x() - point1.x());
- const int idy = SkAbs32(point2.y() - point1.y());
-
- // Special-case horizontal and vertical lines that are really just dots
- if (setupPaintStroke(&paint, 0, !idy) && (!idx || !idy)) {
- const SkScalar diameter = paint.getStrokeWidth();
- const SkScalar radius = SkScalarHalf(diameter);
- SkScalar x = SkIntToScalar(SkMin32(point1.x(), point2.x()));
- SkScalar y = SkIntToScalar(SkMin32(point1.y(), point2.y()));
- SkScalar dx, dy;
- int count;
- SkRect bounds;
-
- if (!idy) { // Horizontal
- bounds.set(x, y - radius, x + SkIntToScalar(idx), y + radius);
- x += radius;
- dx = diameter * 2;
- dy = 0;
- count = idx;
- } else { // Vertical
- bounds.set(x - radius, y, x + radius, y + SkIntToScalar(idy));
- y += radius;
- dx = 0;
- dy = diameter * 2;
- count = idy;
- }
-
- // The actual count is the number of ONs we hit alternating
- // ON(diameter), OFF(diameter), ...
- {
- SkScalar width = SkScalarDiv(SkIntToScalar(count), diameter);
- // Now compute the number of cells (ON and OFF)
- count = SkScalarRound(width);
- // Now compute the number of ONs
- count = (count + 1) >> 1;
- }
-
- SkAutoMalloc storage(count * sizeof(SkPoint));
- SkPoint* verts = (SkPoint*)storage.get();
- // Now build the array of vertices to past to drawPoints
- for (int i = 0; i < count; i++) {
- verts[i].set(x, y);
- x += dx;
- y += dy;
- }
-
- paint.setStyle(SkPaint::kFill_Style);
- paint.setPathEffect(0);
-
- // Clipping to bounds is not required for correctness, but it does
- // allow us to reject the entire array of points if we are completely
- // offscreen. This is common in a webpage for android, where most of
- // the content is clipped out. If drawPoints took an (optional) bounds
- // parameter, that might even be better, as we would *just* use it for
- // culling, and not both wacking the canvas' save/restore stack.
- canvas->save(SkCanvas::kClip_SaveFlag);
- canvas->clipRect(bounds);
- canvas->drawPoints(SkCanvas::kPoints_PointMode, count, verts, paint);
- canvas->restore();
- } else {
- SkPoint pts[2] = { point1, point2 };
- canvas->drawLine(pts[0].fX, pts[0].fY, pts[1].fX, pts[1].fY, paint);
- }
-}
-
-void PlatformGraphicsContext::drawLineForText(const FloatPoint& pt, float width)
-{
- SkRect r;
- setrectForUnderline(&r, m_state->strokeThickness, pt, 0, width);
-
- SkPaint paint;
- paint.setAntiAlias(true);
- paint.setColor(m_state->strokeColor);
-
- mCanvas->drawRect(r, paint);
-}
-
-void PlatformGraphicsContext::drawLineForTextChecking(const FloatPoint& pt,
- float width, GraphicsContext::TextCheckingLineStyle)
-{
- // TODO: Should we draw different based on TextCheckingLineStyle?
- SkRect r;
- setrectForUnderline(&r, m_state->strokeThickness, pt, 0, width);
-
- SkPaint paint;
- paint.setAntiAlias(true);
- paint.setColor(SK_ColorRED); // Is this specified somewhere?
-
- mCanvas->drawRect(r, paint);
-}
-
-void PlatformGraphicsContext::drawRect(const IntRect& rect)
-{
- SkPaint paint;
- SkRect r(rect);
-
- if (m_state->fillColor & 0xFF000000) {
- setupPaintFill(&paint);
- mCanvas->drawRect(r, paint);
- }
-
- // According to GraphicsContext.h, stroking inside drawRect always means
- // a stroke of 1 inside the rect.
- if (m_state->strokeStyle != NoStroke && (m_state->strokeColor & 0xFF000000)) {
- paint.reset();
- setupPaintStroke(&paint, &r);
- paint.setPathEffect(0); // No dashing please
- paint.setStrokeWidth(SK_Scalar1); // Always just 1.0 width
- r.inset(SK_ScalarHalf, SK_ScalarHalf); // Ensure we're "inside"
- mCanvas->drawRect(r, paint);
- }
-}
-
-void PlatformGraphicsContext::fillPath(const Path& pathToFill, WindRule fillRule)
-{
- SkPath* path = pathToFill.platformPath();
- if (!path)
- return;
-
- switch (fillRule) {
- case RULE_NONZERO:
- path->setFillType(SkPath::kWinding_FillType);
- break;
- case RULE_EVENODD:
- path->setFillType(SkPath::kEvenOdd_FillType);
- break;
- }
-
- SkPaint paint;
- setupPaintFill(&paint);
-
- mCanvas->drawPath(*path, paint);
-}
-
-void PlatformGraphicsContext::fillRect(const FloatRect& rect)
-{
- SkPaint paint;
- setupPaintFill(&paint);
- mCanvas->drawRect(rect, paint);
-}
-
-void PlatformGraphicsContext::fillRect(const FloatRect& rect,
- const Color& color, ColorSpace)
-{
- if (color.rgb() & 0xFF000000) {
- SkPaint paint;
-
- setupPaintCommon(&paint);
- paint.setColor(color.rgb()); // Punch in the specified color
- paint.setShader(0); // In case we had one set
-
- // Sometimes we record and draw portions of the page, using clips
- // for each portion. The problem with this is that webkit, sometimes,
- // sees that we're only recording a portion, and they adjust some of
- // their rectangle coordinates accordingly (e.g.
- // RenderBoxModelObject::paintFillLayerExtended() which calls
- // rect.intersect(paintInfo.rect) and then draws the bg with that
- // rect. The result is that we end up drawing rects that are meant to
- // seam together (one for each portion), but if the rects have
- // fractional coordinates (e.g. we are zoomed by a fractional amount)
- // we will double-draw those edges, resulting in visual cracks or
- // artifacts.
-
- // The fix seems to be to just turn off antialasing for rects (this
- // entry-point in GraphicsContext seems to have been sufficient,
- // though perhaps we'll find we need to do this as well in fillRect(r)
- // as well.) Currently setupPaintCommon() enables antialiasing.
-
- // Since we never show the page rotated at a funny angle, disabling
- // antialiasing seems to have no real down-side, and it does fix the
- // bug when we're zoomed (and drawing portions that need to seam).
- paint.setAntiAlias(false);
-
- mCanvas->drawRect(rect, paint);
- }
-}
-
-void PlatformGraphicsContext::fillRoundedRect(
- const IntRect& rect, const IntSize& topLeft, const IntSize& topRight,
- const IntSize& bottomLeft, const IntSize& bottomRight,
- const Color& color, ColorSpace)
-{
- SkPaint paint;
- SkPath path;
- SkScalar radii[8];
-
- radii[0] = SkIntToScalar(topLeft.width());
- radii[1] = SkIntToScalar(topLeft.height());
- radii[2] = SkIntToScalar(topRight.width());
- radii[3] = SkIntToScalar(topRight.height());
- radii[4] = SkIntToScalar(bottomRight.width());
- radii[5] = SkIntToScalar(bottomRight.height());
- radii[6] = SkIntToScalar(bottomLeft.width());
- radii[7] = SkIntToScalar(bottomLeft.height());
- path.addRoundRect(rect, radii);
-
- setupPaintFill(&paint);
- paint.setColor(color.rgb());
- mCanvas->drawPath(path, paint);
-}
-
-void PlatformGraphicsContext::strokeArc(const IntRect& r, int startAngle,
- int angleSpan)
-{
- SkPath path;
- SkPaint paint;
- SkRect oval(r);
-
- if (m_state->strokeStyle == NoStroke) {
- setupPaintFill(&paint); // We want the fill color
- paint.setStyle(SkPaint::kStroke_Style);
- paint.setStrokeWidth(SkFloatToScalar(m_state->strokeThickness));
- } else
- setupPaintStroke(&paint, 0);
-
- // We do this before converting to scalar, so we don't overflow SkFixed
- startAngle = fastMod(startAngle, 360);
- angleSpan = fastMod(angleSpan, 360);
-
- path.addArc(oval, SkIntToScalar(-startAngle), SkIntToScalar(-angleSpan));
- mCanvas->drawPath(path, paint);
-}
-
-void PlatformGraphicsContext::strokePath(const Path& pathToStroke)
-{
- const SkPath* path = pathToStroke.platformPath();
- if (!path)
- return;
-
- SkPaint paint;
- setupPaintStroke(&paint, 0);
-
- mCanvas->drawPath(*path, paint);
-}
-
-void PlatformGraphicsContext::strokeRect(const FloatRect& rect, float lineWidth)
-{
- SkPaint paint;
-
- setupPaintStroke(&paint, 0);
- paint.setStrokeWidth(SkFloatToScalar(lineWidth));
- mCanvas->drawRect(rect, paint);
-}
-
-} // WebCore
diff --git a/Source/WebCore/platform/graphics/android/PlatformGraphicsContext.h b/Source/WebCore/platform/graphics/android/PlatformGraphicsContext.h
deleted file mode 100644
index ce126a4..0000000
--- a/Source/WebCore/platform/graphics/android/PlatformGraphicsContext.h
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Copyright 2006, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef platform_graphics_context_h
-#define platform_graphics_context_h
-
-#include "IntRect.h"
-#include "GraphicsContext.h"
-#include "RenderSkinAndroid.h"
-#include "SkCanvas.h"
-#include "SkPicture.h"
-#include "SkTDArray.h"
-#include <wtf/Vector.h>
-
-class SkCanvas;
-
-namespace WebCore {
-
-class PlatformGraphicsContext {
-public:
- PlatformGraphicsContext(SkCanvas* canvas, bool takeCanvasOwnership = false);
- ~PlatformGraphicsContext();
-
- void setGraphicsContext(GraphicsContext* gc) { m_gc = gc; }
-
- // FIXME: Make mCanvas private
- SkCanvas* mCanvas;
- // FIXME: This is used by ImageBufferAndroid, which should really be
- // managing the canvas lifecycle itself
- bool deleteUs() const { return m_deleteCanvas; }
-
- // State management
- void beginTransparencyLayer(float opacity);
- void endTransparencyLayer();
- void save();
- void restore();
-
- // State values
- void setAlpha(float alpha);
- void setCompositeOperation(CompositeOperator op);
- void setFillColor(const Color& c);
- void setFillShader(SkShader* fillShader);
- void setLineCap(LineCap cap);
- void setLineDash(const DashArray& dashes, float dashOffset);
- void setLineJoin(LineJoin join);
- void setMiterLimit(float limit);
- void setShadow(int radius, int dx, int dy, SkColor c);
- void setShouldAntialias(bool useAA);
- void setStrokeColor(const Color& c);
- void setStrokeShader(SkShader* strokeShader);
- void setStrokeStyle(StrokeStyle style);
- void setStrokeThickness(float f);
-
- // FIXME: These setupPaint* should be private, but
- // they are used by FontAndroid currently
- void setupPaintFill(SkPaint* paint) const;
- bool setupPaintShadow(SkPaint* paint, SkPoint* offset) const;
- // Sets up the paint for stroking. Returns true if the style is really
- // just a dash of squares (the size of the paint's stroke-width.
- bool setupPaintStroke(SkPaint* paint, SkRect* rect, bool isHLine = false);
-
- // Matrix operations
- void concatCTM(const AffineTransform& affine);
- void rotate(float angleInRadians);
- void scale(const FloatSize& size);
- void translate(float x, float y);
- const SkMatrix& getTotalMatrix() { return mCanvas->getTotalMatrix(); }
-
- // Clipping
- void addInnerRoundedRectClip(const IntRect& rect, int thickness);
- void canvasClip(const Path& path);
- void clip(const FloatRect& rect);
- void clip(const Path& path);
- void clipConvexPolygon(size_t numPoints, const FloatPoint*, bool antialias);
- void clipOut(const IntRect& r);
- void clipOut(const Path& p);
- void clipPath(const Path& pathToClip, WindRule clipRule);
-
- // Drawing
- void clearRect(const FloatRect& rect);
- void drawBitmapPattern(const SkBitmap& bitmap, const SkMatrix& matrix,
- CompositeOperator compositeOp, const FloatRect& destRect);
- void drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src,
- const SkRect& dst, CompositeOperator op);
- void drawConvexPolygon(size_t numPoints, const FloatPoint* points,
- bool shouldAntialias);
- void drawEllipse(const IntRect& rect);
- void drawFocusRing(const Vector<IntRect>& rects, int /* width */,
- int /* offset */, const Color& color);
- void drawHighlightForText(const Font& font, const TextRun& run,
- const FloatPoint& point, int h,
- const Color& backgroundColor, ColorSpace colorSpace,
- int from, int to, bool isActive);
- void drawLine(const IntPoint& point1, const IntPoint& point2);
- void drawLineForText(const FloatPoint& pt, float width);
- void drawLineForTextChecking(const FloatPoint& pt, float width,
- GraphicsContext::TextCheckingLineStyle);
- void drawRect(const IntRect& rect);
- void fillPath(const Path& pathToFill, WindRule fillRule);
- void fillRect(const FloatRect& rect);
- void fillRect(const FloatRect& rect, const Color& color, ColorSpace);
- void fillRoundedRect(const IntRect& rect, const IntSize& topLeft,
- const IntSize& topRight, const IntSize& bottomLeft,
- const IntSize& bottomRight, const Color& color,
- ColorSpace);
- void strokeArc(const IntRect& r, int startAngle, int angleSpan);
- void strokePath(const Path& pathToStroke);
- void strokeRect(const FloatRect& rect, float lineWidth);
-
-private:
-
- // shadowsIgnoreTransforms is only true for canvas's ImageBuffer, which will
- // have a GraphicsContext
- bool shadowsIgnoreTransforms() const {
- return m_gc && m_gc->shadowsIgnoreTransforms();
- }
-
- void setupPaintCommon(SkPaint* paint) const;
-
- bool m_deleteCanvas;
- struct State;
- WTF::Vector<State> m_stateStack;
- State* m_state;
- GraphicsContext* m_gc; // Back-ptr to our parent
-};
-
-}
-#endif
diff --git a/Source/WebCore/platform/graphics/android/GraphicsContextAndroid.cpp b/Source/WebCore/platform/graphics/android/context/GraphicsContextAndroid.cpp
index 7d6c809..12b53a3 100644
--- a/Source/WebCore/platform/graphics/android/GraphicsContextAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/context/GraphicsContextAndroid.cpp
@@ -32,6 +32,7 @@
#include "Path.h"
#include "Pattern.h"
#include "PlatformGraphicsContext.h"
+#include "PlatformGraphicsContextSkia.h"
#include "SkBitmapRef.h"
#include "SkBlurDrawLooper.h"
#include "SkBlurMaskFilter.h"
@@ -78,14 +79,14 @@ static SkShader* extractShader(Pattern* pat, Gradient* grad)
GraphicsContext* GraphicsContext::createOffscreenContext(int width, int height)
{
- PlatformGraphicsContext* pgc = new PlatformGraphicsContext(new SkCanvas, true);
+ PlatformGraphicsContextSkia* pgc = new PlatformGraphicsContextSkia(new SkCanvas, true);
SkBitmap bitmap;
bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height);
bitmap.allocPixels();
bitmap.eraseColor(0);
- pgc->mCanvas->setBitmapDevice(bitmap);
+ pgc->getCanvas()->setBitmapDevice(bitmap);
GraphicsContext* ctx = new GraphicsContext(pgc);
return ctx;
@@ -98,7 +99,7 @@ void GraphicsContext::platformInit(PlatformGraphicsContext* gc)
if (gc)
gc->setGraphicsContext(this);
m_data = new GraphicsContextPlatformPrivate(gc);
- setPaintingDisabled(!gc || !gc->mCanvas);
+ setPaintingDisabled(!gc || gc->isPaintingDisabled());
}
void GraphicsContext::platformDestroy()
@@ -643,5 +644,5 @@ void GraphicsContext::drawHighlightForText(const Font& font, const TextRun& run,
SkCanvas* android_gc2canvas(WebCore::GraphicsContext* gc)
{
- return gc->platformContext()->mCanvas;
+ return gc->platformContext()->getCanvas();
}
diff --git a/Source/WebCore/platform/graphics/android/context/GraphicsOperation.h b/Source/WebCore/platform/graphics/android/context/GraphicsOperation.h
new file mode 100644
index 0000000..927ff0a
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/context/GraphicsOperation.h
@@ -0,0 +1,809 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef GraphicsOperation_h
+#define GraphicsOperation_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "Color.h"
+#include "FloatRect.h"
+#include "GlyphBuffer.h"
+#include "Font.h"
+#include "IntRect.h"
+#include "PlatformGraphicsContext.h"
+#include "PlatformGraphicsContextSkia.h"
+#include "SkCanvas.h"
+#include "SkShader.h"
+#include "SkRefCnt.h"
+
+#include <utils/threads.h>
+#include <wtf/text/CString.h>
+
+#define TYPE_CASE(type) case type: return #type;
+
+namespace WebCore {
+
+namespace GraphicsOperation {
+
+class Operation : public SkRefCnt {
+public:
+ typedef enum { UndefinedOperation
+ // State management
+ , BeginTransparencyLayerOperation
+ , EndTransparencyLayerOperation
+ , SaveOperation
+ , RestoreOperation
+ // State setters
+ , SetAlphaOperation
+ , SetCompositeOpOperation
+ , SetFillColorOperation
+ , SetFillShaderOperation
+ , SetLineCapOperation
+ , SetLineDashOperation
+ , SetLineJoinOperation
+ , SetMiterLimitOperation
+ , SetShadowOperation
+ , SetShouldAntialiasOperation
+ , SetStrokeColorOperation
+ , SetStrokeShaderOperation
+ , SetStrokeStyleOperation
+ , SetStrokeThicknessOperation
+ // Paint setup
+ , SetupPaintFillOperation
+ , SetupPaintShadowOperation
+ , SetupPaintStrokeOperation
+ // Matrix operations
+ , ConcatCTMOperation
+ , ScaleOperation
+ , RotateOperation
+ , TranslateOperation
+ // Clipping
+ , InnerRoundedRectClipOperation
+ , ClipOperation
+ , ClipPathOperation
+ , ClipOutOperation
+ , ClearRectOperation
+ // Drawing
+ , DrawBitmapPatternOperation
+ , DrawBitmapRectOperation
+ , DrawEllipseOperation
+ , DrawLineOperation
+ , DrawLineForTextOperation
+ , DrawLineForTextCheckingOperation
+ , DrawRectOperation
+ , FillPathOperation
+ , FillRectOperation
+ , FillRoundedRectOperation
+ , StrokeArcOperation
+ , StrokePathOperation
+ , StrokeRectOperation
+ // Text
+ , DrawComplexTextOperation
+ , DrawTextOperation
+ } OperationType;
+
+ virtual void apply(PlatformGraphicsContext* context) = 0;
+ virtual ~Operation() {}
+ virtual OperationType type() { return UndefinedOperation; }
+ virtual String parameters() { return ""; }
+ String name()
+ {
+ switch (type()) {
+ TYPE_CASE(UndefinedOperation)
+ // State management
+ TYPE_CASE(BeginTransparencyLayerOperation)
+ TYPE_CASE(EndTransparencyLayerOperation)
+ TYPE_CASE(SaveOperation)
+ TYPE_CASE(RestoreOperation)
+ // State setters
+ TYPE_CASE(SetAlphaOperation)
+ TYPE_CASE(SetCompositeOpOperation)
+ TYPE_CASE(SetFillColorOperation)
+ TYPE_CASE(SetFillShaderOperation)
+ TYPE_CASE(SetLineCapOperation)
+ TYPE_CASE(SetLineDashOperation)
+ TYPE_CASE(SetLineJoinOperation)
+ TYPE_CASE(SetMiterLimitOperation)
+ TYPE_CASE(SetShadowOperation)
+ TYPE_CASE(SetShouldAntialiasOperation)
+ TYPE_CASE(SetStrokeColorOperation)
+ TYPE_CASE(SetStrokeShaderOperation)
+ TYPE_CASE(SetStrokeStyleOperation)
+ TYPE_CASE(SetStrokeThicknessOperation)
+ // Paint setup
+ TYPE_CASE(SetupPaintFillOperation)
+ TYPE_CASE(SetupPaintShadowOperation)
+ TYPE_CASE(SetupPaintStrokeOperation)
+ // Matrix operations
+ TYPE_CASE(ConcatCTMOperation)
+ TYPE_CASE(ScaleOperation)
+ TYPE_CASE(RotateOperation)
+ TYPE_CASE(TranslateOperation)
+ // Clipping
+ TYPE_CASE(InnerRoundedRectClipOperation)
+ TYPE_CASE(ClipOperation)
+ TYPE_CASE(ClipPathOperation)
+ TYPE_CASE(ClipOutOperation)
+ TYPE_CASE(ClearRectOperation)
+ // Drawing
+ TYPE_CASE(DrawBitmapPatternOperation)
+ TYPE_CASE(DrawBitmapRectOperation)
+ TYPE_CASE(DrawEllipseOperation)
+ TYPE_CASE(DrawLineOperation)
+ TYPE_CASE(DrawLineForTextOperation)
+ TYPE_CASE(DrawLineForTextCheckingOperation)
+ TYPE_CASE(DrawRectOperation)
+ TYPE_CASE(FillPathOperation)
+ TYPE_CASE(FillRectOperation)
+ TYPE_CASE(FillRoundedRectOperation)
+ TYPE_CASE(StrokeArcOperation)
+ TYPE_CASE(StrokePathOperation)
+ TYPE_CASE(StrokeRectOperation)
+ // Text
+ TYPE_CASE(DrawComplexTextOperation)
+ TYPE_CASE(DrawTextOperation)
+ }
+ return "Undefined";
+ }
+};
+
+//**************************************
+// State management
+//**************************************
+
+class BeginTransparencyLayer : public Operation {
+public:
+ BeginTransparencyLayer(const float opacity) : m_opacity(opacity) {}
+ virtual void apply(PlatformGraphicsContext* context) { context->beginTransparencyLayer(m_opacity); }
+ virtual OperationType type() { return BeginTransparencyLayerOperation; }
+private:
+ float m_opacity;
+};
+class EndTransparencyLayer : public Operation {
+public:
+ EndTransparencyLayer() {}
+ virtual void apply(PlatformGraphicsContext* context) { context->endTransparencyLayer(); }
+ virtual OperationType type() { return EndTransparencyLayerOperation; }
+};
+class Save : public Operation {
+public:
+ virtual void apply(PlatformGraphicsContext* context) { context->save(); }
+ virtual OperationType type() { return SaveOperation; }
+};
+class Restore : public Operation {
+public:
+ virtual void apply(PlatformGraphicsContext* context) { context->restore(); }
+ virtual OperationType type() { return RestoreOperation; }
+};
+
+//**************************************
+// State setters
+//**************************************
+
+class SetAlpha : public Operation {
+public:
+ SetAlpha(const float alpha) : m_alpha(alpha) {}
+ virtual void apply(PlatformGraphicsContext* context) { context->setAlpha(m_alpha); }
+ virtual OperationType type() { return SetAlphaOperation; }
+private:
+ float m_alpha;
+};
+
+class SetCompositeOperation : public Operation {
+public:
+ SetCompositeOperation(CompositeOperator op) : m_operator(op) {}
+ virtual void apply(PlatformGraphicsContext* context) {
+ context->setCompositeOperation(m_operator);
+ }
+ virtual OperationType type() { return SetCompositeOpOperation; }
+private:
+ CompositeOperator m_operator;
+};
+
+class SetFillColor : public Operation {
+public:
+ SetFillColor(Color color) : m_color(color) {}
+ virtual void apply(PlatformGraphicsContext* context) {
+ context->setFillColor(m_color);
+ }
+ virtual OperationType type() { return SetFillColorOperation; }
+ virtual String parameters() {
+ return String::format("r: %d g: %d b: %d a: %d",
+ m_color.red(),
+ m_color.green(),
+ m_color.blue(),
+ m_color.alpha());
+ }
+private:
+ Color m_color;
+};
+
+class SetFillShader : public Operation {
+public:
+ SetFillShader(SkShader* shader) : m_shader(shader) {
+ SkSafeRef(m_shader);
+ }
+ ~SetFillShader() { SkSafeUnref(m_shader); }
+ virtual void apply(PlatformGraphicsContext* context) {
+ context->setFillShader(m_shader);
+ }
+ virtual OperationType type() { return SetFillShaderOperation; }
+private:
+ SkShader* m_shader;
+};
+
+class SetLineCap : public Operation {
+public:
+ SetLineCap(LineCap cap) : m_cap(cap) {}
+ virtual void apply(PlatformGraphicsContext* context) {
+ context->setLineCap(m_cap);
+ }
+ virtual OperationType type() { return SetLineCapOperation; }
+private:
+ LineCap m_cap;
+};
+
+class SetLineDash : public Operation {
+public:
+ SetLineDash(const DashArray& dashes, float dashOffset)
+ : m_dashes(dashes), m_dashOffset(dashOffset) {}
+ virtual void apply(PlatformGraphicsContext* context) {
+ context->setLineDash(m_dashes, m_dashOffset);
+ }
+ virtual OperationType type() { return SetLineDashOperation; }
+private:
+ DashArray m_dashes;
+ float m_dashOffset;
+};
+
+class SetLineJoin : public Operation {
+public:
+ SetLineJoin(LineJoin join) : m_join(join) {}
+ virtual void apply(PlatformGraphicsContext* context) {
+ context->setLineJoin(m_join);
+ }
+ virtual OperationType type() { return SetLineJoinOperation; }
+private:
+ LineJoin m_join;
+};
+
+class SetMiterLimit : public Operation {
+public:
+ SetMiterLimit(float limit) : m_limit(limit) {}
+ virtual void apply(PlatformGraphicsContext* context) {
+ context->setMiterLimit(m_limit);
+ }
+ virtual OperationType type() { return SetMiterLimitOperation; }
+private:
+ float m_limit;
+};
+
+class SetShadow : public Operation {
+public:
+ SetShadow(int radius, int dx, int dy, SkColor c)
+ : m_radius(radius), m_dx(dx), m_dy(dy), m_color(c) {}
+ virtual void apply(PlatformGraphicsContext* context) {
+ context->setShadow(m_radius, m_dx, m_dy, m_color);
+ }
+ virtual OperationType type() { return SetShadowOperation; }
+private:
+ int m_radius;
+ int m_dx;
+ int m_dy;
+ SkColor m_color;
+};
+
+class SetShouldAntialias : public Operation {
+public:
+ SetShouldAntialias(bool useAA) : m_useAA(useAA) {}
+ virtual void apply(PlatformGraphicsContext* context) {
+ context->setShouldAntialias(m_useAA);
+ }
+ virtual OperationType type() { return SetShouldAntialiasOperation; }
+private:
+ bool m_useAA;
+};
+
+class SetStrokeColor : public Operation {
+public:
+ SetStrokeColor(const Color& c) : m_color(c) {}
+ virtual void apply(PlatformGraphicsContext* context) {
+ context->setStrokeColor(m_color);
+ }
+ virtual OperationType type() { return SetStrokeColorOperation; }
+private:
+ Color m_color;
+};
+
+class SetStrokeShader : public Operation {
+public:
+ SetStrokeShader(SkShader* strokeShader) : m_shader(strokeShader) {
+ SkSafeRef(m_shader);
+ }
+ ~SetStrokeShader() { SkSafeUnref(m_shader); }
+ virtual void apply(PlatformGraphicsContext* context) {
+ context->setStrokeShader(m_shader);
+ }
+ virtual OperationType type() { return SetStrokeShaderOperation; }
+private:
+ SkShader* m_shader;
+};
+
+class SetStrokeStyle : public Operation {
+public:
+ SetStrokeStyle(StrokeStyle style) : m_style(style) {}
+ virtual void apply(PlatformGraphicsContext* context) {
+ context->setStrokeStyle(m_style);
+ }
+ virtual OperationType type() { return SetStrokeStyleOperation; }
+private:
+ StrokeStyle m_style;
+};
+
+class SetStrokeThickness : public Operation {
+public:
+ SetStrokeThickness(float thickness) : m_thickness(thickness) {}
+ virtual void apply(PlatformGraphicsContext* context) {
+ context->setStrokeThickness(m_thickness);
+ }
+ virtual OperationType type() { return SetStrokeThicknessOperation; }
+private:
+ float m_thickness;
+};
+
+//**************************************
+// Paint setup
+//**************************************
+
+class SetupPaintFill : public Operation {
+public:
+ SetupPaintFill(SkPaint* paint) : m_paint(*paint) {}
+ virtual void apply(PlatformGraphicsContext* context) {
+ context->setupPaintFill(&m_paint);
+ }
+ virtual OperationType type() { return SetupPaintFillOperation; }
+private:
+ SkPaint m_paint;
+};
+
+class SetupPaintShadow : public Operation {
+public:
+ SetupPaintShadow(SkPaint* paint, SkPoint* offset)
+ : m_paint(*paint), m_offset(*offset) {}
+ virtual void apply(PlatformGraphicsContext* context) {
+ context->setupPaintShadow(&m_paint, &m_offset);
+ }
+ virtual OperationType type() { return SetupPaintShadowOperation; }
+private:
+ SkPaint m_paint;
+ SkPoint m_offset;
+};
+
+class SetupPaintStroke : public Operation {
+public:
+ SetupPaintStroke(SkPaint* paint, SkRect* rect, bool isHLine)
+ : m_paint(*paint), m_rect(*rect), m_isHLine(isHLine) {}
+ virtual void apply(PlatformGraphicsContext* context) {
+ context->setupPaintStroke(&m_paint, &m_rect, m_isHLine);
+ }
+ virtual OperationType type() { return SetupPaintStrokeOperation; }
+private:
+ SkPaint m_paint;
+ SkRect m_rect;
+ bool m_isHLine;
+};
+
+//**************************************
+// Matrix operations
+//**************************************
+
+class ConcatCTM : public Operation {
+public:
+ ConcatCTM(const AffineTransform& affine) : m_matrix(affine) {}
+ virtual void apply(PlatformGraphicsContext* context) {
+ context->concatCTM(m_matrix);
+ }
+ virtual OperationType type() { return ConcatCTMOperation; }
+private:
+ AffineTransform m_matrix;
+};
+
+class Rotate : public Operation {
+public:
+ Rotate(float angleInRadians) : m_angle(angleInRadians) {}
+ virtual void apply(PlatformGraphicsContext* context) {
+ context->rotate(m_angle);
+ }
+ virtual OperationType type() { return RotateOperation; }
+private:
+ float m_angle;
+};
+
+class Scale : public Operation {
+public:
+ Scale(const FloatSize& size) : m_scale(size) {}
+ virtual void apply(PlatformGraphicsContext* context) {
+ context->scale(m_scale);
+ }
+ virtual OperationType type() { return ScaleOperation; }
+private:
+ FloatSize m_scale;
+};
+
+class Translate : public Operation {
+public:
+ Translate(float x, float y) : m_x(x), m_y(y) {}
+ virtual void apply(PlatformGraphicsContext* context) {
+ context->translate(m_x, m_y);
+ }
+ virtual OperationType type() { return TranslateOperation; }
+private:
+ float m_x;
+ float m_y;
+};
+
+//**************************************
+// Clipping
+//**************************************
+
+class InnerRoundedRectClip : public Operation {
+public:
+ InnerRoundedRectClip(const IntRect& rect, int thickness)
+ : m_rect(rect), m_thickness(thickness) {}
+ virtual void apply(PlatformGraphicsContext* context) {
+ context->addInnerRoundedRectClip(m_rect, m_thickness);
+ }
+ virtual OperationType type() { return InnerRoundedRectClipOperation; }
+private:
+ IntRect m_rect;
+ int m_thickness;
+};
+
+class Clip : public Operation {
+public:
+ Clip(const FloatRect& rect) : m_rect(rect) {}
+ virtual void apply(PlatformGraphicsContext* context) {
+ context->clip(m_rect);
+ }
+ virtual OperationType type() { return ClipOperation; }
+private:
+ const FloatRect m_rect;
+};
+
+class ClipPath : public Operation {
+public:
+ ClipPath(const Path& path, bool clipout = false)
+ : m_path(path), m_clipOut(clipout), m_hasWindRule(false) {}
+ void setWindRule(WindRule rule) { m_windRule = rule; m_hasWindRule = true; }
+ virtual void apply(PlatformGraphicsContext* context) {
+ if (m_hasWindRule) {
+ context->clipPath(m_path, m_windRule);
+ return;
+ }
+ if (m_clipOut)
+ context->clipOut(m_path);
+ else
+ context->clip(m_path);
+ }
+ virtual OperationType type() { return ClipPathOperation; }
+private:
+ const Path m_path;
+ bool m_clipOut;
+ WindRule m_windRule;
+ bool m_hasWindRule;
+};
+
+class ClipOut : public Operation {
+public:
+ ClipOut(const IntRect& rect) : m_rect(rect) {}
+ virtual void apply(PlatformGraphicsContext* context) {
+ context->clipOut(m_rect);
+ }
+ virtual OperationType type() { return ClipOutOperation; }
+private:
+ const IntRect m_rect;
+};
+
+class ClearRect : public Operation {
+public:
+ ClearRect(const FloatRect& rect) : m_rect(rect) {}
+ virtual void apply(PlatformGraphicsContext* context) {
+ context->clearRect(m_rect);
+ }
+ virtual OperationType type() { return ClearRectOperation; }
+private:
+ FloatRect m_rect;
+};
+
+//**************************************
+// Drawing
+//**************************************
+
+class DrawBitmapPattern : public Operation {
+public:
+ DrawBitmapPattern(const SkBitmap& bitmap, const SkMatrix& matrix,
+ CompositeOperator op, const FloatRect& destRect)
+ : m_bitmap(bitmap), m_matrix(matrix), m_operator(op), m_destRect(destRect) {}
+ virtual void apply(PlatformGraphicsContext* context) {
+ context->drawBitmapPattern(m_bitmap, m_matrix, m_operator, m_destRect);
+ }
+ virtual OperationType type() { return DrawBitmapPatternOperation; }
+private:
+ // TODO: use refcounted bitmap
+ const SkBitmap m_bitmap;
+ SkMatrix m_matrix;
+ CompositeOperator m_operator;
+ FloatRect m_destRect;
+};
+
+class DrawBitmapRect : public Operation {
+public:
+ DrawBitmapRect(const SkBitmap& bitmap, const SkIRect& srcR,
+ const SkRect& dstR, CompositeOperator op)
+ : m_bitmap(bitmap), m_srcR(srcR), m_dstR(dstR), m_operator(op) {}
+ virtual void apply(PlatformGraphicsContext* context) {
+ context->drawBitmapRect(m_bitmap, &m_srcR, m_dstR, m_operator);
+ }
+ virtual OperationType type() { return DrawBitmapRectOperation; }
+ virtual String parameters() {
+ return String::format("%.2f, %.2f - %.2f x %.2f",
+ m_dstR.fLeft, m_dstR.fTop,
+ m_dstR.width(), m_dstR.height());
+ }
+private:
+ const SkBitmap& m_bitmap;
+ SkIRect m_srcR;
+ SkRect m_dstR;
+ CompositeOperator m_operator;
+};
+
+class DrawEllipse : public Operation {
+public:
+ DrawEllipse(const IntRect& rect) : m_rect(rect) {}
+ virtual void apply(PlatformGraphicsContext* context) {
+ context->drawEllipse(m_rect);
+ }
+ virtual OperationType type() { return DrawEllipseOperation; }
+private:
+ IntRect m_rect;
+};
+
+class DrawLine : public Operation {
+public:
+ DrawLine(const IntPoint& point1, const IntPoint& point2)
+ : m_point1(point1), m_point2(point2) {}
+ virtual void apply(PlatformGraphicsContext* context) {
+ context->drawLine(m_point1, m_point2);
+ }
+ virtual OperationType type() { return DrawLineOperation; }
+private:
+ IntPoint m_point1;
+ IntPoint m_point2;
+};
+
+class DrawLineForText : public Operation {
+public:
+ DrawLineForText(const FloatPoint& pt, float width)
+ : m_point(pt), m_width(width) {}
+ virtual void apply(PlatformGraphicsContext* context) {
+ context->drawLineForText(m_point, m_width);
+ }
+ virtual OperationType type() { return DrawLineForTextOperation; }
+private:
+ FloatPoint m_point;
+ float m_width;
+};
+
+class DrawLineForTextChecking : public Operation {
+public:
+ DrawLineForTextChecking(const FloatPoint& pt, float width,
+ GraphicsContext::TextCheckingLineStyle lineStyle)
+ : m_point(pt), m_width(width), m_lineStyle(lineStyle) {}
+ virtual void apply(PlatformGraphicsContext* context) {
+ context->drawLineForTextChecking(m_point, m_width, m_lineStyle);
+ }
+ virtual OperationType type() { return DrawLineForTextCheckingOperation; }
+private:
+ FloatPoint m_point;
+ float m_width;
+ GraphicsContext::TextCheckingLineStyle m_lineStyle;
+};
+
+class DrawRect : public Operation {
+public:
+ DrawRect(const IntRect& rect) : m_rect(rect) {}
+ virtual void apply(PlatformGraphicsContext* context) {
+ context->drawRect(m_rect);
+ }
+ virtual OperationType type() { return DrawRectOperation; }
+private:
+ IntRect m_rect;
+};
+
+class FillPath : public Operation {
+public:
+ FillPath(const Path& pathToFill, WindRule fillRule)
+ : m_path(pathToFill), m_fillRule(fillRule) {}
+ virtual void apply(PlatformGraphicsContext* context) {
+ context->fillPath(m_path, m_fillRule);
+ }
+ virtual OperationType type() { return FillPathOperation; }
+private:
+ Path m_path;
+ WindRule m_fillRule;
+};
+
+class FillRect : public Operation {
+public:
+ FillRect(const FloatRect& rect) : m_rect(rect), m_hasColor(false) {}
+ void setColor(Color c) { m_color = c; m_hasColor = true; }
+ virtual void apply(PlatformGraphicsContext* context) {
+ if (m_hasColor)
+ context->fillRect(m_rect, m_color);
+ else
+ context->fillRect(m_rect);
+ }
+ virtual OperationType type() { return FillRectOperation; }
+private:
+ FloatRect m_rect;
+ Color m_color;
+ bool m_hasColor;
+};
+
+class FillRoundedRect : public Operation {
+public:
+ FillRoundedRect(const IntRect& rect,
+ const IntSize& topLeft,
+ const IntSize& topRight,
+ const IntSize& bottomLeft,
+ const IntSize& bottomRight,
+ const Color& color)
+ : m_rect(rect)
+ , m_topLeft(topLeft)
+ , m_topRight(topRight)
+ , m_bottomLeft(bottomLeft)
+ , m_bottomRight(bottomRight)
+ , m_color(color)
+ {}
+ virtual void apply(PlatformGraphicsContext* context) {
+ context->fillRoundedRect(m_rect, m_topLeft, m_topRight,
+ m_bottomLeft, m_bottomRight,
+ m_color);
+ }
+ virtual OperationType type() { return FillRoundedRectOperation; }
+private:
+ IntRect m_rect;
+ IntSize m_topLeft;
+ IntSize m_topRight;
+ IntSize m_bottomLeft;
+ IntSize m_bottomRight;
+ Color m_color;
+};
+
+class StrokeArc : public Operation {
+public:
+ StrokeArc(const IntRect& r, int startAngle, int angleSpan)
+ : m_rect(r)
+ , m_startAngle(startAngle)
+ , m_angleSpan(angleSpan)
+ {}
+ virtual void apply(PlatformGraphicsContext* context) {
+ context->strokeArc(m_rect, m_startAngle, m_angleSpan);
+ }
+ virtual OperationType type() { return StrokeArcOperation; }
+private:
+ IntRect m_rect;
+ int m_startAngle;
+ int m_angleSpan;
+};
+
+class StrokePath : public Operation {
+public:
+ StrokePath(const Path& path) : m_path(path) {}
+ virtual void apply(PlatformGraphicsContext* context) {
+ context->strokePath(m_path);
+ }
+ virtual OperationType type() { return StrokePathOperation; }
+private:
+ Path m_path;
+};
+
+
+class StrokeRect : public Operation {
+public:
+ StrokeRect(const FloatRect& rect, float lineWidth)
+ : m_rect(rect), m_lineWidth(lineWidth) {}
+ virtual void apply(PlatformGraphicsContext* context) {
+ context->strokeRect(m_rect, m_lineWidth);
+ }
+ virtual OperationType type() { return StrokeRectOperation; }
+private:
+ FloatRect m_rect;
+ float m_lineWidth;
+};
+
+//**************************************
+// Text
+//**************************************
+
+class DrawComplexText : public Operation {
+public:
+ DrawComplexText(SkPicture* picture) : m_picture(picture) {
+ SkSafeRef(m_picture);
+ }
+ ~DrawComplexText() { SkSafeUnref(m_picture); }
+ virtual void apply(PlatformGraphicsContext* context) {
+ if (!context->getCanvas())
+ return;
+ context->getCanvas()->drawPicture(*m_picture);
+ }
+ virtual OperationType type() { return DrawComplexTextOperation; }
+private:
+ SkPicture* m_picture;
+};
+
+class DrawText : public Operation {
+public:
+ DrawText(const Font* font, const SimpleFontData* simpleFont,
+ const GlyphBuffer& glyphBuffer,
+ int from, int numGlyphs, const FloatPoint& point)
+ : m_font(font), m_simpleFont(simpleFont)
+ , m_glyphBuffer(glyphBuffer), m_from(from)
+ , m_numGlyphs(numGlyphs), m_point(point) {
+
+ SkPicture* picture = new SkPicture();
+ SkCanvas* canvas = picture->beginRecording(0, 0, 0);
+ PlatformGraphicsContextSkia platformContext(canvas);
+ GraphicsContext graphicsContext(&platformContext);
+ m_font->drawGlyphs(&graphicsContext, m_simpleFont,
+ m_glyphBuffer, m_from, m_numGlyphs, m_point);
+ picture->endRecording();
+ m_picture = picture;
+ }
+ ~DrawText() { SkSafeUnref(m_picture); }
+ virtual void apply(PlatformGraphicsContext* context) {
+ if (!context->getCanvas())
+ return;
+ context->getCanvas()->drawPicture(*m_picture);
+ }
+ virtual OperationType type() { return DrawTextOperation; }
+private:
+ SkPicture* m_picture;
+ const Font* m_font;
+ const SimpleFontData* m_simpleFont;
+ const GlyphBuffer m_glyphBuffer;
+ int m_from;
+ int m_numGlyphs;
+ const FloatPoint m_point;
+};
+
+}
+
+}
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif // GraphicsOperation_h
diff --git a/Source/WebCore/platform/graphics/android/context/GraphicsOperationCollection.cpp b/Source/WebCore/platform/graphics/android/context/GraphicsOperationCollection.cpp
new file mode 100644
index 0000000..6118160
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/context/GraphicsOperationCollection.cpp
@@ -0,0 +1,63 @@
+#define LOG_TAG "GraphicsOperationCollection"
+#define LOG_NDEBUG 1
+
+#include "config.h"
+#include "GraphicsOperationCollection.h"
+
+#include "AndroidLog.h"
+#include "GraphicsContext.h"
+#include "PlatformGraphicsContext.h"
+#include "PlatformGraphicsContextRecording.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+namespace WebCore {
+
+GraphicsOperationCollection::GraphicsOperationCollection(const IntRect& drawArea)
+ : m_drawArea(drawArea)
+{
+}
+
+GraphicsOperationCollection::~GraphicsOperationCollection()
+{
+ for (unsigned int i = 0; i < m_operations.size(); i++)
+ SkSafeUnref(m_operations[i]);
+}
+
+void GraphicsOperationCollection::apply(PlatformGraphicsContext* context)
+{
+ ALOGD("\nApply GraphicsOperationCollection %x, %d operations", this, m_operations.size());
+ for (unsigned int i = 0; i < m_operations.size(); i++) {
+ ALOGD("[%d] (%x) %s %s", i, this, m_operations[i]->name().latin1().data(),
+ m_operations[i]->parameters().latin1().data());
+ m_operations[i]->apply(context);
+ }
+}
+
+void GraphicsOperationCollection::append(GraphicsOperation::Operation* operation)
+{
+ m_operations.append(operation);
+}
+
+bool GraphicsOperationCollection::isEmpty()
+{
+ return !m_operations.size();
+}
+
+AutoGraphicsOperationCollection::AutoGraphicsOperationCollection(const IntRect& area)
+{
+ m_graphicsOperationCollection = new GraphicsOperationCollection(area);
+ m_platformGraphicsContext = new PlatformGraphicsContextRecording(m_graphicsOperationCollection);
+ m_graphicsContext = new GraphicsContext(m_platformGraphicsContext);
+}
+
+AutoGraphicsOperationCollection::~AutoGraphicsOperationCollection()
+{
+ SkSafeUnref(m_graphicsOperationCollection);
+ delete m_graphicsContext;
+ delete m_platformGraphicsContext;
+}
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/android/context/GraphicsOperationCollection.h b/Source/WebCore/platform/graphics/android/context/GraphicsOperationCollection.h
new file mode 100644
index 0000000..9d7b530
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/context/GraphicsOperationCollection.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef GraphicsOperationCollection_h
+#define GraphicsOperationCollection_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "Color.h"
+#include "GraphicsOperation.h"
+#include "IntRect.h"
+#include "SkRefCnt.h"
+
+namespace WebCore {
+
+class PlatformGraphicsContext;
+
+class GraphicsOperationCollection : public SkRefCnt {
+public:
+ GraphicsOperationCollection(const IntRect& drawArea);
+ ~GraphicsOperationCollection();
+
+ void apply(PlatformGraphicsContext* context);
+ void append(GraphicsOperation::Operation* operation);
+
+ bool isEmpty();
+
+private:
+ IntRect m_drawArea;
+ Vector<GraphicsOperation::Operation*> m_operations;
+};
+
+class AutoGraphicsOperationCollection {
+public:
+ AutoGraphicsOperationCollection(const IntRect& area);
+ ~AutoGraphicsOperationCollection();
+ GraphicsContext* context() { return m_graphicsContext; }
+ GraphicsOperationCollection* picture() { return m_graphicsOperationCollection; }
+
+private:
+ GraphicsOperationCollection* m_graphicsOperationCollection;
+ PlatformGraphicsContext* m_platformGraphicsContext;
+ GraphicsContext* m_graphicsContext;
+};
+
+}
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif // GraphicsOperationCollection_h
diff --git a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContext.cpp b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContext.cpp
new file mode 100644
index 0000000..bb5d990
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContext.cpp
@@ -0,0 +1,456 @@
+/*
+ * Copyright 2006, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define LOG_TAG "PlatformGraphicsContext"
+#define LOG_NDEBUG 1
+
+#include "config.h"
+#include "PlatformGraphicsContext.h"
+
+#include "AndroidLog.h"
+#include "SkBlurDrawLooper.h"
+#include "SkBlurMaskFilter.h"
+#include "SkColorPriv.h"
+#include "SkDashPathEffect.h"
+#include "SkPaint.h"
+#include "SkShader.h"
+#include "SkiaUtils.h"
+
+namespace WebCore {
+
+//**************************************
+// Helper functions
+//**************************************
+
+static int RoundToInt(float x)
+{
+ return (int)roundf(x);
+}
+
+template <typename T> T* deepCopyPtr(const T* src)
+{
+ return src ? new T(*src) : 0;
+}
+
+// Set a bitmap shader that mimics dashing by width-on, width-off.
+// Returns false if it could not succeed (e.g. there was an existing shader)
+static bool setBitmapDash(SkPaint* paint, int width) {
+ if (width <= 0 || paint->getShader())
+ return false;
+
+ SkColor c = paint->getColor();
+
+ SkBitmap bm;
+ bm.setConfig(SkBitmap::kARGB_8888_Config, 2, 1);
+ bm.allocPixels();
+ bm.lockPixels();
+
+ // set the ON pixel
+ *bm.getAddr32(0, 0) = SkPreMultiplyARGB(0xFF, SkColorGetR(c),
+ SkColorGetG(c), SkColorGetB(c));
+ // set the OFF pixel
+ *bm.getAddr32(1, 0) = 0;
+ bm.unlockPixels();
+
+ SkMatrix matrix;
+ matrix.setScale(SkIntToScalar(width), SK_Scalar1);
+
+ SkShader* s = SkShader::CreateBitmapShader(bm, SkShader::kRepeat_TileMode,
+ SkShader::kClamp_TileMode);
+ s->setLocalMatrix(matrix);
+
+ paint->setShader(s)->unref();
+ return true;
+}
+
+//**************************************
+// State implementation
+//**************************************
+
+PlatformGraphicsContext::State::State()
+ : pathEffect(0)
+ , miterLimit(4)
+ , alpha(1)
+ , strokeThickness(0) // Same as default in GraphicsContextPrivate.h
+ , lineCap(SkPaint::kDefault_Cap)
+ , lineJoin(SkPaint::kDefault_Join)
+ , mode(SkXfermode::kSrcOver_Mode)
+ , dashRatio(3)
+ , fillColor(SK_ColorBLACK)
+ , fillShader(0)
+ , strokeColor(SK_ColorBLACK)
+ , strokeShader(0)
+ , useAA(true)
+ , strokeStyle(SolidStroke)
+{
+}
+
+PlatformGraphicsContext::State::State(const State& other)
+ : pathEffect(other.pathEffect)
+ , miterLimit(other.miterLimit)
+ , alpha(other.alpha)
+ , strokeThickness(other.strokeThickness)
+ , lineCap(other.lineCap)
+ , lineJoin(other.lineJoin)
+ , mode(other.mode)
+ , dashRatio(other.dashRatio)
+ , shadow(other.shadow)
+ , fillColor(other.fillColor)
+ , fillShader(other.fillShader)
+ , strokeColor(other.strokeColor)
+ , strokeShader(other.strokeShader)
+ , useAA(other.useAA)
+ , strokeStyle(other.strokeStyle)
+{
+ SkSafeRef(pathEffect);
+ SkSafeRef(fillShader);
+ SkSafeRef(strokeShader);
+}
+
+PlatformGraphicsContext::State::~State()
+{
+ SkSafeUnref(pathEffect);
+ SkSafeUnref(fillShader);
+ SkSafeUnref(strokeShader);
+}
+
+void PlatformGraphicsContext::State::setShadow(int radius, int dx, int dy, SkColor c)
+{
+ // Cut the radius in half, to visually match the effect seen in
+ // safari browser
+ shadow.blur = SkScalarHalf(SkIntToScalar(radius));
+ shadow.dx = SkIntToScalar(dx);
+ shadow.dy = SkIntToScalar(dy);
+ shadow.color = c;
+}
+
+bool PlatformGraphicsContext::State::setupShadowPaint(SkPaint* paint, SkPoint* offset,
+ bool shadowsIgnoreTransforms)
+{
+ paint->setAntiAlias(true);
+ paint->setDither(true);
+ paint->setXfermodeMode(mode);
+ paint->setColor(shadow.color);
+ offset->set(shadow.dx, shadow.dy);
+
+ // Currently, only GraphicsContexts associated with the
+ // HTMLCanvasElement have shadows ignore transforms set. This
+ // allows us to distinguish between CSS and Canvas shadows which
+ // have different rendering specifications.
+ uint32_t flags = SkBlurMaskFilter::kHighQuality_BlurFlag;
+ if (shadowsIgnoreTransforms) {
+ offset->fY = -offset->fY;
+ flags |= SkBlurMaskFilter::kIgnoreTransform_BlurFlag;
+ }
+
+ if (shadow.blur > 0) {
+ paint->setMaskFilter(SkBlurMaskFilter::Create(shadow.blur,
+ SkBlurMaskFilter::kNormal_BlurStyle))->unref();
+ }
+ return SkColorGetA(shadow.color) && (shadow.blur || shadow.dx || shadow.dy);
+}
+
+SkColor PlatformGraphicsContext::State::applyAlpha(SkColor c) const
+{
+ int s = RoundToInt(alpha * 256);
+ if (s >= 256)
+ return c;
+ if (s < 0)
+ return 0;
+
+ int a = SkAlphaMul(SkColorGetA(c), s);
+ return (c & 0x00FFFFFF) | (a << 24);
+}
+
+// Returns a new State with all of this object's inherited properties copied.
+PlatformGraphicsContext::State PlatformGraphicsContext::State::cloneInheritedProperties()
+{
+ return PlatformGraphicsContext::State(*this);
+}
+
+//**************************************
+// PlatformGraphicsContext
+//**************************************
+
+PlatformGraphicsContext::PlatformGraphicsContext()
+{
+ m_stateStack.append(State());
+ m_state = &m_stateStack.last();
+}
+
+PlatformGraphicsContext::~PlatformGraphicsContext()
+{
+}
+
+//**************************************
+// State management
+//**************************************
+
+void PlatformGraphicsContext::save()
+{
+ m_stateStack.append(m_state->cloneInheritedProperties());
+ m_state = &m_stateStack.last();
+}
+
+void PlatformGraphicsContext::restore()
+{
+ m_stateStack.removeLast();
+ m_state = &m_stateStack.last();
+}
+
+//**************************************
+// State setters
+//**************************************
+
+void PlatformGraphicsContext::setAlpha(float alpha)
+{
+ m_state->alpha = alpha;
+}
+
+void PlatformGraphicsContext::setCompositeOperation(CompositeOperator op)
+{
+ m_state->mode = WebCoreCompositeToSkiaComposite(op);
+}
+
+void PlatformGraphicsContext::setFillColor(const Color& c)
+{
+ m_state->fillColor = c.rgb();
+ setFillShader(0);
+}
+
+void PlatformGraphicsContext::setFillShader(SkShader* fillShader)
+{
+ if (fillShader)
+ m_state->fillColor = Color::black;
+
+ if (fillShader != m_state->fillShader) {
+ SkSafeUnref(m_state->fillShader);
+ m_state->fillShader = fillShader;
+ SkSafeRef(m_state->fillShader);
+ }
+}
+
+void PlatformGraphicsContext::setLineCap(LineCap cap)
+{
+ switch (cap) {
+ case ButtCap:
+ m_state->lineCap = SkPaint::kButt_Cap;
+ break;
+ case RoundCap:
+ m_state->lineCap = SkPaint::kRound_Cap;
+ break;
+ case SquareCap:
+ m_state->lineCap = SkPaint::kSquare_Cap;
+ break;
+ default:
+ ALOGD("PlatformGraphicsContextSkia::setLineCap: unknown LineCap %d\n", cap);
+ break;
+ }
+}
+
+void PlatformGraphicsContext::setLineDash(const DashArray& dashes, float dashOffset)
+{
+ size_t dashLength = dashes.size();
+ if (!dashLength)
+ return;
+
+ size_t count = !(dashLength % 2) ? dashLength : dashLength * 2;
+ SkScalar* intervals = new SkScalar[count];
+
+ for (unsigned int i = 0; i < count; i++)
+ intervals[i] = SkFloatToScalar(dashes[i % dashLength]);
+ SkPathEffect **effectPtr = &m_state->pathEffect;
+ SkSafeUnref(*effectPtr);
+ *effectPtr = new SkDashPathEffect(intervals, count, SkFloatToScalar(dashOffset));
+
+ delete[] intervals;
+}
+
+void PlatformGraphicsContext::setLineJoin(LineJoin join)
+{
+ switch (join) {
+ case MiterJoin:
+ m_state->lineJoin = SkPaint::kMiter_Join;
+ break;
+ case RoundJoin:
+ m_state->lineJoin = SkPaint::kRound_Join;
+ break;
+ case BevelJoin:
+ m_state->lineJoin = SkPaint::kBevel_Join;
+ break;
+ default:
+ ALOGD("PlatformGraphicsContextSkia::setLineJoin: unknown LineJoin %d\n", join);
+ break;
+ }
+}
+
+void PlatformGraphicsContext::setMiterLimit(float limit)
+{
+ m_state->miterLimit = limit;
+}
+
+void PlatformGraphicsContext::setShadow(int radius, int dx, int dy, SkColor c)
+{
+ m_state->setShadow(radius, dx, dy, c);
+}
+
+void PlatformGraphicsContext::setShouldAntialias(bool useAA)
+{
+ m_state->useAA = useAA;
+}
+
+void PlatformGraphicsContext::setStrokeColor(const Color& c)
+{
+ m_state->strokeColor = c.rgb();
+ setStrokeShader(0);
+}
+
+void PlatformGraphicsContext::setStrokeShader(SkShader* strokeShader)
+{
+ if (strokeShader)
+ m_state->strokeColor = Color::black;
+
+ if (strokeShader != m_state->strokeShader) {
+ SkSafeUnref(m_state->strokeShader);
+ m_state->strokeShader = strokeShader;
+ SkSafeRef(m_state->strokeShader);
+ }
+}
+
+void PlatformGraphicsContext::setStrokeStyle(StrokeStyle style)
+{
+ m_state->strokeStyle = style;
+}
+
+void PlatformGraphicsContext::setStrokeThickness(float f)
+{
+ m_state->strokeThickness = f;
+}
+
+//**************************************
+// Paint setup
+//**************************************
+
+void PlatformGraphicsContext::setupPaintCommon(SkPaint* paint) const
+{
+ paint->setAntiAlias(m_state->useAA);
+ paint->setDither(true);
+ paint->setXfermodeMode(m_state->mode);
+ if (SkColorGetA(m_state->shadow.color) > 0) {
+
+ // Currently, only GraphicsContexts associated with the
+ // HTMLCanvasElement have shadows ignore transforms set. This
+ // allows us to distinguish between CSS and Canvas shadows which
+ // have different rendering specifications.
+ SkScalar dy = m_state->shadow.dy;
+ uint32_t flags = SkBlurDrawLooper::kHighQuality_BlurFlag;
+ if (shadowsIgnoreTransforms()) {
+ dy = -dy;
+ flags |= SkBlurDrawLooper::kIgnoreTransform_BlurFlag;
+ flags |= SkBlurDrawLooper::kOverrideColor_BlurFlag;
+ }
+
+ SkDrawLooper* looper = new SkBlurDrawLooper(m_state->shadow.blur,
+ m_state->shadow.dx,
+ dy,
+ m_state->shadow.color,
+ flags);
+ paint->setLooper(looper)->unref();
+ }
+ paint->setFilterBitmap(true);
+}
+
+void PlatformGraphicsContext::setupPaintFill(SkPaint* paint) const
+{
+ this->setupPaintCommon(paint);
+ paint->setColor(m_state->applyAlpha(m_state->fillColor));
+ paint->setShader(m_state->fillShader);
+}
+
+bool PlatformGraphicsContext::setupPaintShadow(SkPaint* paint, SkPoint* offset) const
+{
+ return m_state->setupShadowPaint(paint, offset, shadowsIgnoreTransforms());
+}
+
+bool PlatformGraphicsContext::setupPaintStroke(SkPaint* paint, SkRect* rect,
+ bool isHLine)
+{
+ this->setupPaintCommon(paint);
+ paint->setColor(m_state->applyAlpha(m_state->strokeColor));
+ paint->setShader(m_state->strokeShader);
+
+ float width = m_state->strokeThickness;
+
+ // This allows dashing and dotting to work properly for hairline strokes
+ // FIXME: Should we only do this for dashed and dotted strokes?
+ if (!width)
+ width = 1;
+
+ paint->setStyle(SkPaint::kStroke_Style);
+ paint->setStrokeWidth(SkFloatToScalar(width));
+ paint->setStrokeCap(m_state->lineCap);
+ paint->setStrokeJoin(m_state->lineJoin);
+ paint->setStrokeMiter(SkFloatToScalar(m_state->miterLimit));
+
+ if (rect && (RoundToInt(width) & 1))
+ rect->inset(-SK_ScalarHalf, -SK_ScalarHalf);
+
+ SkPathEffect* pe = m_state->pathEffect;
+ if (pe) {
+ paint->setPathEffect(pe);
+ return false;
+ }
+ switch (m_state->strokeStyle) {
+ case NoStroke:
+ case SolidStroke:
+ width = 0;
+ break;
+ case DashedStroke:
+ width = m_state->dashRatio * width;
+ break;
+ // No break
+ case DottedStroke:
+ break;
+ }
+
+ if (width > 0) {
+ // Return true if we're basically a dotted dash of squares
+ bool justSqrs = RoundToInt(width) == RoundToInt(paint->getStrokeWidth());
+
+ if (justSqrs || !isHLine || !setBitmapDash(paint, width)) {
+#if 0
+ // this is slow enough that we just skip it for now
+ // see http://b/issue?id=4163023
+ SkScalar intervals[] = { width, width };
+ pe = new SkDashPathEffect(intervals, 2, 0);
+ paint->setPathEffect(pe)->unref();
+#endif
+ }
+ return justSqrs;
+ }
+ return false;
+}
+
+} // WebCore
diff --git a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContext.h b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContext.h
new file mode 100644
index 0000000..601de0f
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContext.h
@@ -0,0 +1,204 @@
+/*
+ * Copyright 2006, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef platform_graphics_context_h
+#define platform_graphics_context_h
+
+#include "IntRect.h"
+#include "GraphicsContext.h"
+#include "RenderSkinAndroid.h"
+#include "SkCanvas.h"
+#include "SkPicture.h"
+#include "SkTDArray.h"
+#include <wtf/Vector.h>
+
+class SkCanvas;
+
+namespace WebCore {
+
+class PlatformGraphicsContext {
+public:
+ PlatformGraphicsContext();
+ virtual ~PlatformGraphicsContext();
+ virtual bool isPaintingDisabled() = 0;
+ virtual SkCanvas* getCanvas() = 0;
+
+ void setGraphicsContext(GraphicsContext* gc) { m_gc = gc; }
+ virtual bool deleteUs() const { return false; }
+
+ typedef enum { PaintingContext, RecordingContext } ContextType;
+ virtual ContextType type() = 0;
+
+ // State management
+ virtual void beginTransparencyLayer(float opacity) = 0;
+ virtual void endTransparencyLayer() = 0;
+ virtual void save();
+ virtual void restore();
+
+ // State values
+ virtual void setAlpha(float alpha);
+ virtual void setCompositeOperation(CompositeOperator op);
+ virtual void setFillColor(const Color& c);
+ virtual void setFillShader(SkShader* fillShader);
+ virtual void setLineCap(LineCap cap);
+ virtual void setLineDash(const DashArray& dashes, float dashOffset);
+ virtual void setLineJoin(LineJoin join);
+ virtual void setMiterLimit(float limit);
+ virtual void setShadow(int radius, int dx, int dy, SkColor c);
+ virtual void setShouldAntialias(bool useAA);
+ virtual void setStrokeColor(const Color& c);
+ virtual void setStrokeShader(SkShader* strokeShader);
+ virtual void setStrokeStyle(StrokeStyle style);
+ virtual void setStrokeThickness(float f);
+
+ // FIXME: These setupPaint* should be private, but
+ // they are used by FontAndroid currently
+ virtual void setupPaintFill(SkPaint* paint) const;
+ virtual bool setupPaintShadow(SkPaint* paint, SkPoint* offset) const;
+ // Sets up the paint for stroking. Returns true if the style is really
+ // just a dash of squares (the size of the paint's stroke-width.
+ virtual bool setupPaintStroke(SkPaint* paint, SkRect* rect, bool isHLine = false);
+
+ // Matrix operations
+ virtual void concatCTM(const AffineTransform& affine) = 0;
+ virtual void rotate(float angleInRadians) = 0;
+ virtual void scale(const FloatSize& size) = 0;
+ virtual void translate(float x, float y) = 0;
+ virtual const SkMatrix& getTotalMatrix() = 0;
+
+ // Clipping
+ virtual void addInnerRoundedRectClip(const IntRect& rect, int thickness) = 0;
+ virtual void canvasClip(const Path& path) = 0;
+ virtual void clip(const FloatRect& rect) = 0;
+ virtual void clip(const Path& path) = 0;
+ virtual void clipConvexPolygon(size_t numPoints, const FloatPoint*, bool antialias) = 0;
+ virtual void clipOut(const IntRect& r) = 0;
+ virtual void clipOut(const Path& p) = 0;
+ virtual void clipPath(const Path& pathToClip, WindRule clipRule) = 0;
+
+ // Drawing
+ virtual void clearRect(const FloatRect& rect) = 0;
+ virtual void drawBitmapPattern(const SkBitmap& bitmap, const SkMatrix& matrix,
+ CompositeOperator compositeOp, const FloatRect& destRect) = 0;
+ virtual void drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src,
+ const SkRect& dst, CompositeOperator op) = 0;
+ virtual void drawConvexPolygon(size_t numPoints, const FloatPoint* points,
+ bool shouldAntialias) = 0;
+ virtual void drawEllipse(const IntRect& rect) = 0;
+ virtual void drawFocusRing(const Vector<IntRect>& rects, int /* width */,
+ int /* offset */, const Color& color) = 0;
+ virtual void drawHighlightForText(const Font& font, const TextRun& run,
+ const FloatPoint& point, int h,
+ const Color& backgroundColor, ColorSpace colorSpace,
+ int from, int to, bool isActive) = 0;
+ virtual void drawLine(const IntPoint& point1, const IntPoint& point2) = 0;
+ virtual void drawLineForText(const FloatPoint& pt, float width) = 0;
+ virtual void drawLineForTextChecking(const FloatPoint& pt, float width,
+ GraphicsContext::TextCheckingLineStyle) = 0;
+ virtual void drawRect(const IntRect& rect) = 0;
+ virtual void fillPath(const Path& pathToFill, WindRule fillRule) = 0;
+ virtual void fillRect(const FloatRect& rect) = 0;
+ void fillRect(const FloatRect& rect, const Color& color, ColorSpace) {
+ fillRect(rect, color);
+ }
+ virtual void fillRect(const FloatRect& rect, const Color& color) = 0;
+ void fillRoundedRect(const IntRect& rect, const IntSize& topLeft,
+ const IntSize& topRight, const IntSize& bottomLeft,
+ const IntSize& bottomRight, const Color& color,
+ ColorSpace) {
+ fillRoundedRect(rect, topLeft, topRight, bottomLeft, bottomRight, color);
+ }
+ virtual void fillRoundedRect(const IntRect& rect, const IntSize& topLeft,
+ const IntSize& topRight, const IntSize& bottomLeft,
+ const IntSize& bottomRight, const Color& color) = 0;
+ virtual void strokeArc(const IntRect& r, int startAngle, int angleSpan) = 0;
+ virtual void strokePath(const Path& pathToStroke) = 0;
+ virtual void strokeRect(const FloatRect& rect, float lineWidth) = 0;
+
+ virtual SkCanvas* recordingCanvas() = 0;
+ virtual void endRecording(int type = 0) = 0;
+
+protected:
+
+ struct ShadowRec {
+ SkScalar blur;
+ SkScalar dx;
+ SkScalar dy;
+ SkColor color; // alpha>0 means valid shadow
+ ShadowRec(SkScalar b = 0,
+ SkScalar x = 0,
+ SkScalar y = 0,
+ SkColor c = 0) // by default, alpha=0, so no shadow
+ : blur(b), dx(x), dy(y), color(c)
+ {};
+ };
+
+ class State {
+ public:
+ SkPathEffect* pathEffect;
+ float miterLimit;
+ float alpha;
+ float strokeThickness;
+ SkPaint::Cap lineCap;
+ SkPaint::Join lineJoin;
+ SkXfermode::Mode mode;
+ int dashRatio; // Ratio of the length of a dash to its width
+ ShadowRec shadow;
+ SkColor fillColor;
+ SkShader* fillShader;
+ SkColor strokeColor;
+ SkShader* strokeShader;
+ bool useAA;
+ StrokeStyle strokeStyle;
+
+ State();
+ State(const State& other);
+ ~State();
+
+ void setShadow(int radius, int dx, int dy, SkColor c);
+ bool setupShadowPaint(SkPaint* paint, SkPoint* offset,
+ bool shadowsIgnoreTransforms);
+ SkColor applyAlpha(SkColor c) const;
+
+ State cloneInheritedProperties();
+ private:
+ // Not supported.
+ void operator=(const State&);
+
+ friend class PlatformGraphicsContextRecording;
+ friend class PlatformGraphicsContextSkia;
+ };
+
+ virtual bool shadowsIgnoreTransforms() const = 0;
+ void setupPaintCommon(SkPaint* paint) const;
+ GraphicsContext* m_gc; // Back-ptr to our parent
+
+ struct State;
+ WTF::Vector<State> m_stateStack;
+ State* m_state;
+};
+
+}
+#endif
diff --git a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.cpp b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.cpp
new file mode 100644
index 0000000..d96124d
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.cpp
@@ -0,0 +1,373 @@
+#define LOG_TAG "PlatformGraphicsContextRecording"
+#define LOG_NDEBUG 1
+
+#include "config.h"
+#include "PlatformGraphicsContextRecording.h"
+
+#include "AndroidLog.h"
+#include "Font.h"
+#include "GraphicsContext.h"
+#include "GraphicsOperationCollection.h"
+#include "GraphicsOperation.h"
+
+namespace WebCore {
+
+//**************************************
+// PlatformGraphicsContextRecording
+//**************************************
+
+PlatformGraphicsContextRecording::PlatformGraphicsContextRecording(GraphicsOperationCollection* picture)
+ : PlatformGraphicsContext()
+ , mGraphicsOperationCollection(picture)
+ , mPicture(0)
+{
+}
+
+bool PlatformGraphicsContextRecording::isPaintingDisabled()
+{
+ return !mGraphicsOperationCollection;
+}
+
+SkCanvas* PlatformGraphicsContextRecording::recordingCanvas()
+{
+ SkSafeUnref(mPicture);
+ mPicture = new SkPicture();
+ return mPicture->beginRecording(0, 0, 0);
+}
+
+void PlatformGraphicsContextRecording::endRecording(int type)
+{
+ if (!mPicture)
+ return;
+ mPicture->endRecording();
+ GraphicsOperation::DrawComplexText* text = new GraphicsOperation::DrawComplexText(mPicture);
+ mGraphicsOperationCollection->append(text);
+ mPicture = 0;
+}
+
+
+//**************************************
+// State management
+//**************************************
+
+void PlatformGraphicsContextRecording::beginTransparencyLayer(float opacity)
+{
+ mGraphicsOperationCollection->append(new GraphicsOperation::BeginTransparencyLayer(opacity));
+}
+
+void PlatformGraphicsContextRecording::endTransparencyLayer()
+{
+ mGraphicsOperationCollection->append(new GraphicsOperation::EndTransparencyLayer());
+}
+
+void PlatformGraphicsContextRecording::save()
+{
+ PlatformGraphicsContext::save();
+ mGraphicsOperationCollection->append(new GraphicsOperation::Save());
+}
+
+void PlatformGraphicsContextRecording::restore()
+{
+ PlatformGraphicsContext::restore();
+ mGraphicsOperationCollection->append(new GraphicsOperation::Restore());
+}
+
+//**************************************
+// State setters
+//**************************************
+
+void PlatformGraphicsContextRecording::setAlpha(float alpha)
+{
+ PlatformGraphicsContext::setAlpha(alpha);
+ mGraphicsOperationCollection->append(new GraphicsOperation::SetAlpha(alpha));
+}
+
+void PlatformGraphicsContextRecording::setCompositeOperation(CompositeOperator op)
+{
+ PlatformGraphicsContext::setCompositeOperation(op);
+ mGraphicsOperationCollection->append(new GraphicsOperation::SetCompositeOperation(op));
+}
+
+void PlatformGraphicsContextRecording::setFillColor(const Color& c)
+{
+ PlatformGraphicsContext::setFillColor(c);
+ mGraphicsOperationCollection->append(new GraphicsOperation::SetFillColor(c));
+}
+
+void PlatformGraphicsContextRecording::setFillShader(SkShader* fillShader)
+{
+ PlatformGraphicsContext::setFillShader(fillShader);
+ mGraphicsOperationCollection->append(new GraphicsOperation::SetFillShader(fillShader));
+}
+
+void PlatformGraphicsContextRecording::setLineCap(LineCap cap)
+{
+ PlatformGraphicsContext::setLineCap(cap);
+ mGraphicsOperationCollection->append(new GraphicsOperation::SetLineCap(cap));
+}
+
+void PlatformGraphicsContextRecording::setLineDash(const DashArray& dashes, float dashOffset)
+{
+ PlatformGraphicsContext::setLineDash(dashes, dashOffset);
+ mGraphicsOperationCollection->append(new GraphicsOperation::SetLineDash(dashes, dashOffset));
+}
+
+void PlatformGraphicsContextRecording::setLineJoin(LineJoin join)
+{
+ PlatformGraphicsContext::setLineJoin(join);
+ mGraphicsOperationCollection->append(new GraphicsOperation::SetLineJoin(join));
+}
+
+void PlatformGraphicsContextRecording::setMiterLimit(float limit)
+{
+ PlatformGraphicsContext::setMiterLimit(limit);
+ mGraphicsOperationCollection->append(new GraphicsOperation::SetMiterLimit(limit));
+}
+
+void PlatformGraphicsContextRecording::setShadow(int radius, int dx, int dy, SkColor c)
+{
+ PlatformGraphicsContext::setShadow(radius, dx, dy, c);
+ mGraphicsOperationCollection->append(new GraphicsOperation::SetShadow(radius, dx, dy, c));
+}
+
+void PlatformGraphicsContextRecording::setShouldAntialias(bool useAA)
+{
+ m_state->useAA = useAA;
+ PlatformGraphicsContext::setShouldAntialias(useAA);
+ mGraphicsOperationCollection->append(new GraphicsOperation::SetShouldAntialias(useAA));
+}
+
+void PlatformGraphicsContextRecording::setStrokeColor(const Color& c)
+{
+ PlatformGraphicsContext::setStrokeColor(c);
+ mGraphicsOperationCollection->append(new GraphicsOperation::SetStrokeColor(c));
+}
+
+void PlatformGraphicsContextRecording::setStrokeShader(SkShader* strokeShader)
+{
+ PlatformGraphicsContext::setStrokeShader(strokeShader);
+ mGraphicsOperationCollection->append(new GraphicsOperation::SetStrokeShader(strokeShader));
+}
+
+void PlatformGraphicsContextRecording::setStrokeStyle(StrokeStyle style)
+{
+ PlatformGraphicsContext::setStrokeStyle(style);
+ mGraphicsOperationCollection->append(new GraphicsOperation::SetStrokeStyle(style));
+}
+
+void PlatformGraphicsContextRecording::setStrokeThickness(float f)
+{
+ PlatformGraphicsContext::setStrokeThickness(f);
+ mGraphicsOperationCollection->append(new GraphicsOperation::SetStrokeThickness(f));
+}
+
+//**************************************
+// Matrix operations
+//**************************************
+
+void PlatformGraphicsContextRecording::concatCTM(const AffineTransform& affine)
+{
+ mCurrentMatrix.preConcat(affine);
+ mGraphicsOperationCollection->append(new GraphicsOperation::ConcatCTM(affine));
+}
+
+void PlatformGraphicsContextRecording::rotate(float angleInRadians)
+{
+ float value = angleInRadians * (180.0f / 3.14159265f);
+ mCurrentMatrix.preRotate(SkFloatToScalar(value));
+ mGraphicsOperationCollection->append(new GraphicsOperation::Rotate(angleInRadians));
+}
+
+void PlatformGraphicsContextRecording::scale(const FloatSize& size)
+{
+ mCurrentMatrix.preScale(SkFloatToScalar(size.width()), SkFloatToScalar(size.height()));
+ mGraphicsOperationCollection->append(new GraphicsOperation::Scale(size));
+}
+
+void PlatformGraphicsContextRecording::translate(float x, float y)
+{
+ mCurrentMatrix.preTranslate(SkFloatToScalar(x), SkFloatToScalar(y));
+ mGraphicsOperationCollection->append(new GraphicsOperation::Translate(x, y));
+}
+
+const SkMatrix& PlatformGraphicsContextRecording::getTotalMatrix()
+{
+ return mCurrentMatrix;
+}
+
+//**************************************
+// Clipping
+//**************************************
+
+void PlatformGraphicsContextRecording::addInnerRoundedRectClip(const IntRect& rect,
+ int thickness)
+{
+ mGraphicsOperationCollection->append(new GraphicsOperation::InnerRoundedRectClip(rect, thickness));
+}
+
+void PlatformGraphicsContextRecording::canvasClip(const Path& path)
+{
+ clip(path);
+}
+
+void PlatformGraphicsContextRecording::clip(const FloatRect& rect)
+{
+ mGraphicsOperationCollection->append(new GraphicsOperation::Clip(rect));
+}
+
+void PlatformGraphicsContextRecording::clip(const Path& path)
+{
+ mGraphicsOperationCollection->append(new GraphicsOperation::ClipPath(path));
+}
+
+void PlatformGraphicsContextRecording::clipConvexPolygon(size_t numPoints,
+ const FloatPoint*, bool antialias)
+{
+ // TODO
+}
+
+void PlatformGraphicsContextRecording::clipOut(const IntRect& r)
+{
+ mGraphicsOperationCollection->append(new GraphicsOperation::ClipOut(r));
+}
+
+void PlatformGraphicsContextRecording::clipOut(const Path& path)
+{
+ mGraphicsOperationCollection->append(new GraphicsOperation::ClipPath(path, true));
+}
+
+void PlatformGraphicsContextRecording::clipPath(const Path& pathToClip, WindRule clipRule)
+{
+ GraphicsOperation::ClipPath* operation = new GraphicsOperation::ClipPath(pathToClip);
+ operation->setWindRule(clipRule);
+ mGraphicsOperationCollection->append(operation);
+}
+
+void PlatformGraphicsContextRecording::clearRect(const FloatRect& rect)
+{
+ mGraphicsOperationCollection->append(new GraphicsOperation::ClearRect(rect));
+}
+
+//**************************************
+// Drawing
+//**************************************
+
+void PlatformGraphicsContextRecording::drawBitmapPattern(
+ const SkBitmap& bitmap, const SkMatrix& matrix,
+ CompositeOperator compositeOp, const FloatRect& destRect)
+{
+ mGraphicsOperationCollection->append(new GraphicsOperation::DrawBitmapPattern(bitmap, matrix, compositeOp, destRect));
+}
+
+void PlatformGraphicsContextRecording::drawBitmapRect(const SkBitmap& bitmap,
+ const SkIRect* src, const SkRect& dst,
+ CompositeOperator op)
+{
+ mGraphicsOperationCollection->append(new GraphicsOperation::DrawBitmapRect(bitmap, *src, dst, op));
+}
+
+void PlatformGraphicsContextRecording::drawConvexPolygon(size_t numPoints,
+ const FloatPoint* points,
+ bool shouldAntialias)
+{
+ // TODO
+}
+
+void PlatformGraphicsContextRecording::drawEllipse(const IntRect& rect)
+{
+ mGraphicsOperationCollection->append(new GraphicsOperation::DrawEllipse(rect));
+}
+
+void PlatformGraphicsContextRecording::drawFocusRing(const Vector<IntRect>& rects,
+ int /* width */, int /* offset */,
+ const Color& color)
+{
+ // TODO
+}
+
+void PlatformGraphicsContextRecording::drawHighlightForText(
+ const Font& font, const TextRun& run, const FloatPoint& point, int h,
+ const Color& backgroundColor, ColorSpace colorSpace, int from,
+ int to, bool isActive)
+{
+ IntRect rect = (IntRect)font.selectionRectForText(run, point, h, from, to);
+ if (isActive)
+ fillRect(rect, backgroundColor);
+ else {
+ int x = rect.x(), y = rect.y(), w = rect.width(), h = rect.height();
+ const int t = 3, t2 = t * 2;
+
+ fillRect(IntRect(x, y, w, t), backgroundColor);
+ fillRect(IntRect(x, y+h-t, w, t), backgroundColor);
+ fillRect(IntRect(x, y+t, t, h-t2), backgroundColor);
+ fillRect(IntRect(x+w-t, y+t, t, h-t2), backgroundColor);
+ }
+}
+
+void PlatformGraphicsContextRecording::drawLine(const IntPoint& point1,
+ const IntPoint& point2)
+{
+ mGraphicsOperationCollection->append(new GraphicsOperation::DrawLine(point1, point2));
+}
+
+void PlatformGraphicsContextRecording::drawLineForText(const FloatPoint& pt, float width)
+{
+ mGraphicsOperationCollection->append(new GraphicsOperation::DrawLineForText(pt, width));
+}
+
+void PlatformGraphicsContextRecording::drawLineForTextChecking(const FloatPoint& pt,
+ float width, GraphicsContext::TextCheckingLineStyle lineStyle)
+{
+ mGraphicsOperationCollection->append(new GraphicsOperation::DrawLineForTextChecking(pt, width, lineStyle));
+}
+
+void PlatformGraphicsContextRecording::drawRect(const IntRect& rect)
+{
+ mGraphicsOperationCollection->append(new GraphicsOperation::DrawRect(rect));
+}
+
+void PlatformGraphicsContextRecording::fillPath(const Path& pathToFill, WindRule fillRule)
+{
+ mGraphicsOperationCollection->append(new GraphicsOperation::FillPath(pathToFill, fillRule));
+}
+
+void PlatformGraphicsContextRecording::fillRect(const FloatRect& rect)
+{
+ mGraphicsOperationCollection->append(new GraphicsOperation::FillRect(rect));
+}
+
+void PlatformGraphicsContextRecording::fillRect(const FloatRect& rect,
+ const Color& color)
+{
+ GraphicsOperation::FillRect* operation = new GraphicsOperation::FillRect(rect);
+ operation->setColor(color);
+ mGraphicsOperationCollection->append(operation);
+}
+
+void PlatformGraphicsContextRecording::fillRoundedRect(
+ const IntRect& rect, const IntSize& topLeft, const IntSize& topRight,
+ const IntSize& bottomLeft, const IntSize& bottomRight,
+ const Color& color)
+{
+ mGraphicsOperationCollection->append(new GraphicsOperation::FillRoundedRect(rect, topLeft,
+ topRight, bottomLeft, bottomRight, color));
+}
+
+void PlatformGraphicsContextRecording::strokeArc(const IntRect& r, int startAngle,
+ int angleSpan)
+{
+ mGraphicsOperationCollection->append(new GraphicsOperation::StrokeArc(r, startAngle, angleSpan));
+}
+
+void PlatformGraphicsContextRecording::strokePath(const Path& pathToStroke)
+{
+ mGraphicsOperationCollection->append(new GraphicsOperation::StrokePath(pathToStroke));
+}
+
+void PlatformGraphicsContextRecording::strokeRect(const FloatRect& rect, float lineWidth)
+{
+ mGraphicsOperationCollection->append(new GraphicsOperation::StrokeRect(rect, lineWidth));
+}
+
+
+} // WebCore
diff --git a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.h b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.h
new file mode 100644
index 0000000..ebb0075
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.h
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef platform_graphics_context_recording_h
+#define platform_graphics_context_recording_h
+
+#include "PlatformGraphicsContext.h"
+
+namespace WebCore {
+class GraphicsOperationCollection;
+
+class PlatformGraphicsContextRecording : public PlatformGraphicsContext {
+public:
+ PlatformGraphicsContextRecording(GraphicsOperationCollection* picture);
+ virtual ~PlatformGraphicsContextRecording() {}
+ virtual bool isPaintingDisabled();
+ virtual SkCanvas* getCanvas() { return 0; }
+
+ GraphicsOperationCollection* mGraphicsOperationCollection;
+ SkMatrix mCurrentMatrix;
+
+ virtual SkCanvas* recordingCanvas();
+ virtual void endRecording(int type = 0);
+
+ virtual ContextType type() { return RecordingContext; }
+
+ // State management
+ virtual void beginTransparencyLayer(float opacity);
+ virtual void endTransparencyLayer();
+ virtual void save();
+ virtual void restore();
+
+ // State values
+ virtual void setAlpha(float alpha);
+ virtual void setCompositeOperation(CompositeOperator op);
+ virtual void setFillColor(const Color& c);
+ virtual void setFillShader(SkShader* fillShader);
+ virtual void setLineCap(LineCap cap);
+ virtual void setLineDash(const DashArray& dashes, float dashOffset);
+ virtual void setLineJoin(LineJoin join);
+ virtual void setMiterLimit(float limit);
+ virtual void setShadow(int radius, int dx, int dy, SkColor c);
+ virtual void setShouldAntialias(bool useAA);
+ virtual void setStrokeColor(const Color& c);
+ virtual void setStrokeShader(SkShader* strokeShader);
+ virtual void setStrokeStyle(StrokeStyle style);
+ virtual void setStrokeThickness(float f);
+
+ // Matrix operations
+ virtual void concatCTM(const AffineTransform& affine);
+ virtual void rotate(float angleInRadians);
+ virtual void scale(const FloatSize& size);
+ virtual void translate(float x, float y);
+ virtual const SkMatrix& getTotalMatrix();
+
+ // Clipping
+ virtual void addInnerRoundedRectClip(const IntRect& rect, int thickness);
+ virtual void canvasClip(const Path& path);
+ virtual void clip(const FloatRect& rect);
+ virtual void clip(const Path& path);
+ virtual void clipConvexPolygon(size_t numPoints, const FloatPoint*, bool antialias);
+ virtual void clipOut(const IntRect& r);
+ virtual void clipOut(const Path& p);
+ virtual void clipPath(const Path& pathToClip, WindRule clipRule);
+
+ // Drawing
+ virtual void clearRect(const FloatRect& rect);
+ virtual void drawBitmapPattern(const SkBitmap& bitmap, const SkMatrix& matrix,
+ CompositeOperator compositeOp, const FloatRect& destRect);
+ virtual void drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src,
+ const SkRect& dst, CompositeOperator op);
+ virtual void drawConvexPolygon(size_t numPoints, const FloatPoint* points,
+ bool shouldAntialias);
+ virtual void drawEllipse(const IntRect& rect);
+ virtual void drawFocusRing(const Vector<IntRect>& rects, int /* width */,
+ int /* offset */, const Color& color);
+ virtual void drawHighlightForText(const Font& font, const TextRun& run,
+ const FloatPoint& point, int h,
+ const Color& backgroundColor, ColorSpace colorSpace,
+ int from, int to, bool isActive);
+ virtual void drawLine(const IntPoint& point1, const IntPoint& point2);
+ virtual void drawLineForText(const FloatPoint& pt, float width);
+ virtual void drawLineForTextChecking(const FloatPoint& pt, float width,
+ GraphicsContext::TextCheckingLineStyle);
+ virtual void drawRect(const IntRect& rect);
+ virtual void fillPath(const Path& pathToFill, WindRule fillRule);
+ virtual void fillRect(const FloatRect& rect);
+ virtual void fillRect(const FloatRect& rect, const Color& color);
+ virtual void fillRoundedRect(const IntRect& rect, const IntSize& topLeft,
+ const IntSize& topRight, const IntSize& bottomLeft,
+ const IntSize& bottomRight, const Color& color);
+ virtual void strokeArc(const IntRect& r, int startAngle, int angleSpan);
+ virtual void strokePath(const Path& pathToStroke);
+ virtual void strokeRect(const FloatRect& rect, float lineWidth);
+
+private:
+
+ virtual bool shadowsIgnoreTransforms() const {
+ return false;
+ }
+
+ SkPicture* mPicture;
+};
+
+}
+#endif
diff --git a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextSkia.cpp b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextSkia.cpp
new file mode 100644
index 0000000..9b32726
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextSkia.cpp
@@ -0,0 +1,606 @@
+#define LOG_TAG "PlatformGraphicsContextSkia"
+#define LOG_NDEBUG 1
+
+#include "config.h"
+#include "PlatformGraphicsContextSkia.h"
+
+#include "AndroidLog.h"
+#include "Font.h"
+#include "GraphicsContext.h"
+#include "SkCanvas.h"
+#include "SkCornerPathEffect.h"
+#include "SkPaint.h"
+#include "SkShader.h"
+#include "SkiaUtils.h"
+
+namespace WebCore {
+
+// These are the flags we need when we call saveLayer for transparency.
+// Since it does not appear that webkit intends this to also save/restore
+// the matrix or clip, I do not give those flags (for performance)
+#define TRANSPARENCY_SAVEFLAGS \
+ (SkCanvas::SaveFlags)(SkCanvas::kHasAlphaLayer_SaveFlag | \
+ SkCanvas::kFullColorLayer_SaveFlag)
+
+//**************************************
+// Helper functions
+//**************************************
+
+static void setrectForUnderline(SkRect* r, float lineThickness,
+ const FloatPoint& point, int yOffset, float width)
+{
+#if 0
+ if (lineThickness < 1) // Do we really need/want this?
+ lineThickness = 1;
+#endif
+ r->fLeft = point.x();
+ r->fTop = point.y() + yOffset;
+ r->fRight = r->fLeft + width;
+ r->fBottom = r->fTop + lineThickness;
+}
+
+static inline int fastMod(int value, int max)
+{
+ int sign = SkExtractSign(value);
+
+ value = SkApplySign(value, sign);
+ if (value >= max)
+ value %= max;
+ return SkApplySign(value, sign);
+}
+
+static inline void fixPaintForBitmapsThatMaySeam(SkPaint* paint) {
+ /* Bitmaps may be drawn to seem next to other images. If we are drawn
+ zoomed, or at fractional coordinates, we may see cracks/edges if
+ we antialias, because that will cause us to draw the same pixels
+ more than once (e.g. from the left and right bitmaps that share
+ an edge).
+
+ Disabling antialiasing fixes this, and since so far we are never
+ rotated at non-multiple-of-90 angles, this seems to do no harm
+ */
+ paint->setAntiAlias(false);
+}
+
+//**************************************
+// PlatformGraphicsContextSkia
+//**************************************
+
+PlatformGraphicsContextSkia::PlatformGraphicsContextSkia(SkCanvas* canvas,
+ bool takeCanvasOwnership)
+ : PlatformGraphicsContext()
+ , mCanvas(canvas)
+ , m_deleteCanvas(takeCanvasOwnership)
+{
+ m_gc = 0;
+}
+
+PlatformGraphicsContextSkia::~PlatformGraphicsContextSkia()
+{
+ if (m_deleteCanvas)
+ delete mCanvas;
+}
+
+bool PlatformGraphicsContextSkia::isPaintingDisabled()
+{
+ return !mCanvas;
+}
+
+//**************************************
+// State management
+//**************************************
+
+void PlatformGraphicsContextSkia::beginTransparencyLayer(float opacity)
+{
+ SkCanvas* canvas = mCanvas;
+ canvas->saveLayerAlpha(0, (int)(opacity * 255), TRANSPARENCY_SAVEFLAGS);
+}
+
+void PlatformGraphicsContextSkia::endTransparencyLayer()
+{
+ if (!mCanvas)
+ return;
+ mCanvas->restore();
+}
+
+void PlatformGraphicsContextSkia::save()
+{
+ PlatformGraphicsContext::save();
+ // Save our native canvas.
+ mCanvas->save();
+}
+
+void PlatformGraphicsContextSkia::restore()
+{
+ PlatformGraphicsContext::restore();
+ // Restore our native canvas.
+ mCanvas->restore();
+}
+
+//**************************************
+// Matrix operations
+//**************************************
+
+void PlatformGraphicsContextSkia::concatCTM(const AffineTransform& affine)
+{
+ mCanvas->concat(affine);
+}
+
+void PlatformGraphicsContextSkia::rotate(float angleInRadians)
+{
+ float value = angleInRadians * (180.0f / 3.14159265f);
+ mCanvas->rotate(SkFloatToScalar(value));
+}
+
+void PlatformGraphicsContextSkia::scale(const FloatSize& size)
+{
+ mCanvas->scale(SkFloatToScalar(size.width()), SkFloatToScalar(size.height()));
+}
+
+void PlatformGraphicsContextSkia::translate(float x, float y)
+{
+ mCanvas->translate(SkFloatToScalar(x), SkFloatToScalar(y));
+}
+
+const SkMatrix& PlatformGraphicsContextSkia::getTotalMatrix()
+{
+ return mCanvas->getTotalMatrix();
+}
+
+//**************************************
+// Clipping
+//**************************************
+
+void PlatformGraphicsContextSkia::addInnerRoundedRectClip(const IntRect& rect,
+ int thickness)
+{
+ SkPath path;
+ SkRect r(rect);
+
+ path.addOval(r, SkPath::kCW_Direction);
+ // Only perform the inset if we won't invert r
+ if (2 * thickness < rect.width() && 2 * thickness < rect.height()) {
+ // Adding one to the thickness doesn't make the border too thick as
+ // it's painted over afterwards. But without this adjustment the
+ // border appears a little anemic after anti-aliasing.
+ r.inset(SkIntToScalar(thickness + 1), SkIntToScalar(thickness + 1));
+ path.addOval(r, SkPath::kCCW_Direction);
+ }
+ mCanvas->clipPath(path, SkRegion::kIntersect_Op, true);
+}
+
+void PlatformGraphicsContextSkia::canvasClip(const Path& path)
+{
+ clip(path);
+}
+
+void PlatformGraphicsContextSkia::clip(const FloatRect& rect)
+{
+ mCanvas->clipRect(rect);
+}
+
+void PlatformGraphicsContextSkia::clip(const Path& path)
+{
+ mCanvas->clipPath(*path.platformPath(), SkRegion::kIntersect_Op, true);
+}
+
+void PlatformGraphicsContextSkia::clipConvexPolygon(size_t numPoints,
+ const FloatPoint*, bool antialias)
+{
+ if (numPoints <= 1)
+ return;
+
+ // This is only used if HAVE_PATH_BASED_BORDER_RADIUS_DRAWING is defined
+ // in RenderObject.h which it isn't for us. TODO: Support that :)
+}
+
+void PlatformGraphicsContextSkia::clipOut(const IntRect& r)
+{
+ mCanvas->clipRect(r, SkRegion::kDifference_Op);
+}
+
+void PlatformGraphicsContextSkia::clipOut(const Path& path)
+{
+ mCanvas->clipPath(*path.platformPath(), SkRegion::kDifference_Op);
+}
+
+void PlatformGraphicsContextSkia::clipPath(const Path& pathToClip, WindRule clipRule)
+{
+ SkPath path = *pathToClip.platformPath();
+ path.setFillType(clipRule == RULE_EVENODD
+ ? SkPath::kEvenOdd_FillType : SkPath::kWinding_FillType);
+ mCanvas->clipPath(path);
+}
+void PlatformGraphicsContextSkia::clearRect(const FloatRect& rect)
+{
+ SkPaint paint;
+
+ setupPaintFill(&paint);
+ paint.setXfermodeMode(SkXfermode::kClear_Mode);
+
+ mCanvas->drawRect(rect, paint);
+}
+
+//**************************************
+// Drawing
+//**************************************
+
+void PlatformGraphicsContextSkia::drawBitmapPattern(
+ const SkBitmap& bitmap, const SkMatrix& matrix,
+ CompositeOperator compositeOp, const FloatRect& destRect)
+{
+ SkShader* shader = SkShader::CreateBitmapShader(bitmap,
+ SkShader::kRepeat_TileMode,
+ SkShader::kRepeat_TileMode);
+ shader->setLocalMatrix(matrix);
+ SkPaint paint;
+ setupPaintFill(&paint);
+ paint.setShader(shader);
+ paint.setXfermodeMode(WebCoreCompositeToSkiaComposite(compositeOp));
+ fixPaintForBitmapsThatMaySeam(&paint);
+ mCanvas->drawRect(destRect, paint);
+}
+
+void PlatformGraphicsContextSkia::drawBitmapRect(const SkBitmap& bitmap,
+ const SkIRect* src, const SkRect& dst,
+ CompositeOperator op)
+{
+ SkPaint paint;
+ setupPaintFill(&paint);
+ paint.setXfermodeMode(WebCoreCompositeToSkiaComposite(op));
+ fixPaintForBitmapsThatMaySeam(&paint);
+
+ mCanvas->drawBitmapRect(bitmap, src, dst, &paint);
+}
+
+void PlatformGraphicsContextSkia::drawConvexPolygon(size_t numPoints,
+ const FloatPoint* points,
+ bool shouldAntialias)
+{
+ if (numPoints <= 1)
+ return;
+
+ SkPaint paint;
+ SkPath path;
+
+ path.incReserve(numPoints);
+ path.moveTo(SkFloatToScalar(points[0].x()), SkFloatToScalar(points[0].y()));
+ for (size_t i = 1; i < numPoints; i++)
+ path.lineTo(SkFloatToScalar(points[i].x()), SkFloatToScalar(points[i].y()));
+
+ if (mCanvas->quickReject(path, shouldAntialias ?
+ SkCanvas::kAA_EdgeType : SkCanvas::kBW_EdgeType)) {
+ return;
+ }
+
+ if (m_state->fillColor & 0xFF000000) {
+ setupPaintFill(&paint);
+ paint.setAntiAlias(shouldAntialias);
+ mCanvas->drawPath(path, paint);
+ }
+
+ if (m_state->strokeStyle != NoStroke) {
+ paint.reset();
+ setupPaintStroke(&paint, 0);
+ paint.setAntiAlias(shouldAntialias);
+ mCanvas->drawPath(path, paint);
+ }
+}
+
+void PlatformGraphicsContextSkia::drawEllipse(const IntRect& rect)
+{
+ SkPaint paint;
+ SkRect oval(rect);
+
+ if (m_state->fillColor & 0xFF000000) {
+ setupPaintFill(&paint);
+ mCanvas->drawOval(oval, paint);
+ }
+ if (m_state->strokeStyle != NoStroke) {
+ paint.reset();
+ setupPaintStroke(&paint, &oval);
+ mCanvas->drawOval(oval, paint);
+ }
+}
+
+void PlatformGraphicsContextSkia::drawFocusRing(const Vector<IntRect>& rects,
+ int /* width */, int /* offset */,
+ const Color& color)
+{
+ unsigned rectCount = rects.size();
+ if (!rectCount)
+ return;
+
+ SkRegion focusRingRegion;
+ const SkScalar focusRingOutset = WebCoreFloatToSkScalar(0.8);
+ for (unsigned i = 0; i < rectCount; i++) {
+ SkIRect r = rects[i];
+ r.inset(-focusRingOutset, -focusRingOutset);
+ focusRingRegion.op(r, SkRegion::kUnion_Op);
+ }
+
+ SkPath path;
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setStyle(SkPaint::kStroke_Style);
+
+ paint.setColor(color.rgb());
+ paint.setStrokeWidth(focusRingOutset * 2);
+ paint.setPathEffect(new SkCornerPathEffect(focusRingOutset * 2))->unref();
+ focusRingRegion.getBoundaryPath(&path);
+ mCanvas->drawPath(path, paint);
+}
+
+void PlatformGraphicsContextSkia::drawHighlightForText(
+ const Font& font, const TextRun& run, const FloatPoint& point, int h,
+ const Color& backgroundColor, ColorSpace colorSpace, int from,
+ int to, bool isActive)
+{
+ IntRect rect = (IntRect)font.selectionRectForText(run, point, h, from, to);
+ if (isActive)
+ fillRect(rect, backgroundColor);
+ else {
+ int x = rect.x(), y = rect.y(), w = rect.width(), h = rect.height();
+ const int t = 3, t2 = t * 2;
+
+ fillRect(IntRect(x, y, w, t), backgroundColor);
+ fillRect(IntRect(x, y+h-t, w, t), backgroundColor);
+ fillRect(IntRect(x, y+t, t, h-t2), backgroundColor);
+ fillRect(IntRect(x+w-t, y+t, t, h-t2), backgroundColor);
+ }
+}
+
+void PlatformGraphicsContextSkia::drawLine(const IntPoint& point1,
+ const IntPoint& point2)
+{
+ StrokeStyle style = m_state->strokeStyle;
+ if (style == NoStroke)
+ return;
+
+ SkPaint paint;
+ SkCanvas* canvas = mCanvas;
+ const int idx = SkAbs32(point2.x() - point1.x());
+ const int idy = SkAbs32(point2.y() - point1.y());
+
+ // Special-case horizontal and vertical lines that are really just dots
+ if (setupPaintStroke(&paint, 0, !idy) && (!idx || !idy)) {
+ const SkScalar diameter = paint.getStrokeWidth();
+ const SkScalar radius = SkScalarHalf(diameter);
+ SkScalar x = SkIntToScalar(SkMin32(point1.x(), point2.x()));
+ SkScalar y = SkIntToScalar(SkMin32(point1.y(), point2.y()));
+ SkScalar dx, dy;
+ int count;
+ SkRect bounds;
+
+ if (!idy) { // Horizontal
+ bounds.set(x, y - radius, x + SkIntToScalar(idx), y + radius);
+ x += radius;
+ dx = diameter * 2;
+ dy = 0;
+ count = idx;
+ } else { // Vertical
+ bounds.set(x - radius, y, x + radius, y + SkIntToScalar(idy));
+ y += radius;
+ dx = 0;
+ dy = diameter * 2;
+ count = idy;
+ }
+
+ // The actual count is the number of ONs we hit alternating
+ // ON(diameter), OFF(diameter), ...
+ {
+ SkScalar width = SkScalarDiv(SkIntToScalar(count), diameter);
+ // Now compute the number of cells (ON and OFF)
+ count = SkScalarRound(width);
+ // Now compute the number of ONs
+ count = (count + 1) >> 1;
+ }
+
+ SkAutoMalloc storage(count * sizeof(SkPoint));
+ SkPoint* verts = (SkPoint*)storage.get();
+ // Now build the array of vertices to past to drawPoints
+ for (int i = 0; i < count; i++) {
+ verts[i].set(x, y);
+ x += dx;
+ y += dy;
+ }
+
+ paint.setStyle(SkPaint::kFill_Style);
+ paint.setPathEffect(0);
+
+ // Clipping to bounds is not required for correctness, but it does
+ // allow us to reject the entire array of points if we are completely
+ // offscreen. This is common in a webpage for android, where most of
+ // the content is clipped out. If drawPoints took an (optional) bounds
+ // parameter, that might even be better, as we would *just* use it for
+ // culling, and not both wacking the canvas' save/restore stack.
+ canvas->save(SkCanvas::kClip_SaveFlag);
+ canvas->clipRect(bounds);
+ canvas->drawPoints(SkCanvas::kPoints_PointMode, count, verts, paint);
+ canvas->restore();
+ } else {
+ SkPoint pts[2] = { point1, point2 };
+ canvas->drawLine(pts[0].fX, pts[0].fY, pts[1].fX, pts[1].fY, paint);
+ }
+}
+
+void PlatformGraphicsContextSkia::drawLineForText(const FloatPoint& pt, float width)
+{
+ SkRect r;
+ setrectForUnderline(&r, m_state->strokeThickness, pt, 0, width);
+
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setColor(m_state->strokeColor);
+
+ mCanvas->drawRect(r, paint);
+}
+
+void PlatformGraphicsContextSkia::drawLineForTextChecking(const FloatPoint& pt,
+ float width, GraphicsContext::TextCheckingLineStyle)
+{
+ // TODO: Should we draw different based on TextCheckingLineStyle?
+ SkRect r;
+ setrectForUnderline(&r, m_state->strokeThickness, pt, 0, width);
+
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setColor(SK_ColorRED); // Is this specified somewhere?
+
+ mCanvas->drawRect(r, paint);
+}
+
+void PlatformGraphicsContextSkia::drawRect(const IntRect& rect)
+{
+ SkPaint paint;
+ SkRect r(rect);
+
+ if (m_state->fillColor & 0xFF000000) {
+ setupPaintFill(&paint);
+ mCanvas->drawRect(r, paint);
+ }
+
+ // According to GraphicsContext.h, stroking inside drawRect always means
+ // a stroke of 1 inside the rect.
+ if (m_state->strokeStyle != NoStroke && (m_state->strokeColor & 0xFF000000)) {
+ paint.reset();
+ setupPaintStroke(&paint, &r);
+ paint.setPathEffect(0); // No dashing please
+ paint.setStrokeWidth(SK_Scalar1); // Always just 1.0 width
+ r.inset(SK_ScalarHalf, SK_ScalarHalf); // Ensure we're "inside"
+ mCanvas->drawRect(r, paint);
+ }
+}
+
+void PlatformGraphicsContextSkia::fillPath(const Path& pathToFill, WindRule fillRule)
+{
+ SkPath* path = pathToFill.platformPath();
+ if (!path)
+ return;
+
+ switch (fillRule) {
+ case RULE_NONZERO:
+ path->setFillType(SkPath::kWinding_FillType);
+ break;
+ case RULE_EVENODD:
+ path->setFillType(SkPath::kEvenOdd_FillType);
+ break;
+ }
+
+ SkPaint paint;
+ setupPaintFill(&paint);
+
+ mCanvas->drawPath(*path, paint);
+}
+
+void PlatformGraphicsContextSkia::fillRect(const FloatRect& rect)
+{
+ SkPaint paint;
+ setupPaintFill(&paint);
+ mCanvas->drawRect(rect, paint);
+}
+
+void PlatformGraphicsContextSkia::fillRect(const FloatRect& rect,
+ const Color& color)
+{
+ if (color.rgb() & 0xFF000000) {
+ SkPaint paint;
+
+ setupPaintCommon(&paint);
+ paint.setColor(color.rgb()); // Punch in the specified color
+ paint.setShader(0); // In case we had one set
+
+ // Sometimes we record and draw portions of the page, using clips
+ // for each portion. The problem with this is that webkit, sometimes,
+ // sees that we're only recording a portion, and they adjust some of
+ // their rectangle coordinates accordingly (e.g.
+ // RenderBoxModelObject::paintFillLayerExtended() which calls
+ // rect.intersect(paintInfo.rect) and then draws the bg with that
+ // rect. The result is that we end up drawing rects that are meant to
+ // seam together (one for each portion), but if the rects have
+ // fractional coordinates (e.g. we are zoomed by a fractional amount)
+ // we will double-draw those edges, resulting in visual cracks or
+ // artifacts.
+
+ // The fix seems to be to just turn off antialasing for rects (this
+ // entry-point in GraphicsContext seems to have been sufficient,
+ // though perhaps we'll find we need to do this as well in fillRect(r)
+ // as well.) Currently setupPaintCommon() enables antialiasing.
+
+ // Since we never show the page rotated at a funny angle, disabling
+ // antialiasing seems to have no real down-side, and it does fix the
+ // bug when we're zoomed (and drawing portions that need to seam).
+ paint.setAntiAlias(false);
+
+ mCanvas->drawRect(rect, paint);
+ }
+}
+
+void PlatformGraphicsContextSkia::fillRoundedRect(
+ const IntRect& rect, const IntSize& topLeft, const IntSize& topRight,
+ const IntSize& bottomLeft, const IntSize& bottomRight,
+ const Color& color)
+{
+ SkPaint paint;
+ SkPath path;
+ SkScalar radii[8];
+
+ radii[0] = SkIntToScalar(topLeft.width());
+ radii[1] = SkIntToScalar(topLeft.height());
+ radii[2] = SkIntToScalar(topRight.width());
+ radii[3] = SkIntToScalar(topRight.height());
+ radii[4] = SkIntToScalar(bottomRight.width());
+ radii[5] = SkIntToScalar(bottomRight.height());
+ radii[6] = SkIntToScalar(bottomLeft.width());
+ radii[7] = SkIntToScalar(bottomLeft.height());
+ path.addRoundRect(rect, radii);
+
+ setupPaintFill(&paint);
+ paint.setColor(color.rgb());
+ mCanvas->drawPath(path, paint);
+}
+
+void PlatformGraphicsContextSkia::strokeArc(const IntRect& r, int startAngle,
+ int angleSpan)
+{
+ SkPath path;
+ SkPaint paint;
+ SkRect oval(r);
+
+ if (m_state->strokeStyle == NoStroke) {
+ setupPaintFill(&paint); // We want the fill color
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStrokeWidth(SkFloatToScalar(m_state->strokeThickness));
+ } else
+ setupPaintStroke(&paint, 0);
+
+ // We do this before converting to scalar, so we don't overflow SkFixed
+ startAngle = fastMod(startAngle, 360);
+ angleSpan = fastMod(angleSpan, 360);
+
+ path.addArc(oval, SkIntToScalar(-startAngle), SkIntToScalar(-angleSpan));
+ mCanvas->drawPath(path, paint);
+}
+
+void PlatformGraphicsContextSkia::strokePath(const Path& pathToStroke)
+{
+ const SkPath* path = pathToStroke.platformPath();
+ if (!path)
+ return;
+
+ SkPaint paint;
+ setupPaintStroke(&paint, 0);
+
+ mCanvas->drawPath(*path, paint);
+}
+
+void PlatformGraphicsContextSkia::strokeRect(const FloatRect& rect, float lineWidth)
+{
+ SkPaint paint;
+
+ setupPaintStroke(&paint, 0);
+ paint.setStrokeWidth(SkFloatToScalar(lineWidth));
+ mCanvas->drawRect(rect, paint);
+}
+
+} // WebCore
diff --git a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextSkia.h b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextSkia.h
new file mode 100644
index 0000000..724e20b
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextSkia.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef platform_graphics_context_skia_h
+#define platform_graphics_context_skia_h
+
+#include "PlatformGraphicsContext.h"
+
+namespace WebCore {
+
+class PlatformGraphicsContextSkia : public PlatformGraphicsContext {
+public:
+ PlatformGraphicsContextSkia(SkCanvas* canvas, bool takeCanvasOwnership = false);
+ virtual ~PlatformGraphicsContextSkia();
+ virtual bool isPaintingDisabled();
+ virtual SkCanvas* getCanvas() { return mCanvas; }
+
+ virtual ContextType type() { return PaintingContext; }
+ virtual SkCanvas* recordingCanvas() { return mCanvas; }
+ virtual void endRecording(int type = 0) {}
+
+ // FIXME: This is used by ImageBufferAndroid, which should really be
+ // managing the canvas lifecycle itself
+
+ virtual bool deleteUs() const { return m_deleteCanvas; }
+
+ // State management
+ virtual void beginTransparencyLayer(float opacity);
+ virtual void endTransparencyLayer();
+ virtual void save();
+ virtual void restore();
+
+ // Matrix operations
+ virtual void concatCTM(const AffineTransform& affine);
+ virtual void rotate(float angleInRadians);
+ virtual void scale(const FloatSize& size);
+ virtual void translate(float x, float y);
+ virtual const SkMatrix& getTotalMatrix();
+
+ // Clipping
+ virtual void addInnerRoundedRectClip(const IntRect& rect, int thickness);
+ virtual void canvasClip(const Path& path);
+ virtual void clip(const FloatRect& rect);
+ virtual void clip(const Path& path);
+ virtual void clipConvexPolygon(size_t numPoints, const FloatPoint*, bool antialias);
+ virtual void clipOut(const IntRect& r);
+ virtual void clipOut(const Path& p);
+ virtual void clipPath(const Path& pathToClip, WindRule clipRule);
+
+ // Drawing
+ virtual void clearRect(const FloatRect& rect);
+ virtual void drawBitmapPattern(const SkBitmap& bitmap, const SkMatrix& matrix,
+ CompositeOperator compositeOp, const FloatRect& destRect);
+ virtual void drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src,
+ const SkRect& dst, CompositeOperator op);
+ virtual void drawConvexPolygon(size_t numPoints, const FloatPoint* points,
+ bool shouldAntialias);
+ virtual void drawEllipse(const IntRect& rect);
+ virtual void drawFocusRing(const Vector<IntRect>& rects, int /* width */,
+ int /* offset */, const Color& color);
+ virtual void drawHighlightForText(const Font& font, const TextRun& run,
+ const FloatPoint& point, int h,
+ const Color& backgroundColor, ColorSpace colorSpace,
+ int from, int to, bool isActive);
+ virtual void drawLine(const IntPoint& point1, const IntPoint& point2);
+ virtual void drawLineForText(const FloatPoint& pt, float width);
+ virtual void drawLineForTextChecking(const FloatPoint& pt, float width,
+ GraphicsContext::TextCheckingLineStyle);
+ virtual void drawRect(const IntRect& rect);
+ virtual void fillPath(const Path& pathToFill, WindRule fillRule);
+ virtual void fillRect(const FloatRect& rect);
+ virtual void fillRect(const FloatRect& rect, const Color& color);
+ virtual void fillRoundedRect(const IntRect& rect, const IntSize& topLeft,
+ const IntSize& topRight, const IntSize& bottomLeft,
+ const IntSize& bottomRight, const Color& color);
+ virtual void strokeArc(const IntRect& r, int startAngle, int angleSpan);
+ virtual void strokePath(const Path& pathToStroke);
+ virtual void strokeRect(const FloatRect& rect, float lineWidth);
+
+private:
+
+ // shadowsIgnoreTransforms is only true for canvas's ImageBuffer, which will
+ // have a GraphicsContext
+ virtual bool shadowsIgnoreTransforms() const {
+ return m_gc && m_gc->shadowsIgnoreTransforms();
+ }
+
+ SkCanvas* mCanvas;
+ bool m_deleteCanvas;
+};
+
+}
+#endif
diff --git a/Source/WebCore/plugins/android/PluginViewAndroid.cpp b/Source/WebCore/plugins/android/PluginViewAndroid.cpp
index 315d8a4..fdf6e03 100644
--- a/Source/WebCore/plugins/android/PluginViewAndroid.cpp
+++ b/Source/WebCore/plugins/android/PluginViewAndroid.cpp
@@ -690,7 +690,10 @@ void PluginView::paint(GraphicsContext* context, const IntRect& rect)
notification of its global position change.
*/
updatePluginWidget();
- m_window->setSurfaceClip(context->platformContext()->mCanvas->getTotalClip().getBounds());
+ SkCanvas* canvas = context->platformContext()->getCanvas();
+ if (!canvas)
+ return;
+ m_window->setSurfaceClip(canvas->getTotalClip().getBounds());
} else {
m_window->inval(rect, false);
context->save();
diff --git a/Source/WebKit/android/RenderSkinMediaButton.cpp b/Source/WebKit/android/RenderSkinMediaButton.cpp
index febf575..b3aa57d 100644
--- a/Source/WebKit/android/RenderSkinMediaButton.cpp
+++ b/Source/WebKit/android/RenderSkinMediaButton.cpp
@@ -95,6 +95,9 @@ void RenderSkinMediaButton::Draw(SkCanvas* canvas, const IntRect& r, int buttonT
Decode();
}
+ if (!canvas)
+ return;
+
// If we failed to decode, do nothing. This way the browser still works,
// and webkit will still draw the label and layout space for us.
if (gDecodingFailed)
diff --git a/Source/WebKit/android/WebCoreSupport/MediaPlayerPrivateAndroid.cpp b/Source/WebKit/android/WebCoreSupport/MediaPlayerPrivateAndroid.cpp
index 95ced96..52aeb23 100644
--- a/Source/WebKit/android/WebCoreSupport/MediaPlayerPrivateAndroid.cpp
+++ b/Source/WebKit/android/WebCoreSupport/MediaPlayerPrivateAndroid.cpp
@@ -264,7 +264,9 @@ public:
if (!m_poster || (!m_poster->getPixels() && !m_poster->pixelRef()))
return;
- SkCanvas* canvas = ctxt->platformContext()->mCanvas;
+ SkCanvas* canvas = ctxt->platformContext()->getCanvas();
+ if (!canvas)
+ return;
// We paint with the following rules in mind:
// - only downscale the poster, never upscale
// - maintain the natural aspect ratio of the poster
diff --git a/Source/WebKit/android/jni/PictureSet.cpp b/Source/WebKit/android/jni/PictureSet.cpp
index f3534eb..8beb0ef 100644
--- a/Source/WebKit/android/jni/PictureSet.cpp
+++ b/Source/WebKit/android/jni/PictureSet.cpp
@@ -38,6 +38,8 @@
#include "SkRegion.h"
#include "SkStream.h"
+#include "PlatformGraphicsContext.h"
+
#define MAX_DRAW_TIME 100
#define MIN_SPLITTABLE 400
#define MAX_ADDITIONAL_AREA 0.65
@@ -133,6 +135,9 @@ void PictureSet::add(const Pictures* temp)
{
Pictures pictureAndBounds = *temp;
SkSafeRef(pictureAndBounds.mPicture);
+#ifdef CONTEXT_RECORDING
+ SkSafeRef(pictureAndBounds.mGraphicsOperationCollection);
+#endif
pictureAndBounds.mWroteElapsed = false;
mPictures.append(pictureAndBounds);
}
@@ -478,13 +483,20 @@ void PictureSet::add(const SkIRect& area, uint32_t elapsed, bool split, bool emp
working->mArea.setEmpty();
SkSafeUnref(working->mPicture);
working->mPicture = 0;
+#ifdef CONTEXT_RECORDING
+ SkSafeUnref(working->mGraphicsOperationCollection);
+ working->mGraphicsOperationCollection = 0;
+#endif
}
}
// Now we can add the new Picture to the list, with the correct area
// that need to be repainted
- Pictures pictureAndBounds = {totalArea, 0, totalArea,
- elapsed, split, false, false, empty};
+ Pictures pictureAndBounds = {totalArea, 0,
+#ifdef CONTEXT_RECORDING
+ 0,
+#endif
+ totalArea, elapsed, split, false, false, empty};
#ifdef FAST_PICTURESET
if (mPictures.size() == 0)
@@ -525,6 +537,10 @@ void PictureSet::add(const SkIRect& area, uint32_t elapsed, bool split, bool emp
working->mArea.setEmpty();
SkSafeUnref(working->mPicture);
working->mPicture = 0;
+#ifdef CONTEXT_RECORDING
+ SkSafeUnref(working->mGraphicsOperationCollection);
+ working->mGraphicsOperationCollection = 0;
+#endif
}
}
@@ -677,6 +693,9 @@ void PictureSet::clear()
for (Pictures* working = mPictures.begin(); working != last; working++) {
working->mArea.setEmpty();
SkSafeUnref(working->mPicture);
+#ifdef CONTEXT_RECORDING
+ SkSafeUnref(working->mGraphicsOperationCollection);
+#endif
}
mPictures.clear();
#endif // FAST_PICTURESET
@@ -797,7 +816,14 @@ bool PictureSet::draw(SkCanvas* canvas)
canvas->translate(pathBounds.fLeft, pathBounds.fTop);
canvas->save();
uint32_t startTime = getThreadMsec();
+
+#ifdef CONTEXT_RECORDING
+ WebCore::PlatformGraphicsContextSkia context(canvas);
+ working->mGraphicsOperationCollection->apply(&context);
+#else
canvas->drawPicture(*working->mPicture);
+#endif
+
size_t elapsed = working->mElapsed = getThreadMsec() - startTime;
working->mWroteElapsed = true;
if (maxElapsed < elapsed && (pathBounds.width() >= MIN_SPLITTABLE ||
@@ -1060,6 +1086,14 @@ void PictureSet::setPicture(size_t i, SkPicture* p)
mPictures[i].mEmpty = emptyPicture(p);
}
+#ifdef CONTEXT_RECORDING
+void PictureSet::setGraphicsOperationCollection(size_t i, WebCore::GraphicsOperationCollection* p)
+{
+ SkSafeUnref(mPictures[i].mGraphicsOperationCollection);
+ mPictures[i].mGraphicsOperationCollection = p;
+}
+#endif
+
void PictureSet::split(PictureSet* out) const
{
dump(__FUNCTION__);
diff --git a/Source/WebKit/android/jni/PictureSet.h b/Source/WebKit/android/jni/PictureSet.h
index 1d9a14d..1e639da 100644
--- a/Source/WebKit/android/jni/PictureSet.h
+++ b/Source/WebKit/android/jni/PictureSet.h
@@ -45,7 +45,10 @@
#include <wtf/Vector.h>
#include <wtf/HashMap.h>
+#include "GraphicsOperationCollection.h"
+
// #define FAST_PICTURESET // use a hierarchy of pictures
+// #define CONTEXT_RECORDING // use the new PlatformGraphicsContextRecording
class SkCanvas;
class SkPicture;
@@ -100,6 +103,9 @@ namespace android {
const SkIRect& bounds(size_t i) const {
return mPictures[i].mArea; }
void setPicture(size_t i, SkPicture* p);
+#ifdef CONTEXT_RECORDING
+ void setGraphicsOperationCollection(size_t i, WebCore::GraphicsOperationCollection* p);
+#endif
void setDrawTimes(const PictureSet& );
size_t size() const { return mPictures.size(); }
void split(PictureSet* result) const;
@@ -119,9 +125,13 @@ namespace android {
int mBucketCountX;
int mBucketCountY;
#else
+
struct Pictures {
SkIRect mArea;
SkPicture* mPicture;
+#ifdef CONTEXT_RECORDING
+ WebCore::GraphicsOperationCollection* mGraphicsOperationCollection;
+#endif
SkIRect mUnsplit;
uint32_t mElapsed;
bool mSplit : 8;
diff --git a/Source/WebKit/android/jni/WebViewCore.cpp b/Source/WebKit/android/jni/WebViewCore.cpp
index 540b1dd..6270c63 100644
--- a/Source/WebKit/android/jni/WebViewCore.cpp
+++ b/Source/WebKit/android/jni/WebViewCore.cpp
@@ -62,6 +62,7 @@
#include "Geolocation.h"
#include "GraphicsContext.h"
#include "GraphicsJNI.h"
+#include "GraphicsOperationCollection.h"
#include "HTMLAnchorElement.h"
#include "HTMLAreaElement.h"
#include "HTMLElement.h"
@@ -787,7 +788,7 @@ SkPicture* WebViewCore::rebuildPicture(const SkIRect& inval)
SkAutoMemoryUsageProbe mup(__FUNCTION__);
SkCanvas* recordingCanvas = arp.getRecordingCanvas();
- WebCore::PlatformGraphicsContext pgc(recordingCanvas);
+ WebCore::PlatformGraphicsContextSkia pgc(recordingCanvas);
WebCore::GraphicsContext gc(&pgc);
IntPoint origin = view->minimumScrollPosition();
WebCore::IntRect drawArea(inval.fLeft + origin.x(), inval.fTop + origin.y(),
@@ -803,6 +804,27 @@ SkPicture* WebViewCore::rebuildPicture(const SkIRect& inval)
return picture;
}
+#ifdef CONTEXT_RECORDING
+GraphicsOperationCollection* WebViewCore::rebuildGraphicsOperationCollection(const SkIRect& inval)
+{
+ WebCore::FrameView* view = m_mainFrame->view();
+ int width = view->contentsWidth();
+ int height = view->contentsHeight();
+
+ IntPoint origin = view->minimumScrollPosition();
+ WebCore::IntRect drawArea(inval.fLeft + origin.x(), inval.fTop + origin.y(),
+ inval.width(), inval.height());
+
+ AutoGraphicsOperationCollection autoPicture(drawArea);
+ view->platformWidget()->draw(autoPicture.context(), drawArea);
+
+ m_rebuildInval.op(inval, SkRegion::kUnion_Op);
+
+ SkSafeRef(autoPicture.picture());
+ return autoPicture.picture();
+}
+#endif
+
void WebViewCore::rebuildPictureSet(PictureSet* pictureSet)
{
#ifdef FAST_PICTURESET
@@ -828,6 +850,10 @@ void WebViewCore::rebuildPictureSet(PictureSet* pictureSet)
DBG_SET_LOGD("pictSet=%p [%d] {%d,%d,w=%d,h=%d}", pictureSet, index,
inval.fLeft, inval.fTop, inval.width(), inval.height());
pictureSet->setPicture(index, rebuildPicture(inval));
+#ifdef CONTEXT_RECORDING
+ pictureSet->setGraphicsOperationCollection(index,
+ rebuildGraphicsOperationCollection(inval));
+#endif
}
pictureSet->validate(__FUNCTION__);
diff --git a/Source/WebKit/android/jni/WebViewCore.h b/Source/WebKit/android/jni/WebViewCore.h
index 23568bb..99a13f3 100644
--- a/Source/WebKit/android/jni/WebViewCore.h
+++ b/Source/WebKit/android/jni/WebViewCore.h
@@ -53,6 +53,7 @@
namespace WebCore {
class Color;
+ class GraphicsOperationCollection;
class FrameView;
class HTMLAnchorElement;
class HTMLElement;
@@ -641,6 +642,9 @@ namespace android {
void recordPictureSet(PictureSet* master);
SkPicture* rebuildPicture(const SkIRect& inval);
+#ifdef CONTEXT_RECORDING
+ WebCore::GraphicsOperationCollection* rebuildGraphicsOperationCollection(const SkIRect& inval);
+#endif
void rebuildPictureSet(PictureSet* );
void sendNotifyProgressFinished();
/*