Move SkBitmapDevice functions to their own file
https://codereview.chromium.org/23553006/ git-svn-id: http://skia.googlecode.com/svn/trunk@11022 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
6db2ae21a3
commit
53238bc960
@ -21,6 +21,7 @@
|
||||
'<(skia_src_path)/core/SkBBoxHierarchyRecord.cpp',
|
||||
'<(skia_src_path)/core/SkBBoxHierarchyRecord.h',
|
||||
'<(skia_src_path)/core/SkBitmap.cpp',
|
||||
'<(skia_src_path)/core/SkBitmapDevice.cpp',
|
||||
'<(skia_src_path)/core/SkBitmapFilter.h',
|
||||
'<(skia_src_path)/core/SkBitmapFilter.cpp',
|
||||
'<(skia_src_path)/core/SkBitmapHeap.cpp',
|
||||
|
410
src/core/SkBitmapDevice.cpp
Normal file
410
src/core/SkBitmapDevice.cpp
Normal file
@ -0,0 +1,410 @@
|
||||
/*
|
||||
* Copyright 2013 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "SkBitmapDevice.h"
|
||||
#include "SkConfig8888.h"
|
||||
#include "SkDraw.h"
|
||||
#include "SkRasterClip.h"
|
||||
#include "SkShader.h"
|
||||
|
||||
SK_DEFINE_INST_COUNT(SkBitmapDevice)
|
||||
|
||||
#define CHECK_FOR_NODRAW_ANNOTATION(paint) \
|
||||
do { if (paint.isNoDrawAnnotation()) { return; } } while (0)
|
||||
|
||||
SkBitmapDevice::SkBitmapDevice(const SkBitmap& bitmap)
|
||||
: fBitmap(bitmap) {
|
||||
SkASSERT(SkBitmap::kARGB_4444_Config != bitmap.config());
|
||||
}
|
||||
|
||||
SkBitmapDevice::SkBitmapDevice(const SkBitmap& bitmap, const SkDeviceProperties& deviceProperties)
|
||||
: SkBaseDevice(deviceProperties)
|
||||
, fBitmap(bitmap) {
|
||||
}
|
||||
|
||||
SkBitmapDevice::SkBitmapDevice(SkBitmap::Config config, int width, int height, bool isOpaque) {
|
||||
fBitmap.setConfig(config, width, height);
|
||||
fBitmap.allocPixels();
|
||||
fBitmap.setIsOpaque(isOpaque);
|
||||
if (!isOpaque) {
|
||||
fBitmap.eraseColor(SK_ColorTRANSPARENT);
|
||||
}
|
||||
}
|
||||
|
||||
SkBitmapDevice::SkBitmapDevice(SkBitmap::Config config, int width, int height, bool isOpaque,
|
||||
const SkDeviceProperties& deviceProperties)
|
||||
: SkBaseDevice(deviceProperties) {
|
||||
|
||||
fBitmap.setConfig(config, width, height);
|
||||
fBitmap.allocPixels();
|
||||
fBitmap.setIsOpaque(isOpaque);
|
||||
if (!isOpaque) {
|
||||
fBitmap.eraseColor(SK_ColorTRANSPARENT);
|
||||
}
|
||||
}
|
||||
|
||||
SkBitmapDevice::~SkBitmapDevice() {
|
||||
}
|
||||
|
||||
void SkBitmapDevice::replaceBitmapBackendForRasterSurface(const SkBitmap& bm) {
|
||||
SkASSERT(bm.width() == fBitmap.width());
|
||||
SkASSERT(bm.height() == fBitmap.height());
|
||||
fBitmap = bm; // intent is to use bm's pixelRef (and rowbytes/config)
|
||||
fBitmap.lockPixels();
|
||||
}
|
||||
|
||||
SkBaseDevice* SkBitmapDevice::onCreateCompatibleDevice(SkBitmap::Config config,
|
||||
int width, int height,
|
||||
bool isOpaque,
|
||||
Usage usage) {
|
||||
return SkNEW_ARGS(SkBitmapDevice,(config, width, height, isOpaque,
|
||||
this->getDeviceProperties()));
|
||||
}
|
||||
|
||||
void SkBitmapDevice::lockPixels() {
|
||||
if (fBitmap.lockPixelsAreWritable()) {
|
||||
fBitmap.lockPixels();
|
||||
}
|
||||
}
|
||||
|
||||
void SkBitmapDevice::unlockPixels() {
|
||||
if (fBitmap.lockPixelsAreWritable()) {
|
||||
fBitmap.unlockPixels();
|
||||
}
|
||||
}
|
||||
|
||||
void SkBitmapDevice::getGlobalBounds(SkIRect* bounds) const {
|
||||
if (NULL != bounds) {
|
||||
const SkIPoint& origin = this->getOrigin();
|
||||
bounds->setXYWH(origin.x(), origin.y(),
|
||||
fBitmap.width(), fBitmap.height());
|
||||
}
|
||||
}
|
||||
|
||||
void SkBitmapDevice::clear(SkColor color) {
|
||||
fBitmap.eraseColor(color);
|
||||
}
|
||||
|
||||
const SkBitmap& SkBitmapDevice::onAccessBitmap() {
|
||||
return fBitmap;
|
||||
}
|
||||
|
||||
bool SkBitmapDevice::canHandleImageFilter(SkImageFilter*) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SkBitmapDevice::filterImage(SkImageFilter* filter, const SkBitmap& src,
|
||||
const SkMatrix& ctm, SkBitmap* result,
|
||||
SkIPoint* offset) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SkBitmapDevice::allowImageFilter(SkImageFilter*) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SkBitmapDevice::onReadPixels(const SkBitmap& bitmap,
|
||||
int x, int y,
|
||||
SkCanvas::Config8888 config8888) {
|
||||
SkASSERT(SkBitmap::kARGB_8888_Config == bitmap.config());
|
||||
SkASSERT(!bitmap.isNull());
|
||||
SkASSERT(SkIRect::MakeWH(this->width(), this->height()).contains(SkIRect::MakeXYWH(x, y,
|
||||
bitmap.width(),
|
||||
bitmap.height())));
|
||||
|
||||
SkIRect srcRect = SkIRect::MakeXYWH(x, y, bitmap.width(), bitmap.height());
|
||||
const SkBitmap& src = this->accessBitmap(false);
|
||||
|
||||
SkBitmap subset;
|
||||
if (!src.extractSubset(&subset, srcRect)) {
|
||||
return false;
|
||||
}
|
||||
if (SkBitmap::kARGB_8888_Config != subset.config()) {
|
||||
// It'd be preferable to do this directly to bitmap.
|
||||
subset.copyTo(&subset, SkBitmap::kARGB_8888_Config);
|
||||
}
|
||||
SkAutoLockPixels alp(bitmap);
|
||||
uint32_t* bmpPixels = reinterpret_cast<uint32_t*>(bitmap.getPixels());
|
||||
SkCopyBitmapToConfig8888(bmpPixels, bitmap.rowBytes(), config8888, subset);
|
||||
return true;
|
||||
}
|
||||
|
||||
void SkBitmapDevice::writePixels(const SkBitmap& bitmap,
|
||||
int x, int y,
|
||||
SkCanvas::Config8888 config8888) {
|
||||
if (bitmap.isNull() || bitmap.getTexture()) {
|
||||
return;
|
||||
}
|
||||
const SkBitmap* sprite = &bitmap;
|
||||
// check whether we have to handle a config8888 that doesn't match SkPMColor
|
||||
if (SkBitmap::kARGB_8888_Config == bitmap.config() &&
|
||||
SkCanvas::kNative_Premul_Config8888 != config8888 &&
|
||||
kPMColorAlias != config8888) {
|
||||
|
||||
// We're going to have to convert from a config8888 to the native config
|
||||
// First we clip to the device bounds.
|
||||
SkBitmap dstBmp = this->accessBitmap(true);
|
||||
SkIRect spriteRect = SkIRect::MakeXYWH(x, y,
|
||||
bitmap.width(), bitmap.height());
|
||||
SkIRect devRect = SkIRect::MakeWH(dstBmp.width(), dstBmp.height());
|
||||
if (!spriteRect.intersect(devRect)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// write directly to the device if it has pixels and is SkPMColor
|
||||
bool drawSprite;
|
||||
if (SkBitmap::kARGB_8888_Config == dstBmp.config() && !dstBmp.isNull()) {
|
||||
// we can write directly to the dst when doing the conversion
|
||||
dstBmp.extractSubset(&dstBmp, spriteRect);
|
||||
drawSprite = false;
|
||||
} else {
|
||||
// we convert to a temporary bitmap and draw that as a sprite
|
||||
dstBmp.setConfig(SkBitmap::kARGB_8888_Config,
|
||||
spriteRect.width(),
|
||||
spriteRect.height());
|
||||
if (!dstBmp.allocPixels()) {
|
||||
return;
|
||||
}
|
||||
drawSprite = true;
|
||||
}
|
||||
|
||||
// copy pixels to dstBmp and convert from config8888 to native config.
|
||||
SkAutoLockPixels alp(bitmap);
|
||||
uint32_t* srcPixels = bitmap.getAddr32(spriteRect.fLeft - x,
|
||||
spriteRect.fTop - y);
|
||||
SkCopyConfig8888ToBitmap(dstBmp,
|
||||
srcPixels,
|
||||
bitmap.rowBytes(),
|
||||
config8888);
|
||||
|
||||
if (drawSprite) {
|
||||
// we've clipped the sprite when we made a copy
|
||||
x = spriteRect.fLeft;
|
||||
y = spriteRect.fTop;
|
||||
sprite = &dstBmp;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SkPaint paint;
|
||||
paint.setXfermodeMode(SkXfermode::kSrc_Mode);
|
||||
SkRasterClip clip(SkIRect::MakeWH(fBitmap.width(), fBitmap.height()));
|
||||
SkDraw draw;
|
||||
draw.fRC = &clip;
|
||||
draw.fClip = &clip.bwRgn();
|
||||
draw.fBitmap = &fBitmap; // canvas should have already called accessBitmap
|
||||
draw.fMatrix = &SkMatrix::I();
|
||||
this->drawSprite(draw, *sprite, x, y, paint);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void SkBitmapDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) {
|
||||
draw.drawPaint(paint);
|
||||
}
|
||||
|
||||
void SkBitmapDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, size_t count,
|
||||
const SkPoint pts[], const SkPaint& paint) {
|
||||
CHECK_FOR_NODRAW_ANNOTATION(paint);
|
||||
draw.drawPoints(mode, count, pts, paint);
|
||||
}
|
||||
|
||||
void SkBitmapDevice::drawRect(const SkDraw& draw, const SkRect& r, const SkPaint& paint) {
|
||||
CHECK_FOR_NODRAW_ANNOTATION(paint);
|
||||
draw.drawRect(r, paint);
|
||||
}
|
||||
|
||||
void SkBitmapDevice::drawOval(const SkDraw& draw, const SkRect& oval, const SkPaint& paint) {
|
||||
CHECK_FOR_NODRAW_ANNOTATION(paint);
|
||||
|
||||
SkPath path;
|
||||
path.addOval(oval);
|
||||
// call the VIRTUAL version, so any subclasses who do handle drawPath aren't
|
||||
// required to override drawOval.
|
||||
this->drawPath(draw, path, paint, NULL, true);
|
||||
}
|
||||
|
||||
void SkBitmapDevice::drawRRect(const SkDraw& draw, const SkRRect& rrect, const SkPaint& paint) {
|
||||
CHECK_FOR_NODRAW_ANNOTATION(paint);
|
||||
|
||||
SkPath path;
|
||||
path.addRRect(rrect);
|
||||
// call the VIRTUAL version, so any subclasses who do handle drawPath aren't
|
||||
// required to override drawRRect.
|
||||
this->drawPath(draw, path, paint, NULL, true);
|
||||
}
|
||||
|
||||
void SkBitmapDevice::drawPath(const SkDraw& draw, const SkPath& path,
|
||||
const SkPaint& paint, const SkMatrix* prePathMatrix,
|
||||
bool pathIsMutable) {
|
||||
CHECK_FOR_NODRAW_ANNOTATION(paint);
|
||||
draw.drawPath(path, paint, prePathMatrix, pathIsMutable);
|
||||
}
|
||||
|
||||
void SkBitmapDevice::drawBitmap(const SkDraw& draw, const SkBitmap& bitmap,
|
||||
const SkMatrix& matrix, const SkPaint& paint) {
|
||||
draw.drawBitmap(bitmap, matrix, paint);
|
||||
}
|
||||
|
||||
void SkBitmapDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap,
|
||||
const SkRect* src, const SkRect& dst,
|
||||
const SkPaint& paint,
|
||||
SkCanvas::DrawBitmapRectFlags flags) {
|
||||
SkMatrix matrix;
|
||||
SkRect bitmapBounds, tmpSrc, tmpDst;
|
||||
SkBitmap tmpBitmap;
|
||||
|
||||
bitmapBounds.isetWH(bitmap.width(), bitmap.height());
|
||||
|
||||
// Compute matrix from the two rectangles
|
||||
if (src) {
|
||||
tmpSrc = *src;
|
||||
} else {
|
||||
tmpSrc = bitmapBounds;
|
||||
}
|
||||
matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit);
|
||||
|
||||
const SkRect* dstPtr = &dst;
|
||||
const SkBitmap* bitmapPtr = &bitmap;
|
||||
|
||||
// clip the tmpSrc to the bounds of the bitmap, and recompute dstRect if
|
||||
// needed (if the src was clipped). No check needed if src==null.
|
||||
if (src) {
|
||||
if (!bitmapBounds.contains(*src)) {
|
||||
if (!tmpSrc.intersect(bitmapBounds)) {
|
||||
return; // nothing to draw
|
||||
}
|
||||
// recompute dst, based on the smaller tmpSrc
|
||||
matrix.mapRect(&tmpDst, tmpSrc);
|
||||
dstPtr = &tmpDst;
|
||||
}
|
||||
|
||||
// since we may need to clamp to the borders of the src rect within
|
||||
// the bitmap, we extract a subset.
|
||||
SkIRect srcIR;
|
||||
tmpSrc.roundOut(&srcIR);
|
||||
if (!bitmap.extractSubset(&tmpBitmap, srcIR)) {
|
||||
return;
|
||||
}
|
||||
bitmapPtr = &tmpBitmap;
|
||||
|
||||
// Since we did an extract, we need to adjust the matrix accordingly
|
||||
SkScalar dx = 0, dy = 0;
|
||||
if (srcIR.fLeft > 0) {
|
||||
dx = SkIntToScalar(srcIR.fLeft);
|
||||
}
|
||||
if (srcIR.fTop > 0) {
|
||||
dy = SkIntToScalar(srcIR.fTop);
|
||||
}
|
||||
if (dx || dy) {
|
||||
matrix.preTranslate(dx, dy);
|
||||
}
|
||||
|
||||
SkRect extractedBitmapBounds;
|
||||
extractedBitmapBounds.isetWH(bitmapPtr->width(), bitmapPtr->height());
|
||||
if (extractedBitmapBounds == tmpSrc) {
|
||||
// no fractional part in src, we can just call drawBitmap
|
||||
goto USE_DRAWBITMAP;
|
||||
}
|
||||
} else {
|
||||
USE_DRAWBITMAP:
|
||||
// We can go faster by just calling drawBitmap, which will concat the
|
||||
// matrix with the CTM, and try to call drawSprite if it can. If not,
|
||||
// it will make a shader and call drawRect, as we do below.
|
||||
this->drawBitmap(draw, *bitmapPtr, matrix, paint);
|
||||
return;
|
||||
}
|
||||
|
||||
// construct a shader, so we can call drawRect with the dst
|
||||
SkShader* s = SkShader::CreateBitmapShader(*bitmapPtr,
|
||||
SkShader::kClamp_TileMode,
|
||||
SkShader::kClamp_TileMode);
|
||||
if (NULL == s) {
|
||||
return;
|
||||
}
|
||||
s->setLocalMatrix(matrix);
|
||||
|
||||
SkPaint paintWithShader(paint);
|
||||
paintWithShader.setStyle(SkPaint::kFill_Style);
|
||||
paintWithShader.setShader(s)->unref();
|
||||
|
||||
// Call ourself, in case the subclass wanted to share this setup code
|
||||
// but handle the drawRect code themselves.
|
||||
this->drawRect(draw, *dstPtr, paintWithShader);
|
||||
}
|
||||
|
||||
void SkBitmapDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap,
|
||||
int x, int y, const SkPaint& paint) {
|
||||
draw.drawSprite(bitmap, x, y, paint);
|
||||
}
|
||||
|
||||
void SkBitmapDevice::drawText(const SkDraw& draw, const void* text, size_t len,
|
||||
SkScalar x, SkScalar y, const SkPaint& paint) {
|
||||
draw.drawText((const char*)text, len, x, y, paint);
|
||||
}
|
||||
|
||||
void SkBitmapDevice::drawPosText(const SkDraw& draw, const void* text, size_t len,
|
||||
const SkScalar xpos[], SkScalar y,
|
||||
int scalarsPerPos, const SkPaint& paint) {
|
||||
draw.drawPosText((const char*)text, len, xpos, y, scalarsPerPos, paint);
|
||||
}
|
||||
|
||||
void SkBitmapDevice::drawTextOnPath(const SkDraw& draw, const void* text,
|
||||
size_t len, const SkPath& path,
|
||||
const SkMatrix* matrix,
|
||||
const SkPaint& paint) {
|
||||
draw.drawTextOnPath((const char*)text, len, path, matrix, paint);
|
||||
}
|
||||
|
||||
#ifdef SK_BUILD_FOR_ANDROID
|
||||
void SkBitmapDevice::drawPosTextOnPath(const SkDraw& draw, const void* text, size_t len,
|
||||
const SkPoint pos[], const SkPaint& paint,
|
||||
const SkPath& path, const SkMatrix* matrix) {
|
||||
draw.drawPosTextOnPath((const char*)text, len, pos, paint, path, matrix);
|
||||
}
|
||||
#endif
|
||||
|
||||
void SkBitmapDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode,
|
||||
int vertexCount,
|
||||
const SkPoint verts[], const SkPoint textures[],
|
||||
const SkColor colors[], SkXfermode* xmode,
|
||||
const uint16_t indices[], int indexCount,
|
||||
const SkPaint& paint) {
|
||||
draw.drawVertices(vmode, vertexCount, verts, textures, colors, xmode,
|
||||
indices, indexCount, paint);
|
||||
}
|
||||
|
||||
void SkBitmapDevice::drawDevice(const SkDraw& draw, SkBaseDevice* device,
|
||||
int x, int y, const SkPaint& paint) {
|
||||
const SkBitmap& src = device->accessBitmap(false);
|
||||
draw.drawSprite(src, x, y, paint);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool SkBitmapDevice::filterTextFlags(const SkPaint& paint, TextFlags* flags) {
|
||||
if (!paint.isLCDRenderText() || !paint.isAntiAlias()) {
|
||||
// we're cool with the paint as is
|
||||
return false;
|
||||
}
|
||||
|
||||
if (SkBitmap::kARGB_8888_Config != fBitmap.config() ||
|
||||
paint.getRasterizer() ||
|
||||
paint.getPathEffect() ||
|
||||
paint.isFakeBoldText() ||
|
||||
paint.getStyle() != SkPaint::kFill_Style ||
|
||||
!SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrcOver_Mode)) {
|
||||
// turn off lcd
|
||||
flags->fFlags = paint.getFlags() & ~SkPaint::kLCDRenderText_Flag;
|
||||
flags->fHinting = paint.getHinting();
|
||||
return true;
|
||||
}
|
||||
// we're cool with the paint as is
|
||||
return false;
|
||||
}
|
||||
|
@ -5,32 +5,21 @@
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
#include "SkBitmapDevice.h"
|
||||
|
||||
#include "SkDevice.h"
|
||||
#include "SkDeviceProperties.h"
|
||||
#include "SkDraw.h"
|
||||
#include "SkImageFilter.h"
|
||||
#include "SkMetaData.h"
|
||||
#include "SkRasterClip.h"
|
||||
#include "SkRect.h"
|
||||
#include "SkRRect.h"
|
||||
#include "SkShader.h"
|
||||
|
||||
SK_DEFINE_INST_COUNT(SkBaseDevice)
|
||||
SK_DEFINE_INST_COUNT(SkBitmapDevice)
|
||||
|
||||
#if SK_PMCOLOR_BYTE_ORDER(B,G,R,A)
|
||||
const SkCanvas::Config8888 SkBaseDevice::kPMColorAlias = SkCanvas::kBGRA_Premul_Config8888;
|
||||
#elif SK_PMCOLOR_BYTE_ORDER(R,G,B,A)
|
||||
const SkCanvas::Config8888 SkBaseDevice::kPMColorAlias = SkCanvas::kRGBA_Premul_Config8888;
|
||||
#else
|
||||
const SkCanvas::Config8888 SkBaseDevice::kPMColorAlias = (SkCanvas::Config8888) -1;
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define CHECK_FOR_NODRAW_ANNOTATION(paint) \
|
||||
do { if (paint.isNoDrawAnnotation()) { return; } } while (0)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SkBitmapDevice::SkBitmapDevice(const SkBitmap& bitmap)
|
||||
: fBitmap(bitmap) {
|
||||
SkASSERT(SkBitmap::kARGB_4444_Config != bitmap.config());
|
||||
}
|
||||
|
||||
SkBaseDevice::SkBaseDevice()
|
||||
: fLeakyProperties(SkDeviceProperties::MakeDefault())
|
||||
#ifdef SK_DEBUG
|
||||
@ -41,11 +30,6 @@ SkBaseDevice::SkBaseDevice()
|
||||
fMetaData = NULL;
|
||||
}
|
||||
|
||||
SkBitmapDevice::SkBitmapDevice(const SkBitmap& bitmap, const SkDeviceProperties& deviceProperties)
|
||||
: SkBaseDevice(deviceProperties)
|
||||
, fBitmap(bitmap) {
|
||||
}
|
||||
|
||||
SkBaseDevice::SkBaseDevice(const SkDeviceProperties& deviceProperties)
|
||||
: fLeakyProperties(deviceProperties)
|
||||
#ifdef SK_DEBUG
|
||||
@ -56,41 +40,10 @@ SkBaseDevice::SkBaseDevice(const SkDeviceProperties& deviceProperties)
|
||||
fMetaData = NULL;
|
||||
}
|
||||
|
||||
SkBitmapDevice::SkBitmapDevice(SkBitmap::Config config, int width, int height, bool isOpaque) {
|
||||
fBitmap.setConfig(config, width, height);
|
||||
fBitmap.allocPixels();
|
||||
fBitmap.setIsOpaque(isOpaque);
|
||||
if (!isOpaque) {
|
||||
fBitmap.eraseColor(SK_ColorTRANSPARENT);
|
||||
}
|
||||
}
|
||||
|
||||
SkBitmapDevice::SkBitmapDevice(SkBitmap::Config config, int width, int height, bool isOpaque,
|
||||
const SkDeviceProperties& deviceProperties)
|
||||
: SkBaseDevice(deviceProperties) {
|
||||
|
||||
fBitmap.setConfig(config, width, height);
|
||||
fBitmap.allocPixels();
|
||||
fBitmap.setIsOpaque(isOpaque);
|
||||
if (!isOpaque) {
|
||||
fBitmap.eraseColor(SK_ColorTRANSPARENT);
|
||||
}
|
||||
}
|
||||
|
||||
SkBaseDevice::~SkBaseDevice() {
|
||||
delete fMetaData;
|
||||
}
|
||||
|
||||
SkBitmapDevice::~SkBitmapDevice() {
|
||||
}
|
||||
|
||||
void SkBitmapDevice::replaceBitmapBackendForRasterSurface(const SkBitmap& bm) {
|
||||
SkASSERT(bm.width() == fBitmap.width());
|
||||
SkASSERT(bm.height() == fBitmap.height());
|
||||
fBitmap = bm; // intent is to use bm's pixelRef (and rowbytes/config)
|
||||
fBitmap.lockPixels();
|
||||
}
|
||||
|
||||
SkBaseDevice* SkBaseDevice::createCompatibleDevice(SkBitmap::Config config,
|
||||
int width, int height,
|
||||
bool isOpaque) {
|
||||
@ -105,14 +58,6 @@ SkBaseDevice* SkBaseDevice::createCompatibleDeviceForSaveLayer(SkBitmap::Config
|
||||
isOpaque, kSaveLayer_Usage);
|
||||
}
|
||||
|
||||
SkBaseDevice* SkBitmapDevice::onCreateCompatibleDevice(SkBitmap::Config config,
|
||||
int width, int height,
|
||||
bool isOpaque,
|
||||
Usage usage) {
|
||||
return SkNEW_ARGS(SkBitmapDevice,(config, width, height, isOpaque,
|
||||
this->getDeviceProperties()));
|
||||
}
|
||||
|
||||
SkMetaData& SkBaseDevice::getMetaData() {
|
||||
// metadata users are rare, so we lazily allocate it. If that changes we
|
||||
// can decide to just make it a field in the device (rather than a ptr)
|
||||
@ -122,18 +67,6 @@ SkMetaData& SkBaseDevice::getMetaData() {
|
||||
return *fMetaData;
|
||||
}
|
||||
|
||||
void SkBitmapDevice::lockPixels() {
|
||||
if (fBitmap.lockPixelsAreWritable()) {
|
||||
fBitmap.lockPixels();
|
||||
}
|
||||
}
|
||||
|
||||
void SkBitmapDevice::unlockPixels() {
|
||||
if (fBitmap.lockPixelsAreWritable()) {
|
||||
fBitmap.unlockPixels();
|
||||
}
|
||||
}
|
||||
|
||||
const SkBitmap& SkBaseDevice::accessBitmap(bool changePixels) {
|
||||
const SkBitmap& bitmap = this->onAccessBitmap();
|
||||
if (changePixels) {
|
||||
@ -142,38 +75,6 @@ const SkBitmap& SkBaseDevice::accessBitmap(bool changePixels) {
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
void SkBitmapDevice::getGlobalBounds(SkIRect* bounds) const {
|
||||
if (bounds) {
|
||||
const SkIPoint& origin = this->getOrigin();
|
||||
bounds->setXYWH(origin.x(), origin.y(),
|
||||
fBitmap.width(), fBitmap.height());
|
||||
}
|
||||
}
|
||||
|
||||
void SkBitmapDevice::clear(SkColor color) {
|
||||
fBitmap.eraseColor(color);
|
||||
}
|
||||
|
||||
const SkBitmap& SkBitmapDevice::onAccessBitmap() {
|
||||
return fBitmap;
|
||||
}
|
||||
|
||||
bool SkBitmapDevice::canHandleImageFilter(SkImageFilter*) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SkBitmapDevice::filterImage(SkImageFilter* filter, const SkBitmap& src,
|
||||
const SkMatrix& ctm, SkBitmap* result,
|
||||
SkIPoint* offset) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SkBitmapDevice::allowImageFilter(SkImageFilter*) {
|
||||
return true;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool SkBaseDevice::readPixels(SkBitmap* bitmap, int x, int y,
|
||||
SkCanvas::Config8888 config8888) {
|
||||
if (SkBitmap::kARGB_8888_Config != bitmap->config() ||
|
||||
@ -218,315 +119,3 @@ bool SkBaseDevice::readPixels(SkBitmap* bitmap, int x, int y,
|
||||
return result;
|
||||
}
|
||||
|
||||
#if SK_PMCOLOR_BYTE_ORDER(B,G,R,A)
|
||||
const SkCanvas::Config8888 SkBaseDevice::kPMColorAlias =
|
||||
SkCanvas::kBGRA_Premul_Config8888;
|
||||
#elif SK_PMCOLOR_BYTE_ORDER(R,G,B,A)
|
||||
const SkCanvas::Config8888 SkBaseDevice::kPMColorAlias =
|
||||
SkCanvas::kRGBA_Premul_Config8888;
|
||||
#else
|
||||
const SkCanvas::Config8888 SkBaseDevice::kPMColorAlias =
|
||||
(SkCanvas::Config8888) -1;
|
||||
#endif
|
||||
|
||||
#include <SkConfig8888.h>
|
||||
|
||||
bool SkBitmapDevice::onReadPixels(const SkBitmap& bitmap,
|
||||
int x, int y,
|
||||
SkCanvas::Config8888 config8888) {
|
||||
SkASSERT(SkBitmap::kARGB_8888_Config == bitmap.config());
|
||||
SkASSERT(!bitmap.isNull());
|
||||
SkASSERT(SkIRect::MakeWH(this->width(), this->height()).contains(SkIRect::MakeXYWH(x, y, bitmap.width(), bitmap.height())));
|
||||
|
||||
SkIRect srcRect = SkIRect::MakeXYWH(x, y, bitmap.width(),
|
||||
bitmap.height());
|
||||
const SkBitmap& src = this->accessBitmap(false);
|
||||
|
||||
SkBitmap subset;
|
||||
if (!src.extractSubset(&subset, srcRect)) {
|
||||
return false;
|
||||
}
|
||||
if (SkBitmap::kARGB_8888_Config != subset.config()) {
|
||||
// It'd be preferable to do this directly to bitmap.
|
||||
subset.copyTo(&subset, SkBitmap::kARGB_8888_Config);
|
||||
}
|
||||
SkAutoLockPixels alp(bitmap);
|
||||
uint32_t* bmpPixels = reinterpret_cast<uint32_t*>(bitmap.getPixels());
|
||||
SkCopyBitmapToConfig8888(bmpPixels, bitmap.rowBytes(), config8888, subset);
|
||||
return true;
|
||||
}
|
||||
|
||||
void SkBitmapDevice::writePixels(const SkBitmap& bitmap,
|
||||
int x, int y,
|
||||
SkCanvas::Config8888 config8888) {
|
||||
if (bitmap.isNull() || bitmap.getTexture()) {
|
||||
return;
|
||||
}
|
||||
const SkBitmap* sprite = &bitmap;
|
||||
// check whether we have to handle a config8888 that doesn't match SkPMColor
|
||||
if (SkBitmap::kARGB_8888_Config == bitmap.config() &&
|
||||
SkCanvas::kNative_Premul_Config8888 != config8888 &&
|
||||
kPMColorAlias != config8888) {
|
||||
|
||||
// We're going to have to convert from a config8888 to the native config
|
||||
// First we clip to the device bounds.
|
||||
SkBitmap dstBmp = this->accessBitmap(true);
|
||||
SkIRect spriteRect = SkIRect::MakeXYWH(x, y,
|
||||
bitmap.width(), bitmap.height());
|
||||
SkIRect devRect = SkIRect::MakeWH(dstBmp.width(), dstBmp.height());
|
||||
if (!spriteRect.intersect(devRect)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// write directly to the device if it has pixels and is SkPMColor
|
||||
bool drawSprite;
|
||||
if (SkBitmap::kARGB_8888_Config == dstBmp.config() && !dstBmp.isNull()) {
|
||||
// we can write directly to the dst when doing the conversion
|
||||
dstBmp.extractSubset(&dstBmp, spriteRect);
|
||||
drawSprite = false;
|
||||
} else {
|
||||
// we convert to a temporary bitmap and draw that as a sprite
|
||||
dstBmp.setConfig(SkBitmap::kARGB_8888_Config,
|
||||
spriteRect.width(),
|
||||
spriteRect.height());
|
||||
if (!dstBmp.allocPixels()) {
|
||||
return;
|
||||
}
|
||||
drawSprite = true;
|
||||
}
|
||||
|
||||
// copy pixels to dstBmp and convert from config8888 to native config.
|
||||
SkAutoLockPixels alp(bitmap);
|
||||
uint32_t* srcPixels = bitmap.getAddr32(spriteRect.fLeft - x,
|
||||
spriteRect.fTop - y);
|
||||
SkCopyConfig8888ToBitmap(dstBmp,
|
||||
srcPixels,
|
||||
bitmap.rowBytes(),
|
||||
config8888);
|
||||
|
||||
if (drawSprite) {
|
||||
// we've clipped the sprite when we made a copy
|
||||
x = spriteRect.fLeft;
|
||||
y = spriteRect.fTop;
|
||||
sprite = &dstBmp;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SkPaint paint;
|
||||
paint.setXfermodeMode(SkXfermode::kSrc_Mode);
|
||||
SkRasterClip clip(SkIRect::MakeWH(fBitmap.width(), fBitmap.height()));
|
||||
SkDraw draw;
|
||||
draw.fRC = &clip;
|
||||
draw.fClip = &clip.bwRgn();
|
||||
draw.fBitmap = &fBitmap; // canvas should have already called accessBitmap
|
||||
draw.fMatrix = &SkMatrix::I();
|
||||
this->drawSprite(draw, *sprite, x, y, paint);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void SkBitmapDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) {
|
||||
draw.drawPaint(paint);
|
||||
}
|
||||
|
||||
void SkBitmapDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, size_t count,
|
||||
const SkPoint pts[], const SkPaint& paint) {
|
||||
CHECK_FOR_NODRAW_ANNOTATION(paint);
|
||||
draw.drawPoints(mode, count, pts, paint);
|
||||
}
|
||||
|
||||
void SkBitmapDevice::drawRect(const SkDraw& draw, const SkRect& r, const SkPaint& paint) {
|
||||
CHECK_FOR_NODRAW_ANNOTATION(paint);
|
||||
draw.drawRect(r, paint);
|
||||
}
|
||||
|
||||
void SkBitmapDevice::drawOval(const SkDraw& draw, const SkRect& oval, const SkPaint& paint) {
|
||||
CHECK_FOR_NODRAW_ANNOTATION(paint);
|
||||
|
||||
SkPath path;
|
||||
path.addOval(oval);
|
||||
// call the VIRTUAL version, so any subclasses who do handle drawPath aren't
|
||||
// required to override drawOval.
|
||||
this->drawPath(draw, path, paint, NULL, true);
|
||||
}
|
||||
|
||||
void SkBitmapDevice::drawRRect(const SkDraw& draw, const SkRRect& rrect, const SkPaint& paint) {
|
||||
CHECK_FOR_NODRAW_ANNOTATION(paint);
|
||||
|
||||
SkPath path;
|
||||
path.addRRect(rrect);
|
||||
// call the VIRTUAL version, so any subclasses who do handle drawPath aren't
|
||||
// required to override drawRRect.
|
||||
this->drawPath(draw, path, paint, NULL, true);
|
||||
}
|
||||
|
||||
void SkBitmapDevice::drawPath(const SkDraw& draw, const SkPath& path,
|
||||
const SkPaint& paint, const SkMatrix* prePathMatrix,
|
||||
bool pathIsMutable) {
|
||||
CHECK_FOR_NODRAW_ANNOTATION(paint);
|
||||
draw.drawPath(path, paint, prePathMatrix, pathIsMutable);
|
||||
}
|
||||
|
||||
void SkBitmapDevice::drawBitmap(const SkDraw& draw, const SkBitmap& bitmap,
|
||||
const SkMatrix& matrix, const SkPaint& paint) {
|
||||
draw.drawBitmap(bitmap, matrix, paint);
|
||||
}
|
||||
|
||||
void SkBitmapDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap,
|
||||
const SkRect* src, const SkRect& dst,
|
||||
const SkPaint& paint,
|
||||
SkCanvas::DrawBitmapRectFlags flags) {
|
||||
SkMatrix matrix;
|
||||
SkRect bitmapBounds, tmpSrc, tmpDst;
|
||||
SkBitmap tmpBitmap;
|
||||
|
||||
bitmapBounds.isetWH(bitmap.width(), bitmap.height());
|
||||
|
||||
// Compute matrix from the two rectangles
|
||||
if (src) {
|
||||
tmpSrc = *src;
|
||||
} else {
|
||||
tmpSrc = bitmapBounds;
|
||||
}
|
||||
matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit);
|
||||
|
||||
const SkRect* dstPtr = &dst;
|
||||
const SkBitmap* bitmapPtr = &bitmap;
|
||||
|
||||
// clip the tmpSrc to the bounds of the bitmap, and recompute dstRect if
|
||||
// needed (if the src was clipped). No check needed if src==null.
|
||||
if (src) {
|
||||
if (!bitmapBounds.contains(*src)) {
|
||||
if (!tmpSrc.intersect(bitmapBounds)) {
|
||||
return; // nothing to draw
|
||||
}
|
||||
// recompute dst, based on the smaller tmpSrc
|
||||
matrix.mapRect(&tmpDst, tmpSrc);
|
||||
dstPtr = &tmpDst;
|
||||
}
|
||||
|
||||
// since we may need to clamp to the borders of the src rect within
|
||||
// the bitmap, we extract a subset.
|
||||
SkIRect srcIR;
|
||||
tmpSrc.roundOut(&srcIR);
|
||||
if (!bitmap.extractSubset(&tmpBitmap, srcIR)) {
|
||||
return;
|
||||
}
|
||||
bitmapPtr = &tmpBitmap;
|
||||
|
||||
// Since we did an extract, we need to adjust the matrix accordingly
|
||||
SkScalar dx = 0, dy = 0;
|
||||
if (srcIR.fLeft > 0) {
|
||||
dx = SkIntToScalar(srcIR.fLeft);
|
||||
}
|
||||
if (srcIR.fTop > 0) {
|
||||
dy = SkIntToScalar(srcIR.fTop);
|
||||
}
|
||||
if (dx || dy) {
|
||||
matrix.preTranslate(dx, dy);
|
||||
}
|
||||
|
||||
SkRect extractedBitmapBounds;
|
||||
extractedBitmapBounds.isetWH(bitmapPtr->width(), bitmapPtr->height());
|
||||
if (extractedBitmapBounds == tmpSrc) {
|
||||
// no fractional part in src, we can just call drawBitmap
|
||||
goto USE_DRAWBITMAP;
|
||||
}
|
||||
} else {
|
||||
USE_DRAWBITMAP:
|
||||
// We can go faster by just calling drawBitmap, which will concat the
|
||||
// matrix with the CTM, and try to call drawSprite if it can. If not,
|
||||
// it will make a shader and call drawRect, as we do below.
|
||||
this->drawBitmap(draw, *bitmapPtr, matrix, paint);
|
||||
return;
|
||||
}
|
||||
|
||||
// construct a shader, so we can call drawRect with the dst
|
||||
SkShader* s = SkShader::CreateBitmapShader(*bitmapPtr,
|
||||
SkShader::kClamp_TileMode,
|
||||
SkShader::kClamp_TileMode);
|
||||
if (NULL == s) {
|
||||
return;
|
||||
}
|
||||
s->setLocalMatrix(matrix);
|
||||
|
||||
SkPaint paintWithShader(paint);
|
||||
paintWithShader.setStyle(SkPaint::kFill_Style);
|
||||
paintWithShader.setShader(s)->unref();
|
||||
|
||||
// Call ourself, in case the subclass wanted to share this setup code
|
||||
// but handle the drawRect code themselves.
|
||||
this->drawRect(draw, *dstPtr, paintWithShader);
|
||||
}
|
||||
|
||||
void SkBitmapDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap,
|
||||
int x, int y, const SkPaint& paint) {
|
||||
draw.drawSprite(bitmap, x, y, paint);
|
||||
}
|
||||
|
||||
void SkBitmapDevice::drawText(const SkDraw& draw, const void* text, size_t len,
|
||||
SkScalar x, SkScalar y, const SkPaint& paint) {
|
||||
draw.drawText((const char*)text, len, x, y, paint);
|
||||
}
|
||||
|
||||
void SkBitmapDevice::drawPosText(const SkDraw& draw, const void* text, size_t len,
|
||||
const SkScalar xpos[], SkScalar y,
|
||||
int scalarsPerPos, const SkPaint& paint) {
|
||||
draw.drawPosText((const char*)text, len, xpos, y, scalarsPerPos, paint);
|
||||
}
|
||||
|
||||
void SkBitmapDevice::drawTextOnPath(const SkDraw& draw, const void* text,
|
||||
size_t len, const SkPath& path,
|
||||
const SkMatrix* matrix,
|
||||
const SkPaint& paint) {
|
||||
draw.drawTextOnPath((const char*)text, len, path, matrix, paint);
|
||||
}
|
||||
|
||||
#ifdef SK_BUILD_FOR_ANDROID
|
||||
void SkBitmapDevice::drawPosTextOnPath(const SkDraw& draw, const void* text, size_t len,
|
||||
const SkPoint pos[], const SkPaint& paint,
|
||||
const SkPath& path, const SkMatrix* matrix) {
|
||||
draw.drawPosTextOnPath((const char*)text, len, pos, paint, path, matrix);
|
||||
}
|
||||
#endif
|
||||
|
||||
void SkBitmapDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode,
|
||||
int vertexCount,
|
||||
const SkPoint verts[], const SkPoint textures[],
|
||||
const SkColor colors[], SkXfermode* xmode,
|
||||
const uint16_t indices[], int indexCount,
|
||||
const SkPaint& paint) {
|
||||
draw.drawVertices(vmode, vertexCount, verts, textures, colors, xmode,
|
||||
indices, indexCount, paint);
|
||||
}
|
||||
|
||||
void SkBitmapDevice::drawDevice(const SkDraw& draw, SkBaseDevice* device,
|
||||
int x, int y, const SkPaint& paint) {
|
||||
const SkBitmap& src = device->accessBitmap(false);
|
||||
draw.drawSprite(src, x, y, paint);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool SkBitmapDevice::filterTextFlags(const SkPaint& paint, TextFlags* flags) {
|
||||
if (!paint.isLCDRenderText() || !paint.isAntiAlias()) {
|
||||
// we're cool with the paint as is
|
||||
return false;
|
||||
}
|
||||
|
||||
if (SkBitmap::kARGB_8888_Config != fBitmap.config() ||
|
||||
paint.getRasterizer() ||
|
||||
paint.getPathEffect() ||
|
||||
paint.isFakeBoldText() ||
|
||||
paint.getStyle() != SkPaint::kFill_Style ||
|
||||
!SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrcOver_Mode)) {
|
||||
// turn off lcd
|
||||
flags->fFlags = paint.getFlags() & ~SkPaint::kLCDRenderText_Flag;
|
||||
flags->fHinting = paint.getHinting();
|
||||
return true;
|
||||
}
|
||||
// we're cool with the paint as is
|
||||
return false;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user