diff options
author | reed@android.com <reed@android.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2010-12-20 18:26:13 +0000 |
---|---|---|
committer | reed@android.com <reed@android.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2010-12-20 18:26:13 +0000 |
commit | f2b98d67dcb6fcb3120feede9c72016fc7b3ead8 (patch) | |
tree | d78b57945b29865dcdeb1badbb360575289b292d /src | |
parent | 29e5054dd07c97c2195c5f64bf67aaa6b5afa204 (diff) |
merge with changes for GPU backend
git-svn-id: http://skia.googlecode.com/svn/trunk@637 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src')
29 files changed, 1331 insertions, 423 deletions
diff --git a/src/core/SkBitmapProcShader.cpp b/src/core/SkBitmapProcShader.cpp index 3c7be4c8b8..1eaa46d4d9 100644 --- a/src/core/SkBitmapProcShader.cpp +++ b/src/core/SkBitmapProcShader.cpp @@ -44,8 +44,10 @@ void SkBitmapProcShader::endSession() { this->INHERITED::endSession(); } -bool SkBitmapProcShader::asABitmap(SkBitmap* texture, SkMatrix* texM, - TileMode xy[]) { +SkShader::BitmapType SkBitmapProcShader::asABitmap(SkBitmap* texture, + SkMatrix* texM, + TileMode xy[], + SkScalar* twoPointRadialParams) { if (texture) { *texture = fRawBitmap; } @@ -56,7 +58,7 @@ bool SkBitmapProcShader::asABitmap(SkBitmap* texture, SkMatrix* texM, xy[0] = (TileMode)fState.fTileModeX; xy[1] = (TileMode)fState.fTileModeY; } - return true; + return kDefault_BitmapType; } void SkBitmapProcShader::flatten(SkFlattenableWriteBuffer& buffer) { @@ -82,7 +84,7 @@ bool SkBitmapProcShader::setContext(const SkBitmap& device, fState.fOrigBitmap = fRawBitmap; fState.fOrigBitmap.lockPixels(); - if (!fState.fOrigBitmap.readyToDraw()) { + if (!fState.fOrigBitmap.getTexture() && !fState.fOrigBitmap.readyToDraw()) { fState.fOrigBitmap.unlockPixels(); return false; } diff --git a/src/core/SkBitmapProcShader.h b/src/core/SkBitmapProcShader.h index 09d53afe1d..88598fc1fb 100644 --- a/src/core/SkBitmapProcShader.h +++ b/src/core/SkBitmapProcShader.h @@ -32,7 +32,8 @@ public: virtual void shadeSpan16(int x, int y, uint16_t dstC[], int count); virtual void beginSession(); virtual void endSession(); - virtual bool asABitmap(SkBitmap*, SkMatrix*, TileMode*); + virtual BitmapType asABitmap(SkBitmap*, SkMatrix*, TileMode*, + SkScalar* twoPointRadialParams); static bool CanDo(const SkBitmap&, TileMode tx, TileMode ty); diff --git a/src/core/SkBlitter_ARGB32.cpp b/src/core/SkBlitter_ARGB32.cpp index 905ab6b0b8..88b9491e4c 100644 --- a/src/core/SkBlitter_ARGB32.cpp +++ b/src/core/SkBlitter_ARGB32.cpp @@ -40,6 +40,32 @@ using namespace skia_blitter_support; ////////////////////////////////////////////////////////////////////////////////////// +static void SkARGB32_Blit32(const SkBitmap& device, const SkMask& mask, + const SkIRect& clip, SkPMColor srcColor) { + U8CPU alpha = SkGetPackedA32(srcColor); + unsigned flags = SkBlitRow::kSrcPixelAlpha_Flag32; + if (alpha != 255) { + flags |= SkBlitRow::kGlobalAlpha_Flag32; + } + SkBlitRow::Proc32 proc = SkBlitRow::Factory32(flags); + + int x = clip.fLeft; + int y = clip.fTop; + int width = clip.width(); + int height = clip.height(); + + SkPMColor* dstRow = device.getAddr32(x, y); + const SkPMColor* srcRow = reinterpret_cast<const SkPMColor*>(mask.getAddr(x, y)); + + do { + proc(dstRow, srcRow, width, alpha); + dstRow = (SkPMColor*)((char*)dstRow + device.rowBytes()); + srcRow = (const SkPMColor*)((const char*)srcRow + mask.fRowBytes); + } while (--height != 0); +} + +////////////////////////////////////////////////////////////////////////////////////// + SkARGB32_Blitter::SkARGB32_Blitter(const SkBitmap& device, const SkPaint& paint) : INHERITED(device) { uint32_t color = paint.getColor(); @@ -156,6 +182,9 @@ void SkARGB32_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) { if (mask.fFormat == SkMask::kBW_Format) { SkARGB32_BlendBW(fDevice, mask, clip, fPMColor, SkAlpha255To256(255 - fSrcA)); return; + } else if (SkMask::kARGB32_Format == mask.fFormat) { + SkARGB32_Blit32(fDevice, mask, clip, fPMColor); + return; } int x = clip.fLeft; @@ -188,7 +217,10 @@ void SkARGB32_Opaque_Blitter::blitMask(const SkMask& mask, if (mask.fFormat == SkMask::kBW_Format) { SkARGB32_BlitBW(fDevice, mask, clip, fPMColor); return; - } + } else if (SkMask::kARGB32_Format == mask.fFormat) { + SkARGB32_Blit32(fDevice, mask, clip, fPMColor); + return; + } int x = clip.fLeft; int y = clip.fTop; @@ -306,6 +338,8 @@ void SkARGB32_Black_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) { SkPMColor black = (SkPMColor)(SK_A32_MASK << SK_A32_SHIFT); SkARGB32_BlitBW(fDevice, mask, clip, black); + } else if (SkMask::kARGB32_Format == mask.fFormat) { + SkARGB32_Blit32(fDevice, mask, clip, fPMColor); } else { #if defined(SK_SUPPORT_LCDTEXT) const bool lcdMode = mask.fFormat == SkMask::kHorizontalLCD_Format; diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp index 5a855bb636..0e36c91a4b 100644 --- a/src/core/SkCanvas.cpp +++ b/src/core/SkCanvas.cpp @@ -74,6 +74,9 @@ struct DeviceCM { const SkMatrix* fMatrix; SkPaint* fPaint; // may be null (in the future) int16_t fX, fY; // relative to base matrix/clip + // optional, related to canvas' external matrix + const SkMatrix* fMVMatrix; + const SkMatrix* fExtMatrix; DeviceCM(SkDevice* device, int x, int y, const SkPaint* paint) : fNext(NULL) { @@ -132,8 +135,18 @@ struct DeviceCM { SkASSERT(deviceR.contains(fClip.getBounds())); } #endif + // default is to assume no external matrix + fMVMatrix = NULL; + fExtMatrix = NULL; } - + + // can only be called after calling updateMC() + void updateExternalMatrix(const SkMatrix& extM, const SkMatrix& extI) { + fMVMatrixStorage.setConcat(extI, *fMatrix); + fMVMatrix = &fMVMatrixStorage; + fExtMatrix = &extM; // assumes extM has long life-time (owned by canvas) + } + void translateClip() { if (fX | fY) { fClip.translate(fX, fY); @@ -141,7 +154,7 @@ struct DeviceCM { } private: - SkMatrix fMatrixStorage; + SkMatrix fMatrixStorage, fMVMatrixStorage; }; /* This is the record we keep for each save/restore level in the stack. @@ -240,16 +253,17 @@ public: fLayerX = rec->fX; fLayerY = rec->fY; fPaint = rec->fPaint; - SkDEBUGCODE(this->validate(fDevice->width(), fDevice->height());) + fMVMatrix = rec->fMVMatrix; + fExtMatrix = rec->fExtMatrix; + SkDEBUGCODE(this->validate();) fCurrLayer = rec->fNext; if (fBounder) { fBounder->setClip(fClip); } - // fCurrLayer may be NULL now - fCanvas->prepareForDeviceDraw(fDevice); + fCanvas->prepareForDeviceDraw(fDevice, *fMatrix, *fClip); return true; } return false; @@ -401,6 +415,8 @@ SkDevice* SkCanvas::init(SkDevice* device) { fMCRec->fTopLayer = fMCRec->fLayer; fMCRec->fNext = NULL; + fUseExternalMatrix = false; + return this->setDevice(device); } @@ -427,7 +443,7 @@ SkCanvas::SkCanvas(const SkBitmap& bitmap) : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) { inc_canvas(); - SkDevice* device = SkNEW_ARGS(SkDevice, (bitmap)); + SkDevice* device = SkNEW_ARGS(SkDevice, (this, bitmap, false)); fDeviceFactory = device->getDeviceFactory(); this->init(device)->unref(); } @@ -527,8 +543,8 @@ SkDevice* SkCanvas::setDevice(SkDevice* device) { return device; } -SkDevice* SkCanvas::setBitmapDevice(const SkBitmap& bitmap) { - SkDevice* device = this->setDevice(SkNEW_ARGS(SkDevice, (bitmap))); +SkDevice* SkCanvas::setBitmapDevice(const SkBitmap& bitmap, bool forLayer) { + SkDevice* device = this->setDevice(SkNEW_ARGS(SkDevice, (this, bitmap, forLayer))); device->unref(); return device; } @@ -546,8 +562,9 @@ bool SkCanvas::getViewport(SkIPoint* size) const { bool SkCanvas::setViewport(int width, int height) { if ((getDevice()->getDeviceCapabilities() & SkDevice::kGL_Capability) == 0) return false; - this->setDevice(createDevice(SkBitmap::kARGB_8888_Config, width, height, - false, false))->unref(); + + this->setDevice(this->createDevice(SkBitmap::kARGB_8888_Config, width, height, + false, false))->unref(); return true; } @@ -559,21 +576,30 @@ void SkCanvas::updateDeviceCMCache() { if (NULL == layer->fNext) { // only one layer layer->updateMC(totalMatrix, totalClip, NULL); + if (fUseExternalMatrix) { + layer->updateExternalMatrix(fExternalMatrix, + fExternalInverse); + } } else { SkRegion clip; clip = totalClip; // make a copy do { layer->updateMC(totalMatrix, clip, &clip); + if (fUseExternalMatrix) { + layer->updateExternalMatrix(fExternalMatrix, + fExternalInverse); + } } while ((layer = layer->fNext) != NULL); } fDeviceCMDirty = false; } } -void SkCanvas::prepareForDeviceDraw(SkDevice* device) { +void SkCanvas::prepareForDeviceDraw(SkDevice* device, const SkMatrix& matrix, + const SkRegion& clip) { SkASSERT(device); if (fLastDeviceToGainFocus != device) { - device->gainFocus(this); + device->gainFocus(this, matrix, clip); fLastDeviceToGainFocus = device; } } @@ -651,6 +677,9 @@ int SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint, SkIRect ir; const SkIRect& clipBounds = this->getTotalClip().getBounds(); + if (clipBounds.isEmpty()) { + return count; + } if (NULL != bounds) { SkRect r; @@ -760,7 +789,7 @@ static bool reject_bitmap(const SkBitmap& bitmap) { bitmap.width() > 32767 || bitmap.height() > 32767; } -void SkCanvas::internalDrawBitmap(const SkBitmap& bitmap, +void SkCanvas::internalDrawBitmap(const SkBitmap& bitmap, const SkIRect* srcRect, const SkMatrix& matrix, const SkPaint* paint) { if (reject_bitmap(bitmap)) { return; @@ -768,9 +797,9 @@ void SkCanvas::internalDrawBitmap(const SkBitmap& bitmap, if (NULL == paint) { SkPaint tmpPaint; - this->commonDrawBitmap(bitmap, matrix, tmpPaint); + this->commonDrawBitmap(bitmap, srcRect, matrix, tmpPaint); } else { - this->commonDrawBitmap(bitmap, matrix, *paint); + this->commonDrawBitmap(bitmap, srcRect, matrix, *paint); } } @@ -1023,13 +1052,30 @@ const SkRegion& SkCanvas::getTotalClip() const { return *fMCRec->fRegion; } -/////////////////////////////////////////////////////////////////////////////// - -SkDevice* SkCanvas::createDevice(SkBitmap::Config config, int width, - int height, bool isOpaque, bool isForLayer) { +void SkCanvas::setExternalMatrix(const SkMatrix* matrix) { + if (NULL == matrix || matrix->isIdentity()) { + if (fUseExternalMatrix) { + fDeviceCMDirty = true; + } + fUseExternalMatrix = false; + } else { + fUseExternalMatrix = true; + fDeviceCMDirty = true; // |= (fExternalMatrix != *matrix) + + fExternalMatrix = *matrix; + matrix->invert(&fExternalInverse); + } + + static bool gUseExt; + if (gUseExt != fUseExternalMatrix && false) { + gUseExt = fUseExternalMatrix; + printf("---- fUseExternalMatrix = %d\n", fUseExternalMatrix); + } +} - return fDeviceFactory->newDevice(config, width, height, isOpaque, - isForLayer); +SkDevice* SkCanvas::createDevice(SkBitmap::Config config, int width, int height, + bool isOpaque, bool forLayer) { + return fDeviceFactory->newDevice(this, config, width, height, isOpaque, forLayer); } ////////////////////////////////////////////////////////////////////////////// @@ -1116,7 +1162,7 @@ void SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, SkMatrix matrix; matrix.setTranslate(x, y); - this->internalDrawBitmap(bitmap, matrix, paint); + this->internalDrawBitmap(bitmap, NULL, matrix, paint); } void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src, @@ -1130,15 +1176,7 @@ void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src, return; } - SkBitmap tmp; // storage if we need a subset of bitmap const SkBitmap* bitmapPtr = &bitmap; - - if (NULL != src) { - if (!bitmap.extractSubset(&tmp, *src)) { - return; // extraction failed - } - bitmapPtr = &tmp; - } SkMatrix matrix; SkRect tmpSrc; @@ -1159,23 +1197,32 @@ void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src, SkIntToScalar(bitmap.height())); } matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit); - this->internalDrawBitmap(*bitmapPtr, matrix, paint); + + // ensure that src is "valid" before we pass it to our internal routines + // and to SkDevice. i.e. sure it is contained inside the original bitmap. + SkIRect tmpISrc; + if (src) { + tmpISrc.set(0, 0, bitmap.width(), bitmap.height()); + tmpISrc.intersect(*src); + src = &tmpISrc; + } + this->internalDrawBitmap(*bitmapPtr, src, matrix, paint); } void SkCanvas::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix, const SkPaint* paint) { SkDEBUGCODE(bitmap.validate();) - this->internalDrawBitmap(bitmap, matrix, paint); + this->internalDrawBitmap(bitmap, NULL, matrix, paint); } -void SkCanvas::commonDrawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix, - const SkPaint& paint) { +void SkCanvas::commonDrawBitmap(const SkBitmap& bitmap, const SkIRect* srcRect, + const SkMatrix& matrix, const SkPaint& paint) { SkDEBUGCODE(bitmap.validate();) ITER_BEGIN(paint, SkDrawFilter::kBitmap_Type) while (iter.next()) { - iter.fDevice->drawBitmap(iter, bitmap, matrix, paint); + iter.fDevice->drawBitmap(iter, bitmap, srcRect, matrix, paint); } ITER_END diff --git a/src/core/SkChunkAlloc.cpp b/src/core/SkChunkAlloc.cpp index 90a0c2ad11..e0c03a85a9 100644 --- a/src/core/SkChunkAlloc.cpp +++ b/src/core/SkChunkAlloc.cpp @@ -49,6 +49,11 @@ struct SkChunkAlloc::Block { } return block; } + + bool contains(const void* addr) const { + const char* ptr = reinterpret_cast<const char*>(addr); + return ptr >= (const char*)(this + 1) && ptr < fFreePtr; + } }; SkChunkAlloc::SkChunkAlloc(size_t minSize) @@ -139,3 +144,14 @@ size_t SkChunkAlloc::unalloc(void* ptr) { return bytes; } +bool SkChunkAlloc::contains(const void* addr) const { + const Block* block = fBlock; + while (block) { + if (block->contains(addr)) { + return true; + } + block = block->fNext; + } + return false; +} + diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp index 12efaacbaf..8df0e41d72 100644 --- a/src/core/SkDevice.cpp +++ b/src/core/SkDevice.cpp @@ -4,9 +4,20 @@ SkDeviceFactory::~SkDeviceFactory() {} -SkDevice::SkDevice() {} - -SkDevice::SkDevice(const SkBitmap& bitmap) : fBitmap(bitmap) {} +SkDevice::SkDevice(SkCanvas* canvas) : fCanvas(canvas) {} + +SkDevice::SkDevice(SkCanvas* canvas, const SkBitmap& bitmap, bool isForLayer) + : fCanvas(canvas), fBitmap(bitmap) { + // auto-allocate if we're for offscreen drawing + if (isForLayer) { + if (NULL == fBitmap.getPixels() && NULL == fBitmap.pixelRef()) { + fBitmap.allocPixels(); + if (!fBitmap.isOpaque()) { + fBitmap.eraseColor(0); + } + } + } +} void SkDevice::lockPixels() { fBitmap.lockPixels(); @@ -47,6 +58,39 @@ void SkDevice::setMatrixClip(const SkMatrix&, const SkRegion&) {} /////////////////////////////////////////////////////////////////////////////// +bool SkDevice::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) { + const SkBitmap& src = this->accessBitmap(false); + + SkIRect bounds; + bounds.set(0, 0, src.width(), src.height()); + if (!bounds.intersect(srcRect)) { + return false; + } + + SkBitmap subset; + if (!src.extractSubset(&subset, bounds)) { + return false; + } + + SkBitmap tmp; + if (!subset.copyTo(&tmp, SkBitmap::kARGB_8888_Config)) { + return false; + } + + tmp.swap(*bitmap); + return true; +} + +void SkDevice::writePixels(const SkBitmap& bitmap, int x, int y) { + SkPaint paint; + paint.setXfermodeMode(SkXfermode::kSrc_Mode); + + SkCanvas canvas(this); + canvas.drawSprite(bitmap, x, y, &paint); +} + +/////////////////////////////////////////////////////////////////////////////// + void SkDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) { draw.drawPaint(paint); } @@ -62,13 +106,24 @@ void SkDevice::drawRect(const SkDraw& draw, const SkRect& r, } void SkDevice::drawPath(const SkDraw& draw, const SkPath& path, - const SkPaint& paint) { - draw.drawPath(path, paint); + const SkPaint& paint, const SkMatrix* prePathMatrix, + bool pathIsMutable) { + draw.drawPath(path, paint, prePathMatrix, pathIsMutable); } void SkDevice::drawBitmap(const SkDraw& draw, const SkBitmap& bitmap, - const SkMatrix& matrix, const SkPaint& paint) { - draw.drawBitmap(bitmap, matrix, paint); + const SkIRect* srcRect, + const SkMatrix& matrix, const SkPaint& paint) { + SkBitmap tmp; // storage if we need a subset of bitmap + const SkBitmap* bitmapPtr = &bitmap; + + if (srcRect) { + if (!bitmap.extractSubset(&tmp, *srcRect)) { + return; // extraction failed + } + bitmapPtr = &tmp; + } + draw.drawBitmap(*bitmapPtr, matrix, paint); } void SkDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap, @@ -109,16 +164,15 @@ void SkDevice::drawDevice(const SkDraw& draw, SkDevice* device, draw.drawSprite(device->accessBitmap(false), x, y, paint); } -SkDevice* SkRasterDeviceFactory::newDevice(SkBitmap::Config config, int width, +/////////////////////////////////////////////////////////////////////////////// + +SkDevice* SkRasterDeviceFactory::newDevice(SkCanvas* canvas, + SkBitmap::Config config, int width, int height, bool isOpaque, bool isForLayer) { SkBitmap bitmap; bitmap.setConfig(config, width, height); bitmap.setIsOpaque(isOpaque); - bitmap.allocPixels(); - if (!bitmap.isOpaque()) - bitmap.eraseARGB(0, 0, 0, 0); - - return SkNEW_ARGS(SkDevice, (bitmap)); + return SkNEW_ARGS(SkDevice, (canvas, bitmap, isForLayer)); } diff --git a/src/core/SkDraw.cpp b/src/core/SkDraw.cpp index eff2b32a4c..a117ab7216 100644 --- a/src/core/SkDraw.cpp +++ b/src/core/SkDraw.cpp @@ -143,6 +143,10 @@ private: /////////////////////////////////////////////////////////////////////////////// +SkDraw::SkDraw() { + sk_bzero(this, sizeof(*this)); +} + SkDraw::SkDraw(const SkDraw& src) { memcpy(this, &src, sizeof(*this)); } @@ -276,7 +280,7 @@ static void CallBitmapXferProc(const SkBitmap& bitmap, const SkIRect& rect, } void SkDraw::drawPaint(const SkPaint& paint) const { - SkDEBUGCODE(this->validate(fBitmap->width(), fBitmap->height());) + SkDEBUGCODE(this->validate();) if (fClip->isEmpty()) { return; @@ -540,7 +544,8 @@ static bool bounder_points(SkBounder* bounder, SkCanvas::PointMode mode, #define MAX_DEV_PTS 32 void SkDraw::drawPoints(SkCanvas::PointMode mode, size_t count, - const SkPoint pts[], const SkPaint& paint) const { + const SkPoint pts[], const SkPaint& paint, + bool forceUseDevice) const { // if we're in lines mode, force count to be even if (SkCanvas::kLines_PointMode == mode) { count &= ~(size_t)1; @@ -563,7 +568,7 @@ void SkDraw::drawPoints(SkCanvas::PointMode mode, size_t count, } SkASSERT(pts != NULL); - SkDEBUGCODE(this->validate(fBitmap->width(), fBitmap->height());) + SkDEBUGCODE(this->validate();) // nothing to draw if (fClip->isEmpty() || @@ -572,7 +577,7 @@ void SkDraw::drawPoints(SkCanvas::PointMode mode, size_t count, } PtProcRec rec; - if (rec.init(mode, paint, fMatrix, fClip)) { + if (!forceUseDevice && rec.init(mode, paint, fMatrix, fClip)) { SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint); SkPoint devPts[MAX_DEV_PTS]; @@ -614,7 +619,12 @@ void SkDraw::drawPoints(SkCanvas::PointMode mode, size_t count, preMatrix.setTranslate(pts[i].fX, pts[i].fY); // pass true for the last point, since we can modify // then path then - this->drawPath(path, paint, &preMatrix, (count-1) == i); + if (fDevice) { + fDevice->drawPath(*this, path, paint, &preMatrix, + (count-1) == i); + } else { + this->drawPath(path, paint, &preMatrix, (count-1) == i); + } } } else { SkRect r; @@ -624,7 +634,11 @@ void SkDraw::drawPoints(SkCanvas::PointMode mode, size_t count, r.fTop = pts[i].fY - radius; r.fRight = r.fLeft + width; r.fBottom = r.fTop + width; - this->drawRect(r, paint); + if (fDevice) { + fDevice->drawRect(*this, r, paint); + } else { + this->drawRect(r, paint); + } } } break; @@ -639,7 +653,11 @@ void SkDraw::drawPoints(SkCanvas::PointMode mode, size_t count, for (size_t i = 0; i < count; i += inc) { path.moveTo(pts[i]); path.lineTo(pts[i+1]); - this->drawPath(path, p, NULL, true); + if (fDevice) { + fDevice->drawPath(*this, path, p, NULL, true); + } else { + this->drawPath(path, p, NULL, true); + } path.rewind(); } break; @@ -657,7 +675,7 @@ static inline SkPoint* as_rightbottom(SkRect* r) { } void SkDraw::drawRect(const SkRect& rect, const SkPaint& paint) const { - SkDEBUGCODE(this->validate(fBitmap->width(), fBitmap->height());) + SkDEBUGCODE(this->validate();) // nothing to draw if (fClip->isEmpty() || @@ -799,7 +817,7 @@ static bool map_radius(const SkMatrix& matrix, SkScalar* value) { void SkDraw::drawPath(const SkPath& origSrcPath, const SkPaint& paint, const SkMatrix* prePathMatrix, bool pathIsMutable) const { - SkDEBUGCODE(this->validate(fBitmap->width(), fBitmap->height());) + SkDEBUGCODE(this->validate();) // nothing to draw if (fClip->isEmpty() || @@ -846,7 +864,8 @@ void SkDraw::drawPath(const SkPath& origSrcPath, const SkPaint& paint, // can we approximate a thin (but not hairline) stroke with an alpha-modulated // hairline? Only if the matrix scales evenly in X and Y, and the device-width is // less than a pixel - if (paint.getStyle() == SkPaint::kStroke_Style && paint.getXfermode() == NULL) { + if (paint.isAntiAlias() && + paint.getStyle() == SkPaint::kStroke_Style && paint.getXfermode() == NULL) { SkScalar width = paint.getStrokeWidth(); if (width > 0 && map_radius(*matrix, &width)) { int scale = (int)SkScalarMul(width, 256); @@ -1024,7 +1043,7 @@ static bool clipped_out(const SkMatrix& matrix, const SkRegion& clip, void SkDraw::drawBitmap(const SkBitmap& bitmap, const SkMatrix& prematrix, const SkPaint& paint) const { - SkDEBUGCODE(this->validate(fBitmap->width(), fBitmap->height());) + SkDEBUGCODE(this->validate();) // nothing to draw if (fClip->isEmpty() || @@ -1116,7 +1135,7 @@ void SkDraw::drawBitmap(const SkBitmap& bitmap, const SkMatrix& prematrix, void SkDraw::drawSprite(const SkBitmap& bitmap, int x, int y, const SkPaint& paint) const { - SkDEBUGCODE(this->validate(fBitmap->width(), fBitmap->height());) + SkDEBUGCODE(this->validate();) // nothing to draw if (fClip->isEmpty() || @@ -1207,7 +1226,7 @@ static void measure_text(SkGlyphCache* cache, SkDrawCacheProc glyphCacheProc, void SkDraw::drawText_asPaths(const char text[], size_t byteLength, SkScalar x, SkScalar y, const SkPaint& paint) const { - SkDEBUGCODE(this->validate(fBitmap->width(), fBitmap->height());) + SkDEBUGCODE(this->validate();) SkTextToPathIter iter(text, byteLength, paint, true, true); @@ -1220,7 +1239,12 @@ void SkDraw::drawText_asPaths(const char text[], size_t byteLength, while ((iterPath = iter.next(&xpos)) != NULL) { matrix.postTranslate(xpos - prevXPos, 0); - this->drawPath(*iterPath, iter.getPaint(), &matrix, false); + const SkPaint& pnt = iter.getPaint(); + if (fDevice) { + fDevice->drawPath(*this, *iterPath, pnt, &matrix, false); + } else { + this->drawPath(*iterPath, pnt, &matrix, false); + } prevXPos = xpos; } } @@ -1275,7 +1299,10 @@ static void handle_aftertext(const SkDraw* draw, const SkPaint& paint, ////////////////////////////////////////////////////////////////////////////// static void D1G_NoBounder_RectClip(const SkDraw1Glyph& state, - const SkGlyph& glyph, int left, int top) { + SkFixed fx, SkFixed fy, + const SkGlyph& glyph) { + int left = SkFixedFloor(fx); + int top = SkFixedFloor(fy); SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0); SkASSERT(state.fClip->isRect()); SkASSERT(NULL == state.fBounder); @@ -1316,7 +1343,10 @@ static void D1G_NoBounder_RectClip(const SkDraw1Glyph& state, } static void D1G_NoBounder_RgnClip(const SkDraw1Glyph& state, - const SkGlyph& glyph, int left, int top) { + SkFixed fx, SkFixed fy, + const SkGlyph& glyph) { + int left = SkFixedFloor(fx); + int top = SkFixedFloor(fy); SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0); SkASSERT(!state.fClip->isRect()); SkASSERT(NULL == state.fBounder); @@ -1350,7 +1380,10 @@ static void D1G_NoBounder_RgnClip(const SkDraw1Glyph& state, } static void D1G_Bounder(const SkDraw1Glyph& state, - const SkGlyph& glyph, int left, int top) { + SkFixed fx, SkFixed fy, + const SkGlyph& glyph) { + int left = SkFixedFloor(fx); + int top = SkFixedFloor(fy); SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0); SkMask mask; @@ -1435,7 +1468,7 @@ void SkDraw::drawText(const char text[], size_t byteLength, SkScalar x, SkScalar y, const SkPaint& paint) const { SkASSERT(byteLength == 0 || text != NULL); - SkDEBUGCODE(this->validate(fBitmap->width(), fBitmap->height());) + SkDEBUGCODE(this->validate();) // nothing to draw if (text == NULL || byteLength == 0 || @@ -1470,14 +1503,25 @@ void SkDraw::drawText(const char text[], size_t byteLength, SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc(); - SkAutoGlyphCache autoCache(paint, fMatrix); + const SkMatrix* matrix = fMatrix; + SkFixed finalFYMask = ~0xFFFF; // trunc fy; + if (fProcs && fProcs->fD1GProc) { + // only support the fMVMatrix (for now) for the GPU case, which also + // sets the fD1GProc + if (fMVMatrix) { + matrix = fMVMatrix; + finalFYMask = ~0; // don't truncate + } + } + + SkAutoGlyphCache autoCache(paint, matrix); SkGlyphCache* cache = autoCache.getCache(); - SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint); + SkAutoBlitterChoose blitter(*fBitmap, *matrix, paint); // transform our starting point { SkPoint loc; - fMatrix->mapXY(x, y, &loc); + matrix->mapXY(x, y, &loc); x = loc.fX; y = loc.fY; } @@ -1503,30 +1547,33 @@ void SkDraw::drawText(const char text[], size_t byteLength, SkFixed fy = SkScalarToFixed(y); const char* stop = text + byteLength; + SkFixed fxMask = ~0; + SkFixed fyMask = ~0; if (paint.isSubpixelText()) { - RoundBaseline roundBaseline = computeRoundBaseline(*fMatrix); + RoundBaseline roundBaseline = computeRoundBaseline(*matrix); if (kRound_Y_Baseline == roundBaseline) { - fy = (fy + 0x8000) & ~0xFFFF; + fyMask = 0; +// fy = (fy + 0x8000) & ~0xFFFF; } else if (kRound_X_Baseline == roundBaseline) { - fx = (fx + 0x8000) & ~0xFFFF; + fxMask = 0; } - } else { - // apply the bias here, so we don't have to add 1/2 in the loop - fx += SK_Fixed1/2; - fy += SK_Fixed1/2; } + // apply the bias here, so we don't have to add 1/2 in the loop + fx += SK_FixedHalf; + fy += SK_FixedHalf; + fy &= finalFYMask; SkAutoKern autokern; SkDraw1Glyph d1g; SkDraw1Glyph::Proc proc = d1g.init(this, blitter.get(), cache); while (text < stop) { - const SkGlyph& glyph = glyphCacheProc(cache, &text, fx, fy); + const SkGlyph& glyph = glyphCacheProc(cache, &text, fx & fxMask, fy & fyMask); fx += autokern.adjust(glyph); if (glyph.fWidth) { - proc(d1g, glyph, SkFixedFloor(fx), SkFixedFloor(fy)); + proc(d1g, fx, fy, glyph); } fx += glyph.fAdvanceX; fy += glyph.fAdvanceY; @@ -1636,7 +1683,7 @@ void SkDraw::drawPosText(const char text[], size_t byteLength, SkASSERT(byteLength == 0 || text != NULL); SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); - SkDEBUGCODE(this->validate(fBitmap->width(), fBitmap->height());) + SkDEBUGCODE(this->validate();) // nothing to draw if (text == NULL || byteLength == 0 || @@ -1652,39 +1699,52 @@ void SkDraw::drawPosText(const char text[], size_t byteLength, return; } + const SkMatrix* matrix = fMatrix; + if (fProcs && fProcs->fD1GProc) { + // only support the fMVMatrix (for now) for the GPU case, which also + // sets the fD1GProc + if (fMVMatrix) { + matrix = fMVMatrix; + } + } + SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc(); - SkAutoGlyphCache autoCache(paint, fMatrix); + SkAutoGlyphCache autoCache(paint, matrix); SkGlyphCache* cache = autoCache.getCache(); - SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint); + SkAutoBlitterChoose blitter(*fBitmap, *matrix, paint); const char* stop = text + byteLength; AlignProc alignProc = pick_align_proc(paint.getTextAlign()); SkDraw1Glyph d1g; SkDraw1Glyph::Proc proc = d1g.init(this, blitter.get(), cache); - TextMapState tms(*fMatrix, constY); + TextMapState tms(*matrix, constY); TextMapState::Proc tmsProc = tms.pickProc(scalarsPerPosition); if (paint.isSubpixelText()) { // maybe we should skip the rounding if linearText is set - RoundBaseline roundBaseline = computeRoundBaseline(*fMatrix); + RoundBaseline roundBaseline = computeRoundBaseline(*matrix); if (SkPaint::kLeft_Align == paint.getTextAlign()) { while (text < stop) { + tmsProc(tms, pos); SkFixed fx = SkScalarToFixed(tms.fLoc.fX); SkFixed fy = SkScalarToFixed(tms.fLoc.fY); + SkFixed fxMask = ~0; + SkFixed fyMask = ~0; if (kRound_Y_Baseline == roundBaseline) { - fy = (fy + 0x8000) & ~0xFFFF; + fyMask = 0; } else if (kRound_X_Baseline == roundBaseline) { - fx = (fx + 0x8000) & ~0xFFFF; + fxMask = 0; } - const SkGlyph& glyph = glyphCacheProc(cache, &text, fx, fy); + const SkGlyph& glyph = glyphCacheProc(cache, &text, + fx & fxMask, fy & fyMask); if (glyph.fWidth) { - proc(d1g, glyph, SkFixedFloor(fx), SkFixedFloor(fy)); + proc(d1g, fx, fy, glyph); } pos += scalarsPerPosition; } @@ -1697,6 +1757,8 @@ void SkDraw::drawPosText(const char text[], size_t byteLength, SkDEBUGCODE(SkFixed prevAdvY = glyph->fAdvanceY;) SkFixed fx, fy; + SkFixed fxMask = ~0; + SkFixed fyMask = ~0; tmsProc(tms, pos); { @@ -1706,19 +1768,19 @@ void SkDraw::drawPosText(const char text[], size_t byteLength, fy = fixedLoc.fY; if (kRound_Y_Baseline == roundBaseline) { - fy = (fy + 0x8000) & ~0xFFFF; + fyMask = 0; } else if (kRound_X_Baseline == roundBaseline) { - fx = (fx + 0x8000) & ~0xFFFF; + fxMask = 0; } } // have to call again, now that we've been "aligned" - glyph = &glyphCacheProc(cache, &text, fx, fy); + glyph = &glyphCacheProc(cache, &text, fx & fxMask, fy & fyMask); // the assumption is that the advance hasn't changed SkASSERT(prevAdvX == glyph->fAdvanceX); SkASSERT(prevAdvY == glyph->fAdvanceY); - proc(d1g, *glyph, SkFixedFloor(fx), SkFixedFloor(fy)); + proc(d1g, fx, fy, *glyph); } pos += scalarsPerPosition; } @@ -1734,8 +1796,8 @@ void SkDraw::drawPosText(const char text[], size_t byteLength, SkIPoint fixedLoc; alignProc(tms.fLoc, glyph, &fixedLoc); - proc(d1g, glyph, - SkFixedRound(fixedLoc.fX), SkFixedRound(fixedLoc.fY)); + proc(d1g, fixedLoc.fX + SK_FixedHalf, + fixedLoc.fY + SK_FixedHalf, glyph); } pos += scalarsPerPosition; } @@ -1863,7 +1925,11 @@ void SkDraw::drawTextOnPath(const char text[], size_t byteLength, m.postConcat(*matrix); } morphpath(&tmp, *iterPath, meas, m); - this->drawPath(tmp, iter.getPaint()); + if (fDevice) { + fDevice->drawPath(*this, tmp, iter.getPaint(), NULL, true); + } else { + this->drawPath(tmp, iter.getPaint(), NULL, true); + } } } @@ -2232,7 +2298,7 @@ void SkDraw::drawVertices(SkCanvas::VertexMode vmode, int count, #ifdef SK_DEBUG -void SkDraw::validate(int width, int height) const { +void SkDraw::validate() const { SkASSERT(fBitmap != NULL); SkASSERT(fMatrix != NULL); SkASSERT(fClip != NULL); @@ -2240,8 +2306,11 @@ void SkDraw::validate(int width, int height) const { const SkIRect& cr = fClip->getBounds(); SkIRect br; - br.set(0, 0, width, height); + br.set(0, 0, fBitmap->width(), fBitmap->height()); SkASSERT(cr.isEmpty() || br.contains(cr)); + + // assert that both are null, or both are not-null + SkASSERT(!fMVMatrix == !fExtMatrix); } #endif diff --git a/src/core/SkDrawProcs.h b/src/core/SkDrawProcs.h index d64c088a30..7d69465d6a 100644 --- a/src/core/SkDrawProcs.h +++ b/src/core/SkDrawProcs.h @@ -13,7 +13,9 @@ struct SkDraw1Glyph { SkGlyphCache* fCache; SkIRect fClipBounds; - typedef void (*Proc)(const SkDraw1Glyph&, const SkGlyph&, int x, int y); + // The fixed x,y have been pre-rounded (i.e. 1/2 has already been added), + // so the impls need just trunc down to an int + typedef void (*Proc)(const SkDraw1Glyph&, SkFixed x, SkFixed y, const SkGlyph&); Proc init(const SkDraw* draw, SkBlitter* blitter, SkGlyphCache* cache); }; diff --git a/src/core/SkGlyphCache.cpp b/src/core/SkGlyphCache.cpp index c744dfe540..199ac14761 100644 --- a/src/core/SkGlyphCache.cpp +++ b/src/core/SkGlyphCache.cpp @@ -96,22 +96,7 @@ SkGlyphCache::~SkGlyphCache() { /////////////////////////////////////////////////////////////////////////////// #ifdef SK_DEBUG -class AutoCheckForNull { -public: - AutoCheckForNull(const SkTDArray<SkGlyph*>& array) : fArray(array) { - for (int i = 0; i < array.count(); i++) - SkASSERT(array[i]); - } - ~AutoCheckForNull() { - const SkTDArray<SkGlyph*>& array = fArray; - for (int i = 0; i < array.count(); i++) { - SkASSERT(array[i]); - } - } -private: - const SkTDArray<SkGlyph*>& fArray; -}; -#define VALIDATE() AutoCheckForNull acfn(fGlyphArray) +#define VALIDATE() AutoValidate av(this) #else #define VALIDATE() #endif @@ -288,9 +273,7 @@ SkGlyph* SkGlyphCache::lookupMetrics(uint32_t id, MetricsType mtype) { glyph = (SkGlyph*)fGlyphAlloc.alloc(sizeof(SkGlyph), SkChunkAlloc::kThrow_AllocFailType); - glyph->fID = id; - glyph->fImage = NULL; - glyph->fPath = NULL; + glyph->init(id); *fGlyphArray.insert(hi) = glyph; if (kJustAdvance_MetricsType == mtype) { @@ -519,6 +502,9 @@ SkGlyphCache* SkGlyphCache::VisitCache(const SkDescriptor* desc, cache = SkNEW_ARGS(SkGlyphCache, (desc)); FOUND_IT: + + AutoValidate av(cache); + if (proc(cache, context)) { // stay detached if (insideMutex) { SkASSERT(globals.fTotalMemoryUsed >= cache->fMemoryUsed); @@ -549,6 +535,7 @@ void SkGlyphCache::AttachCache(SkGlyphCache* cache) { SkAutoMutexAcquire ac(globals.fMutex); globals.validate(); + cache->validate(); // if we have a fixed budget for our cache, do a purge here { @@ -664,3 +651,19 @@ size_t SkGlyphCache::InternalFreeCache(SkGlyphCache_Globals* globals, return bytesFreed; } +/////////////////////////////////////////////////////////////////////////////// +#ifdef SK_DEBUG + +void SkGlyphCache::validate() const { + int count = fGlyphArray.count(); + for (int i = 0; i < count; i++) { + const SkGlyph* glyph = fGlyphArray[i]; + SkASSERT(glyph); + SkASSERT(fGlyphAlloc.contains(glyph)); + if (glyph->fImage) { + SkASSERT(fImageAlloc.contains(glyph->fImage)); + } + } +} + +#endif diff --git a/src/core/SkGlyphCache.h b/src/core/SkGlyphCache.h index cc81ed6aa7..16330f87a4 100644 --- a/src/core/SkGlyphCache.h +++ b/src/core/SkGlyphCache.h @@ -91,7 +91,9 @@ public: const SkPaint::FontMetrics& getFontMetricsY() const { return fFontMetricsY; } - + + const SkDescriptor& getDescriptor() const { return *fDesc; } + /* AuxProc/Data allow a client to associate data with this cache entry. Multiple clients can use this, as their data is keyed with a function pointer. In addition to serving as a key, the function pointer is called @@ -154,6 +156,31 @@ public: */ static bool SetCacheUsed(size_t bytesUsed); +#ifdef SK_DEBUG + void validate() const; +#else + void validate() const {} +#endif + + class AutoValidate : SkNoncopyable { + public: + AutoValidate(const SkGlyphCache* cache) : fCache(cache) { + if (fCache) { + fCache->validate(); + } + } + ~AutoValidate() { + if (fCache) { + fCache->validate(); + } + } + void forget() { + fCache = NULL; + } + private: + const SkGlyphCache* fCache; + }; + private: SkGlyphCache(const SkDescriptor*); ~SkGlyphCache(); diff --git a/src/core/SkMatrix.cpp b/src/core/SkMatrix.cpp index e85c6ece4e..f2d1708114 100644 --- a/src/core/SkMatrix.cpp +++ b/src/core/SkMatrix.cpp @@ -1595,8 +1595,10 @@ uint32_t SkMatrix::flatten(void* buffer) const { } uint32_t SkMatrix::unflatten(const void* buffer) { - memcpy(fMat, buffer, 9 * sizeof(SkScalar)); - this->setTypeMask(kUnknown_Mask); + if (buffer) { + memcpy(fMat, buffer, 9 * sizeof(SkScalar)); + this->setTypeMask(kUnknown_Mask); + } return 9 * sizeof(SkScalar); } diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp index 88d924b4c0..d4c5b833ba 100644 --- a/src/core/SkPaint.cpp +++ b/src/core/SkPaint.cpp @@ -1209,6 +1209,11 @@ static SkPaint::Hinting computeHinting(const SkPaint& paint) { return h; } +static SkScalar sk_relax(SkScalar x) { + int n = sk_float_round2int(x * 1024); + return n / 1024.0f; +} + void SkScalerContext::MakeRec(const SkPaint& paint, const SkMatrix* deviceMatrix, Rec* rec) { @@ -1222,10 +1227,10 @@ void SkScalerContext::MakeRec(const SkPaint& paint, if (deviceMatrix) { - rec->fPost2x2[0][0] = deviceMatrix->getScaleX(); - rec->fPost2x2[0][1] = deviceMatrix->getSkewX(); - rec->fPost2x2[1][0] = deviceMatrix->getSkewY(); - rec->fPost2x2[1][1] = deviceMatrix->getScaleY(); + rec->fPost2x2[0][0] = sk_relax(deviceMatrix->getScaleX()); + rec->fPost2x2[0][1] = sk_relax(deviceMatrix->getSkewX()); + rec->fPost2x2[1][0] = sk_relax(deviceMatrix->getSkewY()); + rec->fPost2x2[1][1] = sk_relax(deviceMatrix->getScaleY()); } else { diff --git a/src/core/SkScalerContext.cpp b/src/core/SkScalerContext.cpp index b149be92ce..983f1addcc 100644 --- a/src/core/SkScalerContext.cpp +++ b/src/core/SkScalerContext.cpp @@ -344,7 +344,9 @@ void SkScalerContext::getMetrics(SkGlyph* glyph) { } } - glyph->fMaskFormat = fRec.fMaskFormat; + if (SkMask::kARGB32_Format != glyph->fMaskFormat) { + glyph->fMaskFormat = fRec.fMaskFormat; + } if (fMaskFilter) { SkMask src, dst; @@ -668,9 +670,14 @@ protected: } }; +extern SkScalerContext* SkCreateColorScalerContext(const SkDescriptor* desc); + SkScalerContext* SkScalerContext::Create(const SkDescriptor* desc) { - SkScalerContext* c = SkFontHost::CreateScalerContext(desc); + SkScalerContext* c = NULL; //SkCreateColorScalerContext(desc); + if (NULL == c) { + c = SkFontHost::CreateScalerContext(desc); + } if (NULL == c) { c = SkNEW_ARGS(SkScalerContext_Empty, (desc)); } diff --git a/src/core/SkShader.cpp b/src/core/SkShader.cpp index 34dc32e0ec..7b3a024c4f 100644 --- a/src/core/SkShader.cpp +++ b/src/core/SkShader.cpp @@ -17,6 +17,7 @@ #include "SkShader.h" #include "SkPaint.h" +#include "SkMallocPixelRef.h" SkShader::SkShader() : fLocalMatrix(NULL) { SkDEBUGCODE(fInSession = false;) @@ -195,8 +196,9 @@ SkShader::MatrixClass SkShader::ComputeMatrixClass(const SkMatrix& mat) { ////////////////////////////////////////////////////////////////////////////// -bool SkShader::asABitmap(SkBitmap*, SkMatrix*, TileMode*) { - return false; +SkShader::BitmapType SkShader::asABitmap(SkBitmap*, SkMatrix*, + TileMode*, SkScalar*) { + return kNone_BitmapType; } SkShader* SkShader::CreateBitmapShader(const SkBitmap& src, @@ -209,9 +211,28 @@ SkShader* SkShader::CreateBitmapShader(const SkBitmap& src, #include "SkColorShader.h" #include "SkUtils.h" +SkColorShader::SkColorShader() { + fFlags = 0; + fInheritColor = true; + fAsABitmapPixelRef = NULL; +} + +SkColorShader::SkColorShader(SkColor c) { + fFlags = 0; + fColor = c; + fInheritColor = false; + fAsABitmapPixelRef = NULL; +} + +SkColorShader::~SkColorShader() { + SkSafeUnref(fAsABitmapPixelRef); +} + SkColorShader::SkColorShader(SkFlattenableReadBuffer& b) : INHERITED(b) { fFlags = 0; // computed in setContext - fInheritColor = b.readU8(); + fAsABitmapPixelRef = NULL; + + fInheritColor = b.readU8(); if (fInheritColor) { return; } @@ -285,3 +306,28 @@ void SkColorShader::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) { memset(alpha, SkGetPackedA32(fPMColor), count); } +// if we had a asAColor method, that would be more efficient... +SkShader::BitmapType SkColorShader::asABitmap(SkBitmap* bitmap, SkMatrix* matrix, + TileMode modes[], + SkScalar* twoPointRadialParams) { + // we cache the pixelref, since its generateID is used in the texture cache + if (NULL == fAsABitmapPixelRef) { + SkPMColor* storage = (SkPMColor*)sk_malloc_throw(sizeof(SkPMColor)); + *storage = fPMColor; + fAsABitmapPixelRef = new SkMallocPixelRef(storage, sizeof(SkPMColor), + NULL); + } + + if (bitmap) { + bitmap->setConfig(SkBitmap::kARGB_8888_Config, 1, 1); + bitmap->setPixelRef(fAsABitmapPixelRef); + } + if (matrix) { + matrix->reset(); + } + if (modes) { + modes[0] = modes[1] = SkShader::kRepeat_TileMode; + } + return kDefault_BitmapType; +} + diff --git a/src/core/SkStroke.cpp b/src/core/SkStroke.cpp index 1fb25a6d9a..c35400b515 100644 --- a/src/core/SkStroke.cpp +++ b/src/core/SkStroke.cpp @@ -633,6 +633,10 @@ void SkStroke::strokePath(const SkPath& src, SkPath* dst) const { if (fDoFill) { dst->addPath(src); + } else { + if (src.countPoints() == 2) { + dst->setIsConvex(true); + } } } diff --git a/src/core/SkTextFormatParams.h b/src/core/SkTextFormatParams.h new file mode 100644 index 0000000000..3306270788 --- /dev/null +++ b/src/core/SkTextFormatParams.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SkTextFormatParams_DEFINES +#define SkTextFormatParams_DEFINES + +#include "SkScalar.h" +#include "SkTypes.h" + +// Fraction of the text size to lower a strike through line below the baseline. +#define kStdStrikeThru_Offset (-SK_Scalar1 * 6 / 21) +// Fraction of the text size to lower a underline below the baseline. +#define kStdUnderline_Offset (SK_Scalar1 / 9) +// Fraction of the text size to use for a strike through or under-line. +#define kStdUnderline_Thickness (SK_Scalar1 / 18) + +// The fraction of text size to embolden fake bold text scales with text size. +// At 9 points or below, the stroke width is increased by text size / 24. +// At 36 points and above, it is increased by text size / 32. In between, +// it is interpolated between those values. +static const SkScalar kStdFakeBoldInterpKeys[] = { + SkIntToScalar(9), + SkIntToScalar(36) +}; +static const SkScalar kStdFakeBoldInterpValues[] = { + SK_Scalar1/24, + SK_Scalar1/32 +}; +SK_COMPILE_ASSERT(SK_ARRAY_COUNT(kStdFakeBoldInterpKeys) == + SK_ARRAY_COUNT(kStdFakeBoldInterpValues), + mismatched_array_size); +static const int kStdFakeBoldInterpLength = + SK_ARRAY_COUNT(kStdFakeBoldInterpKeys); + +#endif //SkTextFormatParams_DEFINES diff --git a/src/core/SkUtils.cpp b/src/core/SkUtils.cpp index a88233f412..9fb85c2939 100644 --- a/src/core/SkUtils.cpp +++ b/src/core/SkUtils.cpp @@ -124,7 +124,7 @@ void sk_memset32_portable(uint32_t dst[], uint32_t value, int count) } } -#ifndef ANDROID +#if !defined(ANDROID) || defined(SK_BUILD_FOR_ANDROID_NDK) static void sk_memset16_stub(uint16_t dst[], uint16_t value, int count) { SkMemset16Proc proc = SkMemset16GetPlatformProc(); diff --git a/src/core/core_files.mk b/src/core/core_files.mk index af7b876859..235fa76ac2 100644 --- a/src/core/core_files.mk +++ b/src/core/core_files.mk @@ -72,6 +72,7 @@ SOURCE := \ SkRect.cpp \ SkRefCnt.cpp \ SkRegion.cpp \ + SkRegion_rects.cpp \ SkRegion_path.cpp \ SkScalar.cpp \ SkScalerContext.cpp \ diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp index cc65413328..9aefd0a258 100644 --- a/src/pdf/SkPDFDevice.cpp +++ b/src/pdf/SkPDFDevice.cpp @@ -118,16 +118,23 @@ void alignText(SkDrawCacheProc glyphCacheProc, const SkPaint& paint, //////////////////////////////////////////////////////////////////////////////// -SkDevice* SkPDFDeviceFactory::newDevice(SkBitmap::Config config, - int width, int height, - bool isOpaque, bool isForLayer) { +SkDevice* SkPDFDeviceFactory::newDevice(SkCanvas*, SkBitmap::Config config, + int width, int height, bool isOpaque, + bool /*isForLayer*/) { return SkNEW_ARGS(SkPDFDevice, (width, height)); } +static inline SkBitmap makeABitmap(int width, int height) { + SkBitmap bitmap; + bitmap.setConfig(SkBitmap::kNo_Config, width, height); + return bitmap; +} + SkPDFDevice::SkPDFDevice(int width, int height) : fWidth(width), fHeight(height), - fGraphicStackIndex(0) { + fGraphicStackIndex(0), + SkDevice(NULL, makeABitmap(width, height), false) { fGraphicStack[0].fColor = SK_ColorBLACK; fGraphicStack[0].fTextSize = SK_ScalarNaN; // This has no default value. fGraphicStack[0].fTextScaleX = SK_Scalar1; @@ -271,7 +278,10 @@ void SkPDFDevice::drawPath(const SkDraw& d, const SkPath& path, } void SkPDFDevice::drawBitmap(const SkDraw&, const SkBitmap& bitmap, + const SkIRect* srcRect, const SkMatrix& matrix, const SkPaint& paint) { + // TODO: respect srcRect if present + SkMatrix transform = matrix; transform.postConcat(fGraphicStack[fGraphicStackIndex].fTransform); internalDrawBitmap(transform, bitmap, paint); diff --git a/src/pdf/pdf_files.mk b/src/pdf/pdf_files.mk index 8d721eb816..149e802c2a 100644 --- a/src/pdf/pdf_files.mk +++ b/src/pdf/pdf_files.mk @@ -8,4 +8,4 @@ SOURCE := \ SkPDFImage.cpp \ SkPDFPage.cpp \ SkPDFStream.cpp \ - SkPDFTypes.cpp \ + SkPDFTypes.cpp diff --git a/src/utils/SkProxyCanvas.cpp b/src/utils/SkProxyCanvas.cpp index c643c8277e..d462d01b12 100644 --- a/src/utils/SkProxyCanvas.cpp +++ b/src/utils/SkProxyCanvas.cpp @@ -18,14 +18,6 @@ bool SkProxyCanvas::getViewport(SkIPoint* size) const { return fProxy->getViewport(size); } -bool SkProxyCanvas::setViewport(int x, int y) { - return fProxy->setViewport(x, y); -} - -SkDevice* SkProxyCanvas::setBitmapDevice(const SkBitmap& bitmap) { - return fProxy->setBitmapDevice(bitmap); -} - int SkProxyCanvas::save(SaveFlags flags) { return fProxy->save(flags); } @@ -163,8 +155,8 @@ SkDrawFilter* SkProxyCanvas::setDrawFilter(SkDrawFilter* filter) { return fProxy->setDrawFilter(filter); } -SkDevice* SkProxyCanvas::createDevice(SkBitmap::Config config, int width, - int height, bool isOpaque, bool isForLayer) { +SkDevice* SkProxyCanvas::createDevice(SkBitmap::Config config, int width, int height, + bool isOpaque, bool isForLayer) { return fProxy->createDevice(config, width, height, isOpaque, isForLayer); } diff --git a/src/utils/mac/SkCreateCGImageRef.cpp b/src/utils/mac/SkCreateCGImageRef.cpp index 5c96e21ff6..2169bc09cb 100644 --- a/src/utils/mac/SkCreateCGImageRef.cpp +++ b/src/utils/mac/SkCreateCGImageRef.cpp @@ -26,22 +26,19 @@ static SkBitmap* prepareForImageRef(const SkBitmap& bm, *bitsPerComponent = 8; #if defined(SK_CPU_LENDIAN) && HAS_ARGB_SHIFTS(24, 0, 8, 16) \ || defined(SK_CPU_BENDIAN) && HAS_ARGB_SHIFTS(0, 24, 16, 8) - *info = kCGBitmapByteOrder32Big | - kCGImageAlphaPremultipliedLast; + *info = kCGBitmapByteOrder32Big; #elif defined(SK_CPU_LENDIAN) && HAS_ARGB_SHIFTS(24, 16, 8, 0) \ || defined(SK_CPU_BENDIAN) && HAS_ARGB_SHIFTS(24, 16, 8, 0) // Matches the CGBitmapInfo that Apple recommends for best // performance, used by google chrome. - *info = kCGBitmapByteOrder32Host | - kCGImageAlphaPremultipliedFirst; + *info = kCGBitmapByteOrder32Little; #else // ...add more formats as required... #warning Cannot convert SkBitmap to CGImageRef with these shiftmasks. \ This will probably not work. // Legacy behavior. Perhaps turn this into an error at some // point. - *info = kCGBitmapByteOrder32Big | - kCGImageAlphaPremultipliedLast; + *info = kCGBitmapByteOrder32Big; #endif break; #if 0 @@ -59,6 +56,10 @@ static SkBitmap* prepareForImageRef(const SkBitmap& bm, return NULL; } + if (!bm.isOpaque()) { + *info |= kCGImageAlphaPremultipliedLast; + } + SkBitmap* copy; if (upscaleTo32) { copy = new SkBitmap; @@ -93,7 +94,7 @@ CGImageRef SkCreateCGImageRef(const SkBitmap& bm) { CGDataProviderRef dataRef = CGDataProviderCreateWithData(bitmap, bitmap->getPixels(), s, SkBitmap_ReleaseInfo); - CGColorSpaceRef space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); + CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB(); CGImageRef ref = CGImageCreate(w, h, bitsPerComponent, bitmap->bytesPerPixel() * 8, bitmap->rowBytes(), space, info, dataRef, @@ -103,4 +104,23 @@ CGImageRef SkCreateCGImageRef(const SkBitmap& bm) { return ref; } +void SkCGDrawBitmap(CGContextRef cg, const SkBitmap& bm, float x, float y) { + CGImageRef img = SkCreateCGImageRef(bm); + + if (img) { + CGRect r = CGRectMake(0, 0, bm.width(), bm.height()); + + CGContextSaveGState(cg); + CGContextTranslateCTM(cg, x, r.size.height + y); + CGContextScaleCTM(cg, 1, -1); + + CGContextDrawImage(cg, r, img); + + CGContextRestoreGState(cg); + + CGImageRelease(img); + } +} + + diff --git a/src/utils/mac/SkOSWindow_Mac.cpp b/src/utils/mac/SkOSWindow_Mac.cpp index eb07e2aa73..6828a955f0 100644 --- a/src/utils/mac/SkOSWindow_Mac.cpp +++ b/src/utils/mac/SkOSWindow_Mac.cpp @@ -2,6 +2,8 @@ #if defined(SK_BUILD_FOR_MAC) && !defined(SK_USE_WXWIDGETS) +#include <AGL/agl.h> + #include <Carbon/Carbon.h> #include "SkCGUtils.h" @@ -82,7 +84,7 @@ static void set_axisposition(HIAxisPosition* pos, HIViewRef parent, HIPositionKi pos->offset = 0; } -SkOSWindow::SkOSWindow(void* hWnd) : fHWND(hWnd) +SkOSWindow::SkOSWindow(void* hWnd) : fHWND(hWnd), fAGLCtx(NULL) { OSStatus result; WindowRef wr = (WindowRef)hWnd; @@ -450,5 +452,79 @@ void SkEvent::SignalQueueTimer(SkMSec delay) } } +AGLContext create_gl(WindowRef wref, bool offscreen) +{ + GLint major, minor; + AGLContext ctx; + + aglGetVersion(&major, &minor); + SkDebugf("---- agl version %d %d\n", major, minor); + + const GLint pixelAttrs[] = { + AGL_RGBA, + AGL_STENCIL_SIZE, 8, + AGL_SAMPLE_BUFFERS_ARB, 1, + AGL_MULTISAMPLE, + AGL_SAMPLES_ARB, 2, + (offscreen ? AGL_OFFSCREEN : AGL_ACCELERATED), + (offscreen ? AGL_NONE : AGL_DOUBLEBUFFER), + AGL_NONE + }; + AGLPixelFormat format = aglChoosePixelFormat(NULL, 0, pixelAttrs); + //AGLPixelFormat format = aglCreatePixelFormat(pixelAttrs); + SkDebugf("----- agl format %p\n", format); + ctx = aglCreateContext(format, NULL); + SkDebugf("----- agl context %p\n", ctx); + aglDestroyPixelFormat(format); + + static const GLint interval = 1; + aglSetInteger(ctx, AGL_SWAP_INTERVAL, &interval); + aglSetCurrentContext(ctx); + return ctx; +} + +bool SkOSWindow::attachGL(const SkBitmap* offscreen) +{ + if (NULL == fAGLCtx) { + fAGLCtx = create_gl((WindowRef)fHWND, NULL != offscreen); + if (NULL == fAGLCtx) { + return false; + } + } + + GLboolean success = true; + + if (offscreen) { + success = aglSetOffScreen((AGLContext)fAGLCtx, + offscreen->width(), + offscreen->height(), + offscreen->rowBytes(), + offscreen->getPixels()); + } else { + success = aglSetWindowRef((AGLContext)fAGLCtx, (WindowRef)fHWND); + } + + GLenum err = aglGetError(); + if (err) { + SkDebugf("---- setoffscreen %d %d %s [%d %d]\n", success, err, + aglErrorString(err), offscreen->width(), offscreen->height()); + } + + if (success) { + glClearColor(0, 0, 0, 0); + glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + } + return success; +} + +void SkOSWindow::detachGL() { + aglSetWindowRef((AGLContext)fAGLCtx, NULL); +} + +void SkOSWindow::presentGL() { + aglSwapBuffers((AGLContext)fAGLCtx); + glFlush(); +} + #endif diff --git a/src/utils/win/SkOSWindow_Win.cpp b/src/utils/win/SkOSWindow_Win.cpp index 376c3bdfda..26993be661 100644 --- a/src/utils/win/SkOSWindow_Win.cpp +++ b/src/utils/win/SkOSWindow_Win.cpp @@ -1,213 +1,569 @@ -#include "SkTypes.h"
-
-#if defined(SK_BUILD_FOR_WIN)
-
-#include "SkWindow.h"
-#include "SkCanvas.h"
-#include "SkOSMenu.h"
-#include "SkTime.h"
-
-#include "SkGraphics.h"
-
-static SkOSWindow* gCurrOSWin;
-
-SkOSWindow::SkOSWindow(void* hWnd) : fHWND(hWnd) {
-}
-
-static SkKey winToskKey(WPARAM vk) {
- static const struct {
- WPARAM fVK;
- SkKey fKey;
- } gPair[] = {
- { VK_BACK, kBack_SkKey },
- { VK_CLEAR, kBack_SkKey },
- { VK_RETURN, kOK_SkKey },
- { VK_UP, kUp_SkKey },
- { VK_DOWN, kDown_SkKey },
- { VK_LEFT, kLeft_SkKey },
- { VK_RIGHT, kRight_SkKey }
- };
- for (size_t i = 0; i < SK_ARRAY_COUNT(gPair); i++) {
- if (gPair[i].fVK == vk) {
- return gPair[i].fKey;
- }
- }
- return kNONE_SkKey;
-}
-
-bool SkOSWindow::wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
- switch (message) {
- case WM_KEYDOWN: {
- SkKey key = winToskKey(wParam);
- if (kNONE_SkKey != key) {
- this->handleKey(key);
- return true;
- }
- } break;
- case WM_KEYUP: {
- SkKey key = winToskKey(wParam);
- if (kNONE_SkKey != key) {
- this->handleKeyUp(key);
- return true;
- }
- } break;
- case WM_UNICHAR:
- this->handleChar(lParam);
- return true;
- case WM_SIZE:
- this->resize(lParam & 0xFFFF, lParam >> 16);
- break;
- case WM_PAINT: {
- PAINTSTRUCT ps;
- HDC hdc = BeginPaint(hWnd, &ps);
- this->doPaint(hdc);
- EndPaint(hWnd, &ps);
- return true;
- } break;
- }
- return false;
-}
-
-void SkOSWindow::doPaint(void* ctx) {
- this->update(NULL);
-
- HDC hdc = (HDC)ctx;
- const SkBitmap& bitmap = this->getBitmap();
-
- BITMAPINFO bmi;
- memset(&bmi, 0, sizeof(bmi));
- bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- bmi.bmiHeader.biWidth = bitmap.width();
- bmi.bmiHeader.biHeight = -bitmap.height(); // top-down image
- bmi.bmiHeader.biPlanes = 1;
- bmi.bmiHeader.biBitCount = 32;
- bmi.bmiHeader.biCompression = BI_RGB;
- bmi.bmiHeader.biSizeImage = 0;
-
- //
- // Do the SetDIBitsToDevice.
- //
- bitmap.lockPixels();
- int iRet = SetDIBitsToDevice(hdc,
- 0, 0,
- bitmap.width(), bitmap.height(),
- 0, 0,
- 0, bitmap.height(),
- bitmap.getPixels(),
- &bmi,
- DIB_RGB_COLORS);
- bitmap.unlockPixels();
-}
-
-#if 0
-void SkOSWindow::updateSize()
-{
- RECT r;
- GetWindowRect((HWND)this->getHWND(), &r);
- this->resize(r.right - r.left, r.bottom - r.top);
-}
-#endif
-
-void SkOSWindow::onHandleInval(const SkIRect& r) {
- RECT rect;
- rect.left = r.fLeft;
- rect.top = r.fTop;
- rect.right = r.fRight;
- rect.bottom = r.fBottom;
- InvalidateRect((HWND)this->getHWND(), &rect, false);
-}
-
-void SkOSWindow::onAddMenu(const SkOSMenu* sk_menu)
-{
-}
-
-
-enum {
- SK_MacReturnKey = 36,
- SK_MacDeleteKey = 51,
- SK_MacEndKey = 119,
- SK_MacLeftKey = 123,
- SK_MacRightKey = 124,
- SK_MacDownKey = 125,
- SK_MacUpKey = 126,
-
- SK_Mac0Key = 0x52,
- SK_Mac1Key = 0x53,
- SK_Mac2Key = 0x54,
- SK_Mac3Key = 0x55,
- SK_Mac4Key = 0x56,
- SK_Mac5Key = 0x57,
- SK_Mac6Key = 0x58,
- SK_Mac7Key = 0x59,
- SK_Mac8Key = 0x5b,
- SK_Mac9Key = 0x5c
-};
-
-static SkKey raw2key(uint32_t raw)
-{
- static const struct {
- uint32_t fRaw;
- SkKey fKey;
- } gKeys[] = {
- { SK_MacUpKey, kUp_SkKey },
- { SK_MacDownKey, kDown_SkKey },
- { SK_MacLeftKey, kLeft_SkKey },
- { SK_MacRightKey, kRight_SkKey },
- { SK_MacReturnKey, kOK_SkKey },
- { SK_MacDeleteKey, kBack_SkKey },
- { SK_MacEndKey, kEnd_SkKey },
- { SK_Mac0Key, k0_SkKey },
- { SK_Mac1Key, k1_SkKey },
- { SK_Mac2Key, k2_SkKey },
- { SK_Mac3Key, k3_SkKey },
- { SK_Mac4Key, k4_SkKey },
- { SK_Mac5Key, k5_SkKey },
- { SK_Mac6Key, k6_SkKey },
- { SK_Mac7Key, k7_SkKey },
- { SK_Mac8Key, k8_SkKey },
- { SK_Mac9Key, k9_SkKey }
- };
-
- for (unsigned i = 0; i < SK_ARRAY_COUNT(gKeys); i++)
- if (gKeys[i].fRaw == raw)
- return gKeys[i].fKey;
- return kNONE_SkKey;
-}
-
-///////////////////////////////////////////////////////////////////////////////////////
-
-void SkEvent::SignalNonEmptyQueue()
-{
-// post_skmacevent();
-// SkDebugf("signal nonempty\n");
-}
-
-//static void sk_timer_proc(TMTask* rec)
-//{
-// SkEvent::ServiceQueueTimer();
-// SkDebugf("timer task fired\n");
-//}
-
-void SkEvent::SignalQueueTimer(SkMSec delay)
-{
-#if 0
- if (gTMTaskPtr)
- {
- RemoveTimeTask((QElem*)gTMTaskPtr);
- DisposeTimerUPP(gTMTaskPtr->tmAddr);
- gTMTaskPtr = nil;
- }
- if (delay)
- {
- gTMTaskPtr = &gTMTaskRec;
- memset(gTMTaskPtr, 0, sizeof(gTMTaskRec));
- gTMTaskPtr->tmAddr = NewTimerUPP(sk_timer_proc);
- OSErr err = InstallTimeTask((QElem*)gTMTaskPtr);
-// SkDebugf("installtimetask of %d returned %d\n", delay, err);
- PrimeTimeTask((QElem*)gTMTaskPtr, delay);
- }
-#endif
-}
-
-#endif
-
+#include "SkTypes.h" + +#if defined(SK_BUILD_FOR_WIN) + +#include <GL/glew.h> +#include <GL/wglew.h> +#include <GL/gl.h> +#include <d3d9.h> +#include <WindowsX.h> +#include "SkWindow.h" +#include "SkCanvas.h" +#include "SkOSMenu.h" +#include "SkTime.h" +#include "SkUtils.h" + +#include "SkGraphics.h" + +#define INVALIDATE_DELAY_MS 200 + +static SkOSWindow* gCurrOSWin; +static HWND gEventTarget; + +#define WM_EVENT_CALLBACK (WM_USER+0) + +void post_skwinevent() +{ + PostMessage(gEventTarget, WM_EVENT_CALLBACK, 0, 0); +} + +SkOSWindow::SkOSWindow(void* hWnd) : fHWND(hWnd), + fHGLRC(NULL), + fGLAttached(false), + fD3D9Device(NULL), + fD3D9Attached(FALSE) { + gEventTarget = (HWND)hWnd; +} + +SkOSWindow::~SkOSWindow() { + if (NULL != fD3D9Device) { + ((IDirect3DDevice9*)fD3D9Device)->Release(); + } + if (NULL != fHGLRC) { + wglDeleteContext((HGLRC)fHGLRC); + } +} + +static SkKey winToskKey(WPARAM vk) { + static const struct { + WPARAM fVK; + SkKey fKey; + } gPair[] = { + { VK_BACK, kBack_SkKey }, + { VK_CLEAR, kBack_SkKey }, + { VK_RETURN, kOK_SkKey }, + { VK_UP, kUp_SkKey }, + { VK_DOWN, kDown_SkKey }, + { VK_LEFT, kLeft_SkKey }, + { VK_RIGHT, kRight_SkKey } + }; + for (size_t i = 0; i < SK_ARRAY_COUNT(gPair); i++) { + if (gPair[i].fVK == vk) { + return gPair[i].fKey; + } + } + return kNONE_SkKey; +} + +bool SkOSWindow::wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { + switch (message) { + case WM_KEYDOWN: { + SkKey key = winToskKey(wParam); + if (kNONE_SkKey != key) { + this->handleKey(key); + return true; + } + } break; + case WM_KEYUP: { + SkKey key = winToskKey(wParam); + if (kNONE_SkKey != key) { + this->handleKeyUp(key); + return true; + } + } break; + case WM_UNICHAR: + this->handleChar(wParam); + return true; + case WM_CHAR: { + this->handleChar(SkUTF8_ToUnichar((char*)&wParam)); + return true; + } break; + case WM_SIZE: + this->resize(lParam & 0xFFFF, lParam >> 16); + break; + case WM_PAINT: { + PAINTSTRUCT ps; + HDC hdc = BeginPaint(hWnd, &ps); + this->doPaint(hdc); + EndPaint(hWnd, &ps); + return true; + } break; + + case WM_TIMER: { + RECT* rect = (RECT*)wParam; + InvalidateRect(hWnd, rect, FALSE); + KillTimer(hWnd, (UINT_PTR)rect); + delete rect; + return true; + } break; + + case WM_LBUTTONDOWN: + this->handleClick(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), Click::kDown_State); + return true; + + case WM_MOUSEMOVE: + this->handleClick(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), Click::kMoved_State); + return true; + + case WM_LBUTTONUP: + this->handleClick(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), Click::kUp_State); + return true; + + case WM_EVENT_CALLBACK: + if (SkEvent::ProcessEvent()) { + post_skwinevent(); + } + return true; + } + return false; +} + +void SkOSWindow::doPaint(void* ctx) { + this->update(NULL); + + if (!fGLAttached && !fD3D9Attached) + { + HDC hdc = (HDC)ctx; + const SkBitmap& bitmap = this->getBitmap(); + + BITMAPINFO bmi; + memset(&bmi, 0, sizeof(bmi)); + bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmi.bmiHeader.biWidth = bitmap.width(); + bmi.bmiHeader.biHeight = -bitmap.height(); // top-down image + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biBitCount = 32; + bmi.bmiHeader.biCompression = BI_RGB; + bmi.bmiHeader.biSizeImage = 0; + + // + // Do the SetDIBitsToDevice. + // + bitmap.lockPixels(); + int iRet = SetDIBitsToDevice(hdc, + 0, 0, + bitmap.width(), bitmap.height(), + 0, 0, + 0, bitmap.height(), + bitmap.getPixels(), + &bmi, + DIB_RGB_COLORS); + bitmap.unlockPixels(); + } +} + +#if 0 +void SkOSWindow::updateSize() +{ + RECT r; + GetWindowRect((HWND)this->getHWND(), &r); + this->resize(r.right - r.left, r.bottom - r.top); +} +#endif + +void SkOSWindow::onHandleInval(const SkIRect& r) { + RECT* rect = new RECT; + rect->left = r.fLeft; + rect->top = r.fTop; + rect->right = r.fRight; + rect->bottom = r.fBottom; + SetTimer((HWND)fHWND, (UINT_PTR)rect, INVALIDATE_DELAY_MS, NULL); +} + +void SkOSWindow::onAddMenu(const SkOSMenu* sk_menu) +{ +} + +void SkOSWindow::onSetTitle(const char title[]){ + SetWindowTextA((HWND)fHWND, title); +} + +enum { + SK_MacReturnKey = 36, + SK_MacDeleteKey = 51, + SK_MacEndKey = 119, + SK_MacLeftKey = 123, + SK_MacRightKey = 124, + SK_MacDownKey = 125, + SK_MacUpKey = 126, + + SK_Mac0Key = 0x52, + SK_Mac1Key = 0x53, + SK_Mac2Key = 0x54, + SK_Mac3Key = 0x55, + SK_Mac4Key = 0x56, + SK_Mac5Key = 0x57, + SK_Mac6Key = 0x58, + SK_Mac7Key = 0x59, + SK_Mac8Key = 0x5b, + SK_Mac9Key = 0x5c +}; + +static SkKey raw2key(uint32_t raw) +{ + static const struct { + uint32_t fRaw; + SkKey fKey; + } gKeys[] = { + { SK_MacUpKey, kUp_SkKey }, + { SK_MacDownKey, kDown_SkKey }, + { SK_MacLeftKey, kLeft_SkKey }, + { SK_MacRightKey, kRight_SkKey }, + { SK_MacReturnKey, kOK_SkKey }, + { SK_MacDeleteKey, kBack_SkKey }, + { SK_MacEndKey, kEnd_SkKey }, + { SK_Mac0Key, k0_SkKey }, + { SK_Mac1Key, k1_SkKey }, + { SK_Mac2Key, k2_SkKey }, + { SK_Mac3Key, k3_SkKey }, + { SK_Mac4Key, k4_SkKey }, + { SK_Mac5Key, k5_SkKey }, + { SK_Mac6Key, k6_SkKey }, + { SK_Mac7Key, k7_SkKey }, + { SK_Mac8Key, k8_SkKey }, + { SK_Mac9Key, k9_SkKey } + }; + + for (unsigned i = 0; i < SK_ARRAY_COUNT(gKeys); i++) + if (gKeys[i].fRaw == raw) + return gKeys[i].fKey; + return kNONE_SkKey; +} + +/////////////////////////////////////////////////////////////////////////////////////// + +void SkEvent::SignalNonEmptyQueue() +{ + post_skwinevent(); + //SkDebugf("signal nonempty\n"); +} + +static UINT_PTR gTimer; + +VOID CALLBACK sk_timer_proc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) +{ + SkEvent::ServiceQueueTimer(); + //SkDebugf("timer task fired\n"); +} + +void SkEvent::SignalQueueTimer(SkMSec delay) +{ + if (gTimer) + { + KillTimer(NULL, gTimer); + gTimer = NULL; + } + if (delay) + { + gTimer = SetTimer(NULL, 0, delay, sk_timer_proc); + //SkDebugf("SetTimer of %d returned %d\n", delay, gTimer); + } +} + +static HWND create_dummy() +{ + HMODULE module = GetModuleHandle(NULL); + HWND dummy; + RECT windowRect; + windowRect.left = 0; + windowRect.right = 8; + windowRect.top = 0; + windowRect.bottom = 8; + + WNDCLASS wc; + + wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; + wc.lpfnWndProc = (WNDPROC) DefWindowProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = module; + wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = NULL; + wc.lpszMenuName = NULL; + wc.lpszClassName = L"DummyWindow"; + + if(!RegisterClass(&wc)) + { + return 0; + } + + DWORD style, exStyle; + exStyle = WS_EX_CLIENTEDGE; + style = WS_SYSMENU; + + AdjustWindowRectEx(&windowRect, style, false, exStyle); + + if(!(dummy = CreateWindowEx(exStyle, + L"DummyWindow", + L"Dummy Window", + WS_CLIPSIBLINGS | WS_CLIPCHILDREN | style, + 0, 0, + windowRect.right-windowRect.left, + windowRect.bottom-windowRect.top, + NULL, NULL, + module, + NULL))) + { + UnregisterClass(L"Dummy Window", module); + return NULL; + } + ShowWindow(dummy, SW_HIDE); + + return dummy; +} + +void kill_dummy(HWND dummy) { + DestroyWindow(dummy); + HMODULE module = GetModuleHandle(NULL); + UnregisterClass(L"Dummy Window", module); +} + +HGLRC create_gl(HWND hwnd) { + HDC hdc; + HDC prevHDC; + HGLRC prevGLRC, glrc; + PIXELFORMATDESCRIPTOR pfd; + + static bool glewInitialized; + + prevGLRC = wglGetCurrentContext(); + prevHDC = wglGetCurrentDC(); + + int format = 0; + + // glew must be initialized after a context has been created and made current + // and we need glew already be initialized to get wglChoosePixelFormatEXT :( + // Even worse: SetPixelFormat needs to be called before the context is created + // But SetPixelFormat is only allowed to succeed once per-window. So we need to + // create a dummy window for glew in order for it to call wglGetProcAddress() to + // get wglChoosePixelFormatARB(). This is a Windows problem, not a glew problem. + if (!glewInitialized) { + ZeroMemory(&pfd, sizeof(pfd)); + pfd.nSize = sizeof(pfd); + pfd.nVersion = 1; + pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL; + pfd.iPixelType = PFD_TYPE_RGBA; + pfd.cColorBits = 32; + pfd.cDepthBits = 0; + pfd.cStencilBits = 8; + pfd.iLayerType = PFD_MAIN_PLANE; + HWND dummy = create_dummy(); + SkASSERT(NULL != dummy); + hdc = GetDC(dummy); + format = ChoosePixelFormat(hdc, &pfd); + SetPixelFormat(hdc, format, &pfd); + glrc = wglCreateContext(hdc); + SkASSERT(glrc); + wglMakeCurrent(hdc, glrc); + + GLenum err; + err = glewInit(); + SkASSERT(GLEW_OK == err); + SkASSERT(GLEW_EXT_bgra); + SkASSERT(GLEW_EXT_framebuffer_object); + SkASSERT(WGLEW_ARB_pixel_format); + glewInitialized = true; + wglMakeCurrent(hdc, NULL); + wglDeleteContext(glrc); + glrc = 0; + kill_dummy(dummy); + } + + hdc = GetDC(hwnd); + format = 0; + + GLint iattrs[] = { + WGL_DRAW_TO_WINDOW_ARB, TRUE, + WGL_DOUBLE_BUFFER_ARB, TRUE, + WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB, + WGL_SUPPORT_OPENGL_ARB, TRUE, + WGL_COLOR_BITS_ARB, 24, + WGL_STENCIL_BITS_ARB, 8, + WGL_SAMPLE_BUFFERS_ARB, TRUE, + WGL_SAMPLES_ARB, 0, + 0,0 + }; + for (int samples = 16; samples > 1; --samples) { + iattrs[15] = samples; + GLfloat fattrs[] = {0,0}; + GLuint num; + int formats[64]; + wglChoosePixelFormatARB(hdc, iattrs, fattrs, 64, formats, &num); + num = min(num,64); + for (GLuint i = 0; i < num; ++i) { + DescribePixelFormat(hdc, formats[i], sizeof(pfd), &pfd); + if (SetPixelFormat(hdc, formats[i], &pfd)) { + format = formats[i]; + break; + } + } + } + if (0 == format) { + iattrs[12] = iattrs[13] = 0; + GLfloat fattrs[] = {0,0}; + GLuint num; + wglChoosePixelFormatARB(hdc, iattrs, fattrs, 1, &format, &num); + DescribePixelFormat(hdc, format, sizeof(pfd), &pfd); + BOOL set = SetPixelFormat(hdc, format, &pfd); + SkASSERT(TRUE == set); + } + + glrc = wglCreateContext(hdc); + SkASSERT(glrc); + + wglMakeCurrent(prevHDC, prevGLRC); + return glrc; +} + +bool SkOSWindow::attachGL(const SkBitmap* offscreen) { + if (offscreen) { + printf("windows doesn't support rendering to SkBitmap"); + } + if (NULL == fHGLRC) { + fHGLRC = create_gl((HWND)fHWND); + if (NULL == fHGLRC) { + return false; + } + } + if (wglMakeCurrent(GetDC((HWND)fHWND), (HGLRC)fHGLRC)) { + glClearColor(0, 0, 0, 0); + glClear(GL_COLOR_BUFFER_BIT); + fGLAttached = true; + return true; + } + return false; +} + +void SkOSWindow::detachGL() { + wglMakeCurrent(GetDC((HWND)fHWND), 0); + fGLAttached = false; +} + +void SkOSWindow::presentGL() { + glFlush(); + SwapBuffers(GetDC((HWND)fHWND)); + glClearColor(0,0,0,0); + glClearStencil(0); + glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT); +} + +IDirect3DDevice9* create_d3d9_device(HWND hwnd) { + HRESULT hr; + + IDirect3D9* d3d9; + d3d9 = Direct3DCreate9(D3D_SDK_VERSION); + if (NULL == d3d9) { + return NULL; + } + D3DDEVTYPE devType = D3DDEVTYPE_HAL; + //D3DDEVTYPE devType = D3DDEVTYPE_REF; + DWORD qLevels; + DWORD qLevelsDepth; + D3DMULTISAMPLE_TYPE type; + for (type = D3DMULTISAMPLE_16_SAMPLES; + type >= D3DMULTISAMPLE_NONMASKABLE; --(*(DWORD*)&type)) { + hr = d3d9->CheckDeviceMultiSampleType(D3DADAPTER_DEFAULT, + devType, D3DFMT_D24S8, TRUE, + type, &qLevels); + qLevels = (hr == D3D_OK) ? qLevels : 0; + hr = d3d9->CheckDeviceMultiSampleType(D3DADAPTER_DEFAULT, + devType, D3DFMT_A8R8G8B8, TRUE, + type, &qLevelsDepth); + qLevelsDepth = (hr == D3D_OK) ? qLevelsDepth : 0; + qLevels = min(qLevels,qLevelsDepth); + if (qLevels > 0) { + break; + } + } + qLevels = 0; + IDirect3DDevice9* d3d9Device; + D3DPRESENT_PARAMETERS pres; + memset(&pres, 0, sizeof(pres)); + pres.EnableAutoDepthStencil = TRUE; + pres.AutoDepthStencilFormat = D3DFMT_D24S8; + pres.BackBufferCount = 2; + pres.BackBufferFormat = D3DFMT_A8R8G8B8; + pres.BackBufferHeight = 0; + pres.BackBufferWidth = 0; + if (qLevels > 0) { + pres.MultiSampleType = type; + pres.MultiSampleQuality = qLevels-1; + } else { + pres.MultiSampleType = D3DMULTISAMPLE_NONE; + pres.MultiSampleQuality = 0; + } + pres.SwapEffect = D3DSWAPEFFECT_DISCARD; + pres.Windowed = TRUE; + pres.hDeviceWindow = hwnd; + pres.PresentationInterval = 1; + pres.Flags = 0; + hr = d3d9->CreateDevice(D3DADAPTER_DEFAULT, + devType, + hwnd, + D3DCREATE_HARDWARE_VERTEXPROCESSING, + &pres, + &d3d9Device); + D3DERR_INVALIDCALL; + if (SUCCEEDED(hr)) { + d3d9Device->Clear(0, NULL, D3DCLEAR_TARGET, 0xFFFFFFFF, 0, 0); + return d3d9Device; + } + return NULL; +} + +// This needs some improvement. D3D doesn't have the same notion of attach/detach +// as GL. However, just allowing GDI to write to the window after creating the +// D3D device seems to work. +// We need to handle resizing. On XP and earlier Reset() will trash all our textures +// so we would need to inform the SkGpu/caches or just recreate them. On Vista+ we +// could use an IDirect3DDevice9Ex and call ResetEx() to resize without trashing +// everything. Currently we do nothing and the D3D9 image gets stretched/compressed +// when resized. + +bool SkOSWindow::attachD3D9() { + if (NULL == fD3D9Device) { + fD3D9Device = (void*) create_d3d9_device((HWND)fHWND); + } + if (NULL != fD3D9Device) { + ((IDirect3DDevice9*)fD3D9Device)->BeginScene(); + fD3D9Attached = true; + } + return fD3D9Attached; +} + +void SkOSWindow::detachD3D9() { + if (NULL != fD3D9Device) { + ((IDirect3DDevice9*)fD3D9Device)->EndScene(); + } + fD3D9Attached = false; +} + +void SkOSWindow::presentD3D9() { + if (NULL != fD3D9Device) { + HRESULT hr; + hr = ((IDirect3DDevice9*)fD3D9Device)->EndScene(); + SkASSERT(SUCCEEDED(hr)); + hr = ((IDirect3DDevice9*)d3d9Device())->Present(NULL, NULL, NULL, NULL); + SkASSERT(SUCCEEDED(hr)); + hr = ((IDirect3DDevice9*)fD3D9Device)->Clear(0,NULL,D3DCLEAR_TARGET | + D3DCLEAR_STENCIL, 0x0, 0, + 0); + SkASSERT(SUCCEEDED(hr)); + hr = ((IDirect3DDevice9*)fD3D9Device)->BeginScene(); + SkASSERT(SUCCEEDED(hr)); + } +} + + +#endif
\ No newline at end of file diff --git a/src/views/SkEvent.cpp b/src/views/SkEvent.cpp index 67549b48b5..ec4a7b47b7 100644 --- a/src/views/SkEvent.cpp +++ b/src/views/SkEvent.cpp @@ -536,6 +536,21 @@ void SkEvent::ServiceQueueTimer() SkEvent::SignalQueueTimer(time); } +int SkEvent::CountEventsOnQueue() { + SkEvent_Globals& globals = *(SkEvent_Globals*)SkGlobals::Find(SK_Event_GlobalsTag, create_globals); + globals.fEventMutex.acquire(); + + int count = 0; + const SkEvent* evt = globals.fEventQHead; + while (evt) { + count += 1; + evt = evt->fNextEvent; + } + globals.fEventMutex.release(); + + return count; +} + //////////////////////////////////////////////////////////////// void SkEvent::Init() diff --git a/src/views/SkMetaData.cpp b/src/views/SkMetaData.cpp index c366bd3fee..c871efb136 100644 --- a/src/views/SkMetaData.cpp +++ b/src/views/SkMetaData.cpp @@ -89,6 +89,10 @@ void SkMetaData::setBool(const char name[], bool value) (void)this->set(name, &value, sizeof(bool), kBool_Type, 1); } +void SkMetaData::setData(const char name[], const void* data, size_t byteCount) { + (void)this->set(name, data, sizeof(char), kData_Type, byteCount); +} + void* SkMetaData::set(const char name[], const void* data, size_t dataSize, Type type, int count) { SkASSERT(name); @@ -129,6 +133,9 @@ void* SkMetaData::set(const char name[], const void* data, size_t dataSize, Type case kBool_Type: rec->fData.fBool = *(const bool*)rec->data(); break; + case kData_Type: + rec->fData.fPtr = rec->data(); + break; default: SkASSERT(!"bad type"); break; @@ -213,6 +220,18 @@ bool SkMetaData::findBool(const char name[], bool* value) const return false; } +const void* SkMetaData::findData(const char name[], size_t* length) const { + const Rec* rec = this->find(name, kData_Type); + if (rec) { + SkASSERT(rec->fDataLen == sizeof(char)); + if (length) { + *length = rec->fDataCount; + } + return rec->data(); + } + return NULL; +} + const SkMetaData::Rec* SkMetaData::find(const char name[], Type type) const { const Rec* rec = fRec; @@ -272,6 +291,10 @@ bool SkMetaData::removeBool(const char name[]) return this->remove(name, kBool_Type); } +bool SkMetaData::removeData(const char name[]) { + return this->remove(name, kData_Type); +} + /////////////////////////////////////////////////////////////////////////////////// SkMetaData::Iter::Iter(const SkMetaData& metadata) diff --git a/src/views/SkTextBox.cpp b/src/views/SkTextBox.cpp index df7de986fa..0e31ac68e4 100644 --- a/src/views/SkTextBox.cpp +++ b/src/views/SkTextBox.cpp @@ -16,7 +16,7 @@ */ #include "SkTextBox.h" -#include "../src/core/SkGlyphCache.h" +#include "../core/SkGlyphCache.h" #include "SkUtils.h" #include "SkAutoKern.h" diff --git a/src/views/SkView.cpp b/src/views/SkView.cpp index 652eb85025..7969d3d23c 100644 --- a/src/views/SkView.cpp +++ b/src/views/SkView.cpp @@ -49,6 +49,10 @@ void SkView::setFocusableP(bool pred) this->setFlags(SkSetClearShift(fFlags, pred, kFocusable_Shift)); } +void SkView::setClipToBounds(bool pred) { + this->setFlags(SkSetClearShift(fFlags, !pred, kNoClip_Shift)); +} + void SkView::setSize(SkScalar width, SkScalar height) { width = SkMaxScalar(0, width); @@ -87,12 +91,16 @@ void SkView::draw(SkCanvas* canvas) { SkRect r; r.set(fLoc.fX, fLoc.fY, fLoc.fX + fWidth, fLoc.fY + fHeight); - if (canvas->quickReject(r, SkCanvas::kBW_EdgeType)) - return; + if (this->isClipToBounds() && + canvas->quickReject(r, SkCanvas::kBW_EdgeType)) { + return; + } SkAutoCanvasRestore as(canvas, true); - canvas->clipRect(r); + if (this->isClipToBounds()) { + canvas->clipRect(r); + } canvas->translate(fLoc.fX, fLoc.fY); if (fParent) { @@ -119,37 +127,36 @@ void SkView::draw(SkCanvas* canvas) } } -void SkView::inval(SkRect* rect) -{ - if (!this->isVisible()) - return; - - SkRect bounds; - - this->getLocalBounds(&bounds); - if (rect && !bounds.intersect(*rect)) - return; - - rect = &bounds; +void SkView::inval(SkRect* rect) { SkView* view = this; + SkRect storage; - for (;;) - { - if (view->handleInval(bounds)) - break; + for (;;) { + if (!view->isVisible()) { + return; + } + if (view->isClipToBounds()) { + SkRect bounds; + view->getLocalBounds(&bounds); + if (rect && !bounds.intersect(*rect)) { + return; + } + storage = bounds; + rect = &storage; + } + if (view->handleInval(rect)) { + return; + } - SkRect parentR; SkView* parent = view->fParent; + if (parent == NULL) { + return; + } - if (parent == NULL || !parent->isVisible()) - break; - - bounds.offset(view->fLoc.fX, view->fLoc.fY); - parent->getLocalBounds(&parentR); - if (!bounds.intersect(parentR)) - return; - - view = parent; + if (rect) { + rect->offset(view->fLoc.fX, view->fLoc.fY); + } + view = parent; } } @@ -456,7 +463,7 @@ bool SkView::onClick(Click*) { return false; } -bool SkView::handleInval(const SkRect& r) { +bool SkView::handleInval(const SkRect*) { return false; } diff --git a/src/views/SkWindow.cpp b/src/views/SkWindow.cpp index b63b81a1c0..dbc1eea242 100644 --- a/src/views/SkWindow.cpp +++ b/src/views/SkWindow.cpp @@ -1,5 +1,6 @@ #include "SkWindow.h" #include "SkCanvas.h" +#include "SkDevice.h" #include "SkOSMenu.h" #include "SkSystemEventTypes.h" #include "SkTime.h" @@ -48,6 +49,8 @@ SkWindow::SkWindow() : fFocusView(NULL) #else fConfig = SkBitmap::kARGB_8888_Config; #endif + + fMatrix.reset(); } SkWindow::~SkWindow() @@ -57,6 +60,25 @@ SkWindow::~SkWindow() fMenus.deleteAll(); } +void SkWindow::setMatrix(const SkMatrix& matrix) { + if (fMatrix != matrix) { + fMatrix = matrix; + this->inval(NULL); + } +} + +void SkWindow::preConcat(const SkMatrix& matrix) { + SkMatrix m; + m.setConcat(fMatrix, matrix); + this->setMatrix(m); +} + +void SkWindow::postConcat(const SkMatrix& matrix) { + SkMatrix m; + m.setConcat(matrix, fMatrix); + this->setMatrix(m); +} + void SkWindow::setConfig(SkBitmap::Config config) { this->resize(fBitmap.width(), fBitmap.height(), config); @@ -72,6 +94,7 @@ void SkWindow::resize(int width, int height, SkBitmap::Config config) fConfig = config; fBitmap.setConfig(config, width, height); fBitmap.allocPixels(); + fBitmap.setIsOpaque(true); this->setSize(SkIntToScalar(width), SkIntToScalar(height)); this->inval(NULL); @@ -88,25 +111,31 @@ void SkWindow::eraseRGB(U8CPU r, U8CPU g, U8CPU b) fBitmap.eraseRGB(r, g, b); } -bool SkWindow::handleInval(const SkRect& r) +bool SkWindow::handleInval(const SkRect* localR) { SkIRect ir; - r.round(&ir); + if (localR) { + SkRect devR; + SkMatrix inverse; + if (!fMatrix.invert(&inverse)) { + return false; + } + fMatrix.mapRect(&devR, *localR); + devR.round(&ir); + } else { + ir.set(0, 0, this->width(), this->height()); + } fDirtyRgn.op(ir, SkRegion::kUnion_Op); -#ifdef SK_BUILD_FOR_WIN32xxxx - if (!fWaitingOnInval) - { - fWaitingOnInval = true; - (new SkEvent(SK_EventDelayInval))->post(this->getSinkID(), 10); - } -#else this->onHandleInval(ir); -#endif return true; } +void SkWindow::forceInvalAll() { + fDirtyRgn.setRect(0, 0, this->width(), this->height()); +} + #if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN) #include <windows.h> #include <gx.h> @@ -117,7 +146,7 @@ bool SkWindow::handleInval(const SkRect& r) extern bool gEnableControlledThrow; #endif -bool SkWindow::update(SkIRect* updateArea) +bool SkWindow::update(SkIRect* updateArea, SkCanvas* canvas) { if (!fDirtyRgn.isEmpty()) { @@ -134,37 +163,49 @@ bool SkWindow::update(SkIRect* updateArea) bm.setPixels(buffer); #endif - SkCanvas canvas(bm); + SkCanvas rasterCanvas; + SkDevice* device; - canvas.clipRegion(fDirtyRgn); + if (NULL == canvas) { + canvas = &rasterCanvas; + device = new SkDevice(canvas, bm, false); + canvas->setDevice(device)->unref(); + } else { + canvas->setBitmapDevice(bm); + } + + canvas->clipRegion(fDirtyRgn); if (updateArea) *updateArea = fDirtyRgn.getBounds(); + SkAutoCanvasRestore acr(canvas, true); + canvas->concat(fMatrix); + // empty this now, so we can correctly record any inval calls that // might be made during the draw call. fDirtyRgn.setEmpty(); #ifdef TEST_BOUNDER test_bounder b(bm); - canvas.setBounder(&b); + canvas->setBounder(&b); #endif #ifdef SK_SIMULATE_FAILED_MALLOC gEnableControlledThrow = true; #endif #ifdef SK_BUILD_FOR_WIN32 - try { - this->draw(&canvas); - } - catch (...) { - } + //try { + this->draw(canvas); + //} + //catch (...) { + //} #else - this->draw(&canvas); + this->draw(canvas); #endif #ifdef SK_SIMULATE_FAILED_MALLOC gEnableControlledThrow = false; #endif #ifdef TEST_BOUNDER - canvas.setBounder(NULL); + canvas->setBounder(NULL); #endif #if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN) |