From de8d2667d6953abb31b7c5385ca718ad47adf6a1 Mon Sep 17 00:00:00 2001 From: "maruel@google.com" <maruel@google.com@0039d316-1c4b-4281-b951-d872f2087c98> Date: Thu, 25 Sep 2008 22:08:44 +0000 Subject: [PATCH] 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 --- base/cpu.cc | 104 +-- base/cpu.h | 84 +- base/gfx/bitmap_platform_device_linux.h | 62 +- base/gfx/bitmap_platform_device_win.cc | 974 ++++++++++++------------ base/gfx/bitmap_platform_device_win.h | 222 +++--- base/gfx/platform_canvas_win.cc | 170 ++--- base/gfx/platform_canvas_win.h | 370 ++++----- base/gfx/platform_device_win.cc | 458 +++++------ base/gfx/platform_device_win.h | 192 ++--- gears/SConscript.libgd | 160 ++-- gears/SConscript.libjpeg | 148 ++-- gears/SConscript.libpng | 104 +-- gears/SConscript.portaudio | 102 +-- gears/SConscript.zlib | 94 +-- testing/SConscript.gtest | 68 +- tools/code_coverage/coverage.py | 538 ++++++------- tools/code_coverage/process_coverage.py | 466 ++++++------ tools/memory_watcher/call_stack.cc | 752 +++++++++--------- webkit/SConscript.javascriptcore_pcre | 92 +-- webkit/SConscript.port | 254 +++--- webkit/pending/Peerable.h | 50 +- webkit/port/bindings/v8/v8_collection.h | 518 ++++++------- 22 files changed, 2991 insertions(+), 2991 deletions(-) diff --git a/base/cpu.cc b/base/cpu.cc index d227d9a4f01e7..41ebc083db3fb 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 diff --git a/base/cpu.h b/base/cpu.h index e437a199fa543..15cc668525471 100644 --- a/base/cpu.h +++ b/base/cpu.h @@ -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 d8504dc6dc0e8..2bb5a2400d87d 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 42144121b9cbe..e3ac79971986c 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 a5d04c094f745..cc3f9e805453a 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 c8b1fcb1c5ecb..b22a09724334c 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 6c1c59ef01140..1e88970dd8dbc 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 13d5031d5791d..a1e8568387250 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 b697b1df1bda5..d5052a2f8a31f 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__ + diff --git a/gears/SConscript.libgd b/gears/SConscript.libgd index fb3c25c15957b..652e4e1be3660 100644 --- a/gears/SConscript.libgd +++ b/gears/SConscript.libgd @@ -1,80 +1,80 @@ -# Copyright (c) 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. - -# Ripped and modded from chrome. - -Import('env') - -env = env.Clone( -) - -env.Replace( - LIBGD_DIR = '$THIRD_PARTY_DIR/libgd', - CPPPATH = [ - '$LIBGD_DIR', - '$THIRD_PARTY_DIR/libjpeg', - '$THIRD_PARTY_DIR/libpng', - '$THIRD_PARTY_DIR/zlib', - ], -) - -env.Append( - CPPDEFINES = [ - 'HAVE_CONFIG_H', - 'BGDWIN32', - ], - -) - -if env['PLATFORM'] == 'win32': - env.Append( - CPPFLAGS = [ -# Disable some warnings when building third-party code, so we can enable /WX. -# Examples: -# warning C4244: conversion from 'type1' to 'type2', possible loss of data -# warning C4018: signed/unsigned mismatch in comparison -# warning C4003: not enough actual parameters for macro - '/wd4244', - '/wd4996', - '/wd4005', - '/wd4142', - '/wd4018', - '/wd4133', - '/wd4102', - ], - ) - - -input_files = [ - '$LIBGD_DIR/gd.c', - '$LIBGD_DIR/gdfx.c', - '$LIBGD_DIR/gd_security.c', - '$LIBGD_DIR/gd_gd.c', - '$LIBGD_DIR/gd_gd2.c', - '$LIBGD_DIR/gd_io.c', - '$LIBGD_DIR/gd_io_dp.c', - '$LIBGD_DIR/gd_gif_in.c', - '$LIBGD_DIR/gd_gif_out.c', - '$LIBGD_DIR/gd_io_file.c', - '$LIBGD_DIR/gd_io_ss.c', - '$LIBGD_DIR/gd_jpeg.c', - '$LIBGD_DIR/gd_png.c', - '$LIBGD_DIR/gd_ss.c', - '$LIBGD_DIR/gd_topal.c', - '$LIBGD_DIR/gd_wbmp.c', - '$LIBGD_DIR/gdcache.c', - '$LIBGD_DIR/gdfontg.c', - '$LIBGD_DIR/gdfontl.c', - '$LIBGD_DIR/gdfontmb.c', - '$LIBGD_DIR/gdfonts.c', - '$LIBGD_DIR/gdfontt.c', - '$LIBGD_DIR/gdft.c', - '$LIBGD_DIR/gdhelpers.c', - '$LIBGD_DIR/gdkanji.c', - '$LIBGD_DIR/gdtables.c', - '$LIBGD_DIR/gdxpm.c', - '$LIBGD_DIR/wbmp.c', -] - -env.ChromeStaticLibrary('gd', input_files) +# Copyright (c) 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. + +# Ripped and modded from chrome. + +Import('env') + +env = env.Clone( +) + +env.Replace( + LIBGD_DIR = '$THIRD_PARTY_DIR/libgd', + CPPPATH = [ + '$LIBGD_DIR', + '$THIRD_PARTY_DIR/libjpeg', + '$THIRD_PARTY_DIR/libpng', + '$THIRD_PARTY_DIR/zlib', + ], +) + +env.Append( + CPPDEFINES = [ + 'HAVE_CONFIG_H', + 'BGDWIN32', + ], + +) + +if env['PLATFORM'] == 'win32': + env.Append( + CPPFLAGS = [ +# Disable some warnings when building third-party code, so we can enable /WX. +# Examples: +# warning C4244: conversion from 'type1' to 'type2', possible loss of data +# warning C4018: signed/unsigned mismatch in comparison +# warning C4003: not enough actual parameters for macro + '/wd4244', + '/wd4996', + '/wd4005', + '/wd4142', + '/wd4018', + '/wd4133', + '/wd4102', + ], + ) + + +input_files = [ + '$LIBGD_DIR/gd.c', + '$LIBGD_DIR/gdfx.c', + '$LIBGD_DIR/gd_security.c', + '$LIBGD_DIR/gd_gd.c', + '$LIBGD_DIR/gd_gd2.c', + '$LIBGD_DIR/gd_io.c', + '$LIBGD_DIR/gd_io_dp.c', + '$LIBGD_DIR/gd_gif_in.c', + '$LIBGD_DIR/gd_gif_out.c', + '$LIBGD_DIR/gd_io_file.c', + '$LIBGD_DIR/gd_io_ss.c', + '$LIBGD_DIR/gd_jpeg.c', + '$LIBGD_DIR/gd_png.c', + '$LIBGD_DIR/gd_ss.c', + '$LIBGD_DIR/gd_topal.c', + '$LIBGD_DIR/gd_wbmp.c', + '$LIBGD_DIR/gdcache.c', + '$LIBGD_DIR/gdfontg.c', + '$LIBGD_DIR/gdfontl.c', + '$LIBGD_DIR/gdfontmb.c', + '$LIBGD_DIR/gdfonts.c', + '$LIBGD_DIR/gdfontt.c', + '$LIBGD_DIR/gdft.c', + '$LIBGD_DIR/gdhelpers.c', + '$LIBGD_DIR/gdkanji.c', + '$LIBGD_DIR/gdtables.c', + '$LIBGD_DIR/gdxpm.c', + '$LIBGD_DIR/wbmp.c', +] + +env.ChromeStaticLibrary('gd', input_files) diff --git a/gears/SConscript.libjpeg b/gears/SConscript.libjpeg index 69c338ede50a2..5931eb63545a2 100644 --- a/gears/SConscript.libjpeg +++ b/gears/SConscript.libjpeg @@ -1,74 +1,74 @@ -# Copyright (c) 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. - -# Ripped and modded from chrome. - -Import('env') - -env = env.Clone( - LIBJPEG_DIR = '' -) - -env.Replace( - LIBJPEG_DIR = '$THIRD_PARTY_DIR/libjpeg', - CPPPATH = [ - '$LIBJPEG_DIR', - ], -) - -#env.Append( -# CPPDEFINES = [ -# ], -#) - -input_files = [ - '$LIBJPEG_DIR/jcapimin.c', - '$LIBJPEG_DIR/jcapistd.c', - '$LIBJPEG_DIR/jccoefct.c', - '$LIBJPEG_DIR/jccolor.c', - '$LIBJPEG_DIR/jcdctmgr.c', - '$LIBJPEG_DIR/jchuff.c', - '$LIBJPEG_DIR/jcinit.c', - '$LIBJPEG_DIR/jcmainct.c', - '$LIBJPEG_DIR/jcmarker.c', - '$LIBJPEG_DIR/jcmaster.c', - '$LIBJPEG_DIR/jcomapi.c', - '$LIBJPEG_DIR/jcparam.c', - '$LIBJPEG_DIR/jcphuff.c', - '$LIBJPEG_DIR/jcprepct.c', - '$LIBJPEG_DIR/jcsample.c', - '$LIBJPEG_DIR/jctrans.c', - '$LIBJPEG_DIR/jdapimin.c', - '$LIBJPEG_DIR/jdapistd.c', - '$LIBJPEG_DIR/jdatadst.c', - '$LIBJPEG_DIR/jdatasrc.c', - '$LIBJPEG_DIR/jdcoefct.c', - '$LIBJPEG_DIR/jdcolor.c', - '$LIBJPEG_DIR/jddctmgr.c', - '$LIBJPEG_DIR/jdhuff.c', - '$LIBJPEG_DIR/jdinput.c', - '$LIBJPEG_DIR/jdmainct.c', - '$LIBJPEG_DIR/jdmarker.c', - '$LIBJPEG_DIR/jdmaster.c', - '$LIBJPEG_DIR/jdmerge.c', - '$LIBJPEG_DIR/jdphuff.c', - '$LIBJPEG_DIR/jdpostct.c', - '$LIBJPEG_DIR/jdsample.c', - '$LIBJPEG_DIR/jdtrans.c', - '$LIBJPEG_DIR/jerror.c', - '$LIBJPEG_DIR/jfdctflt.c', - '$LIBJPEG_DIR/jfdctfst.c', - '$LIBJPEG_DIR/jfdctint.c', - '$LIBJPEG_DIR/jidctflt.c', - '$LIBJPEG_DIR/jidctfst.c', - '$LIBJPEG_DIR/jidctint.c', - '$LIBJPEG_DIR/jidctred.c', - '$LIBJPEG_DIR/jquant1.c', - '$LIBJPEG_DIR/jquant2.c', - '$LIBJPEG_DIR/jutils.c', - '$LIBJPEG_DIR/jmemmgr.c', - '$LIBJPEG_DIR/jmemnobs.c', -] - -env.ChromeStaticLibrary('jpeg', input_files) +# Copyright (c) 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. + +# Ripped and modded from chrome. + +Import('env') + +env = env.Clone( + LIBJPEG_DIR = '' +) + +env.Replace( + LIBJPEG_DIR = '$THIRD_PARTY_DIR/libjpeg', + CPPPATH = [ + '$LIBJPEG_DIR', + ], +) + +#env.Append( +# CPPDEFINES = [ +# ], +#) + +input_files = [ + '$LIBJPEG_DIR/jcapimin.c', + '$LIBJPEG_DIR/jcapistd.c', + '$LIBJPEG_DIR/jccoefct.c', + '$LIBJPEG_DIR/jccolor.c', + '$LIBJPEG_DIR/jcdctmgr.c', + '$LIBJPEG_DIR/jchuff.c', + '$LIBJPEG_DIR/jcinit.c', + '$LIBJPEG_DIR/jcmainct.c', + '$LIBJPEG_DIR/jcmarker.c', + '$LIBJPEG_DIR/jcmaster.c', + '$LIBJPEG_DIR/jcomapi.c', + '$LIBJPEG_DIR/jcparam.c', + '$LIBJPEG_DIR/jcphuff.c', + '$LIBJPEG_DIR/jcprepct.c', + '$LIBJPEG_DIR/jcsample.c', + '$LIBJPEG_DIR/jctrans.c', + '$LIBJPEG_DIR/jdapimin.c', + '$LIBJPEG_DIR/jdapistd.c', + '$LIBJPEG_DIR/jdatadst.c', + '$LIBJPEG_DIR/jdatasrc.c', + '$LIBJPEG_DIR/jdcoefct.c', + '$LIBJPEG_DIR/jdcolor.c', + '$LIBJPEG_DIR/jddctmgr.c', + '$LIBJPEG_DIR/jdhuff.c', + '$LIBJPEG_DIR/jdinput.c', + '$LIBJPEG_DIR/jdmainct.c', + '$LIBJPEG_DIR/jdmarker.c', + '$LIBJPEG_DIR/jdmaster.c', + '$LIBJPEG_DIR/jdmerge.c', + '$LIBJPEG_DIR/jdphuff.c', + '$LIBJPEG_DIR/jdpostct.c', + '$LIBJPEG_DIR/jdsample.c', + '$LIBJPEG_DIR/jdtrans.c', + '$LIBJPEG_DIR/jerror.c', + '$LIBJPEG_DIR/jfdctflt.c', + '$LIBJPEG_DIR/jfdctfst.c', + '$LIBJPEG_DIR/jfdctint.c', + '$LIBJPEG_DIR/jidctflt.c', + '$LIBJPEG_DIR/jidctfst.c', + '$LIBJPEG_DIR/jidctint.c', + '$LIBJPEG_DIR/jidctred.c', + '$LIBJPEG_DIR/jquant1.c', + '$LIBJPEG_DIR/jquant2.c', + '$LIBJPEG_DIR/jutils.c', + '$LIBJPEG_DIR/jmemmgr.c', + '$LIBJPEG_DIR/jmemnobs.c', +] + +env.ChromeStaticLibrary('jpeg', input_files) diff --git a/gears/SConscript.libpng b/gears/SConscript.libpng index d184d53ff3002..5cdff5002f567 100644 --- a/gears/SConscript.libpng +++ b/gears/SConscript.libpng @@ -1,52 +1,52 @@ -# Copyright (c) 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. - -# Ripped and modded from chrome. - -Import('env') - -env = env.Clone( -) - -env.Replace( - LIBPNG_DIR = '$THIRD_PARTY_DIR/libpng', - CPPPATH = [ - '$LIBPNG_DIR', - '$THIRD_PARTY_DIR/zlib', - ], -) - -env.Append( - CPPDEFINES = [ - ], -) - -input_files = [ - # Common Files - '$LIBPNG_DIR/png.c', - '$LIBPNG_DIR/pngerror.c', - '$LIBPNG_DIR/pngget.c', - '$LIBPNG_DIR/pngmem.c', - '$LIBPNG_DIR/pngset.c', - '$LIBPNG_DIR/pngtrans.c', - - # Reading PNGs - '$LIBPNG_DIR/pngpread.c', - '$LIBPNG_DIR/pngread.c', - '$LIBPNG_DIR/pngrio.c', - '$LIBPNG_DIR/pngrtran.c', - '$LIBPNG_DIR/pngrutil.c', -] - -# The following files are not yet needed; exclude them to save size. -if not env['OFFICIAL_BUILD']: - input_files += [ - # Writing PNGs - '$LIBPNG_DIR/pngwio.c', - '$LIBPNG_DIR/pngwrite.c', - '$LIBPNG_DIR/pngwtran.c', - '$LIBPNG_DIR/pngwutil.c', - ] - -env.ChromeStaticLibrary('png', input_files) +# Copyright (c) 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. + +# Ripped and modded from chrome. + +Import('env') + +env = env.Clone( +) + +env.Replace( + LIBPNG_DIR = '$THIRD_PARTY_DIR/libpng', + CPPPATH = [ + '$LIBPNG_DIR', + '$THIRD_PARTY_DIR/zlib', + ], +) + +env.Append( + CPPDEFINES = [ + ], +) + +input_files = [ + # Common Files + '$LIBPNG_DIR/png.c', + '$LIBPNG_DIR/pngerror.c', + '$LIBPNG_DIR/pngget.c', + '$LIBPNG_DIR/pngmem.c', + '$LIBPNG_DIR/pngset.c', + '$LIBPNG_DIR/pngtrans.c', + + # Reading PNGs + '$LIBPNG_DIR/pngpread.c', + '$LIBPNG_DIR/pngread.c', + '$LIBPNG_DIR/pngrio.c', + '$LIBPNG_DIR/pngrtran.c', + '$LIBPNG_DIR/pngrutil.c', +] + +# The following files are not yet needed; exclude them to save size. +if not env['OFFICIAL_BUILD']: + input_files += [ + # Writing PNGs + '$LIBPNG_DIR/pngwio.c', + '$LIBPNG_DIR/pngwrite.c', + '$LIBPNG_DIR/pngwtran.c', + '$LIBPNG_DIR/pngwutil.c', + ] + +env.ChromeStaticLibrary('png', input_files) diff --git a/gears/SConscript.portaudio b/gears/SConscript.portaudio index f318c01d5346d..6987457c21331 100644 --- a/gears/SConscript.portaudio +++ b/gears/SConscript.portaudio @@ -1,51 +1,51 @@ -# Copyright (c) 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. - -Import('env') - -env = env.Clone( -) - -env.Replace( - PA_DIR = '$THIRD_PARTY_DIR/portaudio', - CPPPATH = [ - '$PA_DIR/include', - '$PA_DIR/src/common', - '$PA_DIR/src/os/win', - ], -) - -env.Append( - CPPDEFINES = [ - 'PA_NO_DS', - 'PA_NO_ASIO', - ], -) - -if env['PLATFORM'] == 'win32': - env.Append( - CPPFLAGS = [ - '/wd4133', - '/wd4101', - ], - ) - -input_files = [ - '$PA_DIR/src/common/pa_allocation.c', - '$PA_DIR/src/common/pa_converters.c', - '$PA_DIR/src/common/pa_cpuload.c', - '$PA_DIR/src/common/pa_debugprint.c', - '$PA_DIR/src/common/pa_dither.c', - '$PA_DIR/src/common/pa_front.c', - '$PA_DIR/src/common/pa_process.c', - '$PA_DIR/src/common/pa_skeleton.c', - '$PA_DIR/src/common/pa_stream.c', - '$PA_DIR/src/common/pa_trace.c', - '$PA_DIR/src/hostapi/wmme/pa_win_wmme.c', - '$PA_DIR/src/os/win/pa_win_hostapis.c', - '$PA_DIR/src/os/win/pa_win_util.c', - '$PA_DIR/src/os/win/pa_win_waveformat.c', -] - -env.ChromeStaticLibrary('portaudio', input_files) +# Copyright (c) 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. + +Import('env') + +env = env.Clone( +) + +env.Replace( + PA_DIR = '$THIRD_PARTY_DIR/portaudio', + CPPPATH = [ + '$PA_DIR/include', + '$PA_DIR/src/common', + '$PA_DIR/src/os/win', + ], +) + +env.Append( + CPPDEFINES = [ + 'PA_NO_DS', + 'PA_NO_ASIO', + ], +) + +if env['PLATFORM'] == 'win32': + env.Append( + CPPFLAGS = [ + '/wd4133', + '/wd4101', + ], + ) + +input_files = [ + '$PA_DIR/src/common/pa_allocation.c', + '$PA_DIR/src/common/pa_converters.c', + '$PA_DIR/src/common/pa_cpuload.c', + '$PA_DIR/src/common/pa_debugprint.c', + '$PA_DIR/src/common/pa_dither.c', + '$PA_DIR/src/common/pa_front.c', + '$PA_DIR/src/common/pa_process.c', + '$PA_DIR/src/common/pa_skeleton.c', + '$PA_DIR/src/common/pa_stream.c', + '$PA_DIR/src/common/pa_trace.c', + '$PA_DIR/src/hostapi/wmme/pa_win_wmme.c', + '$PA_DIR/src/os/win/pa_win_hostapis.c', + '$PA_DIR/src/os/win/pa_win_util.c', + '$PA_DIR/src/os/win/pa_win_waveformat.c', +] + +env.ChromeStaticLibrary('portaudio', input_files) diff --git a/gears/SConscript.zlib b/gears/SConscript.zlib index 46eceec13deee..4049073c581a3 100644 --- a/gears/SConscript.zlib +++ b/gears/SConscript.zlib @@ -1,47 +1,47 @@ -# Copyright (c) 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. - -# Ripped and modded from chrome. - -Import('env') - -env = env.Clone( -) - -env.Replace( - ZLIB_DIR = '$THIRD_PARTY_DIR/zlib', - CPPPATH = [ - '$ZLIB_DIR', - ], -) - -#env.Append( -# CPPDEFINES = [ -# ], -#) - -input_files = [ - # Common Files - '$ZLIB_DIR/adler32.c', - '$ZLIB_DIR/zutil.c', - # Inflate Algorithm (use inflate or infback, but not both) - '$ZLIB_DIR/inflate.c', - '$ZLIB_DIR/inffast.c', - '$ZLIB_DIR/inftrees.c', -] - -# The following files are not yet needed; exclude them to save size. -if not env['OFFICIAL_BUILD']: - input_files += [ - # Other Algorithms - '$ZLIB_DIR/compress.c', - '$ZLIB_DIR/deflate.c', - '$ZLIB_DIR/uncompr.c', - # Other Common Files - '$ZLIB_DIR/crc32.c', - '$ZLIB_DIR/gzio.c', - '$ZLIB_DIR/trees.c', - ] - -env.ChromeStaticLibrary('zlib-gears', input_files) +# Copyright (c) 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. + +# Ripped and modded from chrome. + +Import('env') + +env = env.Clone( +) + +env.Replace( + ZLIB_DIR = '$THIRD_PARTY_DIR/zlib', + CPPPATH = [ + '$ZLIB_DIR', + ], +) + +#env.Append( +# CPPDEFINES = [ +# ], +#) + +input_files = [ + # Common Files + '$ZLIB_DIR/adler32.c', + '$ZLIB_DIR/zutil.c', + # Inflate Algorithm (use inflate or infback, but not both) + '$ZLIB_DIR/inflate.c', + '$ZLIB_DIR/inffast.c', + '$ZLIB_DIR/inftrees.c', +] + +# The following files are not yet needed; exclude them to save size. +if not env['OFFICIAL_BUILD']: + input_files += [ + # Other Algorithms + '$ZLIB_DIR/compress.c', + '$ZLIB_DIR/deflate.c', + '$ZLIB_DIR/uncompr.c', + # Other Common Files + '$ZLIB_DIR/crc32.c', + '$ZLIB_DIR/gzio.c', + '$ZLIB_DIR/trees.c', + ] + +env.ChromeStaticLibrary('zlib-gears', input_files) diff --git a/testing/SConscript.gtest b/testing/SConscript.gtest index dc8a6887b1f1f..4f6bbf01debee 100644 --- a/testing/SConscript.gtest +++ b/testing/SConscript.gtest @@ -1,34 +1,34 @@ -# 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. - -Import('env') - -env = env.Clone() - -env.Prepend( - CPPPATH = [ - '$GTEST_DIR', - '$GTEST_DIR/include', - ], -) - -if env['PLATFORM'] == 'win32': - env.Append( - CCFLAGS = [ - '/TP', - - '/WX', - '/Wp64', - ], - ) - -input_files = [ - 'gtest/src/gtest-death-test.cc', - 'gtest/src/gtest-filepath.cc', - 'gtest/src/gtest-port.cc', - 'gtest/src/gtest.cc', -] - -env.ChromeStaticLibrary('gtest', input_files) - +# 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. + +Import('env') + +env = env.Clone() + +env.Prepend( + CPPPATH = [ + '$GTEST_DIR', + '$GTEST_DIR/include', + ], +) + +if env['PLATFORM'] == 'win32': + env.Append( + CCFLAGS = [ + '/TP', + + '/WX', + '/Wp64', + ], + ) + +input_files = [ + 'gtest/src/gtest-death-test.cc', + 'gtest/src/gtest-filepath.cc', + 'gtest/src/gtest-port.cc', + 'gtest/src/gtest.cc', +] + +env.ChromeStaticLibrary('gtest', input_files) + diff --git a/tools/code_coverage/coverage.py b/tools/code_coverage/coverage.py index a805cd7a111d3..ca6cd17204bcc 100644 --- a/tools/code_coverage/coverage.py +++ b/tools/code_coverage/coverage.py @@ -1,269 +1,269 @@ -#!/bin/env python -# 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. - - -"""Module to setup and generate code coverage data - -This module first sets up the environment for code coverage, instruments the -binaries, runs the tests and collects the code coverage data. - - -Usage: - coverage.py --upload=<upload_location> - --revision=<revision_number> - --src_root=<root_of_source_tree> - [--tools_path=<tools_path>] -""" - -import logging -import optparse -import os -import shutil -import subprocess -import sys -import tempfile - -import google.logging_utils -import google.process_utils as proc - - -# The list of binaries that will be instrumented for code coverage -# TODO(niranjan): Add a complete list of binaries -windows_binaries = ['unit_tests.exe', - 'ui_tests.exe'] - -# The list of tests that will be run -#TODO(niranjan): Add more tests -windows_tests = ['unit_tests.exe', - 'ui_tests.exe'] - - -def IsWindows(): - """Checks if the current platform is Windows. - """ - return sys.platform[:3] == 'win' - - -class Coverage(object): - """Class to set up and generate code coverage. - - This class contains methods that are useful to set up the environment for - code coverage. - - Attributes: - instrumented: A boolean indicating if all the binaries have been - instrumented. - """ - - def __init__(self, - revision, - vsts_path = None, - lcov_converter_path = None): - google.logging_utils.config_root() - self.revision = revision - self.instrumented = False - self.vsts_path = vsts_path - self.lcov_converter_path = lcov_converter_path - self._dir = None - - - def SetUp(self, binaries): - """Set up the platform specific environment and instrument the binaries for - coverage. - - This method sets up the environment, instruments all the compiled binaries - and sets up the code coverage counters. - - Args: - binaries: List of binaries that need to be instrumented. - - Returns: - Path of the file containing code coverage data on successful - instrumentation. - None on error. - """ - if self.instrumented: - logging.error('Binaries already instrumented') - return None - coverage_file = None - if IsWindows(): - # Stop all previous instance of VSPerfMon counters - counters_command = ('%s -shutdown' % - (os.path.join(self.vsts_path, 'vsperfcmd.exe'))) - (retcode, output) = proc.RunCommandFull(counters_command, - collect_output=True) - # TODO(niranjan): Add a check that to verify that the binaries were built - # using the /PROFILE linker flag. - if self.vsts_path == None or self.lcov_converter_path == None: - return None - # Remove trailing slashes - self.vsts_path = self.vsts_path.rstrip('\\') - instrument_command = '%s /COVERAGE ' % (os.path.join(self.vsts_path, - 'vsinstr.exe')) - for binary in binaries: - logging.info('binary = %s' % (binary)) - logging.info('instrument_command = %s' % (instrument_command)) - # Instrument each binary in the list - (retcode, output) = proc.RunCommandFull(instrument_command + binary, - collect_output=True) - # Check if the file has been instrumented correctly. - if output.pop().rfind('Successfully instrumented') == -1: - logging.error('Error instrumenting %s' % (binary)) - return None - - # Generate the file name for the coverage results - self._dir = tempfile.mkdtemp() - coverage_file = os.path.join(self._dir, 'chrome_win32_%s.coverage' % - (self.revision)) - logging.info('.coverage file: %s' % (coverage_file)) - - # After all the binaries have been instrumented, we start the counters. - counters_command = ('%s -start:coverage -output:%s' % - (os.path.join(self.vsts_path, 'vsperfcmd.exe'), - coverage_file)) - # Here we use subprocess.call() instead of the RunCommandFull because the - # VSPerfCmd spawns another process before terminating and this confuses - # the subprocess.Popen() used by RunCommandFull. - retcode = subprocess.call(counters_command) - # TODO(niranjan): Check whether the counters have been started - # successfully. - - # We are now ready to run tests and measure code coverage. - self.instrumented = True - else: - return None - return coverage_file - - - def TearDown(self): - """Tear down method. - - This method shuts down the counters, and cleans up all the intermediate - artifacts. - """ - if self.instrumented == False: - return - - if IsWindows(): - # Stop counters - counters_command = ('%s -shutdown' % - (os.path.join(self.vsts_path, 'vsperfcmd.exe'))) - (retcode, output) = proc.RunCommandFull(counters_command, - collect_output=True) - logging.info('Counters shut down: %s' % (output)) - # TODO(niranjan): Revert the instrumented binaries to their original - # versions. - else: - return - # Delete all the temp files and folders - if self._dir != None: - shutil.rmtree(self._dir, ignore_errors=True) - logging.info('Cleaned up temporary files and folders') - # Reset the instrumented flag. - self.instrumented = False - - - def Upload(self, coverage_file, upload_path, sym_path=None, src_root=None): - """Upload the results to the dashboard. - - This method uploads the coverage data to a dashboard where it will be - processed. On Windows, this method will first convert the .coverage file to - the lcov format. This method needs to be called before the TearDown method. - - Args: - coverage_file: The coverage data file to upload. - upload_path: Destination where the coverage data will be processed. - sym_path: Symbol path for the build (Win32 only) - src_root: Root folder of the source tree (Win32 only) - - Returns: - True on success. - False on failure. - """ - if self.IsWindows(): - # Stop counters - counters_command = ('%s -shutdown' % - (os.path.join(self.vsts_path, 'vsperfcmd.exe'))) - (retcode, output) = proc.RunCommandFull(counters_command, - collect_output=True) - logging.info('Counters shut down: %s' % (output)) - # Convert the .coverage file to lcov format - if self.lcov_converter_path == False: - logging.error('Lcov converter tool not found') - return False - self.lcov_converter_path = self.lcov_converter_path.rstrip('\\') - convert_command = ('%s -sym_path=%s -src_root=%s ' % - (os.path.join(self.lcov_converter_path, - 'coverage_analyzer.exe'), - sym_path, - src_root)) - logging.info('Conversion to lcov complete') - (retcode, output) = proc.RunCommandFull(convert_command + coverage_file, - collect_output=True) - shutil.copy(coverage_file, coverage_file.replace('.coverage', '')) - # TODO(niranjan): Upload this somewhere! - - -def main(): - # Command line parsing - parser = optparse.OptionParser() - # Path where the .coverage to .lcov converter tools are stored. - parser.add_option('-t', - '--tools_path', - dest='tools_path', - default=None, - help='Location of the coverage tools (windows only)') - parser.add_option('-u', - '--upload', - dest='upload_path' - default=None, - help='Location where the results should be uploaded') - # We need the revision number so that we can generate the output file of the - # format chrome_<platform>_<revision>.lcov - parser.add_option('-r', - '--revision', - dest='revision', - default=None, - help='Revision number of the Chromium source repo') - # Root of the source tree. Needed for converting the generated .coverage file - # on Windows to the open source lcov format. - parser.add_option('-s', - '--src_root', - dest='src_root', - default=None, - help='Root of the source repository') - - if revision == None or src_root == None or upload_path == None: - logging.error('Invalid command line arguments') - sys.exit(1) - - if IsWindows(): - # Initialize coverage - cov = coverage.Coverage(revision, - tools_path, - tools_path) - # Instrument the binaries - coverage_file = cov.SetUp(windows_binaries) - if coverage_file != None: - # Run all the tests - for test in windows_tests: - logging.info('Executing test %s: ' % binary) - (retcode, output) = proc.RunCommandFull(binary, collect_output=True) - if retcode != 0: - sys.exit(retcode) - else: - logging.error('Error during instrumentation.') - sys.exit(1) - - cov.Upload(coverage_file, - upload_path, - os.path.join(src_root, 'chrome', 'Release'), - src_root) - cov.TearDown() - - -if __name__ == '__main__': - sys.exit(main()) - +#!/bin/env python +# 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. + + +"""Module to setup and generate code coverage data + +This module first sets up the environment for code coverage, instruments the +binaries, runs the tests and collects the code coverage data. + + +Usage: + coverage.py --upload=<upload_location> + --revision=<revision_number> + --src_root=<root_of_source_tree> + [--tools_path=<tools_path>] +""" + +import logging +import optparse +import os +import shutil +import subprocess +import sys +import tempfile + +import google.logging_utils +import google.process_utils as proc + + +# The list of binaries that will be instrumented for code coverage +# TODO(niranjan): Add a complete list of binaries +windows_binaries = ['unit_tests.exe', + 'ui_tests.exe'] + +# The list of tests that will be run +#TODO(niranjan): Add more tests +windows_tests = ['unit_tests.exe', + 'ui_tests.exe'] + + +def IsWindows(): + """Checks if the current platform is Windows. + """ + return sys.platform[:3] == 'win' + + +class Coverage(object): + """Class to set up and generate code coverage. + + This class contains methods that are useful to set up the environment for + code coverage. + + Attributes: + instrumented: A boolean indicating if all the binaries have been + instrumented. + """ + + def __init__(self, + revision, + vsts_path = None, + lcov_converter_path = None): + google.logging_utils.config_root() + self.revision = revision + self.instrumented = False + self.vsts_path = vsts_path + self.lcov_converter_path = lcov_converter_path + self._dir = None + + + def SetUp(self, binaries): + """Set up the platform specific environment and instrument the binaries for + coverage. + + This method sets up the environment, instruments all the compiled binaries + and sets up the code coverage counters. + + Args: + binaries: List of binaries that need to be instrumented. + + Returns: + Path of the file containing code coverage data on successful + instrumentation. + None on error. + """ + if self.instrumented: + logging.error('Binaries already instrumented') + return None + coverage_file = None + if IsWindows(): + # Stop all previous instance of VSPerfMon counters + counters_command = ('%s -shutdown' % + (os.path.join(self.vsts_path, 'vsperfcmd.exe'))) + (retcode, output) = proc.RunCommandFull(counters_command, + collect_output=True) + # TODO(niranjan): Add a check that to verify that the binaries were built + # using the /PROFILE linker flag. + if self.vsts_path == None or self.lcov_converter_path == None: + return None + # Remove trailing slashes + self.vsts_path = self.vsts_path.rstrip('\\') + instrument_command = '%s /COVERAGE ' % (os.path.join(self.vsts_path, + 'vsinstr.exe')) + for binary in binaries: + logging.info('binary = %s' % (binary)) + logging.info('instrument_command = %s' % (instrument_command)) + # Instrument each binary in the list + (retcode, output) = proc.RunCommandFull(instrument_command + binary, + collect_output=True) + # Check if the file has been instrumented correctly. + if output.pop().rfind('Successfully instrumented') == -1: + logging.error('Error instrumenting %s' % (binary)) + return None + + # Generate the file name for the coverage results + self._dir = tempfile.mkdtemp() + coverage_file = os.path.join(self._dir, 'chrome_win32_%s.coverage' % + (self.revision)) + logging.info('.coverage file: %s' % (coverage_file)) + + # After all the binaries have been instrumented, we start the counters. + counters_command = ('%s -start:coverage -output:%s' % + (os.path.join(self.vsts_path, 'vsperfcmd.exe'), + coverage_file)) + # Here we use subprocess.call() instead of the RunCommandFull because the + # VSPerfCmd spawns another process before terminating and this confuses + # the subprocess.Popen() used by RunCommandFull. + retcode = subprocess.call(counters_command) + # TODO(niranjan): Check whether the counters have been started + # successfully. + + # We are now ready to run tests and measure code coverage. + self.instrumented = True + else: + return None + return coverage_file + + + def TearDown(self): + """Tear down method. + + This method shuts down the counters, and cleans up all the intermediate + artifacts. + """ + if self.instrumented == False: + return + + if IsWindows(): + # Stop counters + counters_command = ('%s -shutdown' % + (os.path.join(self.vsts_path, 'vsperfcmd.exe'))) + (retcode, output) = proc.RunCommandFull(counters_command, + collect_output=True) + logging.info('Counters shut down: %s' % (output)) + # TODO(niranjan): Revert the instrumented binaries to their original + # versions. + else: + return + # Delete all the temp files and folders + if self._dir != None: + shutil.rmtree(self._dir, ignore_errors=True) + logging.info('Cleaned up temporary files and folders') + # Reset the instrumented flag. + self.instrumented = False + + + def Upload(self, coverage_file, upload_path, sym_path=None, src_root=None): + """Upload the results to the dashboard. + + This method uploads the coverage data to a dashboard where it will be + processed. On Windows, this method will first convert the .coverage file to + the lcov format. This method needs to be called before the TearDown method. + + Args: + coverage_file: The coverage data file to upload. + upload_path: Destination where the coverage data will be processed. + sym_path: Symbol path for the build (Win32 only) + src_root: Root folder of the source tree (Win32 only) + + Returns: + True on success. + False on failure. + """ + if self.IsWindows(): + # Stop counters + counters_command = ('%s -shutdown' % + (os.path.join(self.vsts_path, 'vsperfcmd.exe'))) + (retcode, output) = proc.RunCommandFull(counters_command, + collect_output=True) + logging.info('Counters shut down: %s' % (output)) + # Convert the .coverage file to lcov format + if self.lcov_converter_path == False: + logging.error('Lcov converter tool not found') + return False + self.lcov_converter_path = self.lcov_converter_path.rstrip('\\') + convert_command = ('%s -sym_path=%s -src_root=%s ' % + (os.path.join(self.lcov_converter_path, + 'coverage_analyzer.exe'), + sym_path, + src_root)) + logging.info('Conversion to lcov complete') + (retcode, output) = proc.RunCommandFull(convert_command + coverage_file, + collect_output=True) + shutil.copy(coverage_file, coverage_file.replace('.coverage', '')) + # TODO(niranjan): Upload this somewhere! + + +def main(): + # Command line parsing + parser = optparse.OptionParser() + # Path where the .coverage to .lcov converter tools are stored. + parser.add_option('-t', + '--tools_path', + dest='tools_path', + default=None, + help='Location of the coverage tools (windows only)') + parser.add_option('-u', + '--upload', + dest='upload_path' + default=None, + help='Location where the results should be uploaded') + # We need the revision number so that we can generate the output file of the + # format chrome_<platform>_<revision>.lcov + parser.add_option('-r', + '--revision', + dest='revision', + default=None, + help='Revision number of the Chromium source repo') + # Root of the source tree. Needed for converting the generated .coverage file + # on Windows to the open source lcov format. + parser.add_option('-s', + '--src_root', + dest='src_root', + default=None, + help='Root of the source repository') + + if revision == None or src_root == None or upload_path == None: + logging.error('Invalid command line arguments') + sys.exit(1) + + if IsWindows(): + # Initialize coverage + cov = coverage.Coverage(revision, + tools_path, + tools_path) + # Instrument the binaries + coverage_file = cov.SetUp(windows_binaries) + if coverage_file != None: + # Run all the tests + for test in windows_tests: + logging.info('Executing test %s: ' % binary) + (retcode, output) = proc.RunCommandFull(binary, collect_output=True) + if retcode != 0: + sys.exit(retcode) + else: + logging.error('Error during instrumentation.') + sys.exit(1) + + cov.Upload(coverage_file, + upload_path, + os.path.join(src_root, 'chrome', 'Release'), + src_root) + cov.TearDown() + + +if __name__ == '__main__': + sys.exit(main()) + diff --git a/tools/code_coverage/process_coverage.py b/tools/code_coverage/process_coverage.py index c902f4dd470d7..6cec95bf792a6 100644 --- a/tools/code_coverage/process_coverage.py +++ b/tools/code_coverage/process_coverage.py @@ -1,233 +1,233 @@ -#!/usr/bin/python2.4 -# -# 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. - - -"""Script to clean the lcov files and convert it to HTML - -TODO(niranjan): Add usage information here -""" - - -import optparse -import os -import shutil -import sys -import tempfile - - -# These are source files that were generated during compile time. We want to -# remove references to these files from the lcov file otherwise genhtml will -# throw an error. -win32_srcs_exclude = ['parse.y', - 'xpathgrammar.cpp', - 'cssgrammar.cpp'] - - -def CleanPathNames(dir): - """Clean the pathnames of the HTML generated by genhtml. - - This method is required only for code coverage on Win32. Due to a known issue - with reading from CIFS shares mounted on Linux, genhtml appends a ^M to every - file name it reads from the Windows share, causing corrupt filenames in - genhtml's output folder. - - Args: - dir: Output folder of the genhtml output. - - Returns: - None - """ - # Stip off the ^M characters that get appended to the file name - for file in os.walk(dir): - file_clean = file.replace('\r', '') - if file_clean != file: - os.rename(file, file_clean) - - -def GenerateHtml(lcov_path, dash_root): - """Runs genhtml to convert lcov data to human readable HTML. - - This script expects the LCOV file name to be in the format: - chrome_<platform>_<revision#>.lcov. - This method parses the file name and then sets up the correct folder - hierarchy for the coverage data and then runs genhtml to get the actual HTML - formatted coverage data. - - Args: - lcov_path: Path of the lcov data file. - dash_root: Root location of the dashboard. - - Returns: - Code coverage percentage on sucess. - None on failure. - """ - # Parse the LCOV file name. - filename = os.path.basename(lcov_path).split('.')[0] - buffer = filename.split('_') - dash_root = dash_root.rstrip('/') # Remove trailing '/' - - # Set up correct folder heirarchy in the dashboard root - # TODO(niranjan): Check the formatting using a regexp - if len(buffer) >= 3: # Check if filename has right formatting - platform = buffer[len(buffer) - 2] - revision = buffer[len(buffer) - 1] - if os.path.exists(os.path.join(dash_root, platform)) == False: - os.mkdir(os.path.join(dash_root, platform)) - output_dir = os.join.path(dash_root, platform, revision) - os.mkdir(output_dir) - else: - # TODO(niranjan): Add failure logging here. - return None # File not formatted correctly - - # Run genhtml - os.system('/usr/bin/genhtml -o %s %s' % (output_dir, lcov_path)) - # TODO(niranjan): Check the exit status of the genhtml command. - # TODO(niranjan): Parse the stdout and return coverage percentage. - CleanPathNames(output_dir) - return 'dummy' # TODO(niranjan): Return actual percentage. - - -def CleanWin32Lcov(lcov_path, src_root): - """Cleanup the lcov data generated on Windows. - - This method fixes up the paths inside the lcov file from the Win32 specific - paths to the actual paths of the mounted CIFS share. The lcov files generated - on Windows have the following format: - - SF:c:\chrome_src\src\skia\sgl\skscan_antihair.cpp - DA:97,0 - DA:106,0 - DA:107,0 - DA:109,0 - ... - end_of_record - - This method changes the source-file (SF) lines to a format compatible with - genhtml on Linux by fixing paths. This method also removes references to - certain dynamically generated files to be excluded from the code ceverage. - - Args: - lcov_path: Path of the Win32 lcov file to be cleaned. - src_root: Location of the source and symbols dir. - Returns: - None - """ - strip_flag = False - lcov = open(lcov_path, 'r') - (tmpfile, tmpfile_name) = tempfile.mkstemp() - src_root = src_root.rstrip('/') # Remove trailing '/' - for line in lcov: - if line.startswith('SF'): - # We want to exclude certain auto-generated files otherwise genhtml will - # fail to convert lcov to HTML. - for exp in win32_srcs_exclude: - if line.rfind(exp) != -1: - strip_flag = True # Indicates that we want to remove this section - - # Now we normalize the paths - # e.g. Change SF:c:\foo\src\... to SF:/chrome_src/... - parse_buffer = line.split(':') - buffer = '%s:%s%s' % (parse_buffer[0], - src_root, - parse_buffer[2]) - buffer = buffer.replace('\\', '/') - line = buffer - - # Write to the temp file if the section to write is valid - if strip_flag == False: - tmpfile.write('%s' % (line)) - - # Reset the strip flag - if line.endswith('end_of_record'): - strip_flag = False - - # Close the files and replace the lcov file by the 'clean' tmpfile - tmpfile.close() - lcov.close() - shutil.move(tmpfile_name, lcov_path) - - -def main(): - if sys.platform[:5] != 'linux': # Run this only on Linux - print 'This script is supported only on Linux' - os.exit(1) - - # Command line parsing - parser = optparse.OptionParser() - parser.add_option('-p', - '--platform', - dest='platform', - default=None, - help='Platform that the locv file was generated on. Must be - one of {win32, linux2, macosx}') - parser.add_option('-s', - '--source', - dest='src_dir', - default=None, - help='Path to the source code and symbols') - parser.add_option('-d', - '--dash_root', - dest='dash_root', - default=None, - help='Root directory for the dashboard') - parser.add_option('-l', - '--lcov', - dest='lcov_path', - default=None, - help='Location of the LCOV file to process') - (options, args) = parser.parse_args() - - if options.platform == None: - parser.error('Platform not specified') - if options.lcov_path == None: - parser.error('lcov file path not specified') - if options.src_dir == None: - parser.error('Source directory not specified') - if options.dash_root == None: - parser.error('Dashboard root not specified') - if options.platform == 'win32': - CleanWin32Lcov(options.lcov_path, options.src_dir) - percent = GenerateHtml(options.lcov_path, options.dash_root) - if percent == None: - # TODO(niranjan): Add logging. - print 'Failed to generate code coverage' - os.exit(1) - else: - # TODO(niranjan): Do something with the code coverage numbers - pass - else: - print 'Unsupported platform' - os.exit(1) - - -if __name__ == '__main__': - main() - +#!/usr/bin/python2.4 +# +# 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. + + +"""Script to clean the lcov files and convert it to HTML + +TODO(niranjan): Add usage information here +""" + + +import optparse +import os +import shutil +import sys +import tempfile + + +# These are source files that were generated during compile time. We want to +# remove references to these files from the lcov file otherwise genhtml will +# throw an error. +win32_srcs_exclude = ['parse.y', + 'xpathgrammar.cpp', + 'cssgrammar.cpp'] + + +def CleanPathNames(dir): + """Clean the pathnames of the HTML generated by genhtml. + + This method is required only for code coverage on Win32. Due to a known issue + with reading from CIFS shares mounted on Linux, genhtml appends a ^M to every + file name it reads from the Windows share, causing corrupt filenames in + genhtml's output folder. + + Args: + dir: Output folder of the genhtml output. + + Returns: + None + """ + # Stip off the ^M characters that get appended to the file name + for file in os.walk(dir): + file_clean = file.replace('\r', '') + if file_clean != file: + os.rename(file, file_clean) + + +def GenerateHtml(lcov_path, dash_root): + """Runs genhtml to convert lcov data to human readable HTML. + + This script expects the LCOV file name to be in the format: + chrome_<platform>_<revision#>.lcov. + This method parses the file name and then sets up the correct folder + hierarchy for the coverage data and then runs genhtml to get the actual HTML + formatted coverage data. + + Args: + lcov_path: Path of the lcov data file. + dash_root: Root location of the dashboard. + + Returns: + Code coverage percentage on sucess. + None on failure. + """ + # Parse the LCOV file name. + filename = os.path.basename(lcov_path).split('.')[0] + buffer = filename.split('_') + dash_root = dash_root.rstrip('/') # Remove trailing '/' + + # Set up correct folder heirarchy in the dashboard root + # TODO(niranjan): Check the formatting using a regexp + if len(buffer) >= 3: # Check if filename has right formatting + platform = buffer[len(buffer) - 2] + revision = buffer[len(buffer) - 1] + if os.path.exists(os.path.join(dash_root, platform)) == False: + os.mkdir(os.path.join(dash_root, platform)) + output_dir = os.join.path(dash_root, platform, revision) + os.mkdir(output_dir) + else: + # TODO(niranjan): Add failure logging here. + return None # File not formatted correctly + + # Run genhtml + os.system('/usr/bin/genhtml -o %s %s' % (output_dir, lcov_path)) + # TODO(niranjan): Check the exit status of the genhtml command. + # TODO(niranjan): Parse the stdout and return coverage percentage. + CleanPathNames(output_dir) + return 'dummy' # TODO(niranjan): Return actual percentage. + + +def CleanWin32Lcov(lcov_path, src_root): + """Cleanup the lcov data generated on Windows. + + This method fixes up the paths inside the lcov file from the Win32 specific + paths to the actual paths of the mounted CIFS share. The lcov files generated + on Windows have the following format: + + SF:c:\chrome_src\src\skia\sgl\skscan_antihair.cpp + DA:97,0 + DA:106,0 + DA:107,0 + DA:109,0 + ... + end_of_record + + This method changes the source-file (SF) lines to a format compatible with + genhtml on Linux by fixing paths. This method also removes references to + certain dynamically generated files to be excluded from the code ceverage. + + Args: + lcov_path: Path of the Win32 lcov file to be cleaned. + src_root: Location of the source and symbols dir. + Returns: + None + """ + strip_flag = False + lcov = open(lcov_path, 'r') + (tmpfile, tmpfile_name) = tempfile.mkstemp() + src_root = src_root.rstrip('/') # Remove trailing '/' + for line in lcov: + if line.startswith('SF'): + # We want to exclude certain auto-generated files otherwise genhtml will + # fail to convert lcov to HTML. + for exp in win32_srcs_exclude: + if line.rfind(exp) != -1: + strip_flag = True # Indicates that we want to remove this section + + # Now we normalize the paths + # e.g. Change SF:c:\foo\src\... to SF:/chrome_src/... + parse_buffer = line.split(':') + buffer = '%s:%s%s' % (parse_buffer[0], + src_root, + parse_buffer[2]) + buffer = buffer.replace('\\', '/') + line = buffer + + # Write to the temp file if the section to write is valid + if strip_flag == False: + tmpfile.write('%s' % (line)) + + # Reset the strip flag + if line.endswith('end_of_record'): + strip_flag = False + + # Close the files and replace the lcov file by the 'clean' tmpfile + tmpfile.close() + lcov.close() + shutil.move(tmpfile_name, lcov_path) + + +def main(): + if sys.platform[:5] != 'linux': # Run this only on Linux + print 'This script is supported only on Linux' + os.exit(1) + + # Command line parsing + parser = optparse.OptionParser() + parser.add_option('-p', + '--platform', + dest='platform', + default=None, + help='Platform that the locv file was generated on. Must be + one of {win32, linux2, macosx}') + parser.add_option('-s', + '--source', + dest='src_dir', + default=None, + help='Path to the source code and symbols') + parser.add_option('-d', + '--dash_root', + dest='dash_root', + default=None, + help='Root directory for the dashboard') + parser.add_option('-l', + '--lcov', + dest='lcov_path', + default=None, + help='Location of the LCOV file to process') + (options, args) = parser.parse_args() + + if options.platform == None: + parser.error('Platform not specified') + if options.lcov_path == None: + parser.error('lcov file path not specified') + if options.src_dir == None: + parser.error('Source directory not specified') + if options.dash_root == None: + parser.error('Dashboard root not specified') + if options.platform == 'win32': + CleanWin32Lcov(options.lcov_path, options.src_dir) + percent = GenerateHtml(options.lcov_path, options.dash_root) + if percent == None: + # TODO(niranjan): Add logging. + print 'Failed to generate code coverage' + os.exit(1) + else: + # TODO(niranjan): Do something with the code coverage numbers + pass + else: + print 'Unsupported platform' + os.exit(1) + + +if __name__ == '__main__': + main() + diff --git a/tools/memory_watcher/call_stack.cc b/tools/memory_watcher/call_stack.cc index dcbe541e66f44..ff732782825b9 100644 --- a/tools/memory_watcher/call_stack.cc +++ b/tools/memory_watcher/call_stack.cc @@ -1,376 +1,376 @@ -// 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 "call_stack.h" -#include <shlwapi.h> -#include <tlhelp32.h> - -#include "memory_hook.h" -#include "base/string_util.h" - -// Typedefs for explicit dynamic linking with functions exported from -// dbghelp.dll. -typedef BOOL (__stdcall *t_StackWalk64)(DWORD, HANDLE, HANDLE, - LPSTACKFRAME64, PVOID, - PREAD_PROCESS_MEMORY_ROUTINE64, - PFUNCTION_TABLE_ACCESS_ROUTINE64, - PGET_MODULE_BASE_ROUTINE64, - PTRANSLATE_ADDRESS_ROUTINE64); -typedef PVOID (__stdcall *t_SymFunctionTableAccess64)(HANDLE, DWORD64); -typedef DWORD64 (__stdcall *t_SymGetModuleBase64)(HANDLE, DWORD64); -typedef BOOL (__stdcall *t_SymCleanup)(HANDLE); -typedef BOOL (__stdcall *t_SymGetSymFromAddr64)(HANDLE, DWORD64, - PDWORD64, PIMAGEHLP_SYMBOL64); -typedef BOOL (__stdcall *t_SymGetLineFromAddr64)(HANDLE, DWORD64, PDWORD, - PIMAGEHLP_LINE64); -typedef BOOL (__stdcall *t_SymInitialize)(HANDLE, PCTSTR, BOOL); -typedef DWORD (__stdcall *t_SymGetOptions)(void); -typedef DWORD (__stdcall *t_SymSetOptions)(DWORD); -typedef BOOL (__stdcall *t_SymGetSearchPath)(HANDLE, PTSTR, DWORD); -typedef DWORD64 (__stdcall *t_SymLoadModule64)(HANDLE, HANDLE, PCSTR, - PCSTR, DWORD64, DWORD); -typedef BOOL (__stdcall *t_SymGetModuleInfo64)(HANDLE, DWORD64, - PIMAGEHLP_MODULE64); - -// According to http://msdn2.microsoft.com/en-us/library/ms680650(VS.85).aspx -// "All DbgHelp functions, such as this one, are single threaded. Therefore, -// calls from more than one thread to this function will likely result in -// unexpected behavior or memory corruption. To avoid this, you must -// synchromize all concurrent calls from one thread to this function." -// -// dbghelp_lock_ is used to serialize access across all calls to the DbgHelp -// library. This may be overly conservative (serializing them all together), -// but does guarantee correctness. -static Lock dbghelp_lock_; - -static t_StackWalk64 pStackWalk64 = NULL; -static t_SymCleanup pSymCleanup = NULL; -static t_SymGetSymFromAddr64 pSymGetSymFromAddr64 = NULL; -static t_SymFunctionTableAccess64 pSymFunctionTableAccess64 = NULL; -static t_SymGetModuleBase64 pSymGetModuleBase64 = NULL; -static t_SymGetLineFromAddr64 pSymGetLineFromAddr64 = NULL; -static t_SymInitialize pSymInitialize = NULL; -static t_SymGetOptions pSymGetOptions = NULL; -static t_SymSetOptions pSymSetOptions = NULL; -static t_SymGetModuleInfo64 pSymGetModuleInfo64 = NULL; -static t_SymGetSearchPath pSymGetSearchPath = NULL; -static t_SymLoadModule64 pSymLoadModule64 = NULL; - -#define LOADPROC(module, name) do { \ - p##name = reinterpret_cast<t_##name>(GetProcAddress(module, #name)); \ - if (p##name == NULL) return false; \ -} while (0) - -// Dynamically load the DbgHelp library and supporting routines that we -// will use. -static bool LoadDbgHelp() { - static bool loaded = false; - if (!loaded) { - AutoLock Lock(dbghelp_lock_); - - // Re-check if we've loaded successfully now that we have the lock. - if (loaded) - return true; - - // Load dbghelp.dll, and obtain pointers to the exported functions that we - // will be using. - HMODULE dbghelp_module = LoadLibrary(L"dbghelp.dll"); - if (dbghelp_module) { - LOADPROC(dbghelp_module, StackWalk64); - LOADPROC(dbghelp_module, SymFunctionTableAccess64); - LOADPROC(dbghelp_module, SymGetModuleBase64); - LOADPROC(dbghelp_module, SymCleanup); - LOADPROC(dbghelp_module, SymGetSymFromAddr64); - LOADPROC(dbghelp_module, SymGetLineFromAddr64); - LOADPROC(dbghelp_module, SymInitialize); - LOADPROC(dbghelp_module, SymGetOptions); - LOADPROC(dbghelp_module, SymSetOptions); - LOADPROC(dbghelp_module, SymGetModuleInfo64); - LOADPROC(dbghelp_module, SymGetSearchPath); - LOADPROC(dbghelp_module, SymLoadModule64); - loaded = true; - } else { - return false; - } - } - return loaded; -} - -// Load the symbols for generating stack traces. -static bool LoadSymbols(HANDLE process_handle) { - static bool symbols_loaded = false; - if (symbols_loaded) return true; - - BOOL ok; - - // Initialize the symbol engine. - ok = pSymInitialize(process_handle, /* hProcess */ - NULL, /* UserSearchPath */ - FALSE); /* fInvadeProcess */ - if (!ok) return false; - - DWORD options = pSymGetOptions(); - options |= SYMOPT_LOAD_LINES; - options |= SYMOPT_FAIL_CRITICAL_ERRORS; - options |= SYMOPT_UNDNAME; - options = pSymSetOptions(options); - - const DWORD kMaxSearchPath = 1024; - TCHAR buf[kMaxSearchPath] = {0}; - ok = pSymGetSearchPath(process_handle, buf, kMaxSearchPath); - if (!ok) - return false; - - HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, - GetCurrentProcessId()); - if (snapshot == INVALID_HANDLE_VALUE) - return false; - - MODULEENTRY32W module; - module.dwSize = sizeof(module); // Set the size of the structure. - BOOL cont = Module32FirstW(snapshot, &module); - while (cont) { - DWORD64 base; - // NOTE the SymLoadModule64 function has the peculiarity of accepting a - // both unicode and ASCII strings even though the parameter is PSTR. - base = pSymLoadModule64(process_handle, - 0, - reinterpret_cast<PSTR>(module.szExePath), - reinterpret_cast<PSTR>(module.szModule), - reinterpret_cast<DWORD64>(module.modBaseAddr), - module.modBaseSize); - if (base == 0) { - int err = GetLastError(); - if (err != ERROR_MOD_NOT_FOUND && err != ERROR_INVALID_HANDLE) - return false; - } - cont = Module32NextW(snapshot, &module); - } - CloseHandle(snapshot); - - symbols_loaded = true; - return true; -} - - -CallStack::SymbolCache* CallStack::symbol_cache_; - -bool CallStack::Initialize() { - // We need to delay load the symbol cache until after - // the MemoryHook heap is alive. - symbol_cache_ = new SymbolCache(); - return LoadDbgHelp(); -} - -CallStack::CallStack() { - static LONG callstack_id = 0; - frame_count_ = 0; - hash_ = 0; - id_ = InterlockedIncrement(&callstack_id); - - LoadDbgHelp(); - CHECK(GetStackTrace()); -} - -bool CallStack::IsEqual(const CallStack &target) { - if (frame_count_ != target.frame_count_) - return false; // They can't be equal if the sizes are different. - - // Walk the frames array until we - // either find a mismatch, or until we reach the end of the call stacks. - for (int index = 0; index < frame_count_; index++) { - if (frames_[index] != target.frames_[index]) - return false; // Found a mismatch. They are not equal. - } - - // Reached the end of the call stacks. They are equal. - return true; -} - -void CallStack::AddFrame(DWORD_PTR pc) { - DCHECK(frame_count_ < kMaxTraceFrames); - frames_[frame_count_++] = pc; - - // Create a unique id for this CallStack. - pc = pc + (frame_count_ * 13); // Alter the PC based on position in stack. - hash_ = ~hash_ + (pc << 15); - hash_ = hash_ ^ (pc >> 12); - hash_ = hash_ + (pc << 2); - hash_ = hash_ ^ (pc >> 4); - hash_ = hash_ * 2057; - hash_ = hash_ ^ (pc >> 16); -} - -bool CallStack::GetStackTrace() { - // Initialize the context record. - CONTEXT context; - memset(&context, 0, sizeof(context)); - context.ContextFlags = CONTEXT_FULL; - __asm call x - __asm x: pop eax - __asm mov context.Eip, eax - __asm mov context.Ebp, ebp - __asm mov context.Esp, esp - - STACKFRAME64 frame; - memset(&frame, 0, sizeof(frame)); - -#ifdef _M_IX86 - DWORD image_type = IMAGE_FILE_MACHINE_I386; - frame.AddrPC.Offset = context.Eip; - frame.AddrPC.Mode = AddrModeFlat; - frame.AddrFrame.Offset = context.Ebp; - frame.AddrFrame.Mode = AddrModeFlat; - frame.AddrStack.Offset = context.Esp; - frame.AddrStack.Mode = AddrModeFlat; -#elif - NOT IMPLEMENTED! -#endif - - HANDLE current_process = GetCurrentProcess(); - HANDLE current_thread = GetCurrentThread(); - - // Walk the stack. - unsigned int count = 0; - { - AutoLock lock(dbghelp_lock_); - - while (count < kMaxTraceFrames) { - count++; - if (!pStackWalk64(image_type, - current_process, - current_thread, - &frame, - &context, - 0, - pSymFunctionTableAccess64, - pSymGetModuleBase64, - NULL)) - break; // Couldn't trace back through any more frames. - - if (frame.AddrFrame.Offset == 0) - continue; // End of stack. - - // Push this frame's program counter onto the provided CallStack. - AddFrame((DWORD_PTR)frame.AddrPC.Offset); - } - } - return true; -} - -void CallStack::ToString(std::string* output) { - static const int kStackWalkMaxNameLen = MAX_SYM_NAME; - HANDLE current_process = GetCurrentProcess(); - - if (!LoadSymbols(current_process)) { - *output = "Error"; - return; - } - - AutoLock lock(dbghelp_lock_); - - // Iterate through each frame in the call stack. - for (int32 index = 0; index < frame_count_; index++) { - std::string line; - - DWORD_PTR intruction_pointer = frame(index); - - SymbolCache::iterator it; - it = symbol_cache_->find( intruction_pointer ); - if (it != symbol_cache_->end()) { - line = it->second; - } else { - // Try to locate a symbol for this frame. - DWORD64 symbol_displacement = 0; - ULONG64 buffer[(sizeof(IMAGEHLP_SYMBOL64) + - sizeof(TCHAR)*kStackWalkMaxNameLen + - sizeof(ULONG64) - 1) / sizeof(ULONG64)]; - IMAGEHLP_SYMBOL64* symbol = reinterpret_cast<IMAGEHLP_SYMBOL64*>(buffer); - memset(buffer, 0, sizeof(buffer)); - symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); - symbol->MaxNameLength = kStackWalkMaxNameLen; - BOOL ok = pSymGetSymFromAddr64(current_process, // hProcess - intruction_pointer, // Address - &symbol_displacement, // Displacement - symbol); // Symbol - if (ok) { - // Try to locate more source information for the symbol. - IMAGEHLP_LINE64 Line; - memset(&Line, 0, sizeof(Line)); - Line.SizeOfStruct = sizeof(Line); - DWORD line_displacement; - ok = pSymGetLineFromAddr64(current_process, - intruction_pointer, - &line_displacement, - &Line); - if (ok) { - // Skip junk symbols from our internal stuff. - if (strstr(symbol->Name, "CallStack::") || - strstr(symbol->Name, "MemoryWatcher::") || - strstr(symbol->Name, "Perftools_") || - strstr(symbol->Name, "MemoryHook::") ) { - // Just record a blank string. - (*symbol_cache_)[intruction_pointer] = std::string(""); - continue; - } - - line += " "; - line += static_cast<char*>(Line.FileName); - line += " ("; - line += IntToString(Line.LineNumber); - line += "): "; - line += symbol->Name; - line += "\n"; - } else { - line += " unknown (0):"; - line += symbol->Name; - line += "\n"; - } - } else { - // OK - couldn't get any info. Try for the module. - IMAGEHLP_MODULE64 module_info; - module_info.SizeOfStruct = sizeof(module_info); - if (pSymGetModuleInfo64(current_process, intruction_pointer, - &module_info)) { - line += " ("; - line += static_cast<char*>(module_info.ModuleName); - line += ")\n"; - } else { - line += " ???\n"; - } - } - } - - (*symbol_cache_)[intruction_pointer] = line; - *output += line; - } - *output += "==================\n"; -} - - -Lock AllocationStack::freelist_lock_; -AllocationStack* AllocationStack::freelist_ = NULL; - -void* AllocationStack::operator new(size_t size) { - DCHECK(size == sizeof(AllocationStack)); - { - AutoLock lock(freelist_lock_); - if (freelist_ != NULL) { - AllocationStack* stack = freelist_; - freelist_ = freelist_->next_; - stack->next_ = NULL; - return stack; - } - } - return MemoryHook::Alloc(size); -} - -void AllocationStack::operator delete(void* ptr) { - AllocationStack *stack = reinterpret_cast<AllocationStack*>(ptr); - AutoLock lock(freelist_lock_); - DCHECK(stack->next_ == NULL); - stack->next_ = freelist_; - freelist_ = stack; -} - +// 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 "call_stack.h" +#include <shlwapi.h> +#include <tlhelp32.h> + +#include "memory_hook.h" +#include "base/string_util.h" + +// Typedefs for explicit dynamic linking with functions exported from +// dbghelp.dll. +typedef BOOL (__stdcall *t_StackWalk64)(DWORD, HANDLE, HANDLE, + LPSTACKFRAME64, PVOID, + PREAD_PROCESS_MEMORY_ROUTINE64, + PFUNCTION_TABLE_ACCESS_ROUTINE64, + PGET_MODULE_BASE_ROUTINE64, + PTRANSLATE_ADDRESS_ROUTINE64); +typedef PVOID (__stdcall *t_SymFunctionTableAccess64)(HANDLE, DWORD64); +typedef DWORD64 (__stdcall *t_SymGetModuleBase64)(HANDLE, DWORD64); +typedef BOOL (__stdcall *t_SymCleanup)(HANDLE); +typedef BOOL (__stdcall *t_SymGetSymFromAddr64)(HANDLE, DWORD64, + PDWORD64, PIMAGEHLP_SYMBOL64); +typedef BOOL (__stdcall *t_SymGetLineFromAddr64)(HANDLE, DWORD64, PDWORD, + PIMAGEHLP_LINE64); +typedef BOOL (__stdcall *t_SymInitialize)(HANDLE, PCTSTR, BOOL); +typedef DWORD (__stdcall *t_SymGetOptions)(void); +typedef DWORD (__stdcall *t_SymSetOptions)(DWORD); +typedef BOOL (__stdcall *t_SymGetSearchPath)(HANDLE, PTSTR, DWORD); +typedef DWORD64 (__stdcall *t_SymLoadModule64)(HANDLE, HANDLE, PCSTR, + PCSTR, DWORD64, DWORD); +typedef BOOL (__stdcall *t_SymGetModuleInfo64)(HANDLE, DWORD64, + PIMAGEHLP_MODULE64); + +// According to http://msdn2.microsoft.com/en-us/library/ms680650(VS.85).aspx +// "All DbgHelp functions, such as this one, are single threaded. Therefore, +// calls from more than one thread to this function will likely result in +// unexpected behavior or memory corruption. To avoid this, you must +// synchromize all concurrent calls from one thread to this function." +// +// dbghelp_lock_ is used to serialize access across all calls to the DbgHelp +// library. This may be overly conservative (serializing them all together), +// but does guarantee correctness. +static Lock dbghelp_lock_; + +static t_StackWalk64 pStackWalk64 = NULL; +static t_SymCleanup pSymCleanup = NULL; +static t_SymGetSymFromAddr64 pSymGetSymFromAddr64 = NULL; +static t_SymFunctionTableAccess64 pSymFunctionTableAccess64 = NULL; +static t_SymGetModuleBase64 pSymGetModuleBase64 = NULL; +static t_SymGetLineFromAddr64 pSymGetLineFromAddr64 = NULL; +static t_SymInitialize pSymInitialize = NULL; +static t_SymGetOptions pSymGetOptions = NULL; +static t_SymSetOptions pSymSetOptions = NULL; +static t_SymGetModuleInfo64 pSymGetModuleInfo64 = NULL; +static t_SymGetSearchPath pSymGetSearchPath = NULL; +static t_SymLoadModule64 pSymLoadModule64 = NULL; + +#define LOADPROC(module, name) do { \ + p##name = reinterpret_cast<t_##name>(GetProcAddress(module, #name)); \ + if (p##name == NULL) return false; \ +} while (0) + +// Dynamically load the DbgHelp library and supporting routines that we +// will use. +static bool LoadDbgHelp() { + static bool loaded = false; + if (!loaded) { + AutoLock Lock(dbghelp_lock_); + + // Re-check if we've loaded successfully now that we have the lock. + if (loaded) + return true; + + // Load dbghelp.dll, and obtain pointers to the exported functions that we + // will be using. + HMODULE dbghelp_module = LoadLibrary(L"dbghelp.dll"); + if (dbghelp_module) { + LOADPROC(dbghelp_module, StackWalk64); + LOADPROC(dbghelp_module, SymFunctionTableAccess64); + LOADPROC(dbghelp_module, SymGetModuleBase64); + LOADPROC(dbghelp_module, SymCleanup); + LOADPROC(dbghelp_module, SymGetSymFromAddr64); + LOADPROC(dbghelp_module, SymGetLineFromAddr64); + LOADPROC(dbghelp_module, SymInitialize); + LOADPROC(dbghelp_module, SymGetOptions); + LOADPROC(dbghelp_module, SymSetOptions); + LOADPROC(dbghelp_module, SymGetModuleInfo64); + LOADPROC(dbghelp_module, SymGetSearchPath); + LOADPROC(dbghelp_module, SymLoadModule64); + loaded = true; + } else { + return false; + } + } + return loaded; +} + +// Load the symbols for generating stack traces. +static bool LoadSymbols(HANDLE process_handle) { + static bool symbols_loaded = false; + if (symbols_loaded) return true; + + BOOL ok; + + // Initialize the symbol engine. + ok = pSymInitialize(process_handle, /* hProcess */ + NULL, /* UserSearchPath */ + FALSE); /* fInvadeProcess */ + if (!ok) return false; + + DWORD options = pSymGetOptions(); + options |= SYMOPT_LOAD_LINES; + options |= SYMOPT_FAIL_CRITICAL_ERRORS; + options |= SYMOPT_UNDNAME; + options = pSymSetOptions(options); + + const DWORD kMaxSearchPath = 1024; + TCHAR buf[kMaxSearchPath] = {0}; + ok = pSymGetSearchPath(process_handle, buf, kMaxSearchPath); + if (!ok) + return false; + + HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, + GetCurrentProcessId()); + if (snapshot == INVALID_HANDLE_VALUE) + return false; + + MODULEENTRY32W module; + module.dwSize = sizeof(module); // Set the size of the structure. + BOOL cont = Module32FirstW(snapshot, &module); + while (cont) { + DWORD64 base; + // NOTE the SymLoadModule64 function has the peculiarity of accepting a + // both unicode and ASCII strings even though the parameter is PSTR. + base = pSymLoadModule64(process_handle, + 0, + reinterpret_cast<PSTR>(module.szExePath), + reinterpret_cast<PSTR>(module.szModule), + reinterpret_cast<DWORD64>(module.modBaseAddr), + module.modBaseSize); + if (base == 0) { + int err = GetLastError(); + if (err != ERROR_MOD_NOT_FOUND && err != ERROR_INVALID_HANDLE) + return false; + } + cont = Module32NextW(snapshot, &module); + } + CloseHandle(snapshot); + + symbols_loaded = true; + return true; +} + + +CallStack::SymbolCache* CallStack::symbol_cache_; + +bool CallStack::Initialize() { + // We need to delay load the symbol cache until after + // the MemoryHook heap is alive. + symbol_cache_ = new SymbolCache(); + return LoadDbgHelp(); +} + +CallStack::CallStack() { + static LONG callstack_id = 0; + frame_count_ = 0; + hash_ = 0; + id_ = InterlockedIncrement(&callstack_id); + + LoadDbgHelp(); + CHECK(GetStackTrace()); +} + +bool CallStack::IsEqual(const CallStack &target) { + if (frame_count_ != target.frame_count_) + return false; // They can't be equal if the sizes are different. + + // Walk the frames array until we + // either find a mismatch, or until we reach the end of the call stacks. + for (int index = 0; index < frame_count_; index++) { + if (frames_[index] != target.frames_[index]) + return false; // Found a mismatch. They are not equal. + } + + // Reached the end of the call stacks. They are equal. + return true; +} + +void CallStack::AddFrame(DWORD_PTR pc) { + DCHECK(frame_count_ < kMaxTraceFrames); + frames_[frame_count_++] = pc; + + // Create a unique id for this CallStack. + pc = pc + (frame_count_ * 13); // Alter the PC based on position in stack. + hash_ = ~hash_ + (pc << 15); + hash_ = hash_ ^ (pc >> 12); + hash_ = hash_ + (pc << 2); + hash_ = hash_ ^ (pc >> 4); + hash_ = hash_ * 2057; + hash_ = hash_ ^ (pc >> 16); +} + +bool CallStack::GetStackTrace() { + // Initialize the context record. + CONTEXT context; + memset(&context, 0, sizeof(context)); + context.ContextFlags = CONTEXT_FULL; + __asm call x + __asm x: pop eax + __asm mov context.Eip, eax + __asm mov context.Ebp, ebp + __asm mov context.Esp, esp + + STACKFRAME64 frame; + memset(&frame, 0, sizeof(frame)); + +#ifdef _M_IX86 + DWORD image_type = IMAGE_FILE_MACHINE_I386; + frame.AddrPC.Offset = context.Eip; + frame.AddrPC.Mode = AddrModeFlat; + frame.AddrFrame.Offset = context.Ebp; + frame.AddrFrame.Mode = AddrModeFlat; + frame.AddrStack.Offset = context.Esp; + frame.AddrStack.Mode = AddrModeFlat; +#elif + NOT IMPLEMENTED! +#endif + + HANDLE current_process = GetCurrentProcess(); + HANDLE current_thread = GetCurrentThread(); + + // Walk the stack. + unsigned int count = 0; + { + AutoLock lock(dbghelp_lock_); + + while (count < kMaxTraceFrames) { + count++; + if (!pStackWalk64(image_type, + current_process, + current_thread, + &frame, + &context, + 0, + pSymFunctionTableAccess64, + pSymGetModuleBase64, + NULL)) + break; // Couldn't trace back through any more frames. + + if (frame.AddrFrame.Offset == 0) + continue; // End of stack. + + // Push this frame's program counter onto the provided CallStack. + AddFrame((DWORD_PTR)frame.AddrPC.Offset); + } + } + return true; +} + +void CallStack::ToString(std::string* output) { + static const int kStackWalkMaxNameLen = MAX_SYM_NAME; + HANDLE current_process = GetCurrentProcess(); + + if (!LoadSymbols(current_process)) { + *output = "Error"; + return; + } + + AutoLock lock(dbghelp_lock_); + + // Iterate through each frame in the call stack. + for (int32 index = 0; index < frame_count_; index++) { + std::string line; + + DWORD_PTR intruction_pointer = frame(index); + + SymbolCache::iterator it; + it = symbol_cache_->find( intruction_pointer ); + if (it != symbol_cache_->end()) { + line = it->second; + } else { + // Try to locate a symbol for this frame. + DWORD64 symbol_displacement = 0; + ULONG64 buffer[(sizeof(IMAGEHLP_SYMBOL64) + + sizeof(TCHAR)*kStackWalkMaxNameLen + + sizeof(ULONG64) - 1) / sizeof(ULONG64)]; + IMAGEHLP_SYMBOL64* symbol = reinterpret_cast<IMAGEHLP_SYMBOL64*>(buffer); + memset(buffer, 0, sizeof(buffer)); + symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); + symbol->MaxNameLength = kStackWalkMaxNameLen; + BOOL ok = pSymGetSymFromAddr64(current_process, // hProcess + intruction_pointer, // Address + &symbol_displacement, // Displacement + symbol); // Symbol + if (ok) { + // Try to locate more source information for the symbol. + IMAGEHLP_LINE64 Line; + memset(&Line, 0, sizeof(Line)); + Line.SizeOfStruct = sizeof(Line); + DWORD line_displacement; + ok = pSymGetLineFromAddr64(current_process, + intruction_pointer, + &line_displacement, + &Line); + if (ok) { + // Skip junk symbols from our internal stuff. + if (strstr(symbol->Name, "CallStack::") || + strstr(symbol->Name, "MemoryWatcher::") || + strstr(symbol->Name, "Perftools_") || + strstr(symbol->Name, "MemoryHook::") ) { + // Just record a blank string. + (*symbol_cache_)[intruction_pointer] = std::string(""); + continue; + } + + line += " "; + line += static_cast<char*>(Line.FileName); + line += " ("; + line += IntToString(Line.LineNumber); + line += "): "; + line += symbol->Name; + line += "\n"; + } else { + line += " unknown (0):"; + line += symbol->Name; + line += "\n"; + } + } else { + // OK - couldn't get any info. Try for the module. + IMAGEHLP_MODULE64 module_info; + module_info.SizeOfStruct = sizeof(module_info); + if (pSymGetModuleInfo64(current_process, intruction_pointer, + &module_info)) { + line += " ("; + line += static_cast<char*>(module_info.ModuleName); + line += ")\n"; + } else { + line += " ???\n"; + } + } + } + + (*symbol_cache_)[intruction_pointer] = line; + *output += line; + } + *output += "==================\n"; +} + + +Lock AllocationStack::freelist_lock_; +AllocationStack* AllocationStack::freelist_ = NULL; + +void* AllocationStack::operator new(size_t size) { + DCHECK(size == sizeof(AllocationStack)); + { + AutoLock lock(freelist_lock_); + if (freelist_ != NULL) { + AllocationStack* stack = freelist_; + freelist_ = freelist_->next_; + stack->next_ = NULL; + return stack; + } + } + return MemoryHook::Alloc(size); +} + +void AllocationStack::operator delete(void* ptr) { + AllocationStack *stack = reinterpret_cast<AllocationStack*>(ptr); + AutoLock lock(freelist_lock_); + DCHECK(stack->next_ == NULL); + stack->next_ = freelist_; + freelist_ = stack; +} + diff --git a/webkit/SConscript.javascriptcore_pcre b/webkit/SConscript.javascriptcore_pcre index 42db440b3c2a6..d13267cd6e17f 100644 --- a/webkit/SConscript.javascriptcore_pcre +++ b/webkit/SConscript.javascriptcore_pcre @@ -1,46 +1,46 @@ -# 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. - -Import('env') - -env = env.Clone( - PCRE_DIR = '$WEBKIT_DIR/port/JavaScriptCore/pcre', -) - -env.Prepend( - CPPPATH = [ - '$WEBKIT_DIR/port/JavaScriptCore', - '$WEBKIT_DIR/port/JavaScriptCore/pcre', - '$WEBKIT_DIR/build/JSConfig/WebCore/v8', - ]) - -if env['PLATFORM'] == 'win32': - env.Prepend( - CCFLAGS = [ - '/TP', - '/wd4127', - '/wd4355', - '/wd4510', - '/wd4512', - '/wd4610', - '/wd4706', - '/wd4800', - ], - ) - -dir = env.Dir('$PCRE_DIR') - -dir.addRepository(env.Dir('#/../webkit/pending')) -dir.addRepository(env.Dir('#/../third_party/WebKit/JavaScriptCore/pcre')) - -input_files = [ - '$PCRE_DIR/pcre_compile.cpp', - '$PCRE_DIR/pcre_xclass.cpp', - '$PCRE_DIR/pcre_ucp_searchfuncs.cpp', - '$PCRE_DIR/pcre_tables.cpp', - '$PCRE_DIR/pcre_exec.cpp', -] - -env.ChromeStaticLibrary('JavaScriptCore_pcre', input_files) - +# 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. + +Import('env') + +env = env.Clone( + PCRE_DIR = '$WEBKIT_DIR/port/JavaScriptCore/pcre', +) + +env.Prepend( + CPPPATH = [ + '$WEBKIT_DIR/port/JavaScriptCore', + '$WEBKIT_DIR/port/JavaScriptCore/pcre', + '$WEBKIT_DIR/build/JSConfig/WebCore/v8', + ]) + +if env['PLATFORM'] == 'win32': + env.Prepend( + CCFLAGS = [ + '/TP', + '/wd4127', + '/wd4355', + '/wd4510', + '/wd4512', + '/wd4610', + '/wd4706', + '/wd4800', + ], + ) + +dir = env.Dir('$PCRE_DIR') + +dir.addRepository(env.Dir('#/../webkit/pending')) +dir.addRepository(env.Dir('#/../third_party/WebKit/JavaScriptCore/pcre')) + +input_files = [ + '$PCRE_DIR/pcre_compile.cpp', + '$PCRE_DIR/pcre_xclass.cpp', + '$PCRE_DIR/pcre_ucp_searchfuncs.cpp', + '$PCRE_DIR/pcre_tables.cpp', + '$PCRE_DIR/pcre_exec.cpp', +] + +env.ChromeStaticLibrary('JavaScriptCore_pcre', input_files) + diff --git a/webkit/SConscript.port b/webkit/SConscript.port index ebf1034005142..16f5072b083f3 100644 --- a/webkit/SConscript.port +++ b/webkit/SConscript.port @@ -1,127 +1,127 @@ -# 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. - -Import('env') - -env = env.Clone() - -if env['PLATFORM'] == 'win32': - env.Prepend( - CCFLAGS = [ - '/TP', - - '/wd4244', - '/wd4291', - '/wd4345', - '/wd4521', - '/wd4800', - ],) - -input_files = [ - '$PORT_DIR/css/RGBColor.cpp', - '$PORT_DIR/history/CachedPage.cpp', - '$PORT_DIR/platform/TemporaryLinkStubs.cpp', -] - -if env['PLATFORM'] == 'win32': - # TODO(erg): Temporarily disabling these until the big webkit merge is - # complete; we're just out of date here. - input_files += [ - '$PORT_DIR/platform/graphics/AffineTransformSkia.cpp', - '$PORT_DIR/platform/graphics/ImageSourceSkia.cpp', - '$PORT_DIR/platform/graphics/NativeImageSkia.cpp', - '$PORT_DIR/platform/graphics/PathSkia.cpp', - '$PORT_DIR/platform/graphics/SkiaUtils.cpp', - '$PORT_DIR/platform/graphics/svg/SkiaSupport.cpp', - '$PORT_DIR/platform/graphics/svg/RenderPathSkia.cpp', - '$PORT_DIR/platform/graphics/svg/SVGPaintServerGradientSkia.cpp', - '$PORT_DIR/platform/graphics/svg/SVGPaintServerPatternSkia.cpp', - '$PORT_DIR/platform/graphics/svg/SVGPaintServerSkia.cpp', - '$PORT_DIR/platform/graphics/svg/SVGPaintServerSolidSkia.cpp', - '$PORT_DIR/platform/graphics/svg/SVGResourceClipperSkia.cpp', - '$PORT_DIR/platform/graphics/svg/SVGResourceFilterSkia.cpp', - '$PORT_DIR/platform/image-decoders/bmp/BMPImageDecoder.cpp', - '$PORT_DIR/platform/image-decoders/bmp/BMPImageReader.cpp', - '$PORT_DIR/platform/image-decoders/gif/GIFImageDecoder.cpp', - '$PORT_DIR/platform/image-decoders/gif/GIFImageReader.cpp', - '$PORT_DIR/platform/image-decoders/ico/ICOImageDecoder.cpp', - '$PORT_DIR/platform/image-decoders/jpeg/JPEGImageDecoder.cpp', - '$PORT_DIR/platform/image-decoders/png/PNGImageDecoder.cpp', - '$PORT_DIR/platform/image-decoders/xbm/XBMImageDecoder.cpp', - ] - -if env['PLATFORM'] == 'win32': - # These files aren't win32-specific, they're just files that haven't yet been - # made portable. - input_files = [ - '$PORT_DIR/bridge/FrameWin.cpp', - '$PORT_DIR/bridge/HistoryWin.cpp', - '$PORT_DIR/bridge/PageWin.cpp', - '$PORT_DIR/bridge/PluginsWin.cpp', - '$PORT_DIR/history/BackForwardList.cpp', - '$PORT_DIR/loader/IconDatabaseNone.cpp', - '$PORT_DIR/loader/IconLoader.cpp', - '$PORT_DIR/page/AXObjectCacheWin.cpp', - '$PORT_DIR/page/DragControllerWin.cpp', - '$PORT_DIR/page/EventHandlerWin.cpp', - '$PORT_DIR/platform/BString.cpp', - '$PORT_DIR/platform/ClipboardUtilitiesWin.cpp', - '$PORT_DIR/platform/ClipboardWin.cpp', - '$PORT_DIR/platform/ContextMenuItemWin.cpp', - '$PORT_DIR/platform/ContextMenuWin.cpp', - '$PORT_DIR/platform/CursorWin.cpp', - '$PORT_DIR/platform/DragDataWin.cpp', - '$PORT_DIR/platform/DragImageWin.cpp', - '$PORT_DIR/platform/EditorWin.cpp', - '$PORT_DIR/platform/FileChooserWin.cpp', - '$PORT_DIR/platform/FramelessScrollView.cpp', - '$PORT_DIR/platform/GKURL.cpp', - '$PORT_DIR/platform/KeyEventWin.cpp', - '$PORT_DIR/platform/Language.cpp', - '$PORT_DIR/platform/LogWin.cpp', - '$PORT_DIR/platform/MimeTypeRegistryWin.cpp', - '$PORT_DIR/platform/PasteboardWin.cpp', - '$PORT_DIR/platform/PlatformMouseEventWin.cpp', - '$PORT_DIR/platform/PlatformScrollBarWin.cpp', - '$PORT_DIR/platform/PopupMenuWin.cpp', - '$PORT_DIR/platform/SSLKeyGeneratorWin.cpp', - '$PORT_DIR/platform/ScreenWin.cpp', - '$PORT_DIR/platform/ScrollViewWin.cpp', - '$PORT_DIR/platform/SearchPopupMenuWin.cpp', - '$PORT_DIR/platform/SharedTimerWin.cpp', - '$PORT_DIR/platform/SoundWin.cpp', - '$PORT_DIR/platform/SystemTimeWin.cpp', - '$PORT_DIR/platform/TextBoundariesWin.cpp', - '$PORT_DIR/platform/TextBreakIteratorInternalICUWin.cpp', - '$PORT_DIR/platform/UniscribeStateTextRun.cpp', - '$PORT_DIR/platform/WCDataObject.cpp', - '$PORT_DIR/platform/WheelEventWin.cpp', - '$PORT_DIR/platform/WidgetWin.cpp', - '$PORT_DIR/platform/graphics/FontCacheWin.cpp', - '$PORT_DIR/platform/graphics/FontCustomPlatformData.cpp', - '$PORT_DIR/platform/graphics/FontPlatformDataWin.cpp', - '$PORT_DIR/platform/graphics/FontWin.cpp', - '$PORT_DIR/platform/graphics/GlyphPageTreeNodeWin.cpp', - '$PORT_DIR/platform/graphics/GraphicsContextSkia.cpp', - '$PORT_DIR/platform/graphics/IconWin.cpp', - '$PORT_DIR/platform/graphics/ImageBufferSkia.cpp', - '$PORT_DIR/platform/graphics/ImageSkia.cpp', - '$PORT_DIR/platform/graphics/PlatformContextSkia.cpp', - '$PORT_DIR/platform/graphics/SimpleFontDataWin.cpp', - '$PORT_DIR/platform/graphics/SkGraphicsContext.cpp', - '$PORT_DIR/platform/graphics/SkPaintContext.cpp', - '$PORT_DIR/platform/graphics/svg/SVGResourceMaskerSkia.cpp', - '$PORT_DIR/platform/network/CookieJarWin.cpp', - '$PORT_DIR/rendering/RenderThemeWin.cpp', - ] - -if env['PLATFORM'] == 'win32': - # These are extremely win32 specific and will never be ported. - input_files = [ - '$PORT_DIR/platform/graphics/IntPointWin.cpp', - '$PORT_DIR/platform/graphics/IntRectWin.cpp', - '$PORT_DIR/platform/graphics/IntSizeWin.cpp', - ] - -env.ChromeStaticLibrary("port", input_files) +# 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. + +Import('env') + +env = env.Clone() + +if env['PLATFORM'] == 'win32': + env.Prepend( + CCFLAGS = [ + '/TP', + + '/wd4244', + '/wd4291', + '/wd4345', + '/wd4521', + '/wd4800', + ],) + +input_files = [ + '$PORT_DIR/css/RGBColor.cpp', + '$PORT_DIR/history/CachedPage.cpp', + '$PORT_DIR/platform/TemporaryLinkStubs.cpp', +] + +if env['PLATFORM'] == 'win32': + # TODO(erg): Temporarily disabling these until the big webkit merge is + # complete; we're just out of date here. + input_files += [ + '$PORT_DIR/platform/graphics/AffineTransformSkia.cpp', + '$PORT_DIR/platform/graphics/ImageSourceSkia.cpp', + '$PORT_DIR/platform/graphics/NativeImageSkia.cpp', + '$PORT_DIR/platform/graphics/PathSkia.cpp', + '$PORT_DIR/platform/graphics/SkiaUtils.cpp', + '$PORT_DIR/platform/graphics/svg/SkiaSupport.cpp', + '$PORT_DIR/platform/graphics/svg/RenderPathSkia.cpp', + '$PORT_DIR/platform/graphics/svg/SVGPaintServerGradientSkia.cpp', + '$PORT_DIR/platform/graphics/svg/SVGPaintServerPatternSkia.cpp', + '$PORT_DIR/platform/graphics/svg/SVGPaintServerSkia.cpp', + '$PORT_DIR/platform/graphics/svg/SVGPaintServerSolidSkia.cpp', + '$PORT_DIR/platform/graphics/svg/SVGResourceClipperSkia.cpp', + '$PORT_DIR/platform/graphics/svg/SVGResourceFilterSkia.cpp', + '$PORT_DIR/platform/image-decoders/bmp/BMPImageDecoder.cpp', + '$PORT_DIR/platform/image-decoders/bmp/BMPImageReader.cpp', + '$PORT_DIR/platform/image-decoders/gif/GIFImageDecoder.cpp', + '$PORT_DIR/platform/image-decoders/gif/GIFImageReader.cpp', + '$PORT_DIR/platform/image-decoders/ico/ICOImageDecoder.cpp', + '$PORT_DIR/platform/image-decoders/jpeg/JPEGImageDecoder.cpp', + '$PORT_DIR/platform/image-decoders/png/PNGImageDecoder.cpp', + '$PORT_DIR/platform/image-decoders/xbm/XBMImageDecoder.cpp', + ] + +if env['PLATFORM'] == 'win32': + # These files aren't win32-specific, they're just files that haven't yet been + # made portable. + input_files = [ + '$PORT_DIR/bridge/FrameWin.cpp', + '$PORT_DIR/bridge/HistoryWin.cpp', + '$PORT_DIR/bridge/PageWin.cpp', + '$PORT_DIR/bridge/PluginsWin.cpp', + '$PORT_DIR/history/BackForwardList.cpp', + '$PORT_DIR/loader/IconDatabaseNone.cpp', + '$PORT_DIR/loader/IconLoader.cpp', + '$PORT_DIR/page/AXObjectCacheWin.cpp', + '$PORT_DIR/page/DragControllerWin.cpp', + '$PORT_DIR/page/EventHandlerWin.cpp', + '$PORT_DIR/platform/BString.cpp', + '$PORT_DIR/platform/ClipboardUtilitiesWin.cpp', + '$PORT_DIR/platform/ClipboardWin.cpp', + '$PORT_DIR/platform/ContextMenuItemWin.cpp', + '$PORT_DIR/platform/ContextMenuWin.cpp', + '$PORT_DIR/platform/CursorWin.cpp', + '$PORT_DIR/platform/DragDataWin.cpp', + '$PORT_DIR/platform/DragImageWin.cpp', + '$PORT_DIR/platform/EditorWin.cpp', + '$PORT_DIR/platform/FileChooserWin.cpp', + '$PORT_DIR/platform/FramelessScrollView.cpp', + '$PORT_DIR/platform/GKURL.cpp', + '$PORT_DIR/platform/KeyEventWin.cpp', + '$PORT_DIR/platform/Language.cpp', + '$PORT_DIR/platform/LogWin.cpp', + '$PORT_DIR/platform/MimeTypeRegistryWin.cpp', + '$PORT_DIR/platform/PasteboardWin.cpp', + '$PORT_DIR/platform/PlatformMouseEventWin.cpp', + '$PORT_DIR/platform/PlatformScrollBarWin.cpp', + '$PORT_DIR/platform/PopupMenuWin.cpp', + '$PORT_DIR/platform/SSLKeyGeneratorWin.cpp', + '$PORT_DIR/platform/ScreenWin.cpp', + '$PORT_DIR/platform/ScrollViewWin.cpp', + '$PORT_DIR/platform/SearchPopupMenuWin.cpp', + '$PORT_DIR/platform/SharedTimerWin.cpp', + '$PORT_DIR/platform/SoundWin.cpp', + '$PORT_DIR/platform/SystemTimeWin.cpp', + '$PORT_DIR/platform/TextBoundariesWin.cpp', + '$PORT_DIR/platform/TextBreakIteratorInternalICUWin.cpp', + '$PORT_DIR/platform/UniscribeStateTextRun.cpp', + '$PORT_DIR/platform/WCDataObject.cpp', + '$PORT_DIR/platform/WheelEventWin.cpp', + '$PORT_DIR/platform/WidgetWin.cpp', + '$PORT_DIR/platform/graphics/FontCacheWin.cpp', + '$PORT_DIR/platform/graphics/FontCustomPlatformData.cpp', + '$PORT_DIR/platform/graphics/FontPlatformDataWin.cpp', + '$PORT_DIR/platform/graphics/FontWin.cpp', + '$PORT_DIR/platform/graphics/GlyphPageTreeNodeWin.cpp', + '$PORT_DIR/platform/graphics/GraphicsContextSkia.cpp', + '$PORT_DIR/platform/graphics/IconWin.cpp', + '$PORT_DIR/platform/graphics/ImageBufferSkia.cpp', + '$PORT_DIR/platform/graphics/ImageSkia.cpp', + '$PORT_DIR/platform/graphics/PlatformContextSkia.cpp', + '$PORT_DIR/platform/graphics/SimpleFontDataWin.cpp', + '$PORT_DIR/platform/graphics/SkGraphicsContext.cpp', + '$PORT_DIR/platform/graphics/SkPaintContext.cpp', + '$PORT_DIR/platform/graphics/svg/SVGResourceMaskerSkia.cpp', + '$PORT_DIR/platform/network/CookieJarWin.cpp', + '$PORT_DIR/rendering/RenderThemeWin.cpp', + ] + +if env['PLATFORM'] == 'win32': + # These are extremely win32 specific and will never be ported. + input_files = [ + '$PORT_DIR/platform/graphics/IntPointWin.cpp', + '$PORT_DIR/platform/graphics/IntRectWin.cpp', + '$PORT_DIR/platform/graphics/IntSizeWin.cpp', + ] + +env.ChromeStaticLibrary("port", input_files) diff --git a/webkit/pending/Peerable.h b/webkit/pending/Peerable.h index 75175ad54295d..7eda415a38e34 100644 --- a/webkit/pending/Peerable.h +++ b/webkit/pending/Peerable.h @@ -1,25 +1,25 @@ -// Copyright (c) 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 Peerable_h -#define Peerable_h - -#include <wtf/Noncopyable.h> - -#if USE(V8_BINDING) - -namespace WebCore { - -class Peerable : Noncopyable { -public: - virtual void setPeer(void* peer) = 0; - virtual void* peer() const = 0; -protected: - virtual ~Peerable() { } -}; - -}; - -#endif // USE(V8_BINDING) -#endif // Peerable_h +// Copyright (c) 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 Peerable_h +#define Peerable_h + +#include <wtf/Noncopyable.h> + +#if USE(V8_BINDING) + +namespace WebCore { + +class Peerable : Noncopyable { +public: + virtual void setPeer(void* peer) = 0; + virtual void* peer() const = 0; +protected: + virtual ~Peerable() { } +}; + +}; + +#endif // USE(V8_BINDING) +#endif // Peerable_h diff --git a/webkit/port/bindings/v8/v8_collection.h b/webkit/port/bindings/v8/v8_collection.h index 1bffc7e5e84ce..c468a0e9d5314 100644 --- a/webkit/port/bindings/v8/v8_collection.h +++ b/webkit/port/bindings/v8/v8_collection.h @@ -1,259 +1,259 @@ -// 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. -// Copied from base/basictypes.h with some modifications - -#ifndef V8_PROPERTY_H__ -#define V8_PROPERTY_H__ - -#include <v8.h> -#include "v8_proxy.h" - -namespace WebCore { - -// Returns named property of a collection. -template <class C> -static v8::Handle<v8::Value> GetNamedPropertyOfCollection( - v8::Local<v8::String> name, - v8::Local<v8::Object> object, - v8::Local<v8::Value> data) { - // TODO: assert object is a collection type - ASSERT(V8Proxy::MaybeDOMWrapper(object)); - V8ClassIndex::V8WrapperType t = V8Proxy::GetDOMWrapperType(object); - ASSERT(t != V8ClassIndex::NODE); - C* collection = V8Proxy::ToNativeObject<C>(t, object); - String prop_name = ToWebCoreString(name); - void* result = collection->namedItem(prop_name); - if (!result) return v8::Handle<v8::Value>(); - V8ClassIndex::V8WrapperType type = V8ClassIndex::ToWrapperType(data); - if (type == V8ClassIndex::NODE) - return V8Proxy::NodeToV8Object(static_cast<Node*>(result)); - else - return V8Proxy::ToV8Object(type, result); -} - -// A template of named property accessor of collections. -template <class C> -static v8::Handle<v8::Value> CollectionNamedPropertyGetter( - v8::Local<v8::String> name, const v8::AccessorInfo& info) { - return GetNamedPropertyOfCollection<C>(name, info.Holder(), info.Data()); -} - - -// A template of named property accessor of HTMLSelectElement and -// HTMLFormElement. -template <class C> -static v8::Handle<v8::Value> NodeCollectionNamedPropertyGetter( - v8::Local<v8::String> name, const v8::AccessorInfo& info) { - ASSERT(V8Proxy::MaybeDOMWrapper(info.Holder())); - ASSERT(V8Proxy::GetDOMWrapperType(info.Holder()) == V8ClassIndex::NODE); - C* collection = V8Proxy::DOMWrapperToNode<C>(info.Holder()); - String prop_name = ToWebCoreString(name); - void* result = collection->namedItem(prop_name); - if (!result) return v8::Handle<v8::Value>(); - V8ClassIndex::V8WrapperType type = V8ClassIndex::ToWrapperType(info.Data()); - if (type == V8ClassIndex::NODE) - return V8Proxy::NodeToV8Object(static_cast<Node*>(result)); - else - return V8Proxy::ToV8Object(type, result); -} - - -// A template returns whether a collection has a named property. -// This function does not cause JS heap allocation. -template <class C> -static bool HasNamedPropertyOfCollection(v8::Local<v8::String> name, - v8::Local<v8::Object> object, - v8::Local<v8::Value> data) { - // TODO: assert object is a collection type - ASSERT(V8Proxy::MaybeDOMWrapper(object)); - - V8ClassIndex::V8WrapperType t = V8Proxy::GetDOMWrapperType(object); - C* collection = V8Proxy::ToNativeObject<C>(t, object); - String prop_name = ToWebCoreString(name); - void* result = collection->namedItem(prop_name); - return result != NULL; -} - - -// Returns the property at the index of a collection. -template <class C> -static v8::Handle<v8::Value> GetIndexedPropertyOfCollection( - uint32_t index, v8::Local<v8::Object> object, v8::Local<v8::Value> data) { - // TODO, assert that object must be a collection type - ASSERT(V8Proxy::MaybeDOMWrapper(object)); - V8ClassIndex::V8WrapperType t = V8Proxy::GetDOMWrapperType(object); - ASSERT(t != V8ClassIndex::NODE); - C* collection = V8Proxy::ToNativeObject<C>(t, object); - void* result = collection->item(index); - if (!result) return v8::Handle<v8::Value>(); - V8ClassIndex::V8WrapperType type = V8ClassIndex::ToWrapperType(data); - if (type == V8ClassIndex::NODE) - return V8Proxy::NodeToV8Object(static_cast<Node*>(result)); - else - return V8Proxy::ToV8Object(type, result); -} - - -// A template of index interceptor of collections. -template <class C> -static v8::Handle<v8::Value> CollectionIndexedPropertyGetter( - uint32_t index, const v8::AccessorInfo& info) { - return GetIndexedPropertyOfCollection<C>(index, info.Holder(), info.Data()); -} - - -// A template of index interceptor of HTMLSelectElement and HTMLFormElement. -template <class C> -static v8::Handle<v8::Value> NodeCollectionIndexedPropertyGetter( - uint32_t index, const v8::AccessorInfo& info) { - ASSERT(V8Proxy::MaybeDOMWrapper(info.Holder())); - ASSERT(V8Proxy::GetDOMWrapperType(info.Holder()) == V8ClassIndex::NODE); - C* collection = V8Proxy::DOMWrapperToNode<C>(info.Holder()); - void* result = collection->item(index); - if (!result) return v8::Handle<v8::Value>(); - V8ClassIndex::V8WrapperType type = V8ClassIndex::ToWrapperType(info.Data()); - if (type == V8ClassIndex::NODE) - return V8Proxy::NodeToV8Object(static_cast<Node*>(result)); - else - return V8Proxy::ToV8Object(type, result); -} - - -// Get an array containing the names of indexed properties of -// HTMLSelectElement and HTMLFormElement. -template <class C> -static v8::Handle<v8::Array> NodeCollectionIndexedPropertyEnumerator( - const v8::AccessorInfo& info) { - ASSERT(V8Proxy::MaybeDOMWrapper(info.Holder())); - ASSERT(V8Proxy::GetDOMWrapperType(info.Holder()) == V8ClassIndex::NODE); - C* collection = V8Proxy::DOMWrapperToNode<C>(info.Holder()); - int length = collection->length(); - v8::Handle<v8::Array> properties = v8::Array::New(length); - for (int i = 0; i < length; i++) { - // TODO(ager): Do we need to check that the item function returns - // a non-null value for this index? - v8::Handle<v8::Integer> integer = v8::Integer::New(i); - properties->Set(integer, integer); - } - return properties; -} - -// Get an array containing the names of indexed properties in a collection. -template <class C> -static v8::Handle<v8::Array> CollectionIndexedPropertyEnumerator( - const v8::AccessorInfo& info) { - ASSERT(V8Proxy::MaybeDOMWrapper(info.Holder())); - V8ClassIndex::V8WrapperType t = V8Proxy::GetDOMWrapperType(info.Holder()); - C* collection = V8Proxy::ToNativeObject<C>(t, info.Holder()); - int length = collection->length(); - v8::Handle<v8::Array> properties = v8::Array::New(length); - for (int i = 0; i < length; i++) { - // TODO(ager): Do we need to check that the item function returns - // a non-null value for this index? - v8::Handle<v8::Integer> integer = v8::Integer::New(i); - properties->Set(integer, integer); - } - return properties; -} - - -// Returns whether a collection has a property at a given index. -// This function does not cause JS heap allocation. -template <class C> -static bool HasIndexedPropertyOfCollection(uint32_t index, - v8::Local<v8::Object> object, - v8::Local<v8::Value> data) { - // TODO, assert that object must be a collection type - ASSERT(V8Proxy::MaybeDOMWrapper(object)); - V8ClassIndex::V8WrapperType t = V8Proxy::GetDOMWrapperType(object); - C* collection = V8Proxy::ToNativeObject<C>(t, object); - void* result = collection->item(index); - return result != NULL; -} - - -// A template for indexed getters on collections of strings that should return -// null if the resulting string is a null string. -template <class C> -static v8::Handle<v8::Value> CollectionStringOrNullIndexedPropertyGetter( - uint32_t index, const v8::AccessorInfo& info) { - // TODO, assert that object must be a collection type - ASSERT(V8Proxy::MaybeDOMWrapper(info.Holder())); - V8ClassIndex::V8WrapperType t = V8Proxy::GetDOMWrapperType(info.Holder()); - C* collection = V8Proxy::ToNativeObject<C>(t, info.Holder()); - String result = collection->item(index); - return v8StringOrNull(result); -} - - -// Add indexed getter to the function template for a collection. -template <class T> -static void SetCollectionIndexedGetter(v8::Handle<v8::FunctionTemplate> desc, - V8ClassIndex::V8WrapperType type) { - desc->InstanceTemplate()->SetIndexedPropertyHandler( - CollectionIndexedPropertyGetter<T>, - 0, - 0, - 0, - CollectionIndexedPropertyEnumerator<T>, - v8::External::New(reinterpret_cast<void*>(type))); -} - - -// Add named getter to the function template for a collection. -template <class T> -static void SetCollectionNamedGetter(v8::Handle<v8::FunctionTemplate> desc, - V8ClassIndex::V8WrapperType type) { - desc->InstanceTemplate()->SetNamedPropertyHandler( - CollectionNamedPropertyGetter<T>, - 0, - 0, - 0, - 0, - v8::External::New(reinterpret_cast<void*>(type))); -} - - -// Add named and indexed getters to the function template for a collection. -template <class T> -static void SetCollectionIndexedAndNamedGetters( - v8::Handle<v8::FunctionTemplate> desc, V8ClassIndex::V8WrapperType type) { - // If we interceptor before object, accessing 'length' can trigger - // a webkit assertion error. - // (see fast/dom/HTMLDocument/document-special-properties.html - desc->InstanceTemplate()->SetNamedPropertyHandler( - CollectionNamedPropertyGetter<T>, - 0, - 0, - 0, - 0, - v8::External::New(reinterpret_cast<void*>(type))); - desc->InstanceTemplate()->SetIndexedPropertyHandler( - CollectionIndexedPropertyGetter<T>, - 0, - 0, - 0, - CollectionIndexedPropertyEnumerator<T>, - v8::External::New(reinterpret_cast<void*>(type))); -} - - -// Add indexed getter returning a string or null to a function template -// for a collection. -template <class T> -static void SetCollectionStringOrNullIndexedGetter( - v8::Handle<v8::FunctionTemplate> desc) { - desc->InstanceTemplate()->SetIndexedPropertyHandler( - CollectionStringOrNullIndexedPropertyGetter<T>, - 0, - 0, - 0, - CollectionIndexedPropertyEnumerator<T>); -} - - -} // namespace WebCore - -#endif // V8_PROPERTY_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. +// Copied from base/basictypes.h with some modifications + +#ifndef V8_PROPERTY_H__ +#define V8_PROPERTY_H__ + +#include <v8.h> +#include "v8_proxy.h" + +namespace WebCore { + +// Returns named property of a collection. +template <class C> +static v8::Handle<v8::Value> GetNamedPropertyOfCollection( + v8::Local<v8::String> name, + v8::Local<v8::Object> object, + v8::Local<v8::Value> data) { + // TODO: assert object is a collection type + ASSERT(V8Proxy::MaybeDOMWrapper(object)); + V8ClassIndex::V8WrapperType t = V8Proxy::GetDOMWrapperType(object); + ASSERT(t != V8ClassIndex::NODE); + C* collection = V8Proxy::ToNativeObject<C>(t, object); + String prop_name = ToWebCoreString(name); + void* result = collection->namedItem(prop_name); + if (!result) return v8::Handle<v8::Value>(); + V8ClassIndex::V8WrapperType type = V8ClassIndex::ToWrapperType(data); + if (type == V8ClassIndex::NODE) + return V8Proxy::NodeToV8Object(static_cast<Node*>(result)); + else + return V8Proxy::ToV8Object(type, result); +} + +// A template of named property accessor of collections. +template <class C> +static v8::Handle<v8::Value> CollectionNamedPropertyGetter( + v8::Local<v8::String> name, const v8::AccessorInfo& info) { + return GetNamedPropertyOfCollection<C>(name, info.Holder(), info.Data()); +} + + +// A template of named property accessor of HTMLSelectElement and +// HTMLFormElement. +template <class C> +static v8::Handle<v8::Value> NodeCollectionNamedPropertyGetter( + v8::Local<v8::String> name, const v8::AccessorInfo& info) { + ASSERT(V8Proxy::MaybeDOMWrapper(info.Holder())); + ASSERT(V8Proxy::GetDOMWrapperType(info.Holder()) == V8ClassIndex::NODE); + C* collection = V8Proxy::DOMWrapperToNode<C>(info.Holder()); + String prop_name = ToWebCoreString(name); + void* result = collection->namedItem(prop_name); + if (!result) return v8::Handle<v8::Value>(); + V8ClassIndex::V8WrapperType type = V8ClassIndex::ToWrapperType(info.Data()); + if (type == V8ClassIndex::NODE) + return V8Proxy::NodeToV8Object(static_cast<Node*>(result)); + else + return V8Proxy::ToV8Object(type, result); +} + + +// A template returns whether a collection has a named property. +// This function does not cause JS heap allocation. +template <class C> +static bool HasNamedPropertyOfCollection(v8::Local<v8::String> name, + v8::Local<v8::Object> object, + v8::Local<v8::Value> data) { + // TODO: assert object is a collection type + ASSERT(V8Proxy::MaybeDOMWrapper(object)); + + V8ClassIndex::V8WrapperType t = V8Proxy::GetDOMWrapperType(object); + C* collection = V8Proxy::ToNativeObject<C>(t, object); + String prop_name = ToWebCoreString(name); + void* result = collection->namedItem(prop_name); + return result != NULL; +} + + +// Returns the property at the index of a collection. +template <class C> +static v8::Handle<v8::Value> GetIndexedPropertyOfCollection( + uint32_t index, v8::Local<v8::Object> object, v8::Local<v8::Value> data) { + // TODO, assert that object must be a collection type + ASSERT(V8Proxy::MaybeDOMWrapper(object)); + V8ClassIndex::V8WrapperType t = V8Proxy::GetDOMWrapperType(object); + ASSERT(t != V8ClassIndex::NODE); + C* collection = V8Proxy::ToNativeObject<C>(t, object); + void* result = collection->item(index); + if (!result) return v8::Handle<v8::Value>(); + V8ClassIndex::V8WrapperType type = V8ClassIndex::ToWrapperType(data); + if (type == V8ClassIndex::NODE) + return V8Proxy::NodeToV8Object(static_cast<Node*>(result)); + else + return V8Proxy::ToV8Object(type, result); +} + + +// A template of index interceptor of collections. +template <class C> +static v8::Handle<v8::Value> CollectionIndexedPropertyGetter( + uint32_t index, const v8::AccessorInfo& info) { + return GetIndexedPropertyOfCollection<C>(index, info.Holder(), info.Data()); +} + + +// A template of index interceptor of HTMLSelectElement and HTMLFormElement. +template <class C> +static v8::Handle<v8::Value> NodeCollectionIndexedPropertyGetter( + uint32_t index, const v8::AccessorInfo& info) { + ASSERT(V8Proxy::MaybeDOMWrapper(info.Holder())); + ASSERT(V8Proxy::GetDOMWrapperType(info.Holder()) == V8ClassIndex::NODE); + C* collection = V8Proxy::DOMWrapperToNode<C>(info.Holder()); + void* result = collection->item(index); + if (!result) return v8::Handle<v8::Value>(); + V8ClassIndex::V8WrapperType type = V8ClassIndex::ToWrapperType(info.Data()); + if (type == V8ClassIndex::NODE) + return V8Proxy::NodeToV8Object(static_cast<Node*>(result)); + else + return V8Proxy::ToV8Object(type, result); +} + + +// Get an array containing the names of indexed properties of +// HTMLSelectElement and HTMLFormElement. +template <class C> +static v8::Handle<v8::Array> NodeCollectionIndexedPropertyEnumerator( + const v8::AccessorInfo& info) { + ASSERT(V8Proxy::MaybeDOMWrapper(info.Holder())); + ASSERT(V8Proxy::GetDOMWrapperType(info.Holder()) == V8ClassIndex::NODE); + C* collection = V8Proxy::DOMWrapperToNode<C>(info.Holder()); + int length = collection->length(); + v8::Handle<v8::Array> properties = v8::Array::New(length); + for (int i = 0; i < length; i++) { + // TODO(ager): Do we need to check that the item function returns + // a non-null value for this index? + v8::Handle<v8::Integer> integer = v8::Integer::New(i); + properties->Set(integer, integer); + } + return properties; +} + +// Get an array containing the names of indexed properties in a collection. +template <class C> +static v8::Handle<v8::Array> CollectionIndexedPropertyEnumerator( + const v8::AccessorInfo& info) { + ASSERT(V8Proxy::MaybeDOMWrapper(info.Holder())); + V8ClassIndex::V8WrapperType t = V8Proxy::GetDOMWrapperType(info.Holder()); + C* collection = V8Proxy::ToNativeObject<C>(t, info.Holder()); + int length = collection->length(); + v8::Handle<v8::Array> properties = v8::Array::New(length); + for (int i = 0; i < length; i++) { + // TODO(ager): Do we need to check that the item function returns + // a non-null value for this index? + v8::Handle<v8::Integer> integer = v8::Integer::New(i); + properties->Set(integer, integer); + } + return properties; +} + + +// Returns whether a collection has a property at a given index. +// This function does not cause JS heap allocation. +template <class C> +static bool HasIndexedPropertyOfCollection(uint32_t index, + v8::Local<v8::Object> object, + v8::Local<v8::Value> data) { + // TODO, assert that object must be a collection type + ASSERT(V8Proxy::MaybeDOMWrapper(object)); + V8ClassIndex::V8WrapperType t = V8Proxy::GetDOMWrapperType(object); + C* collection = V8Proxy::ToNativeObject<C>(t, object); + void* result = collection->item(index); + return result != NULL; +} + + +// A template for indexed getters on collections of strings that should return +// null if the resulting string is a null string. +template <class C> +static v8::Handle<v8::Value> CollectionStringOrNullIndexedPropertyGetter( + uint32_t index, const v8::AccessorInfo& info) { + // TODO, assert that object must be a collection type + ASSERT(V8Proxy::MaybeDOMWrapper(info.Holder())); + V8ClassIndex::V8WrapperType t = V8Proxy::GetDOMWrapperType(info.Holder()); + C* collection = V8Proxy::ToNativeObject<C>(t, info.Holder()); + String result = collection->item(index); + return v8StringOrNull(result); +} + + +// Add indexed getter to the function template for a collection. +template <class T> +static void SetCollectionIndexedGetter(v8::Handle<v8::FunctionTemplate> desc, + V8ClassIndex::V8WrapperType type) { + desc->InstanceTemplate()->SetIndexedPropertyHandler( + CollectionIndexedPropertyGetter<T>, + 0, + 0, + 0, + CollectionIndexedPropertyEnumerator<T>, + v8::External::New(reinterpret_cast<void*>(type))); +} + + +// Add named getter to the function template for a collection. +template <class T> +static void SetCollectionNamedGetter(v8::Handle<v8::FunctionTemplate> desc, + V8ClassIndex::V8WrapperType type) { + desc->InstanceTemplate()->SetNamedPropertyHandler( + CollectionNamedPropertyGetter<T>, + 0, + 0, + 0, + 0, + v8::External::New(reinterpret_cast<void*>(type))); +} + + +// Add named and indexed getters to the function template for a collection. +template <class T> +static void SetCollectionIndexedAndNamedGetters( + v8::Handle<v8::FunctionTemplate> desc, V8ClassIndex::V8WrapperType type) { + // If we interceptor before object, accessing 'length' can trigger + // a webkit assertion error. + // (see fast/dom/HTMLDocument/document-special-properties.html + desc->InstanceTemplate()->SetNamedPropertyHandler( + CollectionNamedPropertyGetter<T>, + 0, + 0, + 0, + 0, + v8::External::New(reinterpret_cast<void*>(type))); + desc->InstanceTemplate()->SetIndexedPropertyHandler( + CollectionIndexedPropertyGetter<T>, + 0, + 0, + 0, + CollectionIndexedPropertyEnumerator<T>, + v8::External::New(reinterpret_cast<void*>(type))); +} + + +// Add indexed getter returning a string or null to a function template +// for a collection. +template <class T> +static void SetCollectionStringOrNullIndexedGetter( + v8::Handle<v8::FunctionTemplate> desc) { + desc->InstanceTemplate()->SetIndexedPropertyHandler( + CollectionStringOrNullIndexedPropertyGetter<T>, + 0, + 0, + 0, + CollectionIndexedPropertyEnumerator<T>); +} + + +} // namespace WebCore + +#endif // V8_PROPERTY_H__ + -- GitLab