summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbrettw@google.com <brettw@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-10-31 03:49:49 +0000
committerbrettw@google.com <brettw@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-10-31 03:49:49 +0000
commit99c72200c2aa50f3d1befea0a7b357c31eb429cf (patch)
tree88ef1391af913990363734f08ca0194493505a67
parenta5e2f667cecad6a1eea2b0ac51498d322b57db3d (diff)
downloadchromium_src-99c72200c2aa50f3d1befea0a7b357c31eb429cf.zip
chromium_src-99c72200c2aa50f3d1befea0a7b357c31eb429cf.tar.gz
chromium_src-99c72200c2aa50f3d1befea0a7b357c31eb429cf.tar.bz2
Make ImageBuffer creation and handling conform to proper WebKit form rather than using tacked-on functions on GraphicsContext. Clean up the associated GraphicsContext objects.
Merge SkGraphicsContext, SkPaintContext, and PlatformContextSkia into one class, PlatformContextSkia. This tries to change no code related to this, the code in PlatformContextSkia is just a concatenation of those existing files, and hopefully doesn't need much review. This file is in the wrong style and is a terrible mess, I will clean it up in successive passes so it can be reviewed reasonably. Review URL: http://codereview.chromium.org/8754 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@4270 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/renderer/render_view.cc5
-rw-r--r--webkit/build/port/port.vcproj16
-rw-r--r--webkit/glue/webframe.h6
-rw-r--r--webkit/glue/webframe_impl.cc9
-rw-r--r--webkit/glue/webframe_impl.h3
-rw-r--r--webkit/port/platform/graphics/GraphicsContextPlatformPrivate.cpp44
-rw-r--r--webkit/port/platform/graphics/GraphicsContextPlatformPrivate.h74
-rw-r--r--webkit/port/platform/graphics/GraphicsContextSkia.cpp248
-rw-r--r--webkit/port/platform/graphics/ImageBufferSkia.cpp36
-rw-r--r--webkit/port/platform/graphics/PlatformContextSkia.cpp676
-rw-r--r--webkit/port/platform/graphics/PlatformContextSkia.h237
-rw-r--r--webkit/port/platform/graphics/SkGraphicsContext.cpp415
-rw-r--r--webkit/port/platform/graphics/SkGraphicsContext.h149
-rw-r--r--webkit/port/platform/graphics/SkPaintContext.cpp344
-rw-r--r--webkit/port/platform/graphics/SkPaintContext.h108
-rw-r--r--webkit/port/platform/graphics/chromium/ImageBufferData.h48
-rw-r--r--webkit/port/platform/graphics/svg/SkiaSupport.cpp11
17 files changed, 1104 insertions, 1325 deletions
diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc
index ce9ccdd..6912e8b 100644
--- a/chrome/renderer/render_view.cc
+++ b/chrome/renderer/render_view.cc
@@ -57,7 +57,7 @@
#include "webkit/glue/weburlrequest.h"
#include "webkit/glue/webview.h"
#include "webkit/glue/plugins/webplugin_delegate_impl.h"
-#include "webkit/port/platform/graphics/PlatformContextSkia.h"
+//#include "webkit/port/platform/graphics/PlatformContextSkia.h"
#include "generated_resources.h"
@@ -550,12 +550,11 @@ void RenderView::PrintPage(const ViewMsg_PrintPage_Params& params,
#else
// 100% GDI based.
gfx::VectorCanvas canvas(hdc, src_size_x, src_size_y);
- PlatformContextSkia context(&canvas);
// Set the clipping region to be sure to not overflow.
SkRect clip_rect;
clip_rect.set(0, 0, SkIntToScalar(src_size_x), SkIntToScalar(src_size_y));
canvas.clipRect(clip_rect);
- if (!frame->SpoolPage(params.page_number, &context)) {
+ if (!frame->SpoolPage(params.page_number, &canvas)) {
NOTREACHED() << "Printing page " << params.page_number << " failed.";
return;
}
diff --git a/webkit/build/port/port.vcproj b/webkit/build/port/port.vcproj
index a4d9f3c..d9bde70 100644
--- a/webkit/build/port/port.vcproj
+++ b/webkit/build/port/port.vcproj
@@ -895,10 +895,6 @@
>
</File>
<File
- RelativePath="..\..\port\platform\graphics\GraphicsContextPlatformPrivate.cpp"
- >
- </File>
- <File
RelativePath="..\..\port\platform\graphics\GraphicsContextPlatformPrivate.h"
>
</File>
@@ -978,14 +974,6 @@
RelativePath="..\..\port\platform\graphics\SkiaUtils.h"
>
</File>
- <File
- RelativePath="..\..\port\platform\graphics\SkPaintContext.cpp"
- >
- </File>
- <File
- RelativePath="..\..\port\platform\graphics\SkPaintContext.h"
- >
- </File>
<Filter
Name="svg"
>
@@ -1034,6 +1022,10 @@
Name="chromium"
>
<File
+ RelativePath="..\..\port\platform\graphics\chromium\ImageBufferData.h"
+ >
+ </File>
+ <File
RelativePath="..\..\port\platform\graphics\chromium\PlatformIcon.h"
>
</File>
diff --git a/webkit/glue/webframe.h b/webkit/glue/webframe.h
index c8d73af..9484d3d 100644
--- a/webkit/glue/webframe.h
+++ b/webkit/glue/webframe.h
@@ -10,6 +10,7 @@
#include "base/basictypes.h"
#include "base/ref_counted.h"
#include "base/gfx/bitmap_platform_device.h"
+#include "base/gfx/platform_canvas.h"
#include "base/gfx/size.h"
#include "webkit/glue/console_message_level.h"
#include "webkit/glue/find_in_page_request.h"
@@ -24,8 +25,8 @@ class WebTextInput;
struct NPObject;
namespace gfx {
-class Size;
class Rect;
+class Size;
}
// TODO(darin): use GURL everywhere a URL string appears
@@ -349,8 +350,7 @@ class WebFrame : public base::RefCounted<WebFrame> {
virtual void GetPageRect(int page, gfx::Rect* page_size) const = 0;
// Prints one page. |page| is 0-based.
- virtual bool SpoolPage(int page,
- PlatformContextSkia* context) = 0;
+ virtual bool SpoolPage(int page, gfx::PlatformCanvas* canvas) = 0;
// Does this frame have an onunload or unbeforeunload event listener?
virtual bool HasUnloadListener() = 0;
diff --git a/webkit/glue/webframe_impl.cc b/webkit/glue/webframe_impl.cc
index eb1d1b4..71181a2 100644
--- a/webkit/glue/webframe_impl.cc
+++ b/webkit/glue/webframe_impl.cc
@@ -1845,11 +1845,9 @@ void WebFrameImpl::GetPageRect(int page, gfx::Rect* page_size) const {
*page_size = webkit_glue::FromIntRect(pages_[page]);
}
-bool WebFrameImpl::SpoolPage(int page,
- PlatformContextSkia* context) {
+bool WebFrameImpl::SpoolPage(int page, gfx::PlatformCanvas* canvas) {
// Ensure correct state.
- if (!context ||
- !printing_ ||
+ if (!printing_ ||
page < 0 ||
page >= static_cast<int>(pages_.size())) {
NOTREACHED();
@@ -1861,7 +1859,8 @@ bool WebFrameImpl::SpoolPage(int page,
return false;
}
- GraphicsContext spool(reinterpret_cast<PlatformGraphicsContext*>(context));
+ PlatformContextSkia context(canvas);
+ GraphicsContext spool(&context);
DCHECK(pages_[page].x() == 0);
// Offset to get the right square.
spool.translate(0, -static_cast<float>(pages_[page].y()));
diff --git a/webkit/glue/webframe_impl.h b/webkit/glue/webframe_impl.h
index 9a8afdb..57b6d39 100644
--- a/webkit/glue/webframe_impl.h
+++ b/webkit/glue/webframe_impl.h
@@ -169,8 +169,7 @@ class WebFrameImpl : public WebFrame {
int* width);
virtual int ComputePageRects(const gfx::Size& page_size_px);
virtual void GetPageRect(int page, gfx::Rect* page_size) const;
- virtual bool SpoolPage(int page,
- PlatformContextSkia* context);
+ virtual bool SpoolPage(int page, gfx::PlatformCanvas* canvas);
// Reformats this frame for printing or for screen display, depending on
// |printing| flag. Acts recursively on inner frames.
diff --git a/webkit/port/platform/graphics/GraphicsContextPlatformPrivate.cpp b/webkit/port/platform/graphics/GraphicsContextPlatformPrivate.cpp
deleted file mode 100644
index 7f28d19..0000000
--- a/webkit/port/platform/graphics/GraphicsContextPlatformPrivate.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
-** Copyright 2006, Google Inc.
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-// Don't include config.h here because there should be no dependency on WebKit
-// at all.
-
-#include "config.h"
-
-#include "GraphicsContext.h"
-#include "GraphicsContextPlatformPrivate.h"
-#include "PlatformContextSkia.h"
-
-namespace WebCore {
-
-GraphicsContextPlatformPrivate::GraphicsContextPlatformPrivate(PlatformContextSkia* pgc)
- : SkPaintContext(pgc ? pgc->canvas() : NULL),
- m_context(pgc),
- m_should_delete(false)
-{
- // Set back-reference.
- if (m_context)
- m_context->setPaintContext(this);
-}
-
-GraphicsContextPlatformPrivate::~GraphicsContextPlatformPrivate()
-{
- if (m_should_delete)
- delete m_context;
-}
-
-}
diff --git a/webkit/port/platform/graphics/GraphicsContextPlatformPrivate.h b/webkit/port/platform/graphics/GraphicsContextPlatformPrivate.h
index 77f5e89..fdd37b9 100644
--- a/webkit/port/platform/graphics/GraphicsContextPlatformPrivate.h
+++ b/webkit/port/platform/graphics/GraphicsContextPlatformPrivate.h
@@ -1,47 +1,53 @@
/*
-** Copyright 2006, Google Inc.
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#include "SkPaintContext.h"
+ * Copyright (C) 2006 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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 APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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 GraphicsContextPlatformPrivate_h
+#define GraphicsContextPlatformPrivate_h
class PlatformContextSkia;
namespace WebCore {
-// This class is the interface to communicate to Skia. It is meant to be as
-// opaque as possible. This class accept Skia native data format and not WebKit
-// format.
-// Every functions assume painting is enabled, callers should check this before
-// calling any member function.
-class GraphicsContextPlatformPrivate : public SkPaintContext {
+// This class just holds onto a PlatformContextSkia for GraphicsContext.
+class GraphicsContextPlatformPrivate {
public:
- GraphicsContextPlatformPrivate(PlatformContextSkia* pgc);
- ~GraphicsContextPlatformPrivate();
+ GraphicsContextPlatformPrivate(PlatformContextSkia* platformContext)
+ : m_context(platformContext) { }
- PlatformContextSkia* platformContext() { return m_context; }
+ PlatformContextSkia* context() { return m_context; }
- void setShouldDelete(bool should_delete) {
- m_should_delete = should_delete;
- }
-
- // TODO(maruel): Eventually GraphicsContext should touch the canvas at all
- // to support serialization.
- using SkPaintContext::canvas;
private:
+ // Non-owning pointer to the PlatformContext.
PlatformContextSkia* m_context;
- bool m_should_delete;
+
+ // We don't support copy or assign.
+ GraphicsContextPlatformPrivate(const GraphicsContextPlatformPrivate& other);
+ GraphicsContextPlatformPrivate& operator=(
+ const GraphicsContextPlatformPrivate& other);
};
-}
+} // namespace WebCore
+
+#endif // GraphicsContextPlatformPrivate_h
diff --git a/webkit/port/platform/graphics/GraphicsContextSkia.cpp b/webkit/port/platform/graphics/GraphicsContextSkia.cpp
index e98dbf8..f842693 100644
--- a/webkit/port/platform/graphics/GraphicsContextSkia.cpp
+++ b/webkit/port/platform/graphics/GraphicsContextSkia.cpp
@@ -172,17 +172,6 @@ void add_corner_arc(SkPath* path, const SkRect& rect, const IntSize& size, int s
path->arcTo(r, SkIntToScalar(startAngle), SkIntToScalar(90), false);
}
-COMPILE_ASSERT(static_cast<int>(GraphicsContextPlatformPrivate::NoStroke) == static_cast<int>(NoStroke), AssertNoStroke);
-COMPILE_ASSERT(static_cast<int>(GraphicsContextPlatformPrivate::SolidStroke) == static_cast<int>(SolidStroke), AssertSolidStroke);
-COMPILE_ASSERT(static_cast<int>(GraphicsContextPlatformPrivate::DottedStroke) == static_cast<int>(DottedStroke), AssertDottedStroke);
-COMPILE_ASSERT(static_cast<int>(GraphicsContextPlatformPrivate::DashedStroke) == static_cast<int>(DashedStroke), AssertDashedStroke);
-
-// Note: Remove this function as soon as StrokeStyle is moved in GraphicsTypes.h.
-GraphicsContextPlatformPrivate::StrokeStyle StrokeStyle2StrokeStyle(StrokeStyle style)
-{
- return static_cast<GraphicsContextPlatformPrivate::StrokeStyle>(style);
-}
-
}
////////////////////////////////////////////////////////////////////////////////////////////////
@@ -193,7 +182,7 @@ GraphicsContext::GraphicsContext(PlatformGraphicsContext *gc)
: m_common(createGraphicsContextPrivate())
, m_data(new GraphicsContextPlatformPrivate(gc))
{
- setPaintingDisabled(!m_data->canvas());
+ setPaintingDisabled(!platformContext()->canvas());
}
GraphicsContext::~GraphicsContext()
@@ -205,13 +194,13 @@ GraphicsContext::~GraphicsContext()
void GraphicsContext::savePlatformState()
{
// Save our private State.
- m_data->save();
+ platformContext()->save();
}
void GraphicsContext::restorePlatformState()
{
// Restore our private State.
- m_data->restore();
+ platformContext()->restore();
}
// Draws a filled rectangle with a stroked border.
@@ -223,10 +212,10 @@ void GraphicsContext::drawRect(const IntRect& rect)
SkRect r = rect;
if (!IsRectReasonable(getCTM(), r)) {
// See the fillRect below.
- ClipRectToCanvas(*m_data->canvas(), r, &r);
+ ClipRectToCanvas(*platformContext()->canvas(), r, &r);
}
- m_data->drawRect(r);
+ platformContext()->drawRect(r);
}
// This is only used to draw borders.
@@ -250,7 +239,7 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
//root, which also won't be exact
SkPoint disp = pts[1] - pts[0];
int length = SkScalarRound(disp.fX + disp.fY);
- int width = m_data->setup_paint_stroke(&paint, 0, length);
+ int width = platformContext()->setup_paint_stroke(&paint, 0, length);
// "borrowed" this comment and idea from GraphicsContextCG.cpp
// For odd widths, we add in 0.5 to the appropriate x/y so that the float arithmetic
@@ -271,7 +260,7 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
pts[1].fY = pts[0].fY;
}
}
- m_data->canvas()->drawPoints(SkCanvas::kLines_PointMode, 2, pts, paint);
+ platformContext()->canvas()->drawPoints(SkCanvas::kLines_PointMode, 2, pts, paint);
}
static void setrect_for_underline(SkRect* r, GraphicsContext* context, const IntPoint& point, int width)
@@ -294,7 +283,7 @@ void GraphicsContext::drawLineForText(const IntPoint& pt, int width, bool printi
setrect_for_underline(&r, this, pt, width);
paint.setColor(this->strokeColor().rgb());
- m_data->canvas()->drawRect(r, paint);
+ platformContext()->canvas()->drawRect(r, paint);
}
void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint& pt,
@@ -371,7 +360,7 @@ void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint& pt,
origin_y,
origin_x + SkIntToScalar(width),
origin_y + SkIntToScalar(misspell_bitmap->height()));
- m_data->canvas()->drawRect(rect, paint);
+ platformContext()->canvas()->drawRect(rect, paint);
}
// This method is only used to draw the little circles used in lists.
@@ -386,13 +375,13 @@ void GraphicsContext::drawEllipse(const IntRect& elipseRect)
SkPaint paint;
if (fillColor().rgb() & 0xFF000000) {
- m_data->setup_paint_fill(&paint);
- m_data->canvas()->drawOval(rect, paint);
+ platformContext()->setup_paint_fill(&paint);
+ platformContext()->canvas()->drawOval(rect, paint);
}
if (strokeStyle() != NoStroke) {
paint.reset();
- m_data->setup_paint_stroke(&paint, &rect, 0);
- m_data->canvas()->drawOval(rect, paint);
+ platformContext()->setup_paint_stroke(&paint, &rect, 0);
+ platformContext()->canvas()->drawOval(rect, paint);
}
}
@@ -416,11 +405,11 @@ void GraphicsContext::strokeArc(const IntRect& r, int startAngle, int angleSpan)
SkRect oval = r;
if (strokeStyle() == NoStroke) {
- m_data->setup_paint_fill(&paint); // we want the fill color
+ platformContext()->setup_paint_fill(&paint); // we want the fill color
paint.setStyle(SkPaint::kStroke_Style);
paint.setStrokeWidth(WebCoreFloatToSkScalar(strokeThickness()));
} else
- m_data->setup_paint_stroke(&paint, NULL, 0);
+ platformContext()->setup_paint_stroke(&paint, NULL, 0);
// we do this before converting to scalar, so we don't overflow SkFixed
startAngle = fast_mod(startAngle, 360);
@@ -430,7 +419,7 @@ void GraphicsContext::strokeArc(const IntRect& r, int startAngle, int angleSpan)
path.addArc(oval, SkIntToScalar(-startAngle), SkIntToScalar(-angleSpan));
if (!IsPathReasonable(getCTM(), path))
return;
- m_data->canvas()->drawPath(path, paint);
+ platformContext()->canvas()->drawPath(path, paint);
}
void GraphicsContext::drawConvexPolygon(size_t numPoints, const FloatPoint* points, bool shouldAntialias)
@@ -453,14 +442,14 @@ void GraphicsContext::drawConvexPolygon(size_t numPoints, const FloatPoint* poin
SkPaint paint;
if (fillColor().rgb() & 0xFF000000) {
- m_data->setup_paint_fill(&paint);
- m_data->canvas()->drawPath(path, paint);
+ platformContext()->setup_paint_fill(&paint);
+ platformContext()->canvas()->drawPath(path, paint);
}
if (strokeStyle() != NoStroke) {
paint.reset();
- m_data->setup_paint_stroke(&paint, NULL, 0);
- m_data->canvas()->drawPath(path, paint);
+ platformContext()->setup_paint_stroke(&paint, NULL, 0);
+ platformContext()->canvas()->drawPath(path, paint);
}
}
@@ -468,7 +457,7 @@ void GraphicsContext::fillPath()
{
if (paintingDisabled())
return;
- const SkPath& path = *m_data->currentPath();
+ const SkPath& path = *platformContext()->currentPath();
if (!IsPathReasonable(getCTM(), path))
return;
@@ -478,11 +467,11 @@ void GraphicsContext::fillPath()
if (colorSpace == SolidColorSpace && !fillColor().alpha())
return;
- m_data->setFillRule(state.fillRule == RULE_EVENODD ?
+ platformContext()->setFillRule(state.fillRule == RULE_EVENODD ?
SkPath::kEvenOdd_FillType : SkPath::kWinding_FillType);
SkPaint paint;
- m_data->setup_paint_fill(&paint);
+ platformContext()->setup_paint_fill(&paint);
if (colorSpace == PatternColorSpace) {
SkShader* pat = state.fillPattern->createPlatformPattern(getCTM());
@@ -491,14 +480,14 @@ void GraphicsContext::fillPath()
} else if (colorSpace == GradientColorSpace)
paint.setShader(state.fillGradient->platformGradient());
- m_data->canvas()->drawPath(path, paint);
+ platformContext()->canvas()->drawPath(path, paint);
}
void GraphicsContext::strokePath()
{
if (paintingDisabled())
return;
- const SkPath& path = *m_data->currentPath();
+ const SkPath& path = *platformContext()->currentPath();
if (!IsPathReasonable(getCTM(), path))
return;
@@ -509,7 +498,7 @@ void GraphicsContext::strokePath()
return;
SkPaint paint;
- m_data->setup_paint_stroke(&paint, NULL, 0);
+ platformContext()->setup_paint_stroke(&paint, NULL, 0);
if (colorSpace == PatternColorSpace) {
SkShader* pat = state.strokePattern->createPlatformPattern(getCTM());
@@ -518,7 +507,7 @@ void GraphicsContext::strokePath()
} else if (colorSpace == GradientColorSpace)
paint.setShader(state.strokeGradient->platformGradient());
- m_data->canvas()->drawPath(path, paint);
+ platformContext()->canvas()->drawPath(path, paint);
}
void GraphicsContext::fillRect(const FloatRect& rect)
@@ -529,7 +518,7 @@ void GraphicsContext::fillRect(const FloatRect& rect)
SkRect r = rect;
if (!IsRectReasonable(getCTM(), r)) {
// See the other version of fillRect below.
- ClipRectToCanvas(*m_data->canvas(), r, &r);
+ ClipRectToCanvas(*platformContext()->canvas(), r, &r);
}
const GraphicsContextState& state = m_common->state;
@@ -539,7 +528,7 @@ void GraphicsContext::fillRect(const FloatRect& rect)
return;
SkPaint paint;
- m_data->setup_paint_fill(&paint);
+ platformContext()->setup_paint_fill(&paint);
if (colorSpace == PatternColorSpace) {
SkShader* pat = state.fillPattern->createPlatformPattern(getCTM());
@@ -548,7 +537,7 @@ void GraphicsContext::fillRect(const FloatRect& rect)
} else if (colorSpace == GradientColorSpace)
paint.setShader(state.fillGradient->platformGradient());
- m_data->canvas()->drawRect(r, paint);
+ platformContext()->canvas()->drawRect(r, paint);
}
void GraphicsContext::strokeRect(const FloatRect& rect, float lineWidth)
@@ -565,7 +554,7 @@ void GraphicsContext::strokeRect(const FloatRect& rect, float lineWidth)
return;
SkPaint paint;
- m_data->setup_paint_stroke(&paint, NULL, 0);
+ platformContext()->setup_paint_stroke(&paint, NULL, 0);
paint.setStrokeWidth(WebCoreFloatToSkScalar(lineWidth));
if (colorSpace == PatternColorSpace) {
@@ -575,60 +564,7 @@ void GraphicsContext::strokeRect(const FloatRect& rect, float lineWidth)
} else if (colorSpace == GradientColorSpace)
paint.setShader(state.strokeGradient->platformGradient());
- m_data->canvas()->drawRect(rect, paint);
-}
-
-GraphicsContext* GraphicsContext::createOffscreenContext(int width, int height)
-{
- gfx::PlatformCanvas* canvas = new gfx::PlatformCanvas(width, height, false);
- PlatformContextSkia* pgc = new PlatformContextSkia(canvas);
- canvas->drawARGB(0, 0, 0, 0, SkPorterDuff::kClear_Mode);
-
- // Ensure that the PlatformContextSkia deletes the PlatformCanvas.
- pgc->setShouldDelete(true);
-
- GraphicsContext* gc =
- new GraphicsContext(reinterpret_cast<PlatformGraphicsContext*>(pgc));
-
- // Ensure that the GraphicsContext deletes the PlatformContextSkia.
- gc->setShouldDelete(true);
-
- // The caller is responsible for deleting this pointer.
- return gc;
-}
-
-void GraphicsContext::drawOffscreenContext(GraphicsContext* ctx, const FloatRect* srcRect, const FloatRect& dstRect)
-{
- if (paintingDisabled() || ctx->paintingDisabled())
- return;
-
- SkIRect src;
- if (srcRect) {
- src = enclosingIntRect(*srcRect);
- if (!IsRectReasonable(getCTM(), *srcRect))
- return;
- }
- SkRect dst = dstRect;
- if (!IsRectReasonable(getCTM(), dst))
- return;
-
- SkPaint paint;
- paint.setFilterBitmap(true);
-
- const SkBitmap& bm = ctx->m_data->canvas()->getDevice()->accessBitmap(false);
- m_data->canvas()->drawBitmapRect(bm,
- srcRect ? &src : NULL,
- dst,
- &paint);
-}
-
-FloatRect GraphicsContext::getClipLocalBounds() const
-{
- SkRect r;
- if (!m_data->canvas()->getClipBounds(&r))
- r.setEmpty();
-
- return r;
+ platformContext()->canvas()->drawRect(rect, paint);
}
FloatRect GraphicsContext::getBoundingBoxForCurrentPath(bool includeStroke) const
@@ -637,10 +573,10 @@ FloatRect GraphicsContext::getBoundingBoxForCurrentPath(bool includeStroke) cons
if (includeStroke) {
SkPaint paint;
- m_data->setup_paint_stroke(&paint, NULL, 0);
- paint.getFillPath(*m_data->currentPath(), &boundingPath);
+ platformContext()->setup_paint_stroke(&paint, NULL, 0);
+ paint.getFillPath(*platformContext()->currentPath(), &boundingPath);
} else
- boundingPath = *m_data->currentPath();
+ boundingPath = *platformContext()->currentPath();
SkRect r;
boundingPath.computeBounds(&r, SkPath::kExact_BoundsType);
@@ -652,7 +588,7 @@ FloatRect GraphicsContext::getBoundingBoxForCurrentPath(bool includeStroke) cons
bool GraphicsContext::strokeContains(const Path& path, const FloatPoint& point) const
{
SkPaint paint;
- m_data->setup_paint_stroke(&paint, NULL, 0);
+ platformContext()->setup_paint_stroke(&paint, NULL, 0);
SkPath strokePath;
paint.getFillPath(*path.platformPath(), &strokePath);
@@ -678,13 +614,13 @@ void GraphicsContext::fillRect(const FloatRect& rect, const Color& color)
// will prevent overflow. The rectangle will be transformed to the
// canvas' coordinate space before it is converted to fixed point
// so we are guaranteed not to overflow after doing this.
- ClipRectToCanvas(*m_data->canvas(), r, &r);
+ ClipRectToCanvas(*platformContext()->canvas(), r, &r);
}
SkPaint paint;
- m_data->setup_paint_common(&paint);
+ platformContext()->setup_paint_common(&paint);
paint.setColor(color.rgb());
- m_data->canvas()->drawRect(r, paint);
+ platformContext()->canvas()->drawRect(r, paint);
}
}
@@ -697,7 +633,7 @@ void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLef
SkRect r = rect;
if (!IsRectReasonable(getCTM(), r)) {
// See fillRect().
- ClipRectToCanvas(*m_data->canvas(), r, &r);
+ ClipRectToCanvas(*platformContext()->canvas(), r, &r);
}
SkPath path;
@@ -707,8 +643,8 @@ void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLef
add_corner_arc(&path, r, topLeft, 180);
SkPaint paint;
- m_data->setup_paint_fill(&paint);
- m_data->canvas()->drawPath(path, paint);
+ platformContext()->setup_paint_fill(&paint);
+ platformContext()->canvas()->drawPath(path, paint);
return fillRect(rect, color);
}
@@ -721,7 +657,7 @@ void GraphicsContext::clip(const FloatRect& rect)
if (!IsRectReasonable(getCTM(), r))
return;
- m_data->canvas()->clipRect(r);
+ platformContext()->canvas()->clipRect(r);
}
void GraphicsContext::clip(const Path& path)
@@ -733,7 +669,7 @@ void GraphicsContext::clip(const Path& path)
if (!IsPathReasonable(getCTM(), p))
return;
- m_data->canvas()->clipPath(p);
+ platformContext()->canvas()->clipPath(p);
}
void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness)
@@ -752,7 +688,7 @@ void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness
r.inset(SkIntToScalar(thickness) ,SkIntToScalar(thickness));
path.addOval(r, SkPath::kCCW_Direction);
}
- m_data->canvas()->clipPath(path);
+ platformContext()->canvas()->clipPath(path);
}
@@ -765,7 +701,7 @@ void GraphicsContext::clipOut(const IntRect& rect)
if (!IsRectReasonable(getCTM(), r))
return;
- m_data->canvas()->clipRect(r, SkRegion::kDifference_Op);
+ platformContext()->canvas()->clipRect(r, SkRegion::kDifference_Op);
}
void GraphicsContext::clipOutEllipseInRect(const IntRect& rect)
@@ -779,7 +715,7 @@ void GraphicsContext::clipOutEllipseInRect(const IntRect& rect)
SkPath path;
path.addOval(oval, SkPath::kCCW_Direction);
- m_data->canvas()->clipPath(path, SkRegion::kDifference_Op);
+ platformContext()->canvas()->clipPath(path, SkRegion::kDifference_Op);
}
void GraphicsContext::clipOut(const Path& p)
@@ -791,7 +727,7 @@ void GraphicsContext::clipOut(const Path& p)
if (!IsPathReasonable(getCTM(), path))
return;
- m_data->canvas()->clipPath(path, SkRegion::kDifference_Op);
+ platformContext()->canvas()->clipPath(path, SkRegion::kDifference_Op);
}
void GraphicsContext::beginTransparencyLayer(float opacity)
@@ -803,7 +739,7 @@ void GraphicsContext::beginTransparencyLayer(float opacity)
// (the surface of the page) but layers on top may have transparent parts.
// Without explicitly setting the alpha flag, the layer will inherit the
// opaque setting of the base and some things won't work properly.
- m_data->canvas()->saveLayerAlpha(
+ platformContext()->canvas()->saveLayerAlpha(
NULL,
static_cast<unsigned char>(opacity * 255),
static_cast<SkCanvas::SaveFlags>(SkCanvas::kHasAlphaLayer_SaveFlag |
@@ -816,14 +752,14 @@ void GraphicsContext::endTransparencyLayer()
return;
#if PLATFORM(WIN_OS)
- m_data->canvas()->getTopPlatformDevice().fixupAlphaBeforeCompositing();
+ platformContext()->canvas()->getTopPlatformDevice().fixupAlphaBeforeCompositing();
#endif
- m_data->canvas()->restore();
+ platformContext()->canvas()->restore();
}
void GraphicsContext::setPlatformStrokeStyle(const StrokeStyle& stroke)
{
- m_data->setStrokeStyle(StrokeStyle2StrokeStyle(stroke));
+ platformContext()->setStrokeStyle(stroke);
}
void GraphicsContext::setPlatformShadow(const IntSize& size, int blur, const Color& color)
@@ -843,14 +779,14 @@ void GraphicsContext::setPlatformShadow(const IntSize& size, int blur, const Col
SkIntToScalar(size.width()),
SkIntToScalar(size.height()),
c);
- m_data->setDrawLooper(dl)->unref();
+ platformContext()->setDrawLooper(dl)->unref();
} else
- m_data->setDrawLooper(NULL);
+ platformContext()->setDrawLooper(NULL);
}
void GraphicsContext::clearPlatformShadow()
{
- m_data->setDrawLooper(NULL);
+ platformContext()->setDrawLooper(NULL);
}
void GraphicsContext::drawFocusRing(const Color& color)
@@ -879,28 +815,28 @@ void GraphicsContext::drawFocusRing(const Color& color)
paint.setStrokeWidth(exterior_offset * 2);
paint.setPathEffect(new SkCornerPathEffect(exterior_offset * 2))->unref();
exterior_region.getBoundaryPath(&path);
- m_data->canvas()->drawPath(path, paint);
+ platformContext()->canvas()->drawPath(path, paint);
}
PlatformGraphicsContext* GraphicsContext::platformContext() const
{
ASSERT(!paintingDisabled());
- return reinterpret_cast<PlatformGraphicsContext*>(m_data->platformContext());
+ return m_data->context();
}
void GraphicsContext::setMiterLimit(float limit)
{
- m_data->setMiterLimit(limit);
+ platformContext()->setMiterLimit(limit);
}
void GraphicsContext::setAlpha(float alpha)
{
- m_data->setAlpha(alpha);
+ platformContext()->setAlpha(alpha);
}
void GraphicsContext::setCompositeOperation(CompositeOperator op)
{
- m_data->setPorterDuffMode(WebCoreCompositeToSkiaComposite(op));
+ platformContext()->setPorterDuffMode(WebCoreCompositeToSkiaComposite(op));
}
void GraphicsContext::clearRect(const FloatRect& rect)
@@ -910,25 +846,25 @@ void GraphicsContext::clearRect(const FloatRect& rect)
SkRect r = rect;
if (!IsRectReasonable(getCTM(), r))
- ClipRectToCanvas(*m_data->canvas(), r, &r);
+ ClipRectToCanvas(*platformContext()->canvas(), r, &r);
SkPaint paint;
- m_data->setup_paint_fill(&paint);
+ platformContext()->setup_paint_fill(&paint);
paint.setPorterDuffXfermode(SkPorterDuff::kClear_Mode);
- m_data->canvas()->drawRect(r, paint);
+ platformContext()->canvas()->drawRect(r, paint);
}
void GraphicsContext::setLineCap(LineCap cap)
{
switch (cap) {
case ButtCap:
- m_data->setLineCap(SkPaint::kButt_Cap);
+ platformContext()->setLineCap(SkPaint::kButt_Cap);
break;
case RoundCap:
- m_data->setLineCap(SkPaint::kRound_Cap);
+ platformContext()->setLineCap(SkPaint::kRound_Cap);
break;
case SquareCap:
- m_data->setLineCap(SkPaint::kSquare_Cap);
+ platformContext()->setLineCap(SkPaint::kSquare_Cap);
break;
default:
SkDEBUGF(("GraphicsContext::setLineCap: unknown LineCap %d\n", cap));
@@ -951,7 +887,7 @@ void GraphicsContext::setLineDash(const DashArray& dashes, float dashOffset)
for(unsigned int i = 0; i < count; i++)
intervals[i] = dashes[i % dashLength];
- m_data->setDashPathEffect(new SkDashPathEffect(intervals,
+ platformContext()->setDashPathEffect(new SkDashPathEffect(intervals,
count, dashOffset));
delete[] intervals;
@@ -961,13 +897,13 @@ void GraphicsContext::setLineJoin(LineJoin join)
{
switch (join) {
case MiterJoin:
- m_data->setLineJoin(SkPaint::kMiter_Join);
+ platformContext()->setLineJoin(SkPaint::kMiter_Join);
break;
case RoundJoin:
- m_data->setLineJoin(SkPaint::kRound_Join);
+ platformContext()->setLineJoin(SkPaint::kRound_Join);
break;
case BevelJoin:
- m_data->setLineJoin(SkPaint::kBevel_Join);
+ platformContext()->setLineJoin(SkPaint::kBevel_Join);
break;
default:
SkDEBUGF(("GraphicsContext::setLineJoin: unknown LineJoin %d\n", join));
@@ -979,31 +915,31 @@ void GraphicsContext::scale(const FloatSize& size)
{
if (paintingDisabled())
return;
- m_data->canvas()->scale(WebCoreFloatToSkScalar(size.width()), WebCoreFloatToSkScalar(size.height()));
+ platformContext()->canvas()->scale(WebCoreFloatToSkScalar(size.width()), WebCoreFloatToSkScalar(size.height()));
}
void GraphicsContext::rotate(float angleInRadians)
{
if (paintingDisabled())
return;
- m_data->canvas()->rotate(WebCoreFloatToSkScalar(angleInRadians * (180.0f / 3.14159265f)));
+ platformContext()->canvas()->rotate(WebCoreFloatToSkScalar(angleInRadians * (180.0f / 3.14159265f)));
}
void GraphicsContext::translate(float w, float h)
{
if (paintingDisabled())
return;
- m_data->canvas()->translate(WebCoreFloatToSkScalar(w), WebCoreFloatToSkScalar(h));
+ platformContext()->canvas()->translate(WebCoreFloatToSkScalar(w), WebCoreFloatToSkScalar(h));
}
void GraphicsContext::concatCTM(const AffineTransform& xform)
{
- m_data->canvas()->concat(xform);
+ platformContext()->canvas()->concat(xform);
}
AffineTransform GraphicsContext::getCTM() const
{
- return m_data->canvas()->getTotalMatrix();
+ return platformContext()->canvas()->getTotalMatrix();
}
static inline float square(float n)
@@ -1021,7 +957,7 @@ FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& rect)
// widget. We just need the scale, so we get the affine transform matrix and
// extract the scale.
- const SkMatrix& deviceMatrix = m_data->canvas()->getTotalMatrix();
+ const SkMatrix& deviceMatrix = platformContext()->canvas()->getTotalMatrix();
if (deviceMatrix.isIdentity())
return rect;
@@ -1058,49 +994,39 @@ void GraphicsContext::setURLForRect(const KURL& link, const IntRect& destRect)
void GraphicsContext::setPlatformFillColor(const Color& color)
{
- m_data->setFillColor(color.rgb());
+ platformContext()->setFillColor(color.rgb());
}
-/*
-TODO(brettw): WebKit's implementation of this function moved into the cross-
-platform file GraphicsContext.cpp. We need to figure out how to hook this up
-properly once everything links.
-void GraphicsContext::setPlatformStrokeStyle(const StrokeStyle & strokestyle)
-{
- m_data->setStrokeStyle(StrokeStyle2StrokeStyle(strokestyle));
-}*/
-
void GraphicsContext::setPlatformStrokeColor(const Color& strokecolor)
{
- m_data->setStrokeColor(strokecolor.rgb());
+ platformContext()->setStrokeColor(strokecolor.rgb());
}
void GraphicsContext::setPlatformStrokeThickness(float thickness)
{
- m_data->setStrokeThickness(thickness);
+ platformContext()->setStrokeThickness(thickness);
+}
+
+void GraphicsContext::setPlatformTextDrawingMode(int mode)
+{
+ platformContext()->setTextDrawingMode(mode);
}
void GraphicsContext::addPath(const Path& path)
{
- m_data->addPath(*path.platformPath());
+ platformContext()->addPath(*path.platformPath());
}
void GraphicsContext::beginPath()
{
- m_data->beginPath();
+ platformContext()->beginPath();
}
void GraphicsContext::setUseAntialiasing(bool enable)
{
if (paintingDisabled())
return;
- m_data->setUseAntialiasing(enable);
-}
-
-void GraphicsContext::setShouldDelete(bool should_delete)
-{
- if (m_data)
- m_data->setShouldDelete(should_delete);
+ platformContext()->setUseAntialiasing(enable);
}
// TODO(eseidel): This is needed for image masking and complex text fills
diff --git a/webkit/port/platform/graphics/ImageBufferSkia.cpp b/webkit/port/platform/graphics/ImageBufferSkia.cpp
index 94dac7b..21abf00 100644
--- a/webkit/port/platform/graphics/ImageBufferSkia.cpp
+++ b/webkit/port/platform/graphics/ImageBufferSkia.cpp
@@ -42,9 +42,21 @@ using namespace std;
namespace WebCore {
-auto_ptr<ImageBuffer> ImageBuffer::create(const IntSize& size, bool)
+ImageBufferData::ImageBufferData(const IntSize& size)
+ : m_canvas(size.width(), size.height(), false)
+ , m_platformContext(&m_canvas)
+{
+}
+
+ImageBuffer::ImageBuffer(const IntSize& size, bool grayScale, bool& success)
+ : m_data(size)
+{
+ m_context.set(new GraphicsContext(&m_data.m_platformContext));
+ success = true;
+}
+
+ImageBuffer::~ImageBuffer()
{
- return auto_ptr<ImageBuffer>(new ImageBuffer(size));
}
GraphicsContext* ImageBuffer::context() const
@@ -55,11 +67,8 @@ GraphicsContext* ImageBuffer::context() const
Image* ImageBuffer::image() const
{
if (!m_image) {
- // It's assumed that if image() is called, the actual rendering to
- // the GraphicsContext must be done.
- ASSERT(context());
- const SkBitmap* bitmap = context()->platformContext()->bitmap();
- m_image = BitmapImageSingleFrameSkia::create(*bitmap);
+ m_image = BitmapImageSingleFrameSkia::create(
+ *m_data.m_platformContext.bitmap());
}
return m_image.get();
}
@@ -113,7 +122,7 @@ PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const
destPixel[0] = SkColorGetR(color);
destPixel[1] = SkColorGetG(color);
destPixel[2] = SkColorGetB(color);
- destPixel[3] = SkColorGetA(color);
+ destPixel[3] = SkColorGetA(color);
}
destRow += destBytesPerRow;
}
@@ -176,15 +185,4 @@ String ImageBuffer::toDataURL(const String&) const
return String();
}
-ImageBuffer::ImageBuffer(const IntSize& size) :
- m_data(0),
- m_size(size),
- m_context(GraphicsContext::createOffscreenContext(size.width(), size.height()))
-{
-}
-
-ImageBuffer::~ImageBuffer()
-{
-}
-
} // namespace WebCore
diff --git a/webkit/port/platform/graphics/PlatformContextSkia.cpp b/webkit/port/platform/graphics/PlatformContextSkia.cpp
index 4019578..5bc02d2 100644
--- a/webkit/port/platform/graphics/PlatformContextSkia.cpp
+++ b/webkit/port/platform/graphics/PlatformContextSkia.cpp
@@ -1,5 +1,4 @@
-// Copyright (c) 2008, Google Inc.
-// All rights reserved.
+// Copyright (c) 2008, Google Inc. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
@@ -28,14 +27,683 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "config.h"
-
+#include "GraphicsContext.h"
+#include "NativeImageSkia.h"
#include "PlatformContextSkia.h"
+#undef LOG
+#include "SkiaUtils.h"
+
+#include "base/gfx/image_operations.h"
+#include "base/gfx/native_theme.h"
+#include "base/gfx/platform_canvas.h"
+#include "base/gfx/skia_utils.h"
+
+#include "SkBitmap.h"
+#include "SkColorPriv.h"
+#include "SkShader.h"
+#include "SkDashPathEffect.h"
+
+#if defined(OS_WIN)
+#include <vssym32.h>
+#include "base/gfx/native_theme.h"
+#include "ThemeData.h"
+#include "UniscribeStateTextRun.h"
+#endif
+
+namespace {
+
+int RoundToInt(float x) {
+ // Android uses roundf which VC doesn't have, emulate that function.
+ if (fmodf(x, 1.0f) >= 0.5f)
+ return (int)ceilf(x);
+ return (int)floorf(x);
+}
+
+// Draws the given bitmap to the given canvas. The subset of the source bitmap
+// identified by src_rect is drawn to the given destination rect. The bitmap
+// will be resampled to resample_width * resample_height (this is the size of
+// the whole image, not the subset). See shouldResampleBitmap for more.
+//
+// This does a lot of computation to resample only the portion of the bitmap
+// that will only be drawn. This is critical for performance since when we are
+// scrolling, for example, we are only drawing a small strip of the image.
+// Resampling the whole image every time is very slow, so this speeds up things
+// dramatically.
+void DrawResampledBitmap(SkCanvas& canvas,
+ SkPaint& paint,
+ const NativeImageSkia& bitmap,
+ const SkIRect& src_irect,
+ const SkRect& dest_rect) {
+ // First get the subset we need. This is efficient and does not copy pixels.
+ SkBitmap subset;
+ bitmap.extractSubset(&subset, src_irect);
+ SkRect src_rect;
+ src_rect.set(src_irect);
+
+ // Whether we're doing a subset or using the full source image.
+ bool src_is_full = src_irect.fLeft == 0 && src_irect.fTop == 0 &&
+ src_irect.width() == bitmap.width() &&
+ src_irect.height() == bitmap.height();
+
+ // We will always draw in integer sizes, so round the destination rect.
+ SkIRect dest_rect_rounded;
+ dest_rect.round(&dest_rect_rounded);
+ SkIRect resized_image_rect; // Represents the size of the resized image.
+ resized_image_rect.set(0, 0,
+ dest_rect_rounded.width(), dest_rect_rounded.height());
+
+ if (src_is_full &&
+ bitmap.hasResizedBitmap(dest_rect_rounded.width(),
+ dest_rect_rounded.height())) {
+ // Yay, this bitmap frame already has a resized version appropriate for us.
+ SkBitmap resampled = bitmap.resizedBitmap(dest_rect_rounded.width(),
+ dest_rect_rounded.height());
+ canvas.drawBitmapRect(resampled, NULL, dest_rect, &paint);
+ return;
+ }
+
+ // Compute the visible portion of our rect.
+ SkRect dest_bitmap_subset_sk;
+ ClipRectToCanvas(canvas, dest_rect, &dest_bitmap_subset_sk);
+ dest_bitmap_subset_sk.offset(-dest_rect.fLeft, -dest_rect.fTop);
+
+ // The matrix inverting, etc. could have introduced rounding error which
+ // causes the bounds to be outside of the resized bitmap. We round outward so
+ // we always lean toward it being larger rather than smaller than we need,
+ // and then clamp to the bitmap bounds so we don't get any invalid data.
+ SkIRect dest_bitmap_subset_sk_i;
+ dest_bitmap_subset_sk.roundOut(&dest_bitmap_subset_sk_i);
+ if (!dest_bitmap_subset_sk_i.intersect(resized_image_rect))
+ return; // Resized image does not intersect.
+
+ if (src_is_full && bitmap.shouldCacheResampling(
+ resized_image_rect.width(),
+ resized_image_rect.height(),
+ dest_bitmap_subset_sk_i.width(),
+ dest_bitmap_subset_sk_i.height())) {
+ // We're supposed to resize the entire image and cache it, even though we
+ // don't need all of it.
+ SkBitmap resampled = bitmap.resizedBitmap(dest_rect_rounded.width(),
+ dest_rect_rounded.height());
+ canvas.drawBitmapRect(resampled, NULL, dest_rect, &paint);
+ } else {
+ // We should only resize the exposed part of the bitmap to do the minimal
+ // possible work.
+ gfx::Rect dest_bitmap_subset(dest_bitmap_subset_sk_i.fLeft,
+ dest_bitmap_subset_sk_i.fTop,
+ dest_bitmap_subset_sk_i.width(),
+ dest_bitmap_subset_sk_i.height());
+
+ // Resample the needed part of the image.
+ SkBitmap resampled = gfx::ImageOperations::Resize(subset,
+ gfx::ImageOperations::RESIZE_LANCZOS3,
+ gfx::Size(dest_rect_rounded.width(), dest_rect_rounded.height()),
+ dest_bitmap_subset);
+
+ // Compute where the new bitmap should be drawn. Since our new bitmap may be
+ // smaller than the original, we have to shift it over by the same amount
+ // that we cut off the top and left.
+ SkRect offset_dest_rect = {
+ dest_bitmap_subset.x() + dest_rect.fLeft,
+ dest_bitmap_subset.y() + dest_rect.fTop,
+ dest_bitmap_subset.right() + dest_rect.fLeft,
+ dest_bitmap_subset.bottom() + dest_rect.fTop };
+
+ canvas.drawBitmapRect(resampled, NULL, offset_dest_rect, &paint);
+ }
+}
+
+}
+
+// State -----------------------------------------------------------------------
+
+struct PlatformContextSkia::State {
+ float mMiterLimit;
+ float mAlpha;
+ SkDrawLooper* mLooper;
+ SkPaint::Cap mLineCap;
+ SkPaint::Join mLineJoin;
+ SkPorterDuff::Mode mPorterDuffMode;
+ // Ratio of the length of a dash to its width.
+ int mDashRatio;
+ SkColor mFillColor;
+ WebCore::StrokeStyle mStrokeStyle;
+ SkColor mStrokeColor;
+ float mStrokeThickness;
+ int mTextDrawingMode; // See GraphicsContext.h
+ bool mUseAntialiasing;
+
+ SkDashPathEffect* mDash;
+ SkShader* mGradient;
+ SkShader* mPattern;
+
+ // Note: Keep theses default values in sync with GraphicsContextState.
+ State()
+ : mMiterLimit(4),
+ mAlpha(1),
+ mLooper(NULL),
+ mLineCap(SkPaint::kDefault_Cap),
+ mLineJoin(SkPaint::kDefault_Join),
+ mPorterDuffMode(SkPorterDuff::kSrcOver_Mode),
+ mDashRatio(3),
+ mFillColor(0xFF000000),
+ mStrokeStyle(WebCore::SolidStroke),
+ mStrokeColor(0x0FF000000),
+ mStrokeThickness(0),
+ mTextDrawingMode(WebCore::cTextFill),
+ mUseAntialiasing(true),
+ mDash(NULL),
+ mGradient(NULL),
+ mPattern(NULL) {
+ }
+
+ State(const State& other) {
+ other.mLooper->safeRef();
+ memcpy(this, &other, sizeof(State));
+
+ mDash->safeRef();
+ mGradient->safeRef();
+ mPattern->safeRef();
+ }
+
+ ~State() {
+ mLooper->safeUnref();
+ mDash->safeUnref();
+ mGradient->safeUnref();
+ mPattern->safeUnref();
+ }
+
+ SkDrawLooper* setDrawLooper(SkDrawLooper* dl) {
+ SkRefCnt_SafeAssign(mLooper, dl);
+ return dl;
+ }
+
+ SkColor applyAlpha(SkColor c) const {
+ int s = RoundToInt(mAlpha * 256);
+ if (s >= 256)
+ return c;
+ if (s < 0)
+ return 0;
+
+ int a = SkAlphaMul(SkColorGetA(c), s);
+ return (c & 0x00FFFFFF) | (a << 24);
+ }
+
+ private:
+ // Not supported yet.
+ void operator=(const State&);
+};
PlatformContextSkia::PlatformContextSkia(gfx::PlatformCanvas* canvas)
- : SkGraphicsContext(canvas)
+ : canvas_(canvas)
+ , state_stack_(sizeof(State))
{
+ State* state = reinterpret_cast<State*>(state_stack_.push_back());
+ new (state) State();
+ state_ = state;
}
PlatformContextSkia::~PlatformContextSkia()
{
+ // we force restores so we don't leak any subobjects owned by our
+ // stack of State records.
+ while (state_stack_.count() > 0) {
+ reinterpret_cast<State*>(state_stack_.back())->~State();
+ state_stack_.pop_back();
+ }
+}
+
+
+void PlatformContextSkia::save() {
+ State* newState = reinterpret_cast<State*>(state_stack_.push_back());
+ new (newState) State(*state_);
+ state_ = newState;
+
+ // Save our native canvas.
+ canvas()->save();
+}
+
+void PlatformContextSkia::restore() {
+ // Restore our native canvas.
+ canvas()->restore();
+
+ state_->~State();
+ state_stack_.pop_back();
+
+ state_ = reinterpret_cast<State*>(state_stack_.back());
+}
+
+void PlatformContextSkia::drawRect(SkRect rect) {
+ SkPaint paint;
+ int fillcolor_not_transparent = state_->mFillColor & 0xFF000000;
+ if (fillcolor_not_transparent) {
+ setup_paint_fill(&paint);
+ canvas()->drawRect(rect, paint);
+ }
+
+ if (state_->mStrokeStyle != WebCore::NoStroke &&
+ (state_->mStrokeColor & 0xFF000000)) {
+ if (fillcolor_not_transparent) {
+ // This call is expensive so don't call it unnecessarily.
+ paint.reset();
+ }
+ setup_paint_stroke(&paint, &rect, 0);
+ canvas()->drawRect(rect, paint);
+ }
+}
+
+void PlatformContextSkia::setup_paint_common(SkPaint* paint) const {
+#ifdef SK_DEBUGx
+ {
+ SkPaint defaultPaint;
+ SkASSERT(*paint == defaultPaint);
+ }
+#endif
+
+ paint->setAntiAlias(state_->mUseAntialiasing);
+ paint->setPorterDuffXfermode(state_->mPorterDuffMode);
+ paint->setLooper(state_->mLooper);
+
+ if(state_->mGradient) {
+ paint->setShader(state_->mGradient);
+ } else if (state_->mPattern) {
+ paint->setShader(state_->mPattern);
+ }
+}
+
+void PlatformContextSkia::setup_paint_fill(SkPaint* paint) const {
+ setup_paint_common(paint);
+ paint->setColor(state_->applyAlpha(state_->mFillColor));
+}
+
+int PlatformContextSkia::setup_paint_stroke(SkPaint* paint,
+ SkRect* rect,
+ int length) const {
+ setup_paint_common(paint);
+ float width = state_->mStrokeThickness;
+
+ //this allows dashing and dotting to work properly for hairline strokes
+ if (0 == width)
+ width = 1;
+
+ paint->setColor(state_->applyAlpha(state_->mStrokeColor));
+ paint->setStyle(SkPaint::kStroke_Style);
+ paint->setStrokeWidth(SkFloatToScalar(width));
+ paint->setStrokeCap(state_->mLineCap);
+ paint->setStrokeJoin(state_->mLineJoin);
+ paint->setStrokeMiter(SkFloatToScalar(state_->mMiterLimit));
+
+ if (rect != NULL && (RoundToInt(width) & 1)) {
+ rect->inset(-SK_ScalarHalf, -SK_ScalarHalf);
+ }
+
+ if (state_->mDash) {
+ paint->setPathEffect(state_->mDash);
+ } else {
+ switch (state_->mStrokeStyle) {
+ case WebCore::NoStroke:
+ case WebCore::SolidStroke:
+ break;
+ case WebCore::DashedStroke:
+ width = state_->mDashRatio * width;
+ /* no break */
+ case WebCore::DottedStroke:
+ SkScalar dashLength;
+ if (length) {
+ //determine about how many dashes or dots we should have
+ int numDashes = length/RoundToInt(width);
+ if (!(numDashes & 1))
+ numDashes++; //make it odd so we end on a dash/dot
+ //use the number of dashes to determine the length of a dash/dot, which will be approximately width
+ dashLength = SkScalarDiv(SkIntToScalar(length), SkIntToScalar(numDashes));
+ } else {
+ dashLength = SkFloatToScalar(width);
+ }
+ SkScalar intervals[2] = { dashLength, dashLength };
+ paint->setPathEffect(new SkDashPathEffect(intervals, 2, 0))->unref();
+ }
+ }
+ return RoundToInt(width);
+}
+
+SkDrawLooper* PlatformContextSkia::setDrawLooper(SkDrawLooper* dl) {
+ return state_->setDrawLooper(dl);
+}
+
+void PlatformContextSkia::setMiterLimit(float ml) {
+ state_->mMiterLimit = ml;
+}
+
+void PlatformContextSkia::setAlpha(float alpha) {
+ state_->mAlpha = alpha;
+}
+
+void PlatformContextSkia::setLineCap(SkPaint::Cap lc) {
+ state_->mLineCap = lc;
+}
+
+void PlatformContextSkia::setLineJoin(SkPaint::Join lj) {
+ state_->mLineJoin = lj;
+}
+
+void PlatformContextSkia::setPorterDuffMode(SkPorterDuff::Mode pdm) {
+ state_->mPorterDuffMode = pdm;
+}
+
+void PlatformContextSkia::setFillColor(SkColor color) {
+ state_->mFillColor = color;
+}
+
+WebCore::StrokeStyle PlatformContextSkia::getStrokeStyle() const {
+ return state_->mStrokeStyle;
+}
+
+void PlatformContextSkia::setStrokeStyle(WebCore::StrokeStyle strokestyle) {
+ state_->mStrokeStyle = strokestyle;
+}
+
+void PlatformContextSkia::setStrokeColor(SkColor strokecolor) {
+ state_->mStrokeColor = strokecolor;
+}
+
+float PlatformContextSkia::getStrokeThickness() const {
+ return state_->mStrokeThickness;
+}
+
+void PlatformContextSkia::setStrokeThickness(float thickness) {
+ state_->mStrokeThickness = thickness;
+}
+
+int PlatformContextSkia::getTextDrawingMode() const {
+ return state_->mTextDrawingMode;
+}
+
+void PlatformContextSkia::setTextDrawingMode(int mode) {
+ // cTextClip is never used, so we assert that it isn't set:
+ // https://bugs.webkit.org/show_bug.cgi?id=21898
+ ASSERT((mode & WebCore::cTextClip) == 0);
+ state_->mTextDrawingMode = mode;
+}
+
+void PlatformContextSkia::setUseAntialiasing(bool enable) {
+ state_->mUseAntialiasing = enable;
+}
+
+SkColor PlatformContextSkia::fillColor() const {
+ return state_->mFillColor;
+}
+
+void PlatformContextSkia::beginPath() {
+ path_.reset();
+}
+
+void PlatformContextSkia::addPath(const SkPath& path) {
+ path_.addPath(path);
+}
+
+const SkPath* PlatformContextSkia::currentPath() const {
+ return &path_;
+}
+
+void PlatformContextSkia::setFillRule(SkPath::FillType fr) {
+ path_.setFillType(fr);
+}
+
+void PlatformContextSkia::setGradient(SkShader* gradient) {
+ if (gradient != state_->mGradient) {
+ state_->mGradient->safeUnref();
+ state_->mGradient=gradient;
+ }
+}
+
+void PlatformContextSkia::setPattern(SkShader* pattern) {
+ if (pattern != state_->mPattern) {
+ state_->mPattern->safeUnref();
+ state_->mPattern=pattern;
+ }
+}
+
+void PlatformContextSkia::setDashPathEffect(SkDashPathEffect* dash) {
+ if (dash != state_->mDash) {
+ state_->mDash->safeUnref();
+ state_->mDash=dash;
+ }
+}
+
+const gfx::NativeTheme* PlatformContextSkia::nativeTheme() {
+ return gfx::NativeTheme::instance();
+}
+
+void PlatformContextSkia::paintIcon(HICON icon, const SkIRect& rect) {
+ HDC hdc = canvas_->beginPlatformPaint();
+ DrawIconEx(hdc, rect.fLeft, rect.fTop, icon, rect.width(), rect.height(),
+ 0, 0, DI_NORMAL);
+ canvas_->endPlatformPaint();
+}
+
+// RenderThemeWin.cpp
+void PlatformContextSkia::paintButton(const SkIRect& widgetRect,
+ const ThemeData& themeData) {
+ RECT rect(gfx::SkIRectToRECT(widgetRect));
+ HDC hdc = canvas_->beginPlatformPaint();
+ int state = themeData.m_state;
+ nativeTheme()->PaintButton(hdc,
+ themeData.m_part,
+ state,
+ themeData.m_classicState,
+ &rect);
+ canvas_->endPlatformPaint();
+}
+
+void PlatformContextSkia::paintTextField(const SkIRect& widgetRect,
+ const ThemeData& themeData,
+ SkColor c,
+ bool drawEdges) {
+ RECT rect(gfx::SkIRectToRECT(widgetRect));
+ HDC hdc = canvas_->beginPlatformPaint();
+ nativeTheme()->PaintTextField(hdc,
+ themeData.m_part,
+ themeData.m_state,
+ themeData.m_classicState,
+ &rect,
+ gfx::SkColorToCOLORREF(c),
+ true,
+ drawEdges);
+ canvas_->endPlatformPaint();
+}
+
+void PlatformContextSkia::paintMenuListArrowButton(const SkIRect& widgetRect,
+ unsigned state,
+ unsigned classic_state) {
+ RECT rect(gfx::SkIRectToRECT(widgetRect));
+ HDC hdc = canvas_->beginPlatformPaint();
+ nativeTheme()->PaintMenuList(hdc,
+ CP_DROPDOWNBUTTON,
+ state,
+ classic_state,
+ &rect);
+ canvas_->endPlatformPaint();
+}
+
+void PlatformContextSkia::paintComplexText(UniscribeStateTextRun& state,
+ const SkPoint& point,
+ int from,
+ int to,
+ int ascent) {
+ SkColor color(fillColor());
+ uint8 alpha = SkColorGetA(color);
+ // Skip 100% transparent text; no need to draw anything.
+ if (!alpha)
+ return;
+
+ HDC hdc = canvas_->beginPlatformPaint();
+
+ // TODO(maruel): http://b/700464 SetTextColor doesn't support transparency.
+ // Enforce non-transparent color.
+ color = SkColorSetRGB(SkColorGetR(color),
+ SkColorGetG(color),
+ SkColorGetB(color));
+ SetTextColor(hdc, gfx::SkColorToCOLORREF(color));
+ SetBkMode(hdc, TRANSPARENT);
+
+ // Uniscribe counts the coordinates from the upper left, while WebKit uses
+ // the baseline, so we have to subtract off the ascent.
+ state.Draw(hdc,
+ static_cast<int>(point.fX),
+ static_cast<int>(point.fY - ascent),
+ from,
+ to);
+ canvas_->endPlatformPaint();
+}
+
+bool PlatformContextSkia::paintText(FontHandle hfont,
+ int number_glyph,
+ const uint16* glyphs,
+ const int* advances,
+ const SkPoint& origin) {
+ SkColor color(fillColor());
+ uint8 alpha = SkColorGetA(color);
+ // Skip 100% transparent text; no need to draw anything.
+ if (!alpha)
+ return true;
+
+ bool success = false;
+ HDC hdc = canvas_->beginPlatformPaint();
+ HGDIOBJ old_font = SelectObject(hdc, hfont);
+
+ // TODO(maruel): http://b/700464 SetTextColor doesn't support transparency.
+ // Enforce non-transparent color.
+ color = SkColorSetRGB(SkColorGetR(color),
+ SkColorGetG(color),
+ SkColorGetB(color));
+ SetTextColor(hdc, gfx::SkColorToCOLORREF(color));
+ SetBkMode(hdc, TRANSPARENT);
+
+ // The 'origin' represents the baseline, so we need to move it up to the
+ // top of the bounding square by subtracting the ascent
+ success = !!ExtTextOut(hdc, static_cast<int>(origin.fX),
+ static_cast<int>(origin.fY),
+ ETO_GLYPH_INDEX, NULL,
+ reinterpret_cast<const wchar_t*>(glyphs), number_glyph,
+ advances);
+ SelectObject(hdc, old_font);
+ canvas_->endPlatformPaint();
+ return success;
+}
+
+void PlatformContextSkia::paintSkPaint(const SkRect& rect,
+ const SkPaint& paint) {
+ canvas_->drawRect(rect, paint);
+}
+
+// static
+PlatformContextSkia::ResamplingMode PlatformContextSkia::computeResamplingMode(
+ const NativeImageSkia& bitmap,
+ int src_width, int src_height,
+ float dest_width, float dest_height) {
+ int dest_iwidth = static_cast<int>(dest_width);
+ int dest_iheight = static_cast<int>(dest_height);
+
+ // The percent change below which we will not resample. This usually means
+ // an off-by-one error on the web page, and just doing nearest neighbor
+ // sampling is usually good enough.
+ const float kFractionalChangeThreshold = 0.025f;
+
+ // Images smaller than this in either direction are considered "small" and
+ // are not resampled ever (see below).
+ const int kSmallImageSizeThreshold = 8;
+
+ // The amount an image can be stretched in a single direction before we
+ // say that it is being stretched so much that it must be a line or
+ // background that doesn't need resampling.
+ const float kLargeStretch = 3.0f;
+
+ // Figure out if we should resample this image. We try to prune out some
+ // common cases where resampling won't give us anything, since it is much
+ // slower than drawing stretched.
+ if (src_width == dest_iwidth && src_height == dest_iheight) {
+ // We don't need to resample if the source and destination are the same.
+ return RESAMPLE_NONE;
+ }
+
+ if (src_width <= kSmallImageSizeThreshold ||
+ src_height <= kSmallImageSizeThreshold ||
+ dest_width <= kSmallImageSizeThreshold ||
+ dest_height <= kSmallImageSizeThreshold) {
+ // Never resample small images. These are often used for borders and
+ // rules (think 1x1 images used to make lines).
+ return RESAMPLE_NONE;
+ }
+
+ if (src_height * kLargeStretch <= dest_height ||
+ src_width * kLargeStretch <= dest_width) {
+ // Large image detected.
+
+ // Don't resample if it is being stretched a lot in only one direction.
+ // This is trying to catch cases where somebody has created a border
+ // (which might be large) and then is stretching it to fill some part
+ // of the page.
+ if (src_width == dest_width || src_height == dest_height)
+ return RESAMPLE_NONE;
+
+ // The image is growing a lot and in more than one direction. Resampling
+ // is slow and doesn't give us very much when growing a lot.
+ return RESAMPLE_LINEAR;
+ }
+
+ if ((fabs(dest_width - src_width) / src_width <
+ kFractionalChangeThreshold) &&
+ (fabs(dest_height - src_height) / src_height <
+ kFractionalChangeThreshold)) {
+ // It is disappointingly common on the web for image sizes to be off by
+ // one or two pixels. We don't bother resampling if the size difference
+ // is a small fraction of the original size.
+ return RESAMPLE_NONE;
+ }
+
+ // When the image is not yet done loading, use linear. We don't cache the
+ // partially resampled images, and as they come in incrementally, it causes
+ // us to have to resample the whole thing every time.
+ if (!bitmap.isDataComplete())
+ return RESAMPLE_LINEAR;
+
+ // Everything else gets resampled.
+ return RESAMPLE_AWESOME;
+}
+
+void PlatformContextSkia::paintSkBitmap(const NativeImageSkia& bitmap,
+ const SkIRect& src_rect,
+ const SkRect& dest_rect,
+ const SkPorterDuff::Mode& comp_op) {
+ SkPaint paint;
+ paint.setPorterDuffXfermode(comp_op);
+
+ ResamplingMode resampling = IsPrinting() ? RESAMPLE_NONE :
+ computeResamplingMode(bitmap, src_rect.width(), src_rect.height(),
+ SkScalarToFloat(dest_rect.width()),
+ SkScalarToFloat(dest_rect.height()));
+ if (resampling == RESAMPLE_AWESOME) {
+ paint.setFilterBitmap(false);
+ DrawResampledBitmap(*canvas_, paint, bitmap, src_rect, dest_rect);
+ } else {
+ // No resampling necessary, we can just draw the bitmap.
+ // Note: for serialization, we will want to subset the bitmap first so
+ // we don't send extra pixels.
+ paint.setFilterBitmap(resampling == RESAMPLE_LINEAR);
+ canvas_->drawBitmapRect(bitmap, &src_rect, dest_rect, &paint);
+ }
+}
+
+const SkBitmap* PlatformContextSkia::bitmap() const
+{
+ return &canvas_->getDevice()->accessBitmap(false);
+}
+
+gfx::PlatformCanvas* PlatformContextSkia::canvas() const
+{
+ return canvas_;
+}
+
+bool PlatformContextSkia::IsPrinting() {
+ return canvas_->getTopPlatformDevice().IsVectorial();
}
diff --git a/webkit/port/platform/graphics/PlatformContextSkia.h b/webkit/port/platform/graphics/PlatformContextSkia.h
index c2aee46..e259541 100644
--- a/webkit/port/platform/graphics/PlatformContextSkia.h
+++ b/webkit/port/platform/graphics/PlatformContextSkia.h
@@ -1,35 +1,236 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+// Copyright (c) 2008, Google Inc. All rights reserved.
+//
+// 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.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "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 PlatformContextSkia_h
#define PlatformContextSkia_h
-#include "SkGraphicsContext.h"
+#include "base/gfx/platform_canvas.h"
-namespace WebCore {
-class GraphicsContext;
-class GraphicsContextPlatformPrivate;
-class ScrollView;
+#include "SkDashPathEffect.h"
+#include "SkDrawLooper.h"
+#include "SkDeque.h"
+#include "SkPaint.h"
+#include "SkPath.h"
+
+#include "GraphicsContext.h"
+#include "ThemeData.h"
+
+#if defined(OS_WIN)
+typedef HICON IconHandle;
+typedef HFONT FontHandle;
+#elif defined(OS_LINUX)
+// TODO(erg): Type needs to be defined for half the rest of the stack to
+// compile. When the corresponding implementation to this file gets written,
+// these void pointers need to be replaced with whatever we end up using.
+typedef void* IconHandle;
+typedef void* FontHandle;
+#endif
+
+class UniscribeStateTextRun;
+
+namespace gfx {
+class NativeTheme;
}
-// This class is the "PlatformGraphicsContext" class when running under the
-// Skia/Windows port. Name it PlatformContextSkia until we fix GraphicsContext.h.
-class PlatformContextSkia : public SkGraphicsContext {
- // It initialize the back reference to GraphicsContextPlatformPrivate when the
- // PlatformContextSkia instance is associated with the GraphicsContext.
- friend class WebCore::GraphicsContextPlatformPrivate;
+// This class holds the platform-specific state for GraphicsContext. We put
+// most of our Skia wrappers on this class. In theory, a lot of this stuff could
+// be moved to GraphicsContext directly, except that some code external to this
+// would like to poke at our graphics layer as well (like the Image and Font
+// stuff, which needs some amount of our wrappers and state around SkCanvas).
+//
+// So in general, this class uses just Skia types except when there's no easy
+// conversion. GraphicsContext is responsible for converting the WebKit types to
+// Skia types and setting up the eventual call to the Skia functions.
+//
+// This class then keeps track of all the current Skia state. WebKit expects
+// that the graphics state that is pushed and popped by save() and restore()
+// includes things like colors and pen styles. Skia does this differently, where
+// push and pop only includes transforms and bitmaps, and the application is
+// responsible for managing the painting state which is store in separate
+// SkPaint objects. This class provides the adaptor that allows the painting
+// state to be pushed and popped along with the bitmap.
+class PlatformContextSkia {
public:
+ // Used by computeResamplingMode to tell how bitmaps should be resampled.
+ enum ResamplingMode {
+ // Nearest neighbor resampling. Used when we detect that the page is
+ // trying to make a pattern by stretching a small bitmap very large.
+ RESAMPLE_NONE,
+
+ // Default skia resampling. Used for large growing of images where high
+ // quality resampling doesn't get us very much except a slowdown.
+ RESAMPLE_LINEAR,
+
+ // High quality resampling.
+ RESAMPLE_AWESOME,
+ };
+
// For printing, there shouldn't be any canvas. canvas can be NULL.
PlatformContextSkia(gfx::PlatformCanvas* canvas);
~PlatformContextSkia();
-protected:
- // Make it accessible to friends.
- using SkGraphicsContext::setPaintContext;
+ void save();
+
+ void restore();
+
+ void drawRect(SkRect rect);
+
+ void setup_paint_common(SkPaint* paint) const;
+
+ void setup_paint_fill(SkPaint* paint) const;
+
+ // Sets up the paint for stroking. Returns an int representing the width of
+ // the pen, or 1 if the pen's width is 0 if a non-zero length is provided,
+ // the number of dashes/dots on a dashed/dotted line will be adjusted to
+ // start and end that length with a dash/dot.
+ int setup_paint_stroke(SkPaint* paint, SkRect* rect, int length) const;
+
+ // State proxying functions
+ SkDrawLooper* setDrawLooper(SkDrawLooper* dl);
+ void setMiterLimit(float ml);
+ void setAlpha(float alpha);
+ void setLineCap(SkPaint::Cap lc);
+ void setLineJoin(SkPaint::Join lj);
+ void setFillRule(SkPath::FillType fr);
+ void setPorterDuffMode(SkPorterDuff::Mode pdm);
+ void setFillColor(SkColor color);
+ void setStrokeStyle(WebCore::StrokeStyle strokestyle);
+ void setStrokeColor(SkColor strokecolor);
+ void setStrokeThickness(float thickness);
+ void setTextDrawingMode(int mode);
+ void setUseAntialiasing(bool enable);
+
+ WebCore::StrokeStyle getStrokeStyle() const;
+ float getStrokeThickness() const;
+ int getTextDrawingMode() const;
+
+ void beginPath();
+ void addPath(const SkPath& path);
+ const SkPath* currentPath() const;
+
+ void setGradient(SkShader*);
+ void setPattern(SkShader*);
+ void setDashPathEffect(SkDashPathEffect*);
+
+ SkColor fillColor() const;
+
+ gfx::PlatformCanvas* canvas() {
+ return canvas_;
+ }
+
+ // Gets the default theme.
+ static const gfx::NativeTheme* nativeTheme();
+
+ void paintIcon(IconHandle icon, const SkIRect& rect);
+ // TODO(brettw) these functions should not have to take GraphicsContext
+ // pointers! This is cureently required because our theme drawing code
+ // requires GraphicsContexts, but this class doesn't know about it. This
+ // class's purpose seems no longer necessary, so everything can be moved to
+ // GraphicsContext or ThemeWin, and these parameters can be removed.
+ void paintButton(const SkIRect& widgetRect,
+ const ThemeData& themeData);
+ void paintTextField(const SkIRect& widgetRect,
+ const ThemeData& themeData,
+ SkColor c,
+ bool drawEdges);
+ void paintMenuListArrowButton(const SkIRect& widgetRect,
+ unsigned state,
+ unsigned classic_state);
+ void paintComplexText(UniscribeStateTextRun& state,
+ const SkPoint& point,
+ int from,
+ int to,
+ int ascent);
+
+ // Draws the given glyphs at the given |origin|. |origin| is on the baseline
+ // of the text, and the |ascender_height| must be given for some code paths
+ // since Windows draws text from the upper left.
+ bool paintText(FontHandle hfont,
+ int number_glyph,
+ const uint16* glyphs,
+ const int* advances,
+ const SkPoint& origin);
+
+ // TODO(maruel): I'm still unsure how I will serialize this call.
+ void paintSkPaint(const SkRect& rect, const SkPaint& paint);
+
+ // Draws the given bitmap in the canvas at the location specified in
+ // |dest_rect|. It will be resampled as necessary to fill that rectangle.
+ // The |src_rect| indicates the subset of the bitmap to draw.
+ void paintSkBitmap(const NativeImageSkia& bitmap,
+ const SkIRect& src_rect,
+ const SkRect& dest_rect,
+ const SkPorterDuff::Mode& composite_op);
+
+ // Returns true if the given bitmap subset should be resampled before being
+ // painted into a rectangle of the given size. This is used to indicate
+ // whether bitmap painting should be optimized by not resampling, or given
+ // higher quality by resampling.
+ static ResamplingMode computeResamplingMode(const NativeImageSkia& bitmap,
+ int src_width,
+ int src_height,
+ float dest_width,
+ float dest_height);
+
+ const SkBitmap* bitmap() const;
+
+ // Returns the canvas used for painting, NOT guaranteed to be non-NULL.
+ //
+ // Warning: This function is deprecated so the users are reminded that they
+ // should use this layer of indirection instead of using the canvas
+ // directly. This is to help with the eventual serialization.
+ gfx::PlatformCanvas* canvas() const;
+
+ // Returns if the context is a printing context instead of a display
+ // context. Bitmap shouldn't be resampled when printing to keep the best
+ // possible quality.
+ bool IsPrinting();
private:
+ // Defines drawing style.
+ struct State;
+
+ // NULL indicates painting is disabled. Never delete this object.
+ gfx::PlatformCanvas* canvas_;
+
+ // States stack. Enables local drawing state change with save()/restore()
+ // calls.
+ SkDeque state_stack_;
+ // Pointer to the current drawing state. This is a cached value of
+ // mStateStack.back().
+ State* state_;
+
+ // Current path.
+ SkPath path_;
+
+ // Disallow these.
+ PlatformContextSkia(const PlatformContextSkia&);
+ void operator=(const PlatformContextSkia&);
};
#endif // PlatformContextSkia_h
-
diff --git a/webkit/port/platform/graphics/SkGraphicsContext.cpp b/webkit/port/platform/graphics/SkGraphicsContext.cpp
deleted file mode 100644
index afe5d34..0000000
--- a/webkit/port/platform/graphics/SkGraphicsContext.cpp
+++ /dev/null
@@ -1,415 +0,0 @@
-// Copyright (c) 2008, Google Inc.
-// All rights reserved.
-//
-// 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.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "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 "build/build_config.h"
-#include "SkGraphicsContext.h"
-
-#include "base/gfx/image_operations.h"
-#include "base/gfx/platform_canvas.h"
-#include "base/gfx/skia_utils.h"
-#include "GraphicsContextPlatformPrivate.h"
-#include "NativeImageSkia.h"
-#include "SkBitmap.h"
-
-#if defined(OS_WIN)
-#include <vssym32.h>
-#include "base/gfx/native_theme.h"
-#include "ThemeData.h"
-#include "UniscribeStateTextRun.h"
-#endif
-
-#undef LOG
-#include "SkiaUtils.h"
-
-
-namespace {
-
-// Draws the given bitmap to the given canvas. The subset of the source bitmap
-// identified by src_rect is drawn to the given destination rect. The bitmap
-// will be resampled to resample_width * resample_height (this is the size of
-// the whole image, not the subset). See shouldResampleBitmap for more.
-//
-// This does a lot of computation to resample only the portion of the bitmap
-// that will only be drawn. This is critical for performance since when we are
-// scrolling, for example, we are only drawing a small strip of the image.
-// Resampling the whole image every time is very slow, so this speeds up things
-// dramatically.
-void DrawResampledBitmap(SkCanvas& canvas,
- SkPaint& paint,
- const NativeImageSkia& bitmap,
- const SkIRect& src_irect,
- const SkRect& dest_rect) {
- // First get the subset we need. This is efficient and does not copy pixels.
- SkBitmap subset;
- bitmap.extractSubset(&subset, src_irect);
- SkRect src_rect;
- src_rect.set(src_irect);
-
- // Whether we're doing a subset or using the full source image.
- bool src_is_full = src_irect.fLeft == 0 && src_irect.fTop == 0 &&
- src_irect.width() == bitmap.width() &&
- src_irect.height() == bitmap.height();
-
- // We will always draw in integer sizes, so round the destination rect.
- SkIRect dest_rect_rounded;
- dest_rect.round(&dest_rect_rounded);
- SkIRect resized_image_rect; // Represents the size of the resized image.
- resized_image_rect.set(0, 0,
- dest_rect_rounded.width(), dest_rect_rounded.height());
-
- if (src_is_full &&
- bitmap.hasResizedBitmap(dest_rect_rounded.width(),
- dest_rect_rounded.height())) {
- // Yay, this bitmap frame already has a resized version appropriate for us.
- SkBitmap resampled = bitmap.resizedBitmap(dest_rect_rounded.width(),
- dest_rect_rounded.height());
- canvas.drawBitmapRect(resampled, NULL, dest_rect, &paint);
- return;
- }
-
- // Compute the visible portion of our rect.
- SkRect dest_bitmap_subset_sk;
- ClipRectToCanvas(canvas, dest_rect, &dest_bitmap_subset_sk);
- dest_bitmap_subset_sk.offset(-dest_rect.fLeft, -dest_rect.fTop);
-
- // The matrix inverting, etc. could have introduced rounding error which
- // causes the bounds to be outside of the resized bitmap. We round outward so
- // we always lean toward it being larger rather than smaller than we need,
- // and then clamp to the bitmap bounds so we don't get any invalid data.
- SkIRect dest_bitmap_subset_sk_i;
- dest_bitmap_subset_sk.roundOut(&dest_bitmap_subset_sk_i);
- if (!dest_bitmap_subset_sk_i.intersect(resized_image_rect))
- return; // Resized image does not intersect.
-
- if (src_is_full && bitmap.shouldCacheResampling(
- resized_image_rect.width(),
- resized_image_rect.height(),
- dest_bitmap_subset_sk_i.width(),
- dest_bitmap_subset_sk_i.height())) {
- // We're supposed to resize the entire image and cache it, even though we
- // don't need all of it.
- SkBitmap resampled = bitmap.resizedBitmap(dest_rect_rounded.width(),
- dest_rect_rounded.height());
- canvas.drawBitmapRect(resampled, NULL, dest_rect, &paint);
- } else {
- // We should only resize the exposed part of the bitmap to do the minimal
- // possible work.
- gfx::Rect dest_bitmap_subset(dest_bitmap_subset_sk_i.fLeft,
- dest_bitmap_subset_sk_i.fTop,
- dest_bitmap_subset_sk_i.width(),
- dest_bitmap_subset_sk_i.height());
-
- // Resample the needed part of the image.
- SkBitmap resampled = gfx::ImageOperations::Resize(subset,
- gfx::ImageOperations::RESIZE_LANCZOS3,
- gfx::Size(dest_rect_rounded.width(), dest_rect_rounded.height()),
- dest_bitmap_subset);
-
- // Compute where the new bitmap should be drawn. Since our new bitmap may be
- // smaller than the original, we have to shift it over by the same amount
- // that we cut off the top and left.
- SkRect offset_dest_rect = {
- dest_bitmap_subset.x() + dest_rect.fLeft,
- dest_bitmap_subset.y() + dest_rect.fTop,
- dest_bitmap_subset.right() + dest_rect.fLeft,
- dest_bitmap_subset.bottom() + dest_rect.fTop };
-
- canvas.drawBitmapRect(resampled, NULL, offset_dest_rect, &paint);
- }
-}
-
-} // namespace
-
-
-SkGraphicsContext::SkGraphicsContext(gfx::PlatformCanvas* canvas)
- : paint_context_(NULL),
- canvas_(canvas),
- own_canvas_(false) {
-}
-
-SkGraphicsContext::~SkGraphicsContext() {
- if (own_canvas_)
- delete canvas_;
-}
-
-#if defined(OS_WIN)
-const gfx::NativeTheme* SkGraphicsContext::nativeTheme() {
- return gfx::NativeTheme::instance();
-}
-
-void SkGraphicsContext::paintIcon(HICON icon, const SkIRect& rect) {
- HDC hdc = canvas_->beginPlatformPaint();
- DrawIconEx(hdc, rect.fLeft, rect.fTop, icon, rect.width(), rect.height(),
- 0, 0, DI_NORMAL);
- canvas_->endPlatformPaint();
-}
-
-// RenderThemeWin.cpp
-void SkGraphicsContext::paintButton(const SkIRect& widgetRect,
- const ThemeData& themeData) {
- RECT rect(gfx::SkIRectToRECT(widgetRect));
- HDC hdc = canvas_->beginPlatformPaint();
- int state = themeData.m_state;
- nativeTheme()->PaintButton(hdc,
- themeData.m_part,
- state,
- themeData.m_classicState,
- &rect);
- canvas_->endPlatformPaint();
-}
-
-void SkGraphicsContext::paintTextField(const SkIRect& widgetRect,
- const ThemeData& themeData,
- SkColor c,
- bool drawEdges) {
- RECT rect(gfx::SkIRectToRECT(widgetRect));
- HDC hdc = canvas_->beginPlatformPaint();
- nativeTheme()->PaintTextField(hdc,
- themeData.m_part,
- themeData.m_state,
- themeData.m_classicState,
- &rect,
- gfx::SkColorToCOLORREF(c),
- true,
- drawEdges);
- canvas_->endPlatformPaint();
-}
-
-void SkGraphicsContext::paintMenuListArrowButton(const SkIRect& widgetRect,
- unsigned state,
- unsigned classic_state) {
- RECT rect(gfx::SkIRectToRECT(widgetRect));
- HDC hdc = canvas_->beginPlatformPaint();
- nativeTheme()->PaintMenuList(hdc,
- CP_DROPDOWNBUTTON,
- state,
- classic_state,
- &rect);
- canvas_->endPlatformPaint();
-}
-
-void SkGraphicsContext::paintComplexText(UniscribeStateTextRun& state,
- const SkPoint& point,
- int from,
- int to,
- int ascent) {
- SkColor color(paint_context_->fillColor());
- uint8 alpha = SkColorGetA(color);
- // Skip 100% transparent text; no need to draw anything.
- if (!alpha)
- return;
-
- HDC hdc = canvas_->beginPlatformPaint();
-
- // TODO(maruel): http://b/700464 SetTextColor doesn't support transparency.
- // Enforce non-transparent color.
- color = SkColorSetRGB(SkColorGetR(color),
- SkColorGetG(color),
- SkColorGetB(color));
- SetTextColor(hdc, gfx::SkColorToCOLORREF(color));
- SetBkMode(hdc, TRANSPARENT);
-
- // Uniscribe counts the coordinates from the upper left, while WebKit uses
- // the baseline, so we have to subtract off the ascent.
- state.Draw(hdc,
- static_cast<int>(point.fX),
- static_cast<int>(point.fY - ascent),
- from,
- to);
- canvas_->endPlatformPaint();
-}
-
-bool SkGraphicsContext::paintText(FontHandle hfont,
- int number_glyph,
- const uint16* glyphs,
- const int* advances,
- const SkPoint& origin) {
- SkColor color(paint_context_->fillColor());
- uint8 alpha = SkColorGetA(color);
- // Skip 100% transparent text; no need to draw anything.
- if (!alpha)
- return true;
-
- bool success = false;
- HDC hdc = canvas_->beginPlatformPaint();
- HGDIOBJ old_font = SelectObject(hdc, hfont);
-
- // TODO(maruel): http://b/700464 SetTextColor doesn't support transparency.
- // Enforce non-transparent color.
- color = SkColorSetRGB(SkColorGetR(color),
- SkColorGetG(color),
- SkColorGetB(color));
- SetTextColor(hdc, gfx::SkColorToCOLORREF(color));
- SetBkMode(hdc, TRANSPARENT);
-
- // The 'origin' represents the baseline, so we need to move it up to the
- // top of the bounding square by subtracting the ascent
- success = !!ExtTextOut(hdc, static_cast<int>(origin.fX),
- static_cast<int>(origin.fY),
- ETO_GLYPH_INDEX, NULL,
- reinterpret_cast<const wchar_t*>(glyphs), number_glyph,
- advances);
- SelectObject(hdc, old_font);
- canvas_->endPlatformPaint();
- return success;
-}
-#endif
-
-void SkGraphicsContext::paintSkPaint(const SkRect& rect,
- const SkPaint& paint) {
- canvas_->drawRect(rect, paint);
-}
-
-// static
-SkGraphicsContext::ResamplingMode SkGraphicsContext::computeResamplingMode(
- const NativeImageSkia& bitmap,
- int src_width, int src_height,
- float dest_width, float dest_height) {
- int dest_iwidth = static_cast<int>(dest_width);
- int dest_iheight = static_cast<int>(dest_height);
-
- // The percent change below which we will not resample. This usually means
- // an off-by-one error on the web page, and just doing nearest neighbor
- // sampling is usually good enough.
- const float kFractionalChangeThreshold = 0.025f;
-
- // Images smaller than this in either direction are considered "small" and
- // are not resampled ever (see below).
- const int kSmallImageSizeThreshold = 8;
-
- // The amount an image can be stretched in a single direction before we
- // say that it is being stretched so much that it must be a line or
- // background that doesn't need resampling.
- const float kLargeStretch = 3.0f;
-
- // Figure out if we should resample this image. We try to prune out some
- // common cases where resampling won't give us anything, since it is much
- // slower than drawing stretched.
- if (src_width == dest_iwidth && src_height == dest_iheight) {
- // We don't need to resample if the source and destination are the same.
- return RESAMPLE_NONE;
- }
-
- if (src_width <= kSmallImageSizeThreshold ||
- src_height <= kSmallImageSizeThreshold ||
- dest_width <= kSmallImageSizeThreshold ||
- dest_height <= kSmallImageSizeThreshold) {
- // Never resample small images. These are often used for borders and
- // rules (think 1x1 images used to make lines).
- return RESAMPLE_NONE;
- }
-
- if (src_height * kLargeStretch <= dest_height ||
- src_width * kLargeStretch <= dest_width) {
- // Large image detected.
-
- // Don't resample if it is being stretched a lot in only one direction.
- // This is trying to catch cases where somebody has created a border
- // (which might be large) and then is stretching it to fill some part
- // of the page.
- if (src_width == dest_width || src_height == dest_height)
- return RESAMPLE_NONE;
-
- // The image is growing a lot and in more than one direction. Resampling
- // is slow and doesn't give us very much when growing a lot.
- return RESAMPLE_LINEAR;
- }
-
- if ((fabs(dest_width - src_width) / src_width <
- kFractionalChangeThreshold) &&
- (fabs(dest_height - src_height) / src_height <
- kFractionalChangeThreshold)) {
- // It is disappointingly common on the web for image sizes to be off by
- // one or two pixels. We don't bother resampling if the size difference
- // is a small fraction of the original size.
- return RESAMPLE_NONE;
- }
-
- // When the image is not yet done loading, use linear. We don't cache the
- // partially resampled images, and as they come in incrementally, it causes
- // us to have to resample the whole thing every time.
- if (!bitmap.isDataComplete())
- return RESAMPLE_LINEAR;
-
- // Everything else gets resampled.
- return RESAMPLE_AWESOME;
-}
-
-void SkGraphicsContext::paintSkBitmap(const NativeImageSkia& bitmap,
- const SkIRect& src_rect,
- const SkRect& dest_rect,
- const SkPorterDuff::Mode& comp_op) {
- SkPaint paint;
- paint.setPorterDuffXfermode(comp_op);
-
- ResamplingMode resampling = IsPrinting() ? RESAMPLE_NONE :
- computeResamplingMode(bitmap, src_rect.width(), src_rect.height(),
- SkScalarToFloat(dest_rect.width()),
- SkScalarToFloat(dest_rect.height()));
- if (resampling == RESAMPLE_AWESOME) {
- paint.setFilterBitmap(false);
- DrawResampledBitmap(*canvas_, paint, bitmap, src_rect, dest_rect);
- } else {
- // No resampling necessary, we can just draw the bitmap.
- // Note: for serialization, we will want to subset the bitmap first so
- // we don't send extra pixels.
- paint.setFilterBitmap(resampling == RESAMPLE_LINEAR);
- canvas_->drawBitmapRect(bitmap, &src_rect, dest_rect, &paint);
- }
-}
-
-void SkGraphicsContext::setDashPathEffect(SkDashPathEffect *dash)
-{
- paint_context_->setDashPathEffect(dash);
-}
-
-void SkGraphicsContext::setGradient(SkShader *gradient)
-{
- paint_context_->setGradient(gradient);
-}
-
-void SkGraphicsContext::setPattern(SkShader *pattern)
-{
- paint_context_->setPattern(pattern);
-}
-
-const SkBitmap* SkGraphicsContext::bitmap() const
-{
- return &canvas_->getDevice()->accessBitmap(false);
-}
-
-gfx::PlatformCanvas* SkGraphicsContext::canvas() const
-{
- return canvas_;
-}
-
-bool SkGraphicsContext::IsPrinting() {
- return canvas_->getTopPlatformDevice().IsVectorial();
-}
diff --git a/webkit/port/platform/graphics/SkGraphicsContext.h b/webkit/port/platform/graphics/SkGraphicsContext.h
deleted file mode 100644
index 1c89ed0..0000000
--- a/webkit/port/platform/graphics/SkGraphicsContext.h
+++ /dev/null
@@ -1,149 +0,0 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SkGraphicsContext_h
-#define SkGraphicsContext_h
-
-#include "base/basictypes.h"
-#include "base/gfx/platform_canvas.h"
-#include "SkPorterDuff.h"
-
-class NativeImageSkia;
-struct SkIRect;
-struct SkPoint;
-struct SkRect;
-struct ThemeData;
-class SkBitmap;
-class SkCanvas;
-class SkPaint;
-class SkPaintContext;
-class SkDashPathEffect;
-class SkShader;
-class UniscribeStateTextRun;
-
-namespace gfx {
-class NativeTheme;
-}
-
-#if defined(OS_WIN)
-typedef HICON IconHandle;
-typedef HFONT FontHandle;
-#elif defined(OS_MACOSX)
-typedef CGImageRef IconHandle;
-typedef CTFontRef FontHandle;
-#elif defined(OS_LINUX)
-// TODO(erg): Type needs to be defined for half the rest of the stack to
-// compile. When the corresponding implementation to this file gets written,
-// these void pointers need to be replaced with whatever we end up using.
-typedef void* IconHandle;
-typedef void* FontHandle;
-#endif
-
-class SkGraphicsContext {
- public:
- // Used by computeResamplingMode to indicate how bitmaps should be resampled.
- enum ResamplingMode {
- // Nearest neighbor resampling. Used when we detect that the page is trying
- // to make a pattern by stretching a small bitmap very large.
- RESAMPLE_NONE,
-
- // Default skia resampling. Used for large growing of images where high
- // quality resampling doesn't get us very much except a slowdown.
- RESAMPLE_LINEAR,
-
- // High quality resampling.
- RESAMPLE_AWESOME,
- };
-
- SkGraphicsContext(gfx::PlatformCanvas* canvas);
- ~SkGraphicsContext();
-
- // Gets the default theme.
- static const gfx::NativeTheme* nativeTheme();
-
- void paintIcon(IconHandle icon, const SkIRect& rect);
- void paintButton(const SkIRect& widgetRect,
- const ThemeData& themeData);
- void paintTextField(const SkIRect& widgetRect,
- const ThemeData& themeData,
- SkColor c,
- bool drawEdges);
- void paintMenuListArrowButton(const SkIRect& widgetRect,
- unsigned state,
- unsigned classic_state);
- void paintComplexText(UniscribeStateTextRun& state,
- const SkPoint& point,
- int from,
- int to,
- int ascent);
- bool paintText(FontHandle hfont,
- int number_glyph,
- const uint16* glyphs,
- const int* advances,
- const SkPoint& origin);
-
- // TODO(maruel): I'm still unsure how I will serialize this call.
- void paintSkPaint(const SkRect& rect, const SkPaint& paint);
-
- // Draws the given bitmap in the canvas at the location specified in
- // |dest_rect|. It will be resampled as necessary to fill that rectangle. The
- // |src_rect| indicates the subset of the bitmap to draw.
- void paintSkBitmap(const NativeImageSkia& bitmap,
- const SkIRect& src_rect,
- const SkRect& dest_rect,
- const SkPorterDuff::Mode& composite_op);
-
- // Returns true if the given bitmap subset should be resampled before being
- // painted into a rectangle of the given size. This is used to indicate
- // whether bitmap painting should be optimized by not resampling, or given
- // higher quality by resampling.
- static ResamplingMode computeResamplingMode(const NativeImageSkia& bitmap,
- int src_width,
- int src_height,
- float dest_width,
- float dest_height);
-
- void setShouldDelete(bool should_delete) {
- own_canvas_ = should_delete;
- }
-
- void setDashPathEffect(SkDashPathEffect* dash);
- void setGradient(SkShader* gradient);
- void setPattern(SkShader* gradient);
-
- const SkBitmap* bitmap() const;
-
- // Returns the canvas used for painting, NOT guaranteed to be non-NULL.
- //
- // Warning: This function is deprecated so the users are reminded that they
- // should use this layer of indirection instead of using the canvas directly.
- // This is to help with the eventual serialization.
- gfx::PlatformCanvas* canvas() const;
-
- // Returns if the context is a printing context instead of a display context.
- // Bitmap shouldn't be resampled when printing to keep the best possible
- // quality.
- bool IsPrinting();
-
- protected:
- void setPaintContext(SkPaintContext* context) {
- paint_context_ = context;
- }
-
- private:
- // Keep the painting state.
- SkPaintContext* paint_context_;
-
- // Can be NULL when serializing.
- gfx::PlatformCanvas* canvas_;
-
- // Signal that we own the canvas and must delete it on destruction.
- bool own_canvas_;
-
- // Disallow these.
- SkGraphicsContext(const SkGraphicsContext&);
- void operator=(const SkGraphicsContext&);
-};
-
-#endif // SkGraphicsContext_h
diff --git a/webkit/port/platform/graphics/SkPaintContext.cpp b/webkit/port/platform/graphics/SkPaintContext.cpp
deleted file mode 100644
index 53b165e..0000000
--- a/webkit/port/platform/graphics/SkPaintContext.cpp
+++ /dev/null
@@ -1,344 +0,0 @@
-// Copyright (c) 2008, Google Inc.
-// All rights reserved.
-//
-// 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.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "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 "SkPaintContext.h"
-
-#include "SkColorPriv.h"
-#include "SkShader.h"
-#include "SkDashPathEffect.h"
-
-namespace {
-
-int RoundToInt(float x) {
- // Android uses roundf which VC doesn't have, emulate that function.
- if (fmodf(x, 1.0f) >= 0.5f)
- return (int)ceilf(x);
- return (int)floorf(x);
-}
-
-}
-
-/* TODO / questions
-
- mAlpha: how does this interact with the alpha in Color? multiply them together?
- mPorterDuffMode: do I always respect this? If so, then
- the rgb() & 0xFF000000 check will abort drawing too often
- Is Color premultiplied or not? If it is, then I can't blindly pass it to paint.setColor()
-*/
-struct SkPaintContext::State {
- float mMiterLimit;
- float mAlpha;
- SkDrawLooper* mLooper;
- SkPaint::Cap mLineCap;
- SkPaint::Join mLineJoin;
- SkPorterDuff::Mode mPorterDuffMode;
- // Ratio of the length of a dash to its width.
- int mDashRatio;
- SkColor mFillColor;
- StrokeStyle mStrokeStyle;
- SkColor mStrokeColor;
- float mStrokeThickness;
- bool mUseAntialiasing;
-
- SkDashPathEffect* mDash;
- SkShader* mGradient;
- SkShader* mPattern;
-
- // Note: Keep theses default values in sync with GraphicsContextState.
- State()
- : mMiterLimit(4),
- mAlpha(1),
- mLooper(NULL),
- mLineCap(SkPaint::kDefault_Cap),
- mLineJoin(SkPaint::kDefault_Join),
- mPorterDuffMode(SkPorterDuff::kSrcOver_Mode),
- mDashRatio(3),
- mFillColor(0xFF000000),
- mStrokeStyle(SolidStroke),
- mStrokeColor(0x0FF000000),
- mStrokeThickness(0),
- mUseAntialiasing(true),
- mDash(NULL),
- mGradient(NULL),
- mPattern(NULL) {
- }
-
- State(const State& other) {
- other.mLooper->safeRef();
- memcpy(this, &other, sizeof(State));
-
- mDash->safeRef();
- mGradient->safeRef();
- mPattern->safeRef();
- }
-
- ~State() {
- mLooper->safeUnref();
- mDash->safeUnref();
- mGradient->safeUnref();
- mPattern->safeUnref();
- }
-
- SkDrawLooper* setDrawLooper(SkDrawLooper* dl) {
- SkRefCnt_SafeAssign(mLooper, dl);
- return dl;
- }
-
- SkColor applyAlpha(SkColor c) const {
- int s = RoundToInt(mAlpha * 256);
- if (s >= 256)
- return c;
- if (s < 0)
- return 0;
-
- int a = SkAlphaMul(SkColorGetA(c), s);
- return (c & 0x00FFFFFF) | (a << 24);
- }
-
- private:
- // Not supported yet.
- void operator=(const State&);
-};
-
-// Context will be NULL if painting should be disabled.
-SkPaintContext::SkPaintContext(gfx::PlatformCanvas* context)
- : canvas_(context),
- state_stack_(sizeof(State)) {
- State* state = reinterpret_cast<State*>(state_stack_.push_back());
- new (state) State();
- state_ = state;
-}
-
-SkPaintContext::~SkPaintContext() {
- // we force restores so we don't leak any subobjects owned by our
- // stack of State records.
- while (state_stack_.count() > 0) {
- reinterpret_cast<State*>(state_stack_.back())->~State();
- state_stack_.pop_back();
- }
-}
-
-void SkPaintContext::save() {
- State* newState = reinterpret_cast<State*>(state_stack_.push_back());
- new (newState) State(*state_);
- state_ = newState;
-
- // Save our native canvas.
- canvas()->save();
-}
-
-void SkPaintContext::restore() {
- // Restore our native canvas.
- canvas()->restore();
-
- state_->~State();
- state_stack_.pop_back();
-
- state_ = reinterpret_cast<State*>(state_stack_.back());
-}
-
-void SkPaintContext::drawRect(SkRect rect) {
- SkPaint paint;
- int fillcolor_not_transparent = state_->mFillColor & 0xFF000000;
- if (fillcolor_not_transparent) {
- setup_paint_fill(&paint);
- canvas()->drawRect(rect, paint);
- }
-
- if (state_->mStrokeStyle != NoStroke && (state_->mStrokeColor & 0xFF000000)) {
- if (fillcolor_not_transparent) {
- // This call is expensive so don't call it unnecessarily.
- paint.reset();
- }
- setup_paint_stroke(&paint, &rect, 0);
- canvas()->drawRect(rect, paint);
- }
-}
-
-void SkPaintContext::setup_paint_common(SkPaint* paint) const {
-#ifdef SK_DEBUGx
- {
- SkPaint defaultPaint;
- SkASSERT(*paint == defaultPaint);
- }
-#endif
-
- paint->setAntiAlias(state_->mUseAntialiasing);
- paint->setPorterDuffXfermode(state_->mPorterDuffMode);
- paint->setLooper(state_->mLooper);
-
- if(state_->mGradient) {
- paint->setShader(state_->mGradient);
- } else if (state_->mPattern) {
- paint->setShader(state_->mPattern);
- }
-}
-
-void SkPaintContext::setup_paint_fill(SkPaint* paint) const {
- setup_paint_common(paint);
- paint->setColor(state_->applyAlpha(state_->mFillColor));
-}
-
-int SkPaintContext::setup_paint_stroke(SkPaint* paint,
- SkRect* rect,
- int length) const {
- setup_paint_common(paint);
- float width = state_->mStrokeThickness;
-
- //this allows dashing and dotting to work properly for hairline strokes
- if (0 == width)
- width = 1;
-
- paint->setColor(state_->applyAlpha(state_->mStrokeColor));
- paint->setStyle(SkPaint::kStroke_Style);
- paint->setStrokeWidth(SkFloatToScalar(width));
- paint->setStrokeCap(state_->mLineCap);
- paint->setStrokeJoin(state_->mLineJoin);
- paint->setStrokeMiter(SkFloatToScalar(state_->mMiterLimit));
-
- if (rect != NULL && (RoundToInt(width) & 1)) {
- rect->inset(-SK_ScalarHalf, -SK_ScalarHalf);
- }
-
- if (state_->mDash) {
- paint->setPathEffect(state_->mDash);
- } else {
- switch (state_->mStrokeStyle) {
- case NoStroke:
- case SolidStroke:
- break;
- case DashedStroke:
- width = state_->mDashRatio * width;
- /* no break */
- case DottedStroke:
- SkScalar dashLength;
- if (length) {
- //determine about how many dashes or dots we should have
- int numDashes = length/RoundToInt(width);
- if (!(numDashes & 1))
- numDashes++; //make it odd so we end on a dash/dot
- //use the number of dashes to determine the length of a dash/dot, which will be approximately width
- dashLength = SkScalarDiv(SkIntToScalar(length), SkIntToScalar(numDashes));
- } else {
- dashLength = SkFloatToScalar(width);
- }
- SkScalar intervals[2] = { dashLength, dashLength };
- paint->setPathEffect(new SkDashPathEffect(intervals, 2, 0))->unref();
- }
- }
- return RoundToInt(width);
-}
-
-SkDrawLooper* SkPaintContext::setDrawLooper(SkDrawLooper* dl) {
- return state_->setDrawLooper(dl);
-}
-
-void SkPaintContext::setMiterLimit(float ml) {
- state_->mMiterLimit = ml;
-}
-
-void SkPaintContext::setAlpha(float alpha) {
- state_->mAlpha = alpha;
-}
-
-void SkPaintContext::setLineCap(SkPaint::Cap lc) {
- state_->mLineCap = lc;
-}
-
-void SkPaintContext::setLineJoin(SkPaint::Join lj) {
- state_->mLineJoin = lj;
-}
-
-void SkPaintContext::setPorterDuffMode(SkPorterDuff::Mode pdm) {
- state_->mPorterDuffMode = pdm;
-}
-
-void SkPaintContext::setFillColor(SkColor color) {
- state_->mFillColor = color;
-}
-
-void SkPaintContext::setStrokeStyle(StrokeStyle strokestyle) {
- state_->mStrokeStyle = strokestyle;
-}
-
-void SkPaintContext::setStrokeColor(SkColor strokecolor) {
- state_->mStrokeColor = strokecolor;
-}
-
-void SkPaintContext::setStrokeThickness(float thickness) {
- state_->mStrokeThickness = thickness;
-}
-
-void SkPaintContext::setUseAntialiasing(bool enable) {
- state_->mUseAntialiasing = enable;
-}
-
-SkColor SkPaintContext::fillColor() const {
- return state_->mFillColor;
-}
-
-void SkPaintContext::beginPath() {
- path_.reset();
-}
-
-void SkPaintContext::addPath(const SkPath& path) {
- path_.addPath(path);
-}
-
-const SkPath* SkPaintContext::currentPath() const {
- return &path_;
-}
-
-void SkPaintContext::setFillRule(SkPath::FillType fr) {
- path_.setFillType(fr);
-}
-
-void SkPaintContext::setGradient(SkShader* gradient) {
- if (gradient != state_->mGradient) {
- state_->mGradient->safeUnref();
- state_->mGradient=gradient;
- }
-}
-
-void SkPaintContext::setPattern(SkShader* pattern) {
- if (pattern != state_->mPattern) {
- state_->mPattern->safeUnref();
- state_->mPattern=pattern;
- }
-}
-
-void SkPaintContext::setDashPathEffect(SkDashPathEffect* dash) {
- if (dash != state_->mDash) {
- state_->mDash->safeUnref();
- state_->mDash=dash;
- }
-}
-
diff --git a/webkit/port/platform/graphics/SkPaintContext.h b/webkit/port/platform/graphics/SkPaintContext.h
deleted file mode 100644
index b14d5f2..0000000
--- a/webkit/port/platform/graphics/SkPaintContext.h
+++ /dev/null
@@ -1,108 +0,0 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SkPaintContext_h
-#define SkPaintContext_h
-
-#include "base/gfx/platform_canvas.h"
-
-#include "SkDashPathEffect.h"
-#include "SkDrawLooper.h"
-#include "SkDeque.h"
-#include "SkPaint.h"
-#include "SkPath.h"
-
-
-// This class is the interface to communicate to Skia. It is meant to be as
-// opaque as possible. This class accept Skia native data format and not WebKit
-// format.
-// Every functions assume painting is enabled, callers should check this before
-// calling any member function.
-class SkPaintContext {
- public:
- // Duplicates WebCore::StrokeStyle. We can't include GraphicsContext.h here
- // because we want to keep this class isolated from WebKit. Make sure both
- // enums keep the same values. If StrokeStyle ever gets moved to
- // GraphicsTypes.h, remove this duplicate and include GraphicsTypes.h
- // instead.
- enum StrokeStyle {
- NoStroke,
- SolidStroke,
- DottedStroke,
- DashedStroke
- };
-
- // Context will be NULL if painting should be disabled.
- SkPaintContext(gfx::PlatformCanvas* context);
- ~SkPaintContext();
-
- void save();
-
- void restore();
-
- void drawRect(SkRect rect);
-
- void setup_paint_common(SkPaint* paint) const;
-
- void setup_paint_fill(SkPaint* paint) const;
-
- // Sets up the paint for stroking. Returns an int representing the width of
- // the pen, or 1 if the pen's width is 0 if a non-zero length is provided,
- // the number of dashes/dots on a dashed/dotted line will be adjusted to
- // start and end that length with a dash/dot.
- int setup_paint_stroke(SkPaint* paint, SkRect* rect, int length) const;
-
- // State proxying functions
- SkDrawLooper* setDrawLooper(SkDrawLooper* dl);
- void setMiterLimit(float ml);
- void setAlpha(float alpha);
- void setLineCap(SkPaint::Cap lc);
- void setLineJoin(SkPaint::Join lj);
- void setFillRule(SkPath::FillType fr);
- void setPorterDuffMode(SkPorterDuff::Mode pdm);
- void setFillColor(SkColor color);
- void setStrokeStyle(StrokeStyle strokestyle);
- void setStrokeColor(SkColor strokecolor);
- void setStrokeThickness(float thickness);
- void setUseAntialiasing(bool enable);
-
- void beginPath();
- void addPath(const SkPath& path);
- const SkPath* currentPath() const;
-
- void setGradient(SkShader*);
- void setPattern(SkShader*);
- void setDashPathEffect(SkDashPathEffect*);
-
- SkColor fillColor() const;
-
- protected:
- gfx::PlatformCanvas* canvas() {
- return canvas_;
- }
-
- private:
- // Defines drawing style.
- struct State;
-
- // NULL indicates painting is disabled. Never delete this object.
- gfx::PlatformCanvas* canvas_;
-
- // States stack. Enables local drawing state change with save()/restore()
- // calls.
- SkDeque state_stack_;
- // Pointer to the current drawing state. This is a cached value of
- // mStateStack.back().
- State* state_;
-
- // Current path
- SkPath path_;
-
- // Disallow these.
- SkPaintContext(const SkPaintContext&);
- void operator=(const SkPaintContext&);
-};
-
-#endif
-
diff --git a/webkit/port/platform/graphics/chromium/ImageBufferData.h b/webkit/port/platform/graphics/chromium/ImageBufferData.h
new file mode 100644
index 0000000..267191b
--- /dev/null
+++ b/webkit/port/platform/graphics/chromium/ImageBufferData.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2008 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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 APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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 ImageBufferData_h
+#define ImageBufferData_h
+
+#include "PlatformContextSkia.h"
+
+#include "base/gfx/platform_canvas.h"
+
+namespace WebCore {
+
+class ImageBufferData {
+public:
+ ImageBufferData(const IntSize&);
+
+ gfx::PlatformCanvas m_canvas;
+
+ // Must be second since this will refer to m_canvas.
+ PlatformContextSkia m_platformContext;
+};
+
+} // namespace WebCore
+
+#endif // ImageBufferData_h
+
diff --git a/webkit/port/platform/graphics/svg/SkiaSupport.cpp b/webkit/port/platform/graphics/svg/SkiaSupport.cpp
index 2df8841..1a58df0 100644
--- a/webkit/port/platform/graphics/svg/SkiaSupport.cpp
+++ b/webkit/port/platform/graphics/svg/SkiaSupport.cpp
@@ -35,6 +35,7 @@
#if ENABLE(SVG)
#include "SkiaSupport.h"
+#include "ImageBuffer.h"
#include "GraphicsContext.h"
#include "RenderStyle.h"
#include "RenderPath.h"
@@ -77,14 +78,16 @@ void applyStrokeStyleToContext(GraphicsContext* context, const RenderStyle* styl
GraphicsContext* scratchContext()
{
- static GraphicsContext* scratch = NULL;
+ static ImageBuffer* scratch = NULL;
if (!scratch)
- scratch = GraphicsContext::createOffscreenContext(1, 1);
- return scratch;
+ scratch = ImageBuffer::create(IntSize(1, 1), false).release();
+ // We don't bother checking for failure creating the ImageBuffer, since our
+ // ImageBuffer initializer won't fail.
+ return scratch->context();
}
FloatRect strokeBoundingBox(const Path& path, RenderStyle* style, const RenderObject* object)
- {
+{
GraphicsContext* scratch = scratchContext();
scratch->save();