diff options
author | awalker@google.com <awalker@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-08-20 19:34:30 +0000 |
---|---|---|
committer | awalker@google.com <awalker@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-08-20 19:34:30 +0000 |
commit | 247e24728016f366f80bda88a3d4b8d7efd2dafe (patch) | |
tree | 55c4cd91a050f9abe230e62184bc85c793af8df1 /base | |
parent | 8448f1ae7fc731b8c02f66bb36bb4849096d61a6 (diff) | |
download | chromium_src-247e24728016f366f80bda88a3d4b8d7efd2dafe.zip chromium_src-247e24728016f366f80bda88a3d4b8d7efd2dafe.tar.gz chromium_src-247e24728016f366f80bda88a3d4b8d7efd2dafe.tar.bz2 |
Merges in updated versions of Mac graphics platform classes, adds generic typedefs for use by higher level classes that just need to hold a reference (though does not yet refactor those classes).
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@1099 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base')
-rw-r--r-- | base/base.xcodeproj/project.pbxproj | 10 | ||||
-rw-r--r-- | base/gfx/bitmap_platform_device.h | 40 | ||||
-rwxr-xr-x | base/gfx/bitmap_platform_device_mac.cc | 330 | ||||
-rwxr-xr-x | base/gfx/bitmap_platform_device_mac.h | 122 | ||||
-rw-r--r-- | base/gfx/convolver.h | 5 | ||||
-rw-r--r-- | base/gfx/image_operations.cc | 1 | ||||
-rw-r--r-- | base/gfx/platform_canvas.h | 40 | ||||
-rwxr-xr-x | base/gfx/platform_canvas_mac.cc | 169 | ||||
-rwxr-xr-x | base/gfx/platform_canvas_mac.h | 129 | ||||
-rw-r--r-- | base/gfx/platform_device.h | 40 | ||||
-rwxr-xr-x | base/gfx/platform_device_mac.cc | 130 | ||||
-rwxr-xr-x | base/gfx/platform_device_mac.h | 117 | ||||
-rw-r--r-- | base/gfx/size_mac.cc | 48 | ||||
-rw-r--r-- | base/gfx/skia_utils_mac.cc | 91 | ||||
-rw-r--r-- | base/gfx/skia_utils_mac.h | 71 |
15 files changed, 1338 insertions, 5 deletions
diff --git a/base/base.xcodeproj/project.pbxproj b/base/base.xcodeproj/project.pbxproj index 0479b04..89a1aa5 100644 --- a/base/base.xcodeproj/project.pbxproj +++ b/base/base.xcodeproj/project.pbxproj @@ -461,8 +461,6 @@ 825403D40D92D31D0006B936 /* rect.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = rect.cc; sourceTree = "<group>"; }; 825403D50D92D31D0006B936 /* rect.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rect.h; sourceTree = "<group>"; }; 825403D70D92D31D0006B936 /* size.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = size.h; sourceTree = "<group>"; }; - 825403DA0D92D31D0006B936 /* uniscribe.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = uniscribe.cc; sourceTree = "<group>"; }; - 825403DB0D92D31D0006B936 /* uniscribe.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uniscribe.h; sourceTree = "<group>"; }; 825403DC0D92D31D0006B936 /* vector_canvas.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = vector_canvas.cc; sourceTree = "<group>"; }; 825403DD0D92D31D0006B936 /* vector_canvas.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vector_canvas.h; sourceTree = "<group>"; }; 825403DE0D92D31D0006B936 /* vector_device.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = vector_device.cc; sourceTree = "<group>"; }; @@ -497,6 +495,9 @@ A5A0282D0E4CFA8500498DA9 /* file_util_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = file_util_unittest.cc; sourceTree = "<group>"; }; A5CB82960E5C74E300FD6825 /* platform_test.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = platform_test.h; sourceTree = "<group>"; }; A5CB82970E5C74E300FD6825 /* platform_test_mac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = platform_test_mac.mm; sourceTree = "<group>"; }; + AB6BC1ED0E54E836006436D5 /* bitmap_platform_device.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bitmap_platform_device.h; sourceTree = "<group>"; }; + AB6BC1F10E54E900006436D5 /* platform_canvas.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = platform_canvas.h; sourceTree = "<group>"; }; + AB6BC1F50E54E97B006436D5 /* platform_device.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = platform_device.h; sourceTree = "<group>"; }; ABF4B98E0DC2BA6900A6E319 /* base_paths_mac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = base_paths_mac.mm; sourceTree = "<group>"; }; ABF4B99D0DC2BB6000A6E319 /* clipboard_mac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = clipboard_mac.mm; sourceTree = "<group>"; }; ABF4B9B40DC2BC9F00A6E319 /* path_service.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = path_service.cc; sourceTree = "<group>"; }; @@ -861,6 +862,7 @@ children = ( 825403C00D92D31D0006B936 /* bitmap_header.cc */, 825403C10D92D31D0006B936 /* bitmap_header.h */, + AB6BC1ED0E54E836006436D5 /* bitmap_platform_device.h */, 829E2F940DBFD74B00819EBF /* bitmap_platform_device_mac.cc */, 829E2F950DBFD74B00819EBF /* bitmap_platform_device_mac.h */, E48A06680E3F70B500172919 /* convolver.cc */, @@ -874,9 +876,11 @@ 7B8505A10E5B3FBE00730B43 /* img_resize_perftest.cc */, 825403C80D92D31D0006B936 /* native_theme.cc */, 825403C90D92D31D0006B936 /* native_theme.h */, + AB6BC1F10E54E900006436D5 /* platform_canvas.h */, 7B8505A20E5B3FBE00730B43 /* native_theme_unittest.cc */, 829E2F990DBFD76300819EBF /* platform_canvas_mac.cc */, 829E2F980DBFD76300819EBF /* platform_canvas_mac.h */, + AB6BC1F50E54E97B006436D5 /* platform_device.h */, 7B8505A30E5B3FBE00730B43 /* platform_canvas_unittest.cc */, 829E2F9D0DBFD76F00819EBF /* platform_device_mac.cc */, 829E2F9C0DBFD76F00819EBF /* platform_device_mac.h */, @@ -894,8 +898,6 @@ 825403D70D92D31D0006B936 /* size.h */, 7B8505A50E5B3FBE00730B43 /* skia_utils.cc */, 7B8505A60E5B3FBE00730B43 /* skia_utils.h */, - 825403DA0D92D31D0006B936 /* uniscribe.cc */, - 825403DB0D92D31D0006B936 /* uniscribe.h */, 7B8505A70E5B3FBE00730B43 /* uniscribe_unittest.cc */, 825403DC0D92D31D0006B936 /* vector_canvas.cc */, 825403DD0D92D31D0006B936 /* vector_canvas.h */, diff --git a/base/gfx/bitmap_platform_device.h b/base/gfx/bitmap_platform_device.h new file mode 100644 index 0000000..7d34995 --- /dev/null +++ b/base/gfx/bitmap_platform_device.h @@ -0,0 +1,40 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// 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) +class BitmapPlatformDeviceWin; +typedef BitmapPlatformDeviceWin BitmapPlatformDevice; +#elif defined(OS_MACOSX) +class BitmapPlatformDeviceMac; +typedef BitmapPlatformDeviceMac BitmapPlatformDevice; +#endif diff --git a/base/gfx/bitmap_platform_device_mac.cc b/base/gfx/bitmap_platform_device_mac.cc new file mode 100755 index 0000000..c87a8f0 --- /dev/null +++ b/base/gfx/bitmap_platform_device_mac.cc @@ -0,0 +1,330 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include <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() { + 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 SetTransform(const SkMatrix& t); + void SetClipRegion(const SkRegion& region); + + // Loads the current transform (taking into account offset_*_) 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_; + + // Additional offset applied to the transform. See setDeviceOffset(). + int offset_x_; + int offset_y_; + + // 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), + offset_x_(0), + offset_y_(0), + 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_)); + SkRegion region(rect); + SetClipRegion(region); + CGContextRetain(bitmap_context_); +} + +void BitmapPlatformDeviceMac::BitmapPlatformDeviceMacData::SetTransform( + const SkMatrix& t) { + transform_ = t; + config_dirty_ = true; +} + +void BitmapPlatformDeviceMac::BitmapPlatformDeviceMacData::SetClipRegion( + const SkRegion& region) { + 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_); + t.postTranslate(SkIntToScalar(-offset_x_), SkIntToScalar(-offset_y_)); + LoadTransformToCGContext(bitmap_context_, t); + + // TODO(brettw) we should support more than just rect clipping here. + SkIRect rect = clip_region_.getBounds(); + rect.offset(-offset_x_, -offset_y_); + + CGContextClipToRect(bitmap_context_, SkIRectToCGRect(rect)); +} + + +// 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) { + // each pixel is 4 bytes (RGBA): + void* data = malloc(height * width * 4); + if (!data) return NULL; + + SkBitmap bitmap; + 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 + } + + 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::SetTransform(const SkMatrix& matrix) { + data_->SetTransform(matrix); +} + +void BitmapPlatformDeviceMac::SetDeviceOffset(int x, int y) { + data_->offset_x_ = x; + data_->offset_y_ = y; +} + +void BitmapPlatformDeviceMac::SetClipRegion(const SkRegion& region) { + data_->SetClipRegion(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(); +} + +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); + } + } + } +} + +// 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 +} + +} // namespace gfx diff --git a/base/gfx/bitmap_platform_device_mac.h b/base/gfx/bitmap_platform_device_mac.h new file mode 100755 index 0000000..3a67239 --- /dev/null +++ b/base/gfx/bitmap_platform_device_mac.h @@ -0,0 +1,122 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#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 SetTransform(const SkMatrix& matrix); + virtual void SetDeviceOffset(int x, int y); + + // This currently only supports extremely simple clip rects. + virtual void SetClipRegion(const SkRegion& region); + + virtual void DrawToContext(CGContextRef context, int x, int y, + const CGRect* src_rect); + 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: + // 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 + +#endif // BASE_GFX_BITMAP_PLATFORM_DEVICE_MAC_H__ diff --git a/base/gfx/convolver.h b/base/gfx/convolver.h index 8a2310e..2cb91af 100644 --- a/base/gfx/convolver.h +++ b/base/gfx/convolver.h @@ -34,6 +34,11 @@ #include "base/basictypes.h" +// avoid confusion with Mac OS X's math library (Carbon) +#if defined(OS_MACOSX) +#undef FloatToFixed +#endif + namespace gfx { // Represents a filter in one dimension. Each output pixel has one entry in this diff --git a/base/gfx/image_operations.cc b/base/gfx/image_operations.cc index 4dde08c..e53f6ce 100644 --- a/base/gfx/image_operations.cc +++ b/base/gfx/image_operations.cc @@ -204,7 +204,6 @@ void ResizeFilter::ComputeFilters(int src_size, // that the range covered by the filter won't necessarily cover any source // pixel boundaries. Therefore, we use these clamped values (max of 1) for // some computations. - float clamped_src_support = std::min(1.0f, src_support); float clamped_scale = std::min(1.0f, scale); // Speed up the divisions below by turning them into multiplies. diff --git a/base/gfx/platform_canvas.h b/base/gfx/platform_canvas.h new file mode 100644 index 0000000..269027d --- /dev/null +++ b/base/gfx/platform_canvas.h @@ -0,0 +1,40 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// 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. + +#if defined(OS_WIN) +class PlatformCanvasWin; +typedef PlatformCanvasWin PlatformCanvas; +#elif defined(OS_MACOSX) +class PlatformCanvasMac; +typedef PlatformCanvasMac PlatformCanvas; +#endif diff --git a/base/gfx/platform_canvas_mac.cc b/base/gfx/platform_canvas_mac.cc new file mode 100755 index 0000000..0344a0a --- /dev/null +++ b/base/gfx/platform_canvas_mac.cc @@ -0,0 +1,169 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "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, NULL); +} + +PlatformCanvasMac::PlatformCanvasMac(int width, + int height, + bool is_opaque, + CGContextRef context) + : SkCanvas() { + initialize(width, height, is_opaque, context); +} + +PlatformCanvasMac::~PlatformCanvasMac() { +} + +void PlatformCanvasMac::initialize(int width, + int height, + bool is_opaque, + CGContextRef context) { + SkDevice* device = + createPlatformDevice(width, height, is_opaque, context); + setDevice(device); + device->unref(); // was created with refcount 1, and setDevice also refs +} + +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()); +} + +// Clipping ------------------------------------------------------------------- + +bool PlatformCanvasMac::clipRect(const SkRect& rect, SkRegion::Op op) { + bool ret = SkCanvas::clipRect(rect, op); + getTopPlatformDevice().SetClipRegion(getTotalClip()); + return ret; +} + +bool PlatformCanvasMac::clipPath(const SkPath& path, SkRegion::Op op) { + bool ret = SkCanvas::clipPath(path, op); + getTopPlatformDevice().SetClipRegion(getTotalClip()); + return ret; +} + +bool PlatformCanvasMac::clipRegion(const SkRegion& deviceRgn, SkRegion::Op op) { + bool ret = SkCanvas::clipRegion(deviceRgn, op); + getTopPlatformDevice().SetClipRegion(getTotalClip()); + return ret; +} + +// Transforming --------------------------------------------------------------- + +bool PlatformCanvasMac::translate(SkScalar dx, SkScalar dy) { + if (!SkCanvas::translate(dx, dy)) + return false; + getTopPlatformDevice().SetTransform(getTotalMatrix()); + return true; +} + +bool PlatformCanvasMac::scale(SkScalar sx, SkScalar sy) { + if (!SkCanvas::scale(sx, sy)) + return false; + getTopPlatformDevice().SetTransform(getTotalMatrix()); + return true; +} + +int PlatformCanvasMac::saveLayer(const SkRect* bounds, + const SkPaint* paint, + SaveFlags flags) { + int result = SkCanvas::saveLayer(bounds, paint, flags); + + // saveLayer will have created a new device which, depending on the clip + // rect, may be smaller than the original layer. Therefore, it will have a + // transform applied, and we need to sync CG with that transform. + SkCanvas::LayerIter iter(this, false); + PlatformDeviceMac& new_device = + *static_cast<PlatformDeviceMac*>(iter.device()); + + // There man not actually be a new layer if the layer is empty. + if (!iter.done()) { + new_device.SetDeviceOffset(iter.x(), iter.y()); + new_device.SetTransform(getTotalMatrix()); + new_device.SetClipRegion(getTotalClip()); + } + return result; +} + +int PlatformCanvasMac::save(SkCanvas::SaveFlags flags) { + int ret = SkCanvas::save(flags); + PlatformDeviceMac& device = getTopPlatformDevice(); + device.SetTransform(getTotalMatrix()); + device.SetClipRegion(getTotalClip()); + return ret; +} + +void PlatformCanvasMac::restore() { + SkCanvas::restore(); + PlatformDeviceMac& device = getTopPlatformDevice(); + device.SetTransform(getTotalMatrix()); + device.SetClipRegion(getTotalClip()); +} + +SkDevice* PlatformCanvasMac::createDevice(SkBitmap::Config config, + int width, + int height, + bool is_opaque) { + 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; +} + +} // namespace gfx diff --git a/base/gfx/platform_canvas_mac.h b/base/gfx/platform_canvas_mac.h new file mode 100755 index 0000000..fd07797 --- /dev/null +++ b/base/gfx/platform_canvas_mac.h @@ -0,0 +1,129 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#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 + void initialize(int width, int height, bool is_opaque, CGContextRef context); + + // Keep the platform clipping in sync with the skia clipping. Note that + // platform clipping may only clip to the bounds of the clipping region, if + // it is complex. + virtual bool clipRect(const SkRect& rect, + SkRegion::Op op = SkRegion::kIntersect_Op); + virtual bool clipPath(const SkPath& path, + SkRegion::Op op = SkRegion::kIntersect_Op); + virtual bool clipRegion(const SkRegion& deviceRgn, + SkRegion::Op op = SkRegion::kIntersect_Op); + + // 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(); + + // overridden to keep the platform graphics context in sync with the canvas + virtual bool translate(SkScalar dx, SkScalar dy); + virtual bool scale(SkScalar sx, SkScalar sy); + virtual int saveLayer(const SkRect* bounds, const SkPaint* paint, + SaveFlags flags = kARGB_ClipLayer_SaveFlag); + virtual int save(SkCanvas::SaveFlags flags = SkCanvas::kMatrixClip_SaveFlag); + virtual void restore(); + + // 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); + + // 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 + +#endif // BASE_GFX_PLATFORM_CANVAS_MAC_H__ diff --git a/base/gfx/platform_device.h b/base/gfx/platform_device.h new file mode 100644 index 0000000..22a079f --- /dev/null +++ b/base/gfx/platform_device.h @@ -0,0 +1,40 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// 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) +class PlatformDeviceWin; +typedef PlatformDeviceWin PlatformDevice; +#elif defined(OS_MACOSX) +class PlatformDeviceMac; +typedef PlatformDeviceMac PlatformDevice; +#endif diff --git a/base/gfx/platform_device_mac.cc b/base/gfx/platform_device_mac.cc new file mode 100755 index 0000000..2e3d065 --- /dev/null +++ b/base/gfx/platform_device_mac.cc @@ -0,0 +1,130 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "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}; + 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) { + // TOOD: CoreGraphics can concatenate transforms, but not reset the current + // ont. Either find a workaround or remove this function if it turns out + // to be unneeded on the Mac. +} + +} // namespace gfx diff --git a/base/gfx/platform_device_mac.h b/base/gfx/platform_device_mac.h new file mode 100755 index 0000000..1da1c7a --- /dev/null +++ b/base/gfx/platform_device_mac.h @@ -0,0 +1,117 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#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; + + // Translate the device's coordinate system by the given amount; this will + // override any previous calls to this function. + virtual void SetTransform(const SkMatrix& matrix) = 0; + + // Devices may be in a layer and offset from the root device. In this case, + // the transform (set by setTransform) will corrspond to the root device, and + // this device will actually be offset from there. + // + // This is called after a layered device is created to tell us the location. + // This location will be factored into any transforms applied via + // setTransform. + // + // If this function is not called, the offset defaults to (0, 0); + virtual void SetDeviceOffset(int x, int y) = 0; + + // Sets the clipping region, overriding any previous calls. + virtual void SetClipRegion(const SkRegion& region) = 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; + + // 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); + + 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 + +#endif // BASE_GFX_PLATFORM_DEVICE_MAC_H__ diff --git a/base/gfx/size_mac.cc b/base/gfx/size_mac.cc new file mode 100644 index 0000000..08bf997 --- /dev/null +++ b/base/gfx/size_mac.cc @@ -0,0 +1,48 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import <CoreGraphics/CoreGraphics.h> +#include "base/gfx/size.h" + +#include <ostream> + +namespace gfx { + +CGSize Size::ToCGSize() const { + CGSize s; + s.width = width_; + s.height = height_; + return s; +} + +std::ostream& operator<<(std::ostream& out, const gfx::Size& s) { + return out << s.width() << "x" << s.height(); +} + +} // namespace gfx diff --git a/base/gfx/skia_utils_mac.cc b/base/gfx/skia_utils_mac.cc new file mode 100644 index 0000000..030a887 --- /dev/null +++ b/base/gfx/skia_utils_mac.cc @@ -0,0 +1,91 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "base/gfx/skia_utils_mac.h" + +#include "base/logging.h" +#include "SkRect.h" + +namespace gfx { + +SkIRect CGRectToSkIRect(const CGRect& rect) { + SkIRect sk_rect = { + SkScalarRound(rect.origin.x), + SkScalarRound(rect.origin.x), + SkScalarRound(rect.origin.x + rect.size.width), + SkScalarRound(rect.origin.y + rect.size.height) + }; + return sk_rect; +} + +SkRect CGRectToSkRect(const CGRect& rect) { + SkRect sk_rect = { + rect.origin.x, + rect.origin.x, + rect.origin.x + rect.size.width, + rect.origin.y + rect.size.height, + }; + return sk_rect; +} + +CGRect SkIRectToCGRect(const SkIRect& rect) { + CGRect cg_rect = { + { rect.fLeft, rect.fTop }, + { rect.fRight - rect.fLeft, rect.fBottom - rect.fTop } + }; + return cg_rect; +} + +CGRect SkRectToCGRect(const SkRect& rect) { + CGRect cg_rect = { + { rect.fLeft, rect.fTop }, + { rect.fRight - rect.fLeft, rect.fBottom - rect.fTop } + }; + return cg_rect; +} + +// Converts CGColorRef to the ARGB layout Skia expects. +SkColor CGColorRefToSkColor(CGColorRef color) { + DCHECK(CGColorGetNumberOfComponents(color) == 4); + const CGFloat *components = CGColorGetComponents(color); + return SkColorSetARGB(SkScalarRound(255.0 * components[3]), // alpha + SkScalarRound(255.0 * components[0]), // red + SkScalarRound(255.0 * components[1]), // green + SkScalarRound(255.0 * components[2])); // blue +} + +// Converts ARGB to CGColorRef. +CGColorRef SkColorToCGColorRef(SkColor color) { + return CGColorCreateGenericRGB(SkColorGetR(color) / 255.0, + SkColorGetG(color) / 255.0, + SkColorGetB(color) / 255.0, + SkColorGetA(color) / 255.0); +} + +} // namespace gfx diff --git a/base/gfx/skia_utils_mac.h b/base/gfx/skia_utils_mac.h new file mode 100644 index 0000000..aa17188 --- /dev/null +++ b/base/gfx/skia_utils_mac.h @@ -0,0 +1,71 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +#ifndef BASE_GFX_SKIA_UTILS_MAC_H__ +#define BASE_GFX_SKIA_UTILS_MAC_H__ + +#include "SkColor.h" +#include <CoreGraphics/CGColor.h> + +struct SkIRect; +struct SkPoint; +struct SkRect; + +namespace gfx { + +// Converts a Skia point to a CoreGraphics CGPoint. +// Both use same in-memory format. +inline const CGPoint& SkPointToCGPoint(const SkPoint& point) { + return reinterpret_cast<const CGPoint&>(point); +} + +// Converts a CoreGraphics point to a Skia CGPoint. +// Both use same in-memory format. +inline const SkPoint& CGPointToSkPoint(const CGPoint& point) { + return reinterpret_cast<const SkPoint&>(point); +} + +// Rectangle converters. +SkRect CGRectToSkRect(const CGRect& rect); +SkIRect CGRectToSkIRect(const CGRect& rect); + +// Converts a Skia rect to a CoreGraphics CGRect. +CGRect SkIRectToCGRect(const SkIRect& rect); +CGRect SkRectToCGRect(const SkRect& rect); + +// Converts CGColorRef to the ARGB layout Skia expects. +SkColor CGColorRefToSkColor(CGColorRef color); + +// Converts ARGB to CGColorRef. +CGColorRef SkColorToCGColorRef(SkColor color); + +} // namespace gfx + +#endif |