/* Hit a few SkPicture::Analysis cases not handled elsewhere. */ static void test_analysis(skiatest::Reporter* reporter) { SkPictureRecorder recorder; SkCanvas* canvas = recorder.beginRecording(100, 100); { canvas->drawRect(SkRect::MakeWH(10, 10), SkPaint ()); } SkAutoTUnref<SkPicture> picture(recorder.endRecording()); REPORTER_ASSERT(reporter, !picture->willPlayBackBitmaps()); canvas = recorder.beginRecording(100, 100); { SkPaint paint; // CreateBitmapShader is too smart for us; an empty (or 1x1) bitmap shader // gets optimized into a non-bitmap form, so we create a 2x2 bitmap here. SkBitmap bitmap; bitmap.allocPixels(SkImageInfo::MakeN32Premul(2, 2)); bitmap.eraseColor(SK_ColorBLUE); *(bitmap.getAddr32(0, 0)) = SK_ColorGREEN; SkShader* shader = SkShader::CreateBitmapShader(bitmap, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode); paint.setShader(shader)->unref(); REPORTER_ASSERT(reporter, shader->asABitmap(NULL, NULL, NULL) == SkShader::kDefault_BitmapType); canvas->drawRect(SkRect::MakeWH(10, 10), paint); } picture.reset(recorder.endRecording()); REPORTER_ASSERT(reporter, picture->willPlayBackBitmaps()); }
SkPDFShader::State::State(const SkShader& shader, const SkMatrix& canvasTransform, const SkIRect& bbox) : fCanvasTransform(canvasTransform), fBBox(bbox), fPixelGeneration(0) { fInfo.fColorCount = 0; fInfo.fColors = NULL; fInfo.fColorOffsets = NULL; shader.getLocalMatrix(&fShaderTransform); fImageTileModes[0] = fImageTileModes[1] = SkShader::kClamp_TileMode; fType = shader.asAGradient(&fInfo); if (fType == SkShader::kNone_GradientType) { SkShader::BitmapType bitmapType; SkMatrix matrix; bitmapType = shader.asABitmap(&fImage, &matrix, fImageTileModes, NULL); if (bitmapType != SkShader::kDefault_BitmapType) { fImage.reset(); return; } SkASSERT(matrix.isIdentity()); fPixelGeneration = fImage.getGenerationID(); } else { fColorData.set(sk_malloc_throw( fInfo.fColorCount * (sizeof(SkColor) + sizeof(SkScalar)))); fInfo.fColors = reinterpret_cast<SkColor*>(fColorData.get()); fInfo.fColorOffsets = reinterpret_cast<SkScalar*>(fInfo.fColors + fInfo.fColorCount); shader.asAGradient(&fInfo); } }
SkPDFShader::State::State(const SkShader& shader, const SkMatrix& canvasTransform, const SkIRect& bbox) : fCanvasTransform(canvasTransform), fBBox(bbox), fPixelGeneration(0) { fInfo.fColorCount = 0; fInfo.fColors = NULL; fInfo.fColorOffsets = NULL; fShaderTransform = shader.getLocalMatrix(); fImageTileModes[0] = fImageTileModes[1] = SkShader::kClamp_TileMode; fType = shader.asAGradient(&fInfo); if (fType == SkShader::kNone_GradientType) { SkShader::BitmapType bitmapType; SkMatrix matrix; bitmapType = shader.asABitmap(&fImage, &matrix, fImageTileModes); if (bitmapType != SkShader::kDefault_BitmapType) { fImage.reset(); return; } SkASSERT(matrix.isIdentity()); fPixelGeneration = fImage.getGenerationID(); } else { AllocateGradientInfoStorage(); shader.asAGradient(&fInfo); } }
void addBitmapFromPaint(const SkPaint& paint) { SkShader* shader = paint.getShader(); if (shader) { SkBitmap bm; if (shader->asABitmap(&bm, NULL, NULL)) { fPRSet->add(bm.pixelRef()); } } }
SkGLDevice::TexCache* SkGLDevice::setupGLPaintShader(const SkPaint& paint) { SkGL::SetPaint(paint); SkShader* shader = paint.getShader(); if (NULL == shader) { return NULL; } if (!shader->setContext(this->accessBitmap(false), paint, this->matrix())) { return NULL; } SkBitmap bitmap; SkMatrix matrix; SkShader::TileMode tileModes[2]; if (!shader->asABitmap(&bitmap, &matrix, tileModes)) { return NULL; } bitmap.lockPixels(); if (!bitmap.readyToDraw()) { return NULL; } // see if we've already cached the bitmap from the shader SkPoint max; GLuint name; TexCache* cache = SkGLDevice::LockTexCache(bitmap, &name, &max); // the lock has already called glBindTexture for us SkGL::SetTexParams(paint.isFilterBitmap(), tileModes[0], tileModes[1]); // since our texture coords will be in local space, we wack the texture // matrix to map them back into 0...1 before we load it SkMatrix localM; if (shader->getLocalMatrix(&localM)) { SkMatrix inverse; if (localM.invert(&inverse)) { matrix.preConcat(inverse); } } matrix.postScale(max.fX / bitmap.width(), max.fY / bitmap.height()); glMatrixMode(GL_TEXTURE); SkGL::LoadMatrix(matrix); glMatrixMode(GL_MODELVIEW); // since we're going to use a shader/texture, we don't want the color, // just its alpha SkGL::SetAlpha(paint.getAlpha()); // report that we have setup the texture return cache; }
void addBitmapFromPaint(const SkPaint& paint) { SkShader* shader = paint.getShader(); if (shader) { SkBitmap bm; // Check whether the shader is a gradient in order to short-circuit // call to asABitmap to prevent generation of bitmaps from // gradient shaders, which implement asABitmap. if (SkShader::kNone_GradientType == shader->asAGradient(NULL) && shader->asABitmap(&bm, NULL, NULL)) { fPRSet->add(bm.pixelRef()); } } }
static bool should_draw_immediately(const SkBitmap* bitmap, const SkPaint* paint, size_t bitmapSizeThreshold) { if (bitmap && ((bitmap->getTexture() && !bitmap->isImmutable()) || (bitmap->getSize() > bitmapSizeThreshold))) { return true; } if (paint) { SkShader* shader = paint->getShader(); // Here we detect the case where the shader is an SkBitmapProcShader // with a gpu texture attached. Checking this without RTTI // requires making the assumption that only gradient shaders // and SkBitmapProcShader implement asABitmap(). The following // code may need to be revised if that assumption is ever broken. if (shader && !shader->asAGradient(NULL)) { SkBitmap bm; if (shader->asABitmap(&bm, NULL, NULL) && bm.getTexture()) { return true; } } } return false; }
SkPDFShader::State::State(const SkShader& shader, const SkMatrix& canvasTransform, const SkIRect& bbox, SkScalar rasterScale) : fCanvasTransform(canvasTransform), fBBox(bbox), fPixelGeneration(0) { fInfo.fColorCount = 0; fInfo.fColors = NULL; fInfo.fColorOffsets = NULL; fShaderTransform = shader.getLocalMatrix(); fImageTileModes[0] = fImageTileModes[1] = SkShader::kClamp_TileMode; fType = shader.asAGradient(&fInfo); if (fType == SkShader::kNone_GradientType) { SkShader::BitmapType bitmapType; SkMatrix matrix; bitmapType = shader.asABitmap(&fImage, &matrix, fImageTileModes); if (bitmapType != SkShader::kDefault_BitmapType) { // Generic fallback for unsupported shaders: // * allocate a bbox-sized bitmap // * shade the whole area // * use the result as a bitmap shader // bbox is in device space. While that's exactly what we want for sizing our bitmap, // we need to map it into shader space for adjustments (to match // SkPDFImageShader::Create's behavior). SkRect shaderRect = SkRect::Make(bbox); if (!inverse_transform_bbox(canvasTransform, &shaderRect)) { fImage.reset(); return; } // Clamp the bitmap size to about 1M pixels static const SkScalar kMaxBitmapArea = 1024 * 1024; SkScalar bitmapArea = rasterScale * bbox.width() * rasterScale * bbox.height(); if (bitmapArea > kMaxBitmapArea) { rasterScale *= SkScalarSqrt(SkScalarDiv(kMaxBitmapArea, bitmapArea)); } SkISize size = SkISize::Make(SkScalarRoundToInt(rasterScale * bbox.width()), SkScalarRoundToInt(rasterScale * bbox.height())); SkSize scale = SkSize::Make(SkIntToScalar(size.width()) / shaderRect.width(), SkIntToScalar(size.height()) / shaderRect.height()); fImage.allocN32Pixels(size.width(), size.height()); fImage.eraseColor(SK_ColorTRANSPARENT); SkPaint p; p.setShader(const_cast<SkShader*>(&shader)); SkCanvas canvas(fImage); canvas.scale(scale.width(), scale.height()); canvas.translate(-shaderRect.x(), -shaderRect.y()); canvas.drawPaint(p); fShaderTransform.setTranslate(shaderRect.x(), shaderRect.y()); fShaderTransform.preScale(1 / scale.width(), 1 / scale.height()); } else { SkASSERT(matrix.isIdentity()); } fPixelGeneration = fImage.getGenerationID(); } else { AllocateGradientInfoStorage(); shader.asAGradient(&fInfo); } }
void SkGLDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode, int vertexCount, const SkPoint vertices[], const SkPoint texs[], const SkColor colors[], SkXfermode* xmode, const uint16_t indices[], int indexCount, const SkPaint& paint) { if (false) { SkRect bounds; SkIRect ibounds; bounds.set(vertices, vertexCount); bounds.round(&ibounds); SkDebugf("---- drawverts: %d pts, texs=%d colors=%d indices=%d bounds [%d %d]\n", vertexCount, texs!=0, colors!=0, indexCount, ibounds.width(), ibounds.height()); } SkGLClipIter* iter = this->updateMatrixClip(); SkGL::SetPaint(paint); const SkGLVertex* glVerts; const SkGLVertex* glTexs = NULL; #if GLSCALAR_IS_SCALAR glVerts = (const SkGLVertex*)vertices; #else SkAutoSTMalloc<32, SkGLVertex> storage(vertexCount); storage.get()->setPoints(vertices, vertexCount); glVerts = storage.get(); #endif uint8_t* colorArray = NULL; if (colors) { colorArray = (uint8_t*)sk_malloc_throw(vertexCount*4); SkGL::SetRGBA(colorArray, colors, vertexCount); } SkAutoFree afca(colorArray); SkGLVertex* texArray = NULL; TexCache* cache = NULL; if (texs && paint.getShader()) { SkShader* shader = paint.getShader(); // if (!shader->setContext(this->accessBitmap(), paint, *draw.fMatrix)) { if (!shader->setContext(*draw.fBitmap, paint, *draw.fMatrix)) { goto DONE; } SkBitmap bitmap; SkMatrix matrix; SkShader::TileMode tileModes[2]; if (shader->asABitmap(&bitmap, &matrix, tileModes)) { SkPoint max; GLuint name; cache = SkGLDevice::LockTexCache(bitmap, &name, &max); if (NULL == cache) { return; } matrix.postScale(max.fX / bitmap.width(), max.fY / bitmap.height()); glMatrixMode(GL_TEXTURE); SkGL::LoadMatrix(matrix); glMatrixMode(GL_MODELVIEW); #if GLSCALAR_IS_SCALAR glTexs = (const SkGLVertex*)texs; #else texArray = (SkGLVertex*)sk_malloc_throw(vertexCount * sizeof(SkGLVertex)); texArray->setPoints(texs, vertexCount); glTexs = texArray; #endif SkGL::SetPaintAlpha(paint); SkGL::SetTexParams(paint.isFilterBitmap(), tileModes[0], tileModes[1]); } } DONE: SkAutoFree aftex(texArray); SkGL::DrawVertices(indices ? indexCount : vertexCount, gVertexModeToGL[vmode], glVerts, glTexs, colorArray, indices, iter); if (cache) { SkGLDevice::UnlockTexCache(cache); } }