diff options
author | Derek Sollenberger <djsollen@google.com> | 2011-04-14 09:57:06 -0400 |
---|---|---|
committer | Derek Sollenberger <djsollen@google.com> | 2011-04-14 15:01:11 -0400 |
commit | 87b8e645865f9633f410c02252a0fd3feb18f09b (patch) | |
tree | 21e2521ed6f69bf466849f7c9579c37aa6b22b06 /src | |
parent | 7f10e10e25231b613ebb242fa14ad8c924ce694f (diff) | |
download | external_skia-87b8e645865f9633f410c02252a0fd3feb18f09b.zip external_skia-87b8e645865f9633f410c02252a0fd3feb18f09b.tar.gz external_skia-87b8e645865f9633f410c02252a0fd3feb18f09b.tar.bz2 |
Skia Merge (revision 1116)
There is a companion change in external/webkit
Change-Id: I1c4110e7520bbef3f4e5f9551adb7ec79ac1e3ed
Diffstat (limited to 'src')
51 files changed, 2484 insertions, 1944 deletions
diff --git a/src/animator/SkDisplayXMLParser.cpp b/src/animator/SkDisplayXMLParser.cpp index d2775e8..a94b848 100644 --- a/src/animator/SkDisplayXMLParser.cpp +++ b/src/animator/SkDisplayXMLParser.cpp @@ -164,6 +164,14 @@ bool SkDisplayXMLParser::onAddAttributeLen(const char attrName[], const char att return false; } +#if defined(SK_BUILD_FOR_WIN32) + #define SK_strcasecmp stricmp + #define SK_strncasecmp strnicmp +#else + #define SK_strcasecmp strcasecmp + #define SK_strncasecmp strncasecmp +#endif + bool SkDisplayXMLParser::onEndElement(const char elem[]) { int parentIndex = fParents.count() - 1; @@ -199,7 +207,7 @@ bool SkDisplayXMLParser::onEndElement(const char elem[]) fParents.remove(parentIndex); } fCurrDisplayable = NULL; - if (fInInclude == false && strcasecmp(elem, "screenplay") == 0) { + if (fInInclude == false && SK_strcasecmp(elem, "screenplay") == 0) { if (fMaker.fInMovie == false) { fMaker.fEnableTime = fMaker.getAppTime(); #if defined SK_DEBUG && defined SK_DEBUG_ANIMATION_TIMING @@ -231,7 +239,7 @@ bool SkDisplayXMLParser::onStartElement(const char name[]) bool SkDisplayXMLParser::onStartElementLen(const char name[], size_t len) { fCurrDisplayable = NULL; // init so we'll ignore attributes if we exit early - if (strncasecmp(name, "screenplay", len) == 0) { + if (SK_strncasecmp(name, "screenplay", len) == 0) { fInSkia = true; if (fInInclude == false) fMaker.idsSet(name, len, &fMaker.fScreenplay); diff --git a/src/core/Makefile.am b/src/core/Makefile.am new file mode 100644 index 0000000..4adde0a --- /dev/null +++ b/src/core/Makefile.am @@ -0,0 +1,91 @@ +AM_CPPFLAGS = -I$(top_builddir)/include/core + +noinst_LIBRARIES = libskia.a +libskia_a_SOURCES = Sk64.cpp \ +SkAlphaRuns.cpp \ +SkBitmap.cpp \ +SkBitmapProcShader.cpp \ +SkBitmapProcState.cpp \ +SkBitmapProcState_matrixProcs.cpp \ +SkBitmapSampler.cpp \ +SkBitmapShader.cpp \ +SkBitmap_scroll.cpp \ +SkBlitRow_D16.cpp \ +SkBlitRow_D4444.cpp \ +SkBlitter.cpp \ +SkBlitter_4444.cpp \ +SkBlitter_A1.cpp \ +SkBlitter_A8.cpp \ +SkBlitter_ARGB32.cpp \ +SkBlitter_RGB16.cpp \ +SkBlitter_Sprite.cpp \ +SkBuffer.cpp \ +SkCanvas.cpp \ +SkChunkAlloc.cpp \ +SkColor.cpp \ +SkColorFilter.cpp \ +SkColorTable.cpp \ +SkComposeShader.cpp \ +SkConcaveToTriangles.cpp \ +SkCordic.cpp \ +skCubicClipper.cpp \ +SkDebug.cpp \ +SkDebug_stdio.cpp \ +SkDeque.cpp \ +SkDevice.cpp \ +SkDither.cpp \ +SkDraw.cpp \ +SkEdge.cpp \ +SkFilterProc.cpp \ +SkFlattenable.cpp \ +SkFloat.cpp \ +SkFloatBits.cpp \ +SkGeometry.cpp \ +SkGlobals.cpp \ +SkGlyphCache.cpp \ +SkGraphics.cpp \ +SkMMapStream.cpp \ +SkMask.cpp \ +SkMaskFilter.cpp \ +SkMath.cpp \ +SkMatrix.cpp \ +SkMemory_stdlib.cpp \ +SkPackBits.cpp \ +SkPaint.cpp \ +SkPath.cpp \ +SkPathEffect.cpp \ +SkPathHeap.cpp \ +SkPathMeasure.cpp \ +SkPicture.cpp \ +SkPictureFlat.cpp \ +SkPicturePlayback.cpp \ +SkPictureRecord.cpp \ +SkPixelRef.cpp \ +SkPoint.cpp \ +SkProcSpriteBlitter.cpp \ +SkPtrRecorder.cpp \ +SkRasterizer.cpp \ +SkRect.cpp \ +SkRefCnt.cpp \ +SkRegion.cpp \ +SkRegion_path.cpp \ +SkScalar.cpp \ +SkScalerContext.cpp \ +SkScan.cpp \ +SkScan_AntiPath.cpp \ +SkScan_Antihair.cpp \ +SkScan_Hairline.cpp \ +SkScan_Path.cpp \ +SkShader.cpp \ +SkSpriteBlitter_ARGB32.cpp \ +SkSpriteBlitter_RGB16.cpp \ +SkStream.cpp \ +SkString.cpp \ +SkStroke.cpp \ +SkStrokerPriv.cpp \ +SkTSearch.cpp \ +SkTypeface.cpp \ +SkUnPreMultiply.cpp \ +SkUtils.cpp \ +SkWriter32.cpp \ +SkXfermode.cpp diff --git a/src/core/SkAlphaRuns.cpp b/src/core/SkAlphaRuns.cpp index 46b0206..4125b58 100644 --- a/src/core/SkAlphaRuns.cpp +++ b/src/core/SkAlphaRuns.cpp @@ -17,8 +17,7 @@ #include "SkAntiRun.h" -void SkAlphaRuns::reset(int width) -{ +void SkAlphaRuns::reset(int width) { SkASSERT(width > 0); fRuns[0] = SkToS16(width); @@ -29,8 +28,7 @@ void SkAlphaRuns::reset(int width) SkDEBUGCODE(this->validate();) } -void SkAlphaRuns::Break(int16_t runs[], uint8_t alpha[], int x, int count) -{ +void SkAlphaRuns::Break(int16_t runs[], uint8_t alpha[], int x, int count) { SkASSERT(count > 0 && x >= 0); // SkAlphaRuns::BreakAt(runs, alpha, x); @@ -39,13 +37,11 @@ void SkAlphaRuns::Break(int16_t runs[], uint8_t alpha[], int x, int count) int16_t* next_runs = runs + x; uint8_t* next_alpha = alpha + x; - while (x > 0) - { + while (x > 0) { int n = runs[0]; SkASSERT(n > 0); - if (x < n) - { + if (x < n) { alpha[x] = alpha[0]; runs[0] = SkToS16(x); runs[x] = SkToS16(n - x); @@ -60,37 +56,34 @@ void SkAlphaRuns::Break(int16_t runs[], uint8_t alpha[], int x, int count) alpha = next_alpha; x = count; - for (;;) - { + for (;;) { int n = runs[0]; SkASSERT(n > 0); - if (x < n) - { + if (x < n) { alpha[x] = alpha[0]; runs[0] = SkToS16(x); runs[x] = SkToS16(n - x); break; } x -= n; - if (x <= 0) + if (x <= 0) { break; - + } runs += n; alpha += n; } } -void SkAlphaRuns::add(int x, U8CPU startAlpha, int middleCount, U8CPU stopAlpha, U8CPU maxValue) -{ +void SkAlphaRuns::add(int x, U8CPU startAlpha, int middleCount, U8CPU stopAlpha, + U8CPU maxValue) { SkASSERT(middleCount >= 0); SkASSERT(x >= 0 && x + (startAlpha != 0) + middleCount + (stopAlpha != 0) <= fWidth); int16_t* runs = fRuns; uint8_t* alpha = fAlpha; - if (startAlpha) - { + if (startAlpha) { SkAlphaRuns::Break(runs, alpha, x, 1); /* I should be able to just add alpha[x] + startAlpha. However, if the trailing edge of the previous span and the leading @@ -106,8 +99,8 @@ void SkAlphaRuns::add(int x, U8CPU startAlpha, int middleCount, U8CPU stopAlpha, x = 0; SkDEBUGCODE(this->validate();) } - if (middleCount) - { + + if (middleCount) { SkAlphaRuns::Break(runs, alpha, x, middleCount); alpha += x; runs += x; @@ -122,8 +115,8 @@ void SkAlphaRuns::add(int x, U8CPU startAlpha, int middleCount, U8CPU stopAlpha, } while (middleCount > 0); SkDEBUGCODE(this->validate();) } - if (stopAlpha) - { + + if (stopAlpha) { SkAlphaRuns::Break(runs, alpha, x, 1); alpha[x] = SkToU8(alpha[x] + stopAlpha); SkDEBUGCODE(this->validate();) @@ -131,49 +124,44 @@ void SkAlphaRuns::add(int x, U8CPU startAlpha, int middleCount, U8CPU stopAlpha, } #ifdef SK_DEBUG - void SkAlphaRuns::assertValid(int y, int maxStep) const - { + void SkAlphaRuns::assertValid(int y, int maxStep) const { int max = (y + 1) * maxStep - (y == maxStep - 1); const int16_t* runs = fRuns; const uint8_t* alpha = fAlpha; - while (*runs) - { + while (*runs) { SkASSERT(*alpha <= max); alpha += *runs; runs += *runs; } } - void SkAlphaRuns::dump() const - { + void SkAlphaRuns::dump() const { const int16_t* runs = fRuns; const uint8_t* alpha = fAlpha; SkDebugf("Runs"); - while (*runs) - { + while (*runs) { int n = *runs; SkDebugf(" %02x", *alpha); - if (n > 1) + if (n > 1) { SkDebugf(",%d", n); + } alpha += n; runs += n; } SkDebugf("\n"); } - void SkAlphaRuns::validate() const - { + void SkAlphaRuns::validate() const { SkASSERT(fWidth > 0); int count = 0; const int16_t* runs = fRuns; - while (*runs) - { + while (*runs) { SkASSERT(*runs > 0); count += *runs; SkASSERT(count <= fWidth); diff --git a/src/core/SkAntiRun.h b/src/core/SkAntiRun.h index 12930e6..89e5481 100644 --- a/src/core/SkAntiRun.h +++ b/src/core/SkAntiRun.h @@ -20,151 +20,29 @@ #include "SkBlitter.h" -inline int sk_make_nonzero_neg_one(int x) -{ - return (x | -x) >> 31; -} - -#if 0 -template <int kShift> class SkAntiRun { - static uint8_t coverage_to_alpha(int aa) - { - aa <<= 8 - 2*kShift; - aa -= aa >> (8 - kShift - 1); - return SkToU8(aa); - } -public: - void set(int start, int stop) - { - SkASSERT(start >= 0 && stop > start); - -#if 1 - int fb = start & kMask; - int fe = stop & kMask; - int n = (stop >> kShift) - (start >> kShift) - 1; - - if (n < 0) - { - fb = fe - fb; - n = 0; - fe = 0; - } - else - { - if (fb == 0) - n += 1; - else - fb = (1 << kShift) - fb; - } - - fStartAlpha = coverage_to_alpha(fb); - fMiddleCount = n; - fStopAlpha = coverage_to_alpha(fe); -#else - int x0 = start >> kShift; - int x1 = (stop - 1) >> kShift; - int middle = x1 - x0; - int aa; - - if (middle == 0) - { - aa = stop - start; - aa <<= 8 - 2*kShift; - aa -= aa >> (8 - kShift - 1); - SkASSERT(aa > 0 && aa < kMax); - fStartAlpha = SkToU8(aa); - fMiddleCount = 0; - fStopAlpha = 0; - } - else - { - int aa = start & kMask; - aa <<= 8 - 2*kShift; - aa -= aa >> (8 - kShift - 1); - SkASSERT(aa >= 0 && aa < kMax); - if (aa) - fStartAlpha = SkToU8(kMax - aa); - else - { - fStartAlpha = 0; - middle += 1; - } - aa = stop & kMask; - aa <<= 8 - 2*kShift; - aa -= aa >> (8 - kShift - 1); - SkASSERT(aa >= 0 && aa < kMax); - middle += sk_make_nonzero_neg_one(aa); - - fStopAlpha = SkToU8(aa); - fMiddleCount = middle; - } - SkASSERT(fStartAlpha < kMax); - SkASSERT(fStopAlpha < kMax); -#endif - } - - void blit(int x, int y, SkBlitter* blitter) - { - int16_t runs[2]; - runs[0] = 1; - runs[1] = 0; - - if (fStartAlpha) - { - blitter->blitAntiH(x, y, &fStartAlpha, runs); - x += 1; - } - if (fMiddleCount) - { - blitter->blitH(x, y, fMiddleCount); - x += fMiddleCount; - } - if (fStopAlpha) - blitter->blitAntiH(x, y, &fStopAlpha, runs); - } - - uint8_t getStartAlpha() const { return fStartAlpha; } - int getMiddleCount() const { return fMiddleCount; } - uint8_t getStopAlpha() const { return fStopAlpha; } - -private: - uint8_t fStartAlpha, fStopAlpha; - int fMiddleCount; - - enum { - kMask = (1 << kShift) - 1, - kMax = (1 << (8 - kShift)) - 1 - }; -}; -#endif - -//////////////////////////////////////////////////////////////////////////////////// - class SkAlphaRuns { public: int16_t* fRuns; uint8_t* fAlpha; - bool empty() const - { + bool empty() const { SkASSERT(fRuns[0] > 0); return fAlpha[0] == 0 && fRuns[fRuns[0]] == 0; } + void reset(int width); void add(int x, U8CPU startAlpha, int middleCount, U8CPU stopAlpha, U8CPU maxValue); SkDEBUGCODE(void assertValid(int y, int maxStep) const;) SkDEBUGCODE(void dump() const;) static void Break(int16_t runs[], uint8_t alpha[], int x, int count); - static void BreakAt(int16_t runs[], uint8_t alpha[], int x) - { - while (x > 0) - { + + static void BreakAt(int16_t runs[], uint8_t alpha[], int x) { + while (x > 0) { int n = runs[0]; SkASSERT(n > 0); - if (x < n) - { + if (x < n) { alpha[x] = alpha[0]; runs[0] = SkToS16(x); runs[x] = SkToS16(n - x); diff --git a/src/core/SkBitmap.cpp b/src/core/SkBitmap.cpp index a5f7d57..c19e84d 100644 --- a/src/core/SkBitmap.cpp +++ b/src/core/SkBitmap.cpp @@ -865,61 +865,79 @@ bool SkBitmap::copyTo(SkBitmap* dst, Config dstConfig, Allocator* alloc) const { return false; } + // if we have a texture, first get those pixels + SkBitmap tmpSrc; + const SkBitmap* src = this; + + if (fPixelRef && fPixelRef->readPixels(&tmpSrc)) { + SkASSERT(tmpSrc.width() == this->width()); + SkASSERT(tmpSrc.height() == this->height()); + + // did we get lucky and we can just return tmpSrc? + if (tmpSrc.config() == dstConfig && NULL == alloc) { + dst->swap(tmpSrc); + return true; + } + + // fall through to the raster case + src = &tmpSrc; + } + // we lock this now, since we may need its colortable - SkAutoLockPixels srclock(*this); - if (!this->readyToDraw()) { + SkAutoLockPixels srclock(*src); + if (!src->readyToDraw()) { return false; } - - SkBitmap tmp; - tmp.setConfig(dstConfig, this->width(), this->height()); - + + SkBitmap tmpDst; + tmpDst.setConfig(dstConfig, src->width(), src->height()); + // allocate colortable if srcConfig == kIndex8_Config SkColorTable* ctable = (dstConfig == kIndex8_Config) ? - new SkColorTable(*this->getColorTable()) : NULL; + new SkColorTable(*src->getColorTable()) : NULL; SkAutoUnref au(ctable); - if (!tmp.allocPixels(alloc, ctable)) { + if (!tmpDst.allocPixels(alloc, ctable)) { return false; } - - SkAutoLockPixels dstlock(tmp); - if (!tmp.readyToDraw()) { + + SkAutoLockPixels dstlock(tmpDst); + if (!tmpDst.readyToDraw()) { // allocator/lock failed return false; } - + /* do memcpy for the same configs cases, else use drawing */ - if (this->config() == dstConfig) { - if (tmp.getSize() == this->getSize()) { - memcpy(tmp.getPixels(), this->getPixels(), this->getSafeSize()); + if (src->config() == dstConfig) { + if (tmpDst.getSize() == src->getSize()) { + memcpy(tmpDst.getPixels(), src->getPixels(), src->getSafeSize()); } else { - const char* srcP = reinterpret_cast<const char*>(this->getPixels()); - char* dstP = reinterpret_cast<char*>(tmp.getPixels()); + const char* srcP = reinterpret_cast<const char*>(src->getPixels()); + char* dstP = reinterpret_cast<char*>(tmpDst.getPixels()); // to be sure we don't read too much, only copy our logical pixels - size_t bytesToCopy = tmp.width() * tmp.bytesPerPixel(); - for (int y = 0; y < tmp.height(); y++) { + size_t bytesToCopy = tmpDst.width() * tmpDst.bytesPerPixel(); + for (int y = 0; y < tmpDst.height(); y++) { memcpy(dstP, srcP, bytesToCopy); - srcP += this->rowBytes(); - dstP += tmp.rowBytes(); + srcP += src->rowBytes(); + dstP += tmpDst.rowBytes(); } } } else { // if the src has alpha, we have to clear the dst first - if (!this->isOpaque()) { - tmp.eraseColor(0); + if (!src->isOpaque()) { + tmpDst.eraseColor(0); } - SkCanvas canvas(tmp); + SkCanvas canvas(tmpDst); SkPaint paint; paint.setDither(true); - canvas.drawBitmap(*this, 0, 0, &paint); + canvas.drawBitmap(*src, 0, 0, &paint); } - tmp.setIsOpaque(this->isOpaque()); + tmpDst.setIsOpaque(src->isOpaque()); - dst->swap(tmp); + dst->swap(tmpDst); return true; } diff --git a/src/core/SkBlitter_4444.cpp b/src/core/SkBlitter_4444.cpp index e1c519a..d976f2d 100644 --- a/src/core/SkBlitter_4444.cpp +++ b/src/core/SkBlitter_4444.cpp @@ -41,7 +41,8 @@ class SkARGB4444_Blitter : public SkRasterBlitter { public: SkARGB4444_Blitter(const SkBitmap& device, const SkPaint& paint); virtual void blitH(int x, int y, int width); - virtual void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]); + virtual void blitAntiH(int x, int y, const SkAlpha antialias[], + const int16_t runs[]); virtual void blitV(int x, int y, int height, SkAlpha alpha); virtual void blitRect(int x, int y, int width, int height); virtual void blitMask(const SkMask&, const SkIRect&); @@ -60,9 +61,8 @@ private: }; -SkARGB4444_Blitter::SkARGB4444_Blitter(const SkBitmap& device, const SkPaint& paint) - : INHERITED(device) -{ +SkARGB4444_Blitter::SkARGB4444_Blitter(const SkBitmap& device, + const SkPaint& paint) : INHERITED(device) { // cache premultiplied versions in 4444 SkPMColor c = SkPreMultiplyColor(paint.getColor()); fPMColor16 = SkPixel32ToPixel4444(c); @@ -82,13 +82,6 @@ SkARGB4444_Blitter::SkARGB4444_Blitter(const SkBitmap& device, const SkPaint& pa fRawColor16Other = fRawColor16; } -#if 0 /// don't think this assertion is true, but need it be? - - // our dithered color will be the same or more opaque than the original - // so use dithered to compute our scale - SkASSERT(SkGetPackedA4444(fPMColor16Other) >= SkGetPackedA4444(fPMColor16)); -#endif - fScale16 = SkAlpha15To16(SkGetPackedA4444(fPMColor16Other)); if (16 == fScale16) { // force the original to also be opaque @@ -96,8 +89,7 @@ SkARGB4444_Blitter::SkARGB4444_Blitter(const SkBitmap& device, const SkPaint& pa } } -const SkBitmap* SkARGB4444_Blitter::justAnOpaqueColor(uint32_t* value) -{ +const SkBitmap* SkARGB4444_Blitter::justAnOpaqueColor(uint32_t* value) { if (16 == fScale16) { *value = fPMColor16; return &fDevice; @@ -106,8 +98,7 @@ const SkBitmap* SkARGB4444_Blitter::justAnOpaqueColor(uint32_t* value) } static void src_over_4444(SkPMColor16 dst[], SkPMColor16 color, - SkPMColor16 other, unsigned invScale, int count) -{ + SkPMColor16 other, unsigned invScale, int count) { int twice = count >> 1; while (--twice >= 0) { *dst = color + SkAlphaMulQ4(*dst, invScale); @@ -120,15 +111,13 @@ static void src_over_4444(SkPMColor16 dst[], SkPMColor16 color, } } -static inline uint32_t SkExpand_4444_Replicate(SkPMColor16 c) -{ +static inline uint32_t SkExpand_4444_Replicate(SkPMColor16 c) { uint32_t c32 = SkExpand_4444(c); return c32 | (c32 << 4); } static void src_over_4444x(SkPMColor16 dst[], uint32_t color, - uint32_t other, unsigned invScale, int count) -{ + uint32_t other, unsigned invScale, int count) { int twice = count >> 1; uint32_t tmp; while (--twice >= 0) { @@ -143,8 +132,7 @@ static void src_over_4444x(SkPMColor16 dst[], uint32_t color, } } -void SkARGB4444_Blitter::blitH(int x, int y, int width) -{ +void SkARGB4444_Blitter::blitH(int x, int y, int width) { SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width()); if (0 == fScale16) { @@ -161,16 +149,14 @@ void SkARGB4444_Blitter::blitH(int x, int y, int width) if (16 == fScale16) { sk_dither_memset16(device, color, other, width); - } - else { + } else { src_over_4444x(device, SkExpand_4444_Replicate(color), SkExpand_4444_Replicate(other), 16 - fScale16, width); } } -void SkARGB4444_Blitter::blitV(int x, int y, int height, SkAlpha alpha) -{ +void SkARGB4444_Blitter::blitV(int x, int y, int height, SkAlpha alpha) { if (0 == alpha || 0 == fScale16) { return; } @@ -208,9 +194,9 @@ void SkARGB4444_Blitter::blitV(int x, int y, int height, SkAlpha alpha) } } -void SkARGB4444_Blitter::blitRect(int x, int y, int width, int height) -{ - SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width() && y + height <= fDevice.height()); +void SkARGB4444_Blitter::blitRect(int x, int y, int width, int height) { + SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width() && + y + height <= fDevice.height()); if (0 == fScale16) { return; @@ -243,8 +229,8 @@ void SkARGB4444_Blitter::blitRect(int x, int y, int width, int height) } } -void SkARGB4444_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]) -{ +void SkARGB4444_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[], + const int16_t runs[]) { if (0 == fScale16) { return; } @@ -295,19 +281,19 @@ void SkARGB4444_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[], cons } } -////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// #define solid_8_pixels(mask, dst, color) \ -do { \ -if (mask & 0x80) dst[0] = color; \ -if (mask & 0x40) dst[1] = color; \ -if (mask & 0x20) dst[2] = color; \ -if (mask & 0x10) dst[3] = color; \ -if (mask & 0x08) dst[4] = color; \ -if (mask & 0x04) dst[5] = color; \ -if (mask & 0x02) dst[6] = color; \ -if (mask & 0x01) dst[7] = color; \ -} while (0) + do { \ + if (mask & 0x80) dst[0] = color; \ + if (mask & 0x40) dst[1] = color; \ + if (mask & 0x20) dst[2] = color; \ + if (mask & 0x10) dst[3] = color; \ + if (mask & 0x08) dst[4] = color; \ + if (mask & 0x04) dst[5] = color; \ + if (mask & 0x02) dst[6] = color; \ + if (mask & 0x01) dst[7] = color; \ + } while (0) #define SK_BLITBWMASK_NAME SkARGB4444_BlitBW #define SK_BLITBWMASK_ARGS , SkPMColor16 color @@ -316,17 +302,17 @@ if (mask & 0x01) dst[7] = color; \ #define SK_BLITBWMASK_DEVTYPE uint16_t #include "SkBlitBWMaskTemplate.h" -#define blend_8_pixels(mask, dst, sc, dst_scale) \ -do { \ -if (mask & 0x80) { dst[0] = sc + SkAlphaMulQ4(dst[0], dst_scale); } \ -if (mask & 0x40) { dst[1] = sc + SkAlphaMulQ4(dst[1], dst_scale); } \ -if (mask & 0x20) { dst[2] = sc + SkAlphaMulQ4(dst[2], dst_scale); } \ -if (mask & 0x10) { dst[3] = sc + SkAlphaMulQ4(dst[3], dst_scale); } \ -if (mask & 0x08) { dst[4] = sc + SkAlphaMulQ4(dst[4], dst_scale); } \ -if (mask & 0x04) { dst[5] = sc + SkAlphaMulQ4(dst[5], dst_scale); } \ -if (mask & 0x02) { dst[6] = sc + SkAlphaMulQ4(dst[6], dst_scale); } \ -if (mask & 0x01) { dst[7] = sc + SkAlphaMulQ4(dst[7], dst_scale); } \ -} while (0) +#define blend_8_pixels(mask, dst, sc, dst_scale) \ + do { \ + if (mask & 0x80) { dst[0] = sc + SkAlphaMulQ4(dst[0], dst_scale); } \ + if (mask & 0x40) { dst[1] = sc + SkAlphaMulQ4(dst[1], dst_scale); } \ + if (mask & 0x20) { dst[2] = sc + SkAlphaMulQ4(dst[2], dst_scale); } \ + if (mask & 0x10) { dst[3] = sc + SkAlphaMulQ4(dst[3], dst_scale); } \ + if (mask & 0x08) { dst[4] = sc + SkAlphaMulQ4(dst[4], dst_scale); } \ + if (mask & 0x04) { dst[5] = sc + SkAlphaMulQ4(dst[5], dst_scale); } \ + if (mask & 0x02) { dst[6] = sc + SkAlphaMulQ4(dst[6], dst_scale); } \ + if (mask & 0x01) { dst[7] = sc + SkAlphaMulQ4(dst[7], dst_scale); } \ + } while (0) #define SK_BLITBWMASK_NAME SkARGB4444_BlendBW #define SK_BLITBWMASK_ARGS , uint16_t sc, unsigned dst_scale @@ -335,8 +321,7 @@ if (mask & 0x01) { dst[7] = sc + SkAlphaMulQ4(dst[7], dst_scale); } \ #define SK_BLITBWMASK_DEVTYPE uint16_t #include "SkBlitBWMaskTemplate.h" -void SkARGB4444_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) -{ +void SkARGB4444_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) { SkASSERT(mask.fBounds.contains(clip)); if (0 == fScale16) { @@ -375,7 +360,7 @@ void SkARGB4444_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) } while (--height != 0); } -////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// class SkARGB4444_Shader_Blitter : public SkShaderBlitter { SkXfermode* fXfermode; @@ -386,8 +371,7 @@ class SkARGB4444_Shader_Blitter : public SkShaderBlitter { public: SkARGB4444_Shader_Blitter(const SkBitmap& device, const SkPaint& paint) - : INHERITED(device, paint) -{ + : INHERITED(device, paint) { const int width = device.width(); fBuffer = (SkPMColor*)sk_malloc_throw(width * sizeof(SkPMColor) + width); fAAExpand = (uint8_t*)(fBuffer + width); diff --git a/src/core/SkBlitter_A1.cpp b/src/core/SkBlitter_A1.cpp index 1a91a26..d1416ff 100644 --- a/src/core/SkBlitter_A1.cpp +++ b/src/core/SkBlitter_A1.cpp @@ -18,18 +18,17 @@ #include "SkCoreBlitters.h" SkA1_Blitter::SkA1_Blitter(const SkBitmap& device, const SkPaint& paint) - : INHERITED(device) -{ - fSrcA = SkToU8(SkColorGetA(paint.getColor())); + : INHERITED(device) { + fSrcA = paint.getAlpha(); } -void SkA1_Blitter::blitH(int x, int y, int width) -{ - SkASSERT(x >= 0 && y >= 0 && (unsigned)(x + width) <= (unsigned)fDevice.width()); +void SkA1_Blitter::blitH(int x, int y, int width) { + SkASSERT(x >= 0 && y >= 0 && + (unsigned)(x + width) <= (unsigned)fDevice.width()); - if (fSrcA <= 0x7F) + if (fSrcA <= 0x7F) { return; - + } uint8_t* dst = fDevice.getAddr1(x, y); int right = x + width; @@ -37,23 +36,20 @@ void SkA1_Blitter::blitH(int x, int y, int width) int rite_mask = 0xFF << (8 - (right & 7)); int full_runs = (right >> 3) - ((x + 7) >> 3); - // check for empty right mask, so we don't read off the end (or go slower than we need to) - if (rite_mask == 0) - { + // check for empty right mask, so we don't read off the end + // (or go slower than we need to) + if (rite_mask == 0) { SkASSERT(full_runs >= 0); full_runs -= 1; rite_mask = 0xFF; } - if (left_mask == 0xFF) + if (left_mask == 0xFF) { full_runs -= 1; - - if (full_runs < 0) - { + } + if (full_runs < 0) { SkASSERT((left_mask & rite_mask) != 0); *dst |= (left_mask & rite_mask); - } - else - { + } else { *dst++ |= left_mask; memset(dst, 0xFF, full_runs); dst += full_runs; diff --git a/src/core/SkBlitter_A8.cpp b/src/core/SkBlitter_A8.cpp index f74fbe3..2eb762f 100644 --- a/src/core/SkBlitter_A8.cpp +++ b/src/core/SkBlitter_A8.cpp @@ -21,8 +21,8 @@ #include "SkXfermode.h" SkA8_Blitter::SkA8_Blitter(const SkBitmap& device, const SkPaint& paint) - : INHERITED(device) { - fSrcA = SkColorGetA(paint.getColor()); + : INHERITED(device) { + fSrcA = paint.getAlpha(); } const SkBitmap* SkA8_Blitter::justAnOpaqueColor(uint32_t* value) { diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp index a31623e..16cfc4b 100644 --- a/src/core/SkCanvas.cpp +++ b/src/core/SkCanvas.cpp @@ -24,6 +24,7 @@ #include "SkScalarCompare.h" #include "SkShape.h" #include "SkTemplates.h" +#include "SkTLazy.h" #include "SkUtils.h" #include <new> @@ -50,6 +51,8 @@ #define dec_canvas() #endif +typedef SkTLazy<SkPaint> SkLazyPaint; + /////////////////////////////////////////////////////////////////////////////// // Helpers for computing fast bounds for quickReject tests @@ -279,65 +282,69 @@ private: class AutoDrawLooper { public: - AutoDrawLooper(SkCanvas* canvas, const SkPaint& paint, SkDrawFilter::Type t) - : fCanvas(canvas), fPaint((SkPaint*)&paint), fType(t) { - if ((fLooper = paint.getLooper()) != NULL) { - fLooper->init(canvas, (SkPaint*)&paint); - } else { - fOnce = true; - } + AutoDrawLooper(SkCanvas* canvas, const SkPaint& paint) : fOrigPaint(paint) { + fCanvas = canvas; + fLooper = paint.getLooper(); fFilter = canvas->getDrawFilter(); - fNeedFilterRestore = false; - } + fPaint = NULL; + fSaveCount = canvas->getSaveCount(); + fDone = false; - ~AutoDrawLooper() { - if (fNeedFilterRestore) { - SkASSERT(fFilter); - fFilter->restore(fCanvas, fPaint, fType); - } - if (NULL != fLooper) { - fLooper->restore(); + if (fLooper) { + fLooper->init(canvas); } } - - bool next() { - SkDrawFilter* filter = fFilter; - - // if we drew earlier with a filter, then we need to restore first - if (fNeedFilterRestore) { - SkASSERT(filter); - filter->restore(fCanvas, fPaint, fType); - fNeedFilterRestore = false; - } - - bool result; - - if (NULL != fLooper) { - result = fLooper->next(); - } else { - result = fOnce; - fOnce = false; - } - - // if we're gonna draw, give the filter a chance to do its work - if (result && NULL != filter) { - fNeedFilterRestore = result = filter->filter(fCanvas, fPaint, - fType); - } - return result; + + ~AutoDrawLooper() { + SkASSERT(fCanvas->getSaveCount() == fSaveCount); } - + + const SkPaint& paint() const { + SkASSERT(fPaint); + return *fPaint; + } + + bool next(SkDrawFilter::Type drawType); + private: + SkLazyPaint fLazyPaint; + SkCanvas* fCanvas; + const SkPaint& fOrigPaint; SkDrawLooper* fLooper; SkDrawFilter* fFilter; - SkCanvas* fCanvas; - SkPaint* fPaint; - SkDrawFilter::Type fType; - bool fOnce; - bool fNeedFilterRestore; - + const SkPaint* fPaint; + int fSaveCount; + bool fDone; }; +bool AutoDrawLooper::next(SkDrawFilter::Type drawType) { + if (fDone) { + fPaint = NULL; + return false; + } + if (!fLooper && !fFilter) { + fDone = true; + fPaint = &fOrigPaint; + return true; + } + + SkPaint* paint = fLazyPaint.set(fOrigPaint); + if (fLooper && !fLooper->next(fCanvas, paint)) { + fDone = true; + fPaint = NULL; + return false; + } + if (fFilter) { + fFilter->filter(paint, drawType); + if (NULL == fLooper) { + // no looper means we only draw once + fDone = true; + } + } + fPaint = paint; + return true; +} + /* Stack helper for managing a SkBounder. In the destructor, if we were given a bounder, we call its commit() method, signifying that we are done accumulating bounds for that draw. @@ -379,14 +386,14 @@ private: ////////// macros to place around the internal draw calls ////////////////// -#define ITER_BEGIN(paint, type) \ +#define LOOPER_BEGIN(paint, type) \ /* AutoValidator validator(fMCRec->fTopLayer->fDevice); */ \ - AutoDrawLooper looper(this, paint, type); \ - while (looper.next()) { \ + AutoDrawLooper looper(this, paint); \ + while (looper.next(type)) { \ SkAutoBounderCommit ac(fBounder); \ SkDrawIter iter(this); -#define ITER_END } +#define LOOPER_END } //////////////////////////////////////////////////////////////////////////// @@ -472,6 +479,10 @@ SkDevice* SkCanvas::getDevice() const { return rec->fLayer->fDevice; } +SkDevice* SkCanvas::getTopDevice() const { + return fMCRec->fTopLayer->fDevice; +} + SkDevice* SkCanvas::setDevice(SkDevice* device) { // return root device SkDeque::F2BIter iter(fMCStack); @@ -832,12 +843,11 @@ void SkCanvas::internalDrawBitmap(const SkBitmap& bitmap, const SkIRect* srcRect return; } + SkLazyPaint lazy; if (NULL == paint) { - SkPaint tmpPaint; - this->commonDrawBitmap(bitmap, srcRect, matrix, tmpPaint); - } else { - this->commonDrawBitmap(bitmap, srcRect, matrix, *paint); + paint = lazy.init(); } + this->commonDrawBitmap(bitmap, srcRect, matrix, *paint); } void SkCanvas::drawDevice(SkDevice* device, int x, int y, @@ -848,12 +858,12 @@ void SkCanvas::drawDevice(SkDevice* device, int x, int y, paint = &tmp; } - ITER_BEGIN(*paint, SkDrawFilter::kBitmap_Type) + LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type) while (iter.next()) { iter.fDevice->drawDevice(iter, device, x - iter.getX(), y - iter.getY(), - *paint); + looper.paint()); } - ITER_END + LOOPER_END } ///////////////////////////////////////////////////////////////////////////// @@ -1185,13 +1195,13 @@ SkDevice* SkCanvas::createDevice(SkBitmap::Config config, int width, int height, ////////////////////////////////////////////////////////////////////////////// void SkCanvas::drawPaint(const SkPaint& paint) { - ITER_BEGIN(paint, SkDrawFilter::kPaint_Type) + LOOPER_BEGIN(paint, SkDrawFilter::kPaint_Type) while (iter.next()) { - iter.fDevice->drawPaint(iter, paint); + iter.fDevice->drawPaint(iter, looper.paint()); } - ITER_END + LOOPER_END } void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[], @@ -1202,13 +1212,13 @@ void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[], SkASSERT(pts != NULL); - ITER_BEGIN(paint, SkDrawFilter::kPoint_Type) + LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type) while (iter.next()) { - iter.fDevice->drawPoints(iter, mode, count, pts, paint); + iter.fDevice->drawPoints(iter, mode, count, pts, looper.paint()); } - ITER_END + LOOPER_END } void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) { @@ -1220,13 +1230,13 @@ void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) { } } - ITER_BEGIN(paint, SkDrawFilter::kRect_Type) + LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type) while (iter.next()) { - iter.fDevice->drawRect(iter, r, paint); + iter.fDevice->drawRect(iter, r, looper.paint()); } - ITER_END + LOOPER_END } void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) { @@ -1239,13 +1249,13 @@ void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) { } } - ITER_BEGIN(paint, SkDrawFilter::kPath_Type) + LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type) while (iter.next()) { - iter.fDevice->drawPath(iter, path, paint); + iter.fDevice->drawPath(iter, path, looper.paint()); } - ITER_END + LOOPER_END } void SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, @@ -1305,7 +1315,9 @@ void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src, SkIRect tmpISrc; if (src) { tmpISrc.set(0, 0, bitmap.width(), bitmap.height()); - tmpISrc.intersect(*src); + if (!tmpISrc.intersect(*src)) { + return; + } src = &tmpISrc; } this->internalDrawBitmap(*bitmapPtr, src, matrix, paint); @@ -1321,13 +1333,13 @@ void SkCanvas::commonDrawBitmap(const SkBitmap& bitmap, const SkIRect* srcRect, const SkMatrix& matrix, const SkPaint& paint) { SkDEBUGCODE(bitmap.validate();) - ITER_BEGIN(paint, SkDrawFilter::kBitmap_Type) + LOOPER_BEGIN(paint, SkDrawFilter::kBitmap_Type) while (iter.next()) { - iter.fDevice->drawBitmap(iter, bitmap, srcRect, matrix, paint); + iter.fDevice->drawBitmap(iter, bitmap, srcRect, matrix, looper.paint()); } - ITER_END + LOOPER_END } void SkCanvas::drawSprite(const SkBitmap& bitmap, int x, int y, @@ -1343,13 +1355,13 @@ void SkCanvas::drawSprite(const SkBitmap& bitmap, int x, int y, paint = &tmp; } - ITER_BEGIN(*paint, SkDrawFilter::kBitmap_Type) + LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type) while (iter.next()) { iter.fDevice->drawSprite(iter, bitmap, x - iter.getX(), y - iter.getY(), - *paint); + looper.paint()); } - ITER_END + LOOPER_END } class SkDeviceFilteredPaint { @@ -1357,7 +1369,7 @@ public: SkDeviceFilteredPaint(SkDevice* device, const SkPaint& paint) { SkDevice::TextFlags flags; if (device->filterTextFlags(paint, &flags)) { - SkPaint* newPaint = new (fStorage) SkPaint(paint); + SkPaint* newPaint = fLazy.set(paint); newPaint->setFlags(flags.fFlags); newPaint->setHinting(flags.fHinting); fPaint = newPaint; @@ -1366,71 +1378,63 @@ public: } } - ~SkDeviceFilteredPaint() { - if (reinterpret_cast<SkPaint*>(fStorage) == fPaint) { - fPaint->~SkPaint(); - } - } - const SkPaint& paint() const { return *fPaint; } private: - // points to either fStorage or the caller's paint const SkPaint* fPaint; - // we rely on the fPaint above to ensure proper alignment of fStorage - char fStorage[sizeof(SkPaint)]; + SkLazyPaint fLazy; }; void SkCanvas::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y, const SkPaint& paint) { - ITER_BEGIN(paint, SkDrawFilter::kText_Type) + LOOPER_BEGIN(paint, SkDrawFilter::kText_Type) while (iter.next()) { - SkDeviceFilteredPaint dfp(iter.fDevice, paint); + SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint()); } - ITER_END + LOOPER_END } void SkCanvas::drawPosText(const void* text, size_t byteLength, const SkPoint pos[], const SkPaint& paint) { - ITER_BEGIN(paint, SkDrawFilter::kText_Type) + LOOPER_BEGIN(paint, SkDrawFilter::kText_Type) while (iter.next()) { - SkDeviceFilteredPaint dfp(iter.fDevice, paint); + SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 0, 2, dfp.paint()); } - ITER_END + LOOPER_END } void SkCanvas::drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], SkScalar constY, const SkPaint& paint) { - ITER_BEGIN(paint, SkDrawFilter::kText_Type) + LOOPER_BEGIN(paint, SkDrawFilter::kText_Type) while (iter.next()) { - SkDeviceFilteredPaint dfp(iter.fDevice, paint); + SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); iter.fDevice->drawPosText(iter, text, byteLength, xpos, constY, 1, dfp.paint()); } - ITER_END + LOOPER_END } void SkCanvas::drawTextOnPath(const void* text, size_t byteLength, const SkPath& path, const SkMatrix* matrix, const SkPaint& paint) { - ITER_BEGIN(paint, SkDrawFilter::kText_Type) + LOOPER_BEGIN(paint, SkDrawFilter::kText_Type) while (iter.next()) { iter.fDevice->drawTextOnPath(iter, text, byteLength, path, - matrix, paint); + matrix, looper.paint()); } - ITER_END + LOOPER_END } #ifdef ANDROID @@ -1438,14 +1442,14 @@ void SkCanvas::drawPosTextOnPath(const void* text, size_t byteLength, const SkPoint pos[], const SkPaint& paint, const SkPath& path, const SkMatrix* matrix) { - ITER_BEGIN(paint, SkDrawFilter::kText_Type) + LOOPER_BEGIN(paint, SkDrawFilter::kText_Type) while (iter.next()) { iter.fDevice->drawPosTextOnPath(iter, text, byteLength, pos, - paint, path, matrix); + looper.paint(), path, matrix); } - ITER_END + LOOPER_END } #endif @@ -1454,14 +1458,15 @@ void SkCanvas::drawVertices(VertexMode vmode, int vertexCount, const SkColor colors[], SkXfermode* xmode, const uint16_t indices[], int indexCount, const SkPaint& paint) { - ITER_BEGIN(paint, SkDrawFilter::kPath_Type) + LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type) while (iter.next()) { iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs, - colors, xmode, indices, indexCount, paint); + colors, xmode, indices, indexCount, + looper.paint()); } - ITER_END + LOOPER_END } void SkCanvas::drawData(const void* data, size_t length) { diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp index 8231848..69d0c1c 100644 --- a/src/core/SkDevice.cpp +++ b/src/core/SkDevice.cpp @@ -1,15 +1,16 @@ #include "SkDevice.h" #include "SkDraw.h" +#include "SkMetaData.h" #include "SkRect.h" SkDeviceFactory::~SkDeviceFactory() {} -SkDevice::SkDevice(SkCanvas* canvas) : fCanvas(canvas) { +SkDevice::SkDevice(SkCanvas* canvas) : fCanvas(canvas), fMetaData(NULL) { fOrigin.setZero(); } SkDevice::SkDevice(SkCanvas* canvas, const SkBitmap& bitmap, bool isForLayer) - : fCanvas(canvas), fBitmap(bitmap) { + : fCanvas(canvas), fBitmap(bitmap), fMetaData(NULL) { fOrigin.setZero(); // auto-allocate if we're for offscreen drawing if (isForLayer) { @@ -22,6 +23,19 @@ SkDevice::SkDevice(SkCanvas* canvas, const SkBitmap& bitmap, bool isForLayer) } } +SkDevice::~SkDevice() { + delete fMetaData; +} + +SkMetaData& SkDevice::getMetaData() { + // metadata users are rare, so we lazily allocate it. If that changes we + // can decide to just make it a field in the device (rather than a ptr) + if (NULL == fMetaData) { + fMetaData = new SkMetaData; + } + return *fMetaData; +} + void SkDevice::lockPixels() { fBitmap.lockPixels(); } diff --git a/src/core/SkDraw.cpp b/src/core/SkDraw.cpp index ce0fa9b..14e5a80 100644 --- a/src/core/SkDraw.cpp +++ b/src/core/SkDraw.cpp @@ -679,6 +679,49 @@ static inline SkPoint* as_rightbottom(SkRect* r) { return ((SkPoint*)(void*)r) + 1; } +static bool easy_rect_join(const SkPaint& paint, const SkMatrix& matrix, + SkPoint* strokeSize) { + if (SkPaint::kMiter_Join != paint.getStrokeJoin() || + paint.getStrokeMiter() < SK_ScalarSqrt2) { + return false; + } + + SkASSERT(matrix.rectStaysRect()); + SkPoint pt = { paint.getStrokeWidth(), paint.getStrokeWidth() }; + matrix.mapVectors(strokeSize, &pt, 1); + strokeSize->fX = SkScalarAbs(strokeSize->fX); + strokeSize->fY = SkScalarAbs(strokeSize->fY); + return true; +} + +SkDraw::RectType SkDraw::ComputeRectType(const SkPaint& paint, + const SkMatrix& matrix, + SkPoint* strokeSize) { + RectType rtype; + const SkScalar width = paint.getStrokeWidth(); + const bool zeroWidth = (0 == width); + SkPaint::Style style = paint.getStyle(); + + if ((SkPaint::kStrokeAndFill_Style == style) && zeroWidth) { + style = SkPaint::kFill_Style; + } + + if (paint.getPathEffect() || paint.getMaskFilter() || + paint.getRasterizer() || !matrix.rectStaysRect() || + SkPaint::kStrokeAndFill_Style == style) { + rtype = kPath_RectType; + } else if (SkPaint::kFill_Style == style) { + rtype = kFill_RectType; + } else if (zeroWidth) { + rtype = kHair_RectType; + } else if (easy_rect_join(paint, matrix, strokeSize)) { + rtype = kStroke_RectType; + } else { + rtype = kPath_RectType; + } + return rtype; +} + void SkDraw::drawRect(const SkRect& rect, const SkPaint& paint) const { SkDEBUGCODE(this->validate();) @@ -688,11 +731,16 @@ void SkDraw::drawRect(const SkRect& rect, const SkPaint& paint) const { return; } - // complex enough to draw as a path - if (paint.getPathEffect() || paint.getMaskFilter() || - paint.getRasterizer() || !fMatrix->rectStaysRect() || - (paint.getStyle() != SkPaint::kFill_Style && - SkScalarHalf(paint.getStrokeWidth()) > 0)) { + SkPoint strokeSize; + RectType rtype = ComputeRectType(paint, *fMatrix, &strokeSize); + +#ifdef SK_DISABLE_FAST_AA_STROKE_RECT + if (kStroke_RectType == rtype && paint.isAntiAlias()) { + rtype = kPath_RectType; + } +#endif + + if (kPath_RectType == rtype) { SkPath tmp; tmp.addRect(rect); tmp.setFillType(SkPath::kWinding_FillType); @@ -733,18 +781,30 @@ void SkDraw::drawRect(const SkRect& rect, const SkPaint& paint) const { // we want to "fill" if we are kFill or kStrokeAndFill, since in the latter // case we are also hairline (if we've gotten to here), which devolves to // effectively just kFill - if (paint.getStyle() != SkPaint::kStroke_Style) { - if (paint.isAntiAlias()) { - SkScan::AntiFillRect(devRect, clip, blitter); - } else { - SkScan::FillRect(devRect, clip, blitter); - } - } else { - if (paint.isAntiAlias()) { - SkScan::AntiHairRect(devRect, clip, blitter); - } else { - SkScan::HairRect(devRect, clip, blitter); - } + switch (rtype) { + case kFill_RectType: + if (paint.isAntiAlias()) { + SkScan::AntiFillRect(devRect, clip, blitter); + } else { + SkScan::FillRect(devRect, clip, blitter); + } + break; + case kStroke_RectType: + if (paint.isAntiAlias()) { + SkScan::AntiFrameRect(devRect, strokeSize, clip, blitter); + } else { + SkScan::FrameRect(devRect, strokeSize, clip, blitter); + } + break; + case kHair_RectType: + if (paint.isAntiAlias()) { + SkScan::AntiHairRect(devRect, clip, blitter); + } else { + SkScan::HairRect(devRect, clip, blitter); + } + break; + default: + SkASSERT(!"bad rtype"); } } @@ -1568,7 +1628,7 @@ void SkDraw::drawText(const char text[], size_t byteLength, // apply the bias here, so we don't have to add 1/2 in the loop fx += SK_FixedHalf; fy += SK_FixedHalf; - fy &= finalFYMask; + fyMask &= finalFYMask; SkAutoKern autokern; SkDraw1Glyph d1g; @@ -2364,8 +2424,8 @@ void SkDraw::drawVertices(SkCanvas::VertexMode vmode, int count, } } -//////////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// #ifdef SK_DEBUG @@ -2386,7 +2446,12 @@ void SkDraw::validate() const { #endif -////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +SkBounder::SkBounder() { + // initialize up front. This gets reset by SkCanvas before each draw call. + fClip = &SkRegion::GetEmptyRegion(); +} bool SkBounder::doIRect(const SkIRect& r) { SkIRect rr; diff --git a/src/core/SkFlate.cpp b/src/core/SkFlate.cpp index ade1658..99b331e 100644 --- a/src/core/SkFlate.cpp +++ b/src/core/SkFlate.cpp @@ -24,19 +24,22 @@ bool SkFlate::Inflate(SkStream*, SkDynamicMemoryWStream*) { return false; } #else // static -const size_t SkFlate::kBufferSize = 1024; - -// static bool SkFlate::HaveFlate() { +#ifdef SK_DEBUG + return false; +#else return true; +#endif } namespace { #include SK_ZLIB_INCLUDE -bool doFlate(bool compress, const size_t kBufferSize, SkStream* src, - SkDynamicMemoryWStream* dst) { +// static +const size_t kBufferSize = 1024; + +bool doFlate(bool compress, SkStream* src, SkDynamicMemoryWStream* dst) { uint8_t inputBuffer[kBufferSize]; uint8_t outputBuffer[kBufferSize]; z_stream flateData; @@ -117,12 +120,12 @@ bool doFlate(bool compress, const size_t kBufferSize, SkStream* src, // static bool SkFlate::Deflate(SkStream* src, SkDynamicMemoryWStream* dst) { - return doFlate(true, kBufferSize, src, dst); + return doFlate(true, src, dst); } // static bool SkFlate::Inflate(SkStream* src, SkDynamicMemoryWStream* dst) { - return doFlate(false, kBufferSize, src, dst); + return doFlate(false, src, dst); } #endif diff --git a/src/core/SkGlyphCache.h b/src/core/SkGlyphCache.h index 92e3795..adf0466 100644 --- a/src/core/SkGlyphCache.h +++ b/src/core/SkGlyphCache.h @@ -280,30 +280,27 @@ private: class SkAutoGlyphCache { public: SkAutoGlyphCache(SkGlyphCache* cache) : fCache(cache) {} - SkAutoGlyphCache(const SkDescriptor* desc) - { + SkAutoGlyphCache(const SkDescriptor* desc) { fCache = SkGlyphCache::DetachCache(desc); } - SkAutoGlyphCache(const SkPaint& paint, const SkMatrix* matrix) - { + SkAutoGlyphCache(const SkPaint& paint, const SkMatrix* matrix) { fCache = paint.detachCache(matrix); } - ~SkAutoGlyphCache() - { - if (fCache) + ~SkAutoGlyphCache() { + if (fCache) { SkGlyphCache::AttachCache(fCache); + } } - SkGlyphCache* getCache() const { return fCache; } + SkGlyphCache* getCache() const { return fCache; } - void release() - { - if (fCache) - { + void release() { + if (fCache) { SkGlyphCache::AttachCache(fCache); fCache = NULL; } } + private: SkGlyphCache* fCache; diff --git a/src/core/SkGraphics.cpp b/src/core/SkGraphics.cpp index 40f0ea3..8638504 100644 --- a/src/core/SkGraphics.cpp +++ b/src/core/SkGraphics.cpp @@ -37,48 +37,8 @@ #include "SkUtils.h" #include "SkXfermode.h" -#if 0 - -#define SK_SORT_TEMPLATE_TYPE int -#define SK_SORT_TEMPLATE_NAME sort_int -#define SK_SORT_TEMPLATE_CMP(a, b) ((a) - (b)) -#include "SkSortTemplate.h" - -#define SK_SORT_TEMPLATE_TYPE int* -#define SK_SORT_TEMPLATE_NAME sort_intptr -#define SK_SORT_TEMPLATE_CMP(a, b) (*(a) - *(b)) -#include "SkSortTemplate.h" - -static void test_sort() -{ - int array[] = { 4, 3, 7, 5, 2, 5, 1, 2, 9, 6, 7, 4, 5, 3, 1, 0 }; - int* ptr[SK_ARRAY_COUNT(array)]; - int i, N = SK_ARRAY_COUNT(array) - 1; - - for (i = 0; i < N; i++) - printf(" %d", array[i]); - printf("\n"); - - for (i = 0; i < N; i++) - ptr[i] = &array[i]; - sort_intptr(ptr, N); - for (i = 0; i < N; i++) - printf(" %d", *ptr[i]); - printf("\n"); - - sort_int(array, N); - for (i = 0; i < N; i++) - printf(" %d", array[i]); - printf("\n"); - -} -#endif - -#define SPEED_TESTx - #define typesizeline(type) { #type , sizeof(type) } - #ifdef BUILD_EMBOSS_TABLE extern void SkEmbossMask_BuildTable(); #endif @@ -87,65 +47,6 @@ static void test_sort() extern void SkRadialGradient_BuildTable(); #endif -#define BIG_LOOP_COUNT 1000000 -#define TEXT_LOOP_COUNT 1000 - -#ifdef SPEED_TEST -static int test_s64(int i) -{ - Sk64 a, b, c; - - c.set(0); - a.set(i); - b.setMul(i, i); - a.add(b); - a.add(c); - return c.getFixed(); -} - -static int test_native_64(int i) -{ - int16_t a, b, c; - - c = 0; - a = i; - b = (int64_t)i * i; - a += b; - a += c; - return (int)(c >> 16); -} - -static void test_drawText(SkBitmap::Config config, SkColor color) -{ - SkBitmap bm; - - bm.setConfig(config, 320, 240); - bm.allocPixels(); - - SkCanvas canvas(bm); - SkPaint paint; - - paint.setAntiAlias(true); - paint.setTextSize(SkIntToScalar(12)); - paint.setColor(color); - - SkScalar x = SkIntToScalar(20); - SkScalar y = SkIntToScalar(100); - const char* text = "Hamburgefons"; - size_t len = strlen(text); - - // draw once to populate the cache - canvas.drawText(text, len, x, y, paint); - - SkMSec now = SkTime::GetMSecs(); - for (int i = 0; i < TEXT_LOOP_COUNT; i++) - canvas.drawText(text, len, x, y, paint); - printf("----------- Config: %d, Color=%x, CPS = %g\n", config, color, - len * TEXT_LOOP_COUNT * 1000.0 / (SkTime::GetMSecs() - now)); -} - -#endif - void SkGraphics::Init() { SkGlobals::Init(); @@ -210,154 +111,9 @@ void SkGraphics::Init() { } #endif - - if (false) // test asm fixmul - { - int j; - SkMSec now = SkTime::GetMSecs(); - for (j = 0; j < BIG_LOOP_COUNT; j++) { - (void)SkFixedMul_portable(0x8000, 0x150000); - } - SkMSec now2 = SkTime::GetMSecs(); - printf("-------- SkFixedMul_portable = %d\n", now2 - now); - - for (j = 0; j < BIG_LOOP_COUNT; j++) { - (void)SkFixedMul(0x8000, 0x150000); - } - printf("-------- SkFixedMul = %d\n", SkTime::GetMSecs() - now2); - - SkRandom rand; - for (j = 0; j < 10000; j++) { - SkFixed a = rand.nextS() >> 8; - SkFixed b = rand.nextS() >> 8; - SkFixed c1 = SkFixedMul_portable(a, b); - SkFixed c2 = SkFixedMul(a, b); - if (SkAbs32(c1 - c2) > 1) - printf("------ FixMul disagreement: (%x %x) slow=%x fast=%x\n", a, b, c1, c2); - } - } - - if (false) // test asm fractmul - { - int j; - SkMSec now = SkTime::GetMSecs(); - for (j = 0; j < BIG_LOOP_COUNT; j++) { - (void)SkFractMul_portable(0x800000, 0x1500000); - } - SkMSec now2 = SkTime::GetMSecs(); - printf("-------- SkFractMul_portable = %d\n", now2 - now); - - for (j = 0; j < BIG_LOOP_COUNT; j++) { - (void)SkFractMul(0x800000, 0x1500000); - } - printf("-------- SkFractMul = %d\n", SkTime::GetMSecs() - now2); - - SkRandom rand; - for (j = 0; j < 10000; j++) { - SkFixed a = rand.nextS() >> 1; - SkFixed b = rand.nextS() >> 1; - SkFixed c1 = SkFractMul_portable(a, b); - SkFixed c2 = SkFractMul(a, b); - if (SkAbs32(c1 - c2) > 1) - printf("------ FractMul disagreement: (%x %x) slow=%x fast=%x\n", a, b, c1, c2); - } - } - - if (false) // test asm clz - { - int j; - SkMSec now = SkTime::GetMSecs(); - for (j = 0; j < BIG_LOOP_COUNT; j++) { - (void)SkCLZ_portable(now); - } - SkMSec now2 = SkTime::GetMSecs(); - printf("-------- SkCLZ_portable = %d\n", now2 - now); - - for (j = 0; j < BIG_LOOP_COUNT; j++) { - (void)SkCLZ(now); - } - printf("-------- SkCLZ = %d\n", SkTime::GetMSecs() - now2); - - SkRandom rand; - for (j = 0; j < 10000; j++) { - uint32_t a = rand.nextU(); - int c1 = SkCLZ_portable(a); - int c2 = SkCLZ(a); - if (c1 != c2) - printf("------ CLZ disagreement: (%x) slow=%x fast=%x\n", a, c1, c2); - } - } - -#ifdef SPEED_TEST - if (false) { - int i; - int (*proc)(int); - - static const struct { - int (*proc)(int); - const char* name; - } gList[] = { - { test_s64, "Sk64" }, - { test_native_64, "native" } - }; - - for (size_t j = 0; j < SK_ARRAY_COUNT(gList); j++) { - SkMSec now = SkTime::GetMSecs(); - proc = gList[j].proc; - for (i = 0; i < BIG_LOOP_COUNT; i++) { - proc(i); - } - printf("-------- %s = %d\n", gList[j].name, SkTime::GetMSecs() - now); - } - } -#endif - - if (false) { - size_t i, size = 480; - char* buffer = (char*)sk_malloc_throw(size); - uint16_t* buffer16 = (uint16_t*)buffer; - uint32_t* buffer32 = (uint32_t*)buffer; - - SkMSec now = SkTime::GetMSecs(); - for (i = 0; i < 100000; i++) { - sk_memset16(buffer16, (uint16_t)i, size >> 1); - } - SkMSec now2 = SkTime::GetMSecs(); - for (i = 0; i < 100000; i++) { - sk_memset16_portable(buffer16, (uint16_t)i, size >> 1); - } - SkMSec now3 = SkTime::GetMSecs(); - printf("----------- memset16: native %d, portable %d\n", now2 - now, now3 - now2); - - now = SkTime::GetMSecs(); - for (i = 0; i < 100000; i++) { - sk_memset32(buffer32, i, size >> 2); - } - now2 = SkTime::GetMSecs(); - for (i = 0; i < 100000; i++) { - sk_memset32_portable(buffer32, i, size >> 2); - } - now3 = SkTime::GetMSecs(); - printf("----------- memset32: native %d, portable %d\n", now2 - now, now3 - now2); - - sk_free(buffer); - } - -#ifdef SPEED_TEST - if (false) { - test_drawText(SkBitmap::kARGB_8888_Config, SK_ColorBLACK); - test_drawText(SkBitmap::kARGB_8888_Config, SK_ColorRED); - test_drawText(SkBitmap::kRGB_565_Config, SK_ColorBLACK); - test_drawText(SkBitmap::kRGB_565_Config, SK_ColorRED); - } -#endif - -// if (true) { -// test_sort(); -// } } -//////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// #include "SkGlyphCache.h" diff --git a/src/core/SkLineClipper.cpp b/src/core/SkLineClipper.cpp index 057f546..ab49773 100644 --- a/src/core/SkLineClipper.cpp +++ b/src/core/SkLineClipper.cpp @@ -6,8 +6,19 @@ static SkScalar sect_with_horizontal(const SkPoint src[2], SkScalar Y) { if (SkScalarNearlyZero(dy)) { return SkScalarAve(src[0].fX, src[1].fX); } else { +#ifdef SK_SCALAR_IS_FLOAT + // need the extra precision so we don't compute a value that exceeds + // our original limits + double X0 = src[0].fX; + double Y0 = src[0].fY; + double X1 = src[1].fX; + double Y1 = src[1].fY; + double result = X0 + ((double)Y - Y0) * (X1 - X0) / (Y1 - Y0); + return (float)result; +#else return src[0].fX + SkScalarMulDiv(Y - src[0].fY, src[1].fX - src[0].fX, dy); +#endif } } @@ -17,8 +28,19 @@ static SkScalar sect_with_vertical(const SkPoint src[2], SkScalar X) { if (SkScalarNearlyZero(dx)) { return SkScalarAve(src[0].fY, src[1].fY); } else { +#ifdef SK_SCALAR_IS_FLOAT + // need the extra precision so we don't compute a value that exceeds + // our original limits + double X0 = src[0].fX; + double Y0 = src[0].fY; + double X1 = src[1].fX; + double Y1 = src[1].fY; + double result = Y0 + ((double)X - X0) * (Y1 - Y0) / (X1 - X0); + return (float)result; +#else return src[0].fY + SkScalarMulDiv(X - src[0].fX, src[1].fY - src[0].fY, dx); +#endif } } @@ -106,6 +128,19 @@ bool SkLineClipper::IntersectLine(const SkPoint src[2], const SkRect& clip, return true; } +#ifdef SK_DEBUG +// return value between the two limits, where the limits are either ascending +// or descending. +static bool is_between_unsorted(SkScalar value, + SkScalar limit0, SkScalar limit1) { + if (limit0 < limit1) { + return limit0 <= value && value <= limit1; + } else { + return limit1 <= value && value <= limit0; + } +} +#endif + int SkLineClipper::ClipLine(const SkPoint pts[], const SkRect& clip, SkPoint lines[]) { int index0, index1; @@ -135,9 +170,11 @@ int SkLineClipper::ClipLine(const SkPoint pts[], const SkRect& clip, // now compute intersections if (pts[index0].fY < clip.fTop) { tmp[index0].set(sect_with_horizontal(pts, clip.fTop), clip.fTop); + SkASSERT(is_between_unsorted(tmp[index0].fX, pts[0].fX, pts[1].fX)); } if (tmp[index1].fY > clip.fBottom) { tmp[index1].set(sect_with_horizontal(pts, clip.fBottom), clip.fBottom); + SkASSERT(is_between_unsorted(tmp[index1].fX, pts[0].fX, pts[1].fX)); } // Chop it into 1..3 segments that are wholly within the clip in X. @@ -173,14 +210,16 @@ int SkLineClipper::ClipLine(const SkPoint pts[], const SkRect& clip, if (tmp[index0].fX < clip.fLeft) { r->set(clip.fLeft, tmp[index0].fY); r += 1; - r->set(clip.fLeft, sect_with_vertical(pts, clip.fLeft)); + r->set(clip.fLeft, sect_with_vertical(tmp, clip.fLeft)); + SkASSERT(is_between_unsorted(r->fY, tmp[0].fY, tmp[1].fY)); } else { *r = tmp[index0]; } r += 1; if (tmp[index1].fX > clip.fRight) { - r->set(clip.fRight, sect_with_vertical(pts, clip.fRight)); + r->set(clip.fRight, sect_with_vertical(tmp, clip.fRight)); + SkASSERT(is_between_unsorted(r->fY, tmp[0].fY, tmp[1].fY)); r += 1; r->set(clip.fRight, tmp[index1].fY); } else { diff --git a/src/core/SkMask.cpp b/src/core/SkMask.cpp index 337204b..34f122b 100644 --- a/src/core/SkMask.cpp +++ b/src/core/SkMask.cpp @@ -45,16 +45,14 @@ size_t SkMask::computeTotalImageSize() const { /** We explicitly use this allocator for SkBimap pixels, so that we can freely assign memory allocated by one class to the other. */ -uint8_t* SkMask::AllocImage(size_t size) -{ +uint8_t* SkMask::AllocImage(size_t size) { return (uint8_t*)sk_malloc_throw(SkAlign4(size)); } /** We explicitly use this allocator for SkBimap pixels, so that we can freely assign memory allocated by one class to the other. */ -void SkMask::FreeImage(void* image) -{ +void SkMask::FreeImage(void* image) { sk_free(image); } diff --git a/src/core/SkMetaData.cpp b/src/core/SkMetaData.cpp new file mode 100644 index 0000000..b1901dc --- /dev/null +++ b/src/core/SkMetaData.cpp @@ -0,0 +1,345 @@ +/* libs/graphics/views/SkMetaData.cpp +** +** Copyright 2006, 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. +*/ + +#include "SkMetaData.h" +#include "SkRefCnt.h" + +struct PtrPair { + void* fPtr; + SkMetaData::PtrProc fProc; +}; + +void* SkMetaData::RefCntProc(void* ptr, bool doRef) { + SkASSERT(ptr); + SkRefCnt* refcnt = reinterpret_cast<SkRefCnt*>(ptr); + + if (doRef) { + refcnt->ref(); + } else { + refcnt->unref(); + } + return ptr; +} + +SkMetaData::SkMetaData() : fRec(NULL) +{ +} + +SkMetaData::SkMetaData(const SkMetaData& src) : fRec(NULL) +{ + *this = src; +} + +SkMetaData::~SkMetaData() +{ + this->reset(); +} + +void SkMetaData::reset() +{ + Rec* rec = fRec; + while (rec) { + if (kPtr_Type == rec->fType) { + PtrPair* pair = (PtrPair*)rec->data(); + if (pair->fProc && pair->fPtr) { + pair->fPtr = pair->fProc(pair->fPtr, false); + } + } + Rec* next = rec->fNext; + Rec::Free(rec); + rec = next; + } + fRec = NULL; +} + +SkMetaData& SkMetaData::operator=(const SkMetaData& src) +{ + this->reset(); + + const Rec* rec = src.fRec; + while (rec) + { + this->set(rec->name(), rec->data(), rec->fDataLen, (Type)rec->fType, rec->fDataCount); + rec = rec->fNext; + } + return *this; +} + +void SkMetaData::setS32(const char name[], int32_t value) +{ + (void)this->set(name, &value, sizeof(int32_t), kS32_Type, 1); +} + +void SkMetaData::setScalar(const char name[], SkScalar value) +{ + (void)this->set(name, &value, sizeof(SkScalar), kScalar_Type, 1); +} + +SkScalar* SkMetaData::setScalars(const char name[], int count, const SkScalar values[]) +{ + SkASSERT(count > 0); + if (count > 0) + return (SkScalar*)this->set(name, values, sizeof(SkScalar), kScalar_Type, count); + return NULL; +} + +void SkMetaData::setString(const char name[], const char value[]) +{ + (void)this->set(name, value, sizeof(char), kString_Type, strlen(value) + 1); +} + +void SkMetaData::setPtr(const char name[], void* ptr, PtrProc proc) { + PtrPair pair = { ptr, proc }; + (void)this->set(name, &pair, sizeof(PtrPair), kPtr_Type, 1); +} + +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); + SkASSERT(dataSize); + SkASSERT(count > 0); + + (void)this->remove(name, type); + + size_t len = strlen(name); + Rec* rec = Rec::Alloc(sizeof(Rec) + dataSize * count + len + 1); + +#ifndef SK_DEBUG + rec->fType = SkToU8(type); +#else + rec->fType = type; +#endif + rec->fDataLen = SkToU8(dataSize); + rec->fDataCount = SkToU16(count); + if (data) + memcpy(rec->data(), data, dataSize * count); + memcpy(rec->name(), name, len + 1); + + if (kPtr_Type == type) { + PtrPair* pair = (PtrPair*)rec->data(); + if (pair->fProc && pair->fPtr) { + pair->fPtr = pair->fProc(pair->fPtr, true); + } + } + + rec->fNext = fRec; + fRec = rec; + return rec->data(); +} + +bool SkMetaData::findS32(const char name[], int32_t* value) const +{ + const Rec* rec = this->find(name, kS32_Type); + if (rec) + { + SkASSERT(rec->fDataCount == 1); + if (value) + *value = *(const int32_t*)rec->data(); + return true; + } + return false; +} + +bool SkMetaData::findScalar(const char name[], SkScalar* value) const +{ + const Rec* rec = this->find(name, kScalar_Type); + if (rec) + { + SkASSERT(rec->fDataCount == 1); + if (value) + *value = *(const SkScalar*)rec->data(); + return true; + } + return false; +} + +const SkScalar* SkMetaData::findScalars(const char name[], int* count, SkScalar values[]) const +{ + const Rec* rec = this->find(name, kScalar_Type); + if (rec) + { + if (count) + *count = rec->fDataCount; + if (values) + memcpy(values, rec->data(), rec->fDataCount * rec->fDataLen); + return (const SkScalar*)rec->data(); + } + return NULL; +} + +bool SkMetaData::findPtr(const char name[], void** ptr, PtrProc* proc) const { + const Rec* rec = this->find(name, kPtr_Type); + if (rec) { + SkASSERT(rec->fDataCount == 1); + const PtrPair* pair = (const PtrPair*)rec->data(); + if (ptr) { + *ptr = pair->fPtr; + } + if (proc) { + *proc = pair->fProc; + } + return true; + } + return false; +} + +const char* SkMetaData::findString(const char name[]) const +{ + const Rec* rec = this->find(name, kString_Type); + SkASSERT(rec == NULL || rec->fDataLen == sizeof(char)); + return rec ? (const char*)rec->data() : NULL; +} + +bool SkMetaData::findBool(const char name[], bool* value) const +{ + const Rec* rec = this->find(name, kBool_Type); + if (rec) + { + SkASSERT(rec->fDataCount == 1); + if (value) + *value = *(const bool*)rec->data(); + return true; + } + 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; + while (rec) + { + if (rec->fType == type && !strcmp(rec->name(), name)) + return rec; + rec = rec->fNext; + } + return NULL; +} + +bool SkMetaData::remove(const char name[], Type type) { + Rec* rec = fRec; + Rec* prev = NULL; + while (rec) { + Rec* next = rec->fNext; + if (rec->fType == type && !strcmp(rec->name(), name)) { + if (prev) { + prev->fNext = next; + } else { + fRec = next; + } + + if (kPtr_Type == type) { + PtrPair* pair = (PtrPair*)rec->data(); + if (pair->fProc && pair->fPtr) { + (void)pair->fProc(pair->fPtr, false); + } + } + Rec::Free(rec); + return true; + } + prev = rec; + rec = next; + } + return false; +} + +bool SkMetaData::removeS32(const char name[]) +{ + return this->remove(name, kS32_Type); +} + +bool SkMetaData::removeScalar(const char name[]) +{ + return this->remove(name, kScalar_Type); +} + +bool SkMetaData::removeString(const char name[]) +{ + return this->remove(name, kString_Type); +} + +bool SkMetaData::removePtr(const char name[]) +{ + return this->remove(name, kPtr_Type); +} + +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) { + fRec = metadata.fRec; +} + +void SkMetaData::Iter::reset(const SkMetaData& metadata) { + fRec = metadata.fRec; +} + +const char* SkMetaData::Iter::next(SkMetaData::Type* t, int* count) { + const char* name = NULL; + + if (fRec) { + if (t) { + *t = (SkMetaData::Type)fRec->fType; + } + if (count) { + *count = fRec->fDataCount; + } + name = fRec->name(); + + fRec = fRec->fNext; + } + return name; +} + +/////////////////////////////////////////////////////////////////////////////// + +SkMetaData::Rec* SkMetaData::Rec::Alloc(size_t size) { + return (Rec*)sk_malloc_throw(size); +} + +void SkMetaData::Rec::Free(Rec* rec) { + sk_free(rec); +} + diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp index 5c0f922..95b8ed3 100644 --- a/src/core/SkPaint.cpp +++ b/src/core/SkPaint.cpp @@ -35,6 +35,14 @@ #define SK_DefaultFlags 0 //(kNativeHintsText_Flag) +#ifdef ANDROID +#define GEN_ID_INC fGenerationID++ +#define GEN_ID_INC_EVAL(expression) if (expression) { fGenerationID++; } +#else +#define GEN_ID_INC +#define GEN_ID_INC_EVAL(expression) +#endif + SkPaint::SkPaint() { // since we may have padding, we zero everything so that our memcmp() call // in operator== will work correctly. @@ -65,7 +73,9 @@ SkPaint::SkPaint() { fStyle = kFill_Style; fTextEncoding = kUTF8_TextEncoding; fHinting = kNormal_Hinting; +#ifdef ANDROID fGenerationID = 0; +#endif } SkPaint::SkPaint(const SkPaint& src) { @@ -113,9 +123,13 @@ SkPaint& SkPaint::operator=(const SkPaint& src) { SkSafeUnref(fRasterizer); SkSafeUnref(fLooper); +#ifdef ANDROID uint32_t oldGenerationID = fGenerationID; +#endif memcpy(this, &src, sizeof(src)); +#ifdef ANDROID fGenerationID = oldGenerationID + 1; +#endif return *this; } @@ -127,293 +141,206 @@ int operator==(const SkPaint& a, const SkPaint& b) { void SkPaint::reset() { SkPaint init; +#ifdef ANDROID uint32_t oldGenerationID = fGenerationID; +#endif *this = init; +#ifdef ANDROID fGenerationID = oldGenerationID + 1; +#endif } +#ifdef ANDROID uint32_t SkPaint::getGenerationID() const { return fGenerationID; } +#endif -void SkPaint::setFlags(uint32_t flags) -{ - if (fFlags != flags) { - fFlags = flags; - fGenerationID++; - } +void SkPaint::setHinting(Hinting hintingLevel) { + GEN_ID_INC_EVAL((unsigned) hintingLevel != fHinting); + fHinting = hintingLevel; } -void SkPaint::setAntiAlias(bool doAA) -{ - if (doAA != isAntiAlias()) { - this->setFlags(SkSetClearMask(fFlags, doAA, kAntiAlias_Flag)); - fGenerationID++; - } +void SkPaint::setFlags(uint32_t flags) { + GEN_ID_INC_EVAL(fFlags != flags); + fFlags = flags; } -void SkPaint::setDither(bool doDither) -{ - if (doDither != isDither()) { - this->setFlags(SkSetClearMask(fFlags, doDither, kDither_Flag)); - fGenerationID++; - } +void SkPaint::setAntiAlias(bool doAA) { + GEN_ID_INC_EVAL(doAA != isAntiAlias()); + this->setFlags(SkSetClearMask(fFlags, doAA, kAntiAlias_Flag)); } -void SkPaint::setSubpixelText(bool doSubpixel) -{ - if (doSubpixel != isSubpixelText()) { - this->setFlags(SkSetClearMask(fFlags, doSubpixel, kSubpixelText_Flag)); - fGenerationID++; - } +void SkPaint::setDither(bool doDither) { + GEN_ID_INC_EVAL(doDither != isDither()); + this->setFlags(SkSetClearMask(fFlags, doDither, kDither_Flag)); } -void SkPaint::setLCDRenderText(bool doLCDRender) -{ - if (doLCDRender != isLCDRenderText()) { - this->setFlags(SkSetClearMask(fFlags, doLCDRender, kLCDRenderText_Flag)); - fGenerationID++; - } +void SkPaint::setSubpixelText(bool doSubpixel) { + GEN_ID_INC_EVAL(doSubpixel != isSubpixelText()); + this->setFlags(SkSetClearMask(fFlags, doSubpixel, kSubpixelText_Flag)); } -void SkPaint::setEmbeddedBitmapText(bool doEmbeddedBitmapText) -{ - if (doEmbeddedBitmapText != isEmbeddedBitmapText()) { - this->setFlags(SkSetClearMask(fFlags, doEmbeddedBitmapText, kEmbeddedBitmapText_Flag)); - fGenerationID++; - } +void SkPaint::setLCDRenderText(bool doLCDRender) { + GEN_ID_INC_EVAL(doLCDRender != isLCDRenderText()); + this->setFlags(SkSetClearMask(fFlags, doLCDRender, kLCDRenderText_Flag)); +} + +void SkPaint::setEmbeddedBitmapText(bool doEmbeddedBitmapText) { + GEN_ID_INC_EVAL(doEmbeddedBitmapText != isEmbeddedBitmapText()); + this->setFlags(SkSetClearMask(fFlags, doEmbeddedBitmapText, kEmbeddedBitmapText_Flag)); } -void SkPaint::setAutohinted(bool useAutohinter) -{ +void SkPaint::setAutohinted(bool useAutohinter) { + GEN_ID_INC_EVAL(useAutohinter != isAutohinted()); this->setFlags(SkSetClearMask(fFlags, useAutohinter, kAutoHinting_Flag)); } -void SkPaint::setLinearText(bool doLinearText) -{ - if (doLinearText != isLinearText()) { - this->setFlags(SkSetClearMask(fFlags, doLinearText, kLinearText_Flag)); - fGenerationID++; - } +void SkPaint::setLinearText(bool doLinearText) { + GEN_ID_INC_EVAL(doLinearText != isLinearText()); + this->setFlags(SkSetClearMask(fFlags, doLinearText, kLinearText_Flag)); } -void SkPaint::setUnderlineText(bool doUnderline) -{ - if (doUnderline != isUnderlineText()) { - this->setFlags(SkSetClearMask(fFlags, doUnderline, kUnderlineText_Flag)); - fGenerationID++; - } +void SkPaint::setUnderlineText(bool doUnderline) { + GEN_ID_INC_EVAL(doUnderline != isUnderlineText()); + this->setFlags(SkSetClearMask(fFlags, doUnderline, kUnderlineText_Flag)); } -void SkPaint::setStrikeThruText(bool doStrikeThru) -{ - if (doStrikeThru != isStrikeThruText()) { - this->setFlags(SkSetClearMask(fFlags, doStrikeThru, kStrikeThruText_Flag)); - fGenerationID++; - } +void SkPaint::setStrikeThruText(bool doStrikeThru) { + GEN_ID_INC_EVAL(doStrikeThru != isStrikeThruText()); + this->setFlags(SkSetClearMask(fFlags, doStrikeThru, kStrikeThruText_Flag)); } -void SkPaint::setFakeBoldText(bool doFakeBold) -{ - if (doFakeBold != isFakeBoldText()) { - this->setFlags(SkSetClearMask(fFlags, doFakeBold, kFakeBoldText_Flag)); - fGenerationID++; - } +void SkPaint::setFakeBoldText(bool doFakeBold) { + GEN_ID_INC_EVAL(doFakeBold != isFakeBoldText()); + this->setFlags(SkSetClearMask(fFlags, doFakeBold, kFakeBoldText_Flag)); } -void SkPaint::setDevKernText(bool doDevKern) -{ - if (doDevKern != isDevKernText()) { - this->setFlags(SkSetClearMask(fFlags, doDevKern, kDevKernText_Flag)); - fGenerationID++; - } +void SkPaint::setDevKernText(bool doDevKern) { + GEN_ID_INC_EVAL(doDevKern != isDevKernText()); + this->setFlags(SkSetClearMask(fFlags, doDevKern, kDevKernText_Flag)); } -void SkPaint::setFilterBitmap(bool doFilter) -{ - if (doFilter != isFilterBitmap()) { - this->setFlags(SkSetClearMask(fFlags, doFilter, kFilterBitmap_Flag)); - fGenerationID++; - } +void SkPaint::setFilterBitmap(bool doFilter) { + GEN_ID_INC_EVAL(doFilter != isFilterBitmap()); + this->setFlags(SkSetClearMask(fFlags, doFilter, kFilterBitmap_Flag)); } -void SkPaint::setStyle(Style style) -{ +void SkPaint::setStyle(Style style) { if ((unsigned)style < kStyleCount) { - if ((unsigned)style != fStyle) { - fStyle = style; - fGenerationID++; - } - } -#ifdef SK_DEBUG - else { - SkDebugf("SkPaint::setStyle(%d) out of range\n", style); + GEN_ID_INC_EVAL((unsigned)style != fStyle); + fStyle = style; + } else { + SkDEBUGCODE(SkDebugf("SkPaint::setStyle(%d) out of range\n", style);) } -#endif } -void SkPaint::setColor(SkColor color) -{ - if (color != fColor) { - fColor = color; - fGenerationID++; - } +void SkPaint::setColor(SkColor color) { + GEN_ID_INC_EVAL(color != fColor); + fColor = color; } -void SkPaint::setAlpha(U8CPU a) -{ - U8CPU oldA = SkColorGetA(fColor); - if (a != oldA) { - fColor = SkColorSetARGB(a, SkColorGetR(fColor), SkColorGetG(fColor), SkColorGetB(fColor)); - fGenerationID++; - } +void SkPaint::setAlpha(U8CPU a) { + this->setColor(SkColorSetARGB(a, SkColorGetR(fColor), + SkColorGetG(fColor), SkColorGetB(fColor))); } -void SkPaint::setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) -{ - SkColor oldColor = fColor; - fColor = SkColorSetARGB(a, r, g, b); - if (oldColor != fColor) { - fGenerationID++; - } +void SkPaint::setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) { + this->setColor(SkColorSetARGB(a, r, g, b)); } -void SkPaint::setStrokeWidth(SkScalar width) -{ +void SkPaint::setStrokeWidth(SkScalar width) { if (width >= 0) { - if (width != fWidth) { - fWidth = width; - fGenerationID++; - } - } -#ifdef SK_DEBUG - else { - SkDebugf("SkPaint::setStrokeWidth() called with negative value\n"); + GEN_ID_INC_EVAL(width != fWidth); + fWidth = width; + } else { + SkDEBUGCODE(SkDebugf("SkPaint::setStrokeWidth() called with negative value\n");) } -#endif } -void SkPaint::setStrokeMiter(SkScalar limit) -{ +void SkPaint::setStrokeMiter(SkScalar limit) { if (limit >= 0) { - if (limit != fMiterLimit) { - fMiterLimit = limit; - fGenerationID++; - } - } -#ifdef SK_DEBUG - else { - SkDebugf("SkPaint::setStrokeMiter() called with negative value\n"); + GEN_ID_INC_EVAL(limit != fMiterLimit); + fMiterLimit = limit; + } else { + SkDEBUGCODE(SkDebugf("SkPaint::setStrokeMiter() called with negative value\n");) } -#endif } -void SkPaint::setStrokeCap(Cap ct) -{ +void SkPaint::setStrokeCap(Cap ct) { if ((unsigned)ct < kCapCount) { - if ((unsigned)ct != fCapType) { - fCapType = SkToU8(ct); - fGenerationID++; - } + GEN_ID_INC_EVAL((unsigned)ct != fCapType); + fCapType = SkToU8(ct); + } else { + SkDEBUGCODE(SkDebugf("SkPaint::setStrokeCap(%d) out of range\n", ct);) } -#ifdef SK_DEBUG - else - SkDebugf("SkPaint::setStrokeCap(%d) out of range\n", ct); -#endif } -void SkPaint::setStrokeJoin(Join jt) -{ +void SkPaint::setStrokeJoin(Join jt) { if ((unsigned)jt < kJoinCount) { - if ((unsigned)jt != fJoinType) { - fJoinType = SkToU8(jt); - fGenerationID++; - } + GEN_ID_INC_EVAL((unsigned)jt != fJoinType); + fJoinType = SkToU8(jt); + } else { + SkDEBUGCODE(SkDebugf("SkPaint::setStrokeJoin(%d) out of range\n", jt);) } -#ifdef SK_DEBUG - else - SkDebugf("SkPaint::setStrokeJoin(%d) out of range\n", jt); -#endif } -////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// -void SkPaint::setTextAlign(Align align) -{ +void SkPaint::setTextAlign(Align align) { if ((unsigned)align < kAlignCount) { - if ((unsigned)align != fTextAlign) { - fTextAlign = SkToU8(align); - fGenerationID++; - } + GEN_ID_INC_EVAL((unsigned)align != fTextAlign); + fTextAlign = SkToU8(align); + } else { + SkDEBUGCODE(SkDebugf("SkPaint::setTextAlign(%d) out of range\n", align);) } -#ifdef SK_DEBUG - else - SkDebugf("SkPaint::setTextAlign(%d) out of range\n", align); -#endif } -void SkPaint::setTextSize(SkScalar ts) -{ +void SkPaint::setTextSize(SkScalar ts) { if (ts > 0) { - if (ts != fTextSize) { - fTextSize = ts; - fGenerationID++; - } + GEN_ID_INC_EVAL(ts != fTextSize); + fTextSize = ts; + } else { + SkDEBUGCODE(SkDebugf("SkPaint::setTextSize() called with negative value\n");) } -#ifdef SK_DEBUG - else - SkDebugf("SkPaint::setTextSize() called with negative value\n"); -#endif } -void SkPaint::setTextScaleX(SkScalar scaleX) -{ - if (scaleX != fTextScaleX) { - fTextScaleX = scaleX; - fGenerationID++; - } +void SkPaint::setTextScaleX(SkScalar scaleX) { + GEN_ID_INC_EVAL(scaleX != fTextScaleX); + fTextScaleX = scaleX; } -void SkPaint::setTextSkewX(SkScalar skewX) -{ - if (skewX != fTextSkewX) { - fTextSkewX = skewX; - fGenerationID++; - } +void SkPaint::setTextSkewX(SkScalar skewX) { + GEN_ID_INC_EVAL(skewX != fTextSkewX); + fTextSkewX = skewX; } -void SkPaint::setTextEncoding(TextEncoding encoding) -{ +void SkPaint::setTextEncoding(TextEncoding encoding) { if ((unsigned)encoding <= kGlyphID_TextEncoding) { - if ((unsigned)encoding != fTextEncoding) { - fTextEncoding = encoding; - fGenerationID++; - } + GEN_ID_INC_EVAL((unsigned)encoding != fTextEncoding); + fTextEncoding = encoding; + } else { + SkDEBUGCODE(SkDebugf("SkPaint::setTextEncoding(%d) out of range\n", encoding);) } -#ifdef SK_DEBUG - else - SkDebugf("SkPaint::setTextEncoding(%d) out of range\n", encoding); -#endif } -/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// -SkTypeface* SkPaint::setTypeface(SkTypeface* font) -{ +SkTypeface* SkPaint::setTypeface(SkTypeface* font) { SkRefCnt_SafeAssign(fTypeface, font); - fGenerationID++; + GEN_ID_INC; return font; } SkRasterizer* SkPaint::setRasterizer(SkRasterizer* r) { SkRefCnt_SafeAssign(fRasterizer, r); - fGenerationID++; + GEN_ID_INC; return r; } SkDrawLooper* SkPaint::setLooper(SkDrawLooper* looper) { SkRefCnt_SafeAssign(fLooper, looper); - fGenerationID++; + GEN_ID_INC; return looper; } @@ -426,6 +353,7 @@ static void DetachDescProc(const SkDescriptor* desc, void* context) { *((SkGlyphCache**)context) = SkGlyphCache::DetachCache(desc); } +#ifdef ANDROID const SkGlyph& SkPaint::getUnicharMetrics(SkUnichar text) { SkGlyphCache* cache; descriptorProc(NULL, DetachDescProc, &cache, true); @@ -446,6 +374,7 @@ const void* SkPaint::findImage(const SkGlyph& glyph) { SkGlyphCache::AttachCache(cache); return image; } +#endif int SkPaint::textToGlyphs(const void* textData, size_t byteLength, uint16_t glyphs[]) const { @@ -1601,29 +1530,20 @@ void SkPaint::unflatten(SkFlattenableReadBuffer& buffer) { /////////////////////////////////////////////////////////////////////////////// -SkShader* SkPaint::setShader(SkShader* shader) -{ - if (shader != fShader) { - fGenerationID++; - } +SkShader* SkPaint::setShader(SkShader* shader) { + GEN_ID_INC_EVAL(shader != fShader); SkRefCnt_SafeAssign(fShader, shader); return shader; } -SkColorFilter* SkPaint::setColorFilter(SkColorFilter* filter) -{ - if (filter != fColorFilter) { - fGenerationID++; - } +SkColorFilter* SkPaint::setColorFilter(SkColorFilter* filter) { + GEN_ID_INC_EVAL(filter != fColorFilter); SkRefCnt_SafeAssign(fColorFilter, filter); return filter; } -SkXfermode* SkPaint::setXfermode(SkXfermode* mode) -{ - if (mode != fXfermode) { - fGenerationID++; - } +SkXfermode* SkPaint::setXfermode(SkXfermode* mode) { + GEN_ID_INC_EVAL(mode != fXfermode); SkRefCnt_SafeAssign(fXfermode, mode); return mode; } @@ -1631,24 +1551,18 @@ SkXfermode* SkPaint::setXfermode(SkXfermode* mode) SkXfermode* SkPaint::setXfermodeMode(SkXfermode::Mode mode) { SkSafeUnref(fXfermode); fXfermode = SkXfermode::Create(mode); - fGenerationID++; + GEN_ID_INC; return fXfermode; } -SkPathEffect* SkPaint::setPathEffect(SkPathEffect* effect) -{ - if (effect != fPathEffect) { - fGenerationID++; - } +SkPathEffect* SkPaint::setPathEffect(SkPathEffect* effect) { + GEN_ID_INC_EVAL(effect != fPathEffect); SkRefCnt_SafeAssign(fPathEffect, effect); return effect; } -SkMaskFilter* SkPaint::setMaskFilter(SkMaskFilter* filter) -{ - if (filter != fMaskFilter) { - fGenerationID++; - } +SkMaskFilter* SkPaint::setMaskFilter(SkMaskFilter* filter) { + GEN_ID_INC_EVAL(filter != fMaskFilter); SkRefCnt_SafeAssign(fMaskFilter, filter); return filter; } diff --git a/src/core/SkPath.cpp b/src/core/SkPath.cpp index a01d8e1..5ddc31d 100644 --- a/src/core/SkPath.cpp +++ b/src/core/SkPath.cpp @@ -96,15 +96,19 @@ static void compute_pt_bounds(SkRect* bounds, const SkTDArray<SkPoint>& pts) { //////////////////////////////////////////////////////////////////////////// SkPath::SkPath() : fBoundsIsDirty(true), fFillType(kWinding_FillType) { - fIsConvex = false; + fIsConvex = false; // really should be kUnknown +#ifdef ANDROID fGenerationID = 0; +#endif } SkPath::SkPath(const SkPath& src) { SkDEBUGCODE(src.validate();) - uint32_t currentGenID = fGenerationID; *this = src; - fGenerationID = currentGenID; +#ifdef ANDROID + // the assignment operator above increments the ID so correct for that here + fGenerationID--; +#endif } SkPath::~SkPath() { @@ -121,7 +125,7 @@ SkPath& SkPath::operator=(const SkPath& src) { fFillType = src.fFillType; fBoundsIsDirty = src.fBoundsIsDirty; fIsConvex = src.fIsConvex; - fGenerationID++; + GEN_ID_INC; } SkDEBUGCODE(this->validate();) return *this; @@ -144,20 +148,22 @@ void SkPath::swap(SkPath& other) { SkTSwap<uint8_t>(fFillType, other.fFillType); SkTSwap<uint8_t>(fBoundsIsDirty, other.fBoundsIsDirty); SkTSwap<uint8_t>(fIsConvex, other.fIsConvex); - fGenerationID++; + GEN_ID_INC; } } +#ifdef ANDROID uint32_t SkPath::getGenerationID() const { return fGenerationID; } +#endif void SkPath::reset() { SkDEBUGCODE(this->validate();) fPts.reset(); fVerbs.reset(); - fGenerationID++; + GEN_ID_INC; fBoundsIsDirty = true; fIsConvex = false; // really should be kUnknown } @@ -167,7 +173,7 @@ void SkPath::rewind() { fPts.rewind(); fVerbs.rewind(); - fGenerationID++; + GEN_ID_INC; fBoundsIsDirty = true; fIsConvex = false; // really should be kUnknown } @@ -225,7 +231,7 @@ void SkPath::setLastPt(SkScalar x, SkScalar y) { this->moveTo(x, y); } else { fPts[count - 1].set(x, y); - fGenerationID++; + GEN_ID_INC; } } @@ -263,7 +269,7 @@ void SkPath::moveTo(SkScalar x, SkScalar y) { } pt->set(x, y); - fGenerationID++; + GEN_ID_INC; fBoundsIsDirty = true; } @@ -283,7 +289,7 @@ void SkPath::lineTo(SkScalar x, SkScalar y) { fPts.append()->set(x, y); *fVerbs.append() = kLine_Verb; - fGenerationID++; + GEN_ID_INC; fBoundsIsDirty = true; } @@ -306,7 +312,7 @@ void SkPath::quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2) { pts[1].set(x2, y2); *fVerbs.append() = kQuad_Verb; - fGenerationID++; + GEN_ID_INC; fBoundsIsDirty = true; } @@ -330,7 +336,7 @@ void SkPath::cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, pts[2].set(x3, y3); *fVerbs.append() = kCubic_Verb; - fGenerationID++; + GEN_ID_INC; fBoundsIsDirty = true; } @@ -352,7 +358,7 @@ void SkPath::close() { case kQuad_Verb: case kCubic_Verb: *fVerbs.append() = kClose_Verb; - fGenerationID++; + GEN_ID_INC; break; default: // don't add a close if the prev wasn't a primitive @@ -970,7 +976,7 @@ void SkPath::transform(const SkMatrix& matrix, SkPath* dst) const { matrix.mapRect(&dst->fBounds, fBounds); dst->fBoundsIsDirty = false; } else { - dst->fGenerationID++; + GEN_ID_PTR_INC(dst); dst->fBoundsIsDirty = true; } @@ -1277,8 +1283,8 @@ void SkPath::unflatten(SkFlattenableReadBuffer& buffer) { fFillType = buffer.readS32(); buffer.read(fPts.begin(), sizeof(SkPoint) * fPts.count()); buffer.read(fVerbs.begin(), fVerbs.count()); - - fGenerationID++; + + GEN_ID_INC; fBoundsIsDirty = true; SkDEBUGCODE(this->validate();) diff --git a/src/core/SkPicturePlayback.cpp b/src/core/SkPicturePlayback.cpp index 4a4c7f8..d17599d 100644 --- a/src/core/SkPicturePlayback.cpp +++ b/src/core/SkPicturePlayback.cpp @@ -528,7 +528,9 @@ void SkPicturePlayback::draw(SkCanvas& canvas) { SkipClipRec skipRect, skipRegion, skipPath; #endif +#ifdef ANDROID SkAutoMutexAcquire autoMutex(fDrawMutex); +#endif TextContainer text; fReader.rewind(); diff --git a/src/core/SkPicturePlayback.h b/src/core/SkPicturePlayback.h index f5bf038..350df78 100644 --- a/src/core/SkPicturePlayback.h +++ b/src/core/SkPicturePlayback.h @@ -12,7 +12,10 @@ #include "SkRegion.h" #include "SkPictureFlat.h" #include "SkShape.h" + +#ifdef ANDROID #include "SkThread.h" +#endif class SkPictureRecord; class SkStream; @@ -173,7 +176,9 @@ private: SkRefCntPlayback fRCPlayback; SkTypefacePlayback fTFPlayback; SkFactoryPlayback* fFactoryPlayback; +#ifdef ANDROID SkMutex fDrawMutex; +#endif }; #endif diff --git a/src/core/SkPixelRef.cpp b/src/core/SkPixelRef.cpp index f558f52..9b12226 100644 --- a/src/core/SkPixelRef.cpp +++ b/src/core/SkPixelRef.cpp @@ -79,6 +79,14 @@ void SkPixelRef::setImmutable() { fIsImmutable = true; } +bool SkPixelRef::readPixels(SkBitmap* dst, const SkIRect* subset) { + return this->onReadPixels(dst, subset); +} + +bool SkPixelRef::onReadPixels(SkBitmap* dst, const SkIRect* subset) { + return false; +} + /////////////////////////////////////////////////////////////////////////////// #define MAX_PAIR_COUNT 16 diff --git a/src/core/SkRegion.cpp b/src/core/SkRegion.cpp index 18dafb0..e08d2f8 100644 --- a/src/core/SkRegion.cpp +++ b/src/core/SkRegion.cpp @@ -85,36 +85,29 @@ bool SkRegion::ComputeRunBounds(const SkRegion::RunType runs[], int count, SkIRe ////////////////////////////////////////////////////////////////////////// -SkRegion::SkRegion() -{ +SkRegion::SkRegion() { fBounds.set(0, 0, 0, 0); fRunHead = SkRegion_gEmptyRunHeadPtr; } -SkRegion::SkRegion(const SkRegion& src) -{ +SkRegion::SkRegion(const SkRegion& src) { fRunHead = SkRegion_gEmptyRunHeadPtr; // just need a value that won't trigger sk_free(fRunHead) this->setRegion(src); } -SkRegion::SkRegion(const SkIRect& rect) -{ +SkRegion::SkRegion(const SkIRect& rect) { fRunHead = SkRegion_gEmptyRunHeadPtr; // just need a value that won't trigger sk_free(fRunHead) this->setRect(rect); } -SkRegion::~SkRegion() -{ +SkRegion::~SkRegion() { this->freeRuns(); } -void SkRegion::freeRuns() -{ - if (fRunHead->isComplex()) - { +void SkRegion::freeRuns() { + if (fRunHead->isComplex()) { SkASSERT(fRunHead->fRefCnt >= 1); - if (sk_atomic_dec(&fRunHead->fRefCnt) == 1) - { + if (sk_atomic_dec(&fRunHead->fRefCnt) == 1) { //SkASSERT(gRgnAllocCounter > 0); //SkDEBUGCODE(sk_atomic_dec(&gRgnAllocCounter)); //SkDEBUGF(("************** gRgnAllocCounter::free %d\n", gRgnAllocCounter)); @@ -123,76 +116,68 @@ void SkRegion::freeRuns() } } -void SkRegion::allocateRuns(int count) -{ +void SkRegion::allocateRuns(int count) { fRunHead = RunHead::Alloc(count); } -SkRegion& SkRegion::operator=(const SkRegion& src) -{ +SkRegion& SkRegion::operator=(const SkRegion& src) { (void)this->setRegion(src); return *this; } -void SkRegion::swap(SkRegion& other) -{ +void SkRegion::swap(SkRegion& other) { SkTSwap<SkIRect>(fBounds, other.fBounds); SkTSwap<RunHead*>(fRunHead, other.fRunHead); } -bool SkRegion::setEmpty() -{ +bool SkRegion::setEmpty() { this->freeRuns(); fBounds.set(0, 0, 0, 0); fRunHead = SkRegion_gEmptyRunHeadPtr; return false; } -bool SkRegion::setRect(int32_t left, int32_t top, int32_t right, int32_t bottom) -{ - if (left >= right || top >= bottom) +bool SkRegion::setRect(int32_t left, int32_t top, + int32_t right, int32_t bottom) { + if (left >= right || top >= bottom) { return this->setEmpty(); - + } this->freeRuns(); fBounds.set(left, top, right, bottom); fRunHead = SkRegion_gRectRunHeadPtr; return true; } -bool SkRegion::setRect(const SkIRect& r) -{ +bool SkRegion::setRect(const SkIRect& r) { return this->setRect(r.fLeft, r.fTop, r.fRight, r.fBottom); } -bool SkRegion::setRegion(const SkRegion& src) -{ - if (this != &src) - { +bool SkRegion::setRegion(const SkRegion& src) { + if (this != &src) { this->freeRuns(); fBounds = src.fBounds; fRunHead = src.fRunHead; - if (fRunHead->isComplex()) + if (fRunHead->isComplex()) { sk_atomic_inc(&fRunHead->fRefCnt); + } } return fRunHead != SkRegion_gEmptyRunHeadPtr; } -bool SkRegion::op(const SkIRect& rect, const SkRegion& rgn, Op op) -{ +bool SkRegion::op(const SkIRect& rect, const SkRegion& rgn, Op op) { SkRegion tmp(rect); return this->op(tmp, rgn, op); } -bool SkRegion::op(const SkRegion& rgn, const SkIRect& rect, Op op) -{ +bool SkRegion::op(const SkRegion& rgn, const SkIRect& rect, Op op) { SkRegion tmp(rect); return this->op(rgn, tmp, op); } -////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// #ifdef ANDROID char* SkRegion::toString() @@ -482,52 +467,48 @@ bool SkRegion::intersects(const SkRegion& rgn) const { ///////////////////////////////////////////////////////////////////////////////////// -int operator==(const SkRegion& a, const SkRegion& b) -{ +bool operator==(const SkRegion& a, const SkRegion& b) { SkDEBUGCODE(a.validate();) SkDEBUGCODE(b.validate();) - if (&a == &b) + if (&a == &b) { return true; - if (a.fBounds != b.fBounds) + } + if (a.fBounds != b.fBounds) { return false; + } const SkRegion::RunHead* ah = a.fRunHead; const SkRegion::RunHead* bh = b.fRunHead; // this catches empties and rects being equal - if (ah == bh) + if (ah == bh) { return true; - + } // now we insist that both are complex (but different ptrs) - if (!ah->isComplex() || !bh->isComplex()) + if (!ah->isComplex() || !bh->isComplex()) { return false; - + } return ah->fRunCount == bh->fRunCount && !memcmp(ah->readonly_runs(), bh->readonly_runs(), ah->fRunCount * sizeof(SkRegion::RunType)); } -void SkRegion::translate(int dx, int dy, SkRegion* dst) const -{ +void SkRegion::translate(int dx, int dy, SkRegion* dst) const { SkDEBUGCODE(this->validate();) - if (NULL == dst) + if (NULL == dst) { return; - - if (this->isEmpty()) + } + if (this->isEmpty()) { dst->setEmpty(); - else if (this->isRect()) + } else if (this->isRect()) { dst->setRect(fBounds.fLeft + dx, fBounds.fTop + dy, fBounds.fRight + dx, fBounds.fBottom + dy); - else - { - if (this == dst) - { + } else { + if (this == dst) { dst->fRunHead = dst->fRunHead->ensureWritable(); - } - else - { + } else { SkRegion tmp; tmp.allocateRuns(fRunHead->fRunCount); tmp.fBounds = fBounds; @@ -540,17 +521,17 @@ void SkRegion::translate(int dx, int dy, SkRegion* dst) const RunType* druns = dst->fRunHead->writable_runs(); *druns++ = (SkRegion::RunType)(*sruns++ + dy); // top - for (;;) - { + for (;;) { int bottom = *sruns++; - if (bottom == kRunTypeSentinel) + if (bottom == kRunTypeSentinel) { break; + } *druns++ = (SkRegion::RunType)(bottom + dy); // bottom; - for (;;) - { + for (;;) { int x = *sruns++; - if (x == kRunTypeSentinel) + if (x == kRunTypeSentinel) { break; + } *druns++ = (SkRegion::RunType)(x + dx); *druns++ = (SkRegion::RunType)(*sruns++ + dx); } @@ -1086,7 +1067,14 @@ uint32_t SkRegion::unflatten(const void* storage) { return buffer.pos(); } -////////////////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +const SkRegion& SkRegion::GetEmptyRegion() { + static SkRegion gEmpty; + return gEmpty; +} + +/////////////////////////////////////////////////////////////////////////////// #ifdef SK_DEBUG diff --git a/src/core/SkScalerContext.cpp b/src/core/SkScalerContext.cpp index ff8e168..6b5f663 100644 --- a/src/core/SkScalerContext.cpp +++ b/src/core/SkScalerContext.cpp @@ -27,10 +27,6 @@ #include "SkStroke.h" #include "SkThread.h" -#ifdef SK_DEBUG -// #define TRACK_MISSING_CHARS -#endif - #define ComputeBWRowBytes(width) (((unsigned)(width) + 7) >> 3) static const uint8_t* gBlackGammaTable; @@ -49,14 +45,14 @@ size_t SkGlyph::computeImageSize() const { const size_t size = this->rowBytes() * fHeight; switch (fMaskFormat) { - case SkMask::kHorizontalLCD_Format: - return SkAlign4(size) + sizeof(uint32_t) * ((fWidth + 2) * fHeight); - case SkMask::kVerticalLCD_Format: - return SkAlign4(size) + sizeof(uint32_t) * (fWidth * (fHeight + 2)); - case SkMask::k3D_Format: - return 3 * size; - default: - return size; + case SkMask::kHorizontalLCD_Format: + return SkAlign4(size) + sizeof(uint32_t) * ((fWidth + 2) * fHeight); + case SkMask::kVerticalLCD_Format: + return SkAlign4(size) + sizeof(uint32_t) * (fWidth * (fHeight + 2)); + case SkMask::k3D_Format: + return 3 * size; + default: + return size; } } @@ -154,14 +150,16 @@ SkScalerContext::SkScalerContext(const SkDescriptor* desc) #ifdef DUMP_REC desc->assertChecksum(); - SkDebugf("SkScalarContext checksum %x count %d length %d\n", desc->getChecksum(), desc->getCount(), desc->getLength()); + SkDebugf("SkScalarContext checksum %x count %d length %d\n", + desc->getChecksum(), desc->getCount(), desc->getLength()); SkDebugf(" textsize %g prescale %g preskew %g post [%g %g %g %g]\n", rec->fTextSize, rec->fPreScaleX, rec->fPreSkewX, rec->fPost2x2[0][0], rec->fPost2x2[0][1], rec->fPost2x2[1][0], rec->fPost2x2[1][1]); SkDebugf(" frame %g miter %g hints %d framefill %d format %d join %d\n", rec->fFrameWidth, rec->fMiterLimit, rec->fHints, rec->fFrameAndFill, rec->fMaskFormat, rec->fStrokeJoin); - SkDebugf(" pathEffect %x maskFilter %x\n", desc->findEntry(kPathEffect_SkDescriptorTag, NULL), + SkDebugf(" pathEffect %x maskFilter %x\n", + desc->findEntry(kPathEffect_SkDescriptorTag, NULL), desc->findEntry(kMaskFilter_SkDescriptorTag, NULL)); #endif @@ -452,8 +450,9 @@ void SkScalerContext::getImage(const SkGlyph& origGlyph) { draw.drawPath(devPath, paint); } - if (lcdMode) + if (lcdMode) { glyph->expandA8ToLCD(); + } } else { this->getGlyphContext(*glyph)->generateImage(*glyph); } @@ -501,28 +500,26 @@ void SkScalerContext::getImage(const SkGlyph& origGlyph) { (fRec.fFlags & (kGammaForBlack_Flag | kGammaForWhite_Flag)) != 0) { const uint8_t* table = (fRec.fFlags & kGammaForBlack_Flag) ? gBlackGammaTable : gWhiteGammaTable; - if (NULL != table) - { + if (NULL != table) { uint8_t* dst = (uint8_t*)origGlyph.fImage; unsigned rowBytes = origGlyph.rowBytes(); - for (int y = origGlyph.fHeight - 1; y >= 0; --y) - { - for (int x = origGlyph.fWidth - 1; x >= 0; --x) + for (int y = origGlyph.fHeight - 1; y >= 0; --y) { + for (int x = origGlyph.fWidth - 1; x >= 0; --x) { dst[x] = table[dst[x]]; + } dst += rowBytes; } } } } -void SkScalerContext::getPath(const SkGlyph& glyph, SkPath* path) -{ +void SkScalerContext::getPath(const SkGlyph& glyph, SkPath* path) { this->internalGetPath(glyph, NULL, path, NULL); } -void SkScalerContext::getFontMetrics(SkPaint::FontMetrics* mx, SkPaint::FontMetrics* my) -{ +void SkScalerContext::getFontMetrics(SkPaint::FontMetrics* mx, + SkPaint::FontMetrics* my) { this->generateFontMetrics(mx, my); } @@ -530,16 +527,15 @@ SkUnichar SkScalerContext::generateGlyphToChar(uint16_t glyph) { return 0; } -/////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// -void SkScalerContext::internalGetPath(const SkGlyph& glyph, SkPath* fillPath, SkPath* devPath, SkMatrix* fillToDevMatrix) -{ +void SkScalerContext::internalGetPath(const SkGlyph& glyph, SkPath* fillPath, + SkPath* devPath, SkMatrix* fillToDevMatrix) { SkPath path; this->getGlyphContext(glyph)->generatePath(glyph, &path); - if (fRec.fFrameWidth > 0 || fPathEffect != NULL) - { + if (fRec.fFrameWidth > 0 || fPathEffect != NULL) { // need the path in user-space, with only the point-size applied // so that our stroking and effects will operate the same way they // would if the user had extracted the path themself, and then @@ -554,16 +550,15 @@ void SkScalerContext::internalGetPath(const SkGlyph& glyph, SkPath* fillPath, Sk SkScalar width = fRec.fFrameWidth; - if (fPathEffect) - { + if (fPathEffect) { SkPath effectPath; - if (fPathEffect->filterPath(&effectPath, localPath, &width)) + if (fPathEffect->filterPath(&effectPath, localPath, &width)) { localPath.swap(effectPath); + } } - if (width > 0) - { + if (width > 0) { SkStroke stroker; SkPath outline; @@ -576,41 +571,42 @@ void SkScalerContext::internalGetPath(const SkGlyph& glyph, SkPath* fillPath, Sk } // now return stuff to the caller - if (fillToDevMatrix) + if (fillToDevMatrix) { *fillToDevMatrix = matrix; - - if (devPath) + } + if (devPath) { localPath.transform(matrix, devPath); - - if (fillPath) + } + if (fillPath) { fillPath->swap(localPath); - } - else // nothing tricky to do - { - if (fillToDevMatrix) + } + } else { // nothing tricky to do + if (fillToDevMatrix) { fillToDevMatrix->reset(); - - if (devPath) - { - if (fillPath == NULL) + } + if (devPath) { + if (fillPath == NULL) { devPath->swap(path); - else + } else { *devPath = path; + } } - if (fillPath) + if (fillPath) { fillPath->swap(path); + } } - if (devPath) + if (devPath) { devPath->updateBoundsCache(); - if (fillPath) + } + if (fillPath) { fillPath->updateBoundsCache(); + } } -void SkScalerContext::Rec::getMatrixFrom2x2(SkMatrix* dst) const -{ +void SkScalerContext::Rec::getMatrixFrom2x2(SkMatrix* dst) const { dst->reset(); dst->setScaleX(fPost2x2[0][0]); dst->setSkewX( fPost2x2[0][1]); @@ -618,23 +614,20 @@ void SkScalerContext::Rec::getMatrixFrom2x2(SkMatrix* dst) const dst->setScaleY(fPost2x2[1][1]); } -void SkScalerContext::Rec::getLocalMatrix(SkMatrix* m) const -{ +void SkScalerContext::Rec::getLocalMatrix(SkMatrix* m) const { m->setScale(SkScalarMul(fTextSize, fPreScaleX), fTextSize); - if (fPreSkewX) + if (fPreSkewX) { m->postSkew(fPreSkewX, 0); + } } -void SkScalerContext::Rec::getSingleMatrix(SkMatrix* m) const -{ +void SkScalerContext::Rec::getSingleMatrix(SkMatrix* m) const { this->getLocalMatrix(m); // now concat the device matrix - { - SkMatrix deviceMatrix; - this->getMatrixFrom2x2(&deviceMatrix); - m->postConcat(deviceMatrix); - } + SkMatrix deviceMatrix; + this->getMatrixFrom2x2(&deviceMatrix); + m->postConcat(deviceMatrix); } /////////////////////////////////////////////////////////////////////////////// @@ -673,8 +666,7 @@ protected: extern SkScalerContext* SkCreateColorScalerContext(const SkDescriptor* desc); -SkScalerContext* SkScalerContext::Create(const SkDescriptor* desc) -{ +SkScalerContext* SkScalerContext::Create(const SkDescriptor* desc) { SkScalerContext* c = NULL; //SkCreateColorScalerContext(desc); if (NULL == c) { c = SkFontHost::CreateScalerContext(desc); diff --git a/src/core/SkScan_AntiPath.cpp b/src/core/SkScan_AntiPath.cpp index 90a1f68..5457b59 100644 --- a/src/core/SkScan_AntiPath.cpp +++ b/src/core/SkScan_AntiPath.cpp @@ -26,7 +26,10 @@ #define SCALE (1 << SHIFT) #define MASK (SCALE - 1) -/////////////////////////////////////////////////////////////////////////////////////////// +//#define FORCE_SUPERMASK +//#define FORCE_RLE + +/////////////////////////////////////////////////////////////////////////////// class BaseSuperBlitter : public SkBlitter { public: @@ -99,12 +102,9 @@ SuperBlitter::SuperBlitter(SkBlitter* realBlitter, const SkIRect& ir, fRuns.reset(width); } -void SuperBlitter::flush() -{ - if (fCurrIY >= 0) - { - if (!fRuns.empty()) - { +void SuperBlitter::flush() { + if (fCurrIY >= 0) { + if (!fRuns.empty()) { // SkDEBUGCODE(fRuns.dump();) fRealBlitter->blitAntiH(fLeft, fCurrIY, fRuns.fAlpha, fRuns.fRuns); fRuns.reset(fWidth); @@ -114,8 +114,7 @@ void SuperBlitter::flush() } } -static inline int coverage_to_alpha(int aa) -{ +static inline int coverage_to_alpha(int aa) { aa <<= 8 - 2*SHIFT; aa -= aa >> (8 - SHIFT - 1); return aa; @@ -123,15 +122,13 @@ static inline int coverage_to_alpha(int aa) #define SUPER_Mask ((1 << SHIFT) - 1) -void SuperBlitter::blitH(int x, int y, int width) -{ +void SuperBlitter::blitH(int x, int y, int width) { int iy = y >> SHIFT; SkASSERT(iy >= fCurrIY); x -= fSuperLeft; // hack, until I figure out why my cubics (I think) go beyond the bounds - if (x < 0) - { + if (x < 0) { width += x; x = 0; } @@ -142,8 +139,7 @@ void SuperBlitter::blitH(int x, int y, int width) fCurrY = y; #endif - if (iy != fCurrIY) // new scanline - { + if (iy != fCurrIY) { // new scanline this->flush(); fCurrIY = iy; } @@ -155,7 +151,8 @@ void SuperBlitter::blitH(int x, int y, int width) #if 0 SkAntiRun<SHIFT> arun; arun.set(x, x + width); - fRuns.add(x >> SHIFT, arun.getStartAlpha(), arun.getMiddleCount(), arun.getStopAlpha(), maxValue); + fRuns.add(x >> SHIFT, arun.getStartAlpha(), arun.getMiddleCount(), + arun.getStopAlpha(), maxValue); #else { int start = x; @@ -166,18 +163,16 @@ void SuperBlitter::blitH(int x, int y, int width) int fe = stop & SUPER_Mask; int n = (stop >> SHIFT) - (start >> SHIFT) - 1; - if (n < 0) - { + if (n < 0) { fb = fe - fb; n = 0; fe = 0; - } - else - { - if (fb == 0) + } else { + if (fb == 0) { n += 1; - else + } else { fb = (1 << SHIFT) - fb; + } } fRuns.add(x >> SHIFT, coverage_to_alpha(fb), n, coverage_to_alpha(fe), (1 << (8 - SHIFT)) - (((y & MASK) + 1) >> SHIFT)); @@ -190,8 +185,7 @@ void SuperBlitter::blitH(int x, int y, int width) #endif } -void SuperBlitter::blitRect(int x, int y, int width, int height) -{ +void SuperBlitter::blitRect(int x, int y, int width, int height) { for (int i = 0; i < height; ++i) { blitH(x, y + i, width); } @@ -211,8 +205,10 @@ public: virtual void blitH(int x, int y, int width); - static bool CanHandleRect(const SkIRect& bounds) - { + static bool CanHandleRect(const SkIRect& bounds) { +#ifdef FORCE_RLE + return false; +#endif int width = bounds.width(); int rb = SkAlign4(width); @@ -222,8 +218,13 @@ public: private: enum { +#ifdef FORCE_SUPERMASK + kMAX_WIDTH = 2048, + kMAX_STORAGE = 1024 * 1024 * 2 +#else kMAX_WIDTH = 32, // so we don't try to do very wide things, where the RLE blitter would be faster kMAX_STORAGE = 1024 +#endif }; SkMask fMask; @@ -251,8 +252,7 @@ MaskSuperBlitter::MaskSuperBlitter(SkBlitter* realBlitter, const SkIRect& ir, memset(fStorage, 0, fMask.fBounds.height() * fMask.fRowBytes + 1); } -static void add_aa_span(uint8_t* alpha, U8CPU startAlpha) -{ +static void add_aa_span(uint8_t* alpha, U8CPU startAlpha) { /* I should be able to just add alpha[x] + startAlpha. However, if the trailing edge of the previous span and the leading edge of the current span round to the same super-sampled x value, @@ -263,8 +263,16 @@ static void add_aa_span(uint8_t* alpha, U8CPU startAlpha) *alpha = SkToU8(tmp - (tmp >> 8)); } -static void add_aa_span(uint8_t* alpha, U8CPU startAlpha, int middleCount, U8CPU stopAlpha, U8CPU maxValue) -{ +static inline uint32_t quadplicate_byte(U8CPU value) { + uint32_t pair = (value << 8) | value; + return (pair << 16) | pair; +} + +// minimum count before we want to setup an inner loop, adding 4-at-a-time +#define MIN_COUNT_FOR_QUAD_LOOP 16 + +static void add_aa_span(uint8_t* alpha, U8CPU startAlpha, int middleCount, + U8CPU stopAlpha, U8CPU maxValue) { SkASSERT(middleCount >= 0); /* I should be able to just add alpha[x] + startAlpha. @@ -276,8 +284,27 @@ static void add_aa_span(uint8_t* alpha, U8CPU startAlpha, int middleCount, U8CPU SkASSERT(tmp <= 256); *alpha++ = SkToU8(tmp - (tmp >> 8)); - while (--middleCount >= 0) - { + if (middleCount >= MIN_COUNT_FOR_QUAD_LOOP) { + // loop until we're quad-byte aligned + while (SkTCast<intptr_t>(alpha) & 0x3) { + alpha[0] = SkToU8(alpha[0] + maxValue); + alpha += 1; + middleCount -= 1; + } + + int bigCount = middleCount >> 2; + uint32_t* qptr = reinterpret_cast<uint32_t*>(alpha); + uint32_t qval = quadplicate_byte(maxValue); + do { + *qptr++ += qval; + } while (--bigCount > 0); + + middleCount &= 3; + alpha = reinterpret_cast<uint8_t*> (qptr); + // fall through to the following while-loop + } + + while (--middleCount >= 0) { alpha[0] = SkToU8(alpha[0] + maxValue); alpha += 1; } @@ -289,8 +316,7 @@ static void add_aa_span(uint8_t* alpha, U8CPU startAlpha, int middleCount, U8CPU *alpha = SkToU8(*alpha + stopAlpha); } -void MaskSuperBlitter::blitH(int x, int y, int width) -{ +void MaskSuperBlitter::blitH(int x, int y, int width) { int iy = (y >> SHIFT); SkASSERT(iy >= fMask.fBounds.fTop && iy < fMask.fBounds.fBottom); @@ -313,8 +339,7 @@ void MaskSuperBlitter::blitH(int x, int y, int width) x -= (fMask.fBounds.fLeft << SHIFT); // hack, until I figure out why my cubics (I think) go beyond the bounds - if (x < 0) - { + if (x < 0) { width += x; x = 0; } @@ -334,14 +359,11 @@ void MaskSuperBlitter::blitH(int x, int y, int width) int n = (stop >> SHIFT) - (start >> SHIFT) - 1; - if (n < 0) - { + if (n < 0) { SkASSERT(row >= fMask.fImage); SkASSERT(row < fMask.fImage + kMAX_STORAGE + 1); add_aa_span(row, coverage_to_alpha(fe - fb)); - } - else - { + } else { fb = (1 << SHIFT) - fb; SkASSERT(row >= fMask.fImage); SkASSERT(row + n + 1 < fMask.fImage + kMAX_STORAGE + 1); @@ -407,8 +429,7 @@ void SkScan::AntiFillPath(const SkPath& path, const SkRegion& clip, SkIRect superRect, *superClipRect = NULL; - if (clipRect) - { + if (clipRect) { superRect.set( clipRect->fLeft << SHIFT, clipRect->fTop << SHIFT, clipRect->fRight << SHIFT, clipRect->fBottom << SHIFT); superClipRect = &superRect; @@ -418,14 +439,11 @@ void SkScan::AntiFillPath(const SkPath& path, const SkRegion& clip, // MaskSuperBlitter can't handle drawing outside of ir, so we can't use it // if we're an inverse filltype - if (!path.isInverseFillType() && MaskSuperBlitter::CanHandleRect(ir)) - { + if (!path.isInverseFillType() && MaskSuperBlitter::CanHandleRect(ir)) { MaskSuperBlitter superBlit(blitter, ir, clip); SkASSERT(SkIntToScalar(ir.fTop) <= path.getBounds().fTop); sk_fill_path(path, superClipRect, &superBlit, ir.fTop, ir.fBottom, SHIFT, clip); - } - else - { + } else { SuperBlitter superBlit(blitter, ir, clip); sk_fill_path(path, superClipRect, &superBlit, ir.fTop, ir.fBottom, SHIFT, clip); } diff --git a/src/core/SkScan_Antihair.cpp b/src/core/SkScan_Antihair.cpp index 0003298..99bd2c8 100644 --- a/src/core/SkScan_Antihair.cpp +++ b/src/core/SkScan_Antihair.cpp @@ -1,6 +1,6 @@ /* libs/graphics/sgl/SkScan_Antihair.cpp ** -** Copyright 2006, The Android Open Source Project +** Copyright 2011, 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. @@ -51,14 +51,11 @@ static inline int SmallDot6Scale(int value, int dot6) { static uint8_t gGammaTable[256]; #define ApplyGamma(table, alpha) (table)[alpha] - static void build_gamma_table() - { + static void build_gamma_table() { static bool gInit = false; - if (gInit == false) - { - for (int i = 0; i < 256; i++) - { + if (gInit == false) { + for (int i = 0; i < 256; i++) { SkFixed n = i * 257; n += n >> 15; SkASSERT(n >= 0 && n <= SK_Fixed1); @@ -76,8 +73,8 @@ static inline int SmallDot6Scale(int value, int dot6) { /////////////////////////////////////////////////////////////////////////////// -static void call_hline_blitter(SkBlitter* blitter, int x, int y, int count, U8CPU alpha) -{ +static void call_hline_blitter(SkBlitter* blitter, int x, int y, int count, + U8CPU alpha) { SkASSERT(count > 0); int16_t runs[HLINE_STACK_BUFFER + 1]; @@ -86,9 +83,9 @@ static void call_hline_blitter(SkBlitter* blitter, int x, int y, int count, U8CP aa[0] = ApplyGamma(gGammaTable, alpha); do { int n = count; - if (n > HLINE_STACK_BUFFER) + if (n > HLINE_STACK_BUFFER) { n = HLINE_STACK_BUFFER; - + } runs[0] = SkToS16(n); runs[n] = 0; blitter->blitAntiH(x, y, aa, runs); @@ -97,8 +94,8 @@ static void call_hline_blitter(SkBlitter* blitter, int x, int y, int count, U8CP } while (count > 0); } -static SkFixed hline(int x, int stopx, SkFixed fy, SkFixed /*slope*/, SkBlitter* blitter, int mod64) -{ +static SkFixed hline(int x, int stopx, SkFixed fy, SkFixed /*slope*/, + SkBlitter* blitter, int mod64) { SkASSERT(x < stopx); int count = stopx - x; fy += SK_Fixed1/2; @@ -121,8 +118,8 @@ static SkFixed hline(int x, int stopx, SkFixed fy, SkFixed /*slope*/, SkBlitter* return fy - SK_Fixed1/2; } -static SkFixed horish(int x, int stopx, SkFixed fy, SkFixed dy, SkBlitter* blitter, int mod64) -{ +static SkFixed horish(int x, int stopx, SkFixed fy, SkFixed dy, + SkBlitter* blitter, int mod64) { SkASSERT(x < stopx); #ifdef TEST_GAMMA @@ -139,8 +136,7 @@ static SkFixed horish(int x, int stopx, SkFixed fy, SkFixed dy, SkBlitter* blitt int lower_y = fy >> 16; uint8_t a = (uint8_t)(fy >> 8); unsigned ma = SmallDot6Scale(a, mod64); - if (ma) - { + if (ma) { aa[0] = ApplyGamma(gamma, ma); blitter->blitAntiH(x, lower_y, aa, runs); // the clipping blitters might edit runs, but should not affect us @@ -148,8 +144,7 @@ static SkFixed horish(int x, int stopx, SkFixed fy, SkFixed dy, SkBlitter* blitt SkASSERT(runs[1] == 0); } ma = SmallDot6Scale(255 - a, mod64); - if (ma) - { + if (ma) { aa[0] = ApplyGamma(gamma, ma); blitter->blitAntiH(x, lower_y - 1, aa, runs); // the clipping blitters might edit runs, but should not affect us @@ -162,8 +157,8 @@ static SkFixed horish(int x, int stopx, SkFixed fy, SkFixed dy, SkBlitter* blitt return fy - SK_Fixed1/2; } -static SkFixed vline(int y, int stopy, SkFixed fx, SkFixed /*slope*/, SkBlitter* blitter, int mod64) -{ +static SkFixed vline(int y, int stopy, SkFixed fx, SkFixed /*slope*/, + SkBlitter* blitter, int mod64) { SkASSERT(y < stopy); fx += SK_Fixed1/2; @@ -171,17 +166,19 @@ static SkFixed vline(int y, int stopy, SkFixed fx, SkFixed /*slope*/, SkBlitter* int a = (uint8_t)(fx >> 8); unsigned ma = SmallDot6Scale(a, mod64); - if (ma) + if (ma) { blitter->blitV(x, y, stopy - y, ApplyGamma(gGammaTable, ma)); + } ma = SmallDot6Scale(255 - a, mod64); - if (ma) + if (ma) { blitter->blitV(x - 1, y, stopy - y, ApplyGamma(gGammaTable, ma)); + } return fx - SK_Fixed1/2; } -static SkFixed vertish(int y, int stopy, SkFixed fx, SkFixed dx, SkBlitter* blitter, int mod64) -{ +static SkFixed vertish(int y, int stopy, SkFixed fx, SkFixed dx, + SkBlitter* blitter, int mod64) { SkASSERT(y < stopy); #ifdef TEST_GAMMA const uint8_t* gamma = gGammaTable; @@ -211,23 +208,21 @@ static SkFixed vertish(int y, int stopy, SkFixed fx, SkFixed dx, SkBlitter* blit return fx - SK_Fixed1/2; } -typedef SkFixed (*LineProc)(int istart, int istop, SkFixed fstart, SkFixed slope, SkBlitter*, int); +typedef SkFixed (*LineProc)(int istart, int istop, SkFixed fstart, + SkFixed slope, SkBlitter*, int); -static inline SkFixed fastfixdiv(SkFDot6 a, SkFDot6 b) -{ +static inline SkFixed fastfixdiv(SkFDot6 a, SkFDot6 b) { SkASSERT((a << 16 >> 16) == a); SkASSERT(b != 0); return (a << 16) / b; } static void do_anti_hairline(SkFDot6 x0, SkFDot6 y0, SkFDot6 x1, SkFDot6 y1, - const SkIRect* clip, SkBlitter* blitter) -{ + const SkIRect* clip, SkBlitter* blitter) { // check that we're no larger than 511 pixels (so we can do a faster div). // if we are, subdivide and call again - if (SkAbs32(x1 - x0) > SkIntToFDot6(511) || SkAbs32(y1 - y0) > SkIntToFDot6(511)) - { + if (SkAbs32(x1 - x0) > SkIntToFDot6(511) || SkAbs32(y1 - y0) > SkIntToFDot6(511)) { /* instead of (x0 + x1) >> 1, we shift each separately. This is less precise, but avoids overflowing the intermediate result if the values are huge. A better fix might be to clip the original pts @@ -246,8 +241,7 @@ static void do_anti_hairline(SkFDot6 x0, SkFDot6 y0, SkFDot6 x1, SkFDot6 y1, SkFixed fstart, slope; LineProc proc; - if (SkAbs32(x1 - x0) > SkAbs32(y1 - y0)) // mostly horizontal - { + if (SkAbs32(x1 - x0) > SkAbs32(y1 - y0)) { // mostly horizontal if (x0 > x1) { // we want to go left-to-right SkTSwap<SkFDot6>(x0, x1); SkTSwap<SkFDot6>(y0, y1); @@ -276,12 +270,11 @@ static void do_anti_hairline(SkFDot6 x0, SkFDot6 y0, SkFDot6 x1, SkFDot6 y1, scaleStop = x1 & 63; } - if (clip) - { - if (istart >= clip->fRight || istop <= clip->fLeft) + if (clip){ + if (istart >= clip->fRight || istop <= clip->fLeft) { return; - if (istart < clip->fLeft) - { + } + if (istart < clip->fLeft) { fstart += slope * (clip->fLeft - istart); istart = clip->fLeft; scaleStart = 64; @@ -291,18 +284,15 @@ static void do_anti_hairline(SkFDot6 x0, SkFDot6 y0, SkFDot6 x1, SkFDot6 y1, scaleStop = 64; } SkASSERT(istart <= istop); - if (istart == istop) + if (istart == istop) { return; - + } // now test if our Y values are completely inside the clip int top, bottom; - if (slope >= 0) // T2B - { + if (slope >= 0) { // T2B top = SkFixedFloor(fstart - SK_FixedHalf); bottom = SkFixedCeil(fstart + (istop - istart - 1) * slope + SK_FixedHalf); - } - else // B2T - { + } else { // B2T bottom = SkFixedCeil(fstart + SK_FixedHalf); top = SkFixedFloor(fstart + (istop - istart - 1) * slope - SK_FixedHalf); } @@ -310,16 +300,15 @@ static void do_anti_hairline(SkFDot6 x0, SkFDot6 y0, SkFDot6 x1, SkFDot6 y1, top -= 1; bottom += 1; #endif - if (top >= clip->fBottom || bottom <= clip->fTop) + if (top >= clip->fBottom || bottom <= clip->fTop) { return; - if (clip->fTop <= top && clip->fBottom >= bottom) + } + if (clip->fTop <= top && clip->fBottom >= bottom) { clip = NULL; + } } - } - else // mostly vertical - { - if (y0 > y1) // we want to go top-to-bottom - { + } else { // mostly vertical + if (y0 > y1) { // we want to go top-to-bottom SkTSwap<SkFDot6>(x0, x1); SkTSwap<SkFDot6>(y0, y1); } @@ -327,16 +316,13 @@ static void do_anti_hairline(SkFDot6 x0, SkFDot6 y0, SkFDot6 x1, SkFDot6 y1, istart = SkFDot6Floor(y0); istop = SkFDot6Ceil(y1); fstart = SkFDot6ToFixed(x0); - if (x0 == x1) - { + if (x0 == x1) { if (y0 == y1) { // are we zero length? return; // nothing to do } slope = 0; proc = vline; - } - else - { + } else { slope = fastfixdiv(x1 - x0, y1 - y0); SkASSERT(slope <= SK_Fixed1 && slope >= -SK_Fixed1); fstart += (slope * (32 - (y0 & 63)) + 32) >> 6; @@ -353,12 +339,11 @@ static void do_anti_hairline(SkFDot6 x0, SkFDot6 y0, SkFDot6 x1, SkFDot6 y1, scaleStop = y1 & 63; } - if (clip) - { - if (istart >= clip->fBottom || istop <= clip->fTop) + if (clip) { + if (istart >= clip->fBottom || istop <= clip->fTop) { return; - if (istart < clip->fTop) - { + } + if (istart < clip->fTop) { fstart += slope * (clip->fTop - istart); istart = clip->fTop; scaleStart = 64; @@ -373,13 +358,10 @@ static void do_anti_hairline(SkFDot6 x0, SkFDot6 y0, SkFDot6 x1, SkFDot6 y1, // now test if our X values are completely inside the clip int left, right; - if (slope >= 0) // L2R - { + if (slope >= 0) { // L2R left = SkFixedFloor(fstart - SK_FixedHalf); right = SkFixedCeil(fstart + (istop - istart - 1) * slope + SK_FixedHalf); - } - else // R2L - { + } else { // R2L right = SkFixedCeil(fstart + SK_FixedHalf); left = SkFixedFloor(fstart + (istop - istart - 1) * slope - SK_FixedHalf); } @@ -387,16 +369,17 @@ static void do_anti_hairline(SkFDot6 x0, SkFDot6 y0, SkFDot6 x1, SkFDot6 y1, left -= 1; right += 1; #endif - if (left >= clip->fRight || right <= clip->fLeft) + if (left >= clip->fRight || right <= clip->fLeft) { return; - if (clip->fLeft <= left && clip->fRight >= right) + } + if (clip->fLeft <= left && clip->fRight >= right) { clip = NULL; + } } } SkRectClipBlitter rectClipper; - if (clip) - { + if (clip) { rectClipper.init(blitter, *clip); blitter = &rectClipper; } @@ -413,10 +396,10 @@ static void do_anti_hairline(SkFDot6 x0, SkFDot6 y0, SkFDot6 x1, SkFDot6 y1, } void SkScan::AntiHairLine(const SkPoint& pt0, const SkPoint& pt1, - const SkRegion* clip, SkBlitter* blitter) -{ - if (clip && clip->isEmpty()) + const SkRegion* clip, SkBlitter* blitter) { + if (clip && clip->isEmpty()) { return; + } SkASSERT(clip == NULL || !clip->getBounds().isEmpty()); @@ -480,8 +463,8 @@ void SkScan::AntiHairLine(const SkPoint& pt0, const SkPoint& pt1, do_anti_hairline(x0, y0, x1, y1, NULL, blitter); } -void SkScan::AntiHairRect(const SkRect& rect, const SkRegion* clip, SkBlitter* blitter) -{ +void SkScan::AntiHairRect(const SkRect& rect, const SkRegion* clip, + SkBlitter* blitter) { SkPoint p0, p1; p0.set(rect.fLeft, rect.fTop); @@ -495,7 +478,7 @@ void SkScan::AntiHairRect(const SkRect& rect, const SkRegion* clip, SkBlitter* b SkScan::AntiHairLine(p0, p1, clip, blitter); } -////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// typedef int FDot8; // 24.8 integer fixed point @@ -503,77 +486,76 @@ static inline FDot8 SkFixedToFDot8(SkFixed x) { return (x + 0x80) >> 8; } -static void do_scanline(FDot8 L, int top, FDot8 R, U8CPU alpha, SkBlitter* blitter) -{ +static void do_scanline(FDot8 L, int top, FDot8 R, U8CPU alpha, + SkBlitter* blitter) { SkASSERT(L < R); - if ((L >> 8) == ((R - 1) >> 8)) // 1x1 pixel - { + if ((L >> 8) == ((R - 1) >> 8)) { // 1x1 pixel blitter->blitV(L >> 8, top, 1, SkAlphaMul(alpha, R - L)); return; } int left = L >> 8; - if (L & 0xFF) - { + if (L & 0xFF) { blitter->blitV(left, top, 1, SkAlphaMul(alpha, 256 - (L & 0xFF))); left += 1; } int rite = R >> 8; int width = rite - left; - if (width > 0) + if (width > 0) { call_hline_blitter(blitter, left, top, width, alpha); - - if (R & 0xFF) + } + if (R & 0xFF) { blitter->blitV(rite, top, 1, SkAlphaMul(alpha, R & 0xFF)); + } } -static void antifillrect(const SkXRect& xr, SkBlitter* blitter) -{ - FDot8 L = SkFixedToFDot8(xr.fLeft); - FDot8 T = SkFixedToFDot8(xr.fTop); - FDot8 R = SkFixedToFDot8(xr.fRight); - FDot8 B = SkFixedToFDot8(xr.fBottom); - +static void antifilldot8(FDot8 L, FDot8 T, FDot8 R, FDot8 B, SkBlitter* blitter, + bool fillInner) { // check for empty now that we're in our reduced precision space - if (L >= R || T >= B) + if (L >= R || T >= B) { return; - + } int top = T >> 8; - if (top == ((B - 1) >> 8)) // just one scanline high - { + if (top == ((B - 1) >> 8)) { // just one scanline high do_scanline(L, top, R, B - T - 1, blitter); return; } - if (T & 0xFF) - { + if (T & 0xFF) { do_scanline(L, top, R, 256 - (T & 0xFF), blitter); top += 1; } int bot = B >> 8; int height = bot - top; - if (height > 0) - { + if (height > 0) { int left = L >> 8; - if (L & 0xFF) - { + if (L & 0xFF) { blitter->blitV(left, top, height, 256 - (L & 0xFF)); left += 1; } int rite = R >> 8; int width = rite - left; - if (width > 0) + if (width > 0 && fillInner) { blitter->blitRect(left, top, width, height); - if (R & 0xFF) + } + if (R & 0xFF) { blitter->blitV(rite, top, height, R & 0xFF); + } } - if (B & 0xFF) + if (B & 0xFF) { do_scanline(L, bot, R, B & 0xFF, blitter); + } +} + +static void antifillrect(const SkXRect& xr, SkBlitter* blitter) { + antifilldot8(SkFixedToFDot8(xr.fLeft), SkFixedToFDot8(xr.fTop), + SkFixedToFDot8(xr.fRight), SkFixedToFDot8(xr.fBottom), + blitter, true); } /////////////////////////////////////////////////////////////////////////////// @@ -667,6 +649,165 @@ void SkScan::AntiFillRect(const SkRect& origR, const SkRegion* clip, } } +/////////////////////////////////////////////////////////////////////////////// + +#define SkAlphaMulRound(a, b) SkMulDiv255Round(a, b) + +// calls blitRect() if the rectangle is non-empty +static void fillcheckrect(int L, int T, int R, int B, SkBlitter* blitter) { + if (L < R && T < B) { + blitter->blitRect(L, T, R - L, B - T); + } +} + +static inline FDot8 SkScalarToFDot8(SkScalar x) { +#ifdef SK_SCALAR_IS_FLOAT + return (int)(x * 256); +#else + return x >> 8; +#endif +} + +static inline int FDot8Floor(FDot8 x) { + return x >> 8; +} + +static inline int FDot8Ceil(FDot8 x) { + return (x + 0xFF) >> 8; +} + +// 1 - (1 - a)*(1 - b) +static inline U8CPU InvAlphaMul(U8CPU a, U8CPU b) { + // need precise rounding (not just SkAlphaMul) so that values like + // a=228, b=252 don't overflow the result + return SkToU8(a + b - SkAlphaMulRound(a, b)); +} + +static void inner_scanline(FDot8 L, int top, FDot8 R, U8CPU alpha, + SkBlitter* blitter) { + SkASSERT(L < R); + + if ((L >> 8) == ((R - 1) >> 8)) { // 1x1 pixel + blitter->blitV(L >> 8, top, 1, InvAlphaMul(alpha, R - L)); + return; + } + + int left = L >> 8; + if (L & 0xFF) { + blitter->blitV(left, top, 1, InvAlphaMul(alpha, L & 0xFF)); + left += 1; + } + + int rite = R >> 8; + int width = rite - left; + if (width > 0) { + call_hline_blitter(blitter, left, top, width, alpha); + } + + if (R & 0xFF) { + blitter->blitV(rite, top, 1, InvAlphaMul(alpha, ~R & 0xFF)); + } +} + +static void innerstrokedot8(FDot8 L, FDot8 T, FDot8 R, FDot8 B, + SkBlitter* blitter) { + SkASSERT(L < R && T < B); + + int top = T >> 8; + if (top == ((B - 1) >> 8)) { // just one scanline high + inner_scanline(L, top, R, B - T, blitter); + return; + } + + if (T & 0xFF) { + inner_scanline(L, top, R, T & 0xFF, blitter); + top += 1; + } + + int bot = B >> 8; + int height = bot - top; + if (height > 0) { + if (L & 0xFF) { + blitter->blitV(L >> 8, top, height, L & 0xFF); + } + if (R & 0xFF) { + blitter->blitV(R >> 8, top, height, ~R & 0xFF); + } + } + + if (B & 0xFF) { + inner_scanline(L, bot, R, ~B & 0xFF, blitter); + } +} + +void SkScan::AntiFrameRect(const SkRect& r, const SkPoint& strokeSize, + const SkRegion* clip, SkBlitter* blitter) { + SkASSERT(strokeSize.fX >= 0 && strokeSize.fY >= 0); + + SkScalar rx = SkScalarHalf(strokeSize.fX); + SkScalar ry = SkScalarHalf(strokeSize.fY); + + // outset by the radius + FDot8 L = SkScalarToFDot8(r.fLeft - rx); + FDot8 T = SkScalarToFDot8(r.fTop - ry); + FDot8 R = SkScalarToFDot8(r.fRight + rx); + FDot8 B = SkScalarToFDot8(r.fBottom + ry); + + SkIRect outer; + // set outer to the outer rect of the outer section + outer.set(FDot8Floor(L), FDot8Floor(T), FDot8Ceil(R), FDot8Ceil(B)); + + SkBlitterClipper clipper; + if (clip) { + if (clip->quickReject(outer)) { + return; + } + if (!clip->contains(outer)) { + blitter = clipper.apply(blitter, clip, &outer); + } + // now we can ignore clip for the rest of the function + } + + // stroke the outer hull + antifilldot8(L, T, R, B, blitter, false); + + // set outer to the outer rect of the middle section + outer.set(FDot8Ceil(L), FDot8Ceil(T), FDot8Floor(R), FDot8Floor(B)); + + // in case we lost a bit with diameter/2 + rx = strokeSize.fX - rx; + ry = strokeSize.fY - ry; + // inset by the radius + L = SkScalarToFDot8(r.fLeft + rx); + T = SkScalarToFDot8(r.fTop + ry); + R = SkScalarToFDot8(r.fRight - rx); + B = SkScalarToFDot8(r.fBottom - ry); + + if (L >= R || T >= B) { + fillcheckrect(outer.fLeft, outer.fTop, outer.fRight, outer.fBottom, + blitter); + } else { + SkIRect inner; + // set inner to the inner rect of the middle section + inner.set(FDot8Floor(L), FDot8Floor(T), FDot8Ceil(R), FDot8Ceil(B)); + + // draw the frame in 4 pieces + fillcheckrect(outer.fLeft, outer.fTop, outer.fRight, inner.fTop, + blitter); + fillcheckrect(outer.fLeft, inner.fTop, inner.fLeft, inner.fBottom, + blitter); + fillcheckrect(inner.fRight, inner.fTop, outer.fRight, inner.fBottom, + blitter); + fillcheckrect(outer.fLeft, inner.fBottom, outer.fRight, outer.fBottom, + blitter); + + // now stroke the inner rect, which is similar to antifilldot8() except that + // it treats the fractional coordinates with the inverse bias (since its + // inner). + innerstrokedot8(L, T, R, B, blitter); + } +} + #endif diff --git a/src/core/SkScan_Hairline.cpp b/src/core/SkScan_Hairline.cpp index 0dee814..ac2c19c 100644 --- a/src/core/SkScan_Hairline.cpp +++ b/src/core/SkScan_Hairline.cpp @@ -76,8 +76,8 @@ void SkScan::HairLine(const SkPoint& pt0, const SkPoint& pt1, const SkRegion* cl // outset the right and bottom, to account for how hairlines are // actually drawn, which may hit the pixel to the right or below of // the coordinate - ptsR.fRight += SK_FDot61; - ptsR.fBottom += SK_FDot61; + ptsR.fRight += SK_FDot6One; + ptsR.fBottom += SK_FDot6One; if (!SkIRect::Intersects(ptsR, clipR)) { return; @@ -317,36 +317,39 @@ void SkScan::AntiHairPath(const SkPath& path, const SkRegion* clip, SkBlitter* b hair_path(path, clip, blitter, SkScan::AntiHairLine); } -//////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// -void SkScan::FrameRect(const SkRect& r, SkScalar diameter, const SkRegion* clip, SkBlitter* blitter) -{ - SkASSERT(diameter > 0); +void SkScan::FrameRect(const SkRect& r, const SkPoint& strokeSize, + const SkRegion* clip, SkBlitter* blitter) { + SkASSERT(strokeSize.fX >= 0 && strokeSize.fY >= 0); - if (r.isEmpty()) + if (strokeSize.fX < 0 || strokeSize.fY < 0) { return; + } - SkScalar radius = diameter / 2; + const SkScalar dx = strokeSize.fX; + const SkScalar dy = strokeSize.fY; + SkScalar rx = SkScalarHalf(dx); + SkScalar ry = SkScalarHalf(dy); SkRect outer, tmp; - outer.set( r.fLeft - radius, r.fTop - radius, - r.fRight + radius, r.fBottom + radius); + outer.set(r.fLeft - rx, r.fTop - ry, + r.fRight + rx, r.fBottom + ry); - if (r.width() <= diameter || r.height() <= diameter) - { + if (r.width() <= dx || r.height() <= dx) { SkScan::FillRect(outer, clip, blitter); return; } - tmp.set(outer.fLeft, outer.fTop, outer.fRight, outer.fTop + diameter); + tmp.set(outer.fLeft, outer.fTop, outer.fRight, outer.fTop + dy); SkScan::FillRect(tmp, clip, blitter); - tmp.fTop = outer.fBottom - diameter; + tmp.fTop = outer.fBottom - dy; tmp.fBottom = outer.fBottom; SkScan::FillRect(tmp, clip, blitter); - tmp.set(outer.fLeft, outer.fTop + diameter, outer.fLeft + diameter, outer.fBottom - diameter); + tmp.set(outer.fLeft, outer.fTop + dy, outer.fLeft + dx, outer.fBottom - dy); SkScan::FillRect(tmp, clip, blitter); - tmp.fLeft = outer.fRight - diameter; + tmp.fLeft = outer.fRight - dx; tmp.fRight = outer.fRight; SkScan::FillRect(tmp, clip, blitter); } diff --git a/src/core/SkScan_Path.cpp b/src/core/SkScan_Path.cpp index c5088a1..af5d4b1 100644 --- a/src/core/SkScan_Path.cpp +++ b/src/core/SkScan_Path.cpp @@ -30,12 +30,10 @@ #define kEDGE_TAIL_Y SK_MaxS32 #ifdef SK_DEBUG - static void validate_sort(const SkEdge* edge) - { + static void validate_sort(const SkEdge* edge) { int y = kEDGE_HEAD_Y; - while (edge->fFirstY != SK_MaxS32) - { + while (edge->fFirstY != SK_MaxS32) { edge->validate(); SkASSERT(y <= edge->fFirstY); @@ -47,14 +45,12 @@ #define validate_sort(edge) #endif -static inline void remove_edge(SkEdge* edge) -{ +static inline void remove_edge(SkEdge* edge) { edge->fPrev->fNext = edge->fNext; edge->fNext->fPrev = edge->fPrev; } -static inline void swap_edges(SkEdge* prev, SkEdge* next) -{ +static inline void swap_edges(SkEdge* prev, SkEdge* next) { SkASSERT(prev->fNext == next && next->fPrev == prev); // remove prev from the list @@ -68,31 +64,27 @@ static inline void swap_edges(SkEdge* prev, SkEdge* next) prev->fPrev = next; } -static void backward_insert_edge_based_on_x(SkEdge* edge SkDECLAREPARAM(int, curr_y)) -{ +static void backward_insert_edge_based_on_x(SkEdge* edge SkDECLAREPARAM(int, curr_y)) { SkFixed x = edge->fX; - for (;;) - { + for (;;) { SkEdge* prev = edge->fPrev; // add 1 to curr_y since we may have added new edges (built from curves) // that start on the next scanline SkASSERT(prev && prev->fFirstY <= curr_y + 1); - if (prev->fX <= x) + if (prev->fX <= x) { break; - + } swap_edges(prev, edge); } } -static void insert_new_edges(SkEdge* newEdge, int curr_y) -{ +static void insert_new_edges(SkEdge* newEdge, int curr_y) { SkASSERT(newEdge->fFirstY >= curr_y); - while (newEdge->fFirstY == curr_y) - { + while (newEdge->fFirstY == curr_y) { SkEdge* next = newEdge->fNext; backward_insert_edge_based_on_x(newEdge SkPARAM(curr_y)); newEdge = next; @@ -100,10 +92,8 @@ static void insert_new_edges(SkEdge* newEdge, int curr_y) } #ifdef SK_DEBUG -static void validate_edges_for_y(const SkEdge* edge, int curr_y) -{ - while (edge->fFirstY <= curr_y) - { +static void validate_edges_for_y(const SkEdge* edge, int curr_y) { + while (edge->fFirstY <= curr_y) { SkASSERT(edge->fPrev && edge->fNext); SkASSERT(edge->fPrev->fNext == edge); SkASSERT(edge->fNext->fPrev == edge); @@ -128,16 +118,14 @@ typedef void (*PrePostProc)(SkBlitter* blitter, int y, bool isStartOfScanline); static void walk_edges(SkEdge* prevHead, SkPath::FillType fillType, SkBlitter* blitter, int start_y, int stop_y, - PrePostProc proc) -{ + PrePostProc proc) { validate_sort(prevHead->fNext); int curr_y = start_y; // returns 1 for evenodd, -1 for winding, regardless of inverse-ness int windingMask = (fillType & 1) ? 1 : -1; - for (;;) - { + for (;;) { int w = 0; int left SK_INIT_TO_AVOID_WARNING; bool in_interval = false; @@ -150,23 +138,19 @@ static void walk_edges(SkEdge* prevHead, SkPath::FillType fillType, proc(blitter, curr_y, PREPOST_START); // pre-proc } - while (currE->fFirstY <= curr_y) - { + while (currE->fFirstY <= curr_y) { SkASSERT(currE->fLastY >= curr_y); int x = (currE->fX + SK_Fixed1/2) >> 16; w += currE->fWinding; - if ((w & windingMask) == 0) // we finished an interval - { + if ((w & windingMask) == 0) { // we finished an interval SkASSERT(in_interval); int width = x - left; SkASSERT(width >= 0); if (width) blitter->blitH(left, curr_y, width); in_interval = false; - } - else if (!in_interval) - { + } else if (!in_interval) { left = x; in_interval = true; } @@ -174,38 +158,31 @@ static void walk_edges(SkEdge* prevHead, SkPath::FillType fillType, SkEdge* next = currE->fNext; SkFixed newX; - if (currE->fLastY == curr_y) // are we done with this edge? - { - if (currE->fCurveCount < 0) - { - if (((SkCubicEdge*)currE)->updateCubic()) - { + if (currE->fLastY == curr_y) { // are we done with this edge? + if (currE->fCurveCount < 0) { + if (((SkCubicEdge*)currE)->updateCubic()) { SkASSERT(currE->fFirstY == curr_y + 1); newX = currE->fX; goto NEXT_X; } - } - else if (currE->fCurveCount > 0) - { - if (((SkQuadraticEdge*)currE)->updateQuadratic()) - { + } else if (currE->fCurveCount > 0) { + if (((SkQuadraticEdge*)currE)->updateQuadratic()) { newX = currE->fX; goto NEXT_X; } } remove_edge(currE); - } - else - { + } else { SkASSERT(currE->fLastY > curr_y); newX = currE->fX + currE->fDX; currE->fX = newX; NEXT_X: - if (newX < prevX) // ripple currE backwards until it is x-sorted + if (newX < prevX) { // ripple currE backwards until it is x-sorted backward_insert_edge_based_on_x(currE SkPARAM(curr_y)); - else + } else { prevX = newX; + } } currE = next; SkASSERT(currE); @@ -216,9 +193,9 @@ static void walk_edges(SkEdge* prevHead, SkPath::FillType fillType, } curr_y += 1; - if (curr_y >= stop_y) + if (curr_y >= stop_y) { break; - + } // now currE points to the first edge with a Yint larger than curr_y insert_new_edges(currE, curr_y); } @@ -291,19 +268,6 @@ static void PrePostInverseBlitterProc(SkBlitter* blitter, int y, bool isStart) { #pragma warning ( pop ) #endif -/* Our line edge relies on the maximum span being <= 512, so that it can - use FDot6 and keep the dx,dy in 16bits (for much faster slope divide). - This function returns true if the specified line is too big. -*/ -static inline bool line_too_big(const SkPoint pts[2]) -{ - SkScalar dx = pts[1].fX - pts[0].fX; - SkScalar dy = pts[1].fY - pts[0].fY; - - return SkScalarAbs(dx) > SkIntToScalar(511) || - SkScalarAbs(dy) > SkIntToScalar(511); -} - #ifdef USE_NEW_BUILDER #include "SkEdgeBuilder.h" #else @@ -379,31 +343,29 @@ static int build_edges(SkEdge edge[], const SkPath& path, /* 'quick' computation of the max sized needed to allocated for our edgelist. */ -static int worst_case_edge_count(const SkPath& path, size_t* storage) -{ +static int worst_case_edge_count(const SkPath& path, size_t* storage) { size_t size = 0; int edgeCount = 0; SkPath::Iter iter(path, true); SkPath::Verb verb; - while ((verb = iter.next(NULL)) != SkPath::kDone_Verb) - { + while ((verb = iter.next(NULL)) != SkPath::kDone_Verb) { switch (verb) { - case SkPath::kLine_Verb: - edgeCount += 1; - size += sizeof(SkQuadraticEdge); // treat line like Quad (in case its > 512) - break; - case SkPath::kQuad_Verb: - edgeCount += 2; // might need 2 edges when we chop on Y extrema - size += 2 * sizeof(SkQuadraticEdge); - break; - case SkPath::kCubic_Verb: - edgeCount += 3; // might need 3 edges when we chop on Y extrema - size += 3 * sizeof(SkCubicEdge); - break; - default: - break; + case SkPath::kLine_Verb: + edgeCount += 1; + size += sizeof(SkQuadraticEdge); // treat line like Quad (in case its > 512) + break; + case SkPath::kQuad_Verb: + edgeCount += 2; // might need 2 edges when we chop on Y extrema + size += 2 * sizeof(SkQuadraticEdge); + break; + case SkPath::kCubic_Verb: + edgeCount += 3; // might need 3 edges when we chop on Y extrema + size += 3 * sizeof(SkCubicEdge); + break; + default: + break; } } @@ -477,8 +439,8 @@ static SkEdge* sort_edges(SkEdge* list[], int count, SkEdge** last) { // clipRect (if no null) has already been shifted up // void sk_fill_path(const SkPath& path, const SkIRect* clipRect, SkBlitter* blitter, - int start_y, int stop_y, int shiftEdgesUp, const SkRegion& clipRgn) -{ + int start_y, int stop_y, int shiftEdgesUp, + const SkRegion& clipRgn) { SkASSERT(&path && blitter); #ifdef USE_NEW_BUILDER @@ -583,35 +545,30 @@ void sk_blit_below(SkBlitter* blitter, const SkIRect& ir, const SkRegion& clip) } } -///////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// -SkScanClipper::SkScanClipper(SkBlitter* blitter, const SkRegion* clip, const SkIRect& ir) -{ +SkScanClipper::SkScanClipper(SkBlitter* blitter, const SkRegion* clip, + const SkIRect& ir) { fBlitter = NULL; // null means blit nothing fClipRect = NULL; - if (clip) - { + if (clip) { fClipRect = &clip->getBounds(); - if (!SkIRect::Intersects(*fClipRect, ir)) // completely clipped out + if (!SkIRect::Intersects(*fClipRect, ir)) { // completely clipped out return; + } - if (clip->isRect()) - { - if (fClipRect->contains(ir)) + if (clip->isRect()) { + if (fClipRect->contains(ir)) { fClipRect = NULL; - else - { + } else { // only need a wrapper blitter if we're horizontally clipped - if (fClipRect->fLeft > ir.fLeft || fClipRect->fRight < ir.fRight) - { + if (fClipRect->fLeft > ir.fLeft || fClipRect->fRight < ir.fRight) { fRectBlitter.init(blitter, *fClipRect); blitter = &fRectBlitter; } } - } - else - { + } else { fRgnBlitter.init(blitter, clip); blitter = &fRgnBlitter; } diff --git a/src/core/SkString.cpp b/src/core/SkString.cpp index b8f99c7..49182ea 100644 --- a/src/core/SkString.cpp +++ b/src/core/SkString.cpp @@ -42,15 +42,13 @@ static const size_t kBufferSize = 256; /////////////////////////////////////////////////////////////////////////////// -bool SkStrStartsWith(const char string[], const char prefix[]) -{ +bool SkStrStartsWith(const char string[], const char prefix[]) { SkASSERT(string); SkASSERT(prefix); return !strncmp(string, prefix, strlen(prefix)); } -bool SkStrEndsWith(const char string[], const char suffix[]) -{ +bool SkStrEndsWith(const char string[], const char suffix[]) { SkASSERT(string); SkASSERT(suffix); size_t strLen = strlen(string); @@ -59,50 +57,50 @@ bool SkStrEndsWith(const char string[], const char suffix[]) !strncmp(string + strLen - suffixLen, suffix, suffixLen); } -int SkStrStartsWithOneOf(const char string[], const char prefixes[]) -{ +int SkStrStartsWithOneOf(const char string[], const char prefixes[]) { int index = 0; do { const char* limit = strchr(prefixes, '\0'); - if (!strncmp(string, prefixes, limit - prefixes)) + if (!strncmp(string, prefixes, limit - prefixes)) { return index; + } prefixes = limit + 1; index++; } while (prefixes[0]); return -1; } -char* SkStrAppendS32(char string[], int32_t dec) -{ +char* SkStrAppendS32(char string[], int32_t dec) { SkDEBUGCODE(char* start = string;) char buffer[SkStrAppendS32_MaxSize]; char* p = buffer + sizeof(buffer); bool neg = false; - if (dec < 0) - { + if (dec < 0) { neg = true; dec = -dec; } + do { *--p = SkToU8('0' + dec % 10); dec /= 10; } while (dec != 0); - if (neg) + + if (neg) { *--p = '-'; + } SkASSERT(p >= buffer); char* stop = buffer + sizeof(buffer); - while (p < stop) + while (p < stop) { *string++ = *p++; - + } SkASSERT(string - start <= SkStrAppendS32_MaxSize); return string; } -char* SkStrAppendS64(char string[], int64_t dec, int minDigits) -{ +char* SkStrAppendS64(char string[], int64_t dec, int minDigits) { SkDEBUGCODE(char* start = string;) char buffer[SkStrAppendS64_MaxSize]; @@ -113,18 +111,21 @@ char* SkStrAppendS64(char string[], int64_t dec, int minDigits) neg = true; dec = -dec; } + do { *--p = SkToU8('0' + dec % 10); dec /= 10; minDigits--; } while (dec != 0); + while (minDigits > 0) { *--p = '0'; minDigits--; } - if (neg) - *--p = '-'; + if (neg) { + *--p = '-'; + } SkASSERT(p >= buffer); size_t cp_len = buffer + sizeof(buffer) - p; memcpy(string, p, cp_len); @@ -135,8 +136,7 @@ char* SkStrAppendS64(char string[], int64_t dec, int minDigits) } #ifdef SK_CAN_USE_FLOAT -char* SkStrAppendFloat(char string[], float value) -{ +char* SkStrAppendFloat(char string[], float value) { // since floats have at most 8 significant digits, we limit our %g to that. static const char gFormat[] = "%.8g"; // make it 1 larger for the terminating 0 @@ -148,27 +148,24 @@ char* SkStrAppendFloat(char string[], float value) } #endif -char* SkStrAppendFixed(char string[], SkFixed x) -{ +char* SkStrAppendFixed(char string[], SkFixed x) { SkDEBUGCODE(char* start = string;) - if (x < 0) - { + if (x < 0) { *string++ = '-'; x = -x; } unsigned frac = x & 0xFFFF; x >>= 16; - if (frac == 0xFFFF) // need to do this to "round up", since 65535/65536 is closer to 1 than to .9999 - { + if (frac == 0xFFFF) { + // need to do this to "round up", since 65535/65536 is closer to 1 than to .9999 x += 1; frac = 0; } string = SkStrAppendS32(string, x); // now handle the fractional part (if any) - if (frac) - { + if (frac) { static const uint16_t gTens[] = { 1000, 100, 10, 1 }; const uint16_t* tens = gTens; @@ -189,7 +186,7 @@ char* SkStrAppendFixed(char string[], SkFixed x) return string; } -//////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// #define kMaxRefCnt_SkString SK_MaxU16 @@ -198,47 +195,43 @@ const SkString::Rec SkString::gEmptyRec = { 0, 0, 0 }; #define SizeOfRec() (gEmptyRec.data() - (const char*)&gEmptyRec) -SkString::Rec* SkString::AllocRec(const char text[], U16CPU len) -{ +SkString::Rec* SkString::AllocRec(const char text[], U16CPU len) { Rec* rec; - if (len == 0) + if (len == 0) { rec = const_cast<Rec*>(&gEmptyRec); - else - { + } else { // add 1 for terminating 0, then align4 so we can have some slop when growing the string rec = (Rec*)sk_malloc_throw(SizeOfRec() + SkAlign4(len + 1)); rec->fLength = SkToU16(len); rec->fRefCnt = 1; - if (text) + if (text) { memcpy(rec->data(), text, len); + } rec->data()[len] = 0; } return rec; } -SkString::Rec* SkString::RefRec(Rec* src) -{ - if (src != &gEmptyRec) - { +SkString::Rec* SkString::RefRec(Rec* src) { + if (src != &gEmptyRec) { if (src->fRefCnt == kMaxRefCnt_SkString) { src = AllocRec(src->data(), src->fLength); - } else + } else { src->fRefCnt += 1; + } } return src; } #ifdef SK_DEBUG -void SkString::validate() const -{ +void SkString::validate() const { // make sure know one has written over our global SkASSERT(gEmptyRec.fLength == 0); SkASSERT(gEmptyRec.fRefCnt == 0); SkASSERT(gEmptyRec.data()[0] == 0); - if (fRec != &gEmptyRec) - { + if (fRec != &gEmptyRec) { SkASSERT(fRec->fLength > 0); SkASSERT(fRec->fRefCnt > 0); SkASSERT(fRec->data()[fRec->fLength] == 0); @@ -247,7 +240,7 @@ void SkString::validate() const } #endif -/////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// SkString::SkString() : fRec(const_cast<Rec*>(&gEmptyRec)) { #ifdef SK_DEBUG @@ -255,8 +248,7 @@ SkString::SkString() : fRec(const_cast<Rec*>(&gEmptyRec)) { #endif } -SkString::SkString(size_t len) -{ +SkString::SkString(size_t len) { SkASSERT(SkToU16(len) == len); // can't handle larger than 64K fRec = AllocRec(NULL, (U16CPU)len); @@ -265,8 +257,7 @@ SkString::SkString(size_t len) #endif } -SkString::SkString(const char text[]) -{ +SkString::SkString(const char text[]) { size_t len = text ? strlen(text) : 0; fRec = AllocRec(text, (U16CPU)len); @@ -275,16 +266,14 @@ SkString::SkString(const char text[]) #endif } -SkString::SkString(const char text[], size_t len) -{ +SkString::SkString(const char text[], size_t len) { fRec = AllocRec(text, (U16CPU)len); #ifdef SK_DEBUG fStr = fRec->data(); #endif } -SkString::SkString(const SkString& src) -{ +SkString::SkString(const SkString& src) { src.validate(); fRec = RefRec(src.fRec); @@ -293,56 +282,49 @@ SkString::SkString(const SkString& src) #endif } -SkString::~SkString() -{ +SkString::~SkString() { this->validate(); - if (fRec->fLength) - { + if (fRec->fLength) { SkASSERT(fRec->fRefCnt > 0); - if (--fRec->fRefCnt == 0) + if (--fRec->fRefCnt == 0) { sk_free(fRec); + } } } -bool SkString::equals(const SkString& src) const -{ +bool SkString::equals(const SkString& src) const { return fRec == src.fRec || this->equals(src.c_str(), src.size()); } -bool SkString::equals(const char text[]) const -{ +bool SkString::equals(const char text[]) const { return this->equals(text, text ? strlen(text) : 0); } -bool SkString::equals(const char text[], size_t len) const -{ +bool SkString::equals(const char text[], size_t len) const { SkASSERT(len == 0 || text != NULL); return fRec->fLength == len && !memcmp(fRec->data(), text, len); } -SkString& SkString::operator=(const SkString& src) -{ +SkString& SkString::operator=(const SkString& src) { this->validate(); - if (fRec != src.fRec) - { + if (fRec != src.fRec) { SkString tmp(src); this->swap(tmp); } return *this; } -void SkString::reset() -{ +void SkString::reset() { this->validate(); - if (fRec->fLength) - { + if (fRec->fLength) { SkASSERT(fRec->fRefCnt > 0); - if (--fRec->fRefCnt == 0) + if (--fRec->fRefCnt == 0) { sk_free(fRec); + } } fRec = const_cast<Rec*>(&gEmptyRec); @@ -351,14 +333,11 @@ void SkString::reset() #endif } -char* SkString::writable_str() -{ +char* SkString::writable_str() { this->validate(); - if (fRec->fLength) - { - if (fRec->fRefCnt > 1) - { + if (fRec->fLength) { + if (fRec->fRefCnt > 1) { fRec->fRefCnt -= 1; fRec = AllocRec(fRec->data(), fRec->fLength); #ifdef SK_DEBUG @@ -369,86 +348,79 @@ char* SkString::writable_str() return fRec->data(); } -void SkString::set(const char text[]) -{ +void SkString::set(const char text[]) { this->set(text, text ? strlen(text) : 0); } -void SkString::set(const char text[], size_t len) -{ - if (len == 0) +void SkString::set(const char text[], size_t len) { + if (len == 0) { this->reset(); - else if (fRec->fRefCnt == 1 && len <= fRec->fLength) // should we resize if len <<<< fLength, to save RAM? (e.g. len < (fLength>>1)) - { + } else if (fRec->fRefCnt == 1 && len <= fRec->fLength) { + // should we resize if len <<<< fLength, to save RAM? (e.g. len < (fLength>>1))? // just use less of the buffer without allocating a smaller one char* p = this->writable_str(); - if (text) + if (text) { memcpy(p, text, len); + } p[len] = 0; fRec->fLength = SkToU16(len); - } - else if (fRec->fRefCnt == 1 && ((unsigned)fRec->fLength >> 2) == (len >> 2)) - { + } else if (fRec->fRefCnt == 1 && ((unsigned)fRec->fLength >> 2) == (len >> 2)) { // we have spare room in the current allocation, so don't alloc a larger one char* p = this->writable_str(); - if (text) + if (text) { memcpy(p, text, len); + } p[len] = 0; fRec->fLength = SkToU16(len); - } - else - { + } else { SkString tmp(text, len); this->swap(tmp); } } -void SkString::setUTF16(const uint16_t src[]) -{ +void SkString::setUTF16(const uint16_t src[]) { int count = 0; - while (src[count]) + while (src[count]) { count += 1; + } setUTF16(src, count); } -void SkString::setUTF16(const uint16_t src[], size_t count) -{ - if (count == 0) +void SkString::setUTF16(const uint16_t src[], size_t count) { + if (count == 0) { this->reset(); - else if (count <= fRec->fLength) // should we resize if len <<<< fLength, to save RAM? (e.g. len < (fLength>>1)) - { - if (count < fRec->fLength) + } else if (count <= fRec->fLength) { + // should we resize if len <<<< fLength, to save RAM? (e.g. len < (fLength>>1)) + if (count < fRec->fLength) { this->resize(count); + } char* p = this->writable_str(); - for (size_t i = 0; i < count; i++) + for (size_t i = 0; i < count; i++) { p[i] = SkToU8(src[i]); + } p[count] = 0; - } - else - { - SkString tmp(count); // puts a null terminator at the end of the string - char* p = tmp.writable_str(); + } else { + SkString tmp(count); // puts a null terminator at the end of the string + char* p = tmp.writable_str(); - for (size_t i = 0; i < count; i++) + for (size_t i = 0; i < count; i++) { p[i] = SkToU8(src[i]); - + } this->swap(tmp); } } -void SkString::insert(size_t offset, const char text[]) -{ +void SkString::insert(size_t offset, const char text[]) { this->insert(offset, text, text ? strlen(text) : 0); } -void SkString::insert(size_t offset, const char text[], size_t len) -{ - if (len) - { +void SkString::insert(size_t offset, const char text[], size_t len) { + if (len) { size_t length = fRec->fLength; - if (offset > length) + if (offset > length) { offset = length; + } /* If we're the only owner, and we have room in our allocation for the insert, do it in place, rather than allocating a new buffer. @@ -460,61 +432,59 @@ void SkString::insert(size_t offset, const char text[], size_t len) which is equivalent for testing to (length + 1 + 3) >> 2 == (length + 1 + 3 + len) >> 2 and we can then eliminate the +1+3 since that doesn't affec the answer */ - if (fRec->fRefCnt == 1 && (length >> 2) == ((length + len) >> 2)) - { + if (fRec->fRefCnt == 1 && (length >> 2) == ((length + len) >> 2)) { char* dst = this->writable_str(); - if (offset < length) + if (offset < length) { memmove(dst + offset + len, dst + offset, length - offset); + } memcpy(dst + offset, text, len); dst[length + len] = 0; fRec->fLength = SkToU16(length + len); - } - else - { + } else { /* Seems we should use realloc here, since that is safe if it fails (we have the original data), and might be faster than alloc/copy/free. */ SkString tmp(fRec->fLength + len); char* dst = tmp.writable_str(); - if (offset > 0) + if (offset > 0) { memcpy(dst, fRec->data(), offset); + } memcpy(dst + offset, text, len); - if (offset < fRec->fLength) - memcpy(dst + offset + len, fRec->data() + offset, fRec->fLength - offset); + if (offset < fRec->fLength) { + memcpy(dst + offset + len, fRec->data() + offset, + fRec->fLength - offset); + } this->swap(tmp); } } } -void SkString::insertUnichar(size_t offset, SkUnichar uni) -{ +void SkString::insertUnichar(size_t offset, SkUnichar uni) { char buffer[kMaxBytesInUTF8Sequence]; size_t len = SkUTF8_FromUnichar(uni, buffer); - if (len) + if (len) { this->insert(offset, buffer, len); + } } -void SkString::insertS32(size_t offset, int32_t dec) -{ +void SkString::insertS32(size_t offset, int32_t dec) { char buffer[SkStrAppendS32_MaxSize]; char* stop = SkStrAppendS32(buffer, dec); this->insert(offset, buffer, stop - buffer); } -void SkString::insertS64(size_t offset, int64_t dec, int minDigits) -{ +void SkString::insertS64(size_t offset, int64_t dec, int minDigits) { char buffer[SkStrAppendS64_MaxSize]; char* stop = SkStrAppendS64(buffer, dec, minDigits); this->insert(offset, buffer, stop - buffer); } -void SkString::insertHex(size_t offset, uint32_t hex, int minDigits) -{ +void SkString::insertHex(size_t offset, uint32_t hex, int minDigits) { minDigits = SkPin32(minDigits, 0, 8); static const char gHex[] = "0123456789ABCDEF"; @@ -527,15 +497,16 @@ void SkString::insertHex(size_t offset, uint32_t hex, int minDigits) hex >>= 4; minDigits -= 1; } while (hex != 0); - while (--minDigits >= 0) + + while (--minDigits >= 0) { *--p = '0'; + } SkASSERT(p >= buffer); this->insert(offset, p, buffer + sizeof(buffer) - p); } -void SkString::insertScalar(size_t offset, SkScalar value) -{ +void SkString::insertScalar(size_t offset, SkScalar value) { char buffer[SkStrAppendScalar_MaxSize]; char* stop = SkStrAppendScalar(buffer, value); this->insert(offset, buffer, stop - buffer); @@ -566,30 +537,26 @@ void SkString::prependf(const char format[], ...) { /////////////////////////////////////////////////////////////////////////////// -void SkString::remove(size_t offset, size_t length) -{ +void SkString::remove(size_t offset, size_t length) { size_t size = this->size(); - if (offset < size) - { - if (offset + length > size) + if (offset < size) { + if (offset + length > size) { length = size - offset; - if (length > 0) - { + } + if (length > 0) { SkASSERT(size > length); SkString tmp(size - length); char* dst = tmp.writable_str(); const char* src = this->c_str(); - if (offset) - { + if (offset) { SkASSERT(offset <= tmp.size()); memcpy(dst, src, offset); } size_t tail = size - offset - length; SkASSERT((int32_t)tail >= 0); - if (tail) - { + if (tail) { // SkASSERT(offset + length <= tmp.size()); memcpy(dst + offset, src + offset + length, tail); } @@ -599,8 +566,7 @@ void SkString::remove(size_t offset, size_t length) } } -void SkString::swap(SkString& other) -{ +void SkString::swap(SkString& other) { this->validate(); other.validate(); @@ -610,25 +576,23 @@ void SkString::swap(SkString& other) #endif } -///////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// -SkAutoUCS2::SkAutoUCS2(const char utf8[]) -{ +SkAutoUCS2::SkAutoUCS2(const char utf8[]) { size_t len = strlen(utf8); fUCS2 = (uint16_t*)sk_malloc_throw((len + 1) * sizeof(uint16_t)); uint16_t* dst = fUCS2; - for (;;) - { - SkUnichar uni = SkUTF8_NextUnichar(&utf8); + for (;;) { + SkUnichar uni = SkUTF8_NextUnichar(&utf8); *dst++ = SkToU16(uni); - if (uni == 0) + if (uni == 0) { break; + } } fCount = (int)(dst - fUCS2); } -SkAutoUCS2::~SkAutoUCS2() -{ - delete[] fUCS2; +SkAutoUCS2::~SkAutoUCS2() { + sk_free(fUCS2); } diff --git a/src/core/SkTypeface.cpp b/src/core/SkTypeface.cpp index 7eeaf19..9a764fc 100644 --- a/src/core/SkTypeface.cpp +++ b/src/core/SkTypeface.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +#include "SkAdvancedTypefaceMetrics.h" #include "SkTypeface.h" #include "SkFontHost.h" @@ -76,6 +77,6 @@ SkTypeface* SkTypeface::Deserialize(SkStream* stream) { } SkAdvancedTypefaceMetrics* SkTypeface::getAdvancedTypefaceMetrics( - bool perGlyphInfo) const { + SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo) const { return SkFontHost::GetAdvancedTypefaceMetrics(fUniqueID, perGlyphInfo); } diff --git a/src/core/SkUtils.cpp b/src/core/SkUtils.cpp index 9fb85c2..6aa57ee 100644 --- a/src/core/SkUtils.cpp +++ b/src/core/SkUtils.cpp @@ -43,18 +43,17 @@ } while (0) #endif -/////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// -void sk_memset16_portable(uint16_t dst[], uint16_t value, int count) -{ +void sk_memset16_portable(uint16_t dst[], uint16_t value, int count) { SkASSERT(dst != NULL && count >= 0); - if (count <= 0) + if (count <= 0) { return; + } // not sure if this helps to short-circuit on small values of count - if (count < 8) - { + if (count < 8) { do { *dst++ = (uint16_t)value; } while (--count != 0); @@ -62,8 +61,7 @@ void sk_memset16_portable(uint16_t dst[], uint16_t value, int count) } // ensure we're on a long boundary - if ((size_t)dst & 2) - { + if ((size_t)dst & 2) { *dst++ = (uint16_t)value; count -= 1; } @@ -73,8 +71,7 @@ void sk_memset16_portable(uint16_t dst[], uint16_t value, int count) // handle the bulk with our unrolled macro { int sixteenlongs = count >> 5; - if (sixteenlongs) - { + if (sixteenlongs) { uint32_t* dst32 = (uint32_t*)dst; do { assign_16_longs(dst32, value32); @@ -87,8 +84,7 @@ void sk_memset16_portable(uint16_t dst[], uint16_t value, int count) // handle (most) of the rest { int longs = count >> 1; - if (longs) - { + if (longs) { do { *(uint32_t*)dst = value32; dst += 2; @@ -97,27 +93,23 @@ void sk_memset16_portable(uint16_t dst[], uint16_t value, int count) } // cleanup a possible trailing short - if (count & 1) + if (count & 1) { *dst = (uint16_t)value; + } } -void sk_memset32_portable(uint32_t dst[], uint32_t value, int count) -{ +void sk_memset32_portable(uint32_t dst[], uint32_t value, int count) { SkASSERT(dst != NULL && count >= 0); - { - int sixteenlongs = count >> 4; - if (sixteenlongs) - { - do { - assign_16_longs(dst, value); - } while (--sixteenlongs != 0); - count &= 15; - } + int sixteenlongs = count >> 4; + if (sixteenlongs) { + do { + assign_16_longs(dst, value); + } while (--sixteenlongs != 0); + count &= 15; } - if (count) - { + if (count) { do { *dst++ = value; } while (--count != 0); @@ -125,8 +117,7 @@ void sk_memset32_portable(uint32_t dst[], uint32_t value, int count) } #if !defined(ANDROID) || defined(SK_BUILD_FOR_ANDROID_NDK) -static void sk_memset16_stub(uint16_t dst[], uint16_t value, int count) -{ +static void sk_memset16_stub(uint16_t dst[], uint16_t value, int count) { SkMemset16Proc proc = SkMemset16GetPlatformProc(); sk_memset16 = proc ? proc : sk_memset16_portable; sk_memset16(dst, value, count); @@ -134,8 +125,7 @@ static void sk_memset16_stub(uint16_t dst[], uint16_t value, int count) SkMemset16Proc sk_memset16 = sk_memset16_stub; -static void sk_memset32_stub(uint32_t dst[], uint32_t value, int count) -{ +static void sk_memset32_stub(uint32_t dst[], uint32_t value, int count) { SkMemset32Proc proc = SkMemset32GetPlatformProc(); sk_memset32 = proc ? proc : sk_memset32_portable; sk_memset32(dst, value, count); @@ -145,7 +135,7 @@ SkMemset32Proc sk_memset32 = sk_memset32_stub; #endif -////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// /* 0xxxxxxx 1 total 10xxxxxx // never a leading byte @@ -159,14 +149,12 @@ SkMemset32Proc sk_memset32 = sk_memset32_stub; */ #ifdef SK_DEBUG - static void assert_utf8_leadingbyte(unsigned c) - { + static void assert_utf8_leadingbyte(unsigned c) { SkASSERT(c <= 0xF7); // otherwise leading byte is too big (more than 4 bytes) SkASSERT((c & 0xC0) != 0x80); // can't begin with a middle char } - int SkUTF8_LeadByteToCount(unsigned c) - { + int SkUTF8_LeadByteToCount(unsigned c) { assert_utf8_leadingbyte(c); return (((0xE5 << 24) >> (c >> 4 << 1)) & 3) + 1; } @@ -174,41 +162,36 @@ SkMemset32Proc sk_memset32 = sk_memset32_stub; #define assert_utf8_leadingbyte(c) #endif -int SkUTF8_CountUnichars(const char utf8[]) -{ +int SkUTF8_CountUnichars(const char utf8[]) { SkASSERT(utf8); int count = 0; - for (;;) - { + for (;;) { int c = *(const uint8_t*)utf8; - if (c == 0) + if (c == 0) { break; - + } utf8 += SkUTF8_LeadByteToCount(c); count += 1; } return count; } -int SkUTF8_CountUnichars(const char utf8[], size_t byteLength) -{ +int SkUTF8_CountUnichars(const char utf8[], size_t byteLength) { SkASSERT(NULL != utf8 || 0 == byteLength); int count = 0; const char* stop = utf8 + byteLength; - while (utf8 < stop) - { + while (utf8 < stop) { utf8 += SkUTF8_LeadByteToCount(*(const uint8_t*)utf8); count += 1; } return count; } -SkUnichar SkUTF8_ToUnichar(const char utf8[]) -{ +SkUnichar SkUTF8_ToUnichar(const char utf8[]) { SkASSERT(NULL != utf8); const uint8_t* p = (const uint8_t*)utf8; @@ -217,8 +200,7 @@ SkUnichar SkUTF8_ToUnichar(const char utf8[]) assert_utf8_leadingbyte(c); - if (hic < 0) - { + if (hic < 0) { uint32_t mask = (uint32_t)~0x3F; hic <<= 1; do { @@ -230,8 +212,7 @@ SkUnichar SkUTF8_ToUnichar(const char utf8[]) return c; } -SkUnichar SkUTF8_NextUnichar(const char** ptr) -{ +SkUnichar SkUTF8_NextUnichar(const char** ptr) { SkASSERT(NULL != ptr && NULL != *ptr); const uint8_t* p = (const uint8_t*)*ptr; @@ -240,8 +221,7 @@ SkUnichar SkUTF8_NextUnichar(const char** ptr) assert_utf8_leadingbyte(c); - if (hic < 0) - { + if (hic < 0) { uint32_t mask = (uint32_t)~0x3F; hic <<= 1; do { @@ -254,32 +234,31 @@ SkUnichar SkUTF8_NextUnichar(const char** ptr) return c; } -SkUnichar SkUTF8_PrevUnichar(const char** ptr) -{ +SkUnichar SkUTF8_PrevUnichar(const char** ptr) { SkASSERT(NULL != ptr && NULL != *ptr); const char* p = *ptr; - if (*--p & 0x80) - while (*--p & 0x40) + if (*--p & 0x80) { + while (*--p & 0x40) { ; + } + } *ptr = (char*)p; return SkUTF8_NextUnichar(&p); } -size_t SkUTF8_FromUnichar(SkUnichar uni, char utf8[]) -{ - if ((uint32_t)uni > 0x10FFFF) - { +size_t SkUTF8_FromUnichar(SkUnichar uni, char utf8[]) { + if ((uint32_t)uni > 0x10FFFF) { SkASSERT(!"bad unichar"); return 0; } - if (uni <= 127) - { - if (utf8) + if (uni <= 127) { + if (utf8) { *utf8 = (char)uni; + } return 1; } @@ -289,19 +268,18 @@ size_t SkUTF8_FromUnichar(SkUnichar uni, char utf8[]) SkDEBUGCODE(SkUnichar orig = uni;) - while (uni > 0x7F >> count) - { + while (uni > 0x7F >> count) { *p++ = (char)(0x80 | (uni & 0x3F)); uni >>= 6; count += 1; } - if (utf8) - { + if (utf8) { p = tmp; utf8 += count; - while (p < tmp + count - 1) + while (p < tmp + count - 1) { *--utf8 = *p++; + } *--utf8 = (char)(~(0xFF >> count) | uni); } @@ -309,19 +287,16 @@ size_t SkUTF8_FromUnichar(SkUnichar uni, char utf8[]) return count; } -//////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// -int SkUTF16_CountUnichars(const uint16_t src[]) -{ +int SkUTF16_CountUnichars(const uint16_t src[]) { SkASSERT(src); int count = 0; unsigned c; - while ((c = *src++) != 0) - { + while ((c = *src++) != 0) { SkASSERT(!SkUTF16_IsLowSurrogate(c)); - if (SkUTF16_IsHighSurrogate(c)) - { + if (SkUTF16_IsHighSurrogate(c)) { c = *src++; SkASSERT(SkUTF16_IsLowSurrogate(c)); } @@ -330,18 +305,15 @@ int SkUTF16_CountUnichars(const uint16_t src[]) return count; } -int SkUTF16_CountUnichars(const uint16_t src[], int numberOf16BitValues) -{ +int SkUTF16_CountUnichars(const uint16_t src[], int numberOf16BitValues) { SkASSERT(src); const uint16_t* stop = src + numberOf16BitValues; int count = 0; - while (src < stop) - { + while (src < stop) { unsigned c = *src++; SkASSERT(!SkUTF16_IsLowSurrogate(c)); - if (SkUTF16_IsHighSurrogate(c)) - { + if (SkUTF16_IsHighSurrogate(c)) { SkASSERT(src < stop); c = *src++; SkASSERT(SkUTF16_IsLowSurrogate(c)); @@ -351,16 +323,14 @@ int SkUTF16_CountUnichars(const uint16_t src[], int numberOf16BitValues) return count; } -SkUnichar SkUTF16_NextUnichar(const uint16_t** srcPtr) -{ +SkUnichar SkUTF16_NextUnichar(const uint16_t** srcPtr) { SkASSERT(srcPtr && *srcPtr); const uint16_t* src = *srcPtr; SkUnichar c = *src++; SkASSERT(!SkUTF16_IsLowSurrogate(c)); - if (SkUTF16_IsHighSurrogate(c)) - { + if (SkUTF16_IsHighSurrogate(c)) { unsigned c2 = *src++; SkASSERT(SkUTF16_IsLowSurrogate(c2)); @@ -372,16 +342,14 @@ SkUnichar SkUTF16_NextUnichar(const uint16_t** srcPtr) return c; } -SkUnichar SkUTF16_PrevUnichar(const uint16_t** srcPtr) -{ +SkUnichar SkUTF16_PrevUnichar(const uint16_t** srcPtr) { SkASSERT(srcPtr && *srcPtr); const uint16_t* src = *srcPtr; SkUnichar c = *--src; SkASSERT(!SkUTF16_IsHighSurrogate(c)); - if (SkUTF16_IsLowSurrogate(c)) - { + if (SkUTF16_IsLowSurrogate(c)) { unsigned c2 = *--src; SkASSERT(SkUTF16_IsHighSurrogate(c2)); c = (c2 << 10) + c + (0x10000 - (0xD800 << 10) - 0xDC00); @@ -390,16 +358,13 @@ SkUnichar SkUTF16_PrevUnichar(const uint16_t** srcPtr) return c; } -size_t SkUTF16_FromUnichar(SkUnichar uni, uint16_t dst[]) -{ +size_t SkUTF16_FromUnichar(SkUnichar uni, uint16_t dst[]) { SkASSERT((unsigned)uni <= 0x10FFFF); int extra = (uni > 0xFFFF); - if (dst) - { - if (extra) - { + if (dst) { + if (extra) { // dst[0] = SkToU16(0xD800 | ((uni - 0x10000) >> 10)); // dst[0] = SkToU16(0xD800 | ((uni >> 10) - 64)); dst[0] = SkToU16((0xD800 - 64) + (uni >> 10)); @@ -407,9 +372,7 @@ size_t SkUTF16_FromUnichar(SkUnichar uni, uint16_t dst[]) SkASSERT(SkUTF16_IsHighSurrogate(dst[0])); SkASSERT(SkUTF16_IsLowSurrogate(dst[1])); - } - else - { + } else { dst[0] = SkToU16(uni); SkASSERT(!SkUTF16_IsHighSurrogate(dst[0])); SkASSERT(!SkUTF16_IsLowSurrogate(dst[0])); @@ -418,46 +381,44 @@ size_t SkUTF16_FromUnichar(SkUnichar uni, uint16_t dst[]) return 1 + extra; } -size_t SkUTF16_ToUTF8(const uint16_t utf16[], int numberOf16BitValues, char utf8[]) -{ +size_t SkUTF16_ToUTF8(const uint16_t utf16[], int numberOf16BitValues, + char utf8[]) { SkASSERT(numberOf16BitValues >= 0); - if (numberOf16BitValues <= 0) + if (numberOf16BitValues <= 0) { return 0; + } SkASSERT(utf16 != NULL); const uint16_t* stop = utf16 + numberOf16BitValues; size_t size = 0; - if (utf8 == NULL) // just count - { - while (utf16 < stop) + if (utf8 == NULL) { // just count + while (utf16 < stop) { size += SkUTF8_FromUnichar(SkUTF16_NextUnichar(&utf16), NULL); - } - else - { + } + } else { char* start = utf8; - while (utf16 < stop) + while (utf16 < stop) { utf8 += SkUTF8_FromUnichar(SkUTF16_NextUnichar(&utf16), utf8); + } size = utf8 - start; } return size; } -//////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// #include <stdlib.h> #if 0 -static int round_to_K(size_t bytes) -{ +static int round_to_K(size_t bytes) { return (bytes + 512) >> 10; } #endif SkAutoMemoryUsageProbe::SkAutoMemoryUsageProbe(const char label[]) - : fLabel(label) -{ + : fLabel(label) { #if 0 struct mallinfo mi = mallinfo(); @@ -465,14 +426,14 @@ SkAutoMemoryUsageProbe::SkAutoMemoryUsageProbe(const char label[]) #endif } -SkAutoMemoryUsageProbe::~SkAutoMemoryUsageProbe() -{ +SkAutoMemoryUsageProbe::~SkAutoMemoryUsageProbe() { #if 0 struct mallinfo mi = mallinfo(); printf("SkAutoMemoryUsageProbe "); - if (fLabel) + if (fLabel) { printf("<%s> ", fLabel); + } printf("delta %dK, current total allocated %dK\n", round_to_K(mi.uordblks - fBytesAllocated), round_to_K(mi.uordblks)); diff --git a/src/core/SkXfermode.cpp b/src/core/SkXfermode.cpp index a5b9f13..110ccb3 100644 --- a/src/core/SkXfermode.cpp +++ b/src/core/SkXfermode.cpp @@ -448,8 +448,8 @@ static const ProcCoeff gProcCoeffs[] = { { dstatop_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kSA_Coeff }, { xor_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kISA_Coeff }, - { plus_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, - { multiply_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, + { plus_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kOne_Coeff }, + { multiply_modeproc,SkXfermode::kZero_Coeff, SkXfermode::kSC_Coeff }, { screen_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, { overlay_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, { darken_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, diff --git a/src/core/core_files.mk b/src/core/core_files.mk index 252644e..b3427b0 100644 --- a/src/core/core_files.mk +++ b/src/core/core_files.mk @@ -56,6 +56,7 @@ SOURCE := \ SkMath.cpp \ SkMatrix.cpp \ SkMemory_stdlib.cpp \ + SkMetaData.cpp \ SkPackBits.cpp \ SkPaint.cpp \ SkPath.cpp \ diff --git a/src/effects/SkBlurDrawLooper.cpp b/src/effects/SkBlurDrawLooper.cpp index 9585112..bde04ed 100644 --- a/src/effects/SkBlurDrawLooper.cpp +++ b/src/effects/SkBlurDrawLooper.cpp @@ -7,11 +7,10 @@ SkBlurDrawLooper::SkBlurDrawLooper(SkScalar radius, SkScalar dx, SkScalar dy, SkColor color, uint32_t flags) - : fDx(dx), fDy(dy), fBlurColor(color), fBlurFlags(flags) -{ + : fDx(dx), fDy(dy), fBlurColor(color), fBlurFlags(flags) { + SkASSERT(flags <= kAll_BlurFlag); - if (radius > 0) - { + if (radius > 0) { uint32_t blurFlags = flags & kIgnoreTransform_BlurFlag ? SkBlurMaskFilter::kIgnoreTransform_BlurFlag : SkBlurMaskFilter::kNone_BlurFlag; @@ -23,28 +22,23 @@ SkBlurDrawLooper::SkBlurDrawLooper(SkScalar radius, SkScalar dx, SkScalar dy, fBlur = SkBlurMaskFilter::Create(radius, SkBlurMaskFilter::kNormal_BlurStyle, blurFlags); - } - else - { + } else { fBlur = NULL; } - if (flags & kOverrideColor_BlurFlag) - { + if (flags & kOverrideColor_BlurFlag) { // Set alpha to 1 for the override since transparency will already // be baked into the blurred mask. SkColor opaqueColor = SkColorSetA(color, 255); //The SrcIn xfer mode will multiply 'color' by the incoming alpha - fColorFilter = SkColorFilter::CreateModeFilter(opaqueColor, SkXfermode::kSrcIn_Mode); - } - else - { + fColorFilter = SkColorFilter::CreateModeFilter(opaqueColor, + SkXfermode::kSrcIn_Mode); + } else { fColorFilter = NULL; } } -SkBlurDrawLooper::SkBlurDrawLooper(SkFlattenableReadBuffer& buffer) -{ +SkBlurDrawLooper::SkBlurDrawLooper(SkFlattenableReadBuffer& buffer) { fDx = buffer.readScalar(); fDy = buffer.readScalar(); fBlurColor = buffer.readU32(); @@ -53,14 +47,12 @@ SkBlurDrawLooper::SkBlurDrawLooper(SkFlattenableReadBuffer& buffer) fBlurFlags = buffer.readU32() & kAll_BlurFlag; } -SkBlurDrawLooper::~SkBlurDrawLooper() -{ +SkBlurDrawLooper::~SkBlurDrawLooper() { SkSafeUnref(fBlur); SkSafeUnref(fColorFilter); } -void SkBlurDrawLooper::flatten(SkFlattenableWriteBuffer& buffer) -{ +void SkBlurDrawLooper::flatten(SkFlattenableWriteBuffer& buffer) { buffer.writeScalar(fDx); buffer.writeScalar(fDy); buffer.write32(fBlurColor); @@ -69,70 +61,47 @@ void SkBlurDrawLooper::flatten(SkFlattenableWriteBuffer& buffer) buffer.write32(fBlurFlags); } -void SkBlurDrawLooper::init(SkCanvas* canvas, SkPaint* paint) -{ - // we do nothing if a maskfilter is already installed - if (paint->getMaskFilter() != NULL) - fState = kDone; - else - { - fState = kBeforeEdge; - fPaint = paint; - fCanvas = canvas; - fSaveCount = canvas->getSaveCount(); - } +void SkBlurDrawLooper::init(SkCanvas* canvas) { + fState = kBeforeEdge; } -bool SkBlurDrawLooper::next() -{ - SkColor blurColor; - SkAlpha alpha; +bool SkBlurDrawLooper::next(SkCanvas* canvas, SkPaint* paint) { switch (fState) { - case kBeforeEdge: - fSavedColor = fPaint->getColor(); - blurColor = fBlurColor; - alpha = SkColorGetA(blurColor); - if (alpha == 255) { - blurColor = SkColorSetA(blurColor, fPaint->getAlpha()); - } - fPaint->setColor(blurColor); - fPaint->setMaskFilter(fBlur); - fPaint->setColorFilter(fColorFilter); - fCanvas->save(SkCanvas::kMatrix_SaveFlag); - if (fBlurFlags & kIgnoreTransform_BlurFlag) - { - SkMatrix transform(fCanvas->getTotalMatrix()); - transform.postTranslate(fDx, fDy); - fCanvas->setMatrix(transform); - } - else - { - fCanvas->translate(fDx, fDy); - } - fState = kAfterEdge; - return true; - case kAfterEdge: - fPaint->setColor(fSavedColor); - fPaint->setMaskFilter(NULL); - fPaint->setColorFilter(NULL); - fCanvas->restore(); // to remove the translate we did earlier - fState = kDone; - return true; - default: - SkASSERT(kDone == fState); - return false; - } -} - -void SkBlurDrawLooper::restore() -{ - if (kAfterEdge == fState) - { - fPaint->setColor(fSavedColor); - fPaint->setMaskFilter(NULL); - fPaint->setColorFilter(NULL); - fCanvas->restore(); // to remove the translate we did earlier - fState = kDone; + case kBeforeEdge: + // we do nothing if a maskfilter is already installed + if (paint->getMaskFilter()) { + fState = kDone; + return false; + } +#ifdef ANDROID + SkColor blurColor; + blurColor = fBlurColor; + if (SkColorGetA(blurColor) == 255) { + blurColor = SkColorSetA(blurColor, paint->getAlpha()); + } + paint->setColor(blurColor); +#else + paint->setColor(fBlurColor); +#endif + paint->setMaskFilter(fBlur); + paint->setColorFilter(fColorFilter); + canvas->save(SkCanvas::kMatrix_SaveFlag); + if (fBlurFlags & kIgnoreTransform_BlurFlag) { + SkMatrix transform(canvas->getTotalMatrix()); + transform.postTranslate(fDx, fDy); + canvas->setMatrix(transform); + } else { + canvas->translate(fDx, fDy); + } + fState = kAfterEdge; + return true; + case kAfterEdge: + canvas->restore(); + fState = kDone; + return true; + default: + SkASSERT(kDone == fState); + return false; } } diff --git a/src/effects/SkGradientShader.cpp b/src/effects/SkGradientShader.cpp index 3452212..dca87b0 100644 --- a/src/effects/SkGradientShader.cpp +++ b/src/effects/SkGradientShader.cpp @@ -1397,9 +1397,13 @@ public: SkScalarSquare(fDiff.fY)); } if (matrix) { - SkScalar invDiffL = SkScalarInvert(diffL); - matrix->setSinCos(-SkScalarMul(invDiffL, fDiff.fY), - SkScalarMul(invDiffL, fDiff.fX)); + if (diffL) { + SkScalar invDiffL = SkScalarInvert(diffL); + matrix->setSinCos(-SkScalarMul(invDiffL, fDiff.fY), + SkScalarMul(invDiffL, fDiff.fX)); + } else { + matrix->reset(); + } matrix->preConcat(fPtsToUnit); } if (xy) { diff --git a/src/effects/SkLayerDrawLooper.cpp b/src/effects/SkLayerDrawLooper.cpp index f2d8ba8..b3f3886 100644 --- a/src/effects/SkLayerDrawLooper.cpp +++ b/src/effects/SkLayerDrawLooper.cpp @@ -1,6 +1,15 @@ #include "SkCanvas.h" +#include "SkColor.h" #include "SkLayerDrawLooper.h" #include "SkPaint.h" +#include "SkUnPreMultiply.h" + +SkLayerDrawLooper::LayerInfo::LayerInfo() { + fPaintBits = 0; // ignore out paint + fColorMode = SkXfermode::kDst_Mode; // ignore our color + fOffset.set(0, 0); + fPostTranslate = false; +} SkLayerDrawLooper::SkLayerDrawLooper() { fRecs = NULL; @@ -15,43 +24,128 @@ SkLayerDrawLooper::~SkLayerDrawLooper() { rec = next; } } - -SkPaint* SkLayerDrawLooper::addLayer(SkScalar dx, SkScalar dy) { + +SkPaint* SkLayerDrawLooper::addLayer(const LayerInfo& info) { fCount += 1; Rec* rec = SkNEW(Rec); rec->fNext = fRecs; - rec->fOffset.set(dx, dy); + rec->fInfo = info; fRecs = rec; return &rec->fPaint; } -void SkLayerDrawLooper::init(SkCanvas* canvas, SkPaint* paint) { - fIter.fSavedPaint = *paint; - fIter.fPaint = paint; - fIter.fCanvas = canvas; - fIter.fRec = fRecs; +SkPaint* SkLayerDrawLooper::addLayer(SkScalar dx, SkScalar dy) { + LayerInfo info; + + info.fOffset.set(dx, dy); + return this->addLayer(info); +} + +void SkLayerDrawLooper::init(SkCanvas* canvas) { + fCurrRec = fRecs; canvas->save(SkCanvas::kMatrix_SaveFlag); } -bool SkLayerDrawLooper::next() { - Rec* rec = fIter.fRec; - if (rec) { - *fIter.fPaint = rec->fPaint; - fIter.fCanvas->restore(); - fIter.fCanvas->save(SkCanvas::kMatrix_SaveFlag); - fIter.fCanvas->translate(rec->fOffset.fX, rec->fOffset.fY); +static SkColor xferColor(SkColor src, SkColor dst, SkXfermode::Mode mode) { + switch (mode) { + case SkXfermode::kSrc_Mode: + return src; + case SkXfermode::kDst_Mode: + return dst; + default: { + SkPMColor pmS = SkPreMultiplyColor(src); + SkPMColor pmD = SkPreMultiplyColor(dst); + SkPMColor result = SkXfermode::GetProc(mode)(pmS, pmD); + return SkUnPreMultiply::PMColorToColor(result); + } + } +} + +void SkLayerDrawLooper::ApplyBits(SkPaint* dst, const SkPaint& src, + BitFlags bits, SkXfermode::Mode colorMode) { + dst->setColor(xferColor(src.getColor(), dst->getColor(), colorMode)); + + if (0 == bits) { + return; + } + if (kEntirePaint_Bits == bits) { + // we've already compute the color, so save it from the assignment + SkColor c = dst->getColor(); + *dst = src; + dst->setColor(c); + return; + } + + if (bits & kStyle_Bit) { + dst->setStyle(src.getStyle()); + dst->setStrokeWidth(src.getStrokeWidth()); + dst->setStrokeMiter(src.getStrokeMiter()); + dst->setStrokeCap(src.getStrokeCap()); + dst->setStrokeJoin(src.getStrokeJoin()); + } + + if (bits & kTextSkewX_Bit) { + dst->setTextSkewX(src.getTextSkewX()); + } - fIter.fRec = rec->fNext; - return true; + if (bits & kPathEffect_Bit) { + dst->setPathEffect(src.getPathEffect()); + } + if (bits & kMaskFilter_Bit) { + dst->setMaskFilter(src.getMaskFilter()); + } + if (bits & kShader_Bit) { + dst->setShader(src.getShader()); } - return false; + if (bits & kColorFilter_Bit) { + dst->setColorFilter(src.getColorFilter()); + } + if (bits & kXfermode_Bit) { + dst->setXfermode(src.getXfermode()); + } + + // we never copy these +#if 0 + dst->setFlags(src.getFlags()); + dst->setTypeface(src.getTypeface()); + dst->setTextSize(src.getTextSize()); + dst->setTextScaleX(src.getTextScaleX()); + dst->setTextSkewX(src.getTextSkewX()); + dst->setRasterizer(src.getRasterizer()); + dst->setLooper(src.getLooper()); + dst->setTextEncoding(src.getTextEncoding()); + dst->setHinting(src.getHinting()); +#endif } -void SkLayerDrawLooper::restore() { - fIter.fCanvas->restore(); - *fIter.fPaint = fIter.fSavedPaint; +// Should we add this to canvas? +static void postTranslate(SkCanvas* canvas, SkScalar dx, SkScalar dy) { + SkMatrix m = canvas->getTotalMatrix(); + m.postTranslate(dx, dy); + canvas->setMatrix(m); +} + +bool SkLayerDrawLooper::next(SkCanvas* canvas, SkPaint* paint) { + canvas->restore(); + if (NULL == fCurrRec) { + return false; + } + + ApplyBits(paint, fCurrRec->fPaint, fCurrRec->fInfo.fPaintBits, + fCurrRec->fInfo.fColorMode); + + canvas->save(SkCanvas::kMatrix_SaveFlag); + if (fCurrRec->fInfo.fPostTranslate) { + postTranslate(canvas, fCurrRec->fInfo.fOffset.fX, + fCurrRec->fInfo.fOffset.fY); + } else { + canvas->translate(fCurrRec->fInfo.fOffset.fX, fCurrRec->fInfo.fOffset.fY); + } + fCurrRec = fCurrRec->fNext; + + return true; } SkLayerDrawLooper::Rec* SkLayerDrawLooper::Rec::Reverse(Rec* head) { @@ -87,8 +181,11 @@ void SkLayerDrawLooper::flatten(SkFlattenableWriteBuffer& buffer) { Rec* rec = fRecs; for (int i = 0; i < fCount; i++) { - buffer.writeScalar(rec->fOffset.fX); - buffer.writeScalar(rec->fOffset.fY); + buffer.writeInt(rec->fInfo.fPaintBits); + buffer.writeInt(rec->fInfo.fColorMode); + buffer.writeScalar(rec->fInfo.fOffset.fX); + buffer.writeScalar(rec->fInfo.fOffset.fY); + buffer.writeBool(rec->fInfo.fPostTranslate); rec->fPaint.flatten(buffer); rec = rec->fNext; } @@ -102,9 +199,13 @@ SkLayerDrawLooper::SkLayerDrawLooper(SkFlattenableReadBuffer& buffer) int count = buffer.readInt(); for (int i = 0; i < count; i++) { - SkScalar dx = buffer.readScalar(); - SkScalar dy = buffer.readScalar(); - this->addLayer(dx, dy)->unflatten(buffer); + LayerInfo info; + info.fPaintBits = buffer.readInt(); + info.fColorMode = (SkXfermode::Mode)buffer.readInt(); + info.fOffset.fX = buffer.readScalar(); + info.fOffset.fY = buffer.readScalar(); + info.fPostTranslate = buffer.readBool(); + this->addLayer(info)->unflatten(buffer); } SkASSERT(count == fCount); diff --git a/src/effects/SkPaintFlagsDrawFilter.cpp b/src/effects/SkPaintFlagsDrawFilter.cpp index ed2df88..62eb53a 100644 --- a/src/effects/SkPaintFlagsDrawFilter.cpp +++ b/src/effects/SkPaintFlagsDrawFilter.cpp @@ -2,21 +2,12 @@ #include "SkPaint.h" SkPaintFlagsDrawFilter::SkPaintFlagsDrawFilter(uint32_t clearFlags, - uint32_t setFlags) -{ + uint32_t setFlags) { fClearFlags = SkToU16(clearFlags & SkPaint::kAllFlags); fSetFlags = SkToU16(setFlags & SkPaint::kAllFlags); } -bool SkPaintFlagsDrawFilter::filter(SkCanvas*, SkPaint* paint, Type) -{ - fPrevFlags = paint->getFlags(); - paint->setFlags((fPrevFlags & ~fClearFlags) | fSetFlags); - return true; +void SkPaintFlagsDrawFilter::filter(SkPaint* paint, Type) { + paint->setFlags((paint->getFlags() & ~fClearFlags) | fSetFlags); } -void SkPaintFlagsDrawFilter::restore(SkCanvas*, SkPaint* paint, Type) -{ - paint->setFlags(fPrevFlags); -} - diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp index 3707b67..723c635 100644 --- a/src/gpu/SkGpuDevice.cpp +++ b/src/gpu/SkGpuDevice.cpp @@ -24,6 +24,7 @@ #include "SkDrawProcs.h" #include "SkGlyphCache.h" +#include "SkUtils.h" #define CACHE_LAYER_TEXTURES 1 @@ -171,11 +172,15 @@ SkGpuDevice::SkGpuDevice(GrContext* context, this->width(), this->height()); GrAssert(false); } - } else if (Current3DApiRenderTarget() == renderTargetOrNull) { - fRenderTarget = fContext->createRenderTargetFrom3DApiState(); } else { - fRenderTarget = renderTargetOrNull; - fRenderTarget->ref(); + if (Current3DApiRenderTarget() == renderTargetOrNull) { + fRenderTarget = fContext->createRenderTargetFrom3DApiState(); + } else { + fRenderTarget = renderTargetOrNull; + fRenderTarget->ref(); + } + SkGrRenderTargetPixelRef* pr = new SkGrRenderTargetPixelRef(fRenderTarget); + this->setPixelRef(pr, 0)->unref(); } } @@ -232,16 +237,15 @@ bool SkGpuDevice::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) { return false; } - SkAutoLockPixels alp(tmp); - fContext->setRenderTarget(fRenderTarget); - // we aren't setting the clip or matrix, so mark as dirty - // we don't need to set them for this call and don't have them anyway - fNeedPrepareRenderTarget = true; + tmp.lockPixels(); - if (!fContext->readPixels(bounds.fLeft, bounds.fTop, - bounds.width(), bounds.height(), - GrTexture::kRGBA_8888_PixelConfig, - tmp.getPixels())) { + bool read = fContext->readRenderTargetPixels(fRenderTarget, + bounds.fLeft, bounds.fTop, + bounds.width(), bounds.height(), + kRGBA_8888_GrPixelConfig, + tmp.getPixels()); + tmp.unlockPixels(); + if (!read) { return false; } @@ -254,8 +258,8 @@ void SkGpuDevice::writePixels(const SkBitmap& bitmap, int x, int y) { if (!bitmap.readyToDraw()) { return; } - GrTexture::PixelConfig config = SkGr::BitmapConfig2PixelConfig(bitmap.config(), - bitmap.isOpaque()); + GrPixelConfig config = SkGr::BitmapConfig2PixelConfig(bitmap.config(), + bitmap.isOpaque()); fContext->setRenderTarget(fRenderTarget); // we aren't setting the clip or matrix, so mark as dirty // we don't need to set them for this call and don't have them anyway @@ -305,8 +309,8 @@ void SkGpuDevice::prepareRenderTarget(const SkDraw& draw) { void SkGpuDevice::setMatrixClip(const SkMatrix& matrix, const SkRegion& clip, const SkClipStack& clipStack) { this->INHERITED::setMatrixClip(matrix, clip, clipStack); - - convert_matrixclip(fContext, matrix, clipStack, clip, this->getOrigin()); + // We don't need to set them now because the context may not reflect this device. + fNeedPrepareRenderTarget = true; } void SkGpuDevice::gainFocus(SkCanvas* canvas, const SkMatrix& matrix, @@ -643,37 +647,180 @@ void SkGpuDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, #endif } +/////////////////////////////////////////////////////////////////////////////// + +static void setInsetFan(GrPoint pts[4], const GrRect& r, + GrScalar dx, GrScalar dy) { + pts->setRectFan(r.fLeft + dx, r.fTop + dy, r.fRight - dx, r.fBottom - dy); +} + +static GrColor getColorForMesh(const GrPaint& paint) { + if (NULL == paint.getTexture()) { + return paint.fColor; + } else { + unsigned a = GrColorUnpackA(paint.fColor); + return GrColorPackRGBA(a, a, a, a); + } +} + +static const uint16_t gFillAARectIdx1[] = { + 0, 1, 5, 5, 4, 0, + 1, 2, 6, 6, 5, 1, + 2, 3, 7, 7, 6, 2, + 3, 0, 4, 4, 7, 3, + 4, 5, 6, 6, 7, 4, +}; + +static void fillDevAARect(GrContext* ctx, const GrPaint& paint, + const GrRect& rect) { + if (rect.isEmpty()) { + return; + } + + GrAutoMatrix avm(ctx, GrMatrix::I()); + + GrPoint verts[8]; + GrPoint* texs = NULL; + GrColor colors[8]; + + setInsetFan(&verts[ 0], rect, -0.5f, -0.5f); + setInsetFan(&verts[ 4], rect, 0.5f, 0.5f); + + sk_memset32(&colors[ 0], 0, 4); + sk_memset32(&colors[ 4], getColorForMesh(paint), 4); + + ctx->drawVertices(paint, kTriangles_PrimitiveType, + 8, verts, texs, colors, + gFillAARectIdx1, SK_ARRAY_COUNT(gFillAARectIdx1)); +} + +static const uint16_t gStrokeAARectIdx[] = { + 0 + 0, 1 + 0, 5 + 0, 5 + 0, 4 + 0, 0 + 0, + 1 + 0, 2 + 0, 6 + 0, 6 + 0, 5 + 0, 1 + 0, + 2 + 0, 3 + 0, 7 + 0, 7 + 0, 6 + 0, 2 + 0, + 3 + 0, 0 + 0, 4 + 0, 4 + 0, 7 + 0, 3 + 0, + + 0 + 4, 1 + 4, 5 + 4, 5 + 4, 4 + 4, 0 + 4, + 1 + 4, 2 + 4, 6 + 4, 6 + 4, 5 + 4, 1 + 4, + 2 + 4, 3 + 4, 7 + 4, 7 + 4, 6 + 4, 2 + 4, + 3 + 4, 0 + 4, 4 + 4, 4 + 4, 7 + 4, 3 + 4, + + 0 + 8, 1 + 8, 5 + 8, 5 + 8, 4 + 8, 0 + 8, + 1 + 8, 2 + 8, 6 + 8, 6 + 8, 5 + 8, 1 + 8, + 2 + 8, 3 + 8, 7 + 8, 7 + 8, 6 + 8, 2 + 8, + 3 + 8, 0 + 8, 4 + 8, 4 + 8, 7 + 8, 3 + 8, +}; + +static void strokeDevAARect(GrContext* ctx, const GrPaint& paint, + const GrRect& rect, const SkPoint& strokeSize) { + const GrScalar dx = SkScalarToGrScalar(strokeSize.fX); + const GrScalar dy = SkScalarToGrScalar(strokeSize.fY); + const GrScalar rx = dx * 0.5f; + const GrScalar ry = dy * 0.5f; + + GrScalar spare; + { + GrScalar w = rect.width() - dx; + GrScalar h = rect.height() - dy; + spare = GrMin(w, h); + } + + if (spare <= 0) { + GrRect r(rect); + r.inset(-rx, -ry); + fillDevAARect(ctx, paint, r); + return; + } + + GrAutoMatrix avm(ctx, GrMatrix::I()); + + GrPoint verts[16]; + GrPoint* texs = NULL; + GrColor colors[16]; + + setInsetFan(&verts[ 0], rect, -rx - 0.5f, -ry - 0.5f); + setInsetFan(&verts[ 4], rect, -rx + 0.5f, -ry + 0.5f); + setInsetFan(&verts[ 8], rect, rx - 0.5f, ry - 0.5f); + setInsetFan(&verts[12], rect, rx + 0.5f, ry + 0.5f); + + sk_memset32(&colors[ 0], 0, 4); + sk_memset32(&colors[ 4], getColorForMesh(paint), 8); + sk_memset32(&colors[12], 0, 4); + + ctx->drawVertices(paint, kTriangles_PrimitiveType, + 16, verts, texs, colors, + gStrokeAARectIdx, SK_ARRAY_COUNT(gStrokeAARectIdx)); +} + +/* + * If the paint has a texture, preconcat the ctx's inverse, since when we + * draw verts which are already in device coordinates, we need to "undo" that + * before we run our vertex shaders, which expect the coordinates to be local. + */ +static void preConcatInverseToTextureMatrix(GrContext* ctx, GrPaint* paint) { + if (paint->getTexture()) { + GrMatrix inverse; + if (ctx->getMatrix().invert(&inverse)) { + paint->fSampler.preConcatMatrix(inverse); + } + } +} + void SkGpuDevice::drawRect(const SkDraw& draw, const SkRect& rect, const SkPaint& paint) { CHECK_SHOULD_DRAW(draw); - bool doStroke = paint.getStyle() == SkPaint::kStroke_Style; - SkScalar width = paint.getStrokeWidth(); + const SkMatrix& matrix = *draw.fMatrix; + SkPoint strokeSize; + SkDraw::RectType type = SkDraw::ComputeRectType(paint, matrix, &strokeSize); - /* - We have special code for hairline strokes, miter-strokes, and fills. - Anything else we just call our path code. - */ - bool usePath = doStroke && width > 0 && - paint.getStrokeJoin() != SkPaint::kMiter_Join; - // another reason we might need to call drawPath... - if (paint.getMaskFilter()) { - usePath = true; - } - - if (usePath) { + if (SkDraw::kPath_RectType == type) { SkPath path; path.addRect(rect); this->drawPath(draw, path, paint, NULL, true); - return; - } + } else { + GrPaint grPaint; + SkAutoCachedTexture act; + if (!this->skPaint2GrPaintShader(paint, &act, matrix, &grPaint)) { + return; + } - GrPaint grPaint; - SkAutoCachedTexture act; - if (!this->skPaint2GrPaintShader(paint, &act, *draw.fMatrix, &grPaint)) { - return; + bool doAA = paint.isAntiAlias(); + + if (SkDraw::kHair_RectType == type && doAA) { + strokeSize.set(SK_Scalar1, SK_Scalar1); + type = SkDraw::kStroke_RectType; + } + + switch (type) { + case SkDraw::kHair_RectType: + SkASSERT(!doAA); + fContext->drawRect(grPaint, Sk2Gr(rect), 0); + break; + case SkDraw::kFill_RectType: + if (doAA) { + SkRect devRect; + matrix.mapRect(&devRect, rect); + preConcatInverseToTextureMatrix(fContext, &grPaint); + fillDevAARect(fContext, grPaint, Sk2Gr(devRect)); + } else { + fContext->drawRect(grPaint, Sk2Gr(rect), -1); + } + break; + case SkDraw::kStroke_RectType: + if (doAA) { + SkRect devRect; + matrix.mapRect(&devRect, rect); + preConcatInverseToTextureMatrix(fContext, &grPaint); + strokeDevAARect(fContext, grPaint, Sk2Gr(devRect), strokeSize); + } else { + fContext->drawRect(grPaint, Sk2Gr(rect), paint.getStrokeWidth()); + } + break; + default: + SkASSERT(!"bad value for RectType"); + } } - fContext->drawRect(grPaint, Sk2Gr(rect), doStroke ? width : -1); } #include "SkMaskFilter.h" @@ -715,7 +862,7 @@ static bool drawWithMaskFilter(GrContext* context, const SkPath& path, GrGpu::kNone_AALevel, dstM.fBounds.width(), dstM.fBounds.height(), - GrTexture::kAlpha_8_PixelConfig + kAlpha_8_GrPixelConfig }; GrTexture* texture = context->createUncachedTexture(desc, dstM.fImage, @@ -771,7 +918,22 @@ void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& origSrcPath, // at this point we're done with prePathMatrix SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;) - if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style) { + // This "if" is not part of the SkDraw::drawPath() lift. + // When we get a 1.0 wide stroke we hairline stroke it instead of creating + // a new stroked-path. This is motivated by canvas2D sites that draw + // lines as 1.0 wide stroked paths. We can consider doing an alpha-modulated- + // hairline for width < 1.0 when AA is enabled. + static const int gMatrixMask = ~(SkMatrix::kIdentity_Mask | + SkMatrix::kTranslate_Mask); + if (!paint.getPathEffect() && + SkPaint::kStroke_Style == paint.getStyle() && + !(draw.fMatrix->getType() & gMatrixMask) && + SK_Scalar1 == paint.getStrokeWidth()) { + doFill = false; + } + + if (doFill && (paint.getPathEffect() || + paint.getStyle() != SkPaint::kFill_Style)) { doFill = paint.getFillPath(*pathPtr, &tmpPath); pathPtr = &tmpPath; } @@ -1099,8 +1261,18 @@ static void SkGPU_Draw1Glyph(const SkDraw1Glyph& state, if (NULL == procs->fFontScaler) { procs->fFontScaler = get_gr_font_scaler(state.fCache); } + + /* + * Skia calls us with fx,fy already biased by 1/2. It does this to speed + * up rounding these, so that all of its procs (like us) can just call + * SkFixedFloor and get the "rounded" value. + * + * We take advantage of that for fx, where we pass a rounded value, but + * we want the fractional fy, so we have to unbias it first. + */ procs->fTextContext->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(), fx, 0), - SkIntToFixed(SkFixedFloor(fx)), fy, + SkIntToFixed(SkFixedFloor(fx)), + fy - SK_FixedHalf, procs->fFontScaler); } @@ -1265,9 +1437,7 @@ void SkGpuDevice::unlockCachedTexture(TexCache* cache) { /////////////////////////////////////////////////////////////////////////////// SkGpuDeviceFactory::SkGpuDeviceFactory(GrContext* context, - GrRenderTarget* rootRenderTarget) - : fContext(context) { - + GrRenderTarget* rootRenderTarget) { GrAssert(NULL != context); GrAssert(NULL != rootRenderTarget); @@ -1280,13 +1450,32 @@ SkGpuDeviceFactory::SkGpuDeviceFactory(GrContext* context, fRootRenderTarget = rootRenderTarget; rootRenderTarget->ref(); } + + fContext = context; context->ref(); + fRootTexture = NULL; +} + +SkGpuDeviceFactory::SkGpuDeviceFactory(GrContext* context, GrTexture* rootRenderTargetTexture) { + GrAssert(NULL != context); + GrAssert(NULL != rootRenderTargetTexture); + GrAssert(NULL != rootRenderTargetTexture->asRenderTarget()); + + fRootTexture = rootRenderTargetTexture; + rootRenderTargetTexture->ref(); + + fRootRenderTarget = rootRenderTargetTexture->asRenderTarget(); + fRootRenderTarget->ref(); + + fContext = context; + context->ref(); } SkGpuDeviceFactory::~SkGpuDeviceFactory() { fContext->unref(); fRootRenderTarget->unref(); + GrSafeUnref(fRootTexture); } SkDevice* SkGpuDeviceFactory::newDevice(SkCanvas*, SkBitmap::Config config, @@ -1297,4 +1486,3 @@ SkDevice* SkGpuDeviceFactory::newDevice(SkCanvas*, SkBitmap::Config config, bm.setIsOpaque(isOpaque); return new SkGpuDevice(fContext, bm, isLayer ? NULL : fRootRenderTarget); } - diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp index e57f88a..e7e2365 100644 --- a/src/gpu/SkGr.cpp +++ b/src/gpu/SkGr.cpp @@ -166,10 +166,9 @@ void SkGrClipIterator::reset(const SkClipStack& clipStack) { GrClipType SkGrClipIterator::getType() const { GrAssert(!this->isDone()); - if (NULL != fCurr->fRect) { + if (NULL == fCurr->fPath) { return kRect_ClipType; } else { - GrAssert(NULL != fCurr->fPath); return kPath_ClipType; } } @@ -214,30 +213,25 @@ GrPathFill SkGrClipIterator::getPathFill() const { /////////////////////////////////////////////////////////////////////////////// -GrTexture::PixelConfig SkGr::BitmapConfig2PixelConfig(SkBitmap::Config config, +GrPixelConfig SkGr::BitmapConfig2PixelConfig(SkBitmap::Config config, bool isOpaque) { switch (config) { case SkBitmap::kA8_Config: - return GrTexture::kAlpha_8_PixelConfig; + return kAlpha_8_GrPixelConfig; case SkBitmap::kIndex8_Config: - return GrTexture::kIndex_8_PixelConfig; + return kIndex_8_GrPixelConfig; case SkBitmap::kRGB_565_Config: - return GrTexture::kRGB_565_PixelConfig; + return kRGB_565_GrPixelConfig; case SkBitmap::kARGB_4444_Config: - return GrTexture::kRGBA_4444_PixelConfig; + return kRGBA_4444_GrPixelConfig; case SkBitmap::kARGB_8888_Config: if (isOpaque) { - return GrTexture::kRGBX_8888_PixelConfig; + return kRGBX_8888_GrPixelConfig; } else { - return GrTexture::kRGBA_8888_PixelConfig; + return kRGBA_8888_GrPixelConfig; } default: - return GrTexture::kUnknown_PixelConfig; + return kUnknown_GrPixelConfig; } } -void SkGr::AbandonAllTextures(GrContext* ctx) { - ctx->abandonAllTextures(); -} - - diff --git a/src/gpu/SkGrFontScaler.cpp b/src/gpu/SkGrFontScaler.cpp index 16e44b9..e58f035 100644 --- a/src/gpu/SkGrFontScaler.cpp +++ b/src/gpu/SkGrFontScaler.cpp @@ -86,6 +86,8 @@ SkGrFontScaler::~SkGrFontScaler() { GrMaskFormat SkGrFontScaler::getMaskFormat() { SkMask::Format format = fStrike->getMaskFormat(); switch (format) { + case SkMask::kBW_Format: + // fall through to kA8 -- we store BW glyphs in our 8-bit cache case SkMask::kA8_Format: return kA8_GrMaskFormat; case SkMask::kLCD16_Format: @@ -113,6 +115,18 @@ bool SkGrFontScaler::getPackedGlyphBounds(GrGlyph::PackedID packed, } +static void bits_to_bytes(const uint8_t bits[], uint8_t bytes[], int count) { + while (count > 0) { + unsigned mask = *bits++; + for (int i = 7; i >= 0; --i) { + *bytes++ = (mask & (1 << i)) ? 0xFF : 0; + if (--count == 0) { + return; + } + } + } +} + bool SkGrFontScaler::getPackedGlyphImage(GrGlyph::PackedID packed, int width, int height, int dstRB, void* dst) { @@ -127,7 +141,16 @@ bool SkGrFontScaler::getPackedGlyphImage(GrGlyph::PackedID packed, } int srcRB = glyph.rowBytes(); - if (srcRB == dstRB) { + if (SkMask::kBW_Format == fStrike->getMaskFormat()) { + // expand bits to bytes + const uint8_t* bits = reinterpret_cast<const uint8_t*>(src); + uint8_t* bytes = reinterpret_cast<uint8_t*>(dst); + for (int y = 0; y < height; y++) { + bits_to_bytes(bits, bytes, width); + bits += srcRB; + bytes += dstRB; + } + } else if (srcRB == dstRB) { memcpy(dst, src, dstRB * height); } else { const int bbp = GrMaskFormatBytesPerPixel(this->getMaskFormat()); diff --git a/src/gpu/SkGrTexturePixelRef.cpp b/src/gpu/SkGrTexturePixelRef.cpp index da9ac1a..8becfd4 100644 --- a/src/gpu/SkGrTexturePixelRef.cpp +++ b/src/gpu/SkGrTexturePixelRef.cpp @@ -16,8 +16,12 @@ #include "SkGrTexturePixelRef.h" + #include "GrTexture.h" +#include "SkRect.h" +#include "SkBitmap.h" + SkGrTexturePixelRef::SkGrTexturePixelRef(GrTexture* tex) { fTexture = tex; GrSafeRef(tex); @@ -27,4 +31,72 @@ SkGrTexturePixelRef::~SkGrTexturePixelRef() { GrSafeUnref(fTexture); } +bool SkGrTexturePixelRef::onReadPixels(SkBitmap* dst, const SkIRect* subset) { + if (NULL != fTexture && fTexture->isValid()) { + int left, top, width, height; + if (NULL != subset) { + left = subset->fLeft; + width = subset->width(); + top = subset->fTop; + height = subset->height(); + } else { + left = 0; + width = fTexture->width(); + top = 0; + height = fTexture->height(); + } + dst->setConfig(SkBitmap::kARGB_8888_Config, width, height); + dst->allocPixels(); + SkAutoLockPixels al(*dst); + void* buffer = dst->getPixels(); + return fTexture->readPixels(left, top, width, height, + kRGBA_8888_GrPixelConfig, + buffer); + } else { + return false; + } +} + +//////////////////////////////////////////////////////////////////////////////// + +SkGrRenderTargetPixelRef::SkGrRenderTargetPixelRef(GrRenderTarget* rt) { + fRenderTarget = rt; + GrSafeRef(fRenderTarget); +} +SkGrRenderTargetPixelRef::~SkGrRenderTargetPixelRef() { + GrSafeUnref(fRenderTarget); +} + +SkGpuTexture* SkGrRenderTargetPixelRef::getTexture() { + if (NULL != fRenderTarget) { + return (SkGpuTexture*) fRenderTarget->asTexture(); + } + return NULL; +} + +bool SkGrRenderTargetPixelRef::onReadPixels(SkBitmap* dst, const SkIRect* subset) { + if (NULL != fRenderTarget && fRenderTarget->isValid()) { + int left, top, width, height; + if (NULL != subset) { + left = subset->fLeft; + width = subset->width(); + top = subset->fTop; + height = subset->height(); + } else { + left = 0; + width = fRenderTarget->width(); + top = 0; + height = fRenderTarget->height(); + } + dst->setConfig(SkBitmap::kARGB_8888_Config, width, height); + dst->allocPixels(); + SkAutoLockPixels al(*dst); + void* buffer = dst->getPixels(); + return fRenderTarget->readPixels(left, top, width, height, + kRGBA_8888_GrPixelConfig, + buffer); + } else { + return false; + } +} diff --git a/src/ports/SkFontHost_FONTPATH.cpp b/src/ports/SkFontHost_FONTPATH.cpp index 98f4ba5..afab874 100644 --- a/src/ports/SkFontHost_FONTPATH.cpp +++ b/src/ports/SkFontHost_FONTPATH.cpp @@ -271,7 +271,8 @@ SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace, // static SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics( - uint32_t fontID, bool perGlyphInfo) { + uint32_t fontID, + SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo) { sk_throw(); // not implemented return NULL; } diff --git a/src/ports/SkFontHost_FreeType.cpp b/src/ports/SkFontHost_FreeType.cpp index 7cecb7f..280e0a1 100644 --- a/src/ports/SkFontHost_FreeType.cpp +++ b/src/ports/SkFontHost_FreeType.cpp @@ -98,12 +98,8 @@ InitFreetype() { // Setup LCD filtering. This reduces colour fringes for LCD rendered // glyphs. -//#ifdef ANDROID -// gLCDSupport = false; -//#else err = FT_Library_SetLcdFilter(gFTLibrary, FT_LCD_FILTER_DEFAULT); gLCDSupport = err == 0; -//#endif gLCDSupportValid = true; return true; @@ -345,7 +341,8 @@ static bool getWidthAdvance(FT_Face face, int gId, int16_t* data) { // static SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics( - uint32_t fontID, bool perGlyphInfo) { + uint32_t fontID, + SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo) { #if defined(SK_BUILD_FOR_MAC) || defined(ANDROID) return NULL; #else @@ -387,12 +384,6 @@ SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics( } } - SkASSERT(!FT_HAS_VERTICAL(face)); -#ifdef FT_IS_CID_KEYED - SkASSERT(FT_IS_CID_KEYED(face) == - (info->fType == SkAdvancedTypefaceMetrics::kType1CID_Font)); -#endif - info->fStyle = 0; if (FT_IS_FIXED_WIDTH(face)) info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style; @@ -464,8 +455,12 @@ SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics( info->fBBox = SkIRect::MakeLTRB(face->bbox.xMin, face->bbox.yMax, face->bbox.xMax, face->bbox.yMin); - if (perGlyphInfo && canEmbed(face) && FT_IS_SCALABLE(face) && - info->fType != SkAdvancedTypefaceMetrics::kOther_Font) { + if (!canEmbed(face) || !FT_IS_SCALABLE(face) || + info->fType == SkAdvancedTypefaceMetrics::kOther_Font) { + perGlyphInfo = SkAdvancedTypefaceMetrics::kNo_PerGlyphInfo; + } + + if (perGlyphInfo & SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo) { if (FT_IS_FIXED_WIDTH(face)) { appendRange(&info->fGlyphWidths, 0); int16_t advance = face->max_advance_width; @@ -493,18 +488,24 @@ SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics( info->fGlyphWidths.reset( getAdvanceData(face, face->num_glyphs, &getWidthAdvance)); } + } - if (info->fType == SkAdvancedTypefaceMetrics::kType1_Font) { - // Postscript fonts may contain more than 255 glyphs, so we end up - // using multiple font descriptions with a glyph ordering. Record - // the name of each glyph. - info->fGlyphNames.reset( - new SkAutoTArray<SkString>(face->num_glyphs)); - for (int gID = 0; gID < face->num_glyphs; gID++) { - char glyphName[128]; // PS limit for names is 127 bytes. - FT_Get_Glyph_Name(face, gID, glyphName, 128); - info->fGlyphNames->get()[gID].set(glyphName); - } + if (perGlyphInfo & SkAdvancedTypefaceMetrics::kVAdvance_PerGlyphInfo && + FT_HAS_VERTICAL(face)) { + SkASSERT(false); // Not implemented yet. + } + + if (perGlyphInfo & SkAdvancedTypefaceMetrics::kGlyphNames_PerGlyphInfo && + info->fType == SkAdvancedTypefaceMetrics::kType1_Font) { + // Postscript fonts may contain more than 255 glyphs, so we end up + // using multiple font descriptions with a glyph ordering. Record + // the name of each glyph. + info->fGlyphNames.reset( + new SkAutoTArray<SkString>(face->num_glyphs)); + for (int gID = 0; gID < face->num_glyphs; gID++) { + char glyphName[128]; // PS limit for names is 127 bytes. + FT_Get_Glyph_Name(face, gID, glyphName, 128); + info->fGlyphNames->get()[gID].set(glyphName); } } diff --git a/src/ports/SkFontHost_mac_atsui.cpp b/src/ports/SkFontHost_mac_atsui.cpp index 1d40a42..5bc438a 100644 --- a/src/ports/SkFontHost_mac_atsui.cpp +++ b/src/ports/SkFontHost_mac_atsui.cpp @@ -481,7 +481,8 @@ SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) { // static SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics( - uint32_t fontID, bool perGlyphInfo) { + uint32_t fontID, + SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo) { SkASSERT(!"SkFontHost::GetAdvancedTypefaceMetrics unimplemented"); return NULL; } diff --git a/src/ports/SkFontHost_mac_coretext.cpp b/src/ports/SkFontHost_mac_coretext.cpp index ae39361..2def427 100644 --- a/src/ports/SkFontHost_mac_coretext.cpp +++ b/src/ports/SkFontHost_mac_coretext.cpp @@ -18,28 +18,18 @@ #include "SkFontHost.h" #include "SkDescriptor.h" -#include "SkString.h" -#include "SkPaint.h" #include "SkFloatingPoint.h" +#include "SkPaint.h" +#include "SkString.h" +#include "SkTypeface_mac.h" #include "SkUtils.h" - -//============================================================================ -// Constants -//---------------------------------------------------------------------------- static const SkFontID kSkInvalidFontID = 0; static const size_t FONT_CACHE_MEMORY_BUDGET = 1024 * 1024; static const char FONT_DEFAULT_NAME[] = "Lucida Sans"; -static const float FONT_CANONICAL_POINTSIZE = 1.0f; - - -//============================================================================ -// Types -//---------------------------------------------------------------------------- -// Native font info typedef struct { SkString name; SkTypeface::Style style; @@ -47,13 +37,8 @@ typedef struct { CTFontRef fontRef; } SkNativeFontInfo; -typedef std::vector<SkNativeFontInfo> SkNativeFontInfoList; -typedef SkNativeFontInfoList::iterator SkNativeFontInfoListIterator; -typedef SkNativeFontInfoList::const_iterator SkNativeFontInfoListConstIterator; - - - - +typedef std::vector<SkNativeFontInfo> SkNativeFontInfoList; +typedef SkNativeFontInfoList::iterator SkNativeFontInfoListIterator; //============================================================================ // Macros @@ -73,7 +58,21 @@ typedef SkNativeFontInfoList::const_iterator SkNativeFont #endif +static SkTypeface::Style computeStyleBits(CTFontRef font, bool* isMonospace) { + unsigned style = SkTypeface::kNormal; + CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(font); + if (traits & kCTFontBoldTrait) { + style |= SkTypeface::kBold; + } + if (traits & kCTFontItalicTrait) { + style |= SkTypeface::kItalic; + } + if (isMonospace) { + *isMonospace = (traits & kCTFontMonoSpaceTrait) != 0; + } + return (SkTypeface::Style)style; +} //============================================================================ @@ -82,34 +81,24 @@ typedef SkNativeFontInfoList::const_iterator SkNativeFont #pragma mark - class SkNativeFontCache { public: - SkNativeFontCache(void); - virtual ~SkNativeFontCache(void); - - - // Is a font ID valid? - bool IsValid(SkFontID fontID); - + SkNativeFontCache(void); + virtual ~SkNativeFontCache(void); - // Get a font - CTFontRef GetFont(SkFontID fontID); - SkNativeFontInfo GetFontInfo(const SkString &theName, SkTypeface::Style theStyle); - - - // Create a font - SkNativeFontInfo CreateFont(const SkString &theName, SkTypeface::Style theStyle); - - - // Get the font table - static SkNativeFontCache *Get(void); + bool IsValid(SkFontID fontID); + CTFontRef GetFont(SkFontID fontID); + SkNativeFontInfo GetFontInfo(const char familyName[], SkTypeface::Style); + SkNativeFontInfo CreateFont(const char familyName[], SkTypeface::Style); + SkNativeFontInfo CreateFromCTFont(CTFontRef); + static SkNativeFontCache* Get(void); private: - CTFontRef CreateNativeFont(const SkString &name, SkTypeface::Style style); + CTFontRef CreateNativeFont(const char familyName[], SkTypeface::Style style); private: - SkNativeFontInfoList mFonts; - SkMutex mMutex; + SkNativeFontInfoList mFonts; + SkMutex mMutex; }; SkNativeFontCache::SkNativeFontCache(void) @@ -168,64 +157,76 @@ CTFontRef SkNativeFontCache::GetFont(SkFontID fontID) return(mFonts.at(fontID).fontRef); } -SkNativeFontInfo SkNativeFontCache::GetFontInfo(const SkString &theName, SkTypeface::Style theStyle) +SkNativeFontInfo SkNativeFontCache::GetFontInfo(const char familyName[], + SkTypeface::Style theStyle) { SkAutoMutexAcquire acquireLock(mMutex); SkNativeFontInfo fontInfo; SkNativeFontInfoListIterator theIter; - // Validate our parameters - SkASSERT(!theName.isEmpty()); - + SkASSERT(familyName && *familyName); // Get the state we need fontInfo.style = SkTypeface::kNormal; fontInfo.fontID = kSkInvalidFontID; fontInfo.fontRef = NULL; - // Get the font - for (theIter = mFonts.begin(); theIter != mFonts.end(); theIter++) - { - if (theIter->name == theName && theIter->style == theStyle) - return(*theIter); + for (theIter = mFonts.begin(); theIter != mFonts.end(); theIter++) { + if (theIter->style == theStyle && theIter->name.equals(familyName)) { + return *theIter; } + } - return(fontInfo); + return fontInfo; } -SkNativeFontInfo SkNativeFontCache::CreateFont(const SkString &theName, SkTypeface::Style theStyle) -{ SkAutoMutexAcquire acquireLock(mMutex); +SkNativeFontInfo SkNativeFontCache::CreateFont(const char familyName[], + SkTypeface::Style theStyle) { + SkAutoMutexAcquire acquireLock(mMutex); SkNativeFontInfo fontInfo; - - + + // Validate our parameters - SkASSERT(!theName.isEmpty()); - - + SkASSERT(familyName && *familyName); + + // Create the font - fontInfo.name = theName; - fontInfo.style = theStyle; - fontInfo.fontID = mFonts.size(); - fontInfo.fontRef = CreateNativeFont(theName, theStyle); - + fontInfo.name.set(familyName); + fontInfo.fontID = mFonts.size(); + fontInfo.fontRef = CreateNativeFont(familyName, theStyle); + fontInfo.style = computeStyleBits(fontInfo.fontRef, NULL); + mFonts.push_back(fontInfo); return(fontInfo); } -SkNativeFontCache *SkNativeFontCache::Get(void) -{ static SkNativeFontCache sInstance; - +SkNativeFontInfo SkNativeFontCache::CreateFromCTFont(CTFontRef font) { + SkAutoMutexAcquire acquireLock(mMutex); + SkNativeFontInfo fontInfo; + + // TODO: need to query the font's name +// fontInfo.name.set(familyName); + fontInfo.fontID = mFonts.size(); + fontInfo.fontRef = font; + CFRetain(font); + fontInfo.style = computeStyleBits(font, NULL); + + mFonts.push_back(fontInfo); + return(fontInfo); +} - // Get the instance - // +SkNativeFontCache *SkNativeFontCache::Get(void) { + static SkNativeFontCache sInstance; // We use a local static for well-defined static initialisation order. - return(&sInstance); + return &sInstance; } /////////////////////////////////////////////////////////////////////////// -CTFontRef SkNativeFontCache::CreateNativeFont(const SkString &theName, SkTypeface::Style theStyle) -{ CFMutableDictionaryRef cfAttributes, cfTraits; + +CTFontRef SkNativeFontCache::CreateNativeFont(const char familyName[], + SkTypeface::Style theStyle) { + CFMutableDictionaryRef cfAttributes, cfTraits; CFNumberRef cfFontTraits; CTFontSymbolicTraits ctFontTraits; CTFontDescriptorRef ctFontDesc; @@ -246,31 +247,25 @@ CTFontRef SkNativeFontCache::CreateNativeFont(const SkString &theName, SkTypefac // Create the font info - cfFontName = CFStringCreateWithCString(NULL, theName.c_str(), kCFStringEncodingUTF8); + cfFontName = CFStringCreateWithCString(NULL, familyName, kCFStringEncodingUTF8); cfFontTraits = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &ctFontTraits); cfAttributes = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); cfTraits = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); // Create the font - // - // Fonts are scaled using the Sk matrix, so we always request a font - // at a canonical size FONT_CANONICAL_POINTSIZE - if (cfFontName != NULL && cfFontTraits != NULL && cfAttributes != NULL && cfTraits != NULL) - { + if (cfFontName != NULL && cfFontTraits != NULL && cfAttributes != NULL && cfTraits != NULL) { CFDictionaryAddValue(cfTraits, kCTFontSymbolicTrait, cfFontTraits); CFDictionaryAddValue(cfAttributes, kCTFontFamilyNameAttribute, cfFontName); CFDictionaryAddValue(cfAttributes, kCTFontTraitsAttribute, cfTraits); ctFontDesc = CTFontDescriptorCreateWithAttributes(cfAttributes); - if (ctFontDesc != NULL) - ctFont = CTFontCreateWithFontDescriptor(ctFontDesc, FONT_CANONICAL_POINTSIZE, NULL); - + if (ctFontDesc != NULL) { + ctFont = CTFontCreateWithFontDescriptor(ctFontDesc, 0, NULL); } + } - - // Clean up CFSafeRelease(cfFontName); CFSafeRelease(cfFontTraits); CFSafeRelease(cfAttributes); @@ -280,28 +275,27 @@ CTFontRef SkNativeFontCache::CreateNativeFont(const SkString &theName, SkTypefac return(ctFont); } - - - - //============================================================================ // SkTypeface_Mac //---------------------------------------------------------------------------- #pragma mark - class SkTypeface_Mac : public SkTypeface { public: - SkTypeface_Mac(SkTypeface::Style style, uint32_t fontID); + SkTypeface_Mac(SkTypeface::Style style, uint32_t fontID); }; SkTypeface_Mac::SkTypeface_Mac(SkTypeface::Style style, uint32_t fontID) - : SkTypeface(style, fontID) -{ + : SkTypeface(style, fontID) { } - - +SkTypeface* SkCreateTypefaceFromCTFont(CTFontRef font) { + SkNativeFontInfo info; + + info = SkNativeFontCache::Get()->CreateFromCTFont(font); + return new SkTypeface_Mac(info.style, info.fontID); +} //============================================================================ // SkScalerContext_Mac @@ -358,15 +352,15 @@ SkScalerContext_Mac::SkScalerContext_Mac(const SkDescriptor* desc) mColorSpaceRGB = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGBLinear); mColorSpaceGray = CGColorSpaceCreateDeviceGray(); - const float inv = 1.0f / FONT_CANONICAL_POINTSIZE; - mTransform = CGAffineTransformMake(SkScalarToFloat(skMatrix[SkMatrix::kMScaleX]) * inv, - -SkScalarToFloat(skMatrix[SkMatrix::kMSkewY]) * inv, - -SkScalarToFloat(skMatrix[SkMatrix::kMSkewX]) * inv, - SkScalarToFloat(skMatrix[SkMatrix::kMScaleY]) * inv, - SkScalarToFloat(skMatrix[SkMatrix::kMTransX]) * inv, - SkScalarToFloat(skMatrix[SkMatrix::kMTransY]) * inv); + mTransform = CGAffineTransformMake(SkScalarToFloat(skMatrix[SkMatrix::kMScaleX]), + -SkScalarToFloat(skMatrix[SkMatrix::kMSkewY]), + -SkScalarToFloat(skMatrix[SkMatrix::kMSkewX]), + SkScalarToFloat(skMatrix[SkMatrix::kMScaleY]), + SkScalarToFloat(skMatrix[SkMatrix::kMTransX]), + SkScalarToFloat(skMatrix[SkMatrix::kMTransY])); - mFont = CTFontCreateCopyWithAttributes(ctFont, 0.0, &mTransform, NULL); + // since our matrix includes everything, we pass 1 for pointSize + mFont = CTFontCreateCopyWithAttributes(ctFont, 1, &mTransform, NULL); mGlyphCount = (uint16_t) numGlyphs; } @@ -445,6 +439,19 @@ void SkScalerContext_Mac::generateMetrics(SkGlyph* glyph) #include "SkColorPriv.h" +static void bytes_to_bits(uint8_t dst[], const uint8_t src[], int count) { + while (count > 0) { + uint8_t mask = 0; + for (int i = 7; i >= 0; --i) { + mask |= (*src++ >> 7) << i; + if (0 == --count) { + break; + } + } + *dst++ = mask; + } +} + static inline uint16_t rgb_to_lcd16(uint32_t rgb) { int r = (rgb >> 16) & 0xFF; int g = (rgb >> 8) & 0xFF; @@ -480,6 +487,7 @@ void SkScalerContext_Mac::generateImage(const SkGlyph& glyph) { void* image = glyph.fImage; size_t rowBytes = glyph.rowBytes(); float grayColor = 1; // white + bool doAA = true; /* For LCD16, we first create a temp offscreen cg-context in 32bit, * erase to white, and then draw a black glyph into it. Then we can @@ -496,6 +504,12 @@ void SkScalerContext_Mac::generateImage(const SkGlyph& glyph) { // we draw black-on-white (and invert in rgb_to_lcd16) sk_memset32((uint32_t*)image, 0xFFFFFFFF, size >> 2); grayColor = 0; // black + } else if (SkMask::kBW_Format == glyph.fMaskFormat) { + rowBytes = SkAlign4(glyph.fWidth); + size_t size = glyph.fHeight * rowBytes; + image = storage.realloc(size); + sk_bzero(image, size); + doAA = false; } cgContext = CGBitmapContextCreate(image, glyph.fWidth, glyph.fHeight, 8, @@ -503,13 +517,15 @@ void SkScalerContext_Mac::generateImage(const SkGlyph& glyph) { // Draw the glyph if (cgFont != NULL && cgContext != NULL) { +#ifdef WE_ARE_RUNNING_ON_10_6_OR_LATER CGContextSetAllowsFontSubpixelQuantization(cgContext, true); CGContextSetShouldSubpixelQuantizeFonts(cgContext, true); - +#endif + CGContextSetShouldAntialias(cgContext, doAA); CGContextSetGrayFillColor( cgContext, grayColor, 1.0); CGContextSetTextDrawingMode(cgContext, kCGTextFill); CGContextSetFont( cgContext, cgFont); - CGContextSetFontSize( cgContext, FONT_CANONICAL_POINTSIZE); + CGContextSetFontSize( cgContext, 1); // cgFont know's its size CGContextSetTextMatrix( cgContext, mTransform); CGContextShowGlyphsAtPoint( cgContext, -glyph.fLeft, glyph.fTop + glyph.fHeight, &cgGlyph, 1); @@ -526,6 +542,16 @@ void SkScalerContext_Mac::generateImage(const SkGlyph& glyph) { src = (const uint32_t*)((const char*)src + rowBytes); dst = (uint16_t*)((char*)dst + dstRB); } + } else if (SkMask::kBW_Format == glyph.fMaskFormat) { + // downsample from A8 to A1 + const uint8_t* src = (const uint8_t*)image; + uint8_t* dst = (uint8_t*)glyph.fImage; + size_t dstRB = glyph.rowBytes(); + for (int y = 0; y < glyph.fHeight; y++) { + bytes_to_bits(dst, src, glyph.fWidth); + src += rowBytes; + dst += dstRB; + } } } @@ -616,48 +642,55 @@ void SkScalerContext_Mac::CTPathElement(void *info, const CGPathElement *element } +static const char* map_css_names(const char* name) { + static const struct { + const char* fFrom; + const char* fTo; + } gPairs[] = { + { "sans-serif", "Helvetica" }, + { "serif", "Times" }, + { "monospace", "Courier" } + }; - + for (size_t i = 0; i < SK_ARRAY_COUNT(gPairs); i++) { + if (strcmp(name, gPairs[i].fFrom) == 0) { + return gPairs[i].fTo; + } + } + return name; // no change +} /////////////////////////////////////////////////////////////////////////// #pragma mark - SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace, - const char familyName[], - const void* data, size_t bytelength, - SkTypeface::Style style) -{ SkTypeface *theTypeface; - SkNativeFontCache *fontTable; - SkNativeFontInfo fontInfo; - SkString fontName; - - - // Get the state we need - fontName = SkString(familyName); - fontTable = SkNativeFontCache::Get(); + const char familyName[], + const void* data, size_t bytelength, + SkTypeface::Style style) { + if (familyName) { + familyName = map_css_names(familyName); + } + SkNativeFontCache* fontTable = SkNativeFontCache::Get(); // Clone an existing typeface // TODO: only clone if style matches the familyFace's style... - if (familyName == NULL && familyFace != NULL) - { + if (familyName == NULL && familyFace != NULL) { familyFace->ref(); - return(const_cast<SkTypeface*>(familyFace)); - } - + return const_cast<SkTypeface*>(familyFace); + } - if (fontName.isEmpty()) { - fontName.set(FONT_DEFAULT_NAME); + if (!familyName || !*familyName) { + familyName = FONT_DEFAULT_NAME; } - // Get the native font - fontInfo = fontTable->GetFontInfo(fontName, style); - if (fontInfo.fontID == kSkInvalidFontID) - fontInfo = fontTable->CreateFont(fontName, style); + // Get the native font + SkNativeFontInfo fontInfo = fontTable->GetFontInfo(familyName, style); + if (fontInfo.fontID == kSkInvalidFontID) { + fontInfo = fontTable->CreateFont(familyName, style); + } - // Create the typeface - theTypeface = new SkTypeface_Mac(fontInfo.style, fontInfo.fontID); - return(theTypeface); + return new SkTypeface_Mac(fontInfo.style, fontInfo.fontID); } SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) @@ -674,7 +707,8 @@ SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) // static SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics( - uint32_t fontID, bool perGlyphInfo) { + uint32_t fontID, + SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo) { SkASSERT(!"SkFontHost::GetAdvancedTypefaceMetrics unimplemented"); return NULL; } diff --git a/src/ports/SkFontHost_none.cpp b/src/ports/SkFontHost_none.cpp index d56c94a..91546f8 100644 --- a/src/ports/SkFontHost_none.cpp +++ b/src/ports/SkFontHost_none.cpp @@ -35,7 +35,8 @@ SkTypeface* SkFontHost::CreateTypefaceFromFile(char const*) { // static SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics( - uint32_t fontID, bool perGlyphInfo) { + uint32_t fontID, + SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo) { SkASSERT(!"SkFontHost::GetAdvancedTypefaceMetrics unimplemented"); return NULL; } diff --git a/src/ports/SkFontHost_simple.cpp b/src/ports/SkFontHost_simple.cpp index 60334e7..54d326e 100644 --- a/src/ports/SkFontHost_simple.cpp +++ b/src/ports/SkFontHost_simple.cpp @@ -592,7 +592,8 @@ SkStream* SkFontHost::OpenStream(uint32_t fontID) { #if 0 SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics( - uint32_t fontID, bool perGlyphInfo) { + uint32_t fontID, + SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo) { SkASSERT(!"SkFontHost::GetAdvancedTypefaceMetrics unimplemented"); return NULL; } diff --git a/src/ports/SkFontHost_win.cpp b/src/ports/SkFontHost_win.cpp index a4f430c..a75b002 100644 --- a/src/ports/SkFontHost_win.cpp +++ b/src/ports/SkFontHost_win.cpp @@ -449,7 +449,11 @@ void SkScalerContext_Windows::generateImage(const SkGlyph& glyph) { COLORREF color = SetTextColor(dc, 0); // black SkASSERT(color != CLR_INVALID); uint16_t glyphID = glyph.getGlyphID(); +#if defined(UNICODE) ExtTextOut(dc, 0, 0, ETO_GLYPH_INDEX, NULL, (LPCWSTR)&glyphID, 1, NULL); +#else + ExtTextOut(dc, 0, 0, ETO_GLYPH_INDEX, NULL, (LPCSTR)&glyphID, 1, NULL); +#endif GdiFlush(); // downsample from rgba to rgb565 @@ -609,7 +613,8 @@ static bool getWidthAdvance(HDC hdc, int gId, int16_t* advance) { // static SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics( - uint32_t fontID, bool perGlyphInfo) { + uint32_t fontID, + SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo) { SkAutoMutexAcquire ac(gFTMutex); LogFontTypeface* rec = LogFontTypeface::FindById(fontID); LOGFONT lf = rec->logFont(); @@ -717,7 +722,8 @@ SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics( // If bit 2 is set, the embedding is read-only. if (otm.otmfsType & 0x1) { info->fType = SkAdvancedTypefaceMetrics::kNotEmbeddable_Font; - } else if (perGlyphInfo) { + } else if (perGlyphInfo & + SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo) { info->fGlyphWidths.reset( getAdvanceData(hdc, glyphCount, &getWidthAdvance)); } diff --git a/src/ports/ports_files.mk b/src/ports/ports_files.mk new file mode 100644 index 0000000..563f20b --- /dev/null +++ b/src/ports/ports_files.mk @@ -0,0 +1,6 @@ +SOURCE := \ + SkDebug_stdio.cpp \ + SkGlobals_global.cpp \ + SkOSFile_stdio.cpp \ + SkThread_pthread.cpp \ + SkTime_Unix.cpp diff --git a/src/svg/SkSVGPaintState.cpp b/src/svg/SkSVGPaintState.cpp index 7fc90c7..f3c65e7 100644 --- a/src/svg/SkSVGPaintState.cpp +++ b/src/svg/SkSVGPaintState.cpp @@ -321,7 +321,7 @@ fillStrokeAttrCommon: if (strncmp(attrValue, "url(", 4) == 0) { SkASSERT(attrValue[4] == '#'); const char* idStart = attrValue + 5; - char* idEnd = strrchr(attrValue, ')'); + const char* idEnd = strrchr(attrValue, ')'); SkASSERT(idStart < idEnd); SkString id(idStart, idEnd - idStart); SkSVGElement* found; diff --git a/src/utils/SkOSFile.cpp b/src/utils/SkOSFile.cpp index 982bc08..c1b6943 100644 --- a/src/utils/SkOSFile.cpp +++ b/src/utils/SkOSFile.cpp @@ -31,18 +31,19 @@ SkUTF16_Str::SkUTF16_Str(const char src[]) size_t len = strlen(src); fStr = (uint16_t*)sk_malloc_throw((len + 1) * sizeof(uint16_t)); - for (size_t i = 0; i < len; i++) + size_t i; + for (i = 0; i < len; i++) fStr[i] = src[i]; fStr[i] = 0; } //////////////////////////////////////////////////////////////////////////// -SkOSFile::Iter::Iter() : fHandle(0), fPath16(nil) +SkOSFile::Iter::Iter() : fHandle(0), fPath16(NULL) { } -SkOSFile::Iter::Iter(const char path[], const char suffix[]) : fHandle(0), fPath16(nil) +SkOSFile::Iter::Iter(const char path[], const char suffix[]) : fHandle(0), fPath16(NULL) { this->reset(path, suffix); } @@ -61,7 +62,7 @@ void SkOSFile::Iter::reset(const char path[], const char suffix[]) ::FindClose(fHandle); fHandle = 0; } - if (path == nil) + if (NULL == path) path = ""; sk_free(fPath16); @@ -78,7 +79,7 @@ static bool get_the_file(HANDLE handle, SkString* name, WIN32_FIND_DATAW* dataPt { WIN32_FIND_DATAW data; - if (dataPtr == nil) + if (NULL == dataPtr) { if (::FindNextFileW(handle, &data)) dataPtr = &data; @@ -90,7 +91,7 @@ static bool get_the_file(HANDLE handle, SkString* name, WIN32_FIND_DATAW* dataPt { if (getDir) { - if ((dataPtr->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && !is_magic_dir(dataPtr->cFileName)) + if ((dataPtr->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && !is_magic_dir((uint16_t*)dataPtr->cFileName)) break; } else @@ -103,21 +104,21 @@ static bool get_the_file(HANDLE handle, SkString* name, WIN32_FIND_DATAW* dataPt } // if we get here, we've found a file/dir if (name) - name->setUTF16(dataPtr->cFileName); + name->setUTF16((uint16_t*)dataPtr->cFileName); return true; } bool SkOSFile::Iter::next(SkString* name, bool getDir) { WIN32_FIND_DATAW data; - WIN32_FIND_DATAW* dataPtr = nil; + WIN32_FIND_DATAW* dataPtr = NULL; if (fHandle == 0) // our first time { - if (fPath16 == nil || *fPath16 == 0) // check for no path + if (fPath16 == NULL || *fPath16 == 0) // check for no path return false; - fHandle = ::FindFirstFileW(fPath16, &data); + fHandle = ::FindFirstFileW((LPCWSTR)fPath16, &data); if (fHandle != 0 && fHandle != (HANDLE)~0) dataPtr = &data; } |