static void test_gradient(skiatest::Reporter* reporter) { SkPoint pts[2]; pts[0].iset(0, 0); pts[1].iset(1, 0); SkColor colors[2]; SkScalar pos[2] = {SkIntToScalar(0), SkIntToScalar(1)}; int count = 2; SkShader::TileMode mode = SkShader::kClamp_TileMode; // test 1: all opaque colors[0] = SkColorSetARGB(0xFF, 0, 0, 0); colors[1] = SkColorSetARGB(0xFF, 0, 0, 0); SkShader* grad = SkGradientShader::CreateLinear(pts, colors, pos, count, mode); REPORTER_ASSERT(reporter, grad); REPORTER_ASSERT(reporter, grad->isOpaque()); grad->unref(); // test 2: all 0 alpha colors[0] = SkColorSetARGB(0, 0, 0, 0); colors[1] = SkColorSetARGB(0, 0, 0, 0); grad = SkGradientShader::CreateLinear(pts, colors, pos, count, mode); REPORTER_ASSERT(reporter, grad); REPORTER_ASSERT(reporter, !grad->isOpaque()); grad->unref(); // test 3: one opaque, one transparent colors[0] = SkColorSetARGB(0xFF, 0, 0, 0); colors[1] = SkColorSetARGB(0x40, 0, 0, 0); grad = SkGradientShader::CreateLinear(pts, colors, pos, count, mode); REPORTER_ASSERT(reporter, grad); REPORTER_ASSERT(reporter, !grad->isOpaque()); grad->unref(); // test 4: test 3, swapped colors[0] = SkColorSetARGB(0x40, 0, 0, 0); colors[1] = SkColorSetARGB(0xFF, 0, 0, 0); grad = SkGradientShader::CreateLinear(pts, colors, pos, count, mode); REPORTER_ASSERT(reporter, grad); REPORTER_ASSERT(reporter, !grad->isOpaque()); grad->unref(); }
static void test_bitmap(skiatest::Reporter* reporter) { SkImageInfo info = SkImageInfo::MakeN32Premul(2, 2); SkBitmap bmp; bmp.setConfig(info); // test 1: bitmap without pixel data SkShader* shader = SkShader::CreateBitmapShader(bmp, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode); REPORTER_ASSERT(reporter, shader); REPORTER_ASSERT(reporter, !shader->isOpaque()); shader->unref(); // From this point on, we have pixels bmp.allocPixels(info); // test 2: not opaque by default shader = SkShader::CreateBitmapShader(bmp, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode); REPORTER_ASSERT(reporter, shader); REPORTER_ASSERT(reporter, !shader->isOpaque()); shader->unref(); // test 3: explicitly opaque bmp.setAlphaType(kOpaque_SkAlphaType); shader = SkShader::CreateBitmapShader(bmp, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode); REPORTER_ASSERT(reporter, shader); REPORTER_ASSERT(reporter, shader->isOpaque()); shader->unref(); // test 4: explicitly not opaque bmp.setAlphaType(kPremul_SkAlphaType); shader = SkShader::CreateBitmapShader(bmp, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode); REPORTER_ASSERT(reporter, shader); REPORTER_ASSERT(reporter, !shader->isOpaque()); shader->unref(); }
// Returns true if all pixels painted will be opaque. static inline bool paintIsOpaque(const SkPaint& paint, const SkBitmap* bitmap = 0, bool checkFillOnly = false) { if (paint.getAlpha() < 0xFF) return false; if (!checkFillOnly && paint.getStyle() != SkPaint::kFill_Style && paint.isAntiAlias()) return false; SkShader* shader = paint.getShader(); if (shader && !shader->isOpaque()) return false; if (bitmap && !bitmap->isOpaque()) return false; if (paint.getLooper()) return false; if (paint.getImageFilter()) return false; if (paint.getMaskFilter()) return false; SkColorFilter* colorFilter = paint.getColorFilter(); if (colorFilter && !(colorFilter->getFlags() & SkColorFilter::kAlphaUnchanged_Flag)) return false; return true; }
SkBlitter* SkRasterPipelineBlitter::Create(const SkPixmap& dst, const SkPaint& paint, const SkMatrix& ctm, SkArenaAlloc* alloc) { auto blitter = alloc->make<SkRasterPipelineBlitter>( dst, paint.getBlendMode(), SkPM4f_from_SkColor(paint.getColor(), dst.colorSpace())); SkBlendMode* blend = &blitter->fBlend; SkPM4f* paintColor = &blitter->fPaintColor; SkRasterPipeline* pipeline = &blitter->fShader; SkShader* shader = paint.getShader(); SkColorFilter* colorFilter = paint.getColorFilter(); // TODO: all temporary if (!supported(dst.info()) || !SkBlendMode_AppendStages(*blend)) { return nullptr; } bool is_opaque = paintColor->a() == 1.0f, is_constant = true; if (shader) { pipeline->append(SkRasterPipeline::seed_shader, &blitter->fCurrentY); if (!shader->appendStages(pipeline, dst.colorSpace(), alloc, ctm, paint)) { return nullptr; } if (!is_opaque) { pipeline->append(SkRasterPipeline::scale_1_float, &paintColor->fVec[SkPM4f::A]); } is_opaque = is_opaque && shader->isOpaque(); is_constant = shader->isConstant(); } else { pipeline->append(SkRasterPipeline::constant_color, paintColor); } if (colorFilter) { if (!colorFilter->appendStages(pipeline, dst.colorSpace(), alloc, is_opaque)) { return nullptr; } is_opaque = is_opaque && (colorFilter->getFlags() & SkColorFilter::kAlphaUnchanged_Flag); } if (is_constant) { pipeline->append(SkRasterPipeline::store_f32, &paintColor); pipeline->run(0,1); *pipeline = SkRasterPipeline(); pipeline->append(SkRasterPipeline::constant_color, paintColor); is_opaque = paintColor->a() == 1.0f; } if (is_opaque && *blend == SkBlendMode::kSrcOver) { *blend = SkBlendMode::kSrc; } if (is_constant && *blend == SkBlendMode::kSrc) { SkRasterPipeline p; p.extend(*pipeline); blitter->fDstPtr = &blitter->fMemsetColor; blitter->append_store(&p); p.run(0,1); blitter->fCanMemsetInBlitH = true; } return blitter; }