SkDevice.cpp revision ab1c13864df34aecfd4840ea7d1e4f8730b44f4e
1
2/*
3 * Copyright 2011 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9#include "SkDevice.h"
10#include "SkMetaData.h"
11
12#if SK_PMCOLOR_BYTE_ORDER(B,G,R,A)
13    const SkCanvas::Config8888 SkBaseDevice::kPMColorAlias = SkCanvas::kBGRA_Premul_Config8888;
14#elif SK_PMCOLOR_BYTE_ORDER(R,G,B,A)
15    const SkCanvas::Config8888 SkBaseDevice::kPMColorAlias = SkCanvas::kRGBA_Premul_Config8888;
16#else
17    const SkCanvas::Config8888 SkBaseDevice::kPMColorAlias = (SkCanvas::Config8888) -1;
18#endif
19
20///////////////////////////////////////////////////////////////////////////////
21SkBaseDevice::SkBaseDevice()
22    : fLeakyProperties(SkDeviceProperties::MakeDefault())
23#ifdef SK_DEBUG
24    , fAttachedToCanvas(false)
25#endif
26{
27    fOrigin.setZero();
28    fMetaData = NULL;
29}
30
31SkBaseDevice::SkBaseDevice(const SkDeviceProperties& deviceProperties)
32    : fLeakyProperties(deviceProperties)
33#ifdef SK_DEBUG
34    , fAttachedToCanvas(false)
35#endif
36{
37    fOrigin.setZero();
38    fMetaData = NULL;
39}
40
41SkBaseDevice::~SkBaseDevice() {
42    delete fMetaData;
43}
44
45SkBaseDevice* SkBaseDevice::createCompatibleDevice(SkBitmap::Config config,
46                                                   int width, int height,
47                                                   bool isOpaque) {
48    return this->onCreateCompatibleDevice(config, width, height,
49                                          isOpaque, kGeneral_Usage);
50}
51
52SkBaseDevice* SkBaseDevice::createCompatibleDeviceForSaveLayer(SkBitmap::Config config,
53                                                               int width, int height,
54                                                               bool isOpaque) {
55    return this->onCreateCompatibleDevice(config, width, height,
56                                          isOpaque, kSaveLayer_Usage);
57}
58
59SkMetaData& SkBaseDevice::getMetaData() {
60    // metadata users are rare, so we lazily allocate it. If that changes we
61    // can decide to just make it a field in the device (rather than a ptr)
62    if (NULL == fMetaData) {
63        fMetaData = new SkMetaData;
64    }
65    return *fMetaData;
66}
67
68const SkBitmap& SkBaseDevice::accessBitmap(bool changePixels) {
69    const SkBitmap& bitmap = this->onAccessBitmap();
70    if (changePixels) {
71        bitmap.notifyPixelsChanged();
72    }
73    return bitmap;
74}
75
76bool SkBaseDevice::readPixels(SkBitmap* bitmap, int x, int y,
77                              SkCanvas::Config8888 config8888) {
78    if (SkBitmap::kARGB_8888_Config != bitmap->config() ||
79        NULL != bitmap->getTexture()) {
80        return false;
81    }
82
83    const SkBitmap& src = this->accessBitmap(false);
84
85    SkIRect srcRect = SkIRect::MakeXYWH(x, y, bitmap->width(),
86                                              bitmap->height());
87    SkIRect devbounds = SkIRect::MakeWH(src.width(), src.height());
88    if (!srcRect.intersect(devbounds)) {
89        return false;
90    }
91
92    SkBitmap tmp;
93    SkBitmap* bmp;
94    if (bitmap->isNull()) {
95        tmp.setConfig(SkBitmap::kARGB_8888_Config, bitmap->width(),
96                                                   bitmap->height());
97        if (!tmp.allocPixels()) {
98            return false;
99        }
100        bmp = &tmp;
101    } else {
102        bmp = bitmap;
103    }
104
105    SkIRect subrect = srcRect;
106    subrect.offset(-x, -y);
107    SkBitmap bmpSubset;
108    bmp->extractSubset(&bmpSubset, subrect);
109
110    bool result = this->onReadPixels(bmpSubset,
111                                     srcRect.fLeft,
112                                     srcRect.fTop,
113                                     config8888);
114    if (result && bmp == &tmp) {
115        tmp.swap(*bitmap);
116    }
117    return result;
118}
119