diff options
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/SkBitmapProcShader.cpp | 10 | ||||
-rw-r--r-- | src/core/SkBitmapProcShader.h | 3 | ||||
-rw-r--r-- | src/core/SkBlitter_ARGB32.cpp | 36 | ||||
-rw-r--r-- | src/core/SkCanvas.cpp | 117 | ||||
-rw-r--r-- | src/core/SkChunkAlloc.cpp | 16 | ||||
-rw-r--r-- | src/core/SkDevice.cpp | 80 | ||||
-rw-r--r-- | src/core/SkDraw.cpp | 165 | ||||
-rw-r--r-- | src/core/SkDrawProcs.h | 4 | ||||
-rw-r--r-- | src/core/SkGlyphCache.cpp | 41 | ||||
-rw-r--r-- | src/core/SkGlyphCache.h | 29 | ||||
-rw-r--r-- | src/core/SkMatrix.cpp | 6 | ||||
-rw-r--r-- | src/core/SkPaint.cpp | 13 | ||||
-rw-r--r-- | src/core/SkScalerContext.cpp | 11 | ||||
-rw-r--r-- | src/core/SkShader.cpp | 52 | ||||
-rw-r--r-- | src/core/SkStroke.cpp | 4 | ||||
-rw-r--r-- | src/core/SkTextFormatParams.h | 48 | ||||
-rw-r--r-- | src/core/SkUtils.cpp | 2 | ||||
-rw-r--r-- | src/core/core_files.mk | 1 |
18 files changed, 503 insertions, 135 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 \ |