summaryrefslogtreecommitdiffstats
path: root/skia/sgl
diff options
context:
space:
mode:
Diffstat (limited to 'skia/sgl')
-rw-r--r--skia/sgl/SkAlphaRuns.cpp2
-rw-r--r--skia/sgl/SkAntiRun.h2
-rw-r--r--skia/sgl/SkAutoKern.h2
-rw-r--r--skia/sgl/SkBitmap.cpp65
-rw-r--r--skia/sgl/SkBitmapProcShader.h2
-rw-r--r--skia/sgl/SkBitmapProcState.cpp15
-rw-r--r--skia/sgl/SkBitmapProcState.h9
-rw-r--r--skia/sgl/SkBitmapProcState_matrix.h42
-rw-r--r--skia/sgl/SkBitmapProcState_matrixProcs.cpp71
-rw-r--r--skia/sgl/SkBitmapSampler.cpp2
-rw-r--r--skia/sgl/SkBitmapSampler.h2
-rw-r--r--skia/sgl/SkBitmapSamplerTemplate.h2
-rw-r--r--skia/sgl/SkBitmapShader.cpp2
-rw-r--r--skia/sgl/SkBitmapShader.h2
-rw-r--r--skia/sgl/SkBitmapShader16BilerpTemplate.h2
-rw-r--r--skia/sgl/SkBitmapShaderTemplate.h2
-rw-r--r--skia/sgl/SkBitmap_scroll.cpp1
-rw-r--r--skia/sgl/SkBlitBWMaskTemplate.h2
-rw-r--r--skia/sgl/SkBlitter.cpp2
-rw-r--r--skia/sgl/SkBlitter.h2
-rw-r--r--skia/sgl/SkBlitter_4444.cpp18
-rw-r--r--skia/sgl/SkBlitter_A1.cpp2
-rw-r--r--skia/sgl/SkBlitter_A8.cpp2
-rw-r--r--skia/sgl/SkBlitter_ARGB32.cpp2
-rw-r--r--skia/sgl/SkBlitter_RGB16.cpp12
-rw-r--r--skia/sgl/SkBlitter_Sprite.cpp2
-rw-r--r--skia/sgl/SkCanvas.cpp215
-rw-r--r--skia/sgl/SkColor.cpp6
-rw-r--r--skia/sgl/SkColorFilter.cpp2
-rw-r--r--skia/sgl/SkColorTable.cpp2
-rw-r--r--skia/sgl/SkCoreBlitters.h3
-rw-r--r--skia/sgl/SkDeque.cpp2
-rw-r--r--skia/sgl/SkDraw.cpp67
-rw-r--r--skia/sgl/SkEdge.cpp85
-rw-r--r--skia/sgl/SkEdge.h11
-rw-r--r--skia/sgl/SkFP.h2
-rw-r--r--skia/sgl/SkFilterProc.cpp2
-rw-r--r--skia/sgl/SkFilterProc.h8
-rw-r--r--skia/sgl/SkGeometry.cpp10
-rw-r--r--skia/sgl/SkGeometry.h2
-rw-r--r--skia/sgl/SkGlobals.cpp2
-rw-r--r--skia/sgl/SkGlyphCache.cpp104
-rw-r--r--skia/sgl/SkGlyphCache.h16
-rw-r--r--skia/sgl/SkGraphics.cpp130
-rw-r--r--skia/sgl/SkMask.cpp2
-rw-r--r--skia/sgl/SkMaskFilter.cpp2
-rw-r--r--skia/sgl/SkPaint.cpp126
-rw-r--r--skia/sgl/SkPath.cpp128
-rw-r--r--skia/sgl/SkPathEffect.cpp2
-rw-r--r--skia/sgl/SkPathMeasure.cpp2
-rw-r--r--skia/sgl/SkPicture.cpp238
-rw-r--r--skia/sgl/SkProcSpriteBlitter.cpp2
-rw-r--r--skia/sgl/SkRasterizer.cpp2
-rw-r--r--skia/sgl/SkRefCnt.cpp2
-rw-r--r--skia/sgl/SkRegion_path.cpp39
-rw-r--r--skia/sgl/SkScalerContext.cpp24
-rw-r--r--skia/sgl/SkScan.cpp8
-rw-r--r--skia/sgl/SkScan.h10
-rw-r--r--skia/sgl/SkScanPriv.h2
-rw-r--r--skia/sgl/SkScan_AntiPath.cpp2
-rw-r--r--skia/sgl/SkScan_Antihair.cpp214
-rw-r--r--skia/sgl/SkScan_Hairline.cpp57
-rw-r--r--skia/sgl/SkScan_Path.cpp12
-rw-r--r--skia/sgl/SkShader.cpp2
-rw-r--r--skia/sgl/SkSpriteBlitter.h2
-rw-r--r--skia/sgl/SkSpriteBlitterTemplate.h2
-rw-r--r--skia/sgl/SkSpriteBlitter_ARGB32.cpp2
-rw-r--r--skia/sgl/SkSpriteBlitter_RGB16.cpp9
-rw-r--r--skia/sgl/SkString.cpp7
-rw-r--r--skia/sgl/SkStroke.cpp66
-rw-r--r--skia/sgl/SkStrokerPriv.cpp2
-rw-r--r--skia/sgl/SkStrokerPriv.h2
-rw-r--r--skia/sgl/SkTSearch.cpp2
-rw-r--r--skia/sgl/SkTSort.h2
-rw-r--r--skia/sgl/SkTemplatesPriv.h2
-rw-r--r--skia/sgl/SkUtils.cpp4
-rw-r--r--skia/sgl/SkWriter32.cpp9
-rw-r--r--skia/sgl/SkXfermode.cpp15
78 files changed, 1169 insertions, 771 deletions
diff --git a/skia/sgl/SkAlphaRuns.cpp b/skia/sgl/SkAlphaRuns.cpp
index 35fcfd6..46b0206 100644
--- a/skia/sgl/SkAlphaRuns.cpp
+++ b/skia/sgl/SkAlphaRuns.cpp
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkAlphaRuns.cpp
**
-** Copyright 2006, Google Inc.
+** 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.
diff --git a/skia/sgl/SkAntiRun.h b/skia/sgl/SkAntiRun.h
index 32814f1..12930e66 100644
--- a/skia/sgl/SkAntiRun.h
+++ b/skia/sgl/SkAntiRun.h
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkAntiRun.h
**
-** Copyright 2006, Google Inc.
+** 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.
diff --git a/skia/sgl/SkAutoKern.h b/skia/sgl/SkAutoKern.h
index 644ad85..023cb6b 100644
--- a/skia/sgl/SkAutoKern.h
+++ b/skia/sgl/SkAutoKern.h
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkAutoKern.h
**
-** Copyright 2006, Google Inc.
+** 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.
diff --git a/skia/sgl/SkBitmap.cpp b/skia/sgl/SkBitmap.cpp
index 914fc77..5ca3601 100644
--- a/skia/sgl/SkBitmap.cpp
+++ b/skia/sgl/SkBitmap.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006-2008 Google Inc.
+ * Copyright (C) 2006-2008 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.
@@ -18,6 +18,7 @@
#include "SkColorPriv.h"
#include "SkDither.h"
#include "SkFlattenable.h"
+#include "SkMallocPixelRef.h"
#include "SkMask.h"
#include "SkPixelRef.h"
#include "SkThread.h"
@@ -33,8 +34,8 @@ struct MipLevel {
};
struct SkBitmap::MipMap : SkNoncopyable {
- int fRefCnt;
- int fLevelCount;
+ int32_t fRefCnt;
+ int fLevelCount;
// MipLevel fLevel[fLevelCount];
// Pixels[]
@@ -203,6 +204,20 @@ int SkBitmap::ComputeRowBytes(Config c, int width) {
return rowBytes;
}
+Sk64 SkBitmap::ComputeSize64(Config c, int width, int height) {
+ Sk64 size;
+ size.setMul(SkBitmap::ComputeRowBytes(c, width), height);
+ return size;
+}
+
+size_t SkBitmap::ComputeSize(Config c, int width, int height) {
+ Sk64 size = SkBitmap::ComputeSize64(c, width, height);
+ if (size.isNeg() || !size.is32()) {
+ return 0;
+ }
+ return size.get32();
+}
+
void SkBitmap::setConfig(Config c, int width, int height, int rowBytes) {
this->freePixels();
@@ -334,40 +349,6 @@ void SkBitmap::notifyPixelsChanged() const {
///////////////////////////////////////////////////////////////////////////////
-/** We explicitly use the same allocator for our pixels that SkMask does,
- so that we can freely assign memory allocated by one class to the other.
- */
-class SkMallocPixelRef : public SkPixelRef {
-public:
- /** Allocate the specified buffer for pixels. The memory is freed when the
- last owner of this pixelref is gone.
- */
- SkMallocPixelRef(void* addr, size_t size, SkColorTable* ctable);
- virtual ~SkMallocPixelRef();
-
- virtual void flatten(SkFlattenableWriteBuffer&) const;
- virtual Factory getFactory() const {
- return Create;
- }
- static SkPixelRef* Create(SkFlattenableReadBuffer& buffer) {
- return SkNEW_ARGS(SkMallocPixelRef, (buffer));
- }
-
-protected:
- // overrides from SkPixelRef
- virtual void* onLockPixels(SkColorTable**);
- virtual void onUnlockPixels();
-
- SkMallocPixelRef(SkFlattenableReadBuffer& buffer);
-
-private:
- void* fStorage;
- size_t fSize;
- SkColorTable* fCTable;
-
- typedef SkPixelRef INHERITED;
-};
-
SkMallocPixelRef::SkMallocPixelRef(void* storage, size_t size,
SkColorTable* ctable) {
SkASSERT(storage);
@@ -416,7 +397,7 @@ SkMallocPixelRef::SkMallocPixelRef(SkFlattenableReadBuffer& buffer) : INHERITED(
}
static SkPixelRef::Registrar reg("SkMallocPixelRef",
- SkMallocPixelRef::Create);
+ SkMallocPixelRef::Create);
/** We explicitly use the same allocator for our pixels that SkMask does,
so that we can freely assign memory allocated by one class to the other.
@@ -534,7 +515,7 @@ void SkBitmap::eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const {
SkAutoLockPixels alp(*this);
// perform this check after the lock call
- if (NULL == fPixels) {
+ if (!this->readyToDraw()) {
return;
}
@@ -648,6 +629,8 @@ bool SkBitmap::extractSubset(SkBitmap* result, const SkIRect& subset) const {
if (kRLE_Index8_Config == fConfig) {
SkAutoLockPixels alp(*this);
+ // don't call readyToDraw(), since we can operate w/o a colortable
+ // at this stage
if (this->getPixels() == NULL) {
return false;
}
@@ -725,7 +708,7 @@ bool SkBitmap::copyTo(SkBitmap* dst, Config dstConfig, Allocator* alloc) const {
SkAutoLockPixels srclock(*this);
SkAutoLockPixels dstlock(tmp);
- if (NULL == this->getPixels() || NULL == tmp.getPixels()) {
+ if (!this->readyToDraw() || !tmp.readyToDraw()) {
// allocator/lock failed
return false;
}
@@ -1257,6 +1240,7 @@ void SkBitmap::validate() const {
SkASSERT(NULL == fColorTable || (unsigned)fColorTable->getRefCnt() < 10000);
SkASSERT((uint8_t)ComputeBytesPerPixel((Config)fConfig) == fBytesPerPixel);
+#if 0 // these asserts are not thread-correct, so disable for now
if (fPixelRef) {
if (fPixelLockCount > 0) {
SkASSERT(fPixelRef->getLockCount() > 0);
@@ -1265,6 +1249,7 @@ void SkBitmap::validate() const {
SkASSERT(NULL == fColorTable);
}
}
+#endif
}
#endif
diff --git a/skia/sgl/SkBitmapProcShader.h b/skia/sgl/SkBitmapProcShader.h
index 6d7d0d9..ed790c8 100644
--- a/skia/sgl/SkBitmapProcShader.h
+++ b/skia/sgl/SkBitmapProcShader.h
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkBitmapShader.h
**
-** Copyright 2006, Google Inc.
+** 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.
diff --git a/skia/sgl/SkBitmapProcState.cpp b/skia/sgl/SkBitmapProcState.cpp
index aff7e9d..428921d 100644
--- a/skia/sgl/SkBitmapProcState.cpp
+++ b/skia/sgl/SkBitmapProcState.cpp
@@ -296,9 +296,8 @@ bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) {
}
const SkMatrix* m;
- if (inv.getType() <= SkMatrix::kTranslate_Mask ||
- (SkShader::kClamp_TileMode == fTileModeX &&
- SkShader::kClamp_TileMode == fTileModeY)) {
+ if (SkShader::kClamp_TileMode == fTileModeX &&
+ SkShader::kClamp_TileMode == fTileModeY) {
m = &inv;
} else {
fUnitInvMatrix = inv;
@@ -331,16 +330,6 @@ bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) {
fInvMatrix = m;
fInvProc = m->getMapXYProc();
fInvType = m->getType();
- if (fInvType <= SkMatrix::kTranslate_Mask &&
- inv.getType() > SkMatrix::kTranslate_Mask) {
- SkASSERT(inv.getType() <=
- (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask));
- // It is possible that by the calculation of fUnitInvMatrix, we have
- // eliminated the scale transformation of the matrix (e.g., if inv^(-1)
- // scales fOrigBitmap into an 1X1 rect). We add the scale flag back so
- // that we don't make wrong choice in chooseMatrixProc().
- fInvType |= SkMatrix::kScale_Mask;
- }
fInvSx = SkScalarToFixed(m->getScaleX());
fInvSy = SkScalarToFixed(m->getScaleY());
fInvKy = SkScalarToFixed(m->getSkewY());
diff --git a/skia/sgl/SkBitmapProcState.h b/skia/sgl/SkBitmapProcState.h
index e48a8c3..1366d3b 100644
--- a/skia/sgl/SkBitmapProcState.h
+++ b/skia/sgl/SkBitmapProcState.h
@@ -1,5 +1,5 @@
/*
-** Copyright 2007, Google Inc.
+** Copyright 2007, 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.
@@ -39,9 +39,8 @@ struct SkBitmapProcState {
int count,
uint16_t colors[]);
- typedef SkFixed (*FixedTileProc)(SkFixed, int);
- typedef int (*IntTileProc)(int, int);
-
+ typedef U16CPU (*FixedTileProc)(SkFixed); // returns 0..0xFFFF
+
MatrixProc fMatrixProc; // chooseProcs
SampleProc32 fSampleProc32; // chooseProcs
SampleProc16 fSampleProc16; // chooseProcs
@@ -49,8 +48,6 @@ struct SkBitmapProcState {
SkMatrix fUnitInvMatrix; // chooseProcs
FixedTileProc fTileProcX; // chooseProcs
FixedTileProc fTileProcY; // chooseProcs
- IntTileProc iTileProcX; // chooseProcs
- IntTileProc iTileProcY; // chooseProcs
SkFixed fFilterOneX;
SkFixed fFilterOneY;
diff --git a/skia/sgl/SkBitmapProcState_matrix.h b/skia/sgl/SkBitmapProcState_matrix.h
index fe551c2..1212a41 100644
--- a/skia/sgl/SkBitmapProcState_matrix.h
+++ b/skia/sgl/SkBitmapProcState_matrix.h
@@ -1,5 +1,4 @@
-#define TRANSLATE_NOFILTER_NAME MAKENAME(_nofilter_translate)
#define SCALE_NOFILTER_NAME MAKENAME(_nofilter_scale)
#define SCALE_FILTER_NAME MAKENAME(_filter_scale)
#define AFFINE_NOFILTER_NAME MAKENAME(_nofilter_affine)
@@ -18,38 +17,6 @@
#define PREAMBLE_ARG_Y
#endif
-#ifndef PREAMBLE_TRANS
- #define PREAMBLE_TRANS(state)
-#endif
-
-static void TRANSLATE_NOFILTER_NAME(const SkBitmapProcState& s,
- uint32_t xy[], int count, int x, int y)
-{
- SkASSERT((s.fInvType & ~SkMatrix::kTranslate_Mask) == 0);
-
- PREAMBLE_TRANS(s);
-
- x += SkScalarFloor(s.fInvMatrix->getTranslateX());
- y += SkScalarFloor(s.fInvMatrix->getTranslateY());
-
- *xy++ = (uint32_t)TILEY_TRANS(y, (s.fBitmap->height() - 1));
-
- int maxX = s.fBitmap->width() - 1;
- int i;
- uint16_t* xx = (uint16_t*)xy;
- for (i = (count >> 2); i > 0; --i)
- {
- *xx++ = (uint16_t)TILEX_TRANS(x, maxX); x++;
- *xx++ = (uint16_t)TILEX_TRANS(x, maxX); x++;
- *xx++ = (uint16_t)TILEX_TRANS(x, maxX); x++;
- *xx++ = (uint16_t)TILEX_TRANS(x, maxX); x++;
- }
- for (i = (count & 3); i > 0; --i)
- {
- *xx++ = (uint16_t)TILEX_TRANS(x, maxX); x++;
- }
-}
-
static void SCALE_NOFILTER_NAME(const SkBitmapProcState& s,
uint32_t xy[], int count, int x, int y) {
SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask |
@@ -274,9 +241,6 @@ static void PERSP_FILTER_NAME(const SkBitmapProcState& s,
}
static SkBitmapProcState::MatrixProc MAKENAME(_Procs)[] = {
- TRANSLATE_NOFILTER_NAME,
- TRANSLATE_NOFILTER_NAME, // No need to do filtering if the matrix is no
- // more complex than identity/translate.
SCALE_NOFILTER_NAME,
SCALE_FILTER_NAME,
AFFINE_NOFILTER_NAME,
@@ -291,10 +255,7 @@ static SkBitmapProcState::MatrixProc MAKENAME(_Procs)[] = {
#ifdef CHECK_FOR_DECAL
#undef CHECK_FOR_DECAL
#endif
-#undef TILEX_TRANS
-#undef TILEY_TRANS
-
-#undef TRANSLATE_NOFILTER_NAME
+
#undef SCALE_NOFILTER_NAME
#undef SCALE_FILTER_NAME
#undef AFFINE_NOFILTER_NAME
@@ -307,7 +268,6 @@ static SkBitmapProcState::MatrixProc MAKENAME(_Procs)[] = {
#undef PREAMBLE_PARAM_Y
#undef PREAMBLE_ARG_X
#undef PREAMBLE_ARG_Y
-#undef PREAMBLE_TRANS
#undef TILEX_LOW_BITS
#undef TILEY_LOW_BITS
diff --git a/skia/sgl/SkBitmapProcState_matrixProcs.cpp b/skia/sgl/SkBitmapProcState_matrixProcs.cpp
index 369f9ff..beb21c8 100644
--- a/skia/sgl/SkBitmapProcState_matrixProcs.cpp
+++ b/skia/sgl/SkBitmapProcState_matrixProcs.cpp
@@ -28,8 +28,6 @@ void decal_filter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count);
#define TILEX_LOW_BITS(fx, max) (((fx) >> 12) & 0xF)
#define TILEY_LOW_BITS(fy, max) (((fy) >> 12) & 0xF)
#define CHECK_FOR_DECAL
-#define TILEX_TRANS(x, max) SkClampMax(x, max)
-#define TILEY_TRANS(y, max) SkClampMax(y, max)
#include "SkBitmapProcState_matrix.h"
#define MAKENAME(suffix) RepeatX_RepeatY ## suffix
@@ -37,9 +35,6 @@ void decal_filter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count);
#define TILEY_PROCF(fy, max) (((fy) & 0xFFFF) * ((max) + 1) >> 16)
#define TILEX_LOW_BITS(fx, max) ((((fx) & 0xFFFF) * ((max) + 1) >> 12) & 0xF)
#define TILEY_LOW_BITS(fy, max) ((((fy) & 0xFFFF) * ((max) + 1) >> 12) & 0xF)
-#define REAL_MOD(val, modulus) (((val)%(modulus)) + (modulus)*( (val)<0 ))
-#define TILEX_TRANS(x, max) (REAL_MOD((x), ((max) + 1)))
-#define TILEY_TRANS(y, max) (REAL_MOD((y), ((max) + 1)))
#include "SkBitmapProcState_matrix.h"
#define MAKENAME(suffix) GeneralXY ## suffix
@@ -49,17 +44,13 @@ void decal_filter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count);
#define PREAMBLE_PARAM_Y , SkBitmapProcState::FixedTileProc tileProcY
#define PREAMBLE_ARG_X , tileProcX
#define PREAMBLE_ARG_Y , tileProcY
-#define TILEX_PROCF(fx, max) (tileProcX(fx, max) >> 16)
-#define TILEY_PROCF(fy, max) (tileProcY(fy, max) >> 16)
-#define TILEX_LOW_BITS(fx, max) ((tileProcX(fx, max) >> 14) & 0x3)
-#define TILEY_LOW_BITS(fy, max) ((tileProcY(fy, max) >> 14) & 0x3)
-#define PREAMBLE_TRANS(state) SkBitmapProcState::IntTileProc tileProcX = (state).iTileProcX; \
- SkBitmapProcState::IntTileProc tileProcY = (state).iTileProcY
-#define TILEX_TRANS(x, max) tileProcX(x, max)
-#define TILEY_TRANS(y, max) tileProcY(y, max)
+#define TILEX_PROCF(fx, max) (tileProcX(fx) * ((max) + 1) >> 16)
+#define TILEY_PROCF(fy, max) (tileProcY(fy) * ((max) + 1) >> 16)
+#define TILEX_LOW_BITS(fx, max) ((tileProcX(fx) * ((max) + 1) >> 12) & 0xF)
+#define TILEY_LOW_BITS(fy, max) ((tileProcY(fy) * ((max) + 1) >> 12) & 0xF)
#include "SkBitmapProcState_matrix.h"
-static inline SkFixed fixed_clamp(SkFixed x, int max)
+static inline U16CPU fixed_clamp(SkFixed x)
{
#ifdef SK_CPU_HAS_CONDITIONAL_INSTR
if (x >> 16)
@@ -75,20 +66,19 @@ static inline SkFixed fixed_clamp(SkFixed x, int max)
x = 0xFFFF;
}
#endif
- return x * (max + 1);
+ return x;
}
-static inline SkFixed fixed_repeat(SkFixed x, int max)
+static inline U16CPU fixed_repeat(SkFixed x)
{
- return (x & 0xFFFF) * (max + 1);
+ return x & 0xFFFF;
}
-static inline SkFixed fixed_mirror(SkFixed x, int max)
+static inline U16CPU fixed_mirror(SkFixed x)
{
SkFixed s = x << 15 >> 31;
// s is FFFFFFFF if we're on an odd interval, or 0 if an even interval
- x = ((x ^ s) & 0xFFFF) * (max + 1);
- return s ? (x ^ 0xFFFF) : x;
+ return (x ^ s) & 0xFFFF;
}
static SkBitmapProcState::FixedTileProc choose_tile_proc(unsigned m)
@@ -100,41 +90,6 @@ static SkBitmapProcState::FixedTileProc choose_tile_proc(unsigned m)
SkASSERT(SkShader::kMirror_TileMode == m);
return fixed_mirror;
}
-
-static inline int int_clamp(int x, int max)
-{
- SkASSERT(max >= 0);
-
- return SkClampMax(x, max);
-}
-
-static inline int int_repeat(int x, int max)
-{
- SkASSERT(max >= 0);
-
- return x % (max + 1);
-}
-
-static inline int int_mirror(int x, int max)
-{
- SkASSERT(max >= 0);
-
- int dx = x % (max + 1);
- if (dx < 0)
- dx = -dx - 1;
-
- return (x / (max + 1) % 2) ? max - dx : dx;
-}
-
-static SkBitmapProcState::IntTileProc choose_int_tile_proc(unsigned m)
-{
- if (SkShader::kClamp_TileMode == m)
- return int_clamp;
- if (SkShader::kRepeat_TileMode == m)
- return int_repeat;
- SkASSERT(SkShader::kMirror_TileMode == m);
- return int_mirror;
-}
SkBitmapProcState::MatrixProc SkBitmapProcState::chooseMatrixProc()
{
@@ -142,10 +97,8 @@ SkBitmapProcState::MatrixProc SkBitmapProcState::chooseMatrixProc()
if (fDoFilter)
index = 1;
if (fInvType & SkMatrix::kPerspective_Mask)
- index |= 6;
- else if (fInvType & SkMatrix::kAffine_Mask)
index |= 4;
- else if (fInvType & SkMatrix::kScale_Mask)
+ else if (fInvType & SkMatrix::kAffine_Mask)
index |= 2;
if (SkShader::kClamp_TileMode == fTileModeX &&
@@ -170,8 +123,6 @@ SkBitmapProcState::MatrixProc SkBitmapProcState::chooseMatrixProc()
// only general needs these procs
fTileProcX = choose_tile_proc(fTileModeX);
fTileProcY = choose_tile_proc(fTileModeY);
- iTileProcX = choose_int_tile_proc(fTileModeX);
- iTileProcY = choose_int_tile_proc(fTileModeY);
return GeneralXY_Procs[index];
}
diff --git a/skia/sgl/SkBitmapSampler.cpp b/skia/sgl/SkBitmapSampler.cpp
index 924aeaa..045efd1 100644
--- a/skia/sgl/SkBitmapSampler.cpp
+++ b/skia/sgl/SkBitmapSampler.cpp
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkBitmapSampler.cpp
**
-** Copyright 2006, Google Inc.
+** 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.
diff --git a/skia/sgl/SkBitmapSampler.h b/skia/sgl/SkBitmapSampler.h
index b31bb9f..eeef3b3 100644
--- a/skia/sgl/SkBitmapSampler.h
+++ b/skia/sgl/SkBitmapSampler.h
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkBitmapSampler.h
**
-** Copyright 2006, Google Inc.
+** 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.
diff --git a/skia/sgl/SkBitmapSamplerTemplate.h b/skia/sgl/SkBitmapSamplerTemplate.h
index d9680d6..00df10c 100644
--- a/skia/sgl/SkBitmapSamplerTemplate.h
+++ b/skia/sgl/SkBitmapSamplerTemplate.h
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkBitmapSamplerTemplate.h
**
-** Copyright 2006, Google Inc.
+** 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.
diff --git a/skia/sgl/SkBitmapShader.cpp b/skia/sgl/SkBitmapShader.cpp
index 939080d..5d70dd3 100644
--- a/skia/sgl/SkBitmapShader.cpp
+++ b/skia/sgl/SkBitmapShader.cpp
@@ -1,4 +1,4 @@
-/* Copyright 2006, Google Inc.
+/* 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.
diff --git a/skia/sgl/SkBitmapShader.h b/skia/sgl/SkBitmapShader.h
index d64274c..8d40a4b 100644
--- a/skia/sgl/SkBitmapShader.h
+++ b/skia/sgl/SkBitmapShader.h
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkBitmapShader.h
**
-** Copyright 2006, Google Inc.
+** 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.
diff --git a/skia/sgl/SkBitmapShader16BilerpTemplate.h b/skia/sgl/SkBitmapShader16BilerpTemplate.h
index 555d587..b70801e 100644
--- a/skia/sgl/SkBitmapShader16BilerpTemplate.h
+++ b/skia/sgl/SkBitmapShader16BilerpTemplate.h
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkBitmapShader16BilerpTemplate.h
**
-** Copyright 2006, Google Inc.
+** 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.
diff --git a/skia/sgl/SkBitmapShaderTemplate.h b/skia/sgl/SkBitmapShaderTemplate.h
index b24168c..0174138 100644
--- a/skia/sgl/SkBitmapShaderTemplate.h
+++ b/skia/sgl/SkBitmapShaderTemplate.h
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkBitmapShaderTemplate.h
**
-** Copyright 2006, Google Inc.
+** 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.
diff --git a/skia/sgl/SkBitmap_scroll.cpp b/skia/sgl/SkBitmap_scroll.cpp
index eb2abc8..f9f197d 100644
--- a/skia/sgl/SkBitmap_scroll.cpp
+++ b/skia/sgl/SkBitmap_scroll.cpp
@@ -64,6 +64,7 @@ bool SkBitmap::scrollRect(const SkIRect* subset, int dx, int dy,
SkAutoLockPixels alp(*this);
// if we have no pixels, just return (inval is already updated)
+ // don't call readyToDraw(), since we don't require a colortable per se
if (this->getPixels() == NULL) {
return true;
}
diff --git a/skia/sgl/SkBlitBWMaskTemplate.h b/skia/sgl/SkBlitBWMaskTemplate.h
index f7767fb..e433d36 100644
--- a/skia/sgl/SkBlitBWMaskTemplate.h
+++ b/skia/sgl/SkBlitBWMaskTemplate.h
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkBlitBWMaskTemplate.h
**
-** Copyright 2006, Google Inc.
+** 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.
diff --git a/skia/sgl/SkBlitter.cpp b/skia/sgl/SkBlitter.cpp
index 95a67c7..9208429 100644
--- a/skia/sgl/SkBlitter.cpp
+++ b/skia/sgl/SkBlitter.cpp
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkBlitter.cpp
**
-** Copyright 2006, Google Inc.
+** 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.
diff --git a/skia/sgl/SkBlitter.h b/skia/sgl/SkBlitter.h
index 56d69c9..11b84fd 100644
--- a/skia/sgl/SkBlitter.h
+++ b/skia/sgl/SkBlitter.h
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkBlitter.h
**
-** Copyright 2006, Google Inc.
+** 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.
diff --git a/skia/sgl/SkBlitter_4444.cpp b/skia/sgl/SkBlitter_4444.cpp
index de42312..cce94c5 100644
--- a/skia/sgl/SkBlitter_4444.cpp
+++ b/skia/sgl/SkBlitter_4444.cpp
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkBlitter_ARGB32.cpp
**
- ** Copyright 2006, Google Inc.
+ ** 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.
@@ -379,11 +379,14 @@ class SkARGB4444_Shader_Blitter : public SkShaderBlitter {
SkBlitRow::Proc fOpaqueProc;
SkBlitRow::Proc fAlphaProc;
SkPMColor* fBuffer;
+ uint8_t* fAAExpand;
public:
SkARGB4444_Shader_Blitter(const SkBitmap& device, const SkPaint& paint)
: INHERITED(device, paint)
{
- fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * (sizeof(SkPMColor)));
+ const int width = device.width();
+ fBuffer = (SkPMColor*)sk_malloc_throw(width * sizeof(SkPMColor) + width);
+ fAAExpand = (uint8_t*)(fBuffer + width);
(fXfermode = paint.getXfermode())->safeRef();
@@ -423,7 +426,8 @@ virtual void blitH(int x, int y, int width)
virtual void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[])
{
- SkPMColor* span = fBuffer;
+ SkPMColor* SK_RESTRICT span = fBuffer;
+ uint8_t* SK_RESTRICT aaExpand = fAAExpand;
SkPMColor16* device = fDevice.getAddr16(x, y);
SkShader* shader = fShader;
SkXfermode* xfer = fXfermode;
@@ -439,10 +443,12 @@ virtual void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t ru
if (255 == aa) {
xfer->xfer4444(device, span, count, NULL);
} else {
- // count is almost always 1
- for (int i = count - 1; i >= 0; --i) {
- xfer->xfer4444(&device[i], &span[i], count, antialias);
+ const uint8_t* aaBuffer = antialias;
+ if (count > 1) {
+ memset(aaExpand, aa, count);
+ aaBuffer = aaExpand;
}
+ xfer->xfer4444(device, span, count, aaBuffer);
}
}
device += count;
diff --git a/skia/sgl/SkBlitter_A1.cpp b/skia/sgl/SkBlitter_A1.cpp
index 61d9cf6..1a91a26 100644
--- a/skia/sgl/SkBlitter_A1.cpp
+++ b/skia/sgl/SkBlitter_A1.cpp
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkBlitter_A1.cpp
**
-** Copyright 2006, Google Inc.
+** 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.
diff --git a/skia/sgl/SkBlitter_A8.cpp b/skia/sgl/SkBlitter_A8.cpp
index 23f7f01..18b0881 100644
--- a/skia/sgl/SkBlitter_A8.cpp
+++ b/skia/sgl/SkBlitter_A8.cpp
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkBlitter_A8.cpp
**
-** Copyright 2006, Google Inc.
+** 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.
diff --git a/skia/sgl/SkBlitter_ARGB32.cpp b/skia/sgl/SkBlitter_ARGB32.cpp
index 0fa0e0b..ed2fc0e 100644
--- a/skia/sgl/SkBlitter_ARGB32.cpp
+++ b/skia/sgl/SkBlitter_ARGB32.cpp
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkBlitter_ARGB32.cpp
**
-** Copyright 2006, Google Inc.
+** 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.
diff --git a/skia/sgl/SkBlitter_RGB16.cpp b/skia/sgl/SkBlitter_RGB16.cpp
index aca515d..b253662 100644
--- a/skia/sgl/SkBlitter_RGB16.cpp
+++ b/skia/sgl/SkBlitter_RGB16.cpp
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkBlitter_RGB16.cpp
**
-** Copyright 2006, Google Inc.
+** 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.
@@ -161,6 +161,7 @@ SkRGB16_Blitter::SkRGB16_Blitter(const SkBitmap& device, const SkPaint& paint)
: INHERITED(device) {
SkColor color = paint.getColor();
+ fSrcColor32 = SkPreMultiplyColor(color);
fScale = SkAlpha255To256(SkColorGetA(color));
int r = SkColorGetR(color);
@@ -210,9 +211,9 @@ void SkRGB16_Blitter::blitH(int x, int y, int width) SK_RESTRICT {
}
} else {
// TODO: respect fDoDither
- unsigned scale = 256 - fScale;
+ SkPMColor src32 = fSrcColor32;
do {
- *device = srcColor + SkAlphaMulRGB16(*device, scale);
+ *device = SkSrcOver32To16(src32, *device);
device += 1;
} while (--width != 0);
}
@@ -467,11 +468,10 @@ void SkRGB16_Blitter::blitRect(int x, int y, int width, int height) {
}
}
} else {
- unsigned dst_scale = 256 - fScale; // apply it to the dst
-
+ SkPMColor src32 = fSrcColor32;
while (--height >= 0) {
for (int i = width - 1; i >= 0; --i) {
- device[i] = color16 + SkAlphaMulRGB16(device[i], dst_scale);
+ device[i] = SkSrcOver32To16(src32, device[i]);
}
device = (uint16_t*)((char*)device + deviceRB);
}
diff --git a/skia/sgl/SkBlitter_Sprite.cpp b/skia/sgl/SkBlitter_Sprite.cpp
index 6ce8f13..f0da166 100644
--- a/skia/sgl/SkBlitter_Sprite.cpp
+++ b/skia/sgl/SkBlitter_Sprite.cpp
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkBlitter_Sprite.cpp
**
-** Copyright 2006, Google Inc.
+** 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.
diff --git a/skia/sgl/SkCanvas.cpp b/skia/sgl/SkCanvas.cpp
index a657023..4088416 100644
--- a/skia/sgl/SkCanvas.cpp
+++ b/skia/sgl/SkCanvas.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006-2008 Google Inc.
+ * Copyright (C) 2006-2008 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.
@@ -21,6 +21,7 @@
#include "SkDrawFilter.h"
#include "SkDrawLooper.h"
#include "SkPicture.h"
+#include "SkScalarCompare.h"
#include "SkTemplates.h"
#include "SkUtils.h"
#include <new>
@@ -49,6 +50,14 @@
#endif
///////////////////////////////////////////////////////////////////////////////
+// Helpers for computing fast bounds for quickReject tests
+
+static SkCanvas::EdgeType paint2EdgeType(const SkPaint* paint) {
+ return paint != NULL && paint->isAntiAlias() ?
+ SkCanvas::kAA_EdgeType : SkCanvas::kBW_EdgeType;
+}
+
+///////////////////////////////////////////////////////////////////////////////
/* This is the record we keep for each SkDevice that the user installs.
The clip/matrix/proc are fields that reflect the top of the save/restore
@@ -229,6 +238,7 @@ public:
fBitmap = &fDevice->accessBitmap(true);
fLayerX = rec->fX;
fLayerY = rec->fY;
+ fPaint = rec->fPaint;
SkDEBUGCODE(this->validate();)
fCurrLayer = rec->fNext;
@@ -249,10 +259,11 @@ public:
SkDevice* getDevice() const { return fDevice; }
const SkMatrix& getMatrix() const { return *fMatrix; }
const SkRegion& getClip() const { return *fClip; }
-
+ const SkPaint* getPaint() const { return fPaint; }
private:
SkCanvas* fCanvas;
const DeviceCM* fCurrLayer;
+ const SkPaint* fPaint; // May be null.
int fLayerX;
int fLayerY;
SkBool8 fSkipEmptyClips;
@@ -377,7 +388,8 @@ private:
SkDevice* SkCanvas::init(SkDevice* device) {
fBounder = NULL;
-
+ fLocalBoundsCompareTypeDirty = true;
+
fMCRec = (MCRec*)fMCStack.push_back();
new (fMCRec) MCRec(NULL, 0);
@@ -668,6 +680,7 @@ void SkCanvas::internalRestore() {
SkASSERT(fMCStack.count() != 0);
fDeviceCMDirty = true;
+ fLocalBoundsCompareTypeDirty = true;
// reserve our layer (if any)
DeviceCM* layer = fMCRec->fLayer; // may be null
@@ -750,31 +763,37 @@ void SkCanvas::drawDevice(SkDevice* device, int x, int y,
bool SkCanvas::translate(SkScalar dx, SkScalar dy) {
fDeviceCMDirty = true;
+ fLocalBoundsCompareTypeDirty = true;
return fMCRec->fMatrix->preTranslate(dx, dy);
}
bool SkCanvas::scale(SkScalar sx, SkScalar sy) {
fDeviceCMDirty = true;
+ fLocalBoundsCompareTypeDirty = true;
return fMCRec->fMatrix->preScale(sx, sy);
}
bool SkCanvas::rotate(SkScalar degrees) {
fDeviceCMDirty = true;
+ fLocalBoundsCompareTypeDirty = true;
return fMCRec->fMatrix->preRotate(degrees);
}
bool SkCanvas::skew(SkScalar sx, SkScalar sy) {
fDeviceCMDirty = true;
+ fLocalBoundsCompareTypeDirty = true;
return fMCRec->fMatrix->preSkew(sx, sy);
}
bool SkCanvas::concat(const SkMatrix& matrix) {
fDeviceCMDirty = true;
+ fLocalBoundsCompareTypeDirty = true;
return fMCRec->fMatrix->preConcat(matrix);
}
void SkCanvas::setMatrix(const SkMatrix& matrix) {
fDeviceCMDirty = true;
+ fLocalBoundsCompareTypeDirty = true;
*fMCRec->fMatrix = matrix;
}
@@ -791,6 +810,8 @@ void SkCanvas::resetMatrix() {
bool SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op) {
fDeviceCMDirty = true;
+ fLocalBoundsCompareTypeDirty = true;
+
if (fMCRec->fMatrix->rectStaysRect()) {
SkRect r;
SkIRect ir;
@@ -808,6 +829,7 @@ bool SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op) {
bool SkCanvas::clipPath(const SkPath& path, SkRegion::Op op) {
fDeviceCMDirty = true;
+ fLocalBoundsCompareTypeDirty = true;
SkPath devPath;
path.transform(*fMCRec->fMatrix, &devPath);
@@ -831,24 +853,52 @@ bool SkCanvas::clipPath(const SkPath& path, SkRegion::Op op) {
bool SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) {
fDeviceCMDirty = true;
+ fLocalBoundsCompareTypeDirty = true;
+
return fMCRec->fRegion->op(rgn, op);
}
-bool SkCanvas::quickReject(const SkRect& rect, EdgeType et) const {
- if (fMCRec->fRegion->isEmpty() || rect.isEmpty()) {
- return true;
+void SkCanvas::computeLocalClipBoundsCompareType() const {
+ SkRect r;
+
+ if (!this->getClipBounds(&r, kAA_EdgeType)) {
+ fLocalBoundsCompareType.setEmpty();
+ } else {
+ fLocalBoundsCompareType.set(SkScalarToCompareType(r.fLeft),
+ SkScalarToCompareType(r.fTop),
+ SkScalarToCompareType(r.fRight),
+ SkScalarToCompareType(r.fBottom));
}
+}
- SkRect r;
- SkIRect ir;
+bool SkCanvas::quickReject(const SkRect& rect, EdgeType) const {
+ /* current impl ignores edgetype, and relies on
+ getLocalClipBoundsCompareType(), which always returns a value assuming
+ antialiasing (worst case)
+ */
- fMCRec->fMatrix->mapRect(&r, rect);
- if (kAA_EdgeType == et) {
- r.roundOut(&ir);
- } else {
- r.round(&ir);
+ if (fMCRec->fRegion->isEmpty()) {
+ return true;
}
- return fMCRec->fRegion->quickReject(ir);
+
+ // check for empty user rect (horizontal)
+ SkScalarCompareType userL = SkScalarToCompareType(rect.fLeft);
+ SkScalarCompareType userR = SkScalarToCompareType(rect.fRight);
+ if (userL >= userR) {
+ return true;
+ }
+
+ // check for empty user rect (vertical)
+ SkScalarCompareType userT = SkScalarToCompareType(rect.fTop);
+ SkScalarCompareType userB = SkScalarToCompareType(rect.fBottom);
+ if (userT >= userB) {
+ return true;
+ }
+
+ // check if we are completely outside of the local clip bounds
+ const SkRectCompareType& clipR = this->getLocalClipBoundsCompareType();
+ return userL >= clipR.fRight || userT >= clipR.fBottom ||
+ userR <= clipR.fLeft || userB <= clipR.fTop;
}
bool SkCanvas::quickReject(const SkPath& path, EdgeType et) const {
@@ -858,7 +908,7 @@ bool SkCanvas::quickReject(const SkPath& path, EdgeType et) const {
if (fMCRec->fMatrix->rectStaysRect()) {
SkRect r;
- path.computeBounds(&r, SkPath::kExact_BoundsType);
+ path.computeBounds(&r, SkPath::kFast_BoundsType);
return this->quickReject(r, et);
}
@@ -867,55 +917,38 @@ bool SkCanvas::quickReject(const SkPath& path, EdgeType et) const {
SkIRect ir;
path.transform(*fMCRec->fMatrix, &dstPath);
- dstPath.computeBounds(&r, SkPath::kExact_BoundsType);
+ dstPath.computeBounds(&r, SkPath::kFast_BoundsType);
+ r.round(&ir);
if (kAA_EdgeType == et) {
- r.roundOut(&ir);
- } else {
- r.round(&ir);
+ ir.inset(-1, -1);
}
return fMCRec->fRegion->quickReject(ir);
}
bool SkCanvas::quickRejectY(SkScalar top, SkScalar bottom, EdgeType et) const {
- if (fMCRec->fRegion->isEmpty() || top >= bottom) {
+ /* current impl ignores edgetype, and relies on
+ getLocalClipBoundsCompareType(), which always returns a value assuming
+ antialiasing (worst case)
+ */
+
+ if (fMCRec->fRegion->isEmpty()) {
return true;
}
- const SkMatrix& matrix = *fMCRec->fMatrix;
-
- // if we're rotated/skewed/perspective, give up (for now)
- // TODO: cache this attribute of the matrix? or specialized query method?
- // TODO: if rotate=90 or 270 is common, we can handle those too...
- if (matrix.getType() & ~(SkMatrix::kTranslate_Mask |
- SkMatrix::kScale_Mask)) {
- return false;
- }
- // transform top/botttom into device coordinates
- const SkScalar sy = matrix[SkMatrix::kMScaleY];
- const SkScalar ty = matrix[SkMatrix::kMTransY];
- top = SkScalarMulAdd(top, sy, ty);
- bottom = SkScalarMulAdd(bottom, sy, ty);
-
- // if the scale flipped us, flip back
- if (top > bottom) {
- SkTSwap<SkScalar>(top, bottom);
- }
- // now round based on the edge type
- int ymin, ymax;
- if (kAA_EdgeType == et) {
- ymin = SkScalarFloor(top);
- ymax = SkScalarCeil(bottom);
- } else {
- ymin = SkScalarRound(top);
- ymax = SkScalarRound(bottom);
+ SkScalarCompareType userT = SkScalarAs2sCompliment(top);
+ SkScalarCompareType userB = SkScalarAs2sCompliment(bottom);
+
+ // check for invalid user Y coordinates (i.e. empty)
+ if (userT >= userB) {
+ return true;
}
- // now compare against the bounds of the clip
- const SkIRect& bounds = fMCRec->fRegion->getBounds();
- return ymin >= bounds.fBottom || ymax <= bounds.fTop;
+ // check if we are above or below the local clip bounds
+ const SkRectCompareType& clipR = this->getLocalClipBoundsCompareType();
+ return userT >= clipR.fBottom || userB <= clipR.fTop;
}
-bool SkCanvas::getClipBounds(SkRect* bounds) const {
+bool SkCanvas::getClipBounds(SkRect* bounds, EdgeType et) const {
const SkRegion& clip = *fMCRec->fRegion;
if (clip.isEmpty()) {
if (bounds) {
@@ -928,9 +961,16 @@ bool SkCanvas::getClipBounds(SkRect* bounds) const {
SkMatrix inverse;
SkRect r;
- // TODO: should we cache the inverse (with a dirty bit)?
fMCRec->fMatrix->invert(&inverse);
- r.set(clip.getBounds());
+
+ // get the clip's bounds
+ const SkIRect& ibounds = clip.getBounds();
+ // adjust it outwards if we are antialiasing
+ int inset = (kAA_EdgeType == et);
+ r.iset(ibounds.fLeft - inset, ibounds.fTop - inset,
+ ibounds.fRight + inset, ibounds.fBottom + inset);
+
+ // invert into local coordinates
inverse.mapRect(bounds, r);
}
return true;
@@ -994,6 +1034,14 @@ void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[],
}
void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) {
+ if (paint.canComputeFastBounds()) {
+ SkRect storage;
+ if (this->quickReject(paint.computeFastBounds(r, &storage),
+ paint2EdgeType(&paint))) {
+ return;
+ }
+ }
+
ITER_BEGIN(paint, SkDrawFilter::kRect_Type)
while (iter.next()) {
@@ -1004,6 +1052,15 @@ void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) {
}
void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
+ if (paint.canComputeFastBounds()) {
+ SkRect r;
+ path.computeBounds(&r, SkPath::kFast_BoundsType);
+ if (this->quickReject(paint.computeFastBounds(r, &r),
+ paint2EdgeType(&paint))) {
+ return;
+ }
+ }
+
ITER_BEGIN(paint, SkDrawFilter::kPath_Type)
while (iter.next()) {
@@ -1016,7 +1073,17 @@ void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
void SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y,
const SkPaint* paint) {
SkDEBUGCODE(bitmap.validate();)
-
+
+ if (NULL == paint || (paint->getMaskFilter() == NULL)) {
+ SkRect fastBounds;
+ fastBounds.set(x, y,
+ x + SkIntToScalar(bitmap.width()),
+ y + SkIntToScalar(bitmap.height()));
+ if (this->quickReject(fastBounds, paint2EdgeType(paint))) {
+ return;
+ }
+ }
+
SkMatrix matrix;
matrix.setTranslate(x, y);
this->internalDrawBitmap(bitmap, matrix, paint);
@@ -1029,8 +1096,7 @@ void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src,
}
// do this now, to avoid the cost of calling extract for RLE bitmaps
- if (this->quickReject(dst, paint != NULL && paint->isAntiAlias() ?
- kAA_EdgeType : kBW_EdgeType)) {
+ if (this->quickReject(dst, paint2EdgeType(paint))) {
return;
}
@@ -1229,10 +1295,18 @@ void SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius,
radius = 0;
}
- SkPath path;
SkRect r;
-
r.set(cx - radius, cy - radius, cx + radius, cy + radius);
+
+ if (paint.canComputeFastBounds()) {
+ SkRect storage;
+ if (this->quickReject(paint.computeFastBounds(r, &storage),
+ paint2EdgeType(&paint))) {
+ return;
+ }
+ }
+
+ SkPath path;
path.addOval(r);
this->drawPath(path, paint);
}
@@ -1240,6 +1314,14 @@ void SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius,
void SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry,
const SkPaint& paint) {
if (rx > 0 && ry > 0) {
+ if (paint.canComputeFastBounds()) {
+ SkRect storage;
+ if (this->quickReject(paint.computeFastBounds(r, &storage),
+ paint2EdgeType(&paint))) {
+ return;
+ }
+ }
+
SkPath path;
path.addRoundRect(r, rx, ry, SkPath::kCW_Direction);
this->drawPath(path, paint);
@@ -1249,6 +1331,14 @@ void SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry,
}
void SkCanvas::drawOval(const SkRect& oval, const SkPaint& paint) {
+ if (paint.canComputeFastBounds()) {
+ SkRect storage;
+ if (this->quickReject(paint.computeFastBounds(oval, &storage),
+ paint2EdgeType(&paint))) {
+ return;
+ }
+ }
+
SkPath path;
path.addOval(oval);
this->drawPath(path, paint);
@@ -1316,8 +1406,15 @@ const SkMatrix& SkCanvas::LayerIter::matrix() const {
return fImpl->getMatrix();
}
+const SkPaint& SkCanvas::LayerIter::paint() const {
+ const SkPaint* paint = fImpl->getPaint();
+ if (NULL == paint) {
+ paint = &fDefaultPaint;
+ }
+ return *paint;
+}
+
const SkRegion& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); }
int SkCanvas::LayerIter::x() const { return fImpl->getX(); }
int SkCanvas::LayerIter::y() const { return fImpl->getY(); }
-
diff --git a/skia/sgl/SkColor.cpp b/skia/sgl/SkColor.cpp
index 1e7aa70..4256179 100644
--- a/skia/sgl/SkColor.cpp
+++ b/skia/sgl/SkColor.cpp
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkColor.cpp
**
-** Copyright 2006, Google Inc.
+** 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.
@@ -66,7 +66,9 @@ void SkRGBToHSV(U8CPU r, U8CPU g, U8CPU b, SkScalar hsv[3]) {
SkASSERT(v >= 0 && v <= SK_Scalar1);
if (0 == delta) { // we're a shade of gray
- hsv[0] = hsv[1] = hsv[2] = v;
+ hsv[0] = 0;
+ hsv[1] = 0;
+ hsv[2] = v;
return;
}
diff --git a/skia/sgl/SkColorFilter.cpp b/skia/sgl/SkColorFilter.cpp
index d9034c6..bb4be48 100644
--- a/skia/sgl/SkColorFilter.cpp
+++ b/skia/sgl/SkColorFilter.cpp
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkColorFilter.cpp
**
-** Copyright 2006, Google Inc.
+** 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.
diff --git a/skia/sgl/SkColorTable.cpp b/skia/sgl/SkColorTable.cpp
index b8edf18..f991da3 100644
--- a/skia/sgl/SkColorTable.cpp
+++ b/skia/sgl/SkColorTable.cpp
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkColorTable.cpp
**
-** Copyright 2006, Google Inc.
+** 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.
diff --git a/skia/sgl/SkCoreBlitters.h b/skia/sgl/SkCoreBlitters.h
index e1692f0..5b3497e 100644
--- a/skia/sgl/SkCoreBlitters.h
+++ b/skia/sgl/SkCoreBlitters.h
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkCoreBlitters.h
**
-** Copyright 2006, Google Inc.
+** 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.
@@ -162,6 +162,7 @@ public:
virtual const SkBitmap* justAnOpaqueColor(uint32_t*);
private:
+ SkPMColor fSrcColor32;
unsigned fScale;
uint16_t fColor16; // already scaled by fScale
uint16_t fRawColor16; // unscaled
diff --git a/skia/sgl/SkDeque.cpp b/skia/sgl/SkDeque.cpp
index e424817..4f15051 100644
--- a/skia/sgl/SkDeque.cpp
+++ b/skia/sgl/SkDeque.cpp
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkDeque.cpp
**
-** Copyright 2006, Google Inc.
+** 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.
diff --git a/skia/sgl/SkDraw.cpp b/skia/sgl/SkDraw.cpp
index 106543a..2f0ddff 100644
--- a/skia/sgl/SkDraw.cpp
+++ b/skia/sgl/SkDraw.cpp
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkDraw.cpp
**
-** Copyright 2006, Google Inc.
+** 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.
@@ -37,6 +37,27 @@
//#define TRACE_BITMAP_DRAWS
+class SkAutoRestoreBounder : SkNoncopyable {
+public:
+ // note: initializing fBounder is done only to fix a warning
+ SkAutoRestoreBounder() : fDraw(NULL), fBounder(NULL) {}
+ ~SkAutoRestoreBounder() {
+ if (fDraw) {
+ fDraw->fBounder = fBounder;
+ }
+ }
+
+ void clearBounder(const SkDraw* draw) {
+ fDraw = const_cast<SkDraw*>(draw);
+ fBounder = draw->fBounder;
+ fDraw->fBounder = NULL;
+ }
+
+private:
+ SkDraw* fDraw;
+ SkBounder* fBounder;
+};
+
static SkPoint* rect_points(SkRect& r, int index) {
SkASSERT((unsigned)index < 2);
return &((SkPoint*)(void*)&r)[index];
@@ -182,7 +203,7 @@ static BitmapXferProc ChooseBitmapXferProc(const SkBitmap& bitmap,
return D_Dst_BitmapXferProc; // ignore data
case SkPorterDuff::kSrc_Mode: {
/*
- should I worry about dithering for the lower depths? <reed>
+ should I worry about dithering for the lower depths?
*/
SkPMColor pmc = SkPreMultiplyColor(color);
switch (bitmap.config()) {
@@ -496,6 +517,21 @@ PtProcRec::Proc PtProcRec::chooseProc(SkBlitter* blitter) {
return proc;
}
+static bool bounder_points(SkBounder* bounder, SkCanvas::PointMode mode,
+ size_t count, const SkPoint pts[],
+ const SkPaint& paint, const SkMatrix& matrix) {
+ SkIRect ibounds;
+ SkRect bounds;
+ SkScalar inset = paint.getStrokeWidth();
+
+ bounds.set(pts, count);
+ bounds.inset(-inset, -inset);
+ matrix.mapRect(&bounds);
+
+ bounds.roundOut(&ibounds);
+ return bounder->doIRect(ibounds);
+}
+
// each of these costs 8-bytes of stack space, so don't make it too large
// must be even for lines/polygon to work
#define MAX_DEV_PTS 32
@@ -510,6 +546,18 @@ void SkDraw::drawPoints(SkCanvas::PointMode mode, size_t count,
if ((long)count <= 0) {
return;
}
+
+ SkAutoRestoreBounder arb;
+
+ if (fBounder) {
+ if (!bounder_points(fBounder, mode, count, pts, paint, *fMatrix)) {
+ return;
+ }
+ // clear the bounder for the rest of this function, so we don't call it
+ // again later if we happen to call ourselves for drawRect, drawPath,
+ // etc.
+ arb.clearBounder(this);
+ }
SkASSERT(pts != NULL);
SkDEBUGCODE(this->validate();)
@@ -749,7 +797,7 @@ void SkDraw::drawPath(const SkPath& origSrcPath, const SkPaint& paint,
SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;)
/*
- If the device thickness <= 1.0, then make it a hairline, and
+ If the device thickness < 1.0, then make it a hairline, and
modulate alpha if the thickness is even smaller (e.g. thickness == 0.5
should modulate the alpha by 1/2)
*/
@@ -762,7 +810,7 @@ void SkDraw::drawPath(const SkPath& origSrcPath, const SkPaint& paint,
SkScalar width = paint.getStrokeWidth();
if (width > 0) {
width = matrix->mapRadius(paint.getStrokeWidth());
- if (width <= SK_Scalar1) {
+ if (width < SK_Scalar1) {
int scale = (int)SkScalarMul(width, 256);
int alpha = paint.getAlpha() * scale >> 8;
@@ -931,15 +979,15 @@ void SkDraw::drawBitmap(const SkBitmap& bitmap, const SkMatrix& prematrix,
return;
}
- // do I need to call the bounder first??? <reed>
+ // do I need to call the bounder first???
if (clipped_out(matrix, *fClip, bitmap.width(), bitmap.height())) {
return;
}
// only lock the pixels if we passed the clip test
SkAutoLockPixels alp(bitmap);
- // after the lock, check if we have valid pixels
- if (bitmap.getPixels() == NULL) {
+ // after the lock, check if we are valid
+ if (!bitmap.readyToDraw()) {
return;
}
@@ -988,7 +1036,7 @@ void SkDraw::drawBitmap(const SkBitmap& bitmap, const SkMatrix& prematrix,
SkRect r;
r.set(0, 0, SkIntToScalar(bitmap.width()),
SkIntToScalar(bitmap.height()));
- // is this ok if paint has a rasterizer? <reed>
+ // is this ok if paint has a rasterizer?
draw.drawRect(r, paint);
}
}
@@ -1053,7 +1101,7 @@ void SkDraw::drawSprite(const SkBitmap& bitmap, int x, int y,
matrix.reset();
draw.fMatrix = &matrix;
// call ourself with a rect
- // is this OK if paint has a rasterizer? <reed>
+ // is this OK if paint has a rasterizer?
draw.drawRect(r, paint);
}
@@ -2298,4 +2346,3 @@ bool SkDraw::DrawToMask(const SkPath& devPath, const SkIRect* clipBounds,
return true;
}
-
diff --git a/skia/sgl/SkEdge.cpp b/skia/sgl/SkEdge.cpp
index 3a9474c..b079bef 100644
--- a/skia/sgl/SkEdge.cpp
+++ b/skia/sgl/SkEdge.cpp
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkEdge.cpp
**
-** Copyright 2006, Google Inc.
+** 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.
@@ -77,7 +77,12 @@ int SkEdge::setLine(const SkPoint& p0, const SkPoint& p1, const SkIRect* clip,
fX = SkFDot6ToFixed(x0 + SkFixedMul(slope, (32 - y0) & 63)); // + SK_Fixed1/2
fDX = slope;
- fFirstY = (int16_t)(top); // inlined skToS16()
+#if 0
+ // CHANGED FOR CHROME
+ fFirstY = top;
+ fLastY = bot - 1;
+#else
+ fFirstY = top;
if (top != (long)fFirstY) {
if (fFirstY < top) {
fFirstY = std::numeric_limits<int16_t>::max();
@@ -86,7 +91,7 @@ int SkEdge::setLine(const SkPoint& p0, const SkPoint& p1, const SkIRect* clip,
}
fX -= fDX * (top - (long)fFirstY);
}
- fLastY = (int16_t)(bot - 1); // inlined SkToS16()
+ fLastY = bot - 1;
if (bot-1 != (long)fLastY) {
if (fLastY < bot-1) {
fLastY = std::numeric_limits<int16_t>::max();
@@ -94,6 +99,7 @@ int SkEdge::setLine(const SkPoint& p0, const SkPoint& p1, const SkIRect* clip,
fLastY = std::numeric_limits<int16_t>::min();
}
}
+#endif
fCurveCount = 0;
fWinding = SkToS8(winding);
fCurveShift = 0;
@@ -109,7 +115,7 @@ int SkEdge::updateLine(SkFixed x0, SkFixed y0, SkFixed x1, SkFixed y1)
{
SkASSERT(fWinding == 1 || fWinding == -1);
SkASSERT(fCurveCount != 0);
- SkASSERT(fCurveShift != 0);
+// SkASSERT(fCurveShift != 0);
y0 >>= 10;
y1 >>= 10;
@@ -132,8 +138,8 @@ int SkEdge::updateLine(SkFixed x0, SkFixed y0, SkFixed x1, SkFixed y1)
fX = SkFDot6ToFixed(x0 + SkFixedMul(slope, (32 - y0) & 63)); // + SK_Fixed1/2
fDX = slope;
- fFirstY = SkToS16(top);
- fLastY = SkToS16(bot - 1);
+ fFirstY = top;
+ fLastY = bot - 1;
return 1;
}
@@ -153,7 +159,14 @@ void SkEdge::chopLineWithClip(const SkIRect& clip)
}
}
-/////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+/* We store 1<<shift in a (signed) byte, so its maximum value is 1<<6 == 64.
+ Note that this limits the number of lines we use to approximate a curve.
+ If we need to increase this, we need to store fCurveCount in something
+ larger than int8_t.
+*/
+#define MAX_COEFF_SHIFT 6
static inline SkFDot6 cheap_distance(SkFDot6 dx, SkFDot6 dy)
{
@@ -176,7 +189,7 @@ static inline int diff_to_shift(SkFDot6 dx, SkFDot6 dy)
// down by 5 should give us 1/2 pixel accuracy (assuming our dist is accurate...)
// this is chosen by heuristic: make it as big as possible (to minimize segments)
// ... but small enough so that our curves still look smooth
- dist >>= 5;
+ dist = (dist + (1 << 4)) >> 5;
// each subdivision (shift value) cuts this dist (error) by 1/4
return (32 - SkCLZ(dist)) >> 1;
@@ -230,14 +243,19 @@ int SkQuadraticEdge::setQuadratic(const SkPoint pts[3], const SkIRect* clip, int
SkFDot6 dx = ((x1 << 1) - x0 - x2) >> 2;
SkFDot6 dy = ((y1 << 1) - y0 - y2) >> 2;
shift = diff_to_shift(dx, dy);
+ SkASSERT(shift >= 0);
}
// need at least 1 subdivision for our bias trick
- if (shift == 0)
+ if (shift == 0) {
shift = 1;
-
+ } else if (shift > MAX_COEFF_SHIFT) {
+ shift = MAX_COEFF_SHIFT;
+ }
+
fWinding = SkToS8(winding);
fCurveShift = SkToU8(shift);
- fCurveCount = SkToS16(1 << shift);
+ //fCubicDShift only set for cubics
+ fCurveCount = SkToS8(1 << shift);
SkFixed A = SkFDot6ToFixed(x0 - x1 - x1 + x2);
SkFixed B = SkFDot6ToFixed(x1 - x0 + x1 - x0);
@@ -309,6 +327,11 @@ int SkQuadraticEdge::updateQuadratic()
/////////////////////////////////////////////////////////////////////////
+static inline int SkFDot6UpShift(SkFDot6 x, int upShift) {
+ SkASSERT((x << upShift >> upShift) == x);
+ return x << upShift;
+}
+
/* f(1/3) = (8a + 12b + 6c + d) / 27
f(2/3) = (a + 6b + 12c + 8d) / 27
@@ -386,23 +409,38 @@ int SkCubicEdge::setCubic(const SkPoint pts[4], const SkIRect* clip, int shift)
}
// need at least 1 subdivision for our bias trick
SkASSERT(shift > 0);
+ if (shift > MAX_COEFF_SHIFT) {
+ shift = MAX_COEFF_SHIFT;
+ }
+
+ /* Since our in coming data is initially shifted down by 10 (or 8 in
+ antialias). That means the most we can shift up is 8. However, we
+ compute coefficients with a 3*, so the safest upshift is really 6
+ */
+ int upShift = 6; // largest safe value
+ int downShift = shift + upShift - 10;
+ if (downShift < 0) {
+ downShift = 0;
+ upShift = 10 - shift;
+ }
fWinding = SkToS8(winding);
+ fCurveCount = SkToS8(-1 << shift);
fCurveShift = SkToU8(shift);
- fCurveCount = SkToS16(-1 << shift);
+ fCubicDShift = SkToU8(downShift);
- SkFixed B = SkFDot6ToFixed(3 * (x1 - x0));
- SkFixed C = SkFDot6ToFixed(3 * (x0 - x1 - x1 + x2));
- SkFixed D = SkFDot6ToFixed(x3 + 3 * (x1 - x2) - x0);
+ SkFixed B = SkFDot6UpShift(3 * (x1 - x0), upShift);
+ SkFixed C = SkFDot6UpShift(3 * (x0 - x1 - x1 + x2), upShift);
+ SkFixed D = SkFDot6UpShift(x3 + 3 * (x1 - x2) - x0, upShift);
fCx = SkFDot6ToFixed(x0);
fCDx = B + (C >> shift) + (D >> 2*shift); // biased by shift
fCDDx = 2*C + (3*D >> (shift - 1)); // biased by 2*shift
fCDDDx = 3*D >> (shift - 1); // biased by 2*shift
- B = SkFDot6ToFixed(3 * (y1 - y0));
- C = SkFDot6ToFixed(3 * (y0 - y1 - y1 + y2));
- D = SkFDot6ToFixed(y3 + 3 * (y1 - y2) - y0);
+ B = SkFDot6UpShift(3 * (y1 - y0), upShift);
+ C = SkFDot6UpShift(3 * (y0 - y1 - y1 + y2), upShift);
+ D = SkFDot6UpShift(y3 + 3 * (y1 - y2) - y0, upShift);
fCy = SkFDot6ToFixed(y0);
fCDy = B + (C >> shift) + (D >> 2*shift); // biased by shift
@@ -431,19 +469,20 @@ int SkCubicEdge::updateCubic()
SkFixed oldx = fCx;
SkFixed oldy = fCy;
SkFixed newx, newy;
- int shift = fCurveShift;
+ const int ddshift = fCurveShift;
+ const int dshift = fCubicDShift;
SkASSERT(count < 0);
do {
if (++count < 0)
{
- newx = oldx + (fCDx >> shift);
- fCDx += fCDDx >> shift;
+ newx = oldx + (fCDx >> dshift);
+ fCDx += fCDDx >> ddshift;
fCDDx += fCDDDx;
- newy = oldy + (fCDy >> shift);
- fCDy += fCDDy >> shift;
+ newy = oldy + (fCDy >> dshift);
+ fCDy += fCDDy >> ddshift;
fCDDy += fCDDDy;
}
else // last segment
diff --git a/skia/sgl/SkEdge.h b/skia/sgl/SkEdge.h
index 086e5a6..5b0cc75 100644
--- a/skia/sgl/SkEdge.h
+++ b/skia/sgl/SkEdge.h
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkEdge.h
**
-** Copyright 2006, Google Inc.
+** 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.
@@ -32,10 +32,11 @@ struct SkEdge {
SkFixed fX;
SkFixed fDX;
- int16_t fFirstY;
- int16_t fLastY;
- int16_t fCurveCount; // only used by kQuad(+) and kCubic(-)
- uint8_t fCurveShift;
+ int32_t fFirstY;
+ int32_t fLastY;
+ int8_t fCurveCount; // only used by kQuad(+) and kCubic(-)
+ uint8_t fCurveShift; // appled to all Dx/DDx/DDDx except for fCubicDShift exception
+ uint8_t fCubicDShift; // applied to fCDx and fCDy only in cubic
int8_t fWinding; // 1 or -1
int setLine(const SkPoint& p0, const SkPoint& p1, const SkIRect* clip,
diff --git a/skia/sgl/SkFP.h b/skia/sgl/SkFP.h
index b95cba2..6c0c526 100644
--- a/skia/sgl/SkFP.h
+++ b/skia/sgl/SkFP.h
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkFP.h
**
-** Copyright 2006, Google Inc.
+** 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.
diff --git a/skia/sgl/SkFilterProc.cpp b/skia/sgl/SkFilterProc.cpp
index 8082a34..814bafe 100644
--- a/skia/sgl/SkFilterProc.cpp
+++ b/skia/sgl/SkFilterProc.cpp
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkFilterProc.cpp
**
-** Copyright 2006, Google Inc.
+** 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.
diff --git a/skia/sgl/SkFilterProc.h b/skia/sgl/SkFilterProc.h
index 5aa59ab..9af4ed5 100644
--- a/skia/sgl/SkFilterProc.h
+++ b/skia/sgl/SkFilterProc.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006-2008 Google Inc.
+ * Copyright (C) 2006-2008 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.
@@ -70,7 +70,7 @@ typedef unsigned (*SkFilter32Proc)(uint32_t x00, uint32_t x01,
const SkFilter32Proc* SkGetFilter32ProcTable();
-inline SkFilter32Proc SkGetFilter32Proc22(const SkFilterProc* table,
+inline SkFilter32Proc SkGetFilter32Proc22(const SkFilter32Proc* table,
unsigned x, unsigned y)
{
SkASSERT(table);
@@ -81,7 +81,7 @@ inline SkFilter32Proc SkGetFilter32Proc22(const SkFilterProc* table,
return table[(y << 2) | x];
}
-inline const SkFilter32Proc* SkGetFilter32Proc22Row(const SkFilterProc* table,
+inline const SkFilter32Proc* SkGetFilter32Proc22Row(const SkFilter32Proc* table,
unsigned y)
{
SkASSERT(table);
@@ -89,7 +89,7 @@ inline const SkFilter32Proc* SkGetFilter32Proc22Row(const SkFilterProc* table,
return &table[y << 30 >> 28];
}
-inline SkFilter32Proc SkGetFilter32Proc22RowProc(const SkFilterProc* row,
+inline SkFilter32Proc SkGetFilter32Proc22RowProc(const SkFilter32Proc* row,
unsigned x)
{
SkASSERT(row);
diff --git a/skia/sgl/SkGeometry.cpp b/skia/sgl/SkGeometry.cpp
index 3c72f4b..4f22e92 100644
--- a/skia/sgl/SkGeometry.cpp
+++ b/skia/sgl/SkGeometry.cpp
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkGeometry.cpp
**
-** Copyright 2006, Google Inc.
+** 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.
@@ -260,6 +260,14 @@ static void flatten_double_quad_extrema(SkScalar coords[14])
coords[2] = coords[6] = coords[4];
}
+static void force_quad_monotonic_in_y(SkPoint pts[3])
+{
+ // zap pts[1].fY to the nearest value
+ SkScalar ab = SkScalarAbs(pts[0].fY - pts[1].fY);
+ SkScalar bc = SkScalarAbs(pts[1].fY - pts[2].fY);
+ pts[1].fY = ab < bc ? pts[0].fY : pts[2].fY;
+}
+
/* Returns 0 for 1 quad, and 1 for two quads, either way the answer is
stored in dst[]. Guarantees that the 1/2 quads will be monotonic.
*/
diff --git a/skia/sgl/SkGeometry.h b/skia/sgl/SkGeometry.h
index d4547a5..571159f 100644
--- a/skia/sgl/SkGeometry.h
+++ b/skia/sgl/SkGeometry.h
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkGeometry.h
**
-** Copyright 2006, Google Inc.
+** 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.
diff --git a/skia/sgl/SkGlobals.cpp b/skia/sgl/SkGlobals.cpp
index fb1c948..bc72b97 100644
--- a/skia/sgl/SkGlobals.cpp
+++ b/skia/sgl/SkGlobals.cpp
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkGlobals.cpp
**
-** Copyright 2006, Google Inc.
+** 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.
diff --git a/skia/sgl/SkGlyphCache.cpp b/skia/sgl/SkGlyphCache.cpp
index f67223d..6b214df 100644
--- a/skia/sgl/SkGlyphCache.cpp
+++ b/skia/sgl/SkGlyphCache.cpp
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkGlyphCache.cpp
**
-** Copyright 2006, Google Inc.
+** 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.
@@ -21,7 +21,33 @@
#include "SkTemplates.h"
#define SPEW_PURGE_STATUS
-#define USE_CACHE_HASHxxxxx
+//#define USE_CACHE_HASH
+//#define RECORD_HASH_EFFICIENCY
+
+///////////////////////////////////////////////////////////////////////////////
+
+#ifdef RECORD_HASH_EFFICIENCY
+ static uint32_t gHashSuccess;
+ static uint32_t gHashCollision;
+
+ static void RecordHashSuccess() {
+ gHashSuccess += 1;
+ }
+
+ static void RecordHashCollisionIf(bool pred) {
+ if (pred) {
+ gHashCollision += 1;
+
+ uint32_t total = gHashSuccess + gHashCollision;
+ SkDebugf("Font Cache Hash success rate: %d%%\n",
+ 100 * gHashSuccess / total);
+ }
+ }
+#else
+ #define RecordHashSuccess() (void)0
+ #define RecordHashCollisionIf(pred) (void)0
+#endif
+#define RecordHashCollision() RecordHashCollisionIf(true)
///////////////////////////////////////////////////////////////////////////////
@@ -70,26 +96,40 @@ SkGlyphCache::~SkGlyphCache() {
///////////////////////////////////////////////////////////////////////////////
#ifdef SK_DEBUG
- class AutoCheckForNull {
- public:
- AutoCheckForNull(const SkTDArray<SkGlyph*>& array) : fArray(array) {
- for (int i = 0; i < array.count(); i++)
- SkASSERT(array[i]);
- }
- ~AutoCheckForNull() {
- const SkTDArray<SkGlyph*>& array = fArray;
- for (int i = 0; i < array.count(); i++) {
- SkASSERT(array[i]);
- }
+class AutoCheckForNull {
+public:
+ AutoCheckForNull(const SkTDArray<SkGlyph*>& array) : fArray(array) {
+ for (int i = 0; i < array.count(); i++)
+ SkASSERT(array[i]);
+ }
+ ~AutoCheckForNull() {
+ const SkTDArray<SkGlyph*>& array = fArray;
+ for (int i = 0; i < array.count(); i++) {
+ SkASSERT(array[i]);
}
- private:
- const SkTDArray<SkGlyph*>& fArray;
- };
- #define VALIDATE() AutoCheckForNull acfn(fGlyphArray)
+ }
+private:
+ const SkTDArray<SkGlyph*>& fArray;
+};
+#define VALIDATE() AutoCheckForNull acfn(fGlyphArray)
#else
- #define VALIDATE()
+#define VALIDATE()
#endif
+uint16_t SkGlyphCache::unicharToGlyph(SkUnichar charCode) {
+ VALIDATE();
+ uint32_t id = SkGlyph::MakeID(charCode);
+ const CharGlyphRec& rec = fCharToGlyphHash[ID2HashIndex(id)];
+
+ if (rec.fID == id) {
+ return rec.fGlyph->getGlyphID();
+ } else {
+ return fScalerContext->charToGlyphID(charCode);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
const SkGlyph& SkGlyphCache::getUnicharAdvance(SkUnichar charCode) {
VALIDATE();
uint32_t id = SkGlyph::MakeID(charCode);
@@ -126,12 +166,14 @@ const SkGlyph& SkGlyphCache::getUnicharMetrics(SkUnichar charCode) {
CharGlyphRec* rec = &fCharToGlyphHash[ID2HashIndex(id)];
if (rec->fID != id) {
+ RecordHashCollisionIf(rec->fGlyph != NULL);
// this ID is based on the UniChar
rec->fID = id;
// this ID is based on the glyph index
id = SkGlyph::MakeID(fScalerContext->charToGlyphID(charCode));
rec->fGlyph = this->lookupMetrics(id, kFull_MetricsType);
} else {
+ RecordHashSuccess();
if (rec->fGlyph->isJustAdvance()) {
fScalerContext->getMetrics(rec->fGlyph);
}
@@ -147,12 +189,14 @@ const SkGlyph& SkGlyphCache::getUnicharMetrics(SkUnichar charCode,
CharGlyphRec* rec = &fCharToGlyphHash[ID2HashIndex(id)];
if (rec->fID != id) {
+ RecordHashCollisionIf(rec->fGlyph != NULL);
// this ID is based on the UniChar
rec->fID = id;
// this ID is based on the glyph index
id = SkGlyph::MakeID(fScalerContext->charToGlyphID(charCode), x, y);
rec->fGlyph = this->lookupMetrics(id, kFull_MetricsType);
} else {
+ RecordHashSuccess();
if (rec->fGlyph->isJustAdvance()) {
fScalerContext->getMetrics(rec->fGlyph);
}
@@ -168,9 +212,11 @@ const SkGlyph& SkGlyphCache::getGlyphIDMetrics(uint16_t glyphID) {
SkGlyph* glyph = fGlyphHash[index];
if (NULL == glyph || glyph->fID != id) {
+ RecordHashCollisionIf(glyph != NULL);
glyph = this->lookupMetrics(glyphID, kFull_MetricsType);
fGlyphHash[index] = glyph;
} else {
+ RecordHashSuccess();
if (glyph->isJustAdvance()) {
fScalerContext->getMetrics(glyph);
}
@@ -185,11 +231,13 @@ const SkGlyph& SkGlyphCache::getGlyphIDMetrics(uint16_t glyphID,
uint32_t id = SkGlyph::MakeID(glyphID, x, y);
unsigned index = ID2HashIndex(id);
SkGlyph* glyph = fGlyphHash[index];
-
+
if (NULL == glyph || glyph->fID != id) {
+ RecordHashCollisionIf(glyph != NULL);
glyph = this->lookupMetrics(id, kFull_MetricsType);
fGlyphHash[index] = glyph;
} else {
+ RecordHashSuccess();
if (glyph->isJustAdvance()) {
fScalerContext->getMetrics(glyph);
}
@@ -406,6 +454,23 @@ public:
#define GET_GC_GLOBALS() gGCGlobals
#endif
+void SkGlyphCache::VisitAllCaches(bool (*proc)(SkGlyphCache*, void*),
+ void* context) {
+ SkGlyphCache_Globals& globals = FIND_GC_GLOBALS();
+ SkAutoMutexAcquire ac(globals.fMutex);
+ SkGlyphCache* cache;
+
+ globals.validate();
+
+ for (cache = globals.fHead; cache != NULL; cache = cache->fNext) {
+ if (proc(cache, context)) {
+ break;
+ }
+ }
+
+ globals.validate();
+}
+
/* This guy calls the visitor from within the mutext lock, so the visitor
cannot:
- take too much time
@@ -434,7 +499,6 @@ SkGlyphCache* SkGlyphCache::VisitCache(const SkDescriptor* desc,
}
#endif
- cache = globals.fHead;
for (cache = globals.fHead; cache != NULL; cache = cache->fNext) {
if (cache->fDesc->equals(*desc)) {
cache->detach(&globals.fHead);
diff --git a/skia/sgl/SkGlyphCache.h b/skia/sgl/SkGlyphCache.h
index 6aef173..2462ea5 100644
--- a/skia/sgl/SkGlyphCache.h
+++ b/skia/sgl/SkGlyphCache.h
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkGlyphCache.h
**
-** Copyright 2006, Google Inc.
+** 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.
@@ -66,6 +66,12 @@ public:
const SkGlyph& getUnicharMetrics(SkUnichar, SkFixed x, SkFixed y);
const SkGlyph& getGlyphIDMetrics(uint16_t, SkFixed x, SkFixed y);
+ /** Return the glyphID for the specified Unichar. If the char has already
+ been seen, use the existing cache entry. If not, ask the scalercontext
+ to compute it for us.
+ */
+ uint16_t unicharToGlyph(SkUnichar);
+
/** Return the image associated with the glyph. If it has not been generated
this will trigger that.
*/
@@ -98,6 +104,12 @@ public:
// call the proc)
void removeAuxProc(void (*auxProc)(void*));
+ /** Call proc on all cache entries, stopping early if proc returns true.
+ The proc should not create or delete caches, since it could produce
+ deadlock.
+ */
+ static void VisitAllCaches(bool (*proc)(SkGlyphCache*, void*), void* ctx);
+
/** Find a matching cache entry, and call proc() with it. If none is found
create a new one. If the proc() returns true, detach the cache and
return it, otherwise leave it and return NULL.
@@ -176,7 +188,7 @@ private:
SkPaint::FontMetrics fFontMetricsY;
enum {
- kHashBits = 6,
+ kHashBits = 8,
kHashCount = 1 << kHashBits,
kHashMask = kHashCount - 1
};
diff --git a/skia/sgl/SkGraphics.cpp b/skia/sgl/SkGraphics.cpp
index 1bb3cb3..ed9ab02 100644
--- a/skia/sgl/SkGraphics.cpp
+++ b/skia/sgl/SkGraphics.cpp
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkGraphics.cpp
**
-** Copyright 2006, Google Inc.
+** 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.
@@ -149,10 +149,132 @@ static void test_drawText(SkBitmap::Config config, SkColor color)
#endif
+#include "SkFloatBits.h"
+
+static inline float fast_inc(float x) {
+ SkFloatIntUnion data;
+ data.fFloat = x;
+ data.fSignBitInt += 1;
+ return data.fFloat;
+}
+
+extern float dummy();
+int time_math() {
+ SkMSec now;
+ int i;
+ int sum = 0;
+ const int repeat = 1000000;
+ float f;
+
+ f = dummy();
+ now = SkTime::GetMSecs();
+ for (i = repeat - 1; i >= 0; --i) {
+ sum += (int)f; f = fast_inc(f);
+ sum += (int)f; f = fast_inc(f);
+ sum += (int)f; f = fast_inc(f);
+ sum += (int)f; f = fast_inc(f);
+ }
+ SkDebugf("---- native cast %d\n", SkTime::GetMSecs() - now);
+
+ f = dummy();
+ now = SkTime::GetMSecs();
+ for (i = repeat - 1; i >= 0; --i) {
+ sum += SkFloatToIntCast(f); f = fast_inc(f);
+ sum += SkFloatToIntCast(f); f = fast_inc(f);
+ sum += SkFloatToIntCast(f); f = fast_inc(f);
+ sum += SkFloatToIntCast(f); f = fast_inc(f);
+ }
+ SkDebugf("---- hack cast %d\n", SkTime::GetMSecs() - now);
+
+ f = dummy();
+ now = SkTime::GetMSecs();
+ for (i = repeat - 1; i >= 0; --i) {
+ sum += (int)floorf(f + 0.5f); f = fast_inc(f);
+ sum += (int)floorf(f + 0.5f); f = fast_inc(f);
+ sum += (int)floorf(f + 0.5f); f = fast_inc(f);
+ sum += (int)floorf(f + 0.5f); f = fast_inc(f);
+ }
+ SkDebugf("---- native round %d\n", SkTime::GetMSecs() - now);
+
+ f = dummy();
+ now = SkTime::GetMSecs();
+ for (i = repeat - 1; i >= 0; --i) {
+ sum += SkFloatToIntRound(f); f = fast_inc(f);
+ sum += SkFloatToIntRound(f); f = fast_inc(f);
+ sum += SkFloatToIntRound(f); f = fast_inc(f);
+ sum += SkFloatToIntRound(f); f = fast_inc(f);
+ }
+ SkDebugf("---- hack round %d\n", SkTime::GetMSecs() - now);
+
+ f = dummy();
+ now = SkTime::GetMSecs();
+ for (i = repeat - 1; i >= 0; --i) {
+ sum += SkFloat2Bits(floorf(f)); f = fast_inc(f);
+ sum += SkFloat2Bits(floorf(f)); f = fast_inc(f);
+ sum += SkFloat2Bits(floorf(f)); f = fast_inc(f);
+ sum += SkFloat2Bits(floorf(f)); f = fast_inc(f);
+ }
+ SkDebugf("---- native floor %d\n", SkTime::GetMSecs() - now);
+
+ f = dummy();
+ now = SkTime::GetMSecs();
+ for (i = repeat - 1; i >= 0; --i) {
+ sum += SkFloatToIntFloor(f); f = fast_inc(f);
+ sum += SkFloatToIntFloor(f); f = fast_inc(f);
+ sum += SkFloatToIntFloor(f); f = fast_inc(f);
+ sum += SkFloatToIntFloor(f); f = fast_inc(f);
+ }
+ SkDebugf("---- hack floor %d\n", SkTime::GetMSecs() - now);
+
+ return sum;
+}
+
+static float time_intToFloat() {
+ const int repeat = 1000000;
+ int i, n;
+ SkMSec now;
+ float sum = 0;
+
+ n = (int)dummy();
+ now = SkTime::GetMSecs();
+ for (i = repeat - 1; i >= 0; --i) {
+ sum += (float)n; n += 1;
+ sum += (float)n; n += 1;
+ sum += (float)n; n += 1;
+ sum += (float)n; n += 1;
+ }
+ SkDebugf("---- native i2f %d\n", SkTime::GetMSecs() - now);
+
+ n = (int)dummy();
+ now = SkTime::GetMSecs();
+ for (i = repeat - 1; i >= 0; --i) {
+ sum += SkIntToFloatCast(n); n += 1;
+ sum += SkIntToFloatCast(n); n += 1;
+ sum += SkIntToFloatCast(n); n += 1;
+ sum += SkIntToFloatCast(n); n += 1;
+ }
+ SkDebugf("---- check i2f %d\n", SkTime::GetMSecs() - now);
+
+ n = (int)dummy();
+ now = SkTime::GetMSecs();
+ for (i = repeat - 1; i >= 0; --i) {
+ sum += SkIntToFloatCast_NoOverflowCheck(n); n += 1;
+ sum += SkIntToFloatCast_NoOverflowCheck(n); n += 1;
+ sum += SkIntToFloatCast_NoOverflowCheck(n); n += 1;
+ sum += SkIntToFloatCast_NoOverflowCheck(n); n += 1;
+ }
+ SkDebugf("---- nocheck i2f %d\n", SkTime::GetMSecs() - now);
+
+ return sum;
+}
+
void SkGraphics::Init(bool runUnitTests)
{
SkGlobals::Init();
+// time_math();
+// time_intToFloat();
+
#ifdef BUILD_EMBOSS_TABLE
SkEmbossMask_BuildTable();
#endif
@@ -221,11 +343,12 @@ void SkGraphics::Init(bool runUnitTests)
unittestline(SkMath),
unittestline(SkUtils),
unittestline(SkString),
- unittestline(SkFloat),
unittestline(SkMatrix),
unittestline(SkGeometry),
unittestline(SkPath),
- unittestline(SkPathMeasure)
+ unittestline(SkPathMeasure),
+ unittestline(SkStream),
+ unittestline(SkWStream),
};
for (i = 0; i < (int)SK_ARRAY_COUNT(gUnitTests); i++)
@@ -402,3 +525,4 @@ bool SkGraphics::SetFontCacheUsed(size_t usageInBytes) {
return SkGlyphCache::SetCacheUsed(usageInBytes);
}
+float dummy() { return 1.25f; }
diff --git a/skia/sgl/SkMask.cpp b/skia/sgl/SkMask.cpp
index edc3b0a..b237639 100644
--- a/skia/sgl/SkMask.cpp
+++ b/skia/sgl/SkMask.cpp
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkMask.cpp
**
-** Copyright 2007, Google Inc.
+** Copyright 2007, 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.
diff --git a/skia/sgl/SkMaskFilter.cpp b/skia/sgl/SkMaskFilter.cpp
index 9040cfd..56fff97 100644
--- a/skia/sgl/SkMaskFilter.cpp
+++ b/skia/sgl/SkMaskFilter.cpp
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkMaskFilter.cpp
**
-** Copyright 2006, Google Inc.
+** 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.
diff --git a/skia/sgl/SkPaint.cpp b/skia/sgl/SkPaint.cpp
index ef23f09..bb6b31e 100644
--- a/skia/sgl/SkPaint.cpp
+++ b/skia/sgl/SkPaint.cpp
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkPaint.cpp
**
-** Copyright 2006, Google Inc.
+** 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.
@@ -301,40 +301,26 @@ SkDrawLooper* SkPaint::setLooper(SkDrawLooper* looper)
return looper;
}
-///////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
#include "SkGlyphCache.h"
#include "SkUtils.h"
-class SkAutoRestoreFlags {
-public:
- SkAutoRestoreFlags(SkPaint* paint) : fPaint(paint)
- {
- fFlags = paint->getFlags();
- }
- ~SkAutoRestoreFlags()
- {
- fPaint->setFlags(fFlags);
- }
-private:
- SkPaint* fPaint;
- uint32_t fFlags;
-};
-
-int SkPaint::textToGlyphs(const void* textData, size_t byteLength, uint16_t glyphs[]) const
-{
- if (byteLength == 0)
+int SkPaint::textToGlyphs(const void* textData, size_t byteLength,
+ uint16_t glyphs[]) const {
+ if (byteLength == 0) {
return 0;
+ }
SkASSERT(textData != NULL);
- if (NULL == glyphs)
- {
+ if (NULL == glyphs) {
switch (this->getTextEncoding()) {
case kUTF8_TextEncoding:
return SkUTF8_CountUnichars((const char*)textData, byteLength);
case kUTF16_TextEncoding:
- return SkUTF16_CountUnichars((const uint16_t*)textData, byteLength >> 1);
+ return SkUTF16_CountUnichars((const uint16_t*)textData,
+ byteLength >> 1);
case kGlyphID_TextEncoding:
return byteLength >> 1;
default:
@@ -345,33 +331,60 @@ int SkPaint::textToGlyphs(const void* textData, size_t byteLength, uint16_t glyp
// if we get here, we have a valid glyphs[] array, so time to fill it in
- if (this->getTextEncoding() == kGlyphID_TextEncoding)
- {
+ // handle this encoding before the setup for the glyphcache
+ if (this->getTextEncoding() == kGlyphID_TextEncoding) {
// we want to ignore the low bit of byteLength
memcpy(glyphs, textData, byteLength >> 1 << 1);
return byteLength >> 1;
}
- SkAutoRestoreFlags autoRestore((SkPaint*)this);
- ((SkPaint*)this)->fFlags &= ~kSubpixelText_Flag;
-
- SkAutoGlyphCache autoCache(*this, NULL);
- SkGlyphCache* cache = autoCache.getCache();
- SkMeasureCacheProc proc;
- proc = this->getMeasureCacheProc(kForward_TextBufferDirection, false);
+ SkAutoGlyphCache autoCache(*this, NULL);
+ SkGlyphCache* cache = autoCache.getCache();
- const char* text = (const char*)textData;
- const char* stop = text + byteLength;
- uint16_t* gptr = glyphs;
+ const char* text = (const char*)textData;
+ const char* stop = text + byteLength;
+ uint16_t* gptr = glyphs;
- while (text < stop)
- {
- // no need to provide x, y
- *gptr++ = proc(cache, &text).getGlyphID();
+ switch (this->getTextEncoding()) {
+ case SkPaint::kUTF8_TextEncoding:
+ while (text < stop) {
+ *gptr++ = cache->unicharToGlyph(SkUTF8_NextUnichar(&text));
+ }
+ break;
+ case SkPaint::kUTF16_TextEncoding: {
+ const uint16_t* text16 = (const uint16_t*)text;
+ const uint16_t* stop16 = (const uint16_t*)stop;
+ while (text16 < stop16) {
+ *gptr++ = cache->unicharToGlyph(SkUTF16_NextUnichar(&text16));
+ }
+ break;
+ }
+ default:
+ SkASSERT(!"unknown text encoding");
}
return gptr - glyphs;
}
+///////////////////////////////////////////////////////////////////////////////
+
+static uint32_t sk_glyphID_next(const char** text)
+{
+ const uint16_t* glyph = (const uint16_t*)text;
+ int32_t value = *glyph;
+ glyph += 1;
+ *text = (const char*)glyph;
+ return value;
+}
+
+static uint32_t sk_glyphID_prev(const char** text)
+{
+ const uint16_t* glyph = (const uint16_t*)text;
+ glyph -= 1;
+ int32_t value = *glyph;
+ *text = (const char*)glyph;
+ return value;
+}
+
//////////////////////////////////////////////////////////////////////////////
static const SkGlyph& sk_getMetrics_utf8_next(SkGlyphCache* cache, const char** text)
@@ -1231,7 +1244,7 @@ void SkPaint::descriptorProc(const SkMatrix* deviceMatrix,
descSize += peBuffer.size();
entryCount += 1;
rec.fMaskFormat = SkMask::kA8_Format; // force antialiasing when we do the scan conversion
- // seems like we could support kLCD as well at this point <reed>...
+ // seems like we could support kLCD as well at this point...
}
if (mf) {
mfBuffer.writeFlattenable(mf);
@@ -1431,6 +1444,38 @@ bool SkPaint::getFillPath(const SkPath& src, SkPath* dst) const
return width != 0; // return true if we're filled, or false if we're hairline (width == 0)
}
+bool SkPaint::canComputeFastBounds() const {
+ // use bit-or since no need for early exit
+ return (reinterpret_cast<uintptr_t>(this->getMaskFilter()) |
+ reinterpret_cast<uintptr_t>(this->getLooper()) |
+ reinterpret_cast<uintptr_t>(this->getRasterizer()) |
+ reinterpret_cast<uintptr_t>(this->getPathEffect())) == 0;
+}
+
+const SkRect& SkPaint::computeFastBounds(const SkRect& src,
+ SkRect* storage) const {
+ SkASSERT(storage);
+
+ if (this->getStyle() != SkPaint::kFill_Style) {
+ // if we're stroked, outset the rect by the radius (and join type)
+ SkScalar radius = SkScalarHalf(this->getStrokeWidth());
+
+ if (0 == radius) { // hairline
+ radius = SK_Scalar1;
+ } else if (this->getStrokeJoin() == SkPaint::kMiter_Join) {
+ SkScalar scale = this->getStrokeMiter();
+ if (scale > SK_Scalar1) {
+ radius = SkScalarMul(radius, scale);
+ }
+ }
+ storage->set(src.fLeft - radius, src.fTop - radius,
+ src.fRight + radius, src.fBottom + radius);
+ return *storage;
+ }
+ // no adjustments needed, just return the original rect
+ return src;
+}
+
////////////////////////////////////////////////////////////////////////////////////////
static bool has_thick_frame(const SkPaint& paint)
@@ -1524,4 +1569,3 @@ const SkPath* SkTextToPathIter::next(SkScalar* xpos)
}
return NULL;
}
-
diff --git a/skia/sgl/SkPath.cpp b/skia/sgl/SkPath.cpp
index afe8662..5d6882e 100644
--- a/skia/sgl/SkPath.cpp
+++ b/skia/sgl/SkPath.cpp
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkPath.cpp
**
-** Copyright 2006, Google Inc.
+** 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.
@@ -19,6 +19,63 @@
#include "SkFlattenable.h"
#include "SkMath.h"
+////////////////////////////////////////////////////////////////////////////
+
+/* This guy's constructor/destructor bracket a path editing operation. It is
+ used when we know the bounds of the amount we are going to add to the path
+ (usually a new contour, but not required).
+
+ It captures some state about the path up front (i.e. if it already has a
+ cached bounds), and the if it can, it updates the cache bounds explicitly,
+ avoiding the need to revisit all of the points in computeBounds().
+ */
+class SkAutoPathBoundsUpdate {
+public:
+ SkAutoPathBoundsUpdate(SkPath* path, const SkRect& r) : fRect(r) {
+ this->init(path);
+ }
+
+ SkAutoPathBoundsUpdate(SkPath* path, SkScalar left, SkScalar top,
+ SkScalar right, SkScalar bottom) {
+ fRect.set(left, top, right, bottom);
+ this->init(path);
+ }
+
+ ~SkAutoPathBoundsUpdate() {
+ if (fEmpty) {
+ fPath->fFastBounds = fRect;
+ fPath->fFastBoundsIsDirty = false;
+ } else if (!fDirty) {
+ fPath->fFastBounds.join(fRect);
+ fPath->fFastBoundsIsDirty = false;
+ }
+ }
+
+private:
+ const SkPath* fPath;
+ SkRect fRect;
+ bool fDirty;
+ bool fEmpty;
+
+ // returns true if we should proceed
+ void init(const SkPath* path) {
+ fPath = path;
+ fDirty = path->fFastBoundsIsDirty;
+ fEmpty = path->isEmpty();
+ }
+};
+
+static void compute_fast_bounds(SkRect* bounds, const SkTDArray<SkPoint>& pts) {
+ if (pts.count() <= 1) { // we ignore just 1 point (moveto)
+ bounds->set(0, 0, 0, 0);
+ } else {
+ bounds->set(pts.begin(), pts.count());
+// SkDebugf("------- compute bounds %p %d", &pts, pts.count());
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////
+
/*
Stores the verbs and points as they are given to us, with exceptions:
- we only record "Close" if it was immediately preceeded by Line | Quad | Cubic
@@ -145,24 +202,8 @@ void SkPath::computeBounds(SkRect* bounds, BoundsType bt) const {
if (fFastBoundsIsDirty) {
fFastBoundsIsDirty = false;
- if (fPts.count() <= 1) { // we ignore just 1 point (moveto)
- fFastBounds.set(0, 0, 0, 0);
- } else {
- fFastBounds.set(fPts.begin(), fPts.count());
- }
+ compute_fast_bounds(&fFastBounds, fPts);
}
-#ifdef SK_DEBUG
- else { // check that our cache is correct
- SkRect r;
- if (fPts.count() <= 1) { // we ignore just 1 point (moveto)
- r.set(0, 0, 0, 0);
- } else {
- r.set(fPts.begin(), fPts.count());
- }
- SkASSERT(r == fFastBounds);
- }
-#endif
-
*bounds = fFastBounds;
}
@@ -286,13 +327,15 @@ void SkPath::close() {
}
///////////////////////////////////////////////////////////////////////////////
-
+
void SkPath::addRect(const SkRect& rect, Direction dir) {
this->addRect(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, dir);
}
void SkPath::addRect(SkScalar left, SkScalar top, SkScalar right,
SkScalar bottom, Direction dir) {
+ SkAutoPathBoundsUpdate apbu(this, left, top, right, bottom);
+
this->incReserve(5);
this->moveTo(left, top);
@@ -312,6 +355,8 @@ void SkPath::addRect(SkScalar left, SkScalar top, SkScalar right,
void SkPath::addRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry,
Direction dir) {
+ SkAutoPathBoundsUpdate apbu(this, rect);
+
SkScalar w = rect.width();
SkScalar halfW = SkScalarHalf(w);
SkScalar h = rect.height();
@@ -395,7 +440,7 @@ void SkPath::addRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry,
static void add_corner_arc(SkPath* path, const SkRect& rect,
SkScalar rx, SkScalar ry, int startAngle,
- bool ccw, bool forceMoveTo = false) {
+ SkPath::Direction dir, bool forceMoveTo) {
rx = SkMinScalar(SkScalarHalf(rect.width()), rx);
ry = SkMinScalar(SkScalarHalf(rect.height()), ry);
@@ -416,7 +461,7 @@ static void add_corner_arc(SkPath* path, const SkRect& rect,
SkScalar start = SkIntToScalar(startAngle);
SkScalar sweep = SkIntToScalar(90);
- if (ccw) {
+ if (SkPath::kCCW_Direction == dir) {
start += sweep;
sweep = -sweep;
}
@@ -426,26 +471,30 @@ static void add_corner_arc(SkPath* path, const SkRect& rect,
void SkPath::addRoundRect(const SkRect& rect, const SkScalar rad[],
Direction dir) {
+ SkAutoPathBoundsUpdate apbu(this, rect);
if (kCW_Direction == dir) {
- add_corner_arc(this, rect, rad[0], rad[1], 180, false, true);
- add_corner_arc(this, rect, rad[2], rad[3], 270, false);
- add_corner_arc(this, rect, rad[4], rad[5], 0, false);
- add_corner_arc(this, rect, rad[6], rad[7], 90, false);
+ add_corner_arc(this, rect, rad[0], rad[1], 180, dir, true);
+ add_corner_arc(this, rect, rad[2], rad[3], 270, dir, false);
+ add_corner_arc(this, rect, rad[4], rad[5], 0, dir, false);
+ add_corner_arc(this, rect, rad[6], rad[7], 90, dir, false);
} else {
- add_corner_arc(this, rect, rad[0], rad[1], 180, true, true);
- add_corner_arc(this, rect, rad[6], rad[7], 90, true);
- add_corner_arc(this, rect, rad[4], rad[5], 0, true);
- add_corner_arc(this, rect, rad[2], rad[3], 270, true);
+ add_corner_arc(this, rect, rad[0], rad[1], 180, dir, true);
+ add_corner_arc(this, rect, rad[6], rad[7], 90, dir, false);
+ add_corner_arc(this, rect, rad[4], rad[5], 0, dir, false);
+ add_corner_arc(this, rect, rad[2], rad[3], 270, dir, false);
}
+ this->close();
}
void SkPath::addOval(const SkRect& oval, Direction dir) {
+ SkAutoPathBoundsUpdate apbu(this, oval);
+
SkScalar cx = oval.centerX();
SkScalar cy = oval.centerY();
SkScalar rx = SkScalarHalf(oval.width());
SkScalar ry = SkScalarHalf(oval.height());
-#if 1 // these seem faster than using quads (1/2 the number of edges)
+#if 0 // these seem faster than using quads (1/2 the number of edges)
SkScalar sx = SkScalarMul(rx, CUBIC_ARC_FACTOR);
SkScalar sy = SkScalarMul(ry, CUBIC_ARC_FACTOR);
@@ -468,7 +517,7 @@ void SkPath::addOval(const SkRect& oval, Direction dir) {
SkScalar mx = SkScalarMul(rx, SK_ScalarRoot2Over2);
SkScalar my = SkScalarMul(ry, SK_ScalarRoot2Over2);
- this->incReserve(16);
+ this->incReserve(17); // 8 quads + close
this->moveTo(cx + rx, cy);
if (dir == kCCW_Direction) {
this->quadTo(cx + rx, cy - sy, cx + mx, cy - my);
@@ -547,7 +596,7 @@ void SkPath::addArc(const SkRect& oval, SkScalar startAngle,
if (oval.isEmpty() || 0 == sweepAngle) {
return;
}
-
+
const SkScalar kFullCircleAngle = SkIntToScalar(360);
if (sweepAngle >= kFullCircleAngle || sweepAngle <= -kFullCircleAngle) {
@@ -792,6 +841,7 @@ static void subdivide_cubic_to(SkPath* path, const SkPoint pts[4],
}
void SkPath::transform(const SkMatrix& matrix, SkPath* dst) const {
+ SkDEBUGCODE(this->validate();)
if (dst == NULL) {
dst = (SkPath*)this;
}
@@ -846,6 +896,7 @@ void SkPath::transform(const SkMatrix& matrix, SkPath* dst) const {
dst->fFillType = fFillType;
}
matrix.mapPoints(dst->fPts.begin(), fPts.begin(), fPts.count());
+ SkDEBUGCODE(dst->validate();)
}
}
@@ -1211,11 +1262,18 @@ void SkPath::toString(SkString* str) const {
void SkPath::validate() const {
SkASSERT(this != NULL);
SkASSERT((fFillType & ~3) == 0);
- if (!fFastBoundsIsDirty) {
- SkASSERT(fFastBounds.width() >= 0 && fFastBounds.height() >= 0);
- }
fPts.validate();
fVerbs.validate();
+
+ if (!fFastBoundsIsDirty) {
+ SkRect bounds;
+ compute_fast_bounds(&bounds, fPts);
+ // can't call contains(), since it returns false if the rect is empty
+ SkASSERT(fFastBounds.fLeft <= bounds.fLeft);
+ SkASSERT(fFastBounds.fTop <= bounds.fTop);
+ SkASSERT(fFastBounds.fRight >= bounds.fRight);
+ SkASSERT(fFastBounds.fBottom >= bounds.fBottom);
+ }
}
#if 0 // test to ensure that the iterator returns the same data as the path
diff --git a/skia/sgl/SkPathEffect.cpp b/skia/sgl/SkPathEffect.cpp
index 8321fca..2905895 100644
--- a/skia/sgl/SkPathEffect.cpp
+++ b/skia/sgl/SkPathEffect.cpp
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkPathEffect.cpp
**
-** Copyright 2006, Google Inc.
+** 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.
diff --git a/skia/sgl/SkPathMeasure.cpp b/skia/sgl/SkPathMeasure.cpp
index e877d0f..ec1510d 100644
--- a/skia/sgl/SkPathMeasure.cpp
+++ b/skia/sgl/SkPathMeasure.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006-2008 Google Inc.
+ * Copyright (C) 2006-2008 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.
diff --git a/skia/sgl/SkPicture.cpp b/skia/sgl/SkPicture.cpp
deleted file mode 100644
index 0847004..0000000
--- a/skia/sgl/SkPicture.cpp
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
-**
-** Copyright 2007, Google Inc.
-**
-** 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 "SkPictureFlat.h"
-#include "SkPicturePlayback.h"
-#include "SkPictureRecord.h"
-
-#include "SkCanvas.h"
-#include "SkChunkAlloc.h"
-#include "SkPicture.h"
-#include "SkRegion.h"
-#include "SkStream.h"
-#include "SkTDArray.h"
-#include "SkTSearch.h"
-#include "SkTime.h"
-
-#include "SkReader32.h"
-#include "SkWriter32.h"
-
-#define DUMP_BUFFER_SIZE 65536
-
-//#define ENABLE_TIME_DRAW // dumps milliseconds for each draw
-
-
-#ifdef SK_DEBUG
-// enable SK_DEBUG_TRACE to trace DrawType elements when
-// recorded and played back
-// #define SK_DEBUG_TRACE
-// enable SK_DEBUG_SIZE to see the size of picture components
-// #define SK_DEBUG_SIZE
-// enable SK_DEBUG_DUMP to see the contents of recorded elements
-// #define SK_DEBUG_DUMP
-// enable SK_DEBUG_VALIDATE to check internal structures for consistency
-// #define SK_DEBUG_VALIDATE
-#endif
-
-#if defined SK_DEBUG_TRACE || defined SK_DEBUG_DUMP
-const char* DrawTypeToString(DrawType drawType) {
- switch (drawType) {
- case UNUSED: SkDebugf("DrawType UNUSED\n"); SkASSERT(0); break;
- case CLIP_PATH: return "CLIP_PATH";
- case CLIP_REGION: return "CLIP_REGION";
- case CLIP_RECT: return "CLIP_RECT";
- case CONCAT: return "CONCAT";
- case DRAW_BITMAP: return "DRAW_BITMAP";
- case DRAW_BITMAP_MATRIX: return "DRAW_BITMAP_MATRIX";
- case DRAW_BITMAP_RECT: return "DRAW_BITMAP_RECT";
- case DRAW_PAINT: return "DRAW_PAINT";
- case DRAW_PATH: return "DRAW_PATH";
- case DRAW_PICTURE: return "DRAW_PICTURE";
- case DRAW_POINTS: return "DRAW_POINTS";
- case DRAW_POS_TEXT: return "DRAW_POS_TEXT";
- case DRAW_POS_TEXT_H: return "DRAW_POS_TEXT_H";
- case DRAW_RECT_GENERAL: return "DRAW_RECT_GENERAL";
- case DRAW_RECT_SIMPLE: return "DRAW_RECT_SIMPLE";
- case DRAW_SPRITE: return "DRAW_SPRITE";
- case DRAW_TEXT: return "DRAW_TEXT";
- case DRAW_TEXT_ON_PATH: return "DRAW_TEXT_ON_PATH";
- case RESTORE: return "RESTORE";
- case ROTATE: return "ROTATE";
- case SAVE: return "SAVE";
- case SAVE_LAYER: return "SAVE_LAYER";
- case SCALE: return "SCALE";
- case SKEW: return "SKEW";
- case TRANSLATE: return "TRANSLATE";
- default:
- SkDebugf("DrawType error 0x%08x\n", drawType);
- SkASSERT(0);
- break;
- }
- SkASSERT(0);
- return NULL;
-}
-#endif
-
-#ifdef SK_DEBUG_VALIDATE
-static void validateMatrix(const SkMatrix* matrix) {
- SkScalar scaleX = matrix->getScaleX();
- SkScalar scaleY = matrix->getScaleY();
- SkScalar skewX = matrix->getSkewX();
- SkScalar skewY = matrix->getSkewY();
- SkScalar perspX = matrix->getPerspX();
- SkScalar perspY = matrix->getPerspY();
- if (scaleX != 0 && skewX != 0)
- SkDebugf("scaleX != 0 && skewX != 0\n");
- SkASSERT(scaleX == 0 || skewX == 0);
- SkASSERT(scaleY == 0 || skewY == 0);
- SkASSERT(perspX == 0);
- SkASSERT(perspY == 0);
-}
-#endif
-
-
-///////////////////////////////////////////////////////////////////////////////
-
-SkPicture::SkPicture() {
- fRecord = NULL;
- fPlayback = NULL;
- fWidth = fHeight = 0;
-}
-
-SkPicture::SkPicture(const SkPicture& src) : SkRefCnt() {
- fWidth = src.fWidth;
- fHeight = src.fHeight;
- fRecord = NULL;
-
- /* We want to copy the src's playback. However, if that hasn't been built
- yet, we need to fake a call to endRecording() without actually calling
- it (since it is destructive, and we don't want to change src).
- */
- if (src.fPlayback) {
- fPlayback = SkNEW_ARGS(SkPicturePlayback, (*src.fPlayback));
- } else if (src.fRecord) {
- // here we do a fake src.endRecording()
- fPlayback = SkNEW_ARGS(SkPicturePlayback, (*src.fRecord));
- } else {
- fPlayback = NULL;
- }
-}
-
-SkPicture::~SkPicture() {
- fRecord->safeUnref();
- SkDELETE(fPlayback);
-}
-
-void SkPicture::swap(SkPicture& other) {
- SkTSwap(fRecord, other.fRecord);
- SkTSwap(fPlayback, other.fPlayback);
- SkTSwap(fWidth, other.fWidth);
- SkTSwap(fHeight, other.fHeight);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-SkCanvas* SkPicture::beginRecording(int width, int height) {
- if (fPlayback) {
- SkDELETE(fPlayback);
- fPlayback = NULL;
- }
-
- if (NULL != fRecord) {
- fRecord->unref();
- fRecord = NULL;
- }
-
- fRecord = SkNEW(SkPictureRecord);
-
- fWidth = width;
- fHeight = height;
-
- SkBitmap bm;
- bm.setConfig(SkBitmap::kNo_Config, width, height);
- fRecord->setBitmapDevice(bm);
-
- return fRecord;
-}
-
-SkCanvas* SkPicture::getRecordingCanvas() const {
- // will be null if we are not recording
- return fRecord;
-}
-
-void SkPicture::endRecording() {
- if (NULL == fPlayback) {
- if (NULL != fRecord) {
- fPlayback = SkNEW_ARGS(SkPicturePlayback, (*fRecord));
- fRecord->unref();
- fRecord = NULL;
- }
- }
- SkASSERT(NULL == fRecord);
-}
-
-void SkPicture::draw(SkCanvas* surface) {
- this->endRecording();
- if (fPlayback) {
- fPlayback->draw(*surface);
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-#include "SkStream.h"
-
-#define PICTURE_VERSION 1
-
-SkPicture::SkPicture(SkStream* stream) : SkRefCnt() {
- if (stream->readU32() != PICTURE_VERSION) {
- sk_throw();
- }
-
- fWidth = stream->readU32();
- fHeight = stream->readU32();
-
- fRecord = NULL;
- fPlayback = NULL;
-
- if (stream->readBool()) {
- fPlayback = SkNEW_ARGS(SkPicturePlayback, (stream));
- }
-}
-
-void SkPicture::serialize(SkWStream* stream) const {
- SkPicturePlayback* playback = fPlayback;
-
- if (NULL == playback && fRecord) {
- playback = SkNEW_ARGS(SkPicturePlayback, (*fRecord));
- }
-
- stream->write32(PICTURE_VERSION);
- stream->write32(fWidth);
- stream->write32(fHeight);
- if (playback) {
- stream->writeBool(true);
- playback->serialize(stream);
- // delete playback if it is a local version (i.e. cons'd up just now)
- if (playback != fPlayback) {
- SkDELETE(playback);
- }
- } else {
- stream->writeBool(false);
- }
-}
-
diff --git a/skia/sgl/SkProcSpriteBlitter.cpp b/skia/sgl/SkProcSpriteBlitter.cpp
index 822c218..f727581e 100644
--- a/skia/sgl/SkProcSpriteBlitter.cpp
+++ b/skia/sgl/SkProcSpriteBlitter.cpp
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkProcSpriteBlitter.cpp
**
-** Copyright 2006, Google Inc.
+** 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.
diff --git a/skia/sgl/SkRasterizer.cpp b/skia/sgl/SkRasterizer.cpp
index 8a46bad..f1d087d 100644
--- a/skia/sgl/SkRasterizer.cpp
+++ b/skia/sgl/SkRasterizer.cpp
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkRasterizer.cpp
**
-** Copyright 2006, Google Inc.
+** 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.
diff --git a/skia/sgl/SkRefCnt.cpp b/skia/sgl/SkRefCnt.cpp
index 2f0babc..fea1005 100644
--- a/skia/sgl/SkRefCnt.cpp
+++ b/skia/sgl/SkRefCnt.cpp
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkRefCnt.cpp
**
-** Copyright 2006, Google Inc.
+** 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.
diff --git a/skia/sgl/SkRegion_path.cpp b/skia/sgl/SkRegion_path.cpp
index 11e19b9..d00baf9 100644
--- a/skia/sgl/SkRegion_path.cpp
+++ b/skia/sgl/SkRegion_path.cpp
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkRegion_path.cpp
**
-** Copyright 2006, Google Inc.
+** 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.
@@ -25,7 +25,8 @@ class SkRgnBuilder : public SkBlitter {
public:
virtual ~SkRgnBuilder();
- void init(int maxHeight, int maxTransitions);
+ // returns true if it could allocate the working storage needed
+ bool init(int maxHeight, int maxTransitions);
void done() {
if (fCurrScanline != NULL) {
@@ -96,15 +97,33 @@ SkRgnBuilder::~SkRgnBuilder() {
sk_free(fStorage);
}
-void SkRgnBuilder::init(int maxHeight, int maxTransitions) {
- int count = maxHeight * (3 + maxTransitions);
+bool SkRgnBuilder::init(int maxHeight, int maxTransitions) {
+ if ((maxHeight | maxTransitions) < 0) {
+ return false;
+ }
+
+ Sk64 count, size;
+
+ // compute the count with +1 and +3 slop for the working buffer
+ count.setMul(maxHeight + 1, 3 + maxTransitions);
+ if (!count.is32() || count.isNeg()) {
+ return false;
+ }
+ fStorageCount = count.get32();
- // add maxTransitions to have slop for working buffer
- fStorageCount = count + 3 + maxTransitions;
- fStorage = (SkRegion::RunType*)sk_malloc_throw(fStorageCount * sizeof(SkRegion::RunType));
+ size.setMul(fStorageCount, sizeof(SkRegion::RunType));
+ if (!size.is32() || size.isNeg()) {
+ return false;
+ }
+
+ fStorage = (SkRegion::RunType*)sk_malloc_flags(size.get32(), 0);
+ if (NULL == fStorage) {
+ return false;
+ }
fCurrScanline = NULL; // signal empty collection
fPrevScanline = NULL; // signal first scanline
+ return true;
}
void SkRgnBuilder::blitH(int x, int y, int width) {
@@ -275,7 +294,11 @@ bool SkRegion::setPath(const SkPath& path, const SkRegion& clip) {
SkRgnBuilder builder;
- builder.init(bot - top, SkMax32(pathTransitions, clipTransitions));
+ if (!builder.init(bot - top, SkMax32(pathTransitions, clipTransitions))) {
+ // can't allocate working space, so return false
+ return this->setEmpty();
+ }
+
SkScan::FillPath(path, clip, &builder);
builder.done();
diff --git a/skia/sgl/SkScalerContext.cpp b/skia/sgl/SkScalerContext.cpp
index 0289312..854c4de 100644
--- a/skia/sgl/SkScalerContext.cpp
+++ b/skia/sgl/SkScalerContext.cpp
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkScalerContext.cpp
**
-** Copyright 2006, Google Inc.
+** 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.
@@ -182,6 +182,17 @@ SkScalerContext* SkScalerContext::getGlyphContext(const SkGlyph& glyph) const {
return ctx;
}
+static int plus_minus_pin(int value, int max) {
+ SkASSERT(max >= 0);
+
+ if (value > max) {
+ value = max;
+ } else if (value < -max) {
+ value = -max;
+ }
+ return value;
+}
+
void SkScalerContext::getAdvance(SkGlyph* glyph) {
// mark us as just having a valid advance
glyph->fMaskFormat = MASK_FORMAT_JUST_ADVANCE;
@@ -384,18 +395,19 @@ void SkScalerContext::getImage(const SkGlyph& origGlyph) {
// check to see if we should filter the alpha channel
- if (fRec.fMaskFormat != SkMask::kBW_Format &&
+ if (NULL == fMaskFilter &&
+ fRec.fMaskFormat != SkMask::kBW_Format &&
(fRec.fFlags & (kGammaForBlack_Flag | kGammaForWhite_Flag)) != 0)
{
const uint8_t* table = (fRec.fFlags & kGammaForBlack_Flag) ? gBlackGammaTable : gWhiteGammaTable;
if (NULL != table)
{
- uint8_t* dst = (uint8_t*)glyph->fImage;
- unsigned rowBytes = glyph->rowBytes();
+ uint8_t* dst = (uint8_t*)origGlyph.fImage;
+ unsigned rowBytes = origGlyph.rowBytes();
- for (int y = glyph->fHeight - 1; y >= 0; --y)
+ for (int y = origGlyph.fHeight - 1; y >= 0; --y)
{
- for (int x = glyph->fWidth - 1; x >= 0; --x)
+ for (int x = origGlyph.fWidth - 1; x >= 0; --x)
dst[x] = table[dst[x]];
dst += rowBytes;
}
diff --git a/skia/sgl/SkScan.cpp b/skia/sgl/SkScan.cpp
index 1d80bb1..013b0ea 100644
--- a/skia/sgl/SkScan.cpp
+++ b/skia/sgl/SkScan.cpp
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkScan.cpp
**
-** Copyright 2006, Google Inc.
+** 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.
@@ -65,10 +65,10 @@ void SkScan::FillXRect(const SkXRect& xr, const SkRegion* clip,
void SkScan::FillRect(const SkRect& r, const SkRegion* clip,
SkBlitter* blitter) {
- SkXRect xr;
+ SkIRect ir;
- XRect_set(&xr, r);
- SkScan::FillXRect(xr, clip, blitter);
+ r.round(&ir);
+ SkScan::FillIRect(ir, clip, blitter);
}
#endif
diff --git a/skia/sgl/SkScan.h b/skia/sgl/SkScan.h
index f5b12fb..379c016 100644
--- a/skia/sgl/SkScan.h
+++ b/skia/sgl/SkScan.h
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkScan.h
**
-** Copyright 2006, Google Inc.
+** 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.
@@ -83,7 +83,7 @@ public:
from int to SkFixed. Does not check for overflow if the src coordinates
exceed 32K
*/
-static inline void XRect_set(SkXRect* xr, const SkIRect& src) {
+static void XRect_set(SkXRect* xr, const SkIRect& src) {
xr->fLeft = SkIntToFixed(src.fLeft);
xr->fTop = SkIntToFixed(src.fTop);
xr->fRight = SkIntToFixed(src.fRight);
@@ -94,7 +94,7 @@ static inline void XRect_set(SkXRect* xr, const SkIRect& src) {
from SkScalar to SkFixed. Does not check for overflow if the src coordinates
exceed 32K
*/
-static inline void XRect_set(SkXRect* xr, const SkRect& src) {
+static void XRect_set(SkXRect* xr, const SkRect& src) {
xr->fLeft = SkScalarToFixed(src.fLeft);
xr->fTop = SkScalarToFixed(src.fTop);
xr->fRight = SkScalarToFixed(src.fRight);
@@ -103,7 +103,7 @@ static inline void XRect_set(SkXRect* xr, const SkRect& src) {
/** Round the SkXRect coordinates, and store the result in the SkIRect.
*/
-static inline void XRect_round(const SkXRect& xr, SkIRect* dst) {
+static void XRect_round(const SkXRect& xr, SkIRect* dst) {
dst->fLeft = SkFixedRound(xr.fLeft);
dst->fTop = SkFixedRound(xr.fTop);
dst->fRight = SkFixedRound(xr.fRight);
@@ -113,7 +113,7 @@ static inline void XRect_round(const SkXRect& xr, SkIRect* dst) {
/** Round the SkXRect coordinates out (i.e. use floor for left/top, and ceiling
for right/bottom), and store the result in the SkIRect.
*/
-static inline void XRect_roundOut(const SkXRect& xr, SkIRect* dst) {
+static void XRect_roundOut(const SkXRect& xr, SkIRect* dst) {
dst->fLeft = SkFixedFloor(xr.fLeft);
dst->fTop = SkFixedFloor(xr.fTop);
dst->fRight = SkFixedCeil(xr.fRight);
diff --git a/skia/sgl/SkScanPriv.h b/skia/sgl/SkScanPriv.h
index de7e3e7..43dfdef 100644
--- a/skia/sgl/SkScanPriv.h
+++ b/skia/sgl/SkScanPriv.h
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkScanPriv.h
**
-** Copyright 2006, Google Inc.
+** 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.
diff --git a/skia/sgl/SkScan_AntiPath.cpp b/skia/sgl/SkScan_AntiPath.cpp
index b603f15..9cdeeaa 100644
--- a/skia/sgl/SkScan_AntiPath.cpp
+++ b/skia/sgl/SkScan_AntiPath.cpp
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkScan_AntiPath.cpp
**
-** Copyright 2006, Google Inc.
+** 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.
diff --git a/skia/sgl/SkScan_Antihair.cpp b/skia/sgl/SkScan_Antihair.cpp
index ca36739..04e4690 100644
--- a/skia/sgl/SkScan_Antihair.cpp
+++ b/skia/sgl/SkScan_Antihair.cpp
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkScan_Antihair.cpp
**
-** Copyright 2006, Google Inc.
+** 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.
@@ -23,6 +23,12 @@
#define HLINE_STACK_BUFFER 100
+static inline int SmallDot6Scale(int value, int dot6) {
+ SkASSERT((int16_t)value == value);
+ SkASSERT((unsigned)dot6 <= 64);
+ return SkMulS16(value, dot6) >> 6;
+}
+
//#define TEST_GAMMA
#ifdef TEST_GAMMA
@@ -52,8 +58,9 @@
#define ApplyGamma(table, alpha) SkToU8(alpha)
#endif
+///////////////////////////////////////////////////////////////////////////////
-static void call_hline_blitter(SkBlitter* blitter, int x, int y, int count, uint8_t alpha)
+static void call_hline_blitter(SkBlitter* blitter, int x, int y, int count, U8CPU alpha)
{
SkASSERT(count > 0);
@@ -74,7 +81,7 @@ static void call_hline_blitter(SkBlitter* blitter, int x, int y, int count, uint
} while (count > 0);
}
-static void hline(int x, int stopx, SkFixed fy, SkFixed /*slope*/, SkBlitter* blitter)
+static SkFixed hline(int x, int stopx, SkFixed fy, SkFixed /*slope*/, SkBlitter* blitter, int mod64)
{
SkASSERT(x < stopx);
int count = stopx - x;
@@ -84,16 +91,21 @@ static void hline(int x, int stopx, SkFixed fy, SkFixed /*slope*/, SkBlitter* bl
uint8_t a = (uint8_t)(fy >> 8);
// lower line
- if (a)
- call_hline_blitter(blitter, x, y, count, a);
+ unsigned ma = SmallDot6Scale(a, mod64);
+ if (ma) {
+ call_hline_blitter(blitter, x, y, count, ma);
+ }
// upper line
- a = (uint8_t)(255 - a);
- if (a)
- call_hline_blitter(blitter, x, y - 1, count, a);
+ ma = SmallDot6Scale(255 - a, mod64);
+ if (ma) {
+ call_hline_blitter(blitter, x, y - 1, count, ma);
+ }
+
+ return fy - SK_Fixed1/2;
}
-static void horish(int x, int stopx, SkFixed fy, SkFixed dy, SkBlitter* blitter)
+static SkFixed horish(int x, int stopx, SkFixed fy, SkFixed dy, SkBlitter* blitter, int mod64)
{
SkASSERT(x < stopx);
@@ -110,19 +122,19 @@ static void horish(int x, int stopx, SkFixed fy, SkFixed dy, SkBlitter* blitter)
do {
int lower_y = fy >> 16;
uint8_t a = (uint8_t)(fy >> 8);
-
- if (a)
+ unsigned ma = SmallDot6Scale(a, mod64);
+ if (ma)
{
- aa[0] = ApplyGamma(gamma, a);
+ aa[0] = ApplyGamma(gamma, ma);
blitter->blitAntiH(x, lower_y, aa, runs);
// the clipping blitters might edit runs, but should not affect us
SkASSERT(runs[0] == 1);
SkASSERT(runs[1] == 0);
}
- a = (uint8_t)(255 - a);
- if (a)
+ ma = SmallDot6Scale(255 - a, mod64);
+ if (ma)
{
- aa[0] = ApplyGamma(gamma, a);
+ aa[0] = ApplyGamma(gamma, ma);
blitter->blitAntiH(x, lower_y - 1, aa, runs);
// the clipping blitters might edit runs, but should not affect us
SkASSERT(runs[0] == 1);
@@ -130,9 +142,11 @@ static void horish(int x, int stopx, SkFixed fy, SkFixed dy, SkBlitter* blitter)
}
fy += dy;
} while (++x < stopx);
+
+ return fy - SK_Fixed1/2;
}
-static void vline(int y, int stopy, SkFixed fx, SkFixed /*slope*/, SkBlitter* blitter)
+static SkFixed vline(int y, int stopy, SkFixed fx, SkFixed /*slope*/, SkBlitter* blitter, int mod64)
{
SkASSERT(y < stopy);
fx += SK_Fixed1/2;
@@ -140,14 +154,17 @@ static void vline(int y, int stopy, SkFixed fx, SkFixed /*slope*/, SkBlitter* bl
int x = fx >> 16;
int a = (uint8_t)(fx >> 8);
- if (a)
- blitter->blitV(x, y, stopy - y, ApplyGamma(gGammaTable, a));
- a = 255 - a;
- if (a)
- blitter->blitV(x - 1, y, stopy - y, ApplyGamma(gGammaTable, a));
+ unsigned ma = SmallDot6Scale(a, mod64);
+ if (ma)
+ blitter->blitV(x, y, stopy - y, ApplyGamma(gGammaTable, ma));
+ ma = SmallDot6Scale(255 - a, mod64);
+ if (ma)
+ blitter->blitV(x - 1, y, stopy - y, ApplyGamma(gGammaTable, ma));
+
+ return fx - SK_Fixed1/2;
}
-static void vertish(int y, int stopy, SkFixed fx, SkFixed dx, SkBlitter* blitter)
+static SkFixed vertish(int y, int stopy, SkFixed fx, SkFixed dx, SkBlitter* blitter, int mod64)
{
SkASSERT(y < stopy);
#ifdef TEST_GAMMA
@@ -164,8 +181,8 @@ static void vertish(int y, int stopy, SkFixed fx, SkFixed dx, SkBlitter* blitter
int x = fx >> 16;
uint8_t a = (uint8_t)(fx >> 8);
- aa[0] = ApplyGamma(gamma, 255 - a);
- aa[1] = ApplyGamma(gamma, a);
+ aa[0] = ApplyGamma(gamma, SmallDot6Scale(255 - a, mod64));
+ aa[1] = ApplyGamma(gamma, SmallDot6Scale(a, mod64));
// the clippng blitters might overwrite this guy, so we have to reset it each time
runs[1] = 1;
blitter->blitAntiH(x - 1, y, aa, runs);
@@ -174,9 +191,11 @@ static void vertish(int y, int stopy, SkFixed fx, SkFixed dx, SkBlitter* blitter
SkASSERT(runs[2] == 0);
fx += dx;
} while (++y < stopy);
+
+ return fx - SK_Fixed1/2;
}
-typedef void (*LineProc)(int istart, int istop, SkFixed fstart, SkFixed slope, SkBlitter*);
+typedef SkFixed (*LineProc)(int istart, int istop, SkFixed fstart, SkFixed slope, SkBlitter*, int);
static inline SkFixed fastfixdiv(SkFDot6 a, SkFDot6 b)
{
@@ -184,11 +203,6 @@ static inline SkFixed fastfixdiv(SkFDot6 a, SkFDot6 b)
SkASSERT(b != 0);
return (a << 16) / b;
}
-static inline SkFDot6 fastfixmul(SkFixed fixed, SkFDot6 b)
-{
- SkASSERT(SkAbs32(fixed) <= SK_Fixed1 && SkAbs32(b) <= SkIntToFDot6(511));
- return (fixed * b + 0x8000) >> 16;
-}
static void do_anti_hairline(SkFDot6 x0, SkFDot6 y0, SkFDot6 x1, SkFDot6 y1,
const SkIRect* clip, SkBlitter* blitter)
@@ -205,35 +219,40 @@ static void do_anti_hairline(SkFDot6 x0, SkFDot6 y0, SkFDot6 x1, SkFDot6 y1,
return;
}
+ int scaleStart, scaleStop;
int istart, istop;
SkFixed fstart, slope;
LineProc proc;
if (SkAbs32(x1 - x0) > SkAbs32(y1 - y0)) // mostly horizontal
{
- if (x0 > x1) // we want to go left-to-right
- {
+ if (x0 > x1) { // we want to go left-to-right
SkTSwap<SkFDot6>(x0, x1);
SkTSwap<SkFDot6>(y0, y1);
}
- istart = SkFDot6Round(x0);
- istop = SkFDot6Round(x1);
- if (istart == istop) // too short to draw
- return;
- if (y0 == y1) // completely horizontal, take fast case
- {
+ istart = SkFDot6Floor(x0);
+ istop = SkFDot6Ceil(x1);
+ fstart = SkFDot6ToFixed(y0);
+ if (y0 == y1) { // completely horizontal, take fast case
slope = 0;
- fstart = SkFDot6ToFixed(y0);
proc = hline;
- }
- else
- {
+ } else {
slope = fastfixdiv(y1 - y0, x1 - x0);
SkASSERT(slope >= -SK_Fixed1 && slope <= SK_Fixed1);
- fstart = SkFDot6ToFixed(y0 + fastfixmul(slope, (32 - x0) & 63));
+ fstart += (slope * (32 - (x0 & 63)) + 32) >> 6;
proc = horish;
}
+
+ SkASSERT(istop > istart);
+ if (istop - istart == 1) {
+ scaleStart = x1 - x0;
+ SkASSERT(scaleStart >= 0 && scaleStart <= 64);
+ scaleStop = 0;
+ } else {
+ scaleStart = 64 - (x0 & 63);
+ scaleStop = x1 & 63;
+ }
if (clip)
{
@@ -243,12 +262,16 @@ static void do_anti_hairline(SkFDot6 x0, SkFDot6 y0, SkFDot6 x1, SkFDot6 y1,
{
fstart += slope * (clip->fLeft - istart);
istart = clip->fLeft;
+ scaleStart = 64;
}
- if (istop > clip->fRight)
+ if (istop > clip->fRight) {
istop = clip->fRight;
+ scaleStop = 64;
+ }
SkASSERT(istart <= istop);
if (istart == istop)
return;
+
// now test if our Y values are completely inside the clip
int top, bottom;
if (slope >= 0) // T2B
@@ -274,25 +297,36 @@ static void do_anti_hairline(SkFDot6 x0, SkFDot6 y0, SkFDot6 x1, SkFDot6 y1,
SkTSwap<SkFDot6>(x0, x1);
SkTSwap<SkFDot6>(y0, y1);
}
- istart = SkFDot6Round(y0);
- istop = SkFDot6Round(y1);
- if (istart == istop) // too short to draw
- return;
+ istart = SkFDot6Floor(y0);
+ istop = SkFDot6Ceil(y1);
+ fstart = SkFDot6ToFixed(x0);
if (x0 == x1)
{
+ if (y0 == y1) { // are we zero length?
+ return; // nothing to do
+ }
slope = 0;
- fstart = SkFDot6ToFixed(x0);
proc = vline;
}
else
{
slope = fastfixdiv(x1 - x0, y1 - y0);
SkASSERT(slope <= SK_Fixed1 && slope >= -SK_Fixed1);
- fstart = SkFDot6ToFixed(x0 + fastfixmul(slope, (32 - y0) & 63));
+ fstart += (slope * (32 - (y0 & 63)) + 32) >> 6;
proc = vertish;
}
+ SkASSERT(istop > istart);
+ if (istop - istart == 1) {
+ scaleStart = y1 - y0;
+ SkASSERT(scaleStart >= 0 && scaleStart <= 64);
+ scaleStop = 0;
+ } else {
+ scaleStart = 64 - (y0 & 63);
+ scaleStop = y1 & 63;
+ }
+
if (clip)
{
if (istart >= clip->fBottom || istop <= clip->fTop)
@@ -301,12 +335,16 @@ static void do_anti_hairline(SkFDot6 x0, SkFDot6 y0, SkFDot6 x1, SkFDot6 y1,
{
fstart += slope * (clip->fTop - istart);
istart = clip->fTop;
+ scaleStart = 64;
}
- if (istop > clip->fBottom)
+ if (istop > clip->fBottom) {
istop = clip->fBottom;
+ scaleStop = 64;
+ }
SkASSERT(istart <= istop);
if (istart == istop)
return;
+
// now test if our X values are completely inside the clip
int left, right;
if (slope >= 0) // L2R
@@ -332,7 +370,16 @@ static void do_anti_hairline(SkFDot6 x0, SkFDot6 y0, SkFDot6 x1, SkFDot6 y1,
rectClipper.init(blitter, *clip);
blitter = &rectClipper;
}
- proc(istart, istop, fstart, slope, blitter);
+
+ fstart = proc(istart, istart + 1, fstart, slope, blitter, scaleStart);
+ istart += 1;
+ int fullSpans = istop - istart - 1;
+ if (fullSpans > 0) {
+ fstart = proc(istart, istart + fullSpans, fstart, slope, blitter, 64);
+ }
+ if (scaleStop > 0) {
+ proc(istop - 1, istop, fstart, slope, blitter, scaleStop);
+ }
}
void SkScan::AntiHairLine(const SkPoint& pt0, const SkPoint& pt1,
@@ -360,10 +407,10 @@ void SkScan::AntiHairLine(const SkPoint& pt0, const SkPoint& pt1,
SkFDot6 bottom = SkMax32(y0, y1);
SkIRect ir;
- ir.set( SkFDot6Round(left) - 1,
- SkFDot6Round(top) - 1,
- SkFDot6Round(right) + 1,
- SkFDot6Round(bottom) + 1);
+ ir.set( SkFDot6Floor(left) - 1,
+ SkFDot6Floor(top) - 1,
+ SkFDot6Ceil(right) + 1,
+ SkFDot6Ceil(bottom) + 1);
if (clip->quickReject(ir))
return;
@@ -536,12 +583,61 @@ void SkScan::AntiFillXRect(const SkXRect& xr, const SkRegion* clip,
#ifdef SK_SCALAR_IS_FLOAT
-void SkScan::AntiFillRect(const SkRect& r, const SkRegion* clip,
- SkBlitter* blitter) {
+/* This guy takes a float-rect, but with the key improvement that it has
+ already been clipped, so we know that it is safe to convert it into a
+ XRect (fixedpoint), as it won't overflow.
+*/
+static void antifillrect(const SkRect& r, SkBlitter* blitter) {
SkXRect xr;
XRect_set(&xr, r);
- SkScan::AntiFillXRect(xr, clip, blitter);
+ antifillrect(xr, blitter);
+}
+
+/* We repeat the clipping logic of AntiFillXRect because the float rect might
+ overflow if we blindly converted it to an XRect. This sucks that we have to
+ repeat the clipping logic, but I don't see how to share the code/logic.
+
+ We clip r (as needed) into one or more (smaller) float rects, and then pass
+ those to our version of antifillrect, which converts it into an XRect and
+ then calls the blit.
+*/
+void SkScan::AntiFillRect(const SkRect& r, const SkRegion* clip,
+ SkBlitter* blitter) {
+ if (clip) {
+ SkIRect outerBounds;
+ r.roundOut(&outerBounds);
+
+ if (clip->isRect()) {
+ const SkIRect& clipBounds = clip->getBounds();
+
+ if (clipBounds.contains(outerBounds)) {
+ antifillrect(r, blitter);
+ } else {
+ SkRect tmpR;
+ // this keeps our original edges fractional
+ tmpR.set(clipBounds);
+ if (tmpR.intersect(r)) {
+ antifillrect(tmpR, blitter);
+ }
+ }
+ } else {
+ SkRegion::Cliperator clipper(*clip, outerBounds);
+ const SkIRect& rr = clipper.rect();
+
+ while (!clipper.done()) {
+ SkRect tmpR;
+ // this keeps our original edges fractional
+ tmpR.set(rr);
+ if (tmpR.intersect(r)) {
+ antifillrect(tmpR, blitter);
+ }
+ clipper.next();
+ }
+ }
+ } else {
+ antifillrect(r, blitter);
+ }
}
#endif
diff --git a/skia/sgl/SkScan_Hairline.cpp b/skia/sgl/SkScan_Hairline.cpp
index 5312f25..6a66754 100644
--- a/skia/sgl/SkScan_Hairline.cpp
+++ b/skia/sgl/SkScan_Hairline.cpp
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkScan_Hairline.cpp
**
-** Copyright 2006, Google Inc.
+** 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.
@@ -95,7 +95,7 @@ void SkScan::HairLine(const SkPoint& pt0, const SkPoint& pt1, const SkRegion* cl
return;
SkFixed slope = SkFixedDiv(dy, dx);
- SkFixed startY = SkFDot6ToFixed(y0 + SkFixedMul(slope, (32 - x0) & 63));
+ SkFixed startY = SkFDot6ToFixed(y0) + (slope * ((32 - x0) & 63) >> 6);
horiline(ix0, ix1, startY, slope, blitter);
}
@@ -112,7 +112,7 @@ void SkScan::HairLine(const SkPoint& pt0, const SkPoint& pt1, const SkRegion* cl
return;
SkFixed slope = SkFixedDiv(dx, dy);
- SkFixed startX = SkFDot6ToFixed(x0 + SkFixedMul(slope, (32 - y0) & 63));
+ SkFixed startX = SkFDot6ToFixed(x0) + (slope * ((32 - y0) & 63) >> 6);
vertline(iy0, iy1, startX, slope, blitter);
}
@@ -165,6 +165,25 @@ static bool quad_too_curvy(const SkPoint pts[3])
return true;
}
+static int compute_int_quad_dist(const SkPoint pts[3]) {
+ // compute the vector between the control point ([1]) and the middle of the
+ // line connecting the start and end ([0] and [2])
+ SkScalar dx = SkScalarHalf(pts[0].fX + pts[2].fX) - pts[1].fX;
+ SkScalar dy = SkScalarHalf(pts[0].fY + pts[2].fY) - pts[1].fY;
+ // we want everyone to be positive
+ dx = SkScalarAbs(dx);
+ dy = SkScalarAbs(dy);
+ // convert to whole pixel values (use ceiling to be conservative)
+ int idx = SkScalarCeil(dx);
+ int idy = SkScalarCeil(dy);
+ // use the cheap approx for distance
+ if (idx > idy) {
+ return idx + (idy >> 1);
+ } else {
+ return idy + (idx >> 1);
+ }
+}
+
static void hairquad(const SkPoint pts[3], const SkRegion* clip, SkBlitter* blitter, int level,
void (*lineproc)(const SkPoint&, const SkPoint&, const SkRegion* clip, SkBlitter*))
{
@@ -180,8 +199,19 @@ static void hairquad(const SkPoint pts[3], const SkRegion* clip, SkBlitter* blit
else
lineproc(pts[0], pts[2], clip, blitter);
#else
- lineproc(pts[0], pts[1], clip, blitter);
- lineproc(pts[1], pts[2], clip, blitter);
+ int count = 1 << level;
+ const SkScalar dt = SkFixedToScalar(SK_Fixed1 >> level);
+ SkScalar t = dt;
+ SkPoint prevPt = pts[0];
+ for (int i = 1; i < count; i++) {
+ SkPoint nextPt;
+ SkEvalQuadAt(pts, t, &nextPt);
+ lineproc(prevPt, nextPt, clip, blitter);
+ t += dt;
+ prevPt = nextPt;
+ }
+ // draw the last line explicitly to 1.0, in case t didn't match that exactly
+ lineproc(prevPt, pts[2], clip, blitter);
#endif
}
@@ -244,9 +274,22 @@ static void hair_path(const SkPath& path, const SkRegion* clip, SkBlitter* blitt
case SkPath::kLine_Verb:
lineproc(pts[0], pts[1], clip, blitter);
break;
- case SkPath::kQuad_Verb:
- hairquad(pts, clip, blitter, kMaxQuadSubdivideLevel, lineproc);
+ case SkPath::kQuad_Verb: {
+ int d = compute_int_quad_dist(pts);
+ /* quadratics approach the line connecting their start and end points
+ 4x closer with each subdivision, so we compute the number of
+ subdivisions to be the minimum need to get that distance to be less
+ than a pixel.
+ */
+ int level = (33 - SkCLZ(d)) >> 1;
+// SkDebugf("----- distance %d computedLevel %d\n", d, computedLevel);
+ // sanity check on level (from the previous version)
+ if (level > kMaxQuadSubdivideLevel) {
+ level = kMaxQuadSubdivideLevel;
+ }
+ hairquad(pts, clip, blitter, level, lineproc);
break;
+ }
case SkPath::kCubic_Verb:
haircubic(pts, clip, blitter, kMaxCubicSubdivideLevel, lineproc);
break;
diff --git a/skia/sgl/SkScan_Path.cpp b/skia/sgl/SkScan_Path.cpp
index 43a61bd..8b58991 100644
--- a/skia/sgl/SkScan_Path.cpp
+++ b/skia/sgl/SkScan_Path.cpp
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkScan_Path.cpp
**
-** Copyright 2006, Google Inc.
+** 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.
@@ -23,15 +23,15 @@
#include "SkRegion.h"
#include "SkTemplates.h"
-#define kEDGE_HEAD_Y SK_MinS16
-#define kEDGE_TAIL_Y SK_MaxS16
+#define kEDGE_HEAD_Y SK_MinS32
+#define kEDGE_TAIL_Y SK_MaxS32
#ifdef SK_DEBUG
static void validate_sort(const SkEdge* edge)
{
int y = kEDGE_HEAD_Y;
- while (edge->fFirstY != SK_MaxS16)
+ while (edge->fFirstY != SK_MaxS32)
{
edge->validate();
SkASSERT(y <= edge->fFirstY);
@@ -368,7 +368,7 @@ extern "C" {
valuea = edgea->fX;
valueb = edgeb->fX;
}
- return valuea > valueb ? 1 : valuea < valueb ? -1 : 0;
+ return valuea - valueb;
}
}
@@ -387,7 +387,6 @@ static SkEdge* sort_edges(SkEdge* list[], int count, SkEdge** last)
return list[0];
}
-#ifdef SK_DEBUG
/* 'quick' computation of the max sized needed to allocated for
our edgelist.
*/
@@ -423,7 +422,6 @@ static int worst_case_edge_count(const SkPath& path, size_t* storage)
*storage = size;
return edgeCount;
}
-#endif
/* Much faster than worst_case_edge_count, but over estimates even more
*/
diff --git a/skia/sgl/SkShader.cpp b/skia/sgl/SkShader.cpp
index 9a90959..dd9c859 100644
--- a/skia/sgl/SkShader.cpp
+++ b/skia/sgl/SkShader.cpp
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkShader.cpp
**
-** Copyright 2006, Google Inc.
+** 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.
diff --git a/skia/sgl/SkSpriteBlitter.h b/skia/sgl/SkSpriteBlitter.h
index 7447389..9f7764d 100644
--- a/skia/sgl/SkSpriteBlitter.h
+++ b/skia/sgl/SkSpriteBlitter.h
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkSpriteBlitter.h
**
-** Copyright 2006, Google Inc.
+** 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.
diff --git a/skia/sgl/SkSpriteBlitterTemplate.h b/skia/sgl/SkSpriteBlitterTemplate.h
index 267931e..2ab2b3a 100644
--- a/skia/sgl/SkSpriteBlitterTemplate.h
+++ b/skia/sgl/SkSpriteBlitterTemplate.h
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkSpriteBlitterTemplate.h
**
-** Copyright 2006, Google Inc.
+** 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.
diff --git a/skia/sgl/SkSpriteBlitter_ARGB32.cpp b/skia/sgl/SkSpriteBlitter_ARGB32.cpp
index ede7450..6addde7 100644
--- a/skia/sgl/SkSpriteBlitter_ARGB32.cpp
+++ b/skia/sgl/SkSpriteBlitter_ARGB32.cpp
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkSpriteBlitter_ARGB32.cpp
**
-** Copyright 2006, Google Inc.
+** 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.
diff --git a/skia/sgl/SkSpriteBlitter_RGB16.cpp b/skia/sgl/SkSpriteBlitter_RGB16.cpp
index 3ffea44..a158637 100644
--- a/skia/sgl/SkSpriteBlitter_RGB16.cpp
+++ b/skia/sgl/SkSpriteBlitter_RGB16.cpp
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkSpriteBlitter_RGB16.cpp
**
-** Copyright 2006, Google Inc.
+** 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.
@@ -24,12 +24,7 @@
#define D16_S32A_Opaque_Pixel(dst, sc) \
do { \
if (sc) { \
- unsigned sa = SkGetPackedA32(sc); \
- unsigned result = SkPixel32ToPixel16(sc); \
- if (sa != 0xFF) { \
- result += SkAlphaMulRGB16_ToU16(*dst, SkAlpha255To256(255 - sa)); \
- } \
- *dst = SkToU16(result); \
+ *dst = SkSrcOver32To16(sc, *dst); \
} \
} while (0)
diff --git a/skia/sgl/SkString.cpp b/skia/sgl/SkString.cpp
index 839f5c4..c683e35 100644
--- a/skia/sgl/SkString.cpp
+++ b/skia/sgl/SkString.cpp
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkString.cpp
**
-** Copyright 2006, Google Inc.
+** 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.
@@ -107,7 +107,10 @@ char* SkStrAppendScalar(char string[], SkScalar value)
const uint16_t* tens = gTens;
x = SkFixedRound(frac * 10000);
- SkASSERT(x < 10000);
+ SkASSERT(x <= 10000);
+ if (x == 10000) {
+ x -= 1;
+ }
*string++ = '.';
do {
unsigned powerOfTen = *tens++;
diff --git a/skia/sgl/SkStroke.cpp b/skia/sgl/SkStroke.cpp
index 530f0fa..86dff48 100644
--- a/skia/sgl/SkStroke.cpp
+++ b/skia/sgl/SkStroke.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006-2008 Google Inc.
+ * Copyright (C) 2006-2008 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.
@@ -528,15 +528,61 @@ void SkStroke::setJoin(SkPaint::Join join) {
fJoin = SkToU8(join);
}
+///////////////////////////////////////////////////////////////////////////////
+
+#ifdef SK_SCALAR_IS_FIXED
+ /* return non-zero if the path is too big, and should be shrunk to avoid
+ overflows during intermediate calculations. Note that we compute the
+ bounds for this. If we had a custom callback/walker for paths, we could
+ perhaps go faster by using that, and just perform the abs | in that
+ routine
+ */
+ static int needs_to_shrink(const SkPath& path) {
+ SkRect r;
+ path.computeBounds(&r, SkPath::kFast_BoundsType);
+ SkFixed mask = SkAbs32(r.fLeft);
+ mask |= SkAbs32(r.fTop);
+ mask |= SkAbs32(r.fRight);
+ mask |= SkAbs32(r.fBottom);
+ // we need the top 3 bits clear (after abs) to avoid overflow
+ return mask >> 29;
+ }
+
+ static void identity_proc(SkPoint pts[], int count) {}
+ static void shift_down_2_proc(SkPoint pts[], int count) {
+ for (int i = 0; i < count; i++) {
+ pts->fX >>= 2;
+ pts->fY >>= 2;
+ pts += 1;
+ }
+ }
+ #define APPLY_PROC(proc, pts, count) proc(pts, count)
+#else // float does need any of this
+ #define APPLY_PROC(proc, pts, count)
+#endif
+
void SkStroke::strokePath(const SkPath& src, SkPath* dst) const {
SkASSERT(&src != NULL && dst != NULL);
+ SkScalar radius = SkScalarHalf(fWidth);
+
dst->reset();
- if (SkScalarHalf(fWidth) <= 0) {
+ if (radius <= 0) {
return;
}
+
+#ifdef SK_SCALAR_IS_FIXED
+ void (*proc)(SkPoint pts[], int count) = identity_proc;
+ if (needs_to_shrink(src)) {
+ proc = shift_down_2_proc;
+ radius >>= 2;
+ if (radius == 0) {
+ return;
+ }
+ }
+#endif
- SkPathStroker stroker(SkScalarHalf(fWidth), fMiterLimit, this->getCap(),
+ SkPathStroker stroker(radius, fMiterLimit, this->getCap(),
this->getJoin());
SkPath::Iter iter(src, false);
@@ -546,17 +592,21 @@ void SkStroke::strokePath(const SkPath& src, SkPath* dst) const {
while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
switch (verb) {
case SkPath::kMove_Verb:
+ APPLY_PROC(proc, &pts[0], 1);
stroker.moveTo(pts[0]);
break;
case SkPath::kLine_Verb:
+ APPLY_PROC(proc, &pts[1], 1);
stroker.lineTo(pts[1]);
lastSegment = verb;
break;
case SkPath::kQuad_Verb:
+ APPLY_PROC(proc, &pts[1], 2);
stroker.quadTo(pts[1], pts[2]);
lastSegment = verb;
break;
case SkPath::kCubic_Verb:
+ APPLY_PROC(proc, &pts[1], 3);
stroker.cubicTo(pts[1], pts[2], pts[3]);
lastSegment = verb;
break;
@@ -569,6 +619,16 @@ void SkStroke::strokePath(const SkPath& src, SkPath* dst) const {
}
stroker.done(dst, lastSegment == SkPath::kLine_Verb);
+#ifdef SK_SCALAR_IS_FIXED
+ // undo our previous down_shift
+ if (shift_down_2_proc == proc) {
+ // need a real shift methid on path. antialias paths could use this too
+ SkMatrix matrix;
+ matrix.setScale(SkIntToScalar(4), SkIntToScalar(4));
+ dst->transform(matrix);
+ }
+#endif
+
if (fDoFill) {
dst->addPath(src);
}
diff --git a/skia/sgl/SkStrokerPriv.cpp b/skia/sgl/SkStrokerPriv.cpp
index 28276cb..07833ca 100644
--- a/skia/sgl/SkStrokerPriv.cpp
+++ b/skia/sgl/SkStrokerPriv.cpp
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkStrokerPriv.cpp
**
-** Copyright 2006, Google Inc.
+** 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.
diff --git a/skia/sgl/SkStrokerPriv.h b/skia/sgl/SkStrokerPriv.h
index 1d1eb89..ecb9bde 100644
--- a/skia/sgl/SkStrokerPriv.h
+++ b/skia/sgl/SkStrokerPriv.h
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkStrokerPriv.h
**
-** Copyright 2006, Google Inc.
+** 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.
diff --git a/skia/sgl/SkTSearch.cpp b/skia/sgl/SkTSearch.cpp
index 3a1a7d4..bab348f 100644
--- a/skia/sgl/SkTSearch.cpp
+++ b/skia/sgl/SkTSearch.cpp
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkTSearch.cpp
**
-** Copyright 2006, Google Inc.
+** 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.
diff --git a/skia/sgl/SkTSort.h b/skia/sgl/SkTSort.h
index 660b689..fba49e2 100644
--- a/skia/sgl/SkTSort.h
+++ b/skia/sgl/SkTSort.h
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkTSort.h
**
-** Copyright 2006, Google Inc.
+** 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.
diff --git a/skia/sgl/SkTemplatesPriv.h b/skia/sgl/SkTemplatesPriv.h
index 91ecd51..b0a95a0 100644
--- a/skia/sgl/SkTemplatesPriv.h
+++ b/skia/sgl/SkTemplatesPriv.h
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkTemplatesPriv.h
**
-** Copyright 2006, Google Inc.
+** 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.
diff --git a/skia/sgl/SkUtils.cpp b/skia/sgl/SkUtils.cpp
index 94834fd..4f5ba6ea 100644
--- a/skia/sgl/SkUtils.cpp
+++ b/skia/sgl/SkUtils.cpp
@@ -1,6 +1,6 @@
/* libs/graphics/sgl/SkUtils.cpp
**
-** Copyright 2006, Google Inc.
+** 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.
@@ -427,12 +427,10 @@ size_t SkUTF16_ToUTF8(const uint16_t utf16[], int numberOf16BitValues, char utf8
#include <stdlib.h>
-#if 0
static int round_to_K(size_t bytes)
{
return (bytes + 512) >> 10;
}
-#endif
SkAutoMemoryUsageProbe::SkAutoMemoryUsageProbe(const char label[])
: fLabel(label)
diff --git a/skia/sgl/SkWriter32.cpp b/skia/sgl/SkWriter32.cpp
index 819803f..61d0051 100644
--- a/skia/sgl/SkWriter32.cpp
+++ b/skia/sgl/SkWriter32.cpp
@@ -37,6 +37,15 @@ struct SkWriter32::Block {
}
};
+static size_t compute_block_size(size_t currSize, size_t minSize)
+{
+ if (currSize < minSize)
+ currSize = minSize;
+
+ currSize += (currSize >> 1);
+ return SkAlign4(currSize);
+}
+
///////////////////////////////////////////////////////////////////////////////
SkWriter32::~SkWriter32()
diff --git a/skia/sgl/SkXfermode.cpp b/skia/sgl/SkXfermode.cpp
index 6225e6e..e8a202d 100644
--- a/skia/sgl/SkXfermode.cpp
+++ b/skia/sgl/SkXfermode.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 Google Inc.
+ * Copyright (C) 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.
@@ -30,6 +30,19 @@ static SkPMColor SkFourByteInterp(SkPMColor src, SkPMColor dst, U8CPU alpha) {
return SkPackARGB32(a, r, g, b);
}
+// idea for higher precision blends in xfer procs (and slightly faster)
+// see DstATop as a probable caller
+static U8CPU mulmuldiv255round(U8CPU a, U8CPU b, U8CPU c, U8CPU d) {
+ SkASSERT(a <= 255);
+ SkASSERT(b <= 255);
+ SkASSERT(c <= 255);
+ SkASSERT(d <= 255);
+ unsigned prod = SkMulS16(a, b) + SkMulS16(c, d) + 128;
+ unsigned result = (prod + (prod >> 8)) >> 8;
+ SkASSERT(result <= 255);
+ return result;
+}
+
///////////////////////////////////////////////////////////////////////////////
bool SkXfermode::asCoeff(Coeff* src, Coeff* dst) {