📄 transparencywin.cpp
字号:
/* * 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 "config.h"#include <windows.h>#include "GraphicsContext.h"#include "ImageBuffer.h"#include "PlatformContextSkia.h"#include "SimpleFontData.h"#include "TransformationMatrix.h"#include "TransparencyWin.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 skia::PlatformCanvas* canvasForContext(const GraphicsContext& context){ return context.platformContext()->canvas();}inline const SkBitmap& bitmapForContext(const GraphicsContext& context){ return canvasForContext(context)->getTopPlatformDevice().accessBitmap(false);}void compositeToCopy(const GraphicsContext& sourceLayers, GraphicsContext& destContext, const TransformationMatrix& 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(SkDevice* d, int lx, int ly) : device(d) , x(lx) , y(ly) {} SkDevice* device; int x; int y; }; Vector<DeviceInfo> devices; SkCanvas* sourceCanvas = canvasForContext(sourceLayers); 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(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.adopt(ImageBuffer::create(size, false)); 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->size().width() >= size.width() && m_destBitmap->size().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){}TransparencyWin::~TransparencyWin(){ // 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(); 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; m_layerSize = IntSize(m_sourceRect.width(), m_sourceRect.height()); } 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.}void TransparencyWin::setupLayerForOpaqueCompositeLayer(){ initializeNewContext();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -