From 64e4b265f84573b97d408f7d3e5aa99a647be057 Mon Sep 17 00:00:00 2001 From: Nicolas Roard Date: Mon, 2 Apr 2012 16:16:59 -0700 Subject: Implements a recording GraphicsContext Change-Id: I41feadb23dce25af321331c459eb159c6141831b --- Android.mk | 1 + Source/WebCore/Android.mk | 8 +- .../platform/android/RenderThemeAndroid.cpp | 18 +- Source/WebCore/platform/graphics/Font.h | 6 + .../platform/graphics/android/FontAndroid.cpp | 10 +- .../graphics/android/GraphicsContextAndroid.cpp | 647 ------------ .../graphics/android/GraphicsLayerAndroid.cpp | 4 +- .../graphics/android/ImageBufferAndroid.cpp | 5 +- .../graphics/android/PlatformGraphicsContext.cpp | 1048 -------------------- .../graphics/android/PlatformGraphicsContext.h | 150 --- .../android/context/GraphicsContextAndroid.cpp | 648 ++++++++++++ .../graphics/android/context/GraphicsOperation.h | 809 +++++++++++++++ .../context/GraphicsOperationCollection.cpp | 63 ++ .../android/context/GraphicsOperationCollection.h | 72 ++ .../android/context/PlatformGraphicsContext.cpp | 456 +++++++++ .../android/context/PlatformGraphicsContext.h | 204 ++++ .../context/PlatformGraphicsContextRecording.cpp | 373 +++++++ .../context/PlatformGraphicsContextRecording.h | 128 +++ .../context/PlatformGraphicsContextSkia.cpp | 606 +++++++++++ .../android/context/PlatformGraphicsContextSkia.h | 115 +++ .../WebCore/plugins/android/PluginViewAndroid.cpp | 5 +- Source/WebKit/android/RenderSkinMediaButton.cpp | 3 + .../WebCoreSupport/MediaPlayerPrivateAndroid.cpp | 4 +- Source/WebKit/android/jni/PictureSet.cpp | 38 +- Source/WebKit/android/jni/PictureSet.h | 10 + Source/WebKit/android/jni/WebViewCore.cpp | 28 +- Source/WebKit/android/jni/WebViewCore.h | 4 + 27 files changed, 3605 insertions(+), 1858 deletions(-) delete mode 100644 Source/WebCore/platform/graphics/android/GraphicsContextAndroid.cpp delete mode 100644 Source/WebCore/platform/graphics/android/PlatformGraphicsContext.cpp delete mode 100644 Source/WebCore/platform/graphics/android/PlatformGraphicsContext.h create mode 100644 Source/WebCore/platform/graphics/android/context/GraphicsContextAndroid.cpp create mode 100644 Source/WebCore/platform/graphics/android/context/GraphicsOperation.h create mode 100644 Source/WebCore/platform/graphics/android/context/GraphicsOperationCollection.cpp create mode 100644 Source/WebCore/platform/graphics/android/context/GraphicsOperationCollection.h create mode 100644 Source/WebCore/platform/graphics/android/context/PlatformGraphicsContext.cpp create mode 100644 Source/WebCore/platform/graphics/android/context/PlatformGraphicsContext.h create mode 100644 Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.cpp create mode 100644 Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.h create mode 100644 Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextSkia.cpp create mode 100644 Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextSkia.h 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(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* 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/GraphicsContextAndroid.cpp b/Source/WebCore/platform/graphics/android/GraphicsContextAndroid.cpp deleted file mode 100644 index 7d6c809..0000000 --- a/Source/WebCore/platform/graphics/android/GraphicsContextAndroid.cpp +++ /dev/null @@ -1,647 +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 "GraphicsContext.h" - -#include "AffineTransform.h" -#include "Font.h" -#include "Gradient.h" -#include "NotImplemented.h" -#include "Path.h" -#include "Pattern.h" -#include "PlatformGraphicsContext.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" - -using namespace std; - -namespace WebCore { - -// This class just holds onto a PlatformContextSkia for GraphicsContext. -class GraphicsContextPlatformPrivate { - WTF_MAKE_NONCOPYABLE(GraphicsContextPlatformPrivate); -public: - GraphicsContextPlatformPrivate(PlatformGraphicsContext* platformContext) - : m_context(platformContext) { } - - PlatformGraphicsContext* context() { return m_context; } - -private: - // Non-owning pointer to the PlatformContext. - PlatformGraphicsContext* m_context; -}; - -static SkShader* extractShader(Pattern* pat, Gradient* grad) -{ - if (pat) - return pat->platformPattern(AffineTransform()); - else if (grad) - return grad->platformGradient(); - return 0; -} - -//////////////////////////////////////////////////////////////////////////////////////////////// - -GraphicsContext* GraphicsContext::createOffscreenContext(int width, int height) -{ - PlatformGraphicsContext* pgc = new PlatformGraphicsContext(new SkCanvas, true); - - SkBitmap bitmap; - - bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height); - bitmap.allocPixels(); - bitmap.eraseColor(0); - pgc->mCanvas->setBitmapDevice(bitmap); - - GraphicsContext* ctx = new GraphicsContext(pgc); - return ctx; -} - -//////////////////////////////////////////////////////////////////////////////////////////////// - -void GraphicsContext::platformInit(PlatformGraphicsContext* gc) -{ - if (gc) - gc->setGraphicsContext(this); - m_data = new GraphicsContextPlatformPrivate(gc); - setPaintingDisabled(!gc || !gc->mCanvas); -} - -void GraphicsContext::platformDestroy() -{ - delete m_data; -} - -void GraphicsContext::savePlatformState() -{ - if (paintingDisabled()) - return; - platformContext()->save(); -} - -void GraphicsContext::restorePlatformState() -{ - if (paintingDisabled()) - return; - platformContext()->restore(); -} - -bool GraphicsContext::willFill() const -{ - return m_state.fillColor.rgb(); -} - -bool GraphicsContext::willStroke() const -{ - return m_state.strokeColor.rgb(); -} - -// Draws a filled rectangle with a stroked border. -void GraphicsContext::drawRect(const IntRect& rect) -{ - if (paintingDisabled()) - return; - - platformContext()->drawRect(rect); -} - -// This is only used to draw borders. -void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2) -{ - if (paintingDisabled()) - return; - - platformContext()->drawLine(point1, point2); -} - -void GraphicsContext::drawLineForText(const FloatPoint& pt, float width, bool /* printing */) -{ - if (paintingDisabled()) - return; - - platformContext()->drawLineForText(pt, width); -} - -void GraphicsContext::drawLineForTextChecking(const FloatPoint& pt, float width, - TextCheckingLineStyle style) -{ - if (paintingDisabled()) - return; - - platformContext()->drawLineForTextChecking(pt, width, style); -} - -// This method is only used to draw the little circles used in lists. -void GraphicsContext::drawEllipse(const IntRect& rect) -{ - if (paintingDisabled()) - return; - - platformContext()->drawEllipse(rect); -} - -void GraphicsContext::strokeArc(const IntRect& r, int startAngle, int angleSpan) -{ - if (paintingDisabled()) - return; - - platformContext()->strokeArc(r, startAngle, angleSpan); -} - -void GraphicsContext::drawConvexPolygon(size_t numPoints, const FloatPoint* points, - bool shouldAntialias) -{ - if (paintingDisabled()) - return; - - platformContext()->drawConvexPolygon(numPoints, points, shouldAntialias); -} - -void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight, - const IntSize& bottomLeft, const IntSize& bottomRight, - const Color& color, ColorSpace colorSpace) -{ - if (paintingDisabled()) - return; - - platformContext()->fillRoundedRect(rect, topLeft, topRight, - bottomLeft, bottomRight, color, colorSpace); -} - -void GraphicsContext::fillRect(const FloatRect& rect) -{ - if (paintingDisabled()) - return; - - platformContext()->fillRect(rect); -} - -void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorSpace colorSpace) -{ - if (paintingDisabled()) - return; - - platformContext()->fillRect(rect, color, colorSpace); -} - -void GraphicsContext::clip(const FloatRect& rect) -{ - if (paintingDisabled()) - return; - - platformContext()->clip(rect); -} - -void GraphicsContext::clip(const Path& path) -{ - if (paintingDisabled()) - return; - - platformContext()->clip(path); -} - -void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness) -{ - if (paintingDisabled()) - return; - - platformContext()->addInnerRoundedRectClip(rect, thickness); -} - -void GraphicsContext::canvasClip(const Path& path) -{ - if (paintingDisabled()) - return; - - platformContext()->canvasClip(path); -} - -void GraphicsContext::clipOut(const IntRect& r) -{ - if (paintingDisabled()) - return; - - platformContext()->clipOut(r); -} - -#if ENABLE(SVG) -void GraphicsContext::clipPath(const Path& pathToClip, WindRule clipRule) -{ - if (paintingDisabled()) - return; - - platformContext()->clipPath(pathToClip, clipRule); -} -#endif - -void GraphicsContext::clipOut(const Path& p) -{ - if (paintingDisabled()) - return; - - platformContext()->clipOut(p); -} - -////////////////////////////////////////////////////////////////////////////////////////////////// - -#if SVG_SUPPORT -KRenderingDeviceContext* GraphicsContext::createRenderingDeviceContext() -{ - return new KRenderingDeviceContextQuartz(platformContext()); -} -#endif - -void GraphicsContext::beginTransparencyLayer(float opacity) -{ - if (paintingDisabled()) - return; - - platformContext()->beginTransparencyLayer(opacity); -} - -void GraphicsContext::endTransparencyLayer() -{ - if (paintingDisabled()) - return; - - platformContext()->endTransparencyLayer(); -} - -/////////////////////////////////////////////////////////////////////////// - -void GraphicsContext::setupFillPaint(SkPaint* paint) -{ - if (paintingDisabled()) - return; - platformContext()->setupPaintFill(paint); -} - -void GraphicsContext::setupStrokePaint(SkPaint* paint) -{ - if (paintingDisabled()) - return; - platformContext()->setupPaintStroke(paint, 0); -} - -bool GraphicsContext::setupShadowPaint(SkPaint* paint, SkPoint* offset) -{ - if (paintingDisabled()) - return false; - return platformContext()->setupPaintShadow(paint, offset); -} - -void GraphicsContext::setPlatformStrokeColor(const Color& c, ColorSpace) -{ - if (paintingDisabled()) - return; - platformContext()->setStrokeColor(c); -} - -void GraphicsContext::setPlatformStrokeThickness(float f) -{ - if (paintingDisabled()) - return; - platformContext()->setStrokeThickness(f); -} - -void GraphicsContext::setPlatformStrokeStyle(StrokeStyle style) -{ - if (paintingDisabled()) - return; - platformContext()->setStrokeStyle(style); -} - -void GraphicsContext::setPlatformFillColor(const Color& c, ColorSpace) -{ - if (paintingDisabled()) - return; - platformContext()->setFillColor(c); -} - -void GraphicsContext::setPlatformShadow(const FloatSize& size, float blur, const Color& color, ColorSpace) -{ - if (paintingDisabled()) - return; - - if (blur <= 0) - this->clearPlatformShadow(); - - SkColor c; - if (color.isValid()) - c = color.rgb(); - else - c = SkColorSetARGB(0xFF / 3, 0, 0, 0); // "std" Apple shadow color - platformContext()->setShadow(blur, size.width(), size.height(), c); -} - -void GraphicsContext::clearPlatformShadow() -{ - if (paintingDisabled()) - return; - - platformContext()->setShadow(0, 0, 0, 0); -} - -/////////////////////////////////////////////////////////////////////////////// - -void GraphicsContext::drawFocusRing(const Vector& rects, int width, int offset, const Color& color) -{ - if (paintingDisabled()) - return; - - platformContext()->drawFocusRing(rects, width, offset, color); -} - -void GraphicsContext::drawFocusRing(const Path&, int, int, const Color&) -{ - // Do nothing, since we draw the focus ring independently. -} - -PlatformGraphicsContext* GraphicsContext::platformContext() const -{ - ASSERT(!paintingDisabled()); - return m_data->context(); -} - -void GraphicsContext::setMiterLimit(float limit) -{ - if (paintingDisabled()) - return; - platformContext()->setMiterLimit(limit); -} - -void GraphicsContext::setAlpha(float alpha) -{ - if (paintingDisabled()) - return; - platformContext()->setAlpha(alpha); -} - -void GraphicsContext::setPlatformCompositeOperation(CompositeOperator op) -{ - if (paintingDisabled()) - return; - platformContext()->setCompositeOperation(op); -} - -void GraphicsContext::clearRect(const FloatRect& rect) -{ - if (paintingDisabled()) - return; - - platformContext()->clearRect(rect); -} - -void GraphicsContext::strokeRect(const FloatRect& rect, float lineWidth) -{ - if (paintingDisabled()) - return; - - platformContext()->strokeRect(rect, lineWidth); -} - -void GraphicsContext::setLineCap(LineCap cap) -{ - if (paintingDisabled()) - return; - platformContext()->setLineCap(cap); -} - -#if ENABLE(SVG) -void GraphicsContext::setLineDash(const DashArray& dashes, float dashOffset) -{ - if (paintingDisabled()) - return; - - platformContext()->setLineDash(dashes, dashOffset); -} -#endif - -void GraphicsContext::setLineJoin(LineJoin join) -{ - if (paintingDisabled()) - return; - platformContext()->setLineJoin(join); -} - -void GraphicsContext::scale(const FloatSize& size) -{ - if (paintingDisabled()) - return; - platformContext()->scale(size); -} - -void GraphicsContext::rotate(float angleInRadians) -{ - if (paintingDisabled()) - return; - platformContext()->rotate(angleInRadians); -} - -void GraphicsContext::translate(float x, float y) -{ - if (paintingDisabled()) - return; - platformContext()->translate(x, y); -} - -void GraphicsContext::concatCTM(const AffineTransform& affine) -{ - if (paintingDisabled()) - return; - platformContext()->concatCTM(affine); -} - -// This is intended to round the rect to device pixels (through the CTM) -// and then invert the result back into source space, with the hope that when -// it is drawn (through the matrix), it will land in the "right" place (i.e. -// on pixel boundaries). - -// For android, we record this geometry once and then draw it though various -// scale factors as the user zooms, without re-recording. Thus this routine -// should just leave the original geometry alone. - -// If we instead draw into bitmap tiles, we should then perform this -// transform -> round -> inverse step. - -FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& rect, RoundingMode) -{ - return rect; -} - -////////////////////////////////////////////////////////////////////////////////////////////////// - -void GraphicsContext::setURLForRect(const KURL& link, const IntRect& destRect) -{ -// Appears to be PDF specific, so we ignore it -} - -void GraphicsContext::setPlatformShouldAntialias(bool useAA) -{ - if (paintingDisabled()) - return; - platformContext()->setShouldAntialias(useAA); -} - -void GraphicsContext::setPlatformFillGradient(Gradient* fillGradient) -{ - if (paintingDisabled()) - return; - SkShader* shader = extractShader(0, fillGradient); - platformContext()->setFillShader(shader); -} - -void GraphicsContext::setPlatformFillPattern(Pattern* fillPattern) -{ - if (paintingDisabled()) - return; - SkShader* shader = extractShader(fillPattern, 0); - platformContext()->setFillShader(shader); -} - -void GraphicsContext::setPlatformStrokeGradient(Gradient* strokeGradient) -{ - if (paintingDisabled()) - return; - SkShader* shader = extractShader(0, strokeGradient); - platformContext()->setStrokeShader(shader); -} - -void GraphicsContext::setPlatformStrokePattern(Pattern* strokePattern) -{ - if (paintingDisabled()) - return; - SkShader* shader = extractShader(strokePattern, 0); - platformContext()->setStrokeShader(shader); -} - -AffineTransform GraphicsContext::getCTM() const -{ - if (paintingDisabled()) - return AffineTransform(); - const SkMatrix& m = platformContext()->getTotalMatrix(); - return AffineTransform(SkScalarToDouble(m.getScaleX()), // a - SkScalarToDouble(m.getSkewY()), // b - SkScalarToDouble(m.getSkewX()), // c - SkScalarToDouble(m.getScaleY()), // d - SkScalarToDouble(m.getTranslateX()), // e - SkScalarToDouble(m.getTranslateY())); // f -} - -void GraphicsContext::setCTM(const AffineTransform& transform) -{ - // The SkPicture mode of Skia does not support SkCanvas::setMatrix(), so we - // can not simply use that method here. We could calculate the transform - // required to achieve the desired matrix and use SkCanvas::concat(), but - // there's currently no need for this. - ASSERT_NOT_REACHED(); -} - -/////////////////////////////////////////////////////////////////////////////// - -void GraphicsContext::fillPath(const Path& pathToFill) -{ - if (paintingDisabled()) - return; - - platformContext()->fillPath(pathToFill, fillRule()); -} - -void GraphicsContext::strokePath(const Path& pathToStroke) -{ - if (paintingDisabled()) - return; - - platformContext()->strokePath(pathToStroke); -} - -InterpolationQuality GraphicsContext::imageInterpolationQuality() const -{ - notImplemented(); - return InterpolationDefault; -} - -void GraphicsContext::setImageInterpolationQuality(InterpolationQuality mode) -{ -#if 0 - enum InterpolationQuality { - InterpolationDefault, - InterpolationNone, - InterpolationLow, - InterpolationMedium, - InterpolationHigh - }; -#endif - // TODO: record this, so we can know when to use bitmap-filtering when we draw - // ... not sure how meaningful this will be given our playback model. - - // Certainly safe to do nothing for the present. -} - -void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint*, - bool antialias) -{ - if (paintingDisabled()) - return; - - if (numPoints <= 1) - return; - - // FIXME: IMPLEMENT! -} - -void GraphicsContext::drawHighlightForText(const Font& font, const TextRun& run, - const FloatPoint& point, int h, - const Color& backgroundColor, - ColorSpace colorSpace, int from, - int to, bool isActive) -{ - if (paintingDisabled()) - return; - - platformContext()->drawHighlightForText(font, run, point, h, backgroundColor, - colorSpace, from, to, isActive); -} - -} // namespace WebCore - -/////////////////////////////////////////////////////////////////////////////// - -SkCanvas* android_gc2canvas(WebCore::GraphicsContext* gc) -{ - return gc->platformContext()->mCanvas; -} 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 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 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& 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 - -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& 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 m_stateStack; - State* m_state; - GraphicsContext* m_gc; // Back-ptr to our parent -}; - -} -#endif diff --git a/Source/WebCore/platform/graphics/android/context/GraphicsContextAndroid.cpp b/Source/WebCore/platform/graphics/android/context/GraphicsContextAndroid.cpp new file mode 100644 index 0000000..12b53a3 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/context/GraphicsContextAndroid.cpp @@ -0,0 +1,648 @@ +/* + * 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 "GraphicsContext.h" + +#include "AffineTransform.h" +#include "Font.h" +#include "Gradient.h" +#include "NotImplemented.h" +#include "Path.h" +#include "Pattern.h" +#include "PlatformGraphicsContext.h" +#include "PlatformGraphicsContextSkia.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" + +using namespace std; + +namespace WebCore { + +// This class just holds onto a PlatformContextSkia for GraphicsContext. +class GraphicsContextPlatformPrivate { + WTF_MAKE_NONCOPYABLE(GraphicsContextPlatformPrivate); +public: + GraphicsContextPlatformPrivate(PlatformGraphicsContext* platformContext) + : m_context(platformContext) { } + + PlatformGraphicsContext* context() { return m_context; } + +private: + // Non-owning pointer to the PlatformContext. + PlatformGraphicsContext* m_context; +}; + +static SkShader* extractShader(Pattern* pat, Gradient* grad) +{ + if (pat) + return pat->platformPattern(AffineTransform()); + else if (grad) + return grad->platformGradient(); + return 0; +} + +//////////////////////////////////////////////////////////////////////////////////////////////// + +GraphicsContext* GraphicsContext::createOffscreenContext(int width, int height) +{ + PlatformGraphicsContextSkia* pgc = new PlatformGraphicsContextSkia(new SkCanvas, true); + + SkBitmap bitmap; + + bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height); + bitmap.allocPixels(); + bitmap.eraseColor(0); + pgc->getCanvas()->setBitmapDevice(bitmap); + + GraphicsContext* ctx = new GraphicsContext(pgc); + return ctx; +} + +//////////////////////////////////////////////////////////////////////////////////////////////// + +void GraphicsContext::platformInit(PlatformGraphicsContext* gc) +{ + if (gc) + gc->setGraphicsContext(this); + m_data = new GraphicsContextPlatformPrivate(gc); + setPaintingDisabled(!gc || gc->isPaintingDisabled()); +} + +void GraphicsContext::platformDestroy() +{ + delete m_data; +} + +void GraphicsContext::savePlatformState() +{ + if (paintingDisabled()) + return; + platformContext()->save(); +} + +void GraphicsContext::restorePlatformState() +{ + if (paintingDisabled()) + return; + platformContext()->restore(); +} + +bool GraphicsContext::willFill() const +{ + return m_state.fillColor.rgb(); +} + +bool GraphicsContext::willStroke() const +{ + return m_state.strokeColor.rgb(); +} + +// Draws a filled rectangle with a stroked border. +void GraphicsContext::drawRect(const IntRect& rect) +{ + if (paintingDisabled()) + return; + + platformContext()->drawRect(rect); +} + +// This is only used to draw borders. +void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2) +{ + if (paintingDisabled()) + return; + + platformContext()->drawLine(point1, point2); +} + +void GraphicsContext::drawLineForText(const FloatPoint& pt, float width, bool /* printing */) +{ + if (paintingDisabled()) + return; + + platformContext()->drawLineForText(pt, width); +} + +void GraphicsContext::drawLineForTextChecking(const FloatPoint& pt, float width, + TextCheckingLineStyle style) +{ + if (paintingDisabled()) + return; + + platformContext()->drawLineForTextChecking(pt, width, style); +} + +// This method is only used to draw the little circles used in lists. +void GraphicsContext::drawEllipse(const IntRect& rect) +{ + if (paintingDisabled()) + return; + + platformContext()->drawEllipse(rect); +} + +void GraphicsContext::strokeArc(const IntRect& r, int startAngle, int angleSpan) +{ + if (paintingDisabled()) + return; + + platformContext()->strokeArc(r, startAngle, angleSpan); +} + +void GraphicsContext::drawConvexPolygon(size_t numPoints, const FloatPoint* points, + bool shouldAntialias) +{ + if (paintingDisabled()) + return; + + platformContext()->drawConvexPolygon(numPoints, points, shouldAntialias); +} + +void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight, + const IntSize& bottomLeft, const IntSize& bottomRight, + const Color& color, ColorSpace colorSpace) +{ + if (paintingDisabled()) + return; + + platformContext()->fillRoundedRect(rect, topLeft, topRight, + bottomLeft, bottomRight, color, colorSpace); +} + +void GraphicsContext::fillRect(const FloatRect& rect) +{ + if (paintingDisabled()) + return; + + platformContext()->fillRect(rect); +} + +void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorSpace colorSpace) +{ + if (paintingDisabled()) + return; + + platformContext()->fillRect(rect, color, colorSpace); +} + +void GraphicsContext::clip(const FloatRect& rect) +{ + if (paintingDisabled()) + return; + + platformContext()->clip(rect); +} + +void GraphicsContext::clip(const Path& path) +{ + if (paintingDisabled()) + return; + + platformContext()->clip(path); +} + +void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness) +{ + if (paintingDisabled()) + return; + + platformContext()->addInnerRoundedRectClip(rect, thickness); +} + +void GraphicsContext::canvasClip(const Path& path) +{ + if (paintingDisabled()) + return; + + platformContext()->canvasClip(path); +} + +void GraphicsContext::clipOut(const IntRect& r) +{ + if (paintingDisabled()) + return; + + platformContext()->clipOut(r); +} + +#if ENABLE(SVG) +void GraphicsContext::clipPath(const Path& pathToClip, WindRule clipRule) +{ + if (paintingDisabled()) + return; + + platformContext()->clipPath(pathToClip, clipRule); +} +#endif + +void GraphicsContext::clipOut(const Path& p) +{ + if (paintingDisabled()) + return; + + platformContext()->clipOut(p); +} + +////////////////////////////////////////////////////////////////////////////////////////////////// + +#if SVG_SUPPORT +KRenderingDeviceContext* GraphicsContext::createRenderingDeviceContext() +{ + return new KRenderingDeviceContextQuartz(platformContext()); +} +#endif + +void GraphicsContext::beginTransparencyLayer(float opacity) +{ + if (paintingDisabled()) + return; + + platformContext()->beginTransparencyLayer(opacity); +} + +void GraphicsContext::endTransparencyLayer() +{ + if (paintingDisabled()) + return; + + platformContext()->endTransparencyLayer(); +} + +/////////////////////////////////////////////////////////////////////////// + +void GraphicsContext::setupFillPaint(SkPaint* paint) +{ + if (paintingDisabled()) + return; + platformContext()->setupPaintFill(paint); +} + +void GraphicsContext::setupStrokePaint(SkPaint* paint) +{ + if (paintingDisabled()) + return; + platformContext()->setupPaintStroke(paint, 0); +} + +bool GraphicsContext::setupShadowPaint(SkPaint* paint, SkPoint* offset) +{ + if (paintingDisabled()) + return false; + return platformContext()->setupPaintShadow(paint, offset); +} + +void GraphicsContext::setPlatformStrokeColor(const Color& c, ColorSpace) +{ + if (paintingDisabled()) + return; + platformContext()->setStrokeColor(c); +} + +void GraphicsContext::setPlatformStrokeThickness(float f) +{ + if (paintingDisabled()) + return; + platformContext()->setStrokeThickness(f); +} + +void GraphicsContext::setPlatformStrokeStyle(StrokeStyle style) +{ + if (paintingDisabled()) + return; + platformContext()->setStrokeStyle(style); +} + +void GraphicsContext::setPlatformFillColor(const Color& c, ColorSpace) +{ + if (paintingDisabled()) + return; + platformContext()->setFillColor(c); +} + +void GraphicsContext::setPlatformShadow(const FloatSize& size, float blur, const Color& color, ColorSpace) +{ + if (paintingDisabled()) + return; + + if (blur <= 0) + this->clearPlatformShadow(); + + SkColor c; + if (color.isValid()) + c = color.rgb(); + else + c = SkColorSetARGB(0xFF / 3, 0, 0, 0); // "std" Apple shadow color + platformContext()->setShadow(blur, size.width(), size.height(), c); +} + +void GraphicsContext::clearPlatformShadow() +{ + if (paintingDisabled()) + return; + + platformContext()->setShadow(0, 0, 0, 0); +} + +/////////////////////////////////////////////////////////////////////////////// + +void GraphicsContext::drawFocusRing(const Vector& rects, int width, int offset, const Color& color) +{ + if (paintingDisabled()) + return; + + platformContext()->drawFocusRing(rects, width, offset, color); +} + +void GraphicsContext::drawFocusRing(const Path&, int, int, const Color&) +{ + // Do nothing, since we draw the focus ring independently. +} + +PlatformGraphicsContext* GraphicsContext::platformContext() const +{ + ASSERT(!paintingDisabled()); + return m_data->context(); +} + +void GraphicsContext::setMiterLimit(float limit) +{ + if (paintingDisabled()) + return; + platformContext()->setMiterLimit(limit); +} + +void GraphicsContext::setAlpha(float alpha) +{ + if (paintingDisabled()) + return; + platformContext()->setAlpha(alpha); +} + +void GraphicsContext::setPlatformCompositeOperation(CompositeOperator op) +{ + if (paintingDisabled()) + return; + platformContext()->setCompositeOperation(op); +} + +void GraphicsContext::clearRect(const FloatRect& rect) +{ + if (paintingDisabled()) + return; + + platformContext()->clearRect(rect); +} + +void GraphicsContext::strokeRect(const FloatRect& rect, float lineWidth) +{ + if (paintingDisabled()) + return; + + platformContext()->strokeRect(rect, lineWidth); +} + +void GraphicsContext::setLineCap(LineCap cap) +{ + if (paintingDisabled()) + return; + platformContext()->setLineCap(cap); +} + +#if ENABLE(SVG) +void GraphicsContext::setLineDash(const DashArray& dashes, float dashOffset) +{ + if (paintingDisabled()) + return; + + platformContext()->setLineDash(dashes, dashOffset); +} +#endif + +void GraphicsContext::setLineJoin(LineJoin join) +{ + if (paintingDisabled()) + return; + platformContext()->setLineJoin(join); +} + +void GraphicsContext::scale(const FloatSize& size) +{ + if (paintingDisabled()) + return; + platformContext()->scale(size); +} + +void GraphicsContext::rotate(float angleInRadians) +{ + if (paintingDisabled()) + return; + platformContext()->rotate(angleInRadians); +} + +void GraphicsContext::translate(float x, float y) +{ + if (paintingDisabled()) + return; + platformContext()->translate(x, y); +} + +void GraphicsContext::concatCTM(const AffineTransform& affine) +{ + if (paintingDisabled()) + return; + platformContext()->concatCTM(affine); +} + +// This is intended to round the rect to device pixels (through the CTM) +// and then invert the result back into source space, with the hope that when +// it is drawn (through the matrix), it will land in the "right" place (i.e. +// on pixel boundaries). + +// For android, we record this geometry once and then draw it though various +// scale factors as the user zooms, without re-recording. Thus this routine +// should just leave the original geometry alone. + +// If we instead draw into bitmap tiles, we should then perform this +// transform -> round -> inverse step. + +FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& rect, RoundingMode) +{ + return rect; +} + +////////////////////////////////////////////////////////////////////////////////////////////////// + +void GraphicsContext::setURLForRect(const KURL& link, const IntRect& destRect) +{ +// Appears to be PDF specific, so we ignore it +} + +void GraphicsContext::setPlatformShouldAntialias(bool useAA) +{ + if (paintingDisabled()) + return; + platformContext()->setShouldAntialias(useAA); +} + +void GraphicsContext::setPlatformFillGradient(Gradient* fillGradient) +{ + if (paintingDisabled()) + return; + SkShader* shader = extractShader(0, fillGradient); + platformContext()->setFillShader(shader); +} + +void GraphicsContext::setPlatformFillPattern(Pattern* fillPattern) +{ + if (paintingDisabled()) + return; + SkShader* shader = extractShader(fillPattern, 0); + platformContext()->setFillShader(shader); +} + +void GraphicsContext::setPlatformStrokeGradient(Gradient* strokeGradient) +{ + if (paintingDisabled()) + return; + SkShader* shader = extractShader(0, strokeGradient); + platformContext()->setStrokeShader(shader); +} + +void GraphicsContext::setPlatformStrokePattern(Pattern* strokePattern) +{ + if (paintingDisabled()) + return; + SkShader* shader = extractShader(strokePattern, 0); + platformContext()->setStrokeShader(shader); +} + +AffineTransform GraphicsContext::getCTM() const +{ + if (paintingDisabled()) + return AffineTransform(); + const SkMatrix& m = platformContext()->getTotalMatrix(); + return AffineTransform(SkScalarToDouble(m.getScaleX()), // a + SkScalarToDouble(m.getSkewY()), // b + SkScalarToDouble(m.getSkewX()), // c + SkScalarToDouble(m.getScaleY()), // d + SkScalarToDouble(m.getTranslateX()), // e + SkScalarToDouble(m.getTranslateY())); // f +} + +void GraphicsContext::setCTM(const AffineTransform& transform) +{ + // The SkPicture mode of Skia does not support SkCanvas::setMatrix(), so we + // can not simply use that method here. We could calculate the transform + // required to achieve the desired matrix and use SkCanvas::concat(), but + // there's currently no need for this. + ASSERT_NOT_REACHED(); +} + +/////////////////////////////////////////////////////////////////////////////// + +void GraphicsContext::fillPath(const Path& pathToFill) +{ + if (paintingDisabled()) + return; + + platformContext()->fillPath(pathToFill, fillRule()); +} + +void GraphicsContext::strokePath(const Path& pathToStroke) +{ + if (paintingDisabled()) + return; + + platformContext()->strokePath(pathToStroke); +} + +InterpolationQuality GraphicsContext::imageInterpolationQuality() const +{ + notImplemented(); + return InterpolationDefault; +} + +void GraphicsContext::setImageInterpolationQuality(InterpolationQuality mode) +{ +#if 0 + enum InterpolationQuality { + InterpolationDefault, + InterpolationNone, + InterpolationLow, + InterpolationMedium, + InterpolationHigh + }; +#endif + // TODO: record this, so we can know when to use bitmap-filtering when we draw + // ... not sure how meaningful this will be given our playback model. + + // Certainly safe to do nothing for the present. +} + +void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint*, + bool antialias) +{ + if (paintingDisabled()) + return; + + if (numPoints <= 1) + return; + + // FIXME: IMPLEMENT! +} + +void GraphicsContext::drawHighlightForText(const Font& font, const TextRun& run, + const FloatPoint& point, int h, + const Color& backgroundColor, + ColorSpace colorSpace, int from, + int to, bool isActive) +{ + if (paintingDisabled()) + return; + + platformContext()->drawHighlightForText(font, run, point, h, backgroundColor, + colorSpace, from, to, isActive); +} + +} // namespace WebCore + +/////////////////////////////////////////////////////////////////////////////// + +SkCanvas* android_gc2canvas(WebCore::GraphicsContext* gc) +{ + 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 +#include + +#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 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 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 + +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& 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 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& 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& 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& 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& 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 #include +#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(); /* -- cgit v1.1