diff options
author | maruel@google.com <maruel@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-09-25 22:08:44 +0000 |
---|---|---|
committer | maruel@google.com <maruel@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-09-25 22:08:44 +0000 |
commit | de8d2667d6953abb31b7c5385ca718ad47adf6a1 (patch) | |
tree | 3d4499631bbf551dd81bb50b43452705b37d7bfb /base | |
parent | c9ec45429c64884c35f83b74131c0e3ae5b2bbe9 (diff) | |
download | chromium_src-de8d2667d6953abb31b7c5385ca718ad47adf6a1.zip chromium_src-de8d2667d6953abb31b7c5385ca718ad47adf6a1.tar.gz chromium_src-de8d2667d6953abb31b7c5385ca718ad47adf6a1.tar.bz2 |
Wow, it's been a while since we cleaned EOL.
Ran dos2unix on *.cc, *.h, *.py and SCons*.*
Ran for /R /D %a in (*.*) do @if exist %a\.svn\. svn pset svn:eol-style LF %a\*.cc
Ran for /R /D %a in (*.*) do @if exist %a\.svn\. svn pset svn:eol-style LF %a\*.h
Ran for /R /D %a in (*.*) do @if exist %a\.svn\. svn pset svn:eol-style LF %a\*.py
Ran for /R /D %a in (*.*) do @if exist %a\.svn\. svn pset svn:eol-style LF %a\SCons*.*
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@2611 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base')
-rw-r--r-- | base/cpu.cc | 104 | ||||
-rw-r--r-- | base/cpu.h | 84 | ||||
-rw-r--r-- | base/gfx/bitmap_platform_device_linux.h | 62 | ||||
-rw-r--r-- | base/gfx/bitmap_platform_device_win.cc | 974 | ||||
-rw-r--r-- | base/gfx/bitmap_platform_device_win.h | 222 | ||||
-rw-r--r-- | base/gfx/platform_canvas_win.cc | 170 | ||||
-rw-r--r-- | base/gfx/platform_canvas_win.h | 370 | ||||
-rw-r--r-- | base/gfx/platform_device_win.cc | 458 | ||||
-rw-r--r-- | base/gfx/platform_device_win.h | 192 |
9 files changed, 1318 insertions, 1318 deletions
diff --git a/base/cpu.cc b/base/cpu.cc index d227d9a..41ebc083 100644 --- a/base/cpu.cc +++ b/base/cpu.cc @@ -1,52 +1,52 @@ -// 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/cpu.h"
-#include <intrin.h>
-#include <string>
-
-namespace base {
-
-CPU::CPU()
- : type_(0),
- family_(0),
- model_(0),
- stepping_(0),
- ext_model_(0),
- ext_family_(0),
- cpu_vendor_("unknown") {
- Initialize();
-}
-
-void CPU::Initialize() {
- int cpu_info[4] = {-1};
- char cpu_string[0x20];
-
- // __cpuid with an InfoType argument of 0 returns the number of
- // valid Ids in CPUInfo[0] and the CPU identification string in
- // the other three array elements. The CPU identification string is
- // not in linear order. The code below arranges the information
- // in a human readable form.
- //
- // More info can be found here:
- // http://msdn.microsoft.com/en-us/library/hskdteyh.aspx
- __cpuid(cpu_info, 0);
- int num_ids = cpu_info[0];
- memset(cpu_string, 0, sizeof(cpu_string));
- *(reinterpret_cast<int*>(cpu_string)) = cpu_info[1];
- *(reinterpret_cast<int*>(cpu_string+4)) = cpu_info[3];
- *(reinterpret_cast<int*>(cpu_string+8)) = cpu_info[2];
-
- // Interpret CPU feature information.
- __cpuid(cpu_info, 1);
- stepping_ = cpu_info[0] & 0xf;
- model_ = (cpu_info[0] >> 4) & 0xf;
- family_ = (cpu_info[0] >> 8) & 0xf;
- type_ = (cpu_info[0] >> 12) & 0x3;
- ext_model_ = (cpu_info[0] >> 16) & 0xf;
- ext_family_ = (cpu_info[0] >> 20) & 0xff;
- cpu_vendor_ = cpu_string;
-}
-
-} // namespace base
+// 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/cpu.h" +#include <intrin.h> +#include <string> + +namespace base { + +CPU::CPU() + : type_(0), + family_(0), + model_(0), + stepping_(0), + ext_model_(0), + ext_family_(0), + cpu_vendor_("unknown") { + Initialize(); +} + +void CPU::Initialize() { + int cpu_info[4] = {-1}; + char cpu_string[0x20]; + + // __cpuid with an InfoType argument of 0 returns the number of + // valid Ids in CPUInfo[0] and the CPU identification string in + // the other three array elements. The CPU identification string is + // not in linear order. The code below arranges the information + // in a human readable form. + // + // More info can be found here: + // http://msdn.microsoft.com/en-us/library/hskdteyh.aspx + __cpuid(cpu_info, 0); + int num_ids = cpu_info[0]; + memset(cpu_string, 0, sizeof(cpu_string)); + *(reinterpret_cast<int*>(cpu_string)) = cpu_info[1]; + *(reinterpret_cast<int*>(cpu_string+4)) = cpu_info[3]; + *(reinterpret_cast<int*>(cpu_string+8)) = cpu_info[2]; + + // Interpret CPU feature information. + __cpuid(cpu_info, 1); + stepping_ = cpu_info[0] & 0xf; + model_ = (cpu_info[0] >> 4) & 0xf; + family_ = (cpu_info[0] >> 8) & 0xf; + type_ = (cpu_info[0] >> 12) & 0x3; + ext_model_ = (cpu_info[0] >> 16) & 0xf; + ext_family_ = (cpu_info[0] >> 20) & 0xff; + cpu_vendor_ = cpu_string; +} + +} // namespace base @@ -1,42 +1,42 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BASE_CPU_H_
-#define BASE_CPU_H_
-
-#include <string>
-
-namespace base {
-
-// Query information about the processor.
-class CPU {
- public:
- // Constructor
- CPU();
-
- // Accessors for CPU information.
- const std::string& vendor_name() const { return cpu_vendor_; }
- int stepping() const { return stepping_; }
- int model() const { return model_; }
- int family() const { return family_; }
- int type() const { return type_; }
- int extended_model() const { return ext_model_; }
- int extended_family() const { return ext_family_; }
-
- private:
- // Query the processor for CPUID information.
- void Initialize();
-
- int type_; // process type
- int family_; // family of the processor
- int model_; // model of processor
- int stepping_; // processor revision number
- int ext_model_;
- int ext_family_;
- std::string cpu_vendor_;
-};
-
-} // namespace base
-
-#endif // BASE_CPU_H_
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_CPU_H_ +#define BASE_CPU_H_ + +#include <string> + +namespace base { + +// Query information about the processor. +class CPU { + public: + // Constructor + CPU(); + + // Accessors for CPU information. + const std::string& vendor_name() const { return cpu_vendor_; } + int stepping() const { return stepping_; } + int model() const { return model_; } + int family() const { return family_; } + int type() const { return type_; } + int extended_model() const { return ext_model_; } + int extended_family() const { return ext_family_; } + + private: + // Query the processor for CPUID information. + void Initialize(); + + int type_; // process type + int family_; // family of the processor + int model_; // model of processor + int stepping_; // processor revision number + int ext_model_; + int ext_family_; + std::string cpu_vendor_; +}; + +} // namespace base + +#endif // BASE_CPU_H_ diff --git a/base/gfx/bitmap_platform_device_linux.h b/base/gfx/bitmap_platform_device_linux.h index d8504dc..2bb5a24 100644 --- a/base/gfx/bitmap_platform_device_linux.h +++ b/base/gfx/bitmap_platform_device_linux.h @@ -1,31 +1,31 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BASE_GFX_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"
-
-namespace gfx {
-
-// I'm trying to get away with defining as little as possible on this. Right
-// now, we don't do anything.
-class BitmapPlatformDeviceLinux : public PlatformDeviceLinux {
- 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.
- BitmapPlatformDeviceLinux(const SkBitmap& other);
- virtual ~BitmapPlatformDeviceLinux();
-};
-
-} // namespace gfx
-
-#endif // BASE_GFX_BITMAP_PLATFORM_DEVICE_LINUX_H_
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_GFX_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" + +namespace gfx { + +// I'm trying to get away with defining as little as possible on this. Right +// now, we don't do anything. +class BitmapPlatformDeviceLinux : public PlatformDeviceLinux { + 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. + BitmapPlatformDeviceLinux(const SkBitmap& other); + virtual ~BitmapPlatformDeviceLinux(); +}; + +} // namespace gfx + +#endif // BASE_GFX_BITMAP_PLATFORM_DEVICE_LINUX_H_ diff --git a/base/gfx/bitmap_platform_device_win.cc b/base/gfx/bitmap_platform_device_win.cc index 4214412..e3ac799 100644 --- a/base/gfx/bitmap_platform_device_win.cc +++ b/base/gfx/bitmap_platform_device_win.cc @@ -1,487 +1,487 @@ -// 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/bitmap_header.h"
-#include "base/logging.h"
-#include "base/process_util.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;
-}
-
-// 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<process_util::ProcessMetrics> process_metrics(
- process_util::ProcessMetrics::CreateProcessMetrics(GetCurrentProcess()));
- CHECK(process_metrics->GetPagefileUsage() < kLotsOfMem);
-
- // Everything else.
- CHECK(0);
-}
-
-} // 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);
- // The device offset is already modified according to the transformation.
- void SetDeviceOffset(int x, int y);
-
- const SkMatrix& transform() const {
- return transform_;
- }
-
- protected:
- // Loads the current transform (taking into account offset_*_) 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_;
-
- // 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 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),
- offset_x_(0),
- offset_y_(0),
- 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::SetDeviceOffset(int x,
- int y) {
- offset_x_ = x;
- offset_y_ = y;
- config_dirty_ = true;
-}
-
-void BitmapPlatformDeviceWin::BitmapPlatformDeviceWinData::LoadConfig() {
- if (!config_dirty_ || !hdc_)
- return; // Nothing to do.
- config_dirty_ = false;
-
- // Transform.
- SkMatrix t(transform_);
- t.postTranslate(SkIntToScalar(-offset_x_), SkIntToScalar(-offset_y_));
- 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();
- t.postTranslate(SkIntToScalar(-offset_x_), SkIntToScalar(-offset_y_));
- 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
- // we just expand it here.
- if (width == 0)
- width = 1;
- if (height == 0)
- height = 1;
-
- BITMAPINFOHEADER hdr;
- CreateBitmapHeader(width, height, &hdr);
-
- void* data;
- 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)
- CrashForBitmapAllocationFailure(width, height);
-
- 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::setDeviceOffset(int x, int y) {
- data_->SetDeviceOffset(x, y);
-}
-
-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 {
- BLENDFUNCTION blend_function = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA};
- AlphaBlend(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
-
+// 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/bitmap_header.h" +#include "base/logging.h" +#include "base/process_util.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; +} + +// 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<process_util::ProcessMetrics> process_metrics( + process_util::ProcessMetrics::CreateProcessMetrics(GetCurrentProcess())); + CHECK(process_metrics->GetPagefileUsage() < kLotsOfMem); + + // Everything else. + CHECK(0); +} + +} // 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); + // The device offset is already modified according to the transformation. + void SetDeviceOffset(int x, int y); + + const SkMatrix& transform() const { + return transform_; + } + + protected: + // Loads the current transform (taking into account offset_*_) 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_; + + // 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 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), + offset_x_(0), + offset_y_(0), + 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::SetDeviceOffset(int x, + int y) { + offset_x_ = x; + offset_y_ = y; + config_dirty_ = true; +} + +void BitmapPlatformDeviceWin::BitmapPlatformDeviceWinData::LoadConfig() { + if (!config_dirty_ || !hdc_) + return; // Nothing to do. + config_dirty_ = false; + + // Transform. + SkMatrix t(transform_); + t.postTranslate(SkIntToScalar(-offset_x_), SkIntToScalar(-offset_y_)); + 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(); + t.postTranslate(SkIntToScalar(-offset_x_), SkIntToScalar(-offset_y_)); + 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 + // we just expand it here. + if (width == 0) + width = 1; + if (height == 0) + height = 1; + + BITMAPINFOHEADER hdr; + CreateBitmapHeader(width, height, &hdr); + + void* data; + 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) + CrashForBitmapAllocationFailure(width, height); + + 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::setDeviceOffset(int x, int y) { + data_->SetDeviceOffset(x, y); +} + +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 { + BLENDFUNCTION blend_function = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA}; + AlphaBlend(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 a5d04c0..cc3f9e8 100644 --- a/base/gfx/bitmap_platform_device_win.h +++ b/base/gfx/bitmap_platform_device_win.h @@ -1,111 +1,111 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BASE_GFX_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 setDeviceOffset(int x, int y);
-
- virtual void drawToHDC(HDC dc, int x, int y, const RECT* src_rect);
- virtual void prepareForGDI(int x, int y, int width, int height);
- virtual void postProcessGDI(int x, int y, int width, int height);
- virtual void makeOpaque(int x, int y, int width, int height);
- virtual void fixupAlphaBeforeCompositing();
- virtual bool IsVectorial() { return false; }
-
- // Returns the color value at the specified location. This does not
- // consider any transforms that may be set on the device.
- SkColor getColorAt(int x, int y);
-
- protected:
- // Flushes the Windows device context so that the pixel data can be accessed
- // directly by Skia. Overridden from SkDevice, this is called when Skia
- // starts accessing pixel data.
- virtual void onAccessBitmap(SkBitmap* bitmap);
-
- private:
- // Function pointer used by the processPixels method for setting the alpha
- // value of a particular pixel.
- typedef void (*adjustAlpha)(uint32_t* pixel);
-
- // Reference counted data that can be shared between multiple devices. This
- // allows copy constructors and operator= for devices to work properly. The
- // bitmaps used by the base device class are already refcounted and copyable.
- class BitmapPlatformDeviceWinData;
-
- // Private constructor.
- BitmapPlatformDeviceWin(BitmapPlatformDeviceWinData* data, const SkBitmap& bitmap);
-
- // Loops through each of the pixels in the specified range, invoking
- // adjustor for the alpha value of each pixel. If |width| or |height| are -1,
- // the available width/height is used.
- template<adjustAlpha adjustor>
- void processPixels(int x,
- int y,
- int width,
- int height);
-
- // Data associated with this device, guaranteed non-null.
- scoped_refptr<BitmapPlatformDeviceWinData> data_;
-};
-
-} // namespace gfx
-
-#endif // BASE_GFX_BITMAP_PLATFORM_DEVICE_WIN_H__
-
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_GFX_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 setDeviceOffset(int x, int y); + + virtual void drawToHDC(HDC dc, int x, int y, const RECT* src_rect); + virtual void prepareForGDI(int x, int y, int width, int height); + virtual void postProcessGDI(int x, int y, int width, int height); + virtual void makeOpaque(int x, int y, int width, int height); + virtual void fixupAlphaBeforeCompositing(); + virtual bool IsVectorial() { return false; } + + // Returns the color value at the specified location. This does not + // consider any transforms that may be set on the device. + SkColor getColorAt(int x, int y); + + protected: + // Flushes the Windows device context so that the pixel data can be accessed + // directly by Skia. Overridden from SkDevice, this is called when Skia + // starts accessing pixel data. + virtual void onAccessBitmap(SkBitmap* bitmap); + + private: + // Function pointer used by the processPixels method for setting the alpha + // value of a particular pixel. + typedef void (*adjustAlpha)(uint32_t* pixel); + + // Reference counted data that can be shared between multiple devices. This + // allows copy constructors and operator= for devices to work properly. The + // bitmaps used by the base device class are already refcounted and copyable. + class BitmapPlatformDeviceWinData; + + // Private constructor. + BitmapPlatformDeviceWin(BitmapPlatformDeviceWinData* data, const SkBitmap& bitmap); + + // Loops through each of the pixels in the specified range, invoking + // adjustor for the alpha value of each pixel. If |width| or |height| are -1, + // the available width/height is used. + template<adjustAlpha adjustor> + void processPixels(int x, + int y, + int width, + int height); + + // Data associated with this device, guaranteed non-null. + scoped_refptr<BitmapPlatformDeviceWinData> data_; +}; + +} // namespace gfx + +#endif // BASE_GFX_BITMAP_PLATFORM_DEVICE_WIN_H__ + diff --git a/base/gfx/platform_canvas_win.cc b/base/gfx/platform_canvas_win.cc index c8b1fcb..b22a097 100644 --- a/base/gfx/platform_canvas_win.cc +++ b/base/gfx/platform_canvas_win.cc @@ -1,85 +1,85 @@ -// 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"
-
-#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 {
-
-PlatformCanvasWin::PlatformCanvasWin() : SkCanvas() {
-}
-
-PlatformCanvasWin::PlatformCanvasWin(int width, int height, bool is_opaque)
- : SkCanvas() {
- initialize(width, height, is_opaque, NULL);
-}
-
-PlatformCanvasWin::PlatformCanvasWin(int width,
- int height,
- bool is_opaque,
- HANDLE shared_section)
- : SkCanvas() {
- initialize(width, height, is_opaque, shared_section);
-}
-
-PlatformCanvasWin::~PlatformCanvasWin() {
-}
-
-void PlatformCanvasWin::initialize(int width,
- int height,
- bool is_opaque,
- HANDLE shared_section) {
- SkDevice* device =
- createPlatformDevice(width, height, is_opaque, shared_section);
- setDevice(device);
- device->unref(); // was created with refcount 1, and setDevice also refs
-}
-
-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
+// 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" + +#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 { + +PlatformCanvasWin::PlatformCanvasWin() : SkCanvas() { +} + +PlatformCanvasWin::PlatformCanvasWin(int width, int height, bool is_opaque) + : SkCanvas() { + initialize(width, height, is_opaque, NULL); +} + +PlatformCanvasWin::PlatformCanvasWin(int width, + int height, + bool is_opaque, + HANDLE shared_section) + : SkCanvas() { + initialize(width, height, is_opaque, shared_section); +} + +PlatformCanvasWin::~PlatformCanvasWin() { +} + +void PlatformCanvasWin::initialize(int width, + int height, + bool is_opaque, + HANDLE shared_section) { + SkDevice* device = + createPlatformDevice(width, height, is_opaque, shared_section); + setDevice(device); + device->unref(); // was created with refcount 1, and setDevice also refs +} + +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 6c1c59e..1e88970 100644 --- a/base/gfx/platform_canvas_win.h +++ b/base/gfx/platform_canvas_win.h @@ -1,185 +1,185 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BASE_GFX_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
- void initialize(int width, int height, bool is_opaque, HANDLE shared_section);
-
- // 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 object. 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_EVIL_CONSTRUCTORS(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), for_paint_(true) {
- initPaint(true);
- }
-
- CanvasPaintT(HWND hwnd, bool opaque) : hwnd_(hwnd), for_paint_(true) {
- 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.
- initialize(ps_.rcPaint.right - ps_.rcPaint.left,
- ps_.rcPaint.bottom - ps_.rcPaint.top, opaque, NULL);
-
- // 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_EVIL_CONSTRUCTORS(CanvasPaintT);
-};
-
-typedef CanvasPaintT<PlatformCanvasWin> PlatformCanvasWinPaint;
-
-} // namespace gfx
-
-#endif // BASE_GFX_PLATFORM_CANVAS_WIN_H__
-
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_GFX_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 + void initialize(int width, int height, bool is_opaque, HANDLE shared_section); + + // 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 object. 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_EVIL_CONSTRUCTORS(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), for_paint_(true) { + initPaint(true); + } + + CanvasPaintT(HWND hwnd, bool opaque) : hwnd_(hwnd), for_paint_(true) { + 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. + initialize(ps_.rcPaint.right - ps_.rcPaint.left, + ps_.rcPaint.bottom - ps_.rcPaint.top, opaque, NULL); + + // 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_EVIL_CONSTRUCTORS(CanvasPaintT); +}; + +typedef CanvasPaintT<PlatformCanvasWin> PlatformCanvasWinPaint; + +} // namespace gfx + +#endif // BASE_GFX_PLATFORM_CANVAS_WIN_H__ + diff --git a/base/gfx/platform_device_win.cc b/base/gfx/platform_device_win.cc index 13d5031d..a1e8568 100644 --- a/base/gfx/platform_device_win.cc +++ b/base/gfx/platform_device_win.cc @@ -1,229 +1,229 @@ -// 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
-
+// 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 b697b1d..d5052a2 100644 --- a/base/gfx/platform_device_win.h +++ b/base/gfx/platform_device_win.h @@ -1,96 +1,96 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BASE_GFX_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
-
-#endif // BASE_GFX_PLATFORM_DEVICE_WIN_H__
-
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_GFX_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 + +#endif // BASE_GFX_PLATFORM_DEVICE_WIN_H__ + |