diff options
Diffstat (limited to 'base')
30 files changed, 39 insertions, 4488 deletions
diff --git a/base/base_unittests.scons b/base/base_unittests.scons index 61f9140..b8aafbc 100644 --- a/base/base_unittests.scons +++ b/base/base_unittests.scons @@ -124,7 +124,6 @@ input_files = [ 'gfx/native_theme_unittest.cc', 'gfx/png_codec_unittest.cc', 'gfx/rect_unittest.cc', - 'gfx/vector_canvas_unittest.cc', ] if env['PLATFORM'] in ('posix', 'darwin'): @@ -139,7 +138,6 @@ if env['PLATFORM'] in ('posix', 'darwin'): 'watchdog_unittest.cc', 'gfx/native_theme_unittest.cc', - 'gfx/vector_canvas_unittest.cc', ] for remove in to_be_ported_files: input_files.remove(remove) diff --git a/base/build/base_gfx.vcproj b/base/build/base_gfx.vcproj index 22dc8b4..8b2bc64 100644 --- a/base/build/base_gfx.vcproj +++ b/base/build/base_gfx.vcproj @@ -122,10 +122,6 @@ </References> <Files> <File - RelativePath="..\gfx\bitmap_platform_device_win.cc" - > - </File> - <File RelativePath="..\gfx\bitmap_platform_device_win.h" > </File> @@ -162,18 +158,10 @@ > </File> <File - RelativePath="..\gfx\platform_canvas_win.cc" - > - </File> - <File RelativePath="..\gfx\platform_canvas_win.h" > </File> <File - RelativePath="..\gfx\platform_device_win.cc" - > - </File> - <File RelativePath="..\gfx\platform_device_win.h" > </File> @@ -225,22 +213,6 @@ RelativePath="..\gfx\skia_utils.h" > </File> - <File - RelativePath="..\gfx\vector_canvas.cc" - > - </File> - <File - RelativePath="..\gfx\vector_canvas.h" - > - </File> - <File - RelativePath="..\gfx\vector_device.cc" - > - </File> - <File - RelativePath="..\gfx\vector_device.h" - > - </File> </Files> <Globals> </Globals> diff --git a/base/build/base_unittests.vcproj b/base/build/base_unittests.vcproj index df3444b..3c75166 100644 --- a/base/build/base_unittests.vcproj +++ b/base/build/base_unittests.vcproj @@ -404,17 +404,9 @@ > </File> <File - RelativePath="..\gfx\platform_canvas_unittest.cc" - > - </File> - <File RelativePath="..\gfx\png_codec_unittest.cc" > </File> - <File - RelativePath="..\gfx\vector_canvas_unittest.cc" - > - </File> </Filter> </Files> <Globals> diff --git a/base/gfx/base_gfx.scons b/base/gfx/base_gfx.scons index 748f13b..0af67c6 100644 --- a/base/gfx/base_gfx.scons +++ b/base/gfx/base_gfx.scons @@ -42,8 +42,6 @@ input_files = [ 'rect.cc', 'size.cc', 'skia_utils.cc', - 'vector_canvas.cc', - 'vector_device.cc', ] if env['PLATFORM'] in ('posix', 'darwin'): @@ -53,23 +51,15 @@ if env['PLATFORM'] in ('posix', 'darwin'): 'gdi_util.cc', 'native_theme.cc', 'skia_utils.cc', - 'vector_canvas.cc', - 'vector_device.cc', ] for remove in to_be_ported_files: input_files.remove(remove) if env['PLATFORM'] == 'win32': input_files.extend([ - 'bitmap_platform_device_win.cc', - 'platform_canvas_win.cc', - 'platform_device_win.cc', ]) elif env['PLATFORM'] == 'posix': input_files.extend([ - 'bitmap_platform_device_linux.cc', - 'platform_canvas_linux.cc', - 'platform_device_linux.cc', ]) env.ChromeStaticLibrary('base_gfx', input_files) diff --git a/base/gfx/bitmap_platform_device.h b/base/gfx/bitmap_platform_device.h index 1efa65c..7c25eb2 100644 --- a/base/gfx/bitmap_platform_device.h +++ b/base/gfx/bitmap_platform_device.h @@ -2,26 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Declare a platform-neutral name for this platform's bitmap device class -// that can be used by upper-level classes that just need to pass a reference -// around. - -#if defined(OS_WIN) -#include "base/gfx/bitmap_platform_device_win.h" -#elif defined(OS_MACOSX) -#include "base/gfx/bitmap_platform_device_mac.h" -#elif defined(OS_LINUX) -#include "base/gfx/bitmap_platform_device_linux.h" -#endif - -namespace gfx { - -#if defined(OS_WIN) -typedef BitmapPlatformDeviceWin BitmapPlatformDevice; -#elif defined(OS_MACOSX) -typedef BitmapPlatformDeviceMac BitmapPlatformDevice; -#elif defined(OS_LINUX) -typedef BitmapPlatformDeviceLinux BitmapPlatformDevice; -#endif - -} +// TODO(brettw) this file should be removed and the includes changed to this +// new location. +#include "webkit/port/platform/graphics/skia/public/BitmapPlatformDevice.h" diff --git a/base/gfx/bitmap_platform_device_linux.cc b/base/gfx/bitmap_platform_device_linux.cc deleted file mode 100644 index 18f8ab1..0000000 --- a/base/gfx/bitmap_platform_device_linux.cc +++ /dev/null @@ -1,94 +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/bitmap_platform_device_linux.h" - -#include <cairo/cairo.h> - -#include "base/logging.h" - -namespace gfx { - -// ----------------------------------------------------------------------------- -// These objects are reference counted and own a Cairo surface. The surface is -// the backing store for a Skia bitmap and we reference count it so that we can -// copy BitmapPlatformDeviceLinux objects without having to copy all the image -// data. -// ----------------------------------------------------------------------------- -class BitmapPlatformDeviceLinux::BitmapPlatformDeviceLinuxData - : public base::RefCounted<BitmapPlatformDeviceLinuxData> { - public: - explicit BitmapPlatformDeviceLinuxData(cairo_surface_t* surface) - : surface_(surface) { } - - cairo_surface_t* surface() const { return surface_; } - - protected: - cairo_surface_t *const surface_; - - friend class base::RefCounted<BitmapPlatformDeviceLinuxData>; - ~BitmapPlatformDeviceLinuxData() { - cairo_surface_destroy(surface_); - } - - DISALLOW_EVIL_CONSTRUCTORS(BitmapPlatformDeviceLinuxData); -}; - -// 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. -BitmapPlatformDeviceLinux* BitmapPlatformDeviceLinux::Create( - int width, int height, bool is_opaque) { - cairo_surface_t* surface = - cairo_image_surface_create(CAIRO_FORMAT_ARGB32, - width, height); - - SkBitmap bitmap; - bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height, - cairo_image_surface_get_stride(surface)); - bitmap.setPixels(cairo_image_surface_get_data(surface)); - bitmap.setIsOpaque(is_opaque); - -#ifndef NDEBUG - if (is_opaque) { - bitmap.eraseARGB(255, 0, 255, 128); // bright bluish green - } -#endif - - // The device object will take ownership of the graphics context. - return new BitmapPlatformDeviceLinux - (bitmap, new BitmapPlatformDeviceLinuxData(surface)); -} - -// The device will own the bitmap, which corresponds to also owning the pixel -// data. Therefore, we do not transfer ownership to the SkDevice's bitmap. -BitmapPlatformDeviceLinux::BitmapPlatformDeviceLinux( - const SkBitmap& bitmap, - BitmapPlatformDeviceLinuxData* data) - : PlatformDeviceLinux(bitmap), - data_(data) { -} - -BitmapPlatformDeviceLinux::BitmapPlatformDeviceLinux( - const BitmapPlatformDeviceLinux& other) - : PlatformDeviceLinux(const_cast<BitmapPlatformDeviceLinux&>( - other).accessBitmap(true)), - data_(other.data_) { -} - -BitmapPlatformDeviceLinux::~BitmapPlatformDeviceLinux() { -} - -cairo_surface_t* BitmapPlatformDeviceLinux::surface() const { - return data_->surface(); -} - -BitmapPlatformDeviceLinux& BitmapPlatformDeviceLinux::operator=( - const BitmapPlatformDeviceLinux& other) { - data_ = other.data_; - return *this; -} - -} // namespace gfx diff --git a/base/gfx/bitmap_platform_device_linux.h b/base/gfx/bitmap_platform_device_linux.h index 629fd1d..3db11cb 100644 --- a/base/gfx/bitmap_platform_device_linux.h +++ b/base/gfx/bitmap_platform_device_linux.h @@ -5,87 +5,8 @@ #ifndef BASE_GFX_BITMAP_PLATFORM_DEVICE_LINUX_H_ #define BASE_GFX_BITMAP_PLATFORM_DEVICE_LINUX_H_ -#include "base/gfx/platform_device_linux.h" -#include "base/ref_counted.h" - -typedef struct _cairo_surface cairo_surface_t; - -// ----------------------------------------------------------------------------- -// Image byte ordering on Linux: -// -// Pixels are packed into 32-bit words these days. Even for 24-bit images, -// often 8-bits will be left unused for alignment reasons. Thus, when you see -// ARGB as the byte order you have to wonder if that's in memory order or -// little-endian order. Here I'll write A.R.G.B to specifiy the memory order. -// -// GdkPixbuf's provide a nice backing store and defaults to R.G.B.A order. -// They'll do the needed byte swapping to match the X server when drawn. -// -// Skia can be controled in skia/include/corecg/SkUserConfig.h (see bits about -// SK_R32_SHIFT). For Linux we define it to be ARGB in registers. For little -// endian machines that means B.G.R.A in memory. -// -// The image loaders are controlled in -// webkit/port/platform/image-decoders/ImageDecoder.h (see setRGBA). These are -// also configured for ARGB in registers. -// -// Cairo's only 32-bit mode is ARGB in registers. -// -// X servers commonly have a 32-bit visual with xRGB in registers (since they -// typically don't do alpha blending of drawables at the user level. Composite -// extensions aside.) -// -// We don't use GdkPixbuf because its byte order differs from the rest. Most -// importantly, it differs from Cairo which, being a system library, is -// something that we can't easily change. -// ----------------------------------------------------------------------------- - -namespace gfx { - -// ----------------------------------------------------------------------------- -// This is the Linux bitmap backing for Skia. We create a Cairo image surface -// to store the backing buffer. This buffer is BGRA in memory (on little-endian -// machines). -// -// For now we are also using Cairo to paint to the Drawables so we provide an -// accessor for getting the surface. -// -// This is all quite ok for test_shell. In the future we will want to use -// shared memory between the renderer and the main process at least. In this -// case we'll probably create the buffer from a precreated region of memory. -// ----------------------------------------------------------------------------- -class BitmapPlatformDeviceLinux : public PlatformDeviceLinux { - // A reference counted cairo surface - class BitmapPlatformDeviceLinuxData; - - public: - /// Static constructor. I don't understand this, it's just a copy of the mac - static BitmapPlatformDeviceLinux* Create(int width, int height, - bool is_opaque); - - // Create a BitmapPlatformDeviceLinux from an already constructed bitmap; - // you should probably be using Create(). This may become private later if - // we ever have to share state between some native drawing UI and Skia, like - // the Windows and Mac versions of this class do. - // - // This object takes ownership of @data. - BitmapPlatformDeviceLinux(const SkBitmap& other, - BitmapPlatformDeviceLinuxData* data); - virtual ~BitmapPlatformDeviceLinux(); - BitmapPlatformDeviceLinux& operator=(const BitmapPlatformDeviceLinux& other); - - // A stub copy constructor. Needs to be properly implemented. - BitmapPlatformDeviceLinux(const BitmapPlatformDeviceLinux& other); - - // Bitmaps aren't vector graphics. - virtual bool IsVectorial() { return false; } - - cairo_surface_t* surface() const; - - private: - scoped_refptr<BitmapPlatformDeviceLinuxData> data_; -}; - -} // namespace gfx +// TODO(brettw) this file should be removed and the includes changed to this +// new location. +#include "webkit/port/platform/graphics/skia/public/BitmapPlatformDeviceLinux.h" #endif // BASE_GFX_BITMAP_PLATFORM_DEVICE_LINUX_H_ diff --git a/base/gfx/bitmap_platform_device_mac.cc b/base/gfx/bitmap_platform_device_mac.cc deleted file mode 100755 index 570b07e..0000000 --- a/base/gfx/bitmap_platform_device_mac.cc +++ /dev/null @@ -1,289 +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 <time.h> - -#include "SkMatrix.h" -#include "SkRegion.h" -#include "SkUtils.h" - -#include "base/gfx/bitmap_platform_device_mac.h" -#include "base/gfx/skia_utils_mac.h" -#include "base/logging.h" - -namespace gfx { - -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; -} - -} // namespace - -class BitmapPlatformDeviceMac::BitmapPlatformDeviceMacData - : public base::RefCounted<BitmapPlatformDeviceMacData> { - public: - explicit BitmapPlatformDeviceMacData(CGContextRef bitmap); - - // Create/destroy CoreGraphics context for our bitmap data. - CGContextRef GetBitmapContext() { - LoadConfig(); - return bitmap_context_; - } - - void ReleaseBitmapContext() { - DCHECK(bitmap_context_); - CGContextRelease(bitmap_context_); - bitmap_context_ = NULL; - } - - // Sets the transform and clip operations. This will not update the CGContext, - // 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); - - // Loads the current transform and clip into the DC. Can be called even when - // |bitmap_context_| is NULL (will be a NOP). - void LoadConfig(); - - // Lazily-created graphics context used to draw into the bitmap. - CGContextRef bitmap_context_; - - // True when there is a transform or clip that has not been set to the - // CGContext. The CGContext 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 CGContext: we need to keep track of this - // separately so it can be updated even if the CGContext isn't created yet. - SkMatrix transform_; - - // The current clipping - SkRegion clip_region_; - - private: - friend class base::RefCounted<BitmapPlatformDeviceMacData>; - ~BitmapPlatformDeviceMacData() { - if (bitmap_context_) - CGContextRelease(bitmap_context_); - } - - DISALLOW_COPY_AND_ASSIGN(BitmapPlatformDeviceMacData); -}; - -BitmapPlatformDeviceMac::\ - BitmapPlatformDeviceMacData::BitmapPlatformDeviceMacData( - CGContextRef bitmap) - : bitmap_context_(bitmap), - config_dirty_(true) { // Want to load the config next time. - DCHECK(bitmap_context_); - // Initialize the clip region to the entire bitmap. - - SkIRect rect; - rect.set(0, 0, - CGBitmapContextGetWidth(bitmap_context_), - CGBitmapContextGetHeight(bitmap_context_)); - clip_region_ = SkRegion(rect); - transform_.reset(); - CGContextRetain(bitmap_context_); -} - -void BitmapPlatformDeviceMac::BitmapPlatformDeviceMacData::SetMatrixClip( - const SkMatrix& transform, - const SkRegion& region) { - transform_ = transform; - clip_region_ = region; - config_dirty_ = true; -} - -void BitmapPlatformDeviceMac::BitmapPlatformDeviceMacData::LoadConfig() { - if (!config_dirty_ || !bitmap_context_) - return; // Nothing to do. - config_dirty_ = false; - - // Transform. - SkMatrix t(transform_); - LoadTransformToCGContext(bitmap_context_, t); - t.setTranslateX(-t.getTranslateX()); - t.setTranslateY(-t.getTranslateY()); - LoadClippingRegionToCGContext(bitmap_context_, 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. -BitmapPlatformDeviceMac* BitmapPlatformDeviceMac::Create(CGContextRef context, - int width, - int height, - bool is_opaque) { - void* data = malloc(height * width * 4); - if (!data) return NULL; - - SkBitmap bitmap; - bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height); - bitmap.setPixels(data); - - // Note: The Windows implementation clears the Bitmap later on. - // This bears mentioning since removal of this line makes the - // unit tests only fail periodically (or when MallocPreScribble is set). - bitmap.eraseARGB(0, 0, 0, 0); - - 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 - } - - CGColorSpaceRef color_space = - CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); - // allocate a bitmap context with 4 components per pixel (RGBA): - CGContextRef bitmap_context = - CGBitmapContextCreate(data, width, height, 8, width*4, - color_space, kCGImageAlphaPremultipliedLast); - - // Change the coordinate system to match WebCore's - CGContextTranslateCTM(bitmap_context, 0, height); - CGContextScaleCTM(bitmap_context, 1.0, -1.0); - CGColorSpaceRelease(color_space); - - // The device object will take ownership of the graphics context. - return new BitmapPlatformDeviceMac( - new BitmapPlatformDeviceMacData(bitmap_context), bitmap); -} - -// The device will own the bitmap, which corresponds to also owning the pixel -// data. Therefore, we do not transfer ownership to the SkDevice's bitmap. -BitmapPlatformDeviceMac::BitmapPlatformDeviceMac( - BitmapPlatformDeviceMacData* data, const SkBitmap& bitmap) - : PlatformDeviceMac(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). -BitmapPlatformDeviceMac::BitmapPlatformDeviceMac( - const BitmapPlatformDeviceMac& other) - : PlatformDeviceMac( - const_cast<BitmapPlatformDeviceMac&>(other).accessBitmap(true)), - data_(other.data_) { -} - -BitmapPlatformDeviceMac::~BitmapPlatformDeviceMac() { -} - -BitmapPlatformDeviceMac& BitmapPlatformDeviceMac::operator=( - const BitmapPlatformDeviceMac& other) { - data_ = other.data_; - return *this; -} - -CGContextRef BitmapPlatformDeviceMac::GetBitmapContext() { - return data_->GetBitmapContext(); -} - -void BitmapPlatformDeviceMac::setMatrixClip(const SkMatrix& transform, - const SkRegion& region) { - data_->SetMatrixClip(transform, region); -} - -void BitmapPlatformDeviceMac::DrawToContext(CGContextRef context, int x, int y, - const CGRect* src_rect) { - bool created_dc = false; - if (!data_->bitmap_context_) { - created_dc = true; - GetBitmapContext(); - } - - // this should not make a copy of the bits, since we're not doing - // anything to trigger copy on write - CGImageRef image = CGBitmapContextCreateImage(data_->bitmap_context_); - CGRect bounds; - if (src_rect) { - bounds = *src_rect; - bounds.origin.x = x; - bounds.origin.y = y; - CGImageRef sub_image = CGImageCreateWithImageInRect(image, *src_rect); - CGContextDrawImage(context, bounds, sub_image); - CGImageRelease(sub_image); - } else { - bounds.origin.x = 0; - bounds.origin.y = 0; - bounds.size.width = width(); - bounds.size.height = height(); - CGContextDrawImage(context, bounds, image); - } - CGImageRelease(image); - - if (created_dc) - data_->ReleaseBitmapContext(); -} - -// Returns the color value at the specified location. -SkColor BitmapPlatformDeviceMac::getColorAt(int x, int y) { - const SkBitmap& bitmap = accessBitmap(true); - SkAutoLockPixels lock(bitmap); - uint32_t* data = bitmap.getAddr32(0, 0); - return static_cast<SkColor>(data[x + y * width()]); -} - -void BitmapPlatformDeviceMac::onAccessBitmap(SkBitmap*) { - // Not needed in CoreGraphics -} - -void BitmapPlatformDeviceMac::processPixels(int x, int y, - int width, int height, - adjustAlpha adjustor) { - const SkBitmap& bitmap = accessBitmap(true); - SkMatrix& matrix = data_->transform_; - int bitmap_start_x = SkScalarRound(matrix.getTranslateX()) + x; - int bitmap_start_y = SkScalarRound(matrix.getTranslateY()) + y; - - SkAutoLockPixels lock(bitmap); - if (Constrain(bitmap.width(), &bitmap_start_x, &width) && - Constrain(bitmap.height(), &bitmap_start_y, &height)) { - uint32_t* data = bitmap.getAddr32(0, 0); - size_t row_words = bitmap.rowBytes() / 4; - for (int i = 0; i < height; i++) { - size_t offset = (i + bitmap_start_y) * row_words + bitmap_start_x; - for (int j = 0; j < width; j++) { - adjustor(data + offset + j); - } - } - } -} - -} // namespace gfx - diff --git a/base/gfx/bitmap_platform_device_mac.h b/base/gfx/bitmap_platform_device_mac.h index a008444..ff89741 100755 --- a/base/gfx/bitmap_platform_device_mac.h +++ b/base/gfx/bitmap_platform_device_mac.h @@ -5,91 +5,9 @@ #ifndef BASE_GFX_BITMAP_PLATFORM_DEVICE_MAC_H__ #define BASE_GFX_BITMAP_PLATFORM_DEVICE_MAC_H__ -#include "base/gfx/platform_device_mac.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 CoreGraphics can also -// write to. BitmapPlatformDeviceMac creates a bitmap using -// CGCreateBitmapContext() in a format that Skia supports and can then use this -// to draw text 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 BitmapPlatformDeviceMac : public PlatformDeviceMac { - 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 BitmapPlatformDeviceMac* Create(CGContextRef context, - int width, - int height, - bool is_opaque); - - // Copy constructor. When copied, devices duplicate their internal data, so - // stay linked. This is because their implementation is very heavyweight - // (lots of memory and CoreGraphics state). 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 CoreGraphics drawing state will be unpredictable. - // - // Copy constucting and "=" is designed for saving the device or passing it - // around to another routine willing to deal with the bitmap data directly. - BitmapPlatformDeviceMac(const BitmapPlatformDeviceMac& other); - virtual ~BitmapPlatformDeviceMac(); - - // See warning for copy constructor above. - BitmapPlatformDeviceMac& operator=(const BitmapPlatformDeviceMac& other); - - virtual CGContextRef GetBitmapContext(); - virtual void setMatrixClip(const SkMatrix& transform, const SkRegion& region); - - virtual void DrawToContext(CGContextRef context, int x, int y, - const CGRect* src_rect); - virtual bool IsVectorial() { return false; } - virtual void fixupAlphaBeforeCompositing() { }; - - // 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: - // 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 BitmapPlatformDeviceMacData; - - BitmapPlatformDeviceMac(BitmapPlatformDeviceMacData* data, - const SkBitmap& bitmap); - - // Flushes the CoreGraphics 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*); - - // Data associated with this device, guaranteed non-null. - scoped_refptr<BitmapPlatformDeviceMacData> data_; - - virtual void processPixels(int x, int y, - int width, int height, - adjustAlpha adjustor); -}; - -} // namespace gfx +// TODO(brettw) this file should be removed and the includes changed to this +// new location. +#include "webkit/port/platform/graphics/skia/public/BitmapPlatformDeviceMac.h" #endif // BASE_GFX_BITMAP_PLATFORM_DEVICE_MAC_H__ diff --git a/base/gfx/bitmap_platform_device_win.cc b/base/gfx/bitmap_platform_device_win.cc deleted file mode 100644 index 85597ae..0000000 --- a/base/gfx/bitmap_platform_device_win.cc +++ /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 "base/gfx/bitmap_platform_device_win.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/base/gfx/bitmap_platform_device_win.h b/base/gfx/bitmap_platform_device_win.h index fef7217..566e302 100644 --- a/base/gfx/bitmap_platform_device_win.h +++ b/base/gfx/bitmap_platform_device_win.h @@ -5,107 +5,9 @@ #ifndef BASE_GFX_BITMAP_PLATFORM_DEVICE_WIN_H_ #define BASE_GFX_BITMAP_PLATFORM_DEVICE_WIN_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 +// TODO(brettw) this file should be removed and the includes changed to this +// new location. +#include "webkit/port/platform/graphics/skia/public/BitmapPlatformDeviceWin.h" #endif // BASE_GFX_BITMAP_PLATFORM_DEVICE_WIN_H_ diff --git a/base/gfx/platform_canvas.h b/base/gfx/platform_canvas.h index d7442cc..5bf0ec1 100644 --- a/base/gfx/platform_canvas.h +++ b/base/gfx/platform_canvas.h @@ -2,31 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Declare a platform-neutral name for this platform's canvas class -// that can be used by upper-level classes that just need to pass a reference -// around. - -#include "build/build_config.h" - -#if defined(OS_WIN) -#include "base/gfx/platform_canvas_win.h" -namespace gfx { - -typedef PlatformCanvasWin PlatformCanvas; - -} // namespace gfx -#elif defined(OS_MACOSX) -#include "base/gfx/platform_canvas_mac.h" -namespace gfx { - -typedef PlatformCanvasMac PlatformCanvas; - -} // namespace gfx -#elif defined(OS_LINUX) -#include "base/gfx/platform_canvas_linux.h" -namespace gfx { - -typedef PlatformCanvasLinux PlatformCanvas; - -} // namespace gfx -#endif +// TODO(brettw) this file should be removed and the includes changed to this +// new location. +#include "webkit/port/platform/graphics/skia/public/PlatformCanvas.h" diff --git a/base/gfx/platform_canvas_linux.cc b/base/gfx/platform_canvas_linux.cc deleted file mode 100644 index b579536..0000000 --- a/base/gfx/platform_canvas_linux.cc +++ /dev/null @@ -1,55 +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/platform_canvas_linux.h" - -#include "base/gfx/platform_device_linux.h" -#include "base/gfx/bitmap_platform_device_linux.h" -#include "base/logging.h" - -namespace gfx { - -PlatformCanvasLinux::PlatformCanvasLinux() : SkCanvas() { -} - -PlatformCanvasLinux::PlatformCanvasLinux(int width, int height, bool is_opaque) - : SkCanvas() { - if (!initialize(width, height, is_opaque)) - CHECK(false); -} - -PlatformCanvasLinux::~PlatformCanvasLinux() { -} - -bool PlatformCanvasLinux::initialize(int width, int height, bool is_opaque) { - SkDevice* device = createPlatformDevice(width, height, is_opaque); - if (!device) - return false; - - setDevice(device); - device->unref(); // was created with refcount 1, and setDevice also refs - return true; -} - -PlatformDeviceLinux& PlatformCanvasLinux::getTopPlatformDevice() const { - // All of our devices should be our special PlatformDevice. - SkCanvas::LayerIter iter(const_cast<PlatformCanvasLinux*>(this), false); - return *static_cast<PlatformDeviceLinux*>(iter.device()); -} - -SkDevice* PlatformCanvasLinux::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); -} - -SkDevice* PlatformCanvasLinux::createPlatformDevice(int width, - int height, - bool is_opaque) { - return BitmapPlatformDeviceLinux::Create(width, height, is_opaque); -} - -} // namespace gfx diff --git a/base/gfx/platform_canvas_linux.h b/base/gfx/platform_canvas_linux.h index 804c6b6..dbd9fc2 100644 --- a/base/gfx/platform_canvas_linux.h +++ b/base/gfx/platform_canvas_linux.h @@ -5,47 +5,8 @@ #ifndef BASE_GFX_PLATFORM_CANVAS_LINUX_H_ #define BASE_GFX_PLATFORM_CANVAS_LINUX_H_ -#include "base/gfx/platform_device_linux.h" -#include "base/basictypes.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 PlatformCanvasLinux : public SkCanvas { - public: - // Set is_opaque if you are going to erase the bitmap and not use - // tranparency: 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() - PlatformCanvasLinux(); - PlatformCanvasLinux(int width, int height, bool is_opaque); - virtual ~PlatformCanvasLinux(); - - // For two-part init, call if you use the no-argument constructor above - bool initialize(int width, int height, bool is_opaque); - - // Returns the platform device pointer of the topmost rect with a non-empty - // clip. Both the windows and mac versions have an equivalent of this method; - // a Linux version is added for compatibility. - PlatformDeviceLinux& 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 - // BitmapPlatformDevice object. Can be overridden to change the object type. - virtual SkDevice* createPlatformDevice(int width, int height, bool is_opaque); - - DISALLOW_COPY_AND_ASSIGN(PlatformCanvasLinux); -}; - -} // namespace gfx +// TODO(brettw) this file should be removed and the includes changed to this +// new location. +#include "webkit/port/platform/graphics/skia/public/PlatformCanvasLinux.h" #endif // BASE_GFX_PLATFORM_CANVAS_MAC_H_ diff --git a/base/gfx/platform_canvas_mac.cc b/base/gfx/platform_canvas_mac.cc deleted file mode 100755 index 2777dee..0000000 --- a/base/gfx/platform_canvas_mac.cc +++ /dev/null @@ -1,80 +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/platform_canvas_mac.h" - -#include "base/gfx/bitmap_platform_device_mac.h" -#include "base/logging.h" - -namespace gfx { - -PlatformCanvasMac::PlatformCanvasMac() : SkCanvas() { -} - -PlatformCanvasMac::PlatformCanvasMac(int width, int height, bool is_opaque) - : SkCanvas() { - initialize(width, height, is_opaque); -} - -PlatformCanvasMac::PlatformCanvasMac(int width, - int height, - bool is_opaque, - CGContextRef context) - : SkCanvas() { - initialize(width, height, is_opaque); -} - -PlatformCanvasMac::~PlatformCanvasMac() { -} - -bool PlatformCanvasMac::initialize(int width, - int height, - bool is_opaque) { - SkDevice* device = createPlatformDevice(width, height, is_opaque, NULL); - if (!device) - return false; - - setDevice(device); - device->unref(); // was created with refcount 1, and setDevice also refs - return true; -} - -CGContextRef PlatformCanvasMac::beginPlatformPaint() { - return getTopPlatformDevice().GetBitmapContext(); -} - -void PlatformCanvasMac::endPlatformPaint() { - // flushing will be done in onAccessBitmap -} - -PlatformDeviceMac& PlatformCanvasMac::getTopPlatformDevice() const { - // All of our devices should be our special PlatformDeviceMac. - SkCanvas::LayerIter iter(const_cast<PlatformCanvasMac*>(this), false); - return *static_cast<PlatformDeviceMac*>(iter.device()); -} - -SkDevice* PlatformCanvasMac::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* PlatformCanvasMac::createPlatformDevice(int width, - int height, - bool is_opaque, - CGContextRef context) { - SkDevice* device = BitmapPlatformDeviceMac::Create(context, width, height, - is_opaque); - return device; -} - -SkDevice* PlatformCanvasMac::setBitmapDevice(const SkBitmap&) { - NOTREACHED(); - return NULL; -} - -} // namespace gfx - diff --git a/base/gfx/platform_canvas_mac.h b/base/gfx/platform_canvas_mac.h index 3f79fb3..6ee78e8 100755 --- a/base/gfx/platform_canvas_mac.h +++ b/base/gfx/platform_canvas_mac.h @@ -5,83 +5,9 @@ #ifndef BASE_GFX_PLATFORM_CANVAS_MAC_H__ #define BASE_GFX_PLATFORM_CANVAS_MAC_H__ -#include "base/gfx/platform_device_mac.h" -#include "base/basictypes.h" - -#import "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 PlatformCanvasMac : public SkCanvas { - public: - // Set is_opaque if you are going to erase the bitmap and not use - // tranparency: 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() - PlatformCanvasMac(); - PlatformCanvasMac(int width, int height, bool is_opaque); - PlatformCanvasMac(int width, int height, bool is_opaque, CGContextRef context); - virtual ~PlatformCanvasMac(); - - // For two-part init, call if you use the no-argument constructor above - bool initialize(int width, int height, bool is_opaque); - - // These calls should surround calls to platform drawing routines. The CG - // context returned by beginPlatformPaint is the one 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. - virtual CGContextRef 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(). - PlatformDeviceMac& getTopPlatformDevice() const; - - // Allow callers to see the non-virtual function even though we have an - // override of a virtual one. - using SkCanvas::clipRect; - - 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 - // BitmapPlatformDevice object. Can be overridden to change the object type. - virtual SkDevice* createPlatformDevice(int width, int height, bool is_opaque, - CGContextRef context); - - private: - // Unimplemented. This is to try to prevent people from calling this function - // on SkCanvas. SkCanvas' version is not virtual, so we can't prevent this - // 100%, but hopefully this will make people notice and not use the function. - // Calling SkCanvas' version will create a new device which is not compatible - // with us and we will crash if somebody tries to draw into it with - // CoreGraphics. - SkDevice* setBitmapDevice(const SkBitmap& bitmap); - - DISALLOW_COPY_AND_ASSIGN(PlatformCanvasMac); -}; - -} // namespace gfx +// TODO(brettw) this file should be removed and the includes changed to this +// new location. +#include "webkit/port/platform/graphics/skia/public/PlatformCanvasMac.h" #endif // BASE_GFX_PLATFORM_CANVAS_MAC_H__ diff --git a/base/gfx/platform_canvas_unittest.cc b/base/gfx/platform_canvas_unittest.cc deleted file mode 100644 index 8e227ad..0000000 --- a/base/gfx/platform_canvas_unittest.cc +++ /dev/null @@ -1,296 +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. - -// TODO(awalker): clean up the const/non-const reference handling in this test - -#include "build/build_config.h" - -#if defined(OS_WIN) -#include <windows.h> -#else -#include <unistd.h> -#endif - -#include "base/gfx/platform_canvas.h" -#include "base/gfx/platform_device.h" -#include "testing/gtest/include/gtest/gtest.h" - -#include "SkColor.h" - -namespace gfx { - -namespace { - -// Return true if the canvas is filled to canvas_color, -// and contains a single rectangle filled to rect_color. -bool VerifyRect(const PlatformCanvas& canvas, - uint32_t canvas_color, uint32_t rect_color, - int x, int y, int w, int h) { - PlatformDevice& device = canvas.getTopPlatformDevice(); - const SkBitmap& bitmap = device.accessBitmap(false); - SkAutoLockPixels lock(bitmap); - - for (int cur_y = 0; cur_y < bitmap.height(); cur_y++) { - for (int cur_x = 0; cur_x < bitmap.width(); cur_x++) { - if (cur_x >= x && cur_x < x + w && - cur_y >= y && cur_y < y + h) { - // Inside the square should be rect_color - if (*bitmap.getAddr32(cur_x, cur_y) != rect_color) - return false; - } else { - // Outside the square should be canvas_color - if (*bitmap.getAddr32(cur_x, cur_y) != canvas_color) - return false; - } - } - } - return true; -} - -// Checks whether there is a white canvas with a black square at the given -// location in pixels (not in the canvas coordinate system). -// TODO(ericroman): rename Square to Rect -bool VerifyBlackSquare(const PlatformCanvas& canvas, int x, int y, int w, int h) { - return VerifyRect(canvas, SK_ColorWHITE, SK_ColorBLACK, x, y, w, h); -} - -// Check that every pixel in the canvas is a single color. -bool VerifyCanvasColor(const PlatformCanvas& canvas, uint32_t canvas_color) { - return VerifyRect(canvas, canvas_color, 0, 0, 0, 0, 0); -} - -#if defined(OS_WIN) -void DrawNativeRect(PlatformCanvas& canvas, int x, int y, int w, int h) { - HDC dc = canvas.beginPlatformPaint(); - - RECT inner_rc; - inner_rc.left = x; - inner_rc.top = y; - inner_rc.right = x + w; - inner_rc.bottom = y + h; - FillRect(dc, &inner_rc, reinterpret_cast<HBRUSH>(GetStockObject(BLACK_BRUSH))); - - canvas.endPlatformPaint(); -} -#elif defined(OS_MACOSX) -void DrawNativeRect(PlatformCanvas& canvas, int x, int y, int w, int h) { - CGContextRef context = canvas.beginPlatformPaint(); - - CGRect inner_rc = CGRectMake(x, y, w, h); - // RGBA opaque black - CGColorRef black = CGColorCreateGenericRGB(0.0, 0.0, 0.0, 1.0); - CGContextSetFillColorWithColor(context, black); - CGColorRelease(black); - CGContextFillRect(context, inner_rc); - - canvas.endPlatformPaint(); -} -#else -void DrawNativeRect(PlatformCanvas& canvas, int x, int y, int w, int h) { - NOTIMPLEMENTED(); -} -#endif - -// Clips the contents of the canvas to the given rectangle. This will be -// intersected with any existing clip. -void AddClip(PlatformCanvas& canvas, int x, int y, int w, int h) { - SkRect rect; - rect.set(SkIntToScalar(x), SkIntToScalar(y), - SkIntToScalar(x + w), SkIntToScalar(y + h)); - canvas.clipRect(rect); -} - -class LayerSaver { - public: - LayerSaver(PlatformCanvas& canvas, int x, int y, int w, int h) - : canvas_(canvas), - x_(x), - y_(y), - w_(w), - h_(h) { - SkRect bounds; - bounds.set(SkIntToScalar(x_), SkIntToScalar(y_), - SkIntToScalar(right()), SkIntToScalar(bottom())); - canvas_.saveLayer(&bounds, NULL); - } - - ~LayerSaver() { - canvas_.getTopPlatformDevice().fixupAlphaBeforeCompositing(); - canvas_.restore(); - } - - int x() const { return x_; } - int y() const { return y_; } - int w() const { return w_; } - int h() const { return h_; } - - // Returns the EXCLUSIVE far bounds of the layer. - int right() const { return x_ + w_; } - int bottom() const { return y_ + h_; } - - private: - PlatformCanvas& canvas_; - int x_, y_, w_, h_; -}; - -// Size used for making layers in many of the below tests. -const int kLayerX = 2; -const int kLayerY = 3; -const int kLayerW = 9; -const int kLayerH = 7; - -// Size used by some tests to draw a rectangle inside the layer. -const int kInnerX = 4; -const int kInnerY = 5; -const int kInnerW = 2; -const int kInnerH = 3; - -} - -// This just checks that our checking code is working properly, it just uses -// regular skia primitives. -TEST(PlatformCanvas, SkLayer) { - // Create the canvas initialized to opaque white. - PlatformCanvas canvas(16, 16, true); - canvas.drawColor(SK_ColorWHITE); - - // Make a layer and fill it completely to make sure that the bounds are - // correct. - { - LayerSaver layer(canvas, kLayerX, kLayerY, kLayerW, kLayerH); - canvas.drawColor(SK_ColorBLACK); - } - EXPECT_TRUE(VerifyBlackSquare(canvas, kLayerX, kLayerY, kLayerW, kLayerH)); -} - -// Test native clipping. -TEST(PlatformCanvas, ClipRegion) { - // Initialize a white canvas - PlatformCanvas canvas(16, 16, true); - canvas.drawColor(SK_ColorWHITE); - EXPECT_TRUE(VerifyCanvasColor(canvas, SK_ColorWHITE)); - - // Test that initially the canvas has no clip region, by filling it - // with a black rectangle. - // Note: Don't use LayerSaver, since internally it sets a clip region. - DrawNativeRect(canvas, 0, 0, 16, 16); - canvas.getTopPlatformDevice().fixupAlphaBeforeCompositing(); - EXPECT_TRUE(VerifyCanvasColor(canvas, SK_ColorBLACK)); - - // Test that intersecting disjoint clip rectangles sets an empty clip region - canvas.drawColor(SK_ColorWHITE); - EXPECT_TRUE(VerifyCanvasColor(canvas, SK_ColorWHITE)); - { - LayerSaver layer(canvas, 0, 0, 16, 16); - AddClip(canvas, 2, 3, 4, 5); - AddClip(canvas, 4, 9, 10, 10); - DrawNativeRect(canvas, 0, 0, 16, 16); - } - EXPECT_TRUE(VerifyCanvasColor(canvas, SK_ColorWHITE)); -} - -// Test the layers get filled properly by native rendering. -TEST(PlatformCanvas, FillLayer) { - // Create the canvas initialized to opaque white. - PlatformCanvas canvas(16, 16, true); - - // Make a layer and fill it completely to make sure that the bounds are - // correct. - canvas.drawColor(SK_ColorWHITE); - { - LayerSaver layer(canvas, kLayerX, kLayerY, kLayerW, kLayerH); - DrawNativeRect(canvas, 0, 0, 100, 100); - } - EXPECT_TRUE(VerifyBlackSquare(canvas, kLayerX, kLayerY, kLayerW, kLayerH)); - - // Make a layer and fill it partially to make sure the translation is correct. - canvas.drawColor(SK_ColorWHITE); - { - LayerSaver layer(canvas, kLayerX, kLayerY, kLayerW, kLayerH); - DrawNativeRect(canvas, kInnerX, kInnerY, kInnerW, kInnerH); - } - EXPECT_TRUE(VerifyBlackSquare(canvas, kInnerX, kInnerY, kInnerW, kInnerH)); - - // Add a clip on the layer and fill to make sure clip is correct. - canvas.drawColor(SK_ColorWHITE); - { - LayerSaver layer(canvas, kLayerX, kLayerY, kLayerW, kLayerH); - canvas.save(); - AddClip(canvas, kInnerX, kInnerY, kInnerW, kInnerH); - DrawNativeRect(canvas, 0, 0, 100, 100); - canvas.restore(); - } - EXPECT_TRUE(VerifyBlackSquare(canvas, kInnerX, kInnerY, kInnerW, kInnerH)); - - // Add a clip and then make the layer to make sure the clip is correct. - canvas.drawColor(SK_ColorWHITE); - canvas.save(); - AddClip(canvas, kInnerX, kInnerY, kInnerW, kInnerH); - { - LayerSaver layer(canvas, kLayerX, kLayerY, kLayerW, kLayerH); - DrawNativeRect(canvas, 0, 0, 100, 100); - } - canvas.restore(); - EXPECT_TRUE(VerifyBlackSquare(canvas, kInnerX, kInnerY, kInnerW, kInnerH)); -} - -// Test that translation + make layer works properly. -TEST(PlatformCanvas, TranslateLayer) { - // Create the canvas initialized to opaque white. - PlatformCanvas canvas(16, 16, true); - - // Make a layer and fill it completely to make sure that the bounds are - // correct. - canvas.drawColor(SK_ColorWHITE); - canvas.save(); - canvas.translate(1, 1); - { - LayerSaver layer(canvas, kLayerX, kLayerY, kLayerW, kLayerH); - DrawNativeRect(canvas, 0, 0, 100, 100); - } - canvas.restore(); - EXPECT_TRUE(VerifyBlackSquare(canvas, kLayerX + 1, kLayerY + 1, - kLayerW, kLayerH)); - - // Translate then make the layer. - canvas.drawColor(SK_ColorWHITE); - canvas.save(); - canvas.translate(1, 1); - { - LayerSaver layer(canvas, kLayerX, kLayerY, kLayerW, kLayerH); - DrawNativeRect(canvas, kInnerX, kInnerY, kInnerW, kInnerH); - } - canvas.restore(); - EXPECT_TRUE(VerifyBlackSquare(canvas, kInnerX + 1, kInnerY + 1, - kInnerW, kInnerH)); - - // Make the layer then translate. - canvas.drawColor(SK_ColorWHITE); - canvas.save(); - { - LayerSaver layer(canvas, kLayerX, kLayerY, kLayerW, kLayerH); - canvas.translate(1, 1); - DrawNativeRect(canvas, kInnerX, kInnerY, kInnerW, kInnerH); - } - canvas.restore(); - EXPECT_TRUE(VerifyBlackSquare(canvas, kInnerX + 1, kInnerY + 1, - kInnerW, kInnerH)); - - // Translate both before and after, and have a clip. - canvas.drawColor(SK_ColorWHITE); - canvas.save(); - canvas.translate(1, 1); - { - LayerSaver layer(canvas, kLayerX, kLayerY, kLayerW, kLayerH); - canvas.translate(1, 1); - AddClip(canvas, kInnerX, kInnerY, kInnerW, kInnerH); - DrawNativeRect(canvas, 0, 0, 100, 100); - } - canvas.restore(); - EXPECT_TRUE(VerifyBlackSquare(canvas, kInnerX + 2, kInnerY + 2, - kInnerW, kInnerH)); -} - -} // namespace - diff --git a/base/gfx/platform_canvas_win.cc b/base/gfx/platform_canvas_win.cc deleted file mode 100644 index fe90c55..0000000 --- a/base/gfx/platform_canvas_win.cc +++ /dev/null @@ -1,122 +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/platform_canvas_win.h" - -#include "base/gfx/bitmap_platform_device_win.h" -#include "base/logging.h" -#include "base/process_util.h" - -#ifdef ARCH_CPU_64_BITS -#error This code does not work on x64. Please make sure all the base unit tests\ - pass before doing any real work. -#endif - -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/base/gfx/platform_canvas_win.h b/base/gfx/platform_canvas_win.h index 95ae856..8bd285b 100644 --- a/base/gfx/platform_canvas_win.h +++ b/base/gfx/platform_canvas_win.h @@ -5,192 +5,9 @@ #ifndef BASE_GFX_PLATFORM_CANVAS_WIN_H_ #define BASE_GFX_PLATFORM_CANVAS_WIN_H_ -#include "base/gfx/platform_device_win.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); -}; - -// 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); -}; - -typedef CanvasPaintT<PlatformCanvasWin> PlatformCanvasWinPaint; - -} // namespace gfx +// TODO(brettw) this file should be removed and the includes changed to this +// new location. +#include "webkit/port/platform/graphics/skia/public/PlatformCanvasWin.h" #endif // BASE_GFX_PLATFORM_CANVAS_WIN_H_ diff --git a/base/gfx/platform_device.h b/base/gfx/platform_device.h index f1c890c..11202c6 100644 --- a/base/gfx/platform_device.h +++ b/base/gfx/platform_device.h @@ -2,26 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Declare a platform-neutral name for this platform's device class -// that can be used by upper-level classes that just need to pass a reference -// around. - -#if defined(OS_WIN) -#include "base/gfx/platform_device_win.h" -#elif defined(OS_MACOSX) -#include "base/gfx/platform_device_mac.h" -#elif defined(OS_LINUX) -#include "base/gfx/platform_device_linux.h" -#endif - -namespace gfx { - -#if defined(OS_WIN) -typedef PlatformDeviceWin PlatformDevice; -#elif defined(OS_MACOSX) -typedef PlatformDeviceMac PlatformDevice; -#elif defined(OS_LINUX) -typedef PlatformDeviceLinux PlatformDevice; -#endif - -} // namespace gfx +// TODO(brettw) this file should be removed and the includes changed to this +// new location. +#include "webkit/port/platform/graphics/skia/public/PlatformDevice.h" diff --git a/base/gfx/platform_device_linux.cc b/base/gfx/platform_device_linux.cc deleted file mode 100644 index 1f948b1..0000000 --- a/base/gfx/platform_device_linux.cc +++ /dev/null @@ -1,18 +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/platform_device_linux.h" - -#include "base/logging.h" -#include "SkMatrix.h" -#include "SkPath.h" -#include "SkUtils.h" - -namespace gfx { - -PlatformDeviceLinux::PlatformDeviceLinux(const SkBitmap& bitmap) - : SkDevice(bitmap) { -} - -} // namespace gfx diff --git a/base/gfx/platform_device_linux.h b/base/gfx/platform_device_linux.h index 8be2e4a..ffd5a2d 100644 --- a/base/gfx/platform_device_linux.h +++ b/base/gfx/platform_device_linux.h @@ -5,21 +5,8 @@ #ifndef BASE_GFX_PLATFORM_DEVICE_LINUX_H_ #define BASE_GFX_PLATFORM_DEVICE_LINUX_H_ -#include "SkDevice.h" - -namespace gfx { - -// Blindly copying the mac hierarchy. -class PlatformDeviceLinux : public SkDevice { - public: - // Returns if the preferred rendering engine is vectorial or bitmap based. - virtual bool IsVectorial() = 0; - - protected: - // Forwards |bitmap| to SkDevice's constructor. - PlatformDeviceLinux(const SkBitmap& bitmap); -}; - -} // namespace gfx +// TODO(brettw) this file should be removed and the includes changed to this +// new location. +#include "webkit/port/platform/graphics/skia/public/PlatformDeviceLinux.h" #endif // BASE_GFX_PLATFORM_DEVICE_LINUX_H_ diff --git a/base/gfx/platform_device_mac.cc b/base/gfx/platform_device_mac.cc deleted file mode 100755 index 93909f1..0000000 --- a/base/gfx/platform_device_mac.cc +++ /dev/null @@ -1,161 +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/platform_device_mac.h" - -#include "base/logging.h" -#include "base/gfx/skia_utils_mac.h" -#include "SkMatrix.h" -#include "SkPath.h" -#include "SkUtils.h" - -namespace gfx { - -namespace { - -// Constrains position and size to fit within available_size. -bool constrain(int available_size, int* position, int *size) { - if (*position < 0) { - *size += *position; - *position = 0; - } - if (*size > 0 && *position < available_size) { - int overflow = (*position + *size) - available_size; - if (overflow > 0) { - *size -= overflow; - } - return true; - } - return false; -} - -// Sets the opacity of the specified value to 0xFF. -void makeOpaqueAlphaAdjuster(uint32_t* pixel) { - *pixel |= 0xFF000000; -} - -} // namespace - -PlatformDeviceMac::PlatformDeviceMac(const SkBitmap& bitmap) - : SkDevice(bitmap) { -} - -void PlatformDeviceMac::makeOpaque(int x, int y, int width, int height) { - processPixels(x, y, width, height, makeOpaqueAlphaAdjuster); -} - -// Set up the CGContextRef for peaceful coexistence with Skia -void PlatformDeviceMac::InitializeCGContext(CGContextRef context) { - // CG defaults to the same settings as Skia -} - -// static -void PlatformDeviceMac::LoadPathToCGContext(CGContextRef context, - const SkPath& path) { - // instead of a persistent attribute of the context, CG specifies the fill - // type per call, so we just have to load up the geometry. - CGContextBeginPath(context); - - SkPoint points[4] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} }; - SkPath::Iter iter(path, false); - for (SkPath::Verb verb = iter.next(points); verb != SkPath::kDone_Verb; - verb = iter.next(points)) { - switch (verb) { - case SkPath::kMove_Verb: { // iter.next returns 1 point - CGContextMoveToPoint(context, points[0].fX, points[0].fY); - break; - } - case SkPath::kLine_Verb: { // iter.next returns 2 points - CGContextAddLineToPoint(context, points[1].fX, points[1].fY); - break; - } - case SkPath::kQuad_Verb: { // iter.next returns 3 points - CGContextAddQuadCurveToPoint(context, points[1].fX, points[1].fY, - points[2].fX, points[2].fY); - break; - } - case SkPath::kCubic_Verb: { // iter.next returns 4 points - CGContextAddCurveToPoint(context, points[1].fX, points[1].fY, - points[2].fX, points[2].fY, - points[3].fX, points[3].fY); - break; - } - case SkPath::kClose_Verb: { // iter.next returns 1 point (the last point) - break; - } - case SkPath::kDone_Verb: // iter.next returns 0 points - default: { - NOTREACHED(); - break; - } - } - } - CGContextClosePath(context); -} - -// static -void PlatformDeviceMac::LoadTransformToCGContext(CGContextRef context, - const SkMatrix& matrix) { - // CoreGraphics can concatenate transforms, but not reset the current one. - // So in order to get the required behavior here, we need to first make - // the current transformation matrix identity and only then load the new one. - - // Reset matrix to identity. - CGAffineTransform orig_cg_matrix = CGContextGetCTM(context); - CGAffineTransform orig_cg_matrix_inv = CGAffineTransformInvert(orig_cg_matrix); - CGContextConcatCTM(context, orig_cg_matrix_inv); - - // assert that we have indeed returned to the identity Matrix. - DCHECK(CGAffineTransformIsIdentity(CGContextGetCTM(context))); - - // Convert xform to CG-land. - // Our coordinate system is flipped to match WebKit's so we need to modify - // the xform to match that. - SkMatrix transformed_matrix = matrix; - SkScalar sy = matrix.getScaleY() * (SkScalar)-1; - transformed_matrix.setScaleY(sy); - size_t height = CGBitmapContextGetHeight(context); - SkScalar ty = -matrix.getTranslateY(); // y axis is flipped. - transformed_matrix.setTranslateY(ty + (SkScalar)height); - - CGAffineTransform cg_matrix = SkMatrixToCGAffineTransform(transformed_matrix); - - // Load final transform into context. - CGContextConcatCTM(context, cg_matrix); -} - -// static -void PlatformDeviceMac::LoadClippingRegionToCGContext( - CGContextRef context, - const SkRegion& region, - const SkMatrix& transformation) { - if (region.isEmpty()) { - // region can be empty, in which case everything will be clipped. - SkRect rect; - rect.setEmpty(); - CGContextClipToRect(context, SkRectToCGRect(rect)); - } else if (region.isRect()) { - // Do the transformation. - SkRect rect; - rect.set(region.getBounds()); - transformation.mapRect(&rect); - SkIRect irect; - rect.round(&irect); - CGContextClipToRect(context, SkIRectToCGRect(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); - // TODO(playmobil): Implement. - NOTREACHED(); - // LoadPathToDC(context, path); - // hrgn = PathToRegion(context); - } -} - -} // namespace gfx - diff --git a/base/gfx/platform_device_mac.h b/base/gfx/platform_device_mac.h index 79a14be..f7b1bd0 100755 --- a/base/gfx/platform_device_mac.h +++ b/base/gfx/platform_device_mac.h @@ -5,82 +5,9 @@ #ifndef BASE_GFX_PLATFORM_DEVICE_MAC_H__ #define BASE_GFX_PLATFORM_DEVICE_MAC_H__ -#import <ApplicationServices/ApplicationServices.h> -#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 CoreGraphics can also -// write to. It also provides functionality to play well with CG 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 PlatformDeviceMac : public SkDevice { - public: - // The CGContext that corresponds to the bitmap, used for CoreGraphics - // operations drawing into the bitmap. This is possibly heavyweight, so it - // should exist only during one pass of rendering. - virtual CGContextRef GetBitmapContext() = 0; - - // Draws to the given graphics context. If the bitmap context doesn't exist, - // this will temporarily create it. However, if you have created the bitmap - // context, 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 DrawToContext(CGContextRef context, int x, int y, - const CGRect* src_rect) = 0; - - // Sets the opacity of each pixel in the specified region to be opaque. - void makeOpaque(int x, int y, int width, int height); - - // Returns if the preferred rendering engine is vectorial or bitmap based. - virtual bool IsVectorial() = 0; - - // On platforms where the native rendering API does not support rendering - // into bitmaps with a premultiplied alpha channel, this call is responsible - // for doing any fixup necessary. It is not used on the Mac, since - // CoreGraphics can handle premultiplied alpha just fine. - virtual void fixupAlphaBeforeCompositing() = 0; - - // Initializes the default settings and colors in a device context. - static void InitializeCGContext(CGContextRef context); - - // Loads a SkPath into the CG context. The path can there after be used for - // clipping or as a stroke. - static void LoadPathToCGContext(CGContextRef context, const SkPath& path); - - // Loads a SkRegion into the CG context. - static void LoadClippingRegionToCGContext(CGContextRef context, - const SkRegion& region, - const SkMatrix& transformation); - - protected: - // Forwards |bitmap| to SkDevice's constructor. - PlatformDeviceMac(const SkBitmap& bitmap); - - // Loads the specified Skia transform into the device context - static void LoadTransformToCGContext(CGContextRef context, - const SkMatrix& matrix); - - // Function pointer used by the processPixels method for setting the alpha - // value of a particular pixel. - typedef void (*adjustAlpha)(uint32_t* pixel); - - // Loops through each of the pixels in the specified range, invoking - // adjustor for the alpha value of each pixel. - virtual void processPixels(int x, - int y, - int width, - int height, - adjustAlpha adjustor) = 0; -}; - -} // namespace gfx +// TODO(brettw) this file should be removed and the includes changed to this +// new location. +#include "webkit/port/platform/graphics/skia/public/PlatformDeviceMac.h" #endif // BASE_GFX_PLATFORM_DEVICE_MAC_H__ diff --git a/base/gfx/platform_device_win.cc b/base/gfx/platform_device_win.cc deleted file mode 100644 index a1e8568..0000000 --- a/base/gfx/platform_device_win.cc +++ /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 "base/gfx/platform_device_win.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/base/gfx/platform_device_win.h b/base/gfx/platform_device_win.h index d5052a2..e39dfe1 100644 --- a/base/gfx/platform_device_win.h +++ b/base/gfx/platform_device_win.h @@ -5,92 +5,9 @@ #ifndef BASE_GFX_PLATFORM_DEVICE_WIN_H__ #define BASE_GFX_PLATFORM_DEVICE_WIN_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 +// TODO(brettw) this file should be removed and the includes changed to this +// new location. +#include "webkit/port/platform/graphics/skia/public/PlatformDeviceWin.h" #endif // BASE_GFX_PLATFORM_DEVICE_WIN_H__ diff --git a/base/gfx/vector_canvas.cc b/base/gfx/vector_canvas.cc deleted file mode 100644 index 440ee64..0000000 --- a/base/gfx/vector_canvas.cc +++ /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/base/gfx/vector_canvas_unittest.cc b/base/gfx/vector_canvas_unittest.cc deleted file mode 100644 index 60a79ba..0000000 --- a/base/gfx/vector_canvas_unittest.cc +++ /dev/null @@ -1,1008 +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 <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() << ", " << 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")); - } -} - diff --git a/base/gfx/vector_device.cc b/base/gfx/vector_device.cc deleted file mode 100644 index 26da338..0000000 --- a/base/gfx/vector_device.cc +++ /dev/null @@ -1,612 +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_device.h" - -#include "base/gfx/gdi_util.h" -#include "base/gfx/skia_utils.h" -#include "base/logging.h" -#include "base/scoped_handle.h" - -#include "SkUtils.h" - -namespace gfx { - -VectorDevice* VectorDevice::create(HDC dc, int width, int height) { - InitializeDC(dc); - - // Link the SkBitmap to the current selected bitmap in the device context. - SkBitmap bitmap; - HGDIOBJ selected_bitmap = GetCurrentObject(dc, OBJ_BITMAP); - bool succeeded = false; - if (selected_bitmap != NULL) { - BITMAP bitmap_data; - if (GetObject(selected_bitmap, sizeof(BITMAP), &bitmap_data) == - sizeof(BITMAP)) { - // The context has a bitmap attached. Attach our SkBitmap to it. - // Warning: If the bitmap gets unselected from the HDC, VectorDevice has - // no way to detect this, so the HBITMAP could be released while SkBitmap - // still has a reference to it. Be cautious. - if (width == bitmap_data.bmWidth && - height == bitmap_data.bmHeight) { - bitmap.setConfig(SkBitmap::kARGB_8888_Config, - bitmap_data.bmWidth, - bitmap_data.bmHeight, - bitmap_data.bmWidthBytes); - bitmap.setPixels(bitmap_data.bmBits); - succeeded = true; - } - } - } - - if (!succeeded) - bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height); - - return new VectorDevice(dc, bitmap); -} - -VectorDevice::VectorDevice(HDC dc, const SkBitmap& bitmap) - : PlatformDeviceWin(bitmap), - hdc_(dc), - previous_brush_(NULL), - previous_pen_(NULL) { - transform_.reset(); -} - -VectorDevice::~VectorDevice() { - DCHECK(previous_brush_ == NULL); - DCHECK(previous_pen_ == NULL); -} - - -void VectorDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) { - // TODO(maruel): Bypass the current transformation matrix. - SkRect rect; - rect.fLeft = 0; - rect.fTop = 0; - rect.fRight = SkIntToScalar(width() + 1); - rect.fBottom = SkIntToScalar(height() + 1); - drawRect(draw, rect, paint); -} - -void VectorDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, - size_t count, const SkPoint pts[], - const SkPaint& paint) { - if (!count) - return; - - if (mode == SkCanvas::kPoints_PointMode) { - NOTREACHED(); - return; - } - - SkPaint tmp_paint(paint); - tmp_paint.setStyle(SkPaint::kStroke_Style); - - // Draw a path instead. - SkPath path; - switch (mode) { - case SkCanvas::kLines_PointMode: - if (count % 2) { - NOTREACHED(); - return; - } - for (size_t i = 0; i < count / 2; ++i) { - path.moveTo(pts[2 * i]); - path.lineTo(pts[2 * i + 1]); - } - break; - case SkCanvas::kPolygon_PointMode: - path.moveTo(pts[0]); - for (size_t i = 1; i < count; ++i) { - path.lineTo(pts[i]); - } - break; - default: - NOTREACHED(); - return; - } - // Draw the calculated path. - drawPath(draw, path, tmp_paint); -} - -void VectorDevice::drawRect(const SkDraw& draw, const SkRect& rect, - const SkPaint& paint) { - if (paint.getPathEffect()) { - // Draw a path instead. - SkPath path_orginal; - path_orginal.addRect(rect); - - // Apply the path effect to the rect. - SkPath path_modified; - paint.getFillPath(path_orginal, &path_modified); - - // Removes the path effect from the temporary SkPaint object. - SkPaint paint_no_effet(paint); - paint_no_effet.setPathEffect(NULL)->safeUnref(); - - // Draw the calculated path. - drawPath(draw, path_modified, paint_no_effet); - return; - } - - if (!ApplyPaint(paint)) { - return; - } - HDC dc = getBitmapDC(); - if (!Rectangle(dc, SkScalarRound(rect.fLeft), - SkScalarRound(rect.fTop), - SkScalarRound(rect.fRight), - SkScalarRound(rect.fBottom))) { - NOTREACHED(); - } - Cleanup(); -} - -void VectorDevice::drawPath(const SkDraw& draw, const SkPath& path, - const SkPaint& paint) { - if (paint.getPathEffect()) { - // Apply the path effect forehand. - SkPath path_modified; - paint.getFillPath(path, &path_modified); - - // Removes the path effect from the temporary SkPaint object. - SkPaint paint_no_effet(paint); - paint_no_effet.setPathEffect(NULL)->safeUnref(); - - // Draw the calculated path. - drawPath(draw, path_modified, paint_no_effet); - return; - } - - if (!ApplyPaint(paint)) { - return; - } - HDC dc = getBitmapDC(); - PlatformDeviceWin::LoadPathToDC(dc, path); - switch (paint.getStyle()) { - case SkPaint::kFill_Style: { - BOOL res = StrokeAndFillPath(dc); - DCHECK(res != 0); - break; - } - case SkPaint::kStroke_Style: { - BOOL res = StrokePath(dc); - DCHECK(res != 0); - break; - } - case SkPaint::kStrokeAndFill_Style: { - BOOL res = StrokeAndFillPath(dc); - DCHECK(res != 0); - break; - } - default: - NOTREACHED(); - break; - } - Cleanup(); -} - -void VectorDevice::drawBitmap(const SkDraw& draw, const SkBitmap& bitmap, - const SkMatrix& matrix, const SkPaint& paint) { - // Load the temporary matrix. This is what will translate, rotate and resize - // the bitmap. - SkMatrix actual_transform(transform_); - actual_transform.preConcat(matrix); - LoadTransformToDC(hdc_, actual_transform); - - InternalDrawBitmap(bitmap, 0, 0, paint); - - // Restore the original matrix. - LoadTransformToDC(hdc_, transform_); -} - -void VectorDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap, - int x, int y, const SkPaint& paint) { - SkMatrix identity; - identity.reset(); - LoadTransformToDC(hdc_, identity); - - InternalDrawBitmap(bitmap, x, y, paint); - - // Restore the original matrix. - LoadTransformToDC(hdc_, transform_); -} - -void VectorDevice::drawText(const SkDraw& draw, const void* text, size_t byteLength, - SkScalar x, SkScalar y, const SkPaint& paint) { - // This function isn't used in the code. Verify this assumption. - NOTREACHED(); -} - -void VectorDevice::drawPosText(const SkDraw& draw, const void* text, size_t len, - const SkScalar pos[], SkScalar constY, - int scalarsPerPos, const SkPaint& paint) { - // This function isn't used in the code. Verify this assumption. - NOTREACHED(); -} - -void VectorDevice::drawTextOnPath(const SkDraw& draw, const void* text, - size_t len, - const SkPath& path, const SkMatrix* matrix, - const SkPaint& paint) { - // This function isn't used in the code. Verify this assumption. - NOTREACHED(); -} - -void VectorDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode, - int vertexCount, - const SkPoint vertices[], const SkPoint texs[], - const SkColor colors[], SkXfermode* xmode, - const uint16_t indices[], int indexCount, - const SkPaint& paint) { - // This function isn't used in the code. Verify this assumption. - NOTREACHED(); -} - -void VectorDevice::drawDevice(const SkDraw& draw, SkDevice* device, int x, - int y, const SkPaint& paint) { - // TODO(maruel): http://b/1183870 Playback the EMF buffer at printer's dpi if - // it is a vectorial device. - drawSprite(draw, device->accessBitmap(false), x, y, paint); -} - -bool VectorDevice::ApplyPaint(const SkPaint& paint) { - // Note: The goal here is to transfert the SkPaint's state to the HDC's state. - // This function does not execute the SkPaint drawing commands. These should - // be executed in drawPaint(). - - SkPaint::Style style = paint.getStyle(); - if (!paint.getAlpha()) - style = SkPaint::kStyleCount; - - switch (style) { - case SkPaint::kFill_Style: - if (!CreateBrush(true, paint) || - !CreatePen(false, paint)) - return false; - break; - case SkPaint::kStroke_Style: - if (!CreateBrush(false, paint) || - !CreatePen(true, paint)) - return false; - break; - case SkPaint::kStrokeAndFill_Style: - if (!CreateBrush(true, paint) || - !CreatePen(true, paint)) - return false; - break; - default: - if (!CreateBrush(false, paint) || - !CreatePen(false, paint)) - return false; - break; - } - - /* - getFlags(); - isAntiAlias(); - isDither() - isLinearText() - isSubpixelText() - isUnderlineText() - isStrikeThruText() - isFakeBoldText() - isDevKernText() - isFilterBitmap() - - // Skia's text is not used. This should be fixed. - getTextAlign() - getTextScaleX() - getTextSkewX() - getTextEncoding() - getFontMetrics() - getFontSpacing() - */ - - // BUG 1094907: Implement shaders. Shaders currently in use: - // SkShader::CreateBitmapShader - // SkGradientShader::CreateRadial - // SkGradientShader::CreateLinear - // DCHECK(!paint.getShader()); - - // http://b/1106647 Implement loopers and mask filter. Looper currently in - // use: - // SkBlurDrawLooper is used for shadows. - // DCHECK(!paint.getLooper()); - // DCHECK(!paint.getMaskFilter()); - - // http://b/1165900 Implement xfermode. - // DCHECK(!paint.getXfermode()); - - // The path effect should be processed before arriving here. - DCHECK(!paint.getPathEffect()); - - // These aren't used in the code. Verify this assumption. - DCHECK(!paint.getColorFilter()); - DCHECK(!paint.getRasterizer()); - // Reuse code to load Win32 Fonts. - DCHECK(!paint.getTypeface()); - return true; -} - -void VectorDevice::setMatrixClip(const SkMatrix& transform, - const SkRegion& region) { - transform_ = transform; - LoadTransformToDC(hdc_, transform_); - clip_region_ = region; - if (!clip_region_.isEmpty()) - LoadClipRegion(); -} - -void VectorDevice::drawToHDC(HDC dc, int x, int y, const RECT* src_rect) { - NOTREACHED(); -} - -void VectorDevice::LoadClipRegion() { - SkMatrix t; - t.reset(); - LoadClippingRegionToDC(hdc_, clip_region_, t); -} - -bool VectorDevice::CreateBrush(bool use_brush, COLORREF color) { - DCHECK(previous_brush_ == NULL); - // We can't use SetDCBrushColor() or DC_BRUSH when drawing to a EMF buffer. - // SetDCBrushColor() calls are not recorded at all and DC_BRUSH will use - // WHITE_BRUSH instead. - - if (!use_brush) { - // Set the transparency. - if (0 == SetBkMode(hdc_, TRANSPARENT)) { - NOTREACHED(); - return false; - } - - // Select the NULL brush. - previous_brush_ = SelectObject(GetStockObject(NULL_BRUSH)); - return previous_brush_ != NULL; - } - - // Set the opacity. - if (0 == SetBkMode(hdc_, OPAQUE)) { - NOTREACHED(); - return false; - } - - // Create and select the brush. - previous_brush_ = SelectObject(CreateSolidBrush(color)); - return previous_brush_ != NULL; -} - -bool VectorDevice::CreatePen(bool use_pen, COLORREF color, int stroke_width, - float stroke_miter, DWORD pen_style) { - DCHECK(previous_pen_ == NULL); - // We can't use SetDCPenColor() or DC_PEN when drawing to a EMF buffer. - // SetDCPenColor() calls are not recorded at all and DC_PEN will use BLACK_PEN - // instead. - - // No pen case - if (!use_pen) { - previous_pen_ = SelectObject(GetStockObject(NULL_PEN)); - return previous_pen_ != NULL; - } - - // Use the stock pen if the stroke width is 0. - if (stroke_width == 0) { - // Create a pen with the right color. - previous_pen_ = SelectObject(::CreatePen(PS_SOLID, 0, color)); - return previous_pen_ != NULL; - } - - // Load a custom pen. - LOGBRUSH brush; - brush.lbStyle = BS_SOLID; - brush.lbColor = color; - brush.lbHatch = 0; - HPEN pen = ExtCreatePen(pen_style, stroke_width, &brush, 0, NULL); - DCHECK(pen != NULL); - previous_pen_ = SelectObject(pen); - if (previous_pen_ == NULL) - return false; - - if (!SetMiterLimit(hdc_, stroke_miter, NULL)) { - NOTREACHED(); - return false; - } - return true; -} - -void VectorDevice::Cleanup() { - if (previous_brush_) { - HGDIOBJ result = SelectObject(previous_brush_); - previous_brush_ = NULL; - if (result) { - BOOL res = DeleteObject(result); - DCHECK(res != 0); - } - } - if (previous_pen_) { - HGDIOBJ result = SelectObject(previous_pen_); - previous_pen_ = NULL; - if (result) { - BOOL res = DeleteObject(result); - DCHECK(res != 0); - } - } - // Remove any loaded path from the context. - AbortPath(hdc_); -} - -HGDIOBJ VectorDevice::SelectObject(HGDIOBJ object) { - HGDIOBJ result = ::SelectObject(hdc_, object); - DCHECK(result != HGDI_ERROR); - if (result == HGDI_ERROR) - return NULL; - return result; -} - -bool VectorDevice::CreateBrush(bool use_brush, const SkPaint& paint) { - // Make sure that for transparent color, no brush is used. - if (paint.getAlpha() == 0) { - // Test if it ever happen. - NOTREACHED(); - use_brush = false; - } - - return CreateBrush(use_brush, SkColorToCOLORREF(paint.getColor())); -} - -bool VectorDevice::CreatePen(bool use_pen, const SkPaint& paint) { - // Make sure that for transparent color, no pen is used. - if (paint.getAlpha() == 0) { - // Test if it ever happen. - NOTREACHED(); - use_pen = false; - } - - DWORD pen_style = PS_GEOMETRIC | PS_SOLID; - switch (paint.getStrokeJoin()) { - case SkPaint::kMiter_Join: - // Connects path segments with a sharp join. - pen_style |= PS_JOIN_MITER; - break; - case SkPaint::kRound_Join: - // Connects path segments with a round join. - pen_style |= PS_JOIN_ROUND; - break; - case SkPaint::kBevel_Join: - // Connects path segments with a flat bevel join. - pen_style |= PS_JOIN_BEVEL; - break; - default: - NOTREACHED(); - break; - } - switch (paint.getStrokeCap()) { - case SkPaint::kButt_Cap: - // Begin/end contours with no extension. - pen_style |= PS_ENDCAP_FLAT; - break; - case SkPaint::kRound_Cap: - // Begin/end contours with a semi-circle extension. - pen_style |= PS_ENDCAP_ROUND; - break; - case SkPaint::kSquare_Cap: - // Begin/end contours with a half square extension. - pen_style |= PS_ENDCAP_SQUARE; - break; - default: - NOTREACHED(); - break; - } - - return CreatePen(use_pen, - SkColorToCOLORREF(paint.getColor()), - SkScalarRound(paint.getStrokeWidth()), - paint.getStrokeMiter(), - pen_style); -} - -void VectorDevice::InternalDrawBitmap(const SkBitmap& bitmap, int x, int y, - const SkPaint& paint) { - uint8 alpha = paint.getAlpha(); - if (alpha == 0) - return; - - bool is_translucent; - if (alpha != 255) { - // ApplyPaint expect an opaque color. - SkPaint tmp_paint(paint); - tmp_paint.setAlpha(255); - if (!ApplyPaint(tmp_paint)) - return; - is_translucent = true; - } else { - if (!ApplyPaint(paint)) - return; - is_translucent = false; - } - int src_size_x = bitmap.width(); - int src_size_y = bitmap.height(); - if (!src_size_x || !src_size_y) - return; - - // Create a BMP v4 header that we can serialize. - BITMAPV4HEADER bitmap_header; - gfx::CreateBitmapV4Header(src_size_x, src_size_y, &bitmap_header); - HDC dc = getBitmapDC(); - SkAutoLockPixels lock(bitmap); - DCHECK_EQ(bitmap.getConfig(), SkBitmap::kARGB_8888_Config); - const uint32_t* pixels = static_cast<const uint32_t*>(bitmap.getPixels()); - if (pixels == NULL) { - NOTREACHED(); - return; - } - - if (!is_translucent) { - int row_length = bitmap.rowBytesAsPixels(); - // There is no quick way to determine if an image is opaque. - for (int y2 = 0; y2 < src_size_y; ++y2) { - for (int x2 = 0; x2 < src_size_x; ++x2) { - if (SkColorGetA(pixels[(y2 * row_length) + x2]) != 255) { - is_translucent = true; - y2 = src_size_y; - break; - } - } - } - } - - BITMAPINFOHEADER hdr; - gfx::CreateBitmapHeader(src_size_x, src_size_y, &hdr); - if (is_translucent) { - // The image must be loaded as a bitmap inside a device context. - ScopedHDC bitmap_dc(::CreateCompatibleDC(dc)); - void* bits = NULL; - ScopedBitmap hbitmap(::CreateDIBSection( - bitmap_dc, reinterpret_cast<const BITMAPINFO*>(&hdr), - DIB_RGB_COLORS, &bits, NULL, 0)); - memcpy(bits, pixels, bitmap.getSize()); - DCHECK(hbitmap); - HGDIOBJ old_bitmap = ::SelectObject(bitmap_dc, hbitmap); - DeleteObject(old_bitmap); - - // After some analysis of IE7's behavior, this is the thing to do. I was - // sure IE7 was doing so kind of bitmasking due to the way translucent image - // where renderered but after some windbg tracing, it is being done by the - // printer driver after all (mostly HP printers). IE7 always use AlphaBlend - // for bitmasked images. The trick seems to switch the stretching mode in - // what the driver expects. - DWORD previous_mode = GetStretchBltMode(dc); - BOOL result = SetStretchBltMode(dc, COLORONCOLOR); - DCHECK(result); - // Note that this function expect premultiplied colors (!) - BLENDFUNCTION blend_function = {AC_SRC_OVER, 0, alpha, AC_SRC_ALPHA}; - result = GdiAlphaBlend(dc, - x, y, // Destination origin. - src_size_x, src_size_y, // Destination size. - bitmap_dc, - 0, 0, // Source origin. - src_size_x, src_size_y, // Source size. - blend_function); - DCHECK(result); - result = SetStretchBltMode(dc, previous_mode); - DCHECK(result); - } else { - BOOL result = StretchDIBits(dc, - x, y, // Destination origin. - src_size_x, src_size_y, - 0, 0, // Source origin. - src_size_x, src_size_y, // Source size. - pixels, - reinterpret_cast<const BITMAPINFO*>(&hdr), - DIB_RGB_COLORS, - SRCCOPY); - DCHECK(result); - } - Cleanup(); -} - -} // namespace gfx - diff --git a/base/gfx/vector_device.h b/base/gfx/vector_device.h index 5ebc558..55fe22e 100644 --- a/base/gfx/vector_device.h +++ b/base/gfx/vector_device.h @@ -2,118 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef BASE_GFX_VECTOR_DEVICE_H_ -#define BASE_GFX_VECTOR_DEVICE_H_ - -#include "base/basictypes.h" -#include "base/gfx/platform_device_win.h" -#include "SkMatrix.h" -#include "SkRegion.h" - -namespace gfx { - -// A device is basically a wrapper around SkBitmap that provides a surface for -// SkCanvas to draw into. This specific device is not not backed by a surface -// and is thus unreadable. This is because the backend is completely vectorial. -// This device is a simple wrapper over a Windows device context (HDC) handle. -class VectorDevice : public PlatformDeviceWin { - public: - // Factory function. The DC is kept as the output context. - static VectorDevice* create(HDC dc, int width, int height); - - VectorDevice(HDC dc, const SkBitmap& bitmap); - virtual ~VectorDevice(); - - virtual HDC getBitmapDC() { - return hdc_; - } - - virtual void drawPaint(const SkDraw& draw, const SkPaint& paint); - virtual void drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, - size_t count, const SkPoint[], const SkPaint& paint); - virtual void drawRect(const SkDraw& draw, const SkRect& r, - const SkPaint& paint); - virtual void drawPath(const SkDraw& draw, const SkPath& path, - const SkPaint& paint); - virtual void drawBitmap(const SkDraw& draw, const SkBitmap& bitmap, - const SkMatrix& matrix, const SkPaint& paint); - virtual void drawSprite(const SkDraw& draw, const SkBitmap& bitmap, - int x, int y, const SkPaint& paint); - virtual void drawText(const SkDraw& draw, const void* text, size_t len, - SkScalar x, SkScalar y, const SkPaint& paint); - virtual void drawPosText(const SkDraw& draw, const void* text, size_t len, - const SkScalar pos[], SkScalar constY, - int scalarsPerPos, const SkPaint& paint); - virtual void drawTextOnPath(const SkDraw& draw, const void* text, size_t len, - const SkPath& path, const SkMatrix* matrix, - const SkPaint& paint); - virtual void drawVertices(const SkDraw& draw, SkCanvas::VertexMode, - int vertexCount, - const SkPoint verts[], const SkPoint texs[], - const SkColor colors[], SkXfermode* xmode, - const uint16_t indices[], int indexCount, - const SkPaint& paint); - virtual void drawDevice(const SkDraw& draw, SkDevice*, int x, int y, - const SkPaint&); - - - virtual void setMatrixClip(const SkMatrix& transform, const SkRegion& region); - virtual void drawToHDC(HDC dc, int x, int y, const RECT* src_rect); - virtual bool IsVectorial() { return true; } - - void LoadClipRegion(); - - private: - // Applies the SkPaint's painting properties in the current GDI context, if - // possible. If GDI can't support all paint's properties, returns false. It - // doesn't execute the "commands" in SkPaint. - bool ApplyPaint(const SkPaint& paint); - - // Selects a new object in the device context. It can be a pen, a brush, a - // clipping region, a bitmap or a font. Returns the old selected object. - HGDIOBJ SelectObject(HGDIOBJ object); - - // Creates a brush according to SkPaint's properties. - bool CreateBrush(bool use_brush, const SkPaint& paint); - - // Creates a pen according to SkPaint's properties. - bool CreatePen(bool use_pen, const SkPaint& paint); - - // Restores back the previous objects (pen, brush, etc) after a paint command. - void Cleanup(); - - // Creates a brush according to SkPaint's properties. - bool CreateBrush(bool use_brush, COLORREF color); - - // Creates a pen according to SkPaint's properties. - bool CreatePen(bool use_pen, COLORREF color, int stroke_width, - float stroke_miter, DWORD pen_style); - - // Draws a bitmap in the the device, using the currently loaded matrix. - void InternalDrawBitmap(const SkBitmap& bitmap, int x, int y, - const SkPaint& paint); - - // The Windows Device Context handle. It is the backend used with GDI drawing. - // This backend is write-only and vectorial. - HDC hdc_; - - // 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_; - - // Previously selected brush before the current drawing. - HGDIOBJ previous_brush_; - - // Previously selected pen before the current drawing. - HGDIOBJ previous_pen_; - - DISALLOW_COPY_AND_ASSIGN(VectorDevice); -}; - -} // namespace gfx - -#endif // BASE_GFX_VECTOR_DEVICE_H_ - +// TODO(brettw) this file should be removed and the includes changed to this +// new location. +#include "webkit/port/platform/graphics/skia/public/VectorDevice.h" |