void WebMediaPlayerClientImpl::paintOnAndroid(WebCore::GraphicsContext* context, const IntRect& rect, uint8_t alpha) { OwnPtr<blink::WebGraphicsContext3DProvider> provider = adoptPtr(blink::Platform::current()->createSharedOffscreenGraphicsContext3DProvider()); if (!provider) return; WebGraphicsContext3D* context3D = provider->context3d(); if (!context || !context3D || !m_webMediaPlayer || context->paintingDisabled()) return; if (!context3D->makeContextCurrent()) return; // Copy video texture into a RGBA texture based bitmap first as video texture on Android is GL_TEXTURE_EXTERNAL_OES // which is not supported by Skia yet. The bitmap's size needs to be the same as the video and use naturalSize() here. // Check if we could reuse existing texture based bitmap. // Otherwise, release existing texture based bitmap and allocate a new one based on video size. if (!ensureTextureBackedSkBitmap(provider->grContext(), m_bitmap, m_webMediaPlayer->naturalSize(), kTopLeft_GrSurfaceOrigin, kSkia8888_GrPixelConfig)) return; // Copy video texture to bitmap texture. WebCanvas* canvas = context->canvas(); unsigned textureId = static_cast<unsigned>((m_bitmap.getTexture())->getTextureHandle()); if (!m_webMediaPlayer->copyVideoTextureToPlatformTexture(context3D, textureId, 0, GL_RGBA, GL_UNSIGNED_BYTE, true, false)) return; // Draw the texture based bitmap onto the Canvas. If the canvas is hardware based, this will do a GPU-GPU texture copy. If the canvas is software based, // the texture based bitmap will be readbacked to system memory then draw onto the canvas. SkRect dest; dest.set(rect.x(), rect.y(), rect.x() + rect.width(), rect.y() + rect.height()); SkPaint paint; paint.setAlpha(alpha); // It is not necessary to pass the dest into the drawBitmap call since all the context have been set up before calling paintCurrentFrameInContext. canvas->drawBitmapRect(m_bitmap, NULL, dest, &paint); }
static void paintSkBitmap(PlatformContextSkia* platformContext, const NativeImageSkia& bitmap, const SkIRect& srcRect, const SkRect& destRect, const SkXfermode::Mode& compOp) { SkPaint paint; paint.setXfermodeMode(compOp); paint.setFilterBitmap(true); int alpha = roundf(platformContext->getAlpha() * 256); if (alpha > 255) alpha = 255; else if (alpha < 0) alpha = 0; paint.setAlpha(alpha); skia::PlatformCanvas* canvas = platformContext->canvas(); ResamplingMode resampling = platformContext->isPrinting() ? RESAMPLE_NONE : computeResamplingMode(bitmap, srcRect.width(), srcRect.height(), SkScalarToFloat(destRect.width()), SkScalarToFloat(destRect.height())); if (resampling == RESAMPLE_AWESOME) { drawResampledBitmap(*canvas, paint, bitmap, srcRect, destRect); } else { // No resampling necessary, we can just draw the bitmap. We want to // filter it if we decided to do linear interpolation above, or if there // is something interesting going on with the matrix (like a rotation). // Note: for serialization, we will want to subset the bitmap first so // we don't send extra pixels. canvas->drawBitmapRect(bitmap, &srcRect, destRect, &paint); } }
void SkSVGRenderContext::applyOpacity(SkScalar opacity, uint32_t flags) { if (opacity >= 1) { return; } const bool hasFill = SkToBool(this->fillPaint()); const bool hasStroke = SkToBool(this->strokePaint()); // We can apply the opacity as paint alpha iif it only affects one atomic draw. // For now, this means a) the target node doesn't have any descendants, and // b) it only has a stroke or a fill (but not both). Going forward, we may need // to refine this heuristic (e.g. to accommodate markers). if ((flags & kLeaf) && (hasFill ^ hasStroke)) { auto* pctx = fPresentationContext.writable(); if (hasFill) { pctx->fFillPaint.setAlpha( SkScalarRoundToInt(opacity * pctx->fFillPaint.getAlpha())); } else { pctx->fStrokePaint.setAlpha( SkScalarRoundToInt(opacity * pctx->fStrokePaint.getAlpha())); } } else { // Expensive, layer-based fall back. SkPaint opacityPaint; opacityPaint.setAlpha(opacity_to_alpha(opacity)); // Balanced in the destructor, via restoreToCount(). fCanvas->saveLayer(nullptr, &opacityPaint); } }
static void paintSkBitmap(PlatformContextSkia* platformContext, const NativeImageSkia& bitmap, const SkIRect& srcRect, const SkRect& destRect, const SkXfermode::Mode& compOp) { #if PLATFORM(CHROMIUM) TRACE_EVENT("paintSkBitmap", platformContext, 0); #endif SkPaint paint; paint.setXfermodeMode(compOp); paint.setFilterBitmap(true); paint.setAlpha(platformContext->getNormalizedAlpha()); paint.setLooper(platformContext->getDrawLooper()); // only antialias if we're rotated or skewed paint.setAntiAlias(hasNon90rotation(platformContext)); SkCanvas* canvas = platformContext->canvas(); ResamplingMode resampling; if (platformContext->isAccelerated()) resampling = RESAMPLE_LINEAR; else resampling = platformContext->printing() ? RESAMPLE_NONE : computeResamplingMode(platformContext, bitmap, srcRect.width(), srcRect.height(), SkScalarToFloat(destRect.width()), SkScalarToFloat(destRect.height())); if (resampling == RESAMPLE_AWESOME) { drawResampledBitmap(*canvas, paint, bitmap, srcRect, destRect); } else { // No resampling necessary, we can just draw the bitmap. We want to // filter it if we decided to do linear interpolation above, or if there // is something interesting going on with the matrix (like a rotation). // Note: for serialization, we will want to subset the bitmap first so // we don't send extra pixels. canvas->drawBitmapRect(bitmap.bitmap(), &srcRect, destRect, &paint); } platformContext->didDrawRect(destRect, paint, &bitmap.bitmap()); }
RENDERTHREAD_OPENGL_PIPELINE_TEST(BakedOpDispatcher, onLayerOp_bufferless) { SkPaint layerPaint; layerPaint.setAlpha(128); OffscreenBuffer* buffer = nullptr; // no providing a buffer, should hit rect fallback case LayerOp op(Rect(10, 10), Matrix4::identity(), nullptr, &layerPaint, &buffer); testUnmergedGlopDispatch(renderThread, &op, [](const Glop& glop) { ADD_FAILURE() << "Nothing should happen"; }, 0); }
// Make sure our blits always map src==0 to a noop, and src==FF to full opaque static void test_00_FF(skiatest::Reporter* reporter) { static const int W = 256; static const SkBitmap::Config gDstConfig[] = { SkBitmap::kARGB_8888_Config, SkBitmap::kRGB_565_Config, // SkBitmap::kARGB_4444_Config, // SkBitmap::kA8_Config, }; static const struct { SkColor fSrc; SkColor fDst; SkPMColor fResult32; uint16_t fResult16; uint8_t fResult8; } gSrcRec[] = { { 0, 0, 0, 0, 0 }, { 0, 0xFFFFFFFF, SkPackARGB32(0xFF, 0xFF, 0xFF, 0xFF), 0xFFFF, 0xFF }, { 0xFFFFFFFF, 0, SkPackARGB32(0xFF, 0xFF, 0xFF, 0xFF), 0xFFFF, 0xFF }, { 0xFFFFFFFF, 0xFFFFFFFF, SkPackARGB32(0xFF, 0xFF, 0xFF, 0xFF), 0xFFFF, 0xFF }, }; SkPaint paint; SkBitmap srcBM; srcBM.setConfig(SkBitmap::kARGB_8888_Config, W, 1); srcBM.allocPixels(); for (size_t i = 0; i < SK_ARRAY_COUNT(gDstConfig); i++) { SkBitmap dstBM; dstBM.setConfig(gDstConfig[i], W, 1); dstBM.allocPixels(); SkCanvas canvas(dstBM); for (size_t j = 0; j < SK_ARRAY_COUNT(gSrcRec); j++) { srcBM.eraseColor(gSrcRec[j].fSrc); dstBM.eraseColor(gSrcRec[j].fDst); for (int k = 0; k < 4; k++) { bool dither = (k & 1) != 0; bool blend = (k & 2) != 0; if (gSrcRec[j].fSrc != 0 && blend) { // can't make a numerical promise about blending anything // but 0 // continue; } paint.setDither(dither); paint.setAlpha(blend ? 0x80 : 0xFF); canvas.drawBitmap(srcBM, 0, 0, &paint); if (!check_color(dstBM, gSrcRec[j].fResult32, gSrcRec[j].fResult16, gSrcRec[j].fResult8, reporter)) { SkDebugf("--- src index %d dither %d blend %d\n", j, dither, blend); } } } } }
static void r1(SkLayerRasterizer* rast, SkPaint& p) { rast->addLayer(p); p.setAlpha(0x40); p.setXfermodeMode(SkXfermode::kSrc_Mode); p.setStyle(SkPaint::kStroke_Style); p.setStrokeWidth(SK_Scalar1*2); rast->addLayer(p); }
static inline void drawInnerPath(PlatformContextSkia* context, const SkPath& path, SkPaint& paint, int width) { #if PLATFORM(CHROMIUM) && OS(DARWIN) paint.setAlpha(128); paint.setStrokeWidth(width * 0.5f); context->canvas()->drawPath(path, paint); context->didDrawPath(path, paint); #endif }
virtual void onDraw(SkCanvas* canvas) { SkShader* s = SkShader::CreateBitmapShader(fBM, SkShader::kRepeat_TileMode, SkShader::kMirror_TileMode); SkPaint paint; paint.setAlpha(0x80); paint.setShader(s)->unref(); canvas->drawPaint(paint); }
ShaderMaskBench(void* param, bool isOpaque, FontQuality fq) : INHERITED(param) { fFQ = fq; fText.set(STR); fPaint.setAntiAlias(kBW != fq); fPaint.setLCDRenderText(kLCD == fq); fPaint.setAlpha(isOpaque ? 0xFF : 0x80); fPaint.setShader(new SkColorShader)->unref(); }
void draw_mode(SkCanvas* canvas, SkXfermode* mode, int alpha, SkScalar x, SkScalar y) { SkPaint p; canvas->drawBitmap(fSrcB, x, y, &p); p.setAlpha(alpha); p.setXfermode(mode); canvas->drawBitmap(fDstB, x, y, &p); }
static void r3(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) { p.setStyle(SkPaint::kStroke_Style); p.setStrokeWidth(SK_Scalar1*3); rastBuilder->addLayer(p); p.setAlpha(0x20); p.setStyle(SkPaint::kFill_Style); p.setXfermodeMode(SkXfermode::kSrc_Mode); rastBuilder->addLayer(p); }
virtual void onDraw(SkCanvas* canvas, SkScalar opacity) { SkRect r; r.set(0, 0, this->getWidth(), this->getHeight()); SkPaint paint; paint.setColor(fColor); paint.setAlpha(SkScalarRound(opacity * 255)); canvas->drawRect(r, paint); }
static void initPaint(SkPaint& paint) { // Make sure the paint is opaque, color, alpha, filter, etc. // will be applied later when compositing the alpha8 texture paint.setColor(SK_ColorBLACK); paint.setAlpha(255); paint.setColorFilter(NULL); paint.setMaskFilter(NULL); paint.setShader(NULL); SkXfermode* mode = SkXfermode::Create(SkXfermode::kSrc_Mode); SkSafeUnref(paint.setXfermode(mode)); }
void drawHairlines(SkCanvas* canvas, const SkPath& path, const SkPath& clipA, const SkPath& clipB) { SkPaint paint; paint.setAntiAlias(true); paint.setStyle(SkPaint::kStroke_Style); const SkAlpha fade = 0x33; // draw path in hairline paint.setColor(gPathColor); paint.setAlpha(fade); canvas->drawPath(path, paint); // draw clips in hair line paint.setColor(gClipAColor); paint.setAlpha(fade); canvas->drawPath(clipA, paint); paint.setColor(gClipBColor); paint.setAlpha(fade); canvas->drawPath(clipB, paint); }
static void r7(SkLayerRasterizer* rast, SkPaint& p, SkScalar interp) { p.setPathEffect(makepe(interp, NULL))->unref(); rast->addLayer(p); #if 0 p.setPathEffect(new InverseFillPE())->unref(); p.setXfermodeMode(SkXfermode::kSrcIn_Mode); p.setXfermodeMode(SkXfermode::kClear_Mode); p.setAlpha((1 - interp) * 255); rast->addLayer(p); #endif }
testrast() { SkPaint paint; paint.setAntiAlias(true); #if 0 paint.setStyle(SkPaint::kStroke_Style); paint.setStrokeWidth(SK_Scalar1*4); this->addLayer(paint); paint.setStrokeWidth(SK_Scalar1*1); paint.setXfermode(SkXfermode::kClear_Mode); this->addLayer(paint); #else paint.setAlpha(0x66); this->addLayer(paint, SkIntToScalar(4), SkIntToScalar(4)); paint.setAlpha(0xFF); this->addLayer(paint); #endif }
void PlatformGraphicsContextSkia::drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src, const SkRect& dst, CompositeOperator op) { SkPaint paint; setupPaintCommon(&paint); paint.setAlpha(getNormalizedAlpha()); paint.setXfermodeMode(WebCoreCompositeToSkiaComposite(op)); fixPaintForBitmapsThatMaySeam(&paint); mCanvas->drawBitmapRect(bitmap, src, dst, &paint); }
void onDraw(int loops, SkCanvas* canvas) override { SkRandom rand; SkPaint paint; this->setupPaint(&paint); paint.setFilterQuality(fFilterQuality); paint.setAlpha(fAlpha); for (int i = 0; i < loops; i++) { canvas->drawBitmapRect(fBitmap, fSrcR, fDstR, &paint, SkCanvas::kStrict_SrcRectConstraint); } }
void draw(SkCanvas* canvas) { SkPaint paint; SkPoint center = { 50, 50 }; SkScalar radius = 50; const SkColor colors[] = { 0xFFFFFFFF, 0xFF000000 }; paint.setShader(SkGradientShader::MakeRadial(center, radius, colors, nullptr, SK_ARRAY_COUNT(colors), SkTileMode::kClamp)); for (SkScalar a : { 0.3f, 0.6f, 1.0f } ) { paint.setAlpha((int) (a * 255)); canvas->drawCircle(center.fX, center.fY, radius, paint); canvas->translate(70, 70); } }
static inline void drawOuterPath(PlatformContextSkia* context, const SkPath& path, SkPaint& paint, int width) { #if PLATFORM(CHROMIUM) && OS(DARWIN) paint.setAlpha(64); paint.setStrokeWidth(width); paint.setPathEffect(new SkCornerPathEffect((width - 1) * 0.5f))->unref(); #else paint.setStrokeWidth(1); paint.setPathEffect(new SkCornerPathEffect(1))->unref(); #endif context->canvas()->drawPath(path, paint); context->didDrawPath(path, paint); }
static SkScalar drawCell(SkCanvas* canvas, SkBlendMode mode, SkAlpha a0, SkAlpha a1) { SkPaint paint; paint.setAntiAlias(true); SkRect r = SkRect::MakeWH(W, H); r.inset(W/10, H/10); paint.setColor(SK_ColorBLUE); paint.setAlpha(a0); canvas->drawOval(r, paint); paint.setColor(SK_ColorRED); paint.setAlpha(a1); paint.setBlendMode(mode); for (int angle = 0; angle < 24; ++angle) { SkScalar x = SkScalarCos(SkIntToScalar(angle) * (SK_ScalarPI * 2) / 24) * gWidth; SkScalar y = SkScalarSin(SkIntToScalar(angle) * (SK_ScalarPI * 2) / 24) * gHeight; paint.setStrokeWidth(SK_Scalar1 * angle * 2 / 24); canvas->drawLine(W/2, H/2, W/2 + x, H/2 + y, paint); } return H; }
static void run_test(SkWStream* out, SkBlendMode mode, U8CPU alpha) { sk_sp<SkDocument> pdfDoc(SkDocument::MakePDF(out)); SkCanvas* c = pdfDoc->beginPage(612.0f, 792.0f); SkPaint black; SkPaint background; background.setColor(SK_ColorWHITE); background.setAlpha(alpha); background.setBlendMode(mode); c->drawRect(SkRect::MakeWH(612.0f, 792.0f), background); c->drawRect(SkRect::MakeXYWH(36.0f, 36.0f, 9.0f, 9.0f), black); c->drawRect(SkRect::MakeXYWH(72.0f, 72.0f, 468.0f, 648.0f), background); c->drawRect(SkRect::MakeXYWH(108.0f, 108.0f, 9.0f, 9.0f), black); pdfDoc->close(); }
static void paintSkBitmap(PlatformContextSkia* platformContext, const NativeImageSkia& bitmap, const SkIRect& srcRect, const SkRect& destRect, const SkXfermode::Mode& compOp) { #if PLATFORM(CHROMIUM) TRACE_EVENT0("skia", "paintSkBitmap"); #endif SkPaint paint; paint.setXfermodeMode(compOp); paint.setAlpha(platformContext->getNormalizedAlpha()); paint.setLooper(platformContext->getDrawLooper()); // only antialias if we're rotated or skewed paint.setAntiAlias(hasNon90rotation(platformContext)); SkCanvas* canvas = platformContext->canvas(); ResamplingMode resampling; if (platformContext->isAccelerated()) resampling = RESAMPLE_LINEAR; else if (platformContext->printing()) resampling = RESAMPLE_NONE; else { // Take into account scale applied to the canvas when computing sampling mode (e.g. CSS scale or page scale). SkRect destRectTarget = destRect; if (!(canvas->getTotalMatrix().getType() & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask))) canvas->getTotalMatrix().mapRect(&destRectTarget, destRect); resampling = computeResamplingMode(canvas->getTotalMatrix(), bitmap, srcRect.width(), srcRect.height(), SkScalarToFloat(destRectTarget.width()), SkScalarToFloat(destRectTarget.height())); } if (resampling == RESAMPLE_NONE) { // FIXME: This is to not break tests (it results in the filter bitmap flag // being set to true). We need to decide if we respect RESAMPLE_NONE // being returned from computeResamplingMode. resampling = RESAMPLE_LINEAR; } resampling = limitResamplingMode(platformContext, resampling); paint.setFilterBitmap(resampling == RESAMPLE_LINEAR); if (resampling == RESAMPLE_AWESOME) drawResampledBitmap(*canvas, paint, bitmap, srcRect, destRect); else { // No resampling necessary, we can just draw the bitmap. We want to // filter it if we decided to do linear interpolation above, or if there // is something interesting going on with the matrix (like a rotation). // Note: for serialization, we will want to subset the bitmap first so // we don't send extra pixels. canvas->drawBitmapRect(bitmap.bitmap(), &srcRect, destRect, &paint); } platformContext->didDrawRect(destRect, paint, &bitmap.bitmap()); }
void drawPlatformFocusRing(const PrimitiveType& primitive, SkCanvas* canvas, SkColor color, int width) { SkPaint paint; paint.setAntiAlias(true); paint.setStyle(SkPaint::kStroke_Style); paint.setColor(color); paint.setStrokeWidth(GraphicsContext::focusRingWidth(width)); #if OS(MACOSX) paint.setAlpha(64); const float cornerRadius = (width - 1) * 0.5f; #else const float cornerRadius = 1; #endif drawFocusRingPrimitive(primitive, canvas, paint, cornerRadius); #if OS(MACOSX) // Inner part paint.setAlpha(128); paint.setStrokeWidth(paint.getStrokeWidth() * 0.5f); drawFocusRingPrimitive(primitive, canvas, paint, cornerRadius); #endif }
static void r0(SkLayerRasterizer::Builder* rastBuilder, SkPaint& p) { p.setMaskFilter(SkBlurMaskFilter::Create(kNormal_SkBlurStyle, SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(3))))->unref(); rastBuilder->addLayer(p, SkIntToScalar(3), SkIntToScalar(3)); p.setMaskFilter(nullptr); p.setStyle(SkPaint::kStroke_Style); p.setStrokeWidth(SK_Scalar1); rastBuilder->addLayer(p); p.setAlpha(0x11); p.setStyle(SkPaint::kFill_Style); p.setXfermodeMode(SkXfermode::kSrc_Mode); rastBuilder->addLayer(p); }
static void r0(SkLayerRasterizer* rast, SkPaint& p) { p.setMaskFilter(SkBlurMaskFilter::Create(SkIntToScalar(3), SkBlurMaskFilter::kNormal_BlurStyle))->unref(); rast->addLayer(p, SkIntToScalar(3), SkIntToScalar(3)); p.setMaskFilter(NULL); p.setStyle(SkPaint::kStroke_Style); p.setStrokeWidth(SK_Scalar1); rast->addLayer(p); p.setAlpha(0x11); p.setStyle(SkPaint::kFill_Style); p.setXfermodeMode(SkXfermode::kSrc_Mode); rast->addLayer(p); }
void PlatformGraphicsContextSkia::drawBitmapPattern( const SkBitmap& bitmap, const SkMatrix& matrix, CompositeOperator compositeOp, const FloatRect& destRect) { SkShader* shader = SkShader::CreateBitmapShader(bitmap, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode); shader->setLocalMatrix(matrix); SkPaint paint; setupPaintCommon(&paint); paint.setAlpha(getNormalizedAlpha()); paint.setShader(shader)->unref(); paint.setXfermodeMode(WebCoreCompositeToSkiaComposite(compositeOp)); fixPaintForBitmapsThatMaySeam(&paint); mCanvas->drawRect(destRect, paint); }
DEF_TEST(DontOptimizeSaveLayerDrawDrawRestore, reporter) { // This test is from crbug.com/344987. // The commands are: // saveLayer with paint that modifies alpha // drawBitmapRect // drawBitmapRect // restore // The bug was that this structure was modified so that: // - The saveLayer and restore were eliminated // - The alpha was only applied to the first drawBitmapRectToRect // This test draws blue and red squares inside a 50% transparent // layer. Both colours should show up muted. // When the bug is present, the red square (the second bitmap) // shows upwith full opacity. SkBitmap blueBM; make_bm(&blueBM, 100, 100, SkColorSetARGB(255, 0, 0, 255), true); SkBitmap redBM; make_bm(&redBM, 100, 100, SkColorSetARGB(255, 255, 0, 0), true); SkPaint semiTransparent; semiTransparent.setAlpha(0x80); SkPictureRecorder recorder; SkCanvas* canvas = recorder.beginRecording(100, 100); canvas->drawARGB(0, 0, 0, 0); canvas->saveLayer(0, &semiTransparent); canvas->drawBitmap(blueBM, 25, 25); canvas->drawBitmap(redBM, 50, 50); canvas->restore(); sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture()); // Now replay the picture back on another canvas // and check a couple of its pixels. SkBitmap replayBM; make_bm(&replayBM, 100, 100, SK_ColorBLACK, false); SkCanvas replayCanvas(replayBM); picture->playback(&replayCanvas); replayCanvas.flush(); // With the bug present, at (55, 55) we would get a fully opaque red // intead of a dark red. REPORTER_ASSERT(reporter, replayBM.getColor(30, 30) == 0xff000080); REPORTER_ASSERT(reporter, replayBM.getColor(55, 55) == 0xff800000); }
void GraphicsContext::beginPlatformTransparencyLayer(float opacity) { if (paintingDisabled()) return; // We need the "alpha" layer flag here because the base layer is opaque // (the surface of the page) but layers on top may have transparent parts. // Without explicitly setting the alpha flag, the layer will inherit the // opaque setting of the base and some things won't work properly. SkCanvas::SaveFlags saveFlags = static_cast<SkCanvas::SaveFlags>(SkCanvas::kHasAlphaLayer_SaveFlag | SkCanvas::kFullColorLayer_SaveFlag); SkPaint layerPaint; layerPaint.setAlpha(static_cast<unsigned char>(opacity * 255)); layerPaint.setXfermodeMode(platformContext()->getXfermodeMode()); platformContext()->saveLayer(0, &layerPaint, saveFlags); }