63a76336482f9f32ddba4c092e476a81a6b64b92
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / core / SkDevice.cpp
1 /*
2  * Copyright 2011 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7
8 #include "SkDevice.h"
9 #include "SkDeviceProperties.h"
10 #include "SkDraw.h"
11 #include "SkMetaData.h"
12 #include "SkPatchUtils.h"
13 #include "SkShader.h"
14 #include "SkTextBlob.h"
15
16 SkBaseDevice::SkBaseDevice()
17     : fLeakyProperties(SkNEW_ARGS(SkDeviceProperties, (SkDeviceProperties::kLegacyLCD_InitType)))
18 #ifdef SK_DEBUG
19     , fAttachedToCanvas(false)
20 #endif
21 {
22     fOrigin.setZero();
23     fMetaData = NULL;
24 }
25
26 SkBaseDevice::~SkBaseDevice() {
27     SkDELETE(fLeakyProperties);
28     SkDELETE(fMetaData);
29 }
30
31 SkBaseDevice* SkBaseDevice::createCompatibleDevice(const SkImageInfo& info) {
32     return this->onCreateDevice(info, kGeneral_Usage);
33 }
34
35 SkBaseDevice* SkBaseDevice::createCompatibleDeviceForSaveLayer(const SkImageInfo& info) {
36     return this->onCreateDevice(info, kSaveLayer_Usage);
37 }
38
39 SkMetaData& SkBaseDevice::getMetaData() {
40     // metadata users are rare, so we lazily allocate it. If that changes we
41     // can decide to just make it a field in the device (rather than a ptr)
42     if (NULL == fMetaData) {
43         fMetaData = new SkMetaData;
44     }
45     return *fMetaData;
46 }
47
48 SkImageInfo SkBaseDevice::imageInfo() const {
49     return SkImageInfo::MakeUnknown();
50 }
51
52 const SkBitmap& SkBaseDevice::accessBitmap(bool changePixels) {
53     const SkBitmap& bitmap = this->onAccessBitmap();
54     if (changePixels) {
55         bitmap.notifyPixelsChanged();
56     }
57     return bitmap;
58 }
59
60 void SkBaseDevice::setPixelGeometry(SkPixelGeometry geo) {
61     fLeakyProperties->fPixelGeometry = geo;
62 }
63
64 SkSurface* SkBaseDevice::newSurface(const SkImageInfo&, const SkSurfaceProps&) { return NULL; }
65
66 const void* SkBaseDevice::peekPixels(SkImageInfo*, size_t*) { return NULL; }
67
68 void SkBaseDevice::drawDRRect(const SkDraw& draw, const SkRRect& outer,
69                               const SkRRect& inner, const SkPaint& paint) {
70     SkPath path;
71     path.addRRect(outer);
72     path.addRRect(inner);
73     path.setFillType(SkPath::kEvenOdd_FillType);
74
75     const SkMatrix* preMatrix = NULL;
76     const bool pathIsMutable = true;
77     this->drawPath(draw, path, paint, preMatrix, pathIsMutable);
78 }
79
80 void SkBaseDevice::drawPatch(const SkDraw& draw, const SkPoint cubics[12], const SkColor colors[4],
81                              const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) {
82     SkPatchUtils::VertexData data;
83     
84     SkISize lod = SkPatchUtils::GetLevelOfDetail(cubics, draw.fMatrix);
85
86     // It automatically adjusts lodX and lodY in case it exceeds the number of indices.
87     // If it fails to generate the vertices, then we do not draw. 
88     if (SkPatchUtils::getVertexData(&data, cubics, colors, texCoords, lod.width(), lod.height())) {
89         this->drawVertices(draw, SkCanvas::kTriangles_VertexMode, data.fVertexCount, data.fPoints,
90                            data.fTexCoords, data.fColors, xmode, data.fIndices, data.fIndexCount,
91                            paint);
92     }
93 }
94
95 void SkBaseDevice::drawTextBlob(const SkDraw& draw, const SkTextBlob* blob, SkScalar x, SkScalar y,
96                                 const SkPaint &paint) {
97
98     SkPaint runPaint = paint;
99     SkMatrix localMatrix;
100     SkDraw localDraw(draw);
101
102     if (x || y) {
103         localMatrix = *draw.fMatrix;
104         localMatrix.preTranslate(x, y);
105         localDraw.fMatrix = &localMatrix;
106
107         if (paint.getShader()) {
108             // FIXME: We need to compensate for the translate above. This is suboptimal but
109             // temporary -- until we get proper derived class drawTextBlob implementations.
110
111             // TODO: pass x,y down to the other methods so they can handle the additional
112             // translate without needing to allocate a new shader.
113             SkMatrix shaderMatrix;
114             shaderMatrix.setTranslate(-x, -y);
115             SkAutoTUnref<SkShader> wrapper(
116                 SkShader::CreateLocalMatrixShader(paint.getShader(), shaderMatrix));
117             runPaint.setShader(wrapper);
118         }
119     }
120
121     SkTextBlob::RunIterator it(blob);
122     while (!it.done()) {
123         size_t textLen = it.glyphCount() * sizeof(uint16_t);
124         const SkPoint& offset = it.offset();
125         // applyFontToPaint() always overwrites the exact same attributes,
126         // so it is safe to not re-seed the paint.
127         it.applyFontToPaint(&runPaint);
128
129         switch (it.positioning()) {
130         case SkTextBlob::kDefault_Positioning:
131             this->drawText(localDraw, it.glyphs(), textLen, offset.x(), offset.y(), runPaint);
132             break;
133         case SkTextBlob::kHorizontal_Positioning:
134         case SkTextBlob::kFull_Positioning:
135             this->drawPosText(localDraw, it.glyphs(), textLen, it.pos(), offset.y(),
136                               SkTextBlob::ScalarsPerGlyph(it.positioning()), runPaint);
137             break;
138         default:
139             SkFAIL("unhandled positioning mode");
140         }
141
142         it.next();
143     }
144 }
145
146 bool SkBaseDevice::readPixels(const SkImageInfo& info, void* dstP, size_t rowBytes, int x, int y) {
147 #ifdef SK_DEBUG
148     SkASSERT(info.width() > 0 && info.height() > 0);
149     SkASSERT(dstP);
150     SkASSERT(rowBytes >= info.minRowBytes());
151     SkASSERT(x >= 0 && y >= 0);
152
153     const SkImageInfo& srcInfo = this->imageInfo();
154     SkASSERT(x + info.width() <= srcInfo.width());
155     SkASSERT(y + info.height() <= srcInfo.height());
156 #endif
157     return this->onReadPixels(info, dstP, rowBytes, x, y);
158 }
159
160 bool SkBaseDevice::writePixels(const SkImageInfo& info, const void* pixels, size_t rowBytes,
161                                int x, int y) {
162 #ifdef SK_DEBUG
163     SkASSERT(info.width() > 0 && info.height() > 0);
164     SkASSERT(pixels);
165     SkASSERT(rowBytes >= info.minRowBytes());
166     SkASSERT(x >= 0 && y >= 0);
167
168     const SkImageInfo& dstInfo = this->imageInfo();
169     SkASSERT(x + info.width() <= dstInfo.width());
170     SkASSERT(y + info.height() <= dstInfo.height());
171 #endif
172     return this->onWritePixels(info, pixels, rowBytes, x, y);
173 }
174
175 bool SkBaseDevice::onWritePixels(const SkImageInfo&, const void*, size_t, int, int) {
176     return false;
177 }
178
179 bool SkBaseDevice::onReadPixels(const SkImageInfo&, void*, size_t, int x, int y) {
180     return false;
181 }
182
183 void* SkBaseDevice::accessPixels(SkImageInfo* info, size_t* rowBytes) {
184     SkImageInfo tmpInfo;
185     size_t tmpRowBytes;
186     if (NULL == info) {
187         info = &tmpInfo;
188     }
189     if (NULL == rowBytes) {
190         rowBytes = &tmpRowBytes;
191     }
192     return this->onAccessPixels(info, rowBytes);
193 }
194
195 void* SkBaseDevice::onAccessPixels(SkImageInfo* info, size_t* rowBytes) {
196     return NULL;
197 }
198
199 void SkBaseDevice::EXPERIMENTAL_optimize(const SkPicture* picture) {
200     // The base class doesn't perform any analysis but derived classes may
201 }
202
203 bool SkBaseDevice::EXPERIMENTAL_drawPicture(SkCanvas*, const SkPicture*, const SkMatrix*,
204                                             const SkPaint*) {
205     // The base class doesn't perform any accelerated picture rendering
206     return false;
207 }