| Index: Source/core/platform/graphics/chromium/TransparencyWin.cpp
|
| diff --git a/Source/core/platform/graphics/chromium/TransparencyWin.cpp b/Source/core/platform/graphics/chromium/TransparencyWin.cpp
|
| deleted file mode 100644
|
| index 63dcc0c677ab8d5f1ee450457e31a1fec978833d..0000000000000000000000000000000000000000
|
| --- a/Source/core/platform/graphics/chromium/TransparencyWin.cpp
|
| +++ /dev/null
|
| @@ -1,517 +0,0 @@
|
| -/*
|
| - * Copyright (C) 2009 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 <windows.h>
|
| -#include "config.h"
|
| -
|
| -#include "core/platform/graphics/GraphicsContext.h"
|
| -#include "core/platform/graphics/ImageBuffer.h"
|
| -#include "core/platform/graphics/SimpleFontData.h"
|
| -#include "core/platform/graphics/chromium/TransparencyWin.h"
|
| -#include "core/platform/graphics/skia/SkiaUtils.h"
|
| -#include "platform/transforms/AffineTransform.h"
|
| -
|
| -#include "SkColorPriv.h"
|
| -#include "skia/ext/platform_canvas.h"
|
| -
|
| -namespace WebCore {
|
| -
|
| -namespace {
|
| -
|
| -// The maximum size in pixels of the buffer we'll keep around for drawing text
|
| -// into. Buffers larger than this will be destroyed when we're done with them.
|
| -const int maxCachedBufferPixelSize = 65536;
|
| -
|
| -inline const SkBitmap& bitmapForContext(const GraphicsContext& context)
|
| -{
|
| - return context.layerBitmap();
|
| -}
|
| -
|
| -void compositeToCopy(GraphicsContext& sourceLayers,
|
| - GraphicsContext& destContext,
|
| - const AffineTransform& matrix)
|
| -{
|
| - // Make a list of all devices. The iterator goes top-down, and we want
|
| - // bottom-up. Note that each layer can also have an offset in canvas
|
| - // coordinates, which is the (x, y) position.
|
| - struct DeviceInfo {
|
| - DeviceInfo(SkBaseDevice* d, int lx, int ly)
|
| - : device(d)
|
| - , x(lx)
|
| - , y(ly) {}
|
| - SkBaseDevice* device;
|
| - int x;
|
| - int y;
|
| - };
|
| - Vector<DeviceInfo> devices;
|
| - SkCanvas* sourceCanvas = sourceLayers.canvas();
|
| - SkCanvas::LayerIter iter(sourceCanvas, false);
|
| - while (!iter.done()) {
|
| - devices.append(DeviceInfo(iter.device(), iter.x(), iter.y()));
|
| - iter.next();
|
| - }
|
| -
|
| - // Create a temporary canvas for the compositing into the destination.
|
| - SkBitmap* destBmp = const_cast<SkBitmap*>(&bitmapForContext(destContext));
|
| - SkCanvas destCanvas(*destBmp);
|
| - destCanvas.setMatrix(affineTransformToSkMatrix(matrix));
|
| -
|
| - for (int i = devices.size() - 1; i >= 0; i--) {
|
| - const SkBitmap& srcBmp = devices[i].device->accessBitmap(false);
|
| -
|
| - SkRect destRect;
|
| - destRect.fLeft = devices[i].x;
|
| - destRect.fTop = devices[i].y;
|
| - destRect.fRight = destRect.fLeft + srcBmp.width();
|
| - destRect.fBottom = destRect.fTop + srcBmp.height();
|
| -
|
| - destCanvas.drawBitmapRect(srcBmp, 0, destRect);
|
| - }
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -// If either of these pointers is non-null, both must be valid and point to
|
| -// bitmaps of the same size.
|
| -class TransparencyWin::OwnedBuffers {
|
| -public:
|
| - OwnedBuffers(const IntSize& size, bool needReferenceBuffer)
|
| - {
|
| - m_destBitmap = ImageBuffer::create(size, 1);
|
| -
|
| - if (needReferenceBuffer) {
|
| - m_referenceBitmap.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height());
|
| - m_referenceBitmap.allocPixels();
|
| - m_referenceBitmap.eraseARGB(0, 0, 0, 0);
|
| - }
|
| - }
|
| -
|
| - ImageBuffer* destBitmap() { return m_destBitmap.get(); }
|
| -
|
| - // This bitmap will be empty if you don't specify needReferenceBuffer to the
|
| - // constructor.
|
| - SkBitmap* referenceBitmap() { return &m_referenceBitmap; }
|
| -
|
| - // Returns whether the current layer will fix a buffer of the given size.
|
| - bool canHandleSize(const IntSize& size) const
|
| - {
|
| - return m_destBitmap->internalSize().width() >= size.width() && m_destBitmap->internalSize().height() >= size.height();
|
| - }
|
| -
|
| -private:
|
| - // The destination bitmap we're drawing into.
|
| - OwnPtr<ImageBuffer> m_destBitmap;
|
| -
|
| - // This could be an ImageBuffer but this is an optimization. Since this is
|
| - // only ever used as a reference, we don't need to make a full
|
| - // PlatformCanvas using Skia on Windows. Just allocating a regular SkBitmap
|
| - // is much faster since it's just a Malloc rather than a GDI call.
|
| - SkBitmap m_referenceBitmap;
|
| -};
|
| -
|
| -TransparencyWin::OwnedBuffers* TransparencyWin::m_cachedBuffers = 0;
|
| -
|
| -TransparencyWin::TransparencyWin()
|
| - : m_destContext(0)
|
| - , m_orgTransform()
|
| - , m_layerMode(NoLayer)
|
| - , m_transformMode(KeepTransform)
|
| - , m_drawContext(0)
|
| - , m_savedOnDrawContext(false)
|
| - , m_layerBuffer(0)
|
| - , m_referenceBitmap(0)
|
| - , m_validLayer(false)
|
| -{
|
| -}
|
| -
|
| -TransparencyWin::~TransparencyWin()
|
| -{
|
| - // This should be false, since calling composite() is mandatory.
|
| - ASSERT(!m_savedOnDrawContext);
|
| -}
|
| -
|
| -void TransparencyWin::composite()
|
| -{
|
| - // Matches the save() in initializeNewTextContext (or the constructor for
|
| - // SCALE) to put the context back into the same state we found it.
|
| - if (m_savedOnDrawContext) {
|
| - m_drawContext->restore();
|
| - m_savedOnDrawContext = false;
|
| - }
|
| -
|
| - switch (m_layerMode) {
|
| - case NoLayer:
|
| - break;
|
| - case OpaqueCompositeLayer:
|
| - case WhiteLayer:
|
| - compositeOpaqueComposite();
|
| - break;
|
| - case TextComposite:
|
| - compositeTextComposite();
|
| - break;
|
| - }
|
| -}
|
| -
|
| -void TransparencyWin::init(GraphicsContext* dest,
|
| - LayerMode layerMode,
|
| - TransformMode transformMode,
|
| - const IntRect& region)
|
| -{
|
| - m_destContext = dest;
|
| - m_orgTransform = dest->getCTM();
|
| - m_layerMode = layerMode;
|
| - m_transformMode = transformMode;
|
| - m_sourceRect = region;
|
| -
|
| - computeLayerSize();
|
| - setupLayer();
|
| - setupTransform(region);
|
| -}
|
| -
|
| -void TransparencyWin::computeLayerSize()
|
| -{
|
| - if (m_transformMode == Untransform) {
|
| - // The meaning of the "transformed" source rect is a little ambigous
|
| - // here. The rest of the code doesn't care about it in the Untransform
|
| - // case since we're using our own happy coordinate system. So we set it
|
| - // to be the source rect since that matches how the code below actually
|
| - // uses the variable: to determine how to translate things to account
|
| - // for the offset of the layer.
|
| - m_transformedSourceRect = m_sourceRect;
|
| - } else if (m_transformMode == KeepTransform && m_layerMode != TextComposite) {
|
| - // FIXME: support clipping for other modes
|
| - IntRect clippedSourceRect = m_sourceRect;
|
| - SkRect clipBounds;
|
| - if (m_destContext->getClipBounds(&clipBounds)) {
|
| - FloatRect clipRect(clipBounds.left(), clipBounds.top(), clipBounds.width(), clipBounds.height());
|
| - clippedSourceRect.intersect(enclosingIntRect(clipRect));
|
| - }
|
| - m_transformedSourceRect = m_orgTransform.mapRect(clippedSourceRect);
|
| - } else
|
| - m_transformedSourceRect = m_orgTransform.mapRect(m_sourceRect);
|
| -
|
| - m_layerSize = IntSize(m_transformedSourceRect.width(), m_transformedSourceRect.height());
|
| -}
|
| -
|
| -void TransparencyWin::setupLayer()
|
| -{
|
| - switch (m_layerMode) {
|
| - case NoLayer:
|
| - setupLayerForNoLayer();
|
| - break;
|
| - case OpaqueCompositeLayer:
|
| - setupLayerForOpaqueCompositeLayer();
|
| - break;
|
| - case TextComposite:
|
| - setupLayerForTextComposite();
|
| - break;
|
| - case WhiteLayer:
|
| - setupLayerForWhiteLayer();
|
| - break;
|
| - }
|
| -}
|
| -
|
| -void TransparencyWin::setupLayerForNoLayer()
|
| -{
|
| - m_drawContext = m_destContext; // Draw to the source context.
|
| - m_validLayer = true;
|
| -}
|
| -
|
| -void TransparencyWin::setupLayerForOpaqueCompositeLayer()
|
| -{
|
| - initializeNewContext();
|
| - if (!m_validLayer)
|
| - return;
|
| -
|
| - AffineTransform mapping;
|
| - mapping.translate(-m_transformedSourceRect.x(), -m_transformedSourceRect.y());
|
| - if (m_transformMode == Untransform){
|
| - // Compute the inverse mapping from the canvas space to the
|
| - // coordinate space of our bitmap.
|
| - mapping *= m_orgTransform.inverse();
|
| - }
|
| - compositeToCopy(*m_destContext, *m_drawContext, mapping);
|
| -
|
| - // Save the reference layer so we can tell what changed.
|
| - SkCanvas referenceCanvas(*m_referenceBitmap);
|
| - referenceCanvas.drawBitmap(bitmapForContext(*m_drawContext), 0, 0);
|
| - // Layer rect represents the part of the original layer.
|
| -}
|
| -
|
| -void TransparencyWin::setupLayerForTextComposite()
|
| -{
|
| - ASSERT(m_transformMode == KeepTransform);
|
| - // Fall through to filling with white.
|
| - setupLayerForWhiteLayer();
|
| -}
|
| -
|
| -void TransparencyWin::setupLayerForWhiteLayer()
|
| -{
|
| - initializeNewContext();
|
| - if (!m_validLayer)
|
| - return;
|
| -
|
| - m_drawContext->fillRect(IntRect(IntPoint(0, 0), m_layerSize), Color::white);
|
| - // Layer rect represents the part of the original layer.
|
| -}
|
| -
|
| -void TransparencyWin::setupTransform(const IntRect& region)
|
| -{
|
| - switch (m_transformMode) {
|
| - case KeepTransform:
|
| - setupTransformForKeepTransform(region);
|
| - break;
|
| - case Untransform:
|
| - setupTransformForUntransform();
|
| - break;
|
| - case ScaleTransform:
|
| - setupTransformForScaleTransform();
|
| - break;
|
| - }
|
| -}
|
| -
|
| -void TransparencyWin::setupTransformForKeepTransform(const IntRect& region)
|
| -{
|
| - if (!m_validLayer)
|
| - return;
|
| -
|
| - if (m_layerMode != NoLayer) {
|
| - // Need to save things since we're modifying the transform.
|
| - m_drawContext->save();
|
| - m_savedOnDrawContext = true;
|
| -
|
| - // Account for the fact that the layer may be offset from the
|
| - // original. This only happens when we create a layer that has the
|
| - // same coordinate space as the parent.
|
| - AffineTransform xform;
|
| - xform.translate(-m_transformedSourceRect.x(), -m_transformedSourceRect.y());
|
| -
|
| - // We're making a layer, so apply the old transform to the new one
|
| - // so it's maintained. We know the new layer has the identity
|
| - // transform now, we we can just multiply it.
|
| - xform *= m_orgTransform;
|
| - m_drawContext->concatCTM(xform);
|
| - }
|
| - m_drawRect = m_sourceRect;
|
| -}
|
| -
|
| -void TransparencyWin::setupTransformForUntransform()
|
| -{
|
| - ASSERT(m_layerMode != NoLayer);
|
| - // We now have a new layer with the identity transform, which is the
|
| - // Untransformed space we'll use for drawing.
|
| - m_drawRect = IntRect(IntPoint(0, 0), m_layerSize);
|
| -}
|
| -
|
| -void TransparencyWin::setupTransformForScaleTransform()
|
| -{
|
| - if (!m_validLayer)
|
| - return;
|
| -
|
| - if (m_layerMode == NoLayer) {
|
| - // Need to save things since we're modifying the layer.
|
| - m_drawContext->save();
|
| - m_savedOnDrawContext = true;
|
| -
|
| - // Undo the transform on the current layer when we're re-using the
|
| - // current one.
|
| - m_drawContext->concatCTM(m_drawContext->getCTM().inverse());
|
| -
|
| - // We're drawing to the original layer with just a different size.
|
| - m_drawRect = m_transformedSourceRect;
|
| - } else {
|
| - // Just go ahead and use the layer's coordinate space to draw into.
|
| - // It will have the scaled size, and an identity transform loaded.
|
| - m_drawRect = IntRect(IntPoint(0, 0), m_layerSize);
|
| - }
|
| -}
|
| -
|
| -void TransparencyWin::setTextCompositeColor(Color color)
|
| -{
|
| - m_textCompositeColor = color;
|
| -}
|
| -
|
| -void TransparencyWin::initializeNewContext()
|
| -{
|
| - int pixelSize = m_layerSize.width() * m_layerSize.height();
|
| - if (pixelSize <= 0)
|
| - return;
|
| -
|
| - if (pixelSize > maxCachedBufferPixelSize) {
|
| - // Create a 1-off buffer for drawing into. We only need the reference
|
| - // buffer if we're making an OpaqueCompositeLayer.
|
| - bool needReferenceBitmap = m_layerMode == OpaqueCompositeLayer;
|
| - m_ownedBuffers = adoptPtr(new OwnedBuffers(m_layerSize, needReferenceBitmap));
|
| - m_layerBuffer = m_ownedBuffers->destBitmap();
|
| - if (!m_layerBuffer)
|
| - return;
|
| -
|
| - m_drawContext = m_layerBuffer->context();
|
| - if (needReferenceBitmap) {
|
| - m_referenceBitmap = m_ownedBuffers->referenceBitmap();
|
| - if (!m_referenceBitmap || !m_referenceBitmap->getPixels())
|
| - return;
|
| - }
|
| - m_validLayer = true;
|
| - return;
|
| - }
|
| -
|
| - if (m_cachedBuffers && m_cachedBuffers->canHandleSize(m_layerSize)) {
|
| - // We can re-use the existing buffer. We don't need to clear it since
|
| - // all layer modes will clear it in their initialization.
|
| - m_layerBuffer = m_cachedBuffers->destBitmap();
|
| - m_drawContext = m_cachedBuffers->destBitmap()->context();
|
| - bitmapForContext(*m_drawContext).eraseARGB(0, 0, 0, 0);
|
| - m_referenceBitmap = m_cachedBuffers->referenceBitmap();
|
| - m_referenceBitmap->eraseARGB(0, 0, 0, 0);
|
| - m_validLayer = true;
|
| - return;
|
| - }
|
| -
|
| - // Create a new cached buffer.
|
| - if (m_cachedBuffers)
|
| - delete m_cachedBuffers;
|
| - m_cachedBuffers = new OwnedBuffers(m_layerSize, true);
|
| -
|
| - m_layerBuffer = m_cachedBuffers->destBitmap();
|
| - m_drawContext = m_cachedBuffers->destBitmap()->context();
|
| - m_referenceBitmap = m_cachedBuffers->referenceBitmap();
|
| - m_validLayer = true;
|
| -}
|
| -
|
| -void TransparencyWin::compositeOpaqueComposite()
|
| -{
|
| - if (!m_validLayer)
|
| - return;
|
| -
|
| - m_destContext->save();
|
| -
|
| - SkBitmap* bitmap = const_cast<SkBitmap*>(
|
| - &bitmapForContext(*m_layerBuffer->context()));
|
| -
|
| - // This function will be called for WhiteLayer as well, which we don't want
|
| - // to change.
|
| - if (m_layerMode == OpaqueCompositeLayer) {
|
| - // Fix up our bitmap, making it contain only the pixels which changed
|
| - // and transparent everywhere else.
|
| - SkAutoLockPixels sourceLock(*m_referenceBitmap);
|
| - SkAutoLockPixels lock(*bitmap);
|
| - for (int y = 0; y < bitmap->height(); y++) {
|
| - uint32_t* source = m_referenceBitmap->getAddr32(0, y);
|
| - uint32_t* dest = bitmap->getAddr32(0, y);
|
| - for (int x = 0; x < bitmap->width(); x++) {
|
| - // Clear out any pixels that were untouched.
|
| - if (dest[x] == source[x])
|
| - dest[x] = 0;
|
| - else
|
| - dest[x] |= (0xFF << SK_A32_SHIFT);
|
| - }
|
| - }
|
| - } else
|
| - makeLayerOpaque();
|
| -
|
| - SkRect destRect;
|
| - if (m_transformMode != Untransform) {
|
| - // We want to use Untransformed space.
|
| - //
|
| - // Note that we DON'T call m_layerBuffer->image() here. This actually
|
| - // makes a copy of the image, which is unnecessary and slow. Instead, we
|
| - // just draw the image from inside the destination context.
|
| - SkMatrix identity;
|
| - identity.reset();
|
| - m_destContext->setMatrix(identity);
|
| -
|
| - destRect.set(m_transformedSourceRect.x(), m_transformedSourceRect.y(), m_transformedSourceRect.maxX(), m_transformedSourceRect.maxY());
|
| - } else
|
| - destRect.set(m_sourceRect.x(), m_sourceRect.y(), m_sourceRect.maxX(), m_sourceRect.maxY());
|
| -
|
| - SkPaint paint;
|
| - paint.setFilterBitmap(true);
|
| - paint.setAntiAlias(true);
|
| -
|
| - // Note that we need to specify the source layer subset, since the bitmap
|
| - // may have been cached and it could be larger than what we're using.
|
| - SkRect sourceRect = SkRect::MakeWH(
|
| - SkIntToScalar(m_layerSize.width()),
|
| - SkIntToScalar(m_layerSize.height()));
|
| - m_destContext->drawBitmapRect(*bitmap, &sourceRect, destRect, &paint);
|
| - m_destContext->restore();
|
| -}
|
| -
|
| -void TransparencyWin::compositeTextComposite()
|
| -{
|
| - if (!m_validLayer)
|
| - return;
|
| -
|
| - const SkBitmap& bitmap = m_layerBuffer->context()->layerBitmap(GraphicsContext::ReadWrite);
|
| - SkColor textColor = m_textCompositeColor.rgb();
|
| - for (int y = 0; y < m_layerSize.height(); y++) {
|
| - uint32_t* row = bitmap.getAddr32(0, y);
|
| - for (int x = 0; x < m_layerSize.width(); x++) {
|
| - // The alpha is the average of the R, G, and B channels.
|
| - int alpha = (SkGetPackedR32(row[x]) + SkGetPackedG32(row[x]) + SkGetPackedB32(row[x])) / 3;
|
| -
|
| - // Apply that alpha to the text color and write the result.
|
| - row[x] = SkAlphaMulQ(textColor, SkAlpha255To256(255 - alpha));
|
| - }
|
| - }
|
| -
|
| - // Now the layer has text with the proper color and opacity.
|
| - m_destContext->save();
|
| -
|
| - // We want to use Untransformed space (see above)
|
| - SkMatrix identity;
|
| - identity.reset();
|
| - m_destContext->setMatrix(identity);
|
| - SkRect destRect = { m_transformedSourceRect.x(), m_transformedSourceRect.y(), m_transformedSourceRect.maxX(), m_transformedSourceRect.maxY() };
|
| -
|
| - // Note that we need to specify the source layer subset, since the bitmap
|
| - // may have been cached and it could be larger than what we're using.
|
| - SkRect sourceRect = SkRect::MakeWH(
|
| - SkIntToScalar(m_layerSize.width()),
|
| - SkIntToScalar(m_layerSize.height()));
|
| - m_destContext->drawBitmapRect(bitmap, &sourceRect, destRect, 0);
|
| - m_destContext->restore();
|
| -}
|
| -
|
| -void TransparencyWin::makeLayerOpaque()
|
| -{
|
| - if (!m_validLayer)
|
| - return;
|
| -
|
| - SkBitmap& bitmap = const_cast<SkBitmap&>(m_drawContext->layerBitmap(GraphicsContext::ReadWrite));
|
| - for (int y = 0; y < m_layerSize.height(); y++) {
|
| - uint32_t* row = bitmap.getAddr32(0, y);
|
| - for (int x = 0; x < m_layerSize.width(); x++)
|
| - row[x] |= 0xFF000000;
|
| - }
|
| -}
|
| -
|
| -} // namespace WebCore
|
|
|