diff options
author | brettw@google.com <brettw@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-11-21 23:03:56 +0000 |
---|---|---|
committer | brettw@google.com <brettw@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-11-21 23:03:56 +0000 |
commit | 156f2c0e187c0283f026fd356a4b682d4b4eaaa1 (patch) | |
tree | 209d254abb43d9ff2cb9a904dd16eed00a85bfb4 /webkit/port | |
parent | bd2e63eed24e8c097be6ea3fb46aa354c638e88e (diff) | |
download | chromium_src-156f2c0e187c0283f026fd356a4b682d4b4eaaa1.zip chromium_src-156f2c0e187c0283f026fd356a4b682d4b4eaaa1.tar.gz chromium_src-156f2c0e187c0283f026fd356a4b682d4b4eaaa1.tar.bz2 |
Move skia extensions from the port to skia/ext for Windows only. Fixed the
include guards of the moved files, but nothing else.
Review URL: http://codereview.chromium.org/11568
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@5861 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/port')
12 files changed, 3 insertions, 2352 deletions
diff --git a/webkit/port/platform/graphics/skia/public/BitmapPlatformDevice.h b/webkit/port/platform/graphics/skia/public/BitmapPlatformDevice.h index 1f933a4..1b0df28 100644 --- a/webkit/port/platform/graphics/skia/public/BitmapPlatformDevice.h +++ b/webkit/port/platform/graphics/skia/public/BitmapPlatformDevice.h @@ -7,7 +7,7 @@ // around. #if defined(WIN32) -#include "BitmapPlatformDeviceWin.h" +#include "skia/ext/bitmap_platform_device_win.h" namespace gfx { typedef BitmapPlatformDeviceWin BitmapPlatformDevice; diff --git a/webkit/port/platform/graphics/skia/public/BitmapPlatformDeviceWin.cpp b/webkit/port/platform/graphics/skia/public/BitmapPlatformDeviceWin.cpp deleted file mode 100644 index ceed2c8..0000000 --- a/webkit/port/platform/graphics/skia/public/BitmapPlatformDeviceWin.cpp +++ /dev/null @@ -1,446 +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. - -#include "BitmapPlatformDeviceWin.h" - -#include "base/gfx/gdi_util.h" -#include "base/logging.h" -#include "SkMatrix.h" -#include "SkRegion.h" -#include "SkUtils.h" - -namespace gfx { - -// When Windows draws text, is sets the fourth byte (which Skia uses for alpha) -// to zero. This means that if we try compositing with text that Windows has -// drawn, we get invalid color values (if the alpha is 0, the other channels -// should be 0 since Skia uses premultiplied colors) and strange results. -// -// HTML rendering only requires one bit of transparency. When you ask for a -// semitransparent div, the div itself is drawn in another layer as completely -// opaque, and then composited onto the lower layer with a transfer function. -// The only place an alpha channel is needed is to track what has been drawn -// and what has not been drawn. -// -// Therefore, when we allocate a new device, we fill it with this special -// color. Because Skia uses premultiplied colors, any color where the alpha -// channel is smaller than any component is impossible, so we know that no -// legitimate drawing will produce this color. We use 1 as the alpha value -// because 0 is produced when Windows draws text (even though it should be -// opaque). -// -// When a layer is done and we want to render it to a lower layer, we use -// fixupAlphaBeforeCompositing. This replaces all 0 alpha channels with -// opaque (to fix the text problem), and replaces this magic color value -// with transparency. The result is something that can be correctly -// composited. However, once this has been done, no more can be drawn to -// the layer because fixing the alphas *again* will result in incorrect -// values. -static const uint32_t kMagicTransparencyColor = 0x01FFFEFD; - -namespace { - -// Constrains position and size to fit within available_size. If |size| is -1, -// all the available_size is used. Returns false if the position is out of -// available_size. -bool Constrain(int available_size, int* position, int *size) { - if (*size < -2) - return false; - - if (*position < 0) { - if (*size != -1) - *size += *position; - *position = 0; - } - if (*size == 0 || *position >= available_size) - return false; - - if (*size > 0) { - int overflow = (*position + *size) - available_size; - if (overflow > 0) { - *size -= overflow; - } - } else { - // Fill up available size. - *size = available_size - *position; - } - return true; -} - -// If the pixel value is 0, it gets set to kMagicTransparencyColor. -void PrepareAlphaForGDI(uint32_t* pixel) { - if (*pixel == 0) { - *pixel = kMagicTransparencyColor; - } -} - -// If the pixel value is kMagicTransparencyColor, it gets set to 0. Otherwise -// if the alpha is 0, the alpha is set to 255. -void PostProcessAlphaForGDI(uint32_t* pixel) { - if (*pixel == kMagicTransparencyColor) { - *pixel = 0; - } else if ((*pixel & 0xFF000000) == 0) { - *pixel |= 0xFF000000; - } -} - -// Sets the opacity of the specified value to 0xFF. -void MakeOpaqueAlphaAdjuster(uint32_t* pixel) { - *pixel |= 0xFF000000; -} - -// See the declaration of kMagicTransparencyColor at the top of the file. -void FixupAlphaBeforeCompositing(uint32_t* pixel) { - if (*pixel == kMagicTransparencyColor) - *pixel = 0; - else - *pixel |= 0xFF000000; -} - -} // namespace - -class BitmapPlatformDeviceWin::BitmapPlatformDeviceWinData - : public base::RefCounted<BitmapPlatformDeviceWinData> { - public: - explicit BitmapPlatformDeviceWinData(HBITMAP hbitmap); - - // Create/destroy hdc_, which is the memory DC for our bitmap data. - HDC GetBitmapDC(); - void ReleaseBitmapDC(); - bool IsBitmapDCCreated() const; - - // Sets the transform and clip operations. This will not update the DC, - // but will mark the config as dirty. The next call of LoadConfig will - // pick up these changes. - void SetMatrixClip(const SkMatrix& transform, const SkRegion& region); - - const SkMatrix& transform() const { - return transform_; - } - - protected: - // Loads the current transform and clip into the DC. Can be called even when - // the DC is NULL (will be a NOP). - void LoadConfig(); - - // Windows bitmap corresponding to our surface. - HBITMAP hbitmap_; - - // Lazily-created DC used to draw into the bitmap, see getBitmapDC. - HDC hdc_; - - // True when there is a transform or clip that has not been set to the DC. - // The DC is retrieved for every text operation, and the transform and clip - // do not change as much. We can save time by not loading the clip and - // transform for every one. - bool config_dirty_; - - // Translation assigned to the DC: we need to keep track of this separately - // so it can be updated even if the DC isn't created yet. - SkMatrix transform_; - - // The current clipping - SkRegion clip_region_; - - private: - friend class base::RefCounted<BitmapPlatformDeviceWinData>; - ~BitmapPlatformDeviceWinData(); - - DISALLOW_EVIL_CONSTRUCTORS(BitmapPlatformDeviceWinData); -}; - -BitmapPlatformDeviceWin::BitmapPlatformDeviceWinData::BitmapPlatformDeviceWinData( - HBITMAP hbitmap) - : hbitmap_(hbitmap), - hdc_(NULL), - config_dirty_(true) { // Want to load the config next time. - // Initialize the clip region to the entire bitmap. - BITMAP bitmap_data; - if (GetObject(hbitmap_, sizeof(BITMAP), &bitmap_data)) { - SkIRect rect; - rect.set(0, 0, bitmap_data.bmWidth, bitmap_data.bmHeight); - clip_region_ = SkRegion(rect); - } - - transform_.reset(); -} - -BitmapPlatformDeviceWin::BitmapPlatformDeviceWinData::~BitmapPlatformDeviceWinData() { - if (hdc_) - ReleaseBitmapDC(); - - // this will free the bitmap data as well as the bitmap handle - DeleteObject(hbitmap_); -} - -HDC BitmapPlatformDeviceWin::BitmapPlatformDeviceWinData::GetBitmapDC() { - if (!hdc_) { - hdc_ = CreateCompatibleDC(NULL); - InitializeDC(hdc_); - HGDIOBJ old_bitmap = SelectObject(hdc_, hbitmap_); - // When the memory DC is created, its display surface is exactly one - // monochrome pixel wide and one monochrome pixel high. Since we select our - // own bitmap, we must delete the previous one. - DeleteObject(old_bitmap); - } - - LoadConfig(); - return hdc_; -} - -void BitmapPlatformDeviceWin::BitmapPlatformDeviceWinData::ReleaseBitmapDC() { - DCHECK(hdc_); - DeleteDC(hdc_); - hdc_ = NULL; -} - -bool BitmapPlatformDeviceWin::BitmapPlatformDeviceWinData::IsBitmapDCCreated() - const { - return hdc_ != NULL; -} - - -void BitmapPlatformDeviceWin::BitmapPlatformDeviceWinData::SetMatrixClip( - const SkMatrix& transform, - const SkRegion& region) { - transform_ = transform; - clip_region_ = region; - config_dirty_ = true; -} - -void BitmapPlatformDeviceWin::BitmapPlatformDeviceWinData::LoadConfig() { - if (!config_dirty_ || !hdc_) - return; // Nothing to do. - config_dirty_ = false; - - // Transform. - SkMatrix t(transform_); - LoadTransformToDC(hdc_, t); - // We don't use transform_ for the clipping region since the translation is - // already applied to offset_x_ and offset_y_. - t.reset(); - LoadClippingRegionToDC(hdc_, clip_region_, t); -} - -// We use this static factory function instead of the regular constructor so -// that we can create the pixel data before calling the constructor. This is -// required so that we can call the base class' constructor with the pixel -// data. -BitmapPlatformDeviceWin* BitmapPlatformDeviceWin::create(HDC screen_dc, - int width, - int height, - bool is_opaque, - HANDLE shared_section) { - SkBitmap bitmap; - - // CreateDIBSection appears to get unhappy if we create an empty bitmap, so - // just create a minimal bitmap - if ((width == 0) || (height == 0)) { - width = 1; - height = 1; - } - - BITMAPINFOHEADER hdr = {0}; - CreateBitmapHeader(width, height, &hdr); - - void* data = NULL; - HBITMAP hbitmap = CreateDIBSection(screen_dc, - reinterpret_cast<BITMAPINFO*>(&hdr), 0, - &data, - shared_section, 0); - - // If we run out of GDI objects or some other error occurs, we won't get a - // bitmap here. This will cause us to crash later because the data pointer is - // NULL. To make sure that we can assign blame for those crashes to this code, - // we deliberately crash here, even in release mode. - if (!hbitmap) { - DWORD error = GetLastError(); - LOG(ERROR) << "CreateDIBSection Failed. Error: " << error << "\n"; - return NULL; - } - - bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height); - bitmap.setPixels(data); - bitmap.setIsOpaque(is_opaque); - - if (is_opaque) { -#ifndef NDEBUG - // To aid in finding bugs, we set the background color to something - // obviously wrong so it will be noticable when it is not cleared - bitmap.eraseARGB(255, 0, 255, 128); // bright bluish green -#endif - } else { - // A transparent layer is requested: fill with our magic "transparent" - // color, see the declaration of kMagicTransparencyColor above - sk_memset32(static_cast<uint32_t*>(data), kMagicTransparencyColor, - width * height); - } - - // The device object will take ownership of the HBITMAP. - return new BitmapPlatformDeviceWin(new BitmapPlatformDeviceWinData(hbitmap), - bitmap); -} - -// The device will own the HBITMAP, which corresponds to also owning the pixel -// data. Therefore, we do not transfer ownership to the SkDevice's bitmap. -BitmapPlatformDeviceWin::BitmapPlatformDeviceWin( - BitmapPlatformDeviceWinData* data, - const SkBitmap& bitmap) : PlatformDeviceWin(bitmap), data_(data) { -} - -// The copy constructor just adds another reference to the underlying data. -// We use a const cast since the default Skia definitions don't define the -// proper constedness that we expect (accessBitmap should really be const). -BitmapPlatformDeviceWin::BitmapPlatformDeviceWin( - const BitmapPlatformDeviceWin& other) - : PlatformDeviceWin( - const_cast<BitmapPlatformDeviceWin&>(other).accessBitmap(true)), - data_(other.data_) { -} - -BitmapPlatformDeviceWin::~BitmapPlatformDeviceWin() { -} - -BitmapPlatformDeviceWin& BitmapPlatformDeviceWin::operator=( - const BitmapPlatformDeviceWin& other) { - data_ = other.data_; - return *this; -} - -HDC BitmapPlatformDeviceWin::getBitmapDC() { - return data_->GetBitmapDC(); -} - -void BitmapPlatformDeviceWin::setMatrixClip(const SkMatrix& transform, - const SkRegion& region) { - data_->SetMatrixClip(transform, region); -} - -void BitmapPlatformDeviceWin::drawToHDC(HDC dc, int x, int y, - const RECT* src_rect) { - bool created_dc = !data_->IsBitmapDCCreated(); - HDC source_dc = getBitmapDC(); - - RECT temp_rect; - if (!src_rect) { - temp_rect.left = 0; - temp_rect.right = width(); - temp_rect.top = 0; - temp_rect.bottom = height(); - src_rect = &temp_rect; - } - - int copy_width = src_rect->right - src_rect->left; - int copy_height = src_rect->bottom - src_rect->top; - - // We need to reset the translation for our bitmap or (0,0) won't be in the - // upper left anymore - SkMatrix identity; - identity.reset(); - - LoadTransformToDC(source_dc, identity); - if (isOpaque()) { - BitBlt(dc, - x, - y, - copy_width, - copy_height, - source_dc, - src_rect->left, - src_rect->top, - SRCCOPY); - } else { - DCHECK(copy_width != 0 && copy_height != 0); - BLENDFUNCTION blend_function = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA}; - GdiAlphaBlend(dc, - x, - y, - copy_width, - copy_height, - source_dc, - src_rect->left, - src_rect->top, - copy_width, - copy_height, - blend_function); - } - LoadTransformToDC(source_dc, data_->transform()); - - if (created_dc) - data_->ReleaseBitmapDC(); -} - -void BitmapPlatformDeviceWin::prepareForGDI(int x, int y, int width, - int height) { - processPixels<PrepareAlphaForGDI>(x, y, width, height); -} - -void BitmapPlatformDeviceWin::postProcessGDI(int x, int y, int width, - int height) { - processPixels<PostProcessAlphaForGDI>(x, y, width, height); -} - -void BitmapPlatformDeviceWin::makeOpaque(int x, int y, int width, int height) { - processPixels<MakeOpaqueAlphaAdjuster>(x, y, width, height); -} - -void BitmapPlatformDeviceWin::fixupAlphaBeforeCompositing() { - const SkBitmap& bitmap = accessBitmap(true); - SkAutoLockPixels lock(bitmap); - uint32_t* data = bitmap.getAddr32(0, 0); - - size_t words = bitmap.rowBytes() / sizeof(uint32_t) * bitmap.height(); - for (size_t i = 0; i < words; i++) { - if (data[i] == kMagicTransparencyColor) - data[i] = 0; - else - data[i] |= 0xFF000000; - } -} - -// Returns the color value at the specified location. -SkColor BitmapPlatformDeviceWin::getColorAt(int x, int y) { - const SkBitmap& bitmap = accessBitmap(false); - SkAutoLockPixels lock(bitmap); - uint32_t* data = bitmap.getAddr32(0, 0); - return static_cast<SkColor>(data[x + y * width()]); -} - -void BitmapPlatformDeviceWin::onAccessBitmap(SkBitmap* bitmap) { - // FIXME(brettw) OPTIMIZATION: We should only flush if we know a GDI - // operation has occurred on our DC. - if (data_->IsBitmapDCCreated()) - GdiFlush(); -} - -template<BitmapPlatformDeviceWin::adjustAlpha adjustor> -void BitmapPlatformDeviceWin::processPixels(int x, - int y, - int width, - int height) { - const SkBitmap& bitmap = accessBitmap(true); - DCHECK_EQ(bitmap.config(), SkBitmap::kARGB_8888_Config); - const SkMatrix& matrix = data_->transform(); - int bitmap_start_x = SkScalarRound(matrix.getTranslateX()) + x; - int bitmap_start_y = SkScalarRound(matrix.getTranslateY()) + y; - - if (Constrain(bitmap.width(), &bitmap_start_x, &width) && - Constrain(bitmap.height(), &bitmap_start_y, &height)) { - SkAutoLockPixels lock(bitmap); - DCHECK_EQ(bitmap.rowBytes() % sizeof(uint32_t), 0u); - size_t row_words = bitmap.rowBytes() / sizeof(uint32_t); - // Set data to the first pixel to be modified. - uint32_t* data = bitmap.getAddr32(0, 0) + (bitmap_start_y * row_words) + - bitmap_start_x; - for (int i = 0; i < height; i++) { - for (int j = 0; j < width; j++) { - adjustor(data + j); - } - data += row_words; - } - } -} - -} // namespace gfx - diff --git a/webkit/port/platform/graphics/skia/public/BitmapPlatformDeviceWin.h b/webkit/port/platform/graphics/skia/public/BitmapPlatformDeviceWin.h deleted file mode 100644 index 24008d4..0000000 --- a/webkit/port/platform/graphics/skia/public/BitmapPlatformDeviceWin.h +++ /dev/null @@ -1,111 +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 BitmapPlatformDeviceWin_h -#define BitmapPlatformDeviceWin_h - -#include "base/gfx/platform_device_win.h" -#include "base/ref_counted.h" - -namespace gfx { - -// A device is basically a wrapper around SkBitmap that provides a surface for -// SkCanvas to draw into. Our device provides a surface Windows can also write -// to. BitmapPlatformDeviceWin creates a bitmap using CreateDIBSection() in a -// format that Skia supports and can then use this to draw ClearType into, etc. -// This pixel data is provided to the bitmap that the device contains so that it -// can be shared. -// -// The device owns the pixel data, when the device goes away, the pixel data -// also becomes invalid. THIS IS DIFFERENT THAN NORMAL SKIA which uses -// reference counting for the pixel data. In normal Skia, you could assign -// another bitmap to this device's bitmap and everything will work properly. -// For us, that other bitmap will become invalid as soon as the device becomes -// invalid, which may lead to subtle bugs. Therefore, DO NOT ASSIGN THE -// DEVICE'S PIXEL DATA TO ANOTHER BITMAP, make sure you copy instead. -class BitmapPlatformDeviceWin : public PlatformDeviceWin { - public: - // Factory function. The screen DC is used to create the bitmap, and will not - // be stored beyond this function. is_opaque should be set if the caller - // knows the bitmap will be completely opaque and allows some optimizations. - // - // The shared_section parameter is optional (pass NULL for default behavior). - // If shared_section is non-null, then it must be a handle to a file-mapping - // object returned by CreateFileMapping. See CreateDIBSection for details. - static BitmapPlatformDeviceWin* create(HDC screen_dc, - int width, - int height, - bool is_opaque, - HANDLE shared_section); - - // Copy constructor. When copied, devices duplicate their internal data, so - // stay linked. This is because their implementation is very heavyweight - // (lots of memory and some GDI objects). If a device has been copied, both - // clip rects and other state will stay in sync. - // - // This means it will NOT work to duplicate a device and assign it to a - // canvas, because the two canvases will each set their own clip rects, and - // the resulting GDI clip rect will be random. - // - // Copy constucting and "=" is designed for saving the device or passing it - // around to another routine willing to deal with the bitmap data directly. - BitmapPlatformDeviceWin(const BitmapPlatformDeviceWin& other); - virtual ~BitmapPlatformDeviceWin(); - - // See warning for copy constructor above. - BitmapPlatformDeviceWin& operator=(const BitmapPlatformDeviceWin& other); - - // Retrieves the bitmap DC, which is the memory DC for our bitmap data. The - // bitmap DC is lazy created. - virtual HDC getBitmapDC(); - virtual void setMatrixClip(const SkMatrix& transform, const SkRegion& region); - - virtual void drawToHDC(HDC dc, int x, int y, const RECT* src_rect); - virtual void prepareForGDI(int x, int y, int width, int height); - virtual void postProcessGDI(int x, int y, int width, int height); - virtual void makeOpaque(int x, int y, int width, int height); - virtual void fixupAlphaBeforeCompositing(); - virtual bool IsVectorial() { return false; } - - // Returns the color value at the specified location. This does not - // consider any transforms that may be set on the device. - SkColor getColorAt(int x, int y); - - protected: - // Flushes the Windows device context so that the pixel data can be accessed - // directly by Skia. Overridden from SkDevice, this is called when Skia - // starts accessing pixel data. - virtual void onAccessBitmap(SkBitmap* bitmap); - - private: - // Function pointer used by the processPixels method for setting the alpha - // value of a particular pixel. - typedef void (*adjustAlpha)(uint32_t* pixel); - - // Reference counted data that can be shared between multiple devices. This - // allows copy constructors and operator= for devices to work properly. The - // bitmaps used by the base device class are already refcounted and copyable. - class BitmapPlatformDeviceWinData; - - // Private constructor. - BitmapPlatformDeviceWin(BitmapPlatformDeviceWinData* data, - const SkBitmap& bitmap); - - // Loops through each of the pixels in the specified range, invoking - // adjustor for the alpha value of each pixel. If |width| or |height| are -1, - // the available width/height is used. - template<adjustAlpha adjustor> - void processPixels(int x, - int y, - int width, - int height); - - // Data associated with this device, guaranteed non-null. - scoped_refptr<BitmapPlatformDeviceWinData> data_; -}; - -} // namespace gfx - -#endif // BASE_GFX_BITMAP_PLATFORM_DEVICE_WIN_H_ - diff --git a/webkit/port/platform/graphics/skia/public/PlatformCanvas.h b/webkit/port/platform/graphics/skia/public/PlatformCanvas.h index 162bf3e..a2af39e 100644 --- a/webkit/port/platform/graphics/skia/public/PlatformCanvas.h +++ b/webkit/port/platform/graphics/skia/public/PlatformCanvas.h @@ -7,7 +7,7 @@ // around. #if defined(WIN32) -#include "PlatformCanvasWin.h" +#include "skia/ext/platform_canvas_win.h" namespace gfx { typedef PlatformCanvasWin PlatformCanvas; diff --git a/webkit/port/platform/graphics/skia/public/PlatformCanvasWin.cpp b/webkit/port/platform/graphics/skia/public/PlatformCanvasWin.cpp deleted file mode 100644 index 6c0fe08..0000000 --- a/webkit/port/platform/graphics/skia/public/PlatformCanvasWin.cpp +++ /dev/null @@ -1,118 +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. - -#include "PlatformCanvasWin.h" - -#include "BitmapPlatformDeviceWin.h" - -#include "base/logging.h" -#include "base/process_util.h" - -namespace gfx { - -// Crashes the process. This is called when a bitmap allocation fails, and this -// function tries to determine why it might have failed, and crash on different -// lines. This allows us to see in crash dumps the most likely reason for the -// failure. It takes the size of the bitmap we were trying to allocate as its -// arguments so we can check that as well. -void CrashForBitmapAllocationFailure(int w, int h) { - // The maximum number of GDI objects per process is 10K. If we're very close - // to that, it's probably the problem. - const int kLotsOfGDIObjs = 9990; - CHECK(GetGuiResources(GetCurrentProcess(), GR_GDIOBJECTS) < kLotsOfGDIObjs); - - // If the bitmap is ginormous, then we probably can't allocate it. - // We use 64M pixels = 256MB @ 4 bytes per pixel. - const int64 kGinormousBitmapPxl = 64000000; - CHECK(static_cast<int64>(w) * static_cast<int64>(h) < kGinormousBitmapPxl); - - // If we're using a crazy amount of virtual address space, then maybe there - // isn't enough for our bitmap. - const int64 kLotsOfMem = 1500000000; // 1.5GB. - scoped_ptr<base::ProcessMetrics> process_metrics( - base::ProcessMetrics::CreateProcessMetrics(GetCurrentProcess())); - CHECK(process_metrics->GetPagefileUsage() < kLotsOfMem); - - // Everything else. - CHECK(0); -} - - -PlatformCanvasWin::PlatformCanvasWin() : SkCanvas() { -} - -PlatformCanvasWin::PlatformCanvasWin(int width, int height, bool is_opaque) - : SkCanvas() { - bool initialized = initialize(width, height, is_opaque, NULL); - if (!initialized) - CrashForBitmapAllocationFailure(width, height); -} - -PlatformCanvasWin::PlatformCanvasWin(int width, - int height, - bool is_opaque, - HANDLE shared_section) - : SkCanvas() { - bool initialized = initialize(width, height, is_opaque, shared_section); - if (!initialized) - CrashForBitmapAllocationFailure(width, height); -} - -PlatformCanvasWin::~PlatformCanvasWin() { -} - -bool PlatformCanvasWin::initialize(int width, - int height, - bool is_opaque, - HANDLE shared_section) { - SkDevice* device = - createPlatformDevice(width, height, is_opaque, shared_section); - if (!device) - return false; - - setDevice(device); - device->unref(); // was created with refcount 1, and setDevice also refs - return true; -} - -HDC PlatformCanvasWin::beginPlatformPaint() { - return getTopPlatformDevice().getBitmapDC(); -} - -void PlatformCanvasWin::endPlatformPaint() { - // we don't clear the DC here since it will be likely to be used again - // flushing will be done in onAccessBitmap -} - -PlatformDeviceWin& PlatformCanvasWin::getTopPlatformDevice() const { - // All of our devices should be our special PlatformDevice. - SkCanvas::LayerIter iter(const_cast<PlatformCanvasWin*>(this), false); - return *static_cast<PlatformDeviceWin*>(iter.device()); -} - -SkDevice* PlatformCanvasWin::createDevice(SkBitmap::Config config, - int width, - int height, - bool is_opaque, bool isForLayer) { - DCHECK(config == SkBitmap::kARGB_8888_Config); - return createPlatformDevice(width, height, is_opaque, NULL); -} - -SkDevice* PlatformCanvasWin::createPlatformDevice(int width, - int height, - bool is_opaque, - HANDLE shared_section) { - HDC screen_dc = GetDC(NULL); - SkDevice* device = BitmapPlatformDeviceWin::create(screen_dc, width, height, - is_opaque, shared_section); - ReleaseDC(NULL, screen_dc); - return device; -} - -SkDevice* PlatformCanvasWin::setBitmapDevice(const SkBitmap&) { - NOTREACHED(); - return NULL; -} - -} // namespace gfx diff --git a/webkit/port/platform/graphics/skia/public/PlatformCanvasWin.h b/webkit/port/platform/graphics/skia/public/PlatformCanvasWin.h deleted file mode 100644 index fa84693..0000000 --- a/webkit/port/platform/graphics/skia/public/PlatformCanvasWin.h +++ /dev/null @@ -1,202 +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 PlatformCanvasWin_h -#define PlatformCanvasWin_h - -#include <windows.h> - -#include "PlatformDeviceWin.h" -#include "base/basictypes.h" - -#include "SkCanvas.h" - -namespace gfx { - -// This class is a specialization of the regular SkCanvas that is designed to -// work with a gfx::PlatformDevice to manage platform-specific drawing. It -// allows using both Skia operations and platform-specific operations. -class PlatformCanvasWin : public SkCanvas { - public: - // Set is_opaque if you are going to erase the bitmap and not use - // transparency: this will enable some optimizations. The shared_section - // parameter is passed to gfx::PlatformDevice::create. See it for details. - // - // If you use the version with no arguments, you MUST call initialize() - PlatformCanvasWin(); - PlatformCanvasWin(int width, int height, bool is_opaque); - PlatformCanvasWin(int width, int height, bool is_opaque, - HANDLE shared_section); - virtual ~PlatformCanvasWin(); - - // For two-part init, call if you use the no-argument constructor above. Note - // that we want this to optionally match the Linux initialize if you only - // pass 3 arguments, hence the evil default argument. - bool initialize(int width, int height, bool is_opaque, - HANDLE shared_section = NULL); - - // These calls should surround calls to platform drawing routines, the DC - // returned by beginPlatformPaint is the DC that can be used to draw into. - // Call endPlatformPaint when you are done and want to use Skia operations - // again; this will synchronize the bitmap to Windows. - virtual HDC beginPlatformPaint(); - virtual void endPlatformPaint(); - - // Returns the platform device pointer of the topmost rect with a non-empty - // clip. In practice, this is usually either the top layer or nothing, since - // we usually set the clip to new layers when we make them. - // - // If there is no layer that is not all clipped out, this will return a - // dummy device so callers do not have to check. If you are concerned about - // performance, check the clip before doing any painting. - // - // This is different than SkCanvas' getDevice, because that returns the - // bottommost device. - // - // Danger: the resulting device should not be saved. It will be invalidated - // by the next call to save() or restore(). - PlatformDeviceWin& getTopPlatformDevice() const; - - protected: - // Creates a device store for use by the canvas. We override this so that - // the device is always our own so we know that we can use GDI operations - // on it. Simply calls into createPlatformDevice(). - virtual SkDevice* createDevice(SkBitmap::Config, int width, int height, - bool is_opaque, bool isForLayer); - - // Creates a device store for use by the canvas. By default, it creates a - // BitmapPlatformDeviceWin. Can be overridden to change the object type. - virtual SkDevice* createPlatformDevice(int width, int height, bool is_opaque, - HANDLE shared_section); - - private: - // Unimplemented. - virtual SkDevice* setBitmapDevice(const SkBitmap& bitmap); - - // Disallow copy and assign. - PlatformCanvasWin(const PlatformCanvasWin&); - PlatformCanvasWin& operator=(const PlatformCanvasWin&); -}; - -// A class designed to help with WM_PAINT operations on Windows. It will -// do BeginPaint/EndPaint on init/destruction, and will create the bitmap and -// canvas with the correct size and transform for the dirty rect. The bitmap -// will be automatically painted to the screen on destruction. -// -// You MUST call isEmpty before painting to determine if anything needs -// painting. Sometimes the dirty rect can actually be empty, and this makes -// the bitmap functions we call unhappy. The caller should not paint in this -// case. -// -// Therefore, all you need to do is: -// case WM_PAINT: { -// gfx::PlatformCanvasWinPaint canvas(hwnd); -// if (!canvas.isEmpty()) { -// ... paint to the canvas ... -// } -// return 0; -// } -template <class T> -class CanvasPaintT : public T { - public: - CanvasPaintT(HWND hwnd) : hwnd_(hwnd), paint_dc_(NULL), for_paint_(true) { - memset(&ps_, 0, sizeof(ps_)); - initPaint(true); - } - - CanvasPaintT(HWND hwnd, bool opaque) : hwnd_(hwnd), paint_dc_(NULL), - for_paint_(true) { - memset(&ps_, 0, sizeof(ps_)); - initPaint(opaque); - } - - // Creates a CanvasPaintT for the specified region that paints to the - // specified dc. This does NOT do BeginPaint/EndPaint. - CanvasPaintT(HDC dc, bool opaque, int x, int y, int w, int h) - : hwnd_(NULL), - paint_dc_(dc), - for_paint_(false) { - memset(&ps_, 0, sizeof(ps_)); - ps_.rcPaint.left = x; - ps_.rcPaint.right = x + w; - ps_.rcPaint.top = y; - ps_.rcPaint.bottom = y + h; - init(opaque); - } - - - virtual ~CanvasPaintT() { - if (!isEmpty()) { - restoreToCount(1); - // Commit the drawing to the screen - getTopPlatformDevice().drawToHDC(paint_dc_, - ps_.rcPaint.left, ps_.rcPaint.top, - NULL); - } - if (for_paint_) - EndPaint(hwnd_, &ps_); - } - - // Returns true if the invalid region is empty. The caller should call this - // function to determine if anything needs painting. - bool isEmpty() const { - return ps_.rcPaint.right - ps_.rcPaint.left == 0 || - ps_.rcPaint.bottom - ps_.rcPaint.top == 0; - } - - // Use to access the Windows painting parameters, especially useful for - // getting the bounding rect for painting: paintstruct().rcPaint - const PAINTSTRUCT& paintStruct() const { - return ps_; - } - - // Returns the DC that will be painted to - HDC paintDC() const { - return paint_dc_; - } - - protected: - HWND hwnd_; - HDC paint_dc_; - PAINTSTRUCT ps_; - - private: - void initPaint(bool opaque) { - paint_dc_ = BeginPaint(hwnd_, &ps_); - - init(opaque); - } - - void init(bool opaque) { - // FIXME(brettw) for ClearType, we probably want to expand the bounds of - // painting by one pixel so that the boundaries will be correct (ClearType - // text can depend on the adjacent pixel). Then we would paint just the - // inset pixels to the screen. - const int width = ps_.rcPaint.right - ps_.rcPaint.left; - const int height = ps_.rcPaint.bottom - ps_.rcPaint.top; - if (!initialize(width, height, opaque, NULL)) { - // Cause a deliberate crash; - *(char*) 0 = 0; - } - - // This will bring the canvas into the screen coordinate system for the - // dirty rect - translate(SkIntToScalar(-ps_.rcPaint.left), - SkIntToScalar(-ps_.rcPaint.top)); - } - - // If true, this canvas was created for a BeginPaint. - const bool for_paint_; - - // Disallow copy and assign. - CanvasPaintT(const CanvasPaintT&); - CanvasPaintT& operator=(const CanvasPaintT&); -}; - -typedef CanvasPaintT<PlatformCanvasWin> PlatformCanvasWinPaint; - -} // namespace gfx - -#endif // PlatformCanvasWin_h - diff --git a/webkit/port/platform/graphics/skia/public/PlatformDevice.h b/webkit/port/platform/graphics/skia/public/PlatformDevice.h index a381fd1..1cd8847 100644 --- a/webkit/port/platform/graphics/skia/public/PlatformDevice.h +++ b/webkit/port/platform/graphics/skia/public/PlatformDevice.h @@ -7,7 +7,7 @@ // around. #if defined(WIN32) -#include "PlatformDeviceWin.h" +#include "skia/ext/platform_device_win.h" #elif defined(__APPLE__) #include "skia/ext/platform_device_mac.h" #elif defined(__linux__) diff --git a/webkit/port/platform/graphics/skia/public/PlatformDeviceWin.cpp b/webkit/port/platform/graphics/skia/public/PlatformDeviceWin.cpp deleted file mode 100644 index 65dcffc..0000000 --- a/webkit/port/platform/graphics/skia/public/PlatformDeviceWin.cpp +++ /dev/null @@ -1,229 +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. - -#include "PlatformDeviceWin.h" - -#include "base/logging.h" -#include "base/gfx/skia_utils.h" -#include "SkMatrix.h" -#include "SkPath.h" -#include "SkRegion.h" -#include "SkUtils.h" - -namespace gfx { - -PlatformDeviceWin::PlatformDeviceWin(const SkBitmap& bitmap) - : SkDevice(bitmap) { -} - -// static -void PlatformDeviceWin::InitializeDC(HDC context) { - // Enables world transformation. - // If the GM_ADVANCED graphics mode is set, GDI always draws arcs in the - // counterclockwise direction in logical space. This is equivalent to the - // statement that, in the GM_ADVANCED graphics mode, both arc control points - // and arcs themselves fully respect the device context's world-to-device - // transformation. - BOOL res = SetGraphicsMode(context, GM_ADVANCED); - DCHECK_NE(res, 0); - - // Enables dithering. - res = SetStretchBltMode(context, HALFTONE); - DCHECK_NE(res, 0); - // As per SetStretchBltMode() documentation, SetBrushOrgEx() must be called - // right after. - res = SetBrushOrgEx(context, 0, 0, NULL); - DCHECK_NE(res, 0); - - // Sets up default orientation. - res = SetArcDirection(context, AD_CLOCKWISE); - DCHECK_NE(res, 0); - - // Sets up default colors. - res = SetBkColor(context, RGB(255, 255, 255)); - DCHECK_NE(res, CLR_INVALID); - res = SetTextColor(context, RGB(0, 0, 0)); - DCHECK_NE(res, CLR_INVALID); - res = SetDCBrushColor(context, RGB(255, 255, 255)); - DCHECK_NE(res, CLR_INVALID); - res = SetDCPenColor(context, RGB(0, 0, 0)); - DCHECK_NE(res, CLR_INVALID); - - // Sets up default transparency. - res = SetBkMode(context, OPAQUE); - DCHECK_NE(res, 0); - res = SetROP2(context, R2_COPYPEN); - DCHECK_NE(res, 0); -} - -// static -void PlatformDeviceWin::LoadPathToDC(HDC context, const SkPath& path) { - switch (path.getFillType()) { - case SkPath::kWinding_FillType: { - int res = SetPolyFillMode(context, WINDING); - DCHECK(res != 0); - break; - } - case SkPath::kEvenOdd_FillType: { - int res = SetPolyFillMode(context, ALTERNATE); - DCHECK(res != 0); - break; - } - default: { - NOTREACHED(); - break; - } - } - BOOL res = BeginPath(context); - DCHECK(res != 0); - - CubicPaths paths; - if (!SkPathToCubicPaths(&paths, path)) - return; - - std::vector<POINT> points; - for (CubicPaths::const_iterator path(paths.begin()); path != paths.end(); - ++path) { - if (!path->size()) - continue; - // DCHECK_EQ(points.size() % 4, 0); - points.resize(0); - points.reserve(path->size() * 3 / 4 + 1); - points.push_back(SkPointToPOINT(path->front().p[0])); - for (CubicPath::const_iterator point(path->begin()); point != path->end(); - ++point) { - // Never add point->p[0] - points.push_back(SkPointToPOINT(point->p[1])); - points.push_back(SkPointToPOINT(point->p[2])); - points.push_back(SkPointToPOINT(point->p[3])); - } - DCHECK_EQ((points.size() - 1) % 3, 0); - // This is slightly inefficient since all straight line and quadratic lines - // are "upgraded" to a cubic line. - // TODO(maruel): http://b/1147346 We should use - // PolyDraw/PolyBezier/Polyline whenever possible. - res = PolyBezier(context, &points.front(), - static_cast<DWORD>(points.size())); - DCHECK_NE(res, 0); - if (res == 0) - break; - } - if (res == 0) { - // Make sure the path is discarded. - AbortPath(context); - } else { - res = EndPath(context); - DCHECK(res != 0); - } -} - -// static -void PlatformDeviceWin::LoadTransformToDC(HDC dc, const SkMatrix& matrix) { - XFORM xf; - xf.eM11 = matrix[SkMatrix::kMScaleX]; - xf.eM21 = matrix[SkMatrix::kMSkewX]; - xf.eDx = matrix[SkMatrix::kMTransX]; - xf.eM12 = matrix[SkMatrix::kMSkewY]; - xf.eM22 = matrix[SkMatrix::kMScaleY]; - xf.eDy = matrix[SkMatrix::kMTransY]; - SetWorldTransform(dc, &xf); -} - -// static -bool PlatformDeviceWin::SkPathToCubicPaths(CubicPaths* paths, - const SkPath& skpath) { - paths->clear(); - CubicPath* current_path = NULL; - SkPoint current_points[4]; - CubicPoints points_to_add; - SkPath::Iter iter(skpath, false); - for (SkPath::Verb verb = iter.next(current_points); - verb != SkPath::kDone_Verb; - verb = iter.next(current_points)) { - switch (verb) { - case SkPath::kMove_Verb: { // iter.next returns 1 point - // Ignores it since the point is copied in the next operation. See - // SkPath::Iter::next() for reference. - paths->push_back(CubicPath()); - current_path = &paths->back(); - // Skip point addition. - continue; - } - case SkPath::kLine_Verb: { // iter.next returns 2 points - points_to_add.p[0] = current_points[0]; - points_to_add.p[1] = current_points[0]; - points_to_add.p[2] = current_points[1]; - points_to_add.p[3] = current_points[1]; - break; - } - case SkPath::kQuad_Verb: { // iter.next returns 3 points - points_to_add.p[0] = current_points[0]; - points_to_add.p[1] = current_points[1]; - points_to_add.p[2] = current_points[2]; - points_to_add.p[3] = current_points[2]; - break; - } - case SkPath::kCubic_Verb: { // iter.next returns 4 points - points_to_add.p[0] = current_points[0]; - points_to_add.p[1] = current_points[1]; - points_to_add.p[2] = current_points[2]; - points_to_add.p[3] = current_points[3]; - break; - } - case SkPath::kClose_Verb: { // iter.next returns 1 point (the last point) - paths->push_back(CubicPath()); - current_path = &paths->back(); - continue; - } - case SkPath::kDone_Verb: // iter.next returns 0 points - default: { - current_path = NULL; - // Will return false. - break; - } - } - DCHECK(current_path); - if (!current_path) { - paths->clear(); - return false; - } - current_path->push_back(points_to_add); - } - return true; -} - -// static -void PlatformDeviceWin::LoadClippingRegionToDC(HDC context, - const SkRegion& region, - const SkMatrix& transformation) { - HRGN hrgn; - if (region.isEmpty()) { - // region can be empty, in which case everything will be clipped. - hrgn = CreateRectRgn(0, 0, 0, 0); - } else if (region.isRect()) { - // Do the transformation. - SkRect rect; - rect.set(region.getBounds()); - transformation.mapRect(&rect); - SkIRect irect; - rect.round(&irect); - hrgn = CreateRectRgnIndirect(&SkIRectToRECT(irect)); - } else { - // It is complex. - SkPath path; - region.getBoundaryPath(&path); - // Clip. Note that windows clipping regions are not affected by the - // transform so apply it manually. - path.transform(transformation); - LoadPathToDC(context, path); - hrgn = PathToRegion(context); - } - int result = SelectClipRgn(context, hrgn); - DCHECK_NE(result, ERROR); - result = DeleteObject(hrgn); - DCHECK_NE(result, 0); -} - -} // namespace gfx - diff --git a/webkit/port/platform/graphics/skia/public/PlatformDeviceWin.h b/webkit/port/platform/graphics/skia/public/PlatformDeviceWin.h deleted file mode 100644 index 48b7197..0000000 --- a/webkit/port/platform/graphics/skia/public/PlatformDeviceWin.h +++ /dev/null @@ -1,98 +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 PlatformDeviceWin_h -#define PlatformDeviceWin_h - -#include <windows.h> - -#include <vector> - -#include "SkDevice.h" - -class SkMatrix; -class SkPath; -class SkRegion; - -namespace gfx { - -// A device is basically a wrapper around SkBitmap that provides a surface for -// SkCanvas to draw into. Our device provides a surface Windows can also write -// to. It also provides functionality to play well with GDI drawing functions. -// This class is abstract and must be subclassed. It provides the basic -// interface to implement it either with or without a bitmap backend. -class PlatformDeviceWin : public SkDevice { - public: - // The DC that corresponds to the bitmap, used for GDI operations drawing - // into the bitmap. This is possibly heavyweight, so it should be existant - // only during one pass of rendering. - virtual HDC getBitmapDC() = 0; - - // Draws to the given screen DC, if the bitmap DC doesn't exist, this will - // temporarily create it. However, if you have created the bitmap DC, it will - // be more efficient if you don't free it until after this call so it doesn't - // have to be created twice. If src_rect is null, then the entirety of the - // source device will be copied. - virtual void drawToHDC(HDC dc, int x, int y, const RECT* src_rect) = 0; - - // Invoke before using GDI functions. See description in platform_device.cc - // for specifics. - // NOTE: x,y,width and height are relative to the current transform. - virtual void prepareForGDI(int x, int y, int width, int height) { } - - // Invoke after using GDI functions. See description in platform_device.cc - // for specifics. - // NOTE: x,y,width and height are relative to the current transform. - virtual void postProcessGDI(int x, int y, int width, int height) { } - - // Sets the opacity of each pixel in the specified region to be opaque. - virtual void makeOpaque(int x, int y, int width, int height) { } - - // Call this function to fix the alpha channels before compositing this layer - // onto another. Internally, the device uses a special alpha method to work - // around problems with Windows. This call will put the values into what - // Skia expects, so it can be composited onto other layers. - // - // After this call, no more drawing can be done because the - // alpha channels will be "correct", which, if this function is called again - // will make them wrong. See the implementation for more discussion. - virtual void fixupAlphaBeforeCompositing() { } - - // Returns if the preferred rendering engine is vectorial or bitmap based. - virtual bool IsVectorial() = 0; - - // Initializes the default settings and colors in a device context. - static void InitializeDC(HDC context); - - // Loads a SkPath into the GDI context. The path can there after be used for - // clipping or as a stroke. - static void LoadPathToDC(HDC context, const SkPath& path); - - // Loads a SkRegion into the GDI context. - static void LoadClippingRegionToDC(HDC context, const SkRegion& region, - const SkMatrix& transformation); - - protected: - // Arrays must be inside structures. - struct CubicPoints { - SkPoint p[4]; - }; - typedef std::vector<CubicPoints> CubicPath; - typedef std::vector<CubicPath> CubicPaths; - - // Forwards |bitmap| to SkDevice's constructor. - PlatformDeviceWin(const SkBitmap& bitmap); - - // Loads the specified Skia transform into the device context, excluding - // perspective (which GDI doesn't support). - static void LoadTransformToDC(HDC dc, const SkMatrix& matrix); - - // Transforms SkPath's paths into a series of cubic path. - static bool SkPathToCubicPaths(CubicPaths* paths, const SkPath& skpath); -}; - -} // namespace gfx - -#endif // PlatformDeviceWin_h - diff --git a/webkit/port/platform/graphics/skia/public/VectorCanvas.cpp b/webkit/port/platform/graphics/skia/public/VectorCanvas.cpp deleted file mode 100644 index 440ee64..0000000 --- a/webkit/port/platform/graphics/skia/public/VectorCanvas.cpp +++ /dev/null @@ -1,90 +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. - -#include "base/gfx/vector_canvas.h" - -#include "base/gfx/vector_device.h" -#include "base/logging.h" - -namespace gfx { - -VectorCanvas::VectorCanvas() { -} - -VectorCanvas::VectorCanvas(HDC dc, int width, int height) { - bool initialized = initialize(dc, width, height); - CHECK(initialized); -} - -VectorCanvas::~VectorCanvas() { -} - -bool VectorCanvas::initialize(HDC context, int width, int height) { - SkDevice* device = createPlatformDevice(width, height, true, context); - if (!device) - return false; - - setDevice(device); - device->unref(); // was created with refcount 1, and setDevice also refs - return true; -} - -SkBounder* VectorCanvas::setBounder(SkBounder* bounder) { - if (!IsTopDeviceVectorial()) - return PlatformCanvasWin::setBounder(bounder); - - // This function isn't used in the code. Verify this assumption. - NOTREACHED(); - return NULL; -} - -SkDevice* VectorCanvas::createDevice(SkBitmap::Config config, - int width, int height, - bool is_opaque, bool isForLayer) { - DCHECK(config == SkBitmap::kARGB_8888_Config); - return createPlatformDevice(width, height, is_opaque, NULL); -} - -SkDrawFilter* VectorCanvas::setDrawFilter(SkDrawFilter* filter) { - // This function isn't used in the code. Verify this assumption. - NOTREACHED(); - return NULL; -} - -SkDevice* VectorCanvas::createPlatformDevice(int width, - int height, bool is_opaque, - HANDLE shared_section) { - if (!is_opaque) { - // TODO(maruel): http://b/1184002 1184002 When restoring a semi-transparent - // layer, i.e. merging it, we need to rasterize it because GDI doesn't - // support transparency except for AlphaBlend(). Right now, a - // BitmapPlatformDeviceWin is created when VectorCanvas think a saveLayers() - // call is being done. The way to save a layer would be to create an - // EMF-based VectorDevice and have this device registers the drawing. When - // playing back the device into a bitmap, do it at the printer's dpi instead - // of the layout's dpi (which is much lower). - return PlatformCanvasWin::createPlatformDevice(width, height, is_opaque, - shared_section); - } - - // TODO(maruel): http://b/1183870 Look if it would be worth to increase the - // resolution by ~10x (any worthy factor) to increase the rendering precision - // (think about printing) while using a relatively low dpi. This happens - // because we receive float as input but the GDI functions works with - // integers. The idea is to premultiply the matrix with this factor and - // multiply each SkScalar that are passed to SkScalarRound(value) as - // SkScalarRound(value * 10). Safari is already doing the same for text - // rendering. - DCHECK(shared_section); - PlatformDeviceWin* device = VectorDevice::create( - reinterpret_cast<HDC>(shared_section), width, height); - return device; -} - -bool VectorCanvas::IsTopDeviceVectorial() const { - return getTopPlatformDevice().IsVectorial(); -} - -} // namespace gfx - diff --git a/webkit/port/platform/graphics/skia/public/VectorCanvas.h b/webkit/port/platform/graphics/skia/public/VectorCanvas.h deleted file mode 100644 index 8538366..0000000 --- a/webkit/port/platform/graphics/skia/public/VectorCanvas.h +++ /dev/null @@ -1,46 +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 BASE_GFX_VECTOR_CANVAS_H_ -#define BASE_GFX_VECTOR_CANVAS_H_ - -#include "base/gfx/platform_canvas_win.h" -#include "base/gfx/vector_device.h" - -namespace gfx { - -// This class is a specialization of the regular PlatformCanvas. It is designed -// to work with a VectorDevice to manage platform-specific drawing. It allows -// using both Skia operations and platform-specific operations. It *doesn't* -// support reading back from the bitmap backstore since it is not used. -class VectorCanvas : public PlatformCanvasWin { - public: - VectorCanvas(); - VectorCanvas(HDC dc, int width, int height); - virtual ~VectorCanvas(); - - // For two-part init, call if you use the no-argument constructor above - bool initialize(HDC context, int width, int height); - - virtual SkBounder* setBounder(SkBounder*); - virtual SkDevice* createDevice(SkBitmap::Config config, - int width, int height, - bool is_opaque, bool isForLayer); - virtual SkDrawFilter* setDrawFilter(SkDrawFilter* filter); - - private: - // |is_opaque| is unused. |shared_section| is in fact the HDC used for output. - virtual SkDevice* createPlatformDevice(int width, int height, bool is_opaque, - HANDLE shared_section); - - // Returns true if the top device is vector based and not bitmap based. - bool IsTopDeviceVectorial() const; - - DISALLOW_COPY_AND_ASSIGN(VectorCanvas); -}; - -} // namespace gfx - -#endif // BASE_GFX_VECTOR_CANVAS_H_ - diff --git a/webkit/port/platform/graphics/skia/public/VectorCanvas_unittest.cpp b/webkit/port/platform/graphics/skia/public/VectorCanvas_unittest.cpp deleted file mode 100644 index 28adff7..0000000 --- a/webkit/port/platform/graphics/skia/public/VectorCanvas_unittest.cpp +++ /dev/null @@ -1,1009 +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. - -#include "VectorCanvas.h" - -#include <vector> - -#include "base/command_line.h" -#include "base/file_util.h" -#include "base/gfx/gdi_util.h" -#include "base/gfx/png_decoder.h" -#include "base/gfx/png_encoder.h" -#include "base/gfx/size.h" -#include "base/path_service.h" -#include "base/string_util.h" -#include "base/win_util.h" -#include "testing/gtest/include/gtest/gtest.h" - -#include "SkDashPathEffect.h" - -namespace { - -const wchar_t* const kGenerateSwitch = L"vector-canvas-generate"; - -// Base class for unit test that uses data. It initializes a directory path -// based on the test's name. -class DataUnitTest : public testing::Test { - public: - DataUnitTest(const std::wstring& base_path) : base_path_(base_path) { } - - protected: - // Load the test's data path. - virtual void SetUp() { - const testing::TestInfo& test_info = - *testing::UnitTest::GetInstance()->current_test_info(); - PathService::Get(base::DIR_SOURCE_ROOT, &test_dir_); - file_util::AppendToPath(&test_dir_, base_path_); - file_util::AppendToPath(&test_dir_, L"data"); - file_util::AppendToPath(&test_dir_, - ASCIIToWide(test_info.test_case_name())); - file_util::AppendToPath(&test_dir_, ASCIIToWide(test_info.name())); - - // Hack for a quick lowercase. We assume all the tests names are ASCII. - std::string tmp(WideToASCII(test_dir_)); - for (size_t i = 0; i < tmp.size(); ++i) - tmp[i] = ToLowerASCII(tmp[i]); - test_dir_ = ASCIIToWide(tmp); - } - - // Returns the fully qualified path of directory containing test data files. - const std::wstring& test_dir() const { - return test_dir_; - } - - // Returns the fully qualified path of a data file. - std::wstring test_file(const std::wstring& filename) const { - // Hack for a quick lowercase. We assume all the test data file names are - // ASCII. - std::string tmp(WideToASCII(filename)); - for (size_t i = 0; i < tmp.size(); ++i) - tmp[i] = ToLowerASCII(tmp[i]); - - std::wstring path(test_dir()); - file_util::AppendToPath(&path, ASCIIToWide(tmp)); - return path; - } - - private: - // Path where the unit test is coming from: base, net, chrome, etc. - std::wstring base_path_; - - // Path to directory used to contain the test data. - std::wstring test_dir_; - - DISALLOW_EVIL_CONSTRUCTORS(DataUnitTest); -}; - -// Lightweight HDC management. -class Context { - public: - Context() : context_(CreateCompatibleDC(NULL)) { - EXPECT_TRUE(context_); - } - ~Context() { - DeleteDC(context_); - } - - HDC context() const { return context_; } - - private: - HDC context_; - - DISALLOW_EVIL_CONSTRUCTORS(Context); -}; - -// Lightweight HBITMAP management. -class Bitmap { - public: - Bitmap(const Context& context, int x, int y) { - BITMAPINFOHEADER hdr; - gfx::CreateBitmapHeader(x, y, &hdr); - bitmap_ = CreateDIBSection(context.context(), - reinterpret_cast<BITMAPINFO*>(&hdr), 0, - &data_, NULL, 0); - EXPECT_TRUE(bitmap_); - EXPECT_TRUE(SelectObject(context.context(), bitmap_)); - } - ~Bitmap() { - EXPECT_TRUE(DeleteObject(bitmap_)); - } - - private: - HBITMAP bitmap_; - - void* data_; - - DISALLOW_EVIL_CONSTRUCTORS(Bitmap); -}; - -// Lightweight raw-bitmap management. The image, once initialized, is immuable. -// It is mainly used for comparison. -class Image { - public: - // Creates the image from the given filename on disk. - Image(const std::wstring& filename) : ignore_alpha_(true) { - std::string compressed; - file_util::ReadFileToString(filename, &compressed); - EXPECT_TRUE(compressed.size()); - - int w; - int h; - EXPECT_TRUE(PNGDecoder::Decode( - reinterpret_cast<const unsigned char*>(compressed.c_str()), - compressed.size(), PNGDecoder::FORMAT_BGRA, &data_, &w, &h)); - size_.SetSize(w, h); - row_length_ = w * sizeof(uint32); - } - - // Loads the image from a canvas. - Image(const gfx::PlatformCanvasWin& canvas) : ignore_alpha_(true) { - // Use a different way to access the bitmap. The normal way would be to - // query the SkBitmap. - HDC context = canvas.getTopPlatformDevice().getBitmapDC(); - HGDIOBJ bitmap = GetCurrentObject(context, OBJ_BITMAP); - EXPECT_TRUE(bitmap != NULL); - // Initialize the clip region to the entire bitmap. - BITMAP bitmap_data; - EXPECT_EQ(GetObject(bitmap, sizeof(BITMAP), &bitmap_data), - sizeof(BITMAP)); - size_.SetSize(bitmap_data.bmWidth, bitmap_data.bmHeight); - row_length_ = bitmap_data.bmWidthBytes; - size_t size = row_length_ * size_.height(); - data_.resize(size); - memcpy(&*data_.begin(), bitmap_data.bmBits, size); - } - - // Loads the image from a canvas. - Image(const SkBitmap& bitmap) : ignore_alpha_(true) { - SkAutoLockPixels lock(bitmap); - size_.SetSize(bitmap.width(), bitmap.height()); - row_length_ = static_cast<int>(bitmap.rowBytes()); - size_t size = row_length_ * size_.height(); - data_.resize(size); - memcpy(&*data_.begin(), bitmap.getAddr(0, 0), size); - } - - const gfx::Size& size() const { - return size_; - } - - int row_length() const { - return row_length_; - } - - // Save the image to a png file. Used to create the initial test files. - void SaveToFile(const std::wstring& filename) { - std::vector<unsigned char> compressed; - ASSERT_TRUE(PNGEncoder::Encode(&*data_.begin(), - PNGEncoder::FORMAT_BGRA, - size_.width(), - size_.height(), - row_length_, - true, - &compressed)); - ASSERT_TRUE(compressed.size()); - FILE* f = file_util::OpenFile(filename, "wb"); - ASSERT_TRUE(f); - ASSERT_EQ(fwrite(&*compressed.begin(), 1, compressed.size(), f), - compressed.size()); - file_util::CloseFile(f); - } - - // Returns the percentage of the image that is different from the other, - // between 0 and 100. - double PercentageDifferent(const Image& rhs) const { - if (size_ != rhs.size_ || row_length_ != rhs.row_length_ || - size_.width() == 0 || size_.height() == 0) - return 100.; // When of different size or empty, they are 100% different. - - // Compute pixels different in the overlap - int pixels_different = 0; - for (int y = 0; y < size_.height(); ++y) { - for (int x = 0; x < size_.width(); ++x) { - uint32_t lhs_pixel = pixel_at(x, y); - uint32_t rhs_pixel = rhs.pixel_at(x, y); - if (lhs_pixel != rhs_pixel) - ++pixels_different; - } - } - - // Like the WebKit ImageDiff tool, we define percentage different in terms - // of the size of the 'actual' bitmap. - double total_pixels = static_cast<double>(size_.width()) * - static_cast<double>(size_.height()); - return static_cast<double>(pixels_different) / total_pixels * 100.; - } - - // Returns the 0x0RGB or 0xARGB value of the pixel at the given location, - // depending on ignore_alpha_. - uint32 pixel_at(int x, int y) const { - EXPECT_TRUE(x >= 0 && x < size_.width()); - EXPECT_TRUE(y >= 0 && y < size_.height()); - const uint32* data = reinterpret_cast<const uint32*>(&*data_.begin()); - const uint32* data_row = data + y * row_length_ / sizeof(uint32); - if (ignore_alpha_) - return data_row[x] & 0xFFFFFF; // Strip out A. - else - return data_row[x]; - } - - private: - // Pixel dimensions of the image. - gfx::Size size_; - - // Length of a line in bytes. - int row_length_; - - // Actual bitmap data in arrays of RGBAs (so when loaded as uint32, it's - // 0xABGR). - std::vector<unsigned char> data_; - - // Flag to signal if the comparison functions should ignore the alpha channel. - const bool ignore_alpha_; - - DISALLOW_EVIL_CONSTRUCTORS(Image); -}; - -// Base for tests. Capability to process an image. -class ImageTest : public DataUnitTest { - public: - typedef DataUnitTest parent; - - // In what state is the test running. - enum ProcessAction { - GENERATE, - COMPARE, - NOOP, - }; - - ImageTest(const std::wstring& base_path, ProcessAction default_action) - : parent(base_path), - action_(default_action) { - } - - protected: - virtual void SetUp() { - parent::SetUp(); - - if (action_ == GENERATE) { - // Make sure the directory exist. - file_util::CreateDirectory(test_dir()); - } - } - - // Compares or saves the bitmap currently loaded in the context, depending on - // kGenerating value. Returns 0 on success or any positive value between ]0, - // 100] on failure. The return value is the percentage of difference between - // the image in the file and the image in the canvas. - double ProcessCanvas(const gfx::PlatformCanvasWin& canvas, - std::wstring filename) const { - filename += L".png"; - switch (action_) { - case GENERATE: - SaveImage(canvas, filename); - return 0.; - case COMPARE: - return CompareImage(canvas, filename); - case NOOP: - return 0; - default: - // Invalid state, returns that the image is 100 different. - return 100.; - } - } - - // Compares the bitmap currently loaded in the context with the file. Returns - // the percentage of pixel difference between both images, between 0 and 100. - double CompareImage(const gfx::PlatformCanvasWin& canvas, - const std::wstring& filename) const { - Image image1(canvas); - Image image2(test_file(filename)); - double diff = image1.PercentageDifferent(image2); - return diff; - } - - // Saves the bitmap currently loaded in the context into the file. - void SaveImage(const gfx::PlatformCanvasWin& canvas, - const std::wstring& filename) const { - Image(canvas).SaveToFile(test_file(filename)); - } - - ProcessAction action_; - - DISALLOW_EVIL_CONSTRUCTORS(ImageTest); -}; - -// Premultiply the Alpha channel on the R, B and G channels. -void Premultiply(SkBitmap bitmap) { - SkAutoLockPixels lock(bitmap); - for (int x = 0; x < bitmap.width(); ++x) { - for (int y = 0; y < bitmap.height(); ++y) { - uint32_t* pixel_addr = bitmap.getAddr32(x, y); - uint32_t color = *pixel_addr; - BYTE alpha = SkColorGetA(color); - if (!alpha) { - *pixel_addr = 0; - } else { - BYTE alpha_offset = alpha / 2; - *pixel_addr = SkColorSetARGB( - SkColorGetA(color), - (SkColorGetR(color) * 255 + alpha_offset) / alpha, - (SkColorGetG(color) * 255 + alpha_offset) / alpha, - (SkColorGetB(color) * 255 + alpha_offset) / alpha); - } - } - } -} - -void LoadPngFileToSkBitmap(const std::wstring& file, SkBitmap* bitmap) { - std::string compressed; - file_util::ReadFileToString(file, &compressed); - EXPECT_TRUE(compressed.size()); - // Extra-lame. If you care, fix it. - std::vector<unsigned char> data; - data.assign(reinterpret_cast<const unsigned char*>(compressed.c_str()), - reinterpret_cast<const unsigned char*>(compressed.c_str() + - compressed.size())); - EXPECT_TRUE(PNGDecoder::Decode(&data, bitmap)); - EXPECT_FALSE(bitmap->isOpaque()); - Premultiply(*bitmap); -} - -} // namespace - -// Streams an image. -inline std::ostream& operator<<(std::ostream& out, const Image& image) { - return out << "Image(" << image.size().width() << ", " - << image.size().height() << ", " << image.row_length() << ")"; -} - -// Runs simultaneously the same drawing commands on VectorCanvas and -// PlatformCanvas and compare the results. -class VectorCanvasTest : public ImageTest { - public: - typedef ImageTest parent; - - VectorCanvasTest() : parent(L"base", CurrentMode()), compare_canvas_(true) { - } - - protected: - virtual void SetUp() { - parent::SetUp(); - Init(100); - number_ = 0; - } - - virtual void TearDown() { - delete pcanvas_; - pcanvas_ = NULL; - - delete vcanvas_; - vcanvas_ = NULL; - - delete bitmap_; - bitmap_ = NULL; - - delete context_; - context_ = NULL; - - parent::TearDown(); - } - - void Init(int size) { - size_ = size; - context_ = new Context(); - bitmap_ = new Bitmap(*context_, size_, size_); - vcanvas_ = new gfx::VectorCanvas(context_->context(), size_, size_); - pcanvas_ = new gfx::PlatformCanvasWin(size_, size_, false); - - // Clear white. - vcanvas_->drawARGB(255, 255, 255, 255, SkPorterDuff::kSrc_Mode); - pcanvas_->drawARGB(255, 255, 255, 255, SkPorterDuff::kSrc_Mode); - } - - // Compares both canvas and returns the pixel difference in percentage between - // both images. 0 on success and ]0, 100] on failure. - double ProcessImage(const std::wstring& filename) { - std::wstring number(StringPrintf(L"%02d_", number_++)); - double diff1 = parent::ProcessCanvas(*vcanvas_, number + L"vc_" + filename); - double diff2 = parent::ProcessCanvas(*pcanvas_, number + L"pc_" + filename); - if (!compare_canvas_) - return std::max(diff1, diff2); - - Image image1(*vcanvas_); - Image image2(*pcanvas_); - double diff = image1.PercentageDifferent(image2); - return std::max(std::max(diff1, diff2), diff); - } - - // Returns COMPARE, which is the default. If kGenerateSwitch command - // line argument is used to start this process, GENERATE is returned instead. - static ProcessAction CurrentMode() { - return CommandLine().HasSwitch(kGenerateSwitch) ? GENERATE : COMPARE; - } - - // Length in x and y of the square canvas. - int size_; - - // Current image number in the current test. Used to number of test files. - int number_; - - // A temporary HDC to draw into. - Context* context_; - - // Bitmap created inside context_. - Bitmap* bitmap_; - - // Vector based canvas. - gfx::VectorCanvas* vcanvas_; - - // Pixel based canvas. - gfx::PlatformCanvasWin* pcanvas_; - - // When true (default), vcanvas_ and pcanvas_ contents are compared and - // verified to be identical. - bool compare_canvas_; -}; - - -//////////////////////////////////////////////////////////////////////////////// -// Actual tests - -TEST_F(VectorCanvasTest, Uninitialized) { - // Do a little mubadumba do get uninitialized stuff. - VectorCanvasTest::TearDown(); - - // The goal is not to verify that have the same uninitialized data. - compare_canvas_ = false; - - context_ = new Context(); - bitmap_ = new Bitmap(*context_, size_, size_); - vcanvas_ = new gfx::VectorCanvas(context_->context(), size_, size_); - pcanvas_ = new gfx::PlatformCanvasWin(size_, size_, false); - - // VectorCanvas default initialization is black. - // PlatformCanvas default initialization is almost white 0x01FFFEFD (invalid - // Skia color) in both Debug and Release. See magicTransparencyColor in - // platform_device.cc - EXPECT_EQ(0., ProcessImage(L"empty")); -} - -TEST_F(VectorCanvasTest, BasicDrawing) { - EXPECT_EQ(Image(*vcanvas_).PercentageDifferent(Image(*pcanvas_)), 0.) - << L"clean"; - EXPECT_EQ(0., ProcessImage(L"clean")); - - // Clear white. - { - vcanvas_->drawARGB(255, 255, 255, 255, SkPorterDuff::kSrc_Mode); - pcanvas_->drawARGB(255, 255, 255, 255, SkPorterDuff::kSrc_Mode); - } - EXPECT_EQ(0., ProcessImage(L"drawARGB")); - - // Diagonal line top-left to bottom-right. - { - SkPaint paint; - // Default color is black. - vcanvas_->drawLine(10, 10, 90, 90, paint); - pcanvas_->drawLine(10, 10, 90, 90, paint); - } - EXPECT_EQ(0., ProcessImage(L"drawLine_black")); - - // Rect. - { - SkPaint paint; - paint.setColor(SK_ColorGREEN); - vcanvas_->drawRectCoords(25, 25, 75, 75, paint); - pcanvas_->drawRectCoords(25, 25, 75, 75, paint); - } - EXPECT_EQ(0., ProcessImage(L"drawRect_green")); - - // A single-point rect doesn't leave any mark. - { - SkPaint paint; - paint.setColor(SK_ColorBLUE); - vcanvas_->drawRectCoords(5, 5, 5, 5, paint); - pcanvas_->drawRectCoords(5, 5, 5, 5, paint); - } - EXPECT_EQ(0., ProcessImage(L"drawRect_noop")); - - // Rect. - { - SkPaint paint; - paint.setColor(SK_ColorBLUE); - vcanvas_->drawRectCoords(75, 50, 80, 55, paint); - pcanvas_->drawRectCoords(75, 50, 80, 55, paint); - } - EXPECT_EQ(0., ProcessImage(L"drawRect_noop")); - - // Empty again - { - vcanvas_->drawPaint(SkPaint()); - pcanvas_->drawPaint(SkPaint()); - } - EXPECT_EQ(0., ProcessImage(L"drawPaint_black")); - - // Horizontal line left to right. - { - SkPaint paint; - paint.setColor(SK_ColorRED); - vcanvas_->drawLine(10, 20, 90, 20, paint); - pcanvas_->drawLine(10, 20, 90, 20, paint); - } - EXPECT_EQ(0., ProcessImage(L"drawLine_left_to_right")); - - // Vertical line downward. - { - SkPaint paint; - paint.setColor(SK_ColorRED); - vcanvas_->drawLine(30, 10, 30, 90, paint); - pcanvas_->drawLine(30, 10, 30, 90, paint); - } - EXPECT_EQ(0., ProcessImage(L"drawLine_red")); -} - -TEST_F(VectorCanvasTest, Circles) { - // There is NO WAY to make them agree. At least verify that the output doesn't - // change across versions. This test is disabled. See bug 1060231. - compare_canvas_ = false; - - // Stroked Circle. - { - SkPaint paint; - SkPath path; - path.addCircle(50, 75, 10); - paint.setStyle(SkPaint::kStroke_Style); - paint.setColor(SK_ColorMAGENTA); - vcanvas_->drawPath(path, paint); - pcanvas_->drawPath(path, paint); - } - EXPECT_EQ(0., ProcessImage(L"circle_stroke")); - - // Filled Circle. - { - SkPaint paint; - SkPath path; - path.addCircle(50, 25, 10); - paint.setStyle(SkPaint::kFill_Style); - vcanvas_->drawPath(path, paint); - pcanvas_->drawPath(path, paint); - } - EXPECT_EQ(0., ProcessImage(L"circle_fill")); - - // Stroked Circle over. - { - SkPaint paint; - SkPath path; - path.addCircle(50, 25, 10); - paint.setStyle(SkPaint::kStroke_Style); - paint.setColor(SK_ColorBLUE); - vcanvas_->drawPath(path, paint); - pcanvas_->drawPath(path, paint); - } - EXPECT_EQ(0., ProcessImage(L"circle_over_strike")); - - // Stroke and Fill Circle. - { - SkPaint paint; - SkPath path; - path.addCircle(12, 50, 10); - paint.setStyle(SkPaint::kStrokeAndFill_Style); - paint.setColor(SK_ColorRED); - vcanvas_->drawPath(path, paint); - pcanvas_->drawPath(path, paint); - } - EXPECT_EQ(0., ProcessImage(L"circle_stroke_and_fill")); - - // Line + Quad + Cubic. - { - SkPaint paint; - SkPath path; - paint.setStyle(SkPaint::kStroke_Style); - paint.setColor(SK_ColorGREEN); - path.moveTo(1, 1); - path.lineTo(60, 40); - path.lineTo(80, 80); - path.quadTo(20, 50, 10, 90); - path.quadTo(50, 20, 90, 10); - path.cubicTo(20, 40, 50, 50, 10, 10); - path.cubicTo(30, 20, 50, 50, 90, 10); - path.addRect(90, 90, 95, 96); - vcanvas_->drawPath(path, paint); - pcanvas_->drawPath(path, paint); - } - EXPECT_EQ(0., ProcessImage(L"mixed_stroke")); -} - -TEST_F(VectorCanvasTest, LineOrientation) { - // There is NO WAY to make them agree. At least verify that the output doesn't - // change across versions. This test is disabled. See bug 1060231. - compare_canvas_ = false; - - // Horizontal lines. - { - SkPaint paint; - paint.setColor(SK_ColorRED); - // Left to right. - vcanvas_->drawLine(10, 20, 90, 20, paint); - pcanvas_->drawLine(10, 20, 90, 20, paint); - // Right to left. - vcanvas_->drawLine(90, 30, 10, 30, paint); - pcanvas_->drawLine(90, 30, 10, 30, paint); - } - EXPECT_EQ(0., ProcessImage(L"horizontal")); - - // Vertical lines. - { - SkPaint paint; - paint.setColor(SK_ColorRED); - // Top down. - vcanvas_->drawLine(20, 10, 20, 90, paint); - pcanvas_->drawLine(20, 10, 20, 90, paint); - // Bottom up. - vcanvas_->drawLine(30, 90, 30, 10, paint); - pcanvas_->drawLine(30, 90, 30, 10, paint); - } - EXPECT_EQ(0., ProcessImage(L"vertical")); - - // Try again with a 180 degres rotation. - vcanvas_->rotate(180); - pcanvas_->rotate(180); - - // Horizontal lines (rotated). - { - SkPaint paint; - paint.setColor(SK_ColorRED); - vcanvas_->drawLine(-10, -25, -90, -25, paint); - pcanvas_->drawLine(-10, -25, -90, -25, paint); - vcanvas_->drawLine(-90, -35, -10, -35, paint); - pcanvas_->drawLine(-90, -35, -10, -35, paint); - } - EXPECT_EQ(0., ProcessImage(L"horizontal_180")); - - // Vertical lines (rotated). - { - SkPaint paint; - paint.setColor(SK_ColorRED); - vcanvas_->drawLine(-25, -10, -25, -90, paint); - pcanvas_->drawLine(-25, -10, -25, -90, paint); - vcanvas_->drawLine(-35, -90, -35, -10, paint); - pcanvas_->drawLine(-35, -90, -35, -10, paint); - } - EXPECT_EQ(0., ProcessImage(L"vertical_180")); -} - -TEST_F(VectorCanvasTest, PathOrientation) { - // There is NO WAY to make them agree. At least verify that the output doesn't - // change across versions. This test is disabled. See bug 1060231. - compare_canvas_ = false; - - // Horizontal lines. - { - SkPaint paint; - paint.setStyle(SkPaint::kStroke_Style); - paint.setColor(SK_ColorRED); - SkPath path; - SkPoint start; - start.set(10, 20); - SkPoint end; - end.set(90, 20); - path.moveTo(start); - path.lineTo(end); - vcanvas_->drawPath(path, paint); - pcanvas_->drawPath(path, paint); - } - EXPECT_EQ(0., ProcessImage(L"drawPath_ltr")); - - // Horizontal lines. - { - SkPaint paint; - paint.setStyle(SkPaint::kStroke_Style); - paint.setColor(SK_ColorRED); - SkPath path; - SkPoint start; - start.set(90, 30); - SkPoint end; - end.set(10, 30); - path.moveTo(start); - path.lineTo(end); - vcanvas_->drawPath(path, paint); - pcanvas_->drawPath(path, paint); - } - EXPECT_EQ(0., ProcessImage(L"drawPath_rtl")); -} - -TEST_F(VectorCanvasTest, DiagonalLines) { - SkPaint paint; - paint.setColor(SK_ColorRED); - - vcanvas_->drawLine(10, 10, 90, 90, paint); - pcanvas_->drawLine(10, 10, 90, 90, paint); - EXPECT_EQ(0., ProcessImage(L"nw-se")); - - // Starting here, there is NO WAY to make them agree. At least verify that the - // output doesn't change across versions. This test is disabled. See bug - // 1060231. - compare_canvas_ = false; - - vcanvas_->drawLine(10, 95, 90, 15, paint); - pcanvas_->drawLine(10, 95, 90, 15, paint); - EXPECT_EQ(0., ProcessImage(L"sw-ne")); - - vcanvas_->drawLine(90, 10, 10, 90, paint); - pcanvas_->drawLine(90, 10, 10, 90, paint); - EXPECT_EQ(0., ProcessImage(L"ne-sw")); - - vcanvas_->drawLine(95, 90, 15, 10, paint); - pcanvas_->drawLine(95, 90, 15, 10, paint); - EXPECT_EQ(0., ProcessImage(L"se-nw")); -} - -TEST_F(VectorCanvasTest, PathEffects) { - { - SkPaint paint; - SkScalar intervals[] = { 1, 1 }; - SkPathEffect* effect = new SkDashPathEffect(intervals, arraysize(intervals), - 0); - paint.setPathEffect(effect)->unref(); - paint.setColor(SK_ColorMAGENTA); - paint.setStyle(SkPaint::kStroke_Style); - - vcanvas_->drawLine(10, 10, 90, 10, paint); - pcanvas_->drawLine(10, 10, 90, 10, paint); - } - EXPECT_EQ(0., ProcessImage(L"dash_line")); - - - // Starting here, there is NO WAY to make them agree. At least verify that the - // output doesn't change across versions. This test is disabled. See bug - // 1060231. - compare_canvas_ = false; - - { - SkPaint paint; - SkScalar intervals[] = { 3, 5 }; - SkPathEffect* effect = new SkDashPathEffect(intervals, arraysize(intervals), - 0); - paint.setPathEffect(effect)->unref(); - paint.setColor(SK_ColorMAGENTA); - paint.setStyle(SkPaint::kStroke_Style); - - SkPath path; - path.moveTo(10, 15); - path.lineTo(90, 15); - path.lineTo(90, 90); - vcanvas_->drawPath(path, paint); - pcanvas_->drawPath(path, paint); - } - EXPECT_EQ(0., ProcessImage(L"dash_path")); - - { - SkPaint paint; - SkScalar intervals[] = { 2, 1 }; - SkPathEffect* effect = new SkDashPathEffect(intervals, arraysize(intervals), - 0); - paint.setPathEffect(effect)->unref(); - paint.setColor(SK_ColorMAGENTA); - paint.setStyle(SkPaint::kStroke_Style); - - vcanvas_->drawRectCoords(20, 20, 30, 30, paint); - pcanvas_->drawRectCoords(20, 20, 30, 30, paint); - } - EXPECT_EQ(0., ProcessImage(L"dash_rect")); - - // This thing looks like it has been drawn by a 3 years old kid. I haven't - // filed a bug on this since I guess nobody is expecting this to look nice. - { - SkPaint paint; - SkScalar intervals[] = { 1, 1 }; - SkPathEffect* effect = new SkDashPathEffect(intervals, arraysize(intervals), - 0); - paint.setPathEffect(effect)->unref(); - paint.setColor(SK_ColorMAGENTA); - paint.setStyle(SkPaint::kStroke_Style); - - SkPath path; - path.addCircle(50, 75, 10); - vcanvas_->drawPath(path, paint); - pcanvas_->drawPath(path, paint); - EXPECT_EQ(0., ProcessImage(L"circle")); - } -} - -TEST_F(VectorCanvasTest, Bitmaps) { - // ICM is enabled on VectorCanvas only on Windows 2000 so bitmap-based tests - // can't compare the pixels between PlatformCanvas and VectorCanvas. We don't - // really care about Windows 2000 pixel colors. - if (win_util::GetWinVersion() <= win_util::WINVERSION_2000) - return; - { - SkBitmap bitmap; - LoadPngFileToSkBitmap(test_file(L"bitmap_opaque.png"), &bitmap); - vcanvas_->drawBitmap(bitmap, 13, 3, NULL); - pcanvas_->drawBitmap(bitmap, 13, 3, NULL); - EXPECT_EQ(0., ProcessImage(L"opaque")); - } - - { - SkBitmap bitmap; - LoadPngFileToSkBitmap(test_file(L"bitmap_alpha.png"), &bitmap); - vcanvas_->drawBitmap(bitmap, 5, 15, NULL); - pcanvas_->drawBitmap(bitmap, 5, 15, NULL); - EXPECT_EQ(0., ProcessImage(L"alpha")); - } -} - -TEST_F(VectorCanvasTest, ClippingRect) { - // ICM is enabled on VectorCanvas only on Windows 2000 so bitmap-based tests - // can't compare the pixels between PlatformCanvas and VectorCanvas. We don't - // really care about Windows 2000 pixel colors. - if (win_util::GetWinVersion() <= win_util::WINVERSION_2000) - return; - SkBitmap bitmap; - LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap); - SkRect rect; - rect.fLeft = 2; - rect.fTop = 2; - rect.fRight = 30.5f; - rect.fBottom = 30.5f; - vcanvas_->clipRect(rect); - pcanvas_->clipRect(rect); - - vcanvas_->drawBitmap(bitmap, 13, 3, NULL); - pcanvas_->drawBitmap(bitmap, 13, 3, NULL); - EXPECT_EQ(0., ProcessImage(L"rect")); -} - -TEST_F(VectorCanvasTest, ClippingPath) { - // ICM is enabled on VectorCanvas only on Windows 2000 so bitmap-based tests - // can't compare the pixels between PlatformCanvas and VectorCanvas. We don't - // really care about Windows 2000 pixel colors. - if (win_util::GetWinVersion() <= win_util::WINVERSION_2000) - return; - SkBitmap bitmap; - LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap); - SkPath path; - path.addCircle(20, 20, 10); - vcanvas_->clipPath(path); - pcanvas_->clipPath(path); - - vcanvas_->drawBitmap(bitmap, 14, 3, NULL); - pcanvas_->drawBitmap(bitmap, 14, 3, NULL); - EXPECT_EQ(0., ProcessImage(L"path")); -} - -TEST_F(VectorCanvasTest, ClippingCombined) { - // ICM is enabled on VectorCanvas only on Windows 2000 so bitmap-based tests - // can't compare the pixels between PlatformCanvas and VectorCanvas. We don't - // really care about Windows 2000 pixel colors. - if (win_util::GetWinVersion() <= win_util::WINVERSION_2000) - return; - SkBitmap bitmap; - LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap); - - SkRect rect; - rect.fLeft = 2; - rect.fTop = 2; - rect.fRight = 30.5f; - rect.fBottom = 30.5f; - vcanvas_->clipRect(rect); - pcanvas_->clipRect(rect); - SkPath path; - path.addCircle(20, 20, 10); - vcanvas_->clipPath(path, SkRegion::kUnion_Op); - pcanvas_->clipPath(path, SkRegion::kUnion_Op); - - vcanvas_->drawBitmap(bitmap, 15, 3, NULL); - pcanvas_->drawBitmap(bitmap, 15, 3, NULL); - EXPECT_EQ(0., ProcessImage(L"combined")); -} - -TEST_F(VectorCanvasTest, ClippingIntersect) { - // ICM is enabled on VectorCanvas only on Windows 2000 so bitmap-based tests - // can't compare the pixels between PlatformCanvas and VectorCanvas. We don't - // really care about Windows 2000 pixel colors. - if (win_util::GetWinVersion() <= win_util::WINVERSION_2000) - return; - SkBitmap bitmap; - LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap); - - SkRect rect; - rect.fLeft = 2; - rect.fTop = 2; - rect.fRight = 30.5f; - rect.fBottom = 30.5f; - vcanvas_->clipRect(rect); - pcanvas_->clipRect(rect); - SkPath path; - path.addCircle(23, 23, 15); - vcanvas_->clipPath(path); - pcanvas_->clipPath(path); - - vcanvas_->drawBitmap(bitmap, 15, 3, NULL); - pcanvas_->drawBitmap(bitmap, 15, 3, NULL); - EXPECT_EQ(0., ProcessImage(L"intersect")); -} - -TEST_F(VectorCanvasTest, ClippingClean) { - // ICM is enabled on VectorCanvas only on Windows 2000 so bitmap-based tests - // can't compare the pixels between PlatformCanvas and VectorCanvas. We don't - // really care about Windows 2000 pixel colors. - if (win_util::GetWinVersion() <= win_util::WINVERSION_2000) - return; - SkBitmap bitmap; - LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap); - { - SkRegion old_region(pcanvas_->getTotalClip()); - SkRect rect; - rect.fLeft = 2; - rect.fTop = 2; - rect.fRight = 30.5f; - rect.fBottom = 30.5f; - vcanvas_->clipRect(rect); - pcanvas_->clipRect(rect); - - vcanvas_->drawBitmap(bitmap, 15, 3, NULL); - pcanvas_->drawBitmap(bitmap, 15, 3, NULL); - EXPECT_EQ(0., ProcessImage(L"clipped")); - vcanvas_->clipRegion(old_region, SkRegion::kReplace_Op); - pcanvas_->clipRegion(old_region, SkRegion::kReplace_Op); - } - { - // Verify that the clipping region has been fixed back. - vcanvas_->drawBitmap(bitmap, 55, 3, NULL); - pcanvas_->drawBitmap(bitmap, 55, 3, NULL); - EXPECT_EQ(0., ProcessImage(L"unclipped")); - } -} - -TEST_F(VectorCanvasTest, Matrix) { - // ICM is enabled on VectorCanvas only on Windows 2000 so bitmap-based tests - // can't compare the pixels between PlatformCanvas and VectorCanvas. We don't - // really care about Windows 2000 pixel colors. - if (win_util::GetWinVersion() <= win_util::WINVERSION_2000) - return; - SkBitmap bitmap; - LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap); - { - vcanvas_->translate(15, 3); - pcanvas_->translate(15, 3); - vcanvas_->drawBitmap(bitmap, 0, 0, NULL); - pcanvas_->drawBitmap(bitmap, 0, 0, NULL); - EXPECT_EQ(0., ProcessImage(L"translate1")); - } - { - vcanvas_->translate(-30, -23); - pcanvas_->translate(-30, -23); - vcanvas_->drawBitmap(bitmap, 0, 0, NULL); - pcanvas_->drawBitmap(bitmap, 0, 0, NULL); - EXPECT_EQ(0., ProcessImage(L"translate2")); - } - vcanvas_->resetMatrix(); - pcanvas_->resetMatrix(); - - // For scaling and rotation, they use a different algorithm (nearest - // neighborhood vs smoothing). At least verify that the output doesn't change - // across versions. - compare_canvas_ = false; - - { - vcanvas_->scale(SkDoubleToScalar(1.9), SkDoubleToScalar(1.5)); - pcanvas_->scale(SkDoubleToScalar(1.9), SkDoubleToScalar(1.5)); - vcanvas_->drawBitmap(bitmap, 1, 1, NULL); - pcanvas_->drawBitmap(bitmap, 1, 1, NULL); - EXPECT_EQ(0., ProcessImage(L"scale")); - } - vcanvas_->resetMatrix(); - pcanvas_->resetMatrix(); - - { - vcanvas_->rotate(67); - pcanvas_->rotate(67); - vcanvas_->drawBitmap(bitmap, 20, -50, NULL); - pcanvas_->drawBitmap(bitmap, 20, -50, NULL); - EXPECT_EQ(0., ProcessImage(L"rotate")); - } -} - |