1c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com/* 2c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com * Copyright 2012 Google Inc. 3c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com * 4c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com * Use of this source code is governed by a BSD-style license that can be 5c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com * found in the LICENSE file. 6c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com */ 7c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com 8c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com#include "SkSurface_Base.h" 9c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com#include "SkImagePriv.h" 10c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com#include "SkCanvas.h" 1197af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com#include "SkDevice.h" 12c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com#include "SkMallocPixelRef.h" 13c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com 14c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.comstatic const size_t kIgnoreRowBytesValue = (size_t)~0; 15c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com 16c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.comclass SkSurface_Raster : public SkSurface_Base { 17c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.compublic: 182bd8b8100529c96c81c30f749f672f4caf775b04reed@google.com static bool Valid(const SkImageInfo&, size_t rb = kIgnoreRowBytesValue); 19c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com 202bd8b8100529c96c81c30f749f672f4caf775b04reed@google.com SkSurface_Raster(const SkImageInfo&, void*, size_t rb); 211360c52b10dad45d7a6850370eab40c6253d7988reed@google.com SkSurface_Raster(SkPixelRef*); 22c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com 23c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com virtual SkCanvas* onNewCanvas() SK_OVERRIDE; 242bd8b8100529c96c81c30f749f672f4caf775b04reed@google.com virtual SkSurface* onNewSurface(const SkImageInfo&) SK_OVERRIDE; 255ee449af7448c202cfc6e9a359d8f996392885b2junov@chromium.org virtual SkImage* onNewImageSnapshot() SK_OVERRIDE; 26c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y, 27c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com const SkPaint*) SK_OVERRIDE; 28c4c9870953037be94da00ac9db887d171f6e479ccommit-bot@chromium.org virtual void onCopyOnWrite(ContentChangeMode) SK_OVERRIDE; 29c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com 30c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.comprivate: 31c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com SkBitmap fBitmap; 32c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com bool fWeOwnThePixels; 33c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com 34c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com typedef SkSurface_Base INHERITED; 35c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com}; 36c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com 37c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com/////////////////////////////////////////////////////////////////////////////// 38c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com 392bd8b8100529c96c81c30f749f672f4caf775b04reed@google.combool SkSurface_Raster::Valid(const SkImageInfo& info, size_t rowBytes) { 40c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com static const size_t kMaxTotalSize = SK_MaxS32; 41c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com 42c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com int shift = 0; 431360c52b10dad45d7a6850370eab40c6253d7988reed@google.com switch (info.fColorType) { 441360c52b10dad45d7a6850370eab40c6253d7988reed@google.com case kAlpha_8_SkColorType: 45c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com shift = 0; 46c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com break; 471360c52b10dad45d7a6850370eab40c6253d7988reed@google.com case kRGB_565_SkColorType: 48c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com shift = 1; 49c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com break; 5028fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org case kN32_SkColorType: 51c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com shift = 2; 52c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com break; 53c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com default: 54c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com return false; 55c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com } 56c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com 57c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com if (kIgnoreRowBytesValue == rowBytes) { 58c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com return true; 59c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com } 60c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com 61c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com uint64_t minRB = (uint64_t)info.fWidth << shift; 62c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com if (minRB > rowBytes) { 63c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com return false; 64c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com } 65c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com 66c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com size_t alignedRowBytes = rowBytes >> shift << shift; 67c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com if (alignedRowBytes != rowBytes) { 68c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com return false; 69c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com } 70c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com 711360c52b10dad45d7a6850370eab40c6253d7988reed@google.com uint64_t size = sk_64_mul(info.fHeight, rowBytes); 72c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com if (size > kMaxTotalSize) { 73c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com return false; 74c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com } 75fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 76c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com return true; 77c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com} 78c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com 792bd8b8100529c96c81c30f749f672f4caf775b04reed@google.comSkSurface_Raster::SkSurface_Raster(const SkImageInfo& info, void* pixels, size_t rb) 801360c52b10dad45d7a6850370eab40c6253d7988reed@google.com : INHERITED(info) 811360c52b10dad45d7a6850370eab40c6253d7988reed@google.com{ 82a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org fBitmap.installPixels(info, pixels, rb); 8397af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com fWeOwnThePixels = false; // We are "Direct" 84c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com} 85c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com 861360c52b10dad45d7a6850370eab40c6253d7988reed@google.comSkSurface_Raster::SkSurface_Raster(SkPixelRef* pr) 87e13af711d4ff9031c9ed3054a4c33a56a0c62e1fcommit-bot@chromium.org : INHERITED(pr->info().fWidth, pr->info().fHeight) 881360c52b10dad45d7a6850370eab40c6253d7988reed@google.com{ 89e13af711d4ff9031c9ed3054a4c33a56a0c62e1fcommit-bot@chromium.org const SkImageInfo& info = pr->info(); 90e13af711d4ff9031c9ed3054a4c33a56a0c62e1fcommit-bot@chromium.org 91a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org fBitmap.setInfo(info, info.minRowBytes()); 92e13af711d4ff9031c9ed3054a4c33a56a0c62e1fcommit-bot@chromium.org fBitmap.setPixelRef(pr); 93c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com fWeOwnThePixels = true; 94c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com 95e13af711d4ff9031c9ed3054a4c33a56a0c62e1fcommit-bot@chromium.org if (!info.isOpaque()) { 96dbfac8a72393eaf01670aeb3244de0e18d8faf98junov@google.com fBitmap.eraseColor(SK_ColorTRANSPARENT); 97c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com } 98c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com} 99c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com 100c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.comSkCanvas* SkSurface_Raster::onNewCanvas() { 101c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com return SkNEW_ARGS(SkCanvas, (fBitmap)); 102c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com} 103c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com 1042bd8b8100529c96c81c30f749f672f4caf775b04reed@google.comSkSurface* SkSurface_Raster::onNewSurface(const SkImageInfo& info) { 105b947625800a26194fcf63d7b57dadb1a63677f6amike@reedtribe.org return SkSurface::NewRaster(info); 106c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com} 107c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com 108c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.comvoid SkSurface_Raster::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, 109c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com const SkPaint* paint) { 110c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com canvas->drawBitmap(fBitmap, x, y, paint); 111c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com} 112c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com 1135ee449af7448c202cfc6e9a359d8f996392885b2junov@chromium.orgSkImage* SkSurface_Raster::onNewImageSnapshot() { 11497af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com return SkNewImageFromBitmap(fBitmap, fWeOwnThePixels); 11597af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com} 11697af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com 117c4c9870953037be94da00ac9db887d171f6e479ccommit-bot@chromium.orgvoid SkSurface_Raster::onCopyOnWrite(ContentChangeMode mode) { 11897af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com // are we sharing pixelrefs with the image? 119c4c9870953037be94da00ac9db887d171f6e479ccommit-bot@chromium.org SkASSERT(NULL != this->getCachedImage()); 120acea3ef448c9903de3aa6a013c839dce577e6ce3junov@chromium.org if (SkBitmapImageGetPixelRef(this->getCachedImage()) == fBitmap.pixelRef()) { 12197af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com SkASSERT(fWeOwnThePixels); 122c4c9870953037be94da00ac9db887d171f6e479ccommit-bot@chromium.org if (kDiscard_ContentChangeMode == mode) { 123672588b684d484dce6ae251e9e163e4a46924322reed@google.com fBitmap.setPixelRef(NULL); 124c4c9870953037be94da00ac9db887d171f6e479ccommit-bot@chromium.org fBitmap.allocPixels(); 125c4c9870953037be94da00ac9db887d171f6e479ccommit-bot@chromium.org } else { 126c4c9870953037be94da00ac9db887d171f6e479ccommit-bot@chromium.org SkBitmap prev(fBitmap); 1276285f4f7662853336b788d6ee3e177c396f7fb01commit-bot@chromium.org prev.deepCopyTo(&fBitmap); 128c4c9870953037be94da00ac9db887d171f6e479ccommit-bot@chromium.org } 12997af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com // Now fBitmap is a deep copy of itself (and therefore different from 13097af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com // what is being used by the image. Next we update the canvas to use 13197af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com // this as its backend, so we can't modify the image's pixels anymore. 132acea3ef448c9903de3aa6a013c839dce577e6ce3junov@chromium.org SkASSERT(NULL != this->getCachedCanvas()); 133acea3ef448c9903de3aa6a013c839dce577e6ce3junov@chromium.org this->getCachedCanvas()->getDevice()->replaceBitmapBackendForRasterSurface(fBitmap); 13497af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com } 13597af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com} 13697af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com 137c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com/////////////////////////////////////////////////////////////////////////////// 138c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com 1392bd8b8100529c96c81c30f749f672f4caf775b04reed@google.comSkSurface* SkSurface::NewRasterDirect(const SkImageInfo& info, void* pixels, size_t rowBytes) { 140b947625800a26194fcf63d7b57dadb1a63677f6amike@reedtribe.org if (!SkSurface_Raster::Valid(info, rowBytes)) { 141c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com return NULL; 142c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com } 143c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com if (NULL == pixels) { 144c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com return NULL; 145c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com } 146fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 147b947625800a26194fcf63d7b57dadb1a63677f6amike@reedtribe.org return SkNEW_ARGS(SkSurface_Raster, (info, pixels, rowBytes)); 148c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com} 149c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com 1502bd8b8100529c96c81c30f749f672f4caf775b04reed@google.comSkSurface* SkSurface::NewRaster(const SkImageInfo& info) { 151b947625800a26194fcf63d7b57dadb1a63677f6amike@reedtribe.org if (!SkSurface_Raster::Valid(info)) { 152c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com return NULL; 153c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com } 154fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 155bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com SkAutoTUnref<SkPixelRef> pr(SkMallocPixelRef::NewAllocate(info, 0, NULL)); 156bf790232f6d94b54239dbc210d8beee7411ca458reed@google.com if (NULL == pr.get()) { 157c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com return NULL; 158c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com } 1591360c52b10dad45d7a6850370eab40c6253d7988reed@google.com return SkNEW_ARGS(SkSurface_Raster, (pr)); 160c9062047cea66575868270b4dcaeb1dab113c8a7reed@google.com} 161