0

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
This commit is contained in:
maruel@google.com
2008-09-25 22:08:44 +00:00
parent c9ec45429c
commit de8d2667d6
22 changed files with 2991 additions and 2991 deletions

@ -1,52 +1,52 @@
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/cpu.h"
#include <intrin.h>
#include <string>
namespace base {
CPU::CPU()
: type_(0),
family_(0),
model_(0),
stepping_(0),
ext_model_(0),
ext_family_(0),
cpu_vendor_("unknown") {
Initialize();
}
void CPU::Initialize() {
int cpu_info[4] = {-1};
char cpu_string[0x20];
// __cpuid with an InfoType argument of 0 returns the number of
// valid Ids in CPUInfo[0] and the CPU identification string in
// the other three array elements. The CPU identification string is
// not in linear order. The code below arranges the information
// in a human readable form.
//
// More info can be found here:
// http://msdn.microsoft.com/en-us/library/hskdteyh.aspx
__cpuid(cpu_info, 0);
int num_ids = cpu_info[0];
memset(cpu_string, 0, sizeof(cpu_string));
*(reinterpret_cast<int*>(cpu_string)) = cpu_info[1];
*(reinterpret_cast<int*>(cpu_string+4)) = cpu_info[3];
*(reinterpret_cast<int*>(cpu_string+8)) = cpu_info[2];
// Interpret CPU feature information.
__cpuid(cpu_info, 1);
stepping_ = cpu_info[0] & 0xf;
model_ = (cpu_info[0] >> 4) & 0xf;
family_ = (cpu_info[0] >> 8) & 0xf;
type_ = (cpu_info[0] >> 12) & 0x3;
ext_model_ = (cpu_info[0] >> 16) & 0xf;
ext_family_ = (cpu_info[0] >> 20) & 0xff;
cpu_vendor_ = cpu_string;
}
} // namespace base
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/cpu.h"
#include <intrin.h>
#include <string>
namespace base {
CPU::CPU()
: type_(0),
family_(0),
model_(0),
stepping_(0),
ext_model_(0),
ext_family_(0),
cpu_vendor_("unknown") {
Initialize();
}
void CPU::Initialize() {
int cpu_info[4] = {-1};
char cpu_string[0x20];
// __cpuid with an InfoType argument of 0 returns the number of
// valid Ids in CPUInfo[0] and the CPU identification string in
// the other three array elements. The CPU identification string is
// not in linear order. The code below arranges the information
// in a human readable form.
//
// More info can be found here:
// http://msdn.microsoft.com/en-us/library/hskdteyh.aspx
__cpuid(cpu_info, 0);
int num_ids = cpu_info[0];
memset(cpu_string, 0, sizeof(cpu_string));
*(reinterpret_cast<int*>(cpu_string)) = cpu_info[1];
*(reinterpret_cast<int*>(cpu_string+4)) = cpu_info[3];
*(reinterpret_cast<int*>(cpu_string+8)) = cpu_info[2];
// Interpret CPU feature information.
__cpuid(cpu_info, 1);
stepping_ = cpu_info[0] & 0xf;
model_ = (cpu_info[0] >> 4) & 0xf;
family_ = (cpu_info[0] >> 8) & 0xf;
type_ = (cpu_info[0] >> 12) & 0x3;
ext_model_ = (cpu_info[0] >> 16) & 0xf;
ext_family_ = (cpu_info[0] >> 20) & 0xff;
cpu_vendor_ = cpu_string;
}
} // namespace base

@ -1,42 +1,42 @@
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_CPU_H_
#define BASE_CPU_H_
#include <string>
namespace base {
// Query information about the processor.
class CPU {
public:
// Constructor
CPU();
// Accessors for CPU information.
const std::string& vendor_name() const { return cpu_vendor_; }
int stepping() const { return stepping_; }
int model() const { return model_; }
int family() const { return family_; }
int type() const { return type_; }
int extended_model() const { return ext_model_; }
int extended_family() const { return ext_family_; }
private:
// Query the processor for CPUID information.
void Initialize();
int type_; // process type
int family_; // family of the processor
int model_; // model of processor
int stepping_; // processor revision number
int ext_model_;
int ext_family_;
std::string cpu_vendor_;
};
} // namespace base
#endif // BASE_CPU_H_
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_CPU_H_
#define BASE_CPU_H_
#include <string>
namespace base {
// Query information about the processor.
class CPU {
public:
// Constructor
CPU();
// Accessors for CPU information.
const std::string& vendor_name() const { return cpu_vendor_; }
int stepping() const { return stepping_; }
int model() const { return model_; }
int family() const { return family_; }
int type() const { return type_; }
int extended_model() const { return ext_model_; }
int extended_family() const { return ext_family_; }
private:
// Query the processor for CPUID information.
void Initialize();
int type_; // process type
int family_; // family of the processor
int model_; // model of processor
int stepping_; // processor revision number
int ext_model_;
int ext_family_;
std::string cpu_vendor_;
};
} // namespace base
#endif // BASE_CPU_H_

@ -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_

@ -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

@ -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__

@ -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

@ -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__

@ -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

@ -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__

@ -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)

@ -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)

@ -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)

@ -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)

@ -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)

@ -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)

@ -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())

@ -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()

@ -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;
}

@ -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)

@ -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)

@ -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

@ -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__