This source file includes following definitions.
- CreateHBitmap
- GetBitmapDC
- ReleaseBitmapDC
- IsBitmapDCCreated
- SetMatrixClip
- LoadConfig
- DeleteHBitmapCallback
- InstallHBitmapPixels
- Create
- Create
- CreateAndClear
- transform_
- BeginPlatformPaint
- EndPlatformPaint
- setMatrixClip
- DrawToNativeContext
- onAccessBitmap
- onCreateDevice
- CreatePlatformCanvas
- Allocate
#include <windows.h>
#include <psapi.h>
#include "base/debug/gdi_debug_util_win.h"
#include "base/logging.h"
#include "skia/ext/bitmap_platform_device_win.h"
#include "skia/ext/platform_canvas.h"
#include "third_party/skia/include/core/SkMatrix.h"
#include "third_party/skia/include/core/SkRefCnt.h"
#include "third_party/skia/include/core/SkRegion.h"
#include "third_party/skia/include/core/SkUtils.h"
namespace {
HBITMAP CreateHBitmap(int width, int height, bool is_opaque,
HANDLE shared_section, void** data) {
if ((width == 0) || (height == 0)) {
width = 1;
height = 1;
}
BITMAPINFOHEADER hdr = {0};
hdr.biSize = sizeof(BITMAPINFOHEADER);
hdr.biWidth = width;
hdr.biHeight = -height;
hdr.biPlanes = 1;
hdr.biBitCount = 32;
hdr.biCompression = BI_RGB;
hdr.biSizeImage = 0;
hdr.biXPelsPerMeter = 1;
hdr.biYPelsPerMeter = 1;
hdr.biClrUsed = 0;
hdr.biClrImportant = 0;
HBITMAP hbitmap = CreateDIBSection(NULL, reinterpret_cast<BITMAPINFO*>(&hdr),
0, data, shared_section, 0);
#if !defined(_WIN64)
if (!hbitmap)
base::debug::GDIBitmapAllocFailure(&hdr, shared_section);
#endif
return hbitmap;
}
}
namespace skia {
HDC BitmapPlatformDevice::GetBitmapDC() {
if (!hdc_) {
hdc_ = CreateCompatibleDC(NULL);
InitializeDC(hdc_);
old_hbitmap_ = static_cast<HBITMAP>(SelectObject(hdc_, hbitmap_));
}
LoadConfig();
return hdc_;
}
void BitmapPlatformDevice::ReleaseBitmapDC() {
SkASSERT(hdc_);
SelectObject(hdc_, old_hbitmap_);
DeleteDC(hdc_);
hdc_ = NULL;
old_hbitmap_ = NULL;
}
bool BitmapPlatformDevice::IsBitmapDCCreated()
const {
return hdc_ != NULL;
}
void BitmapPlatformDevice::SetMatrixClip(
const SkMatrix& transform,
const SkRegion& region) {
transform_ = transform;
clip_region_ = region;
config_dirty_ = true;
}
void BitmapPlatformDevice::LoadConfig() {
if (!config_dirty_ || !hdc_)
return;
config_dirty_ = false;
LoadTransformToDC(hdc_, transform_);
LoadClippingRegionToDC(hdc_, clip_region_, transform_);
}
static void DeleteHBitmapCallback(void* addr, void* context) {
DeleteObject(static_cast<HBITMAP>(context));
}
static bool InstallHBitmapPixels(SkBitmap* bitmap, int width, int height,
bool is_opaque, void* data, HBITMAP hbitmap) {
const SkAlphaType at = is_opaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
const SkImageInfo info = SkImageInfo::MakeN32(width, height, at);
const size_t rowBytes = info.minRowBytes();
return bitmap->installPixels(info, data, rowBytes, DeleteHBitmapCallback,
hbitmap);
}
BitmapPlatformDevice* BitmapPlatformDevice::Create(
int width,
int height,
bool is_opaque,
HANDLE shared_section) {
void* data;
HBITMAP hbitmap = CreateHBitmap(width, height, is_opaque, shared_section,
&data);
if (!hbitmap)
return NULL;
SkBitmap bitmap;
if (!InstallHBitmapPixels(&bitmap, width, height, is_opaque, data, hbitmap))
return NULL;
#ifndef NDEBUG
if (!shared_section && is_opaque)
bitmap.eraseARGB(255, 0, 255, 128);
#endif
return new BitmapPlatformDevice(hbitmap, bitmap);
}
BitmapPlatformDevice* BitmapPlatformDevice::Create(int width, int height,
bool is_opaque) {
return Create(width, height, is_opaque, NULL);
}
BitmapPlatformDevice* BitmapPlatformDevice::CreateAndClear(int width,
int height,
bool is_opaque) {
BitmapPlatformDevice* device = BitmapPlatformDevice::Create(width, height,
is_opaque);
if (device && !is_opaque)
device->clear(0);
return device;
}
BitmapPlatformDevice::BitmapPlatformDevice(
HBITMAP hbitmap,
const SkBitmap& bitmap)
: SkBitmapDevice(bitmap),
hbitmap_(hbitmap),
old_hbitmap_(NULL),
hdc_(NULL),
config_dirty_(true),
transform_(SkMatrix::I()) {
SkDEBUGCODE(begin_paint_count_ = 0);
SetPlatformDevice(this, this);
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);
}
}
BitmapPlatformDevice::~BitmapPlatformDevice() {
SkASSERT(begin_paint_count_ == 0);
if (hdc_)
ReleaseBitmapDC();
}
HDC BitmapPlatformDevice::BeginPlatformPaint() {
SkDEBUGCODE(begin_paint_count_++);
return GetBitmapDC();
}
void BitmapPlatformDevice::EndPlatformPaint() {
SkASSERT(begin_paint_count_--);
PlatformDevice::EndPlatformPaint();
}
void BitmapPlatformDevice::setMatrixClip(const SkMatrix& transform,
const SkRegion& region,
const SkClipStack&) {
SetMatrixClip(transform, region);
}
void BitmapPlatformDevice::DrawToNativeContext(HDC dc, int x, int y,
const RECT* src_rect) {
bool created_dc = !IsBitmapDCCreated();
HDC source_dc = BeginPlatformPaint();
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;
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 {
SkASSERT(copy_width != 0 && copy_height != 0);
BLENDFUNCTION blend_function = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA};
GdiAlphaBlend(dc,
x,
y,
copy_width,
copy_height,
source_dc,
src_rect->left,
src_rect->top,
copy_width,
copy_height,
blend_function);
}
LoadTransformToDC(source_dc, transform_);
EndPlatformPaint();
if (created_dc)
ReleaseBitmapDC();
}
const SkBitmap& BitmapPlatformDevice::onAccessBitmap() {
if (IsBitmapDCCreated())
GdiFlush();
return SkBitmapDevice::onAccessBitmap();
}
SkBaseDevice* BitmapPlatformDevice::onCreateDevice(const SkImageInfo& info,
Usage ) {
SkASSERT(info.colorType() == kPMColor_SkColorType);
return BitmapPlatformDevice::CreateAndClear(info.width(), info.height(),
info.isOpaque());
}
SkCanvas* CreatePlatformCanvas(int width,
int height,
bool is_opaque,
HANDLE shared_section,
OnFailureType failureType) {
skia::RefPtr<SkBaseDevice> dev = skia::AdoptRef(
BitmapPlatformDevice::Create(width, height, is_opaque, shared_section));
return CreateCanvas(dev, failureType);
}
PlatformBitmap::~PlatformBitmap() {
if (surface_) {
if (platform_extra_)
SelectObject(surface_, reinterpret_cast<HGDIOBJ>(platform_extra_));
DeleteDC(surface_);
}
}
bool PlatformBitmap::Allocate(int width, int height, bool is_opaque) {
void* data;
HBITMAP hbitmap = CreateHBitmap(width, height, is_opaque, 0, &data);
if (!hbitmap)
return false;
surface_ = CreateCompatibleDC(NULL);
InitializeDC(surface_);
HGDIOBJ stock_bitmap = SelectObject(surface_, hbitmap);
platform_extra_ = reinterpret_cast<intptr_t>(stock_bitmap);
if (!InstallHBitmapPixels(&bitmap_, width, height, is_opaque, data, hbitmap))
return false;
bitmap_.lockPixels();
return true;
}
}