fix overflow in matrixproc, and add debugging code to test that

git-svn-id: http://skia.googlecode.com/svn/trunk@548 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
reed@android.com 2010-04-14 13:36:33 +00:00
Родитель c846ede6a0
Коммит 258cb228c6
4 изменённых файлов: 36 добавлений и 11 удалений

Просмотреть файл

@ -137,6 +137,15 @@ bool SkBitmapProcShader::setContext(const SkBitmap& device,
#define BUF_MAX 128 #define BUF_MAX 128
#define TEST_BUFFER_OVERRITEx
#ifdef TEST_BUFFER_OVERRITE
#define TEST_BUFFER_EXTRA 32
#define TEST_PATTERN 0x88888888
#else
#define TEST_BUFFER_EXTRA 0
#endif
void SkBitmapProcShader::shadeSpan(int x, int y, SkPMColor dstC[], int count) { void SkBitmapProcShader::shadeSpan(int x, int y, SkPMColor dstC[], int count) {
const SkBitmapProcState& state = fState; const SkBitmapProcState& state = fState;
if (state.fShaderProc32) { if (state.fShaderProc32) {
@ -144,10 +153,10 @@ void SkBitmapProcShader::shadeSpan(int x, int y, SkPMColor dstC[], int count) {
return; return;
} }
uint32_t buffer[BUF_MAX]; uint32_t buffer[BUF_MAX + TEST_BUFFER_EXTRA];
SkBitmapProcState::MatrixProc mproc = state.fMatrixProc; SkBitmapProcState::MatrixProc mproc = state.fMatrixProc;
SkBitmapProcState::SampleProc32 sproc = state.fSampleProc32; SkBitmapProcState::SampleProc32 sproc = state.fSampleProc32;
int max = fState.maxCountForBufferSize(sizeof(buffer)); int max = fState.maxCountForBufferSize(sizeof(buffer[0]) * BUF_MAX);
SkASSERT(state.fBitmap->getPixels()); SkASSERT(state.fBitmap->getPixels());
SkASSERT(state.fBitmap->pixelRef() == NULL || SkASSERT(state.fBitmap->pixelRef() == NULL ||
@ -158,12 +167,24 @@ void SkBitmapProcShader::shadeSpan(int x, int y, SkPMColor dstC[], int count) {
if (n > max) { if (n > max) {
n = max; n = max;
} }
SkASSERT(n > 0 && n < BUF_MAX*2);
#ifdef TEST_BUFFER_OVERRITE
for (int i = 0; i < TEST_BUFFER_EXTRA; i++) {
buffer[BUF_MAX + i] = TEST_PATTERN;
}
#endif
mproc(state, buffer, n, x, y); mproc(state, buffer, n, x, y);
#ifdef TEST_BUFFER_OVERRITE
for (int j = 0; j < TEST_BUFFER_EXTRA; j++) {
SkASSERT(buffer[BUF_MAX + j] == TEST_PATTERN);
}
#endif
sproc(state, buffer, n, dstC); sproc(state, buffer, n, dstC);
if ((count -= n) == 0) { if ((count -= n) == 0) {
break; break;
} }
SkASSERT(count > 0);
x += n; x += n;
dstC += n; dstC += n;
} }

Просмотреть файл

@ -543,7 +543,6 @@ bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) {
*/ */
int SkBitmapProcState::maxCountForBufferSize(size_t bufferSize) const { int SkBitmapProcState::maxCountForBufferSize(size_t bufferSize) const {
int32_t size = static_cast<int32_t>(bufferSize); int32_t size = static_cast<int32_t>(bufferSize);
int perElemShift;
size &= ~3; // only care about 4-byte aligned chunks size &= ~3; // only care about 4-byte aligned chunks
if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) { if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) {
@ -551,11 +550,15 @@ int SkBitmapProcState::maxCountForBufferSize(size_t bufferSize) const {
if (size < 0) { if (size < 0) {
size = 0; size = 0;
} }
perElemShift = fDoFilter ? 2 : 1; size >>= 1;
} else { } else {
perElemShift = fDoFilter ? 3 : 2; size >>= 2;
} }
return size >> perElemShift; if (fDoFilter) {
size >>= 1;
}
return size;
} }

Просмотреть файл

@ -91,10 +91,11 @@ struct SkBitmapProcState {
*/ */
void platformProcs(); void platformProcs();
/** Given the size of a buffer, to be used for calling the matrix and /** Given the byte size of the index buffer to be passed to the matrix proc,
sample procs, this return the maximum count that can be stored in the return the maximum number of resulting pixels that can be computed
buffer, taking into account that filtering and scale-vs-affine affect (i.e. the number of SkPMColor values to be written by the sample proc).
this value. This routine takes into account that filtering and scale-vs-affine
affect the amount of buffer space needed.
Only valid to call after chooseProcs (setContext) has been called. It is Only valid to call after chooseProcs (setContext) has been called. It is
safe to call this inside the shader's shadeSpan() method. safe to call this inside the shader's shadeSpan() method.

Просмотреть файл

@ -368,7 +368,7 @@ static void clampx_nofilter_trans(const SkBitmapProcState& s,
} }
// fill the remaining with the max value // fill the remaining with the max value
sk_memset16(xptr, width - 1, count * sizeof(uint16_t)); sk_memset16(xptr, width - 1, count);
} }
static void repeatx_nofilter_trans(const SkBitmapProcState& s, static void repeatx_nofilter_trans(const SkBitmapProcState& s,