#include "config.h"
#include "GraphicsContext.h"
+#include "ImageBuffer.h"
#include "NativeImageSkia.h"
#include "PlatformContextSkia.h"
#include "SkiaUtils.h"
// color to produce a new output color.
SkColor applyAlpha(SkColor) const;
+#if defined(__linux__) || PLATFORM(WIN_OS)
+ // If non-empty, the current State is clipped to this image.
+ SkBitmap m_imageBufferClip;
+ // If m_imageBufferClip is non-empty, this is the region the image is clipped to.
+ WebCore::FloatRect m_clip;
+#endif
+
private:
// Not supported.
void operator=(const State&);
}
PlatformContextSkia::State::State(const State& other)
+ : m_alpha(other.m_alpha)
+ , m_porterDuffMode(other.m_porterDuffMode)
+ , m_gradient(other.m_gradient)
+ , m_pattern(other.m_pattern)
+ , m_useAntialiasing(other.m_useAntialiasing)
+ , m_looper(other.m_looper)
+ , m_fillColor(other.m_fillColor)
+ , m_strokeStyle(other.m_strokeStyle)
+ , m_strokeColor(other.m_strokeColor)
+ , m_strokeThickness(other.m_strokeThickness)
+ , m_dashRatio(other.m_dashRatio)
+ , m_miterLimit(other.m_miterLimit)
+ , m_lineCap(other.m_lineCap)
+ , m_lineJoin(other.m_lineJoin)
+ , m_dash(other.m_dash)
+ , m_textDrawingMode(other.m_textDrawingMode)
+#if defined(__linux__) || PLATFORM(WIN_OS)
+ , m_imageBufferClip(other.m_imageBufferClip)
+ , m_clip(other.m_clip)
+#endif
{
- memcpy(this, &other, sizeof(State));
-
+ // Up the ref count of these. saveRef does nothing if 'this' is NULL.
m_looper->safeRef();
m_dash->safeRef();
m_gradient->safeRef();
PlatformContextSkia::PlatformContextSkia(skia::PlatformCanvas* canvas)
: m_canvas(canvas)
, m_stateStack(sizeof(State))
+#if PLATFORM(WIN_OS)
+ , m_drawingToImageBuffer(false)
+#endif
{
m_stateStack.append(State());
m_state = &m_stateStack.last();
m_canvas = canvas;
}
+#if PLATFORM(WIN_OS)
+void PlatformContextSkia::setDrawingToImageBuffer(bool value)
+{
+ m_drawingToImageBuffer = value;
+}
+
+bool PlatformContextSkia::isDrawingToImageBuffer() const
+{
+ return m_drawingToImageBuffer;
+}
+#endif
+
void PlatformContextSkia::save()
{
m_stateStack.append(*m_state);
m_state = &m_stateStack.last();
+#if defined(__linux__) || PLATFORM(WIN_OS)
+ // The clip image only needs to be applied once. Reset the image so that we
+ // don't attempt to clip multiple times.
+ m_state->m_imageBufferClip.reset();
+#endif
+
// Save our native canvas.
canvas()->save();
}
+#if defined(__linux__) || PLATFORM(WIN_OS)
+void PlatformContextSkia::beginLayerClippedToImage(const WebCore::FloatRect& rect,
+ const WebCore::ImageBuffer* imageBuffer)
+{
+ // Skia doesn't support clipping to an image, so we create a layer. The next
+ // time restore is invoked the layer and |imageBuffer| are combined to
+ // create the resulting image.
+ m_state->m_clip = rect;
+ SkRect bounds = { SkFloatToScalar(rect.x()), SkFloatToScalar(rect.y()),
+ SkFloatToScalar(rect.right()), SkFloatToScalar(rect.bottom()) };
+
+ canvas()->saveLayerAlpha(&bounds, 255,
+ static_cast<SkCanvas::SaveFlags>(SkCanvas::kHasAlphaLayer_SaveFlag | SkCanvas::kFullColorLayer_SaveFlag));
+ // Copy off the image as |imageBuffer| may be deleted before restore is invoked.
+ const SkBitmap* bitmap = imageBuffer->context()->platformContext()->bitmap();
+ if (!bitmap->pixelRef()) {
+ // The bitmap owns it's pixels. This happens when we've allocated the
+ // pixels in some way and assigned them directly to the bitmap (as
+ // happens when we allocate a DIB). In this case the assignment operator
+ // does not copy the pixels, rather the copied bitmap ends up
+ // referencing the same pixels. As the pixels may not live as long as we
+ // need it to, we copy the image.
+ bitmap->copyTo(&m_state->m_imageBufferClip, SkBitmap::kARGB_8888_Config);
+ } else {
+ // If there is a pixel ref, we can safely use the assignment operator.
+ m_state->m_imageBufferClip = *bitmap;
+ }
+}
+#endif
+
void PlatformContextSkia::restore()
{
+#if defined(__linux__) || PLATFORM(WIN_OS)
+ if (!m_state->m_imageBufferClip.empty()) {
+ applyClipFromImage(m_state->m_clip, m_state->m_imageBufferClip);
+ canvas()->restore();
+ }
+#endif
+
m_stateStack.removeLast();
m_state = &m_stateStack.last();
{
return m_canvas->getTopPlatformDevice().IsVectorial();
}
+
+#if defined(__linux__) || PLATFORM(WIN_OS)
+void PlatformContextSkia::applyClipFromImage(const WebCore::FloatRect& rect, const SkBitmap& imageBuffer)
+{
+ // NOTE: this assumes the image mask contains opaque black for the portions that are to be shown, as such we
+ // only look at the alpha when compositing. I'm not 100% sure this is what WebKit expects for image clipping.
+ SkPaint paint;
+ paint.setPorterDuffXfermode(SkPorterDuff::kDstIn_Mode);
+ m_canvas->drawBitmap(imageBuffer, SkFloatToScalar(rect.x()), SkFloatToScalar(rect.y()), &paint);
+}
+#endif