SkDevice.cpp revision b122ee50fb56cf6669fe1668b82c8815896e9943
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 16SkBaseDevice::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 26SkBaseDevice::~SkBaseDevice() { 27 SkDELETE(fLeakyProperties); 28 SkDELETE(fMetaData); 29} 30 31SkBaseDevice* SkBaseDevice::createCompatibleDevice(const SkImageInfo& info) { 32 return this->onCreateCompatibleDevice(CreateInfo(info, kGeneral_Usage)); 33} 34 35SkBaseDevice* SkBaseDevice::createCompatibleDeviceForSaveLayer(const SkImageInfo& info) { 36 return this->onCreateCompatibleDevice(CreateInfo(info, kSaveLayer_Usage)); 37} 38 39SkBaseDevice* SkBaseDevice::createCompatibleDeviceForImageFilter(const SkImageInfo& info) { 40 return this->onCreateCompatibleDevice(CreateInfo(info, kImageFilter_Usage)); 41} 42 43SkMetaData& SkBaseDevice::getMetaData() { 44 // metadata users are rare, so we lazily allocate it. If that changes we 45 // can decide to just make it a field in the device (rather than a ptr) 46 if (NULL == fMetaData) { 47 fMetaData = new SkMetaData; 48 } 49 return *fMetaData; 50} 51 52SkImageInfo SkBaseDevice::imageInfo() const { 53 return SkImageInfo::MakeUnknown(); 54} 55 56const SkBitmap& SkBaseDevice::accessBitmap(bool changePixels) { 57 const SkBitmap& bitmap = this->onAccessBitmap(); 58 if (changePixels) { 59 bitmap.notifyPixelsChanged(); 60 } 61 return bitmap; 62} 63 64void SkBaseDevice::setPixelGeometry(SkPixelGeometry geo) { 65 fLeakyProperties->setPixelGeometry(geo); 66} 67 68SkSurface* SkBaseDevice::newSurface(const SkImageInfo&, const SkSurfaceProps&) { return NULL; } 69 70const void* SkBaseDevice::peekPixels(SkImageInfo*, size_t*) { return NULL; } 71 72void SkBaseDevice::drawDRRect(const SkDraw& draw, const SkRRect& outer, 73 const SkRRect& inner, const SkPaint& paint) { 74 SkPath path; 75 path.addRRect(outer); 76 path.addRRect(inner); 77 path.setFillType(SkPath::kEvenOdd_FillType); 78 79 const SkMatrix* preMatrix = NULL; 80 const bool pathIsMutable = true; 81 this->drawPath(draw, path, paint, preMatrix, pathIsMutable); 82} 83 84void SkBaseDevice::drawPatch(const SkDraw& draw, const SkPoint cubics[12], const SkColor colors[4], 85 const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) { 86 SkPatchUtils::VertexData data; 87 88 SkISize lod = SkPatchUtils::GetLevelOfDetail(cubics, draw.fMatrix); 89 90 // It automatically adjusts lodX and lodY in case it exceeds the number of indices. 91 // If it fails to generate the vertices, then we do not draw. 92 if (SkPatchUtils::getVertexData(&data, cubics, colors, texCoords, lod.width(), lod.height())) { 93 this->drawVertices(draw, SkCanvas::kTriangles_VertexMode, data.fVertexCount, data.fPoints, 94 data.fTexCoords, data.fColors, xmode, data.fIndices, data.fIndexCount, 95 paint); 96 } 97} 98 99void SkBaseDevice::drawTextBlob(const SkDraw& draw, const SkTextBlob* blob, SkScalar x, SkScalar y, 100 const SkPaint &paint) { 101 102 SkPaint runPaint = paint; 103 104 SkTextBlob::RunIterator it(blob); 105 while (!it.done()) { 106 size_t textLen = it.glyphCount() * sizeof(uint16_t); 107 const SkPoint& offset = it.offset(); 108 // applyFontToPaint() always overwrites the exact same attributes, 109 // so it is safe to not re-seed the paint. 110 it.applyFontToPaint(&runPaint); 111 112 switch (it.positioning()) { 113 case SkTextBlob::kDefault_Positioning: 114 this->drawText(draw, it.glyphs(), textLen, x + offset.x(), y + offset.y(), runPaint); 115 break; 116 case SkTextBlob::kHorizontal_Positioning: 117 this->drawPosText(draw, it.glyphs(), textLen, it.pos(), 1, 118 SkPoint::Make(x, y + offset.y()), runPaint); 119 break; 120 case SkTextBlob::kFull_Positioning: 121 this->drawPosText(draw, it.glyphs(), textLen, it.pos(), 2, 122 SkPoint::Make(x, y), runPaint); 123 break; 124 default: 125 SkFAIL("unhandled positioning mode"); 126 } 127 128 it.next(); 129 } 130} 131 132bool SkBaseDevice::readPixels(const SkImageInfo& info, void* dstP, size_t rowBytes, int x, int y) { 133#ifdef SK_DEBUG 134 SkASSERT(info.width() > 0 && info.height() > 0); 135 SkASSERT(dstP); 136 SkASSERT(rowBytes >= info.minRowBytes()); 137 SkASSERT(x >= 0 && y >= 0); 138 139 const SkImageInfo& srcInfo = this->imageInfo(); 140 SkASSERT(x + info.width() <= srcInfo.width()); 141 SkASSERT(y + info.height() <= srcInfo.height()); 142#endif 143 return this->onReadPixels(info, dstP, rowBytes, x, y); 144} 145 146bool SkBaseDevice::writePixels(const SkImageInfo& info, const void* pixels, size_t rowBytes, 147 int x, int y) { 148#ifdef SK_DEBUG 149 SkASSERT(info.width() > 0 && info.height() > 0); 150 SkASSERT(pixels); 151 SkASSERT(rowBytes >= info.minRowBytes()); 152 SkASSERT(x >= 0 && y >= 0); 153 154 const SkImageInfo& dstInfo = this->imageInfo(); 155 SkASSERT(x + info.width() <= dstInfo.width()); 156 SkASSERT(y + info.height() <= dstInfo.height()); 157#endif 158 return this->onWritePixels(info, pixels, rowBytes, x, y); 159} 160 161bool SkBaseDevice::onWritePixels(const SkImageInfo&, const void*, size_t, int, int) { 162 return false; 163} 164 165bool SkBaseDevice::onReadPixels(const SkImageInfo&, void*, size_t, int x, int y) { 166 return false; 167} 168 169void* SkBaseDevice::accessPixels(SkImageInfo* info, size_t* rowBytes) { 170 SkImageInfo tmpInfo; 171 size_t tmpRowBytes; 172 if (NULL == info) { 173 info = &tmpInfo; 174 } 175 if (NULL == rowBytes) { 176 rowBytes = &tmpRowBytes; 177 } 178 return this->onAccessPixels(info, rowBytes); 179} 180 181void* SkBaseDevice::onAccessPixels(SkImageInfo* info, size_t* rowBytes) { 182 return NULL; 183} 184 185bool SkBaseDevice::EXPERIMENTAL_drawPicture(SkCanvas*, const SkPicture*, const SkMatrix*, 186 const SkPaint*) { 187 // The base class doesn't perform any accelerated picture rendering 188 return false; 189} 190