void paintSkiaText(GraphicsContext* context, HFONT hfont, int numGlyphs, const WORD* glyphs, const int* advances, const GOFFSET* offsets, const SkPoint* origin) { HDC dc = GetDC(0); HGDIOBJ oldFont = SelectObject(dc, hfont); PlatformContextSkia* platformContext = context->platformContext(); SkCanvas* canvas = platformContext->canvas(); TextDrawingModeFlags textMode = platformContext->getTextDrawingMode(); // If platformContext is GPU-backed make its GL context current. platformContext->makeGrContextCurrent(); // Filling (if necessary). This is the common case. SkPaint paint; platformContext->setupPaintForFilling(&paint); paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); setupPaintForFont(hfont, &paint, platformContext); bool didFill = false; if ((textMode & TextModeFill) && (SkColorGetA(paint.getColor()) || paint.getLooper())) { skiaDrawText(canvas, *origin, &paint, &glyphs[0], &advances[0], &offsets[0], numGlyphs); didFill = true; } // Stroking on top (if necessary). if ((textMode & TextModeStroke) && platformContext->getStrokeStyle() != NoStroke && platformContext->getStrokeThickness() > 0) { paint.reset(); platformContext->setupPaintForStroking(&paint, 0, 0); paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); setupPaintForFont(hfont, &paint, platformContext); if (didFill) { // If there is a shadow and we filled above, there will already be // a shadow. We don't want to draw it again or it will be too dark // and it will go on top of the fill. // // Note that this isn't strictly correct, since the stroke could be // very thick and the shadow wouldn't account for this. The "right" // thing would be to draw to a new layer and then draw that layer // with a shadow. But this is a lot of extra work for something // that isn't normally an issue. paint.setLooper(0); } skiaDrawText(canvas, *origin, &paint, &glyphs[0], &advances[0], &offsets[0], numGlyphs); } SelectObject(dc, oldFont); ReleaseDC(0, dc); }
void GraphicsContext::drawConvexPolygon(size_t numPoints, const FloatPoint* points, bool shouldAntialias) { if (paintingDisabled()) return; if (numPoints <= 1) return; SkPath path; setPathFromConvexPoints(&path, numPoints, points); SkPaint paint; platformContext()->setupPaintForFilling(&paint); paint.setAntiAlias(shouldAntialias); platformContext()->canvas()->drawPath(path, paint); platformContext()->didDrawPath(path, paint); if (strokeStyle() != NoStroke) { paint.reset(); platformContext()->setupPaintForStroking(&paint, 0, 0); platformContext()->canvas()->drawPath(path, paint); platformContext()->didDrawPath(path, paint); } }
static SkScalar draw_row(SkCanvas* canvas, const SkBitmap& bm) { //此为canvas的save操作 //在超过了作用域之后,会自动调用restore函数 SkAutoCanvasRestore acr(canvas, true); SkPaint paint; SkScalar x = 0; const int scale = 64; //开启抗锯齿 : 见百度百科 paint.setAntiAlias(true); //绘制行首文字 : 见结果图每行行头文字 const char* name = gConfigNames[bm.config()]; canvas->drawText(name, strlen(name), x, SkIntToScalar(bm.height())*scale*5/8, paint); //平移到(48, 0)???为何是48--牛群 canvas->translate(SkIntToScalar(192), 0); //缩放 : x,y轴乘各乘以一个系数, 进行放大或缩小.: 此处因为4个像素很小,所以进行了放大. canvas->scale(SkIntToScalar(scale), SkIntToScalar(scale)); /*逐个画每行的6个方块*/ //画前三个, 正常的, 滤镜的, 滤镜+防抖动的. x += draw_set(canvas, bm, 0, &paint); //画笔复原 paint.reset(); /*开启透明, 画后三个, 正常的, 滤镜的, 滤镜+防抖动的. */ paint.setAlpha(0x80); draw_set(canvas, bm, x, &paint); return x * scale / 3; }
void PlatformContextSkiaJava::drawRect(SkRect rect) { SkPaint paint; int fillcolorNotTransparent = m_state->m_fillColor & 0xFF000000; if (fillcolorNotTransparent) { setupPaintForFilling(&paint); canvas()->drawRect(rect, paint); } if (m_state->m_strokeStyle != WebCore::NoStroke && (m_state->m_strokeColor & 0xFF000000)) { // We do a fill of four rects to simulate the stroke of a border. SkColor oldFillColor = m_state->m_fillColor; // setFillColor() will set the shader to NULL, so save a ref to it now. SkShader* oldFillShader = m_state->m_fillShader; oldFillShader->safeRef(); setFillColor(m_state->m_strokeColor); paint.reset(); setupPaintForFilling(&paint); SkRect topBorder = { rect.fLeft, rect.fTop, rect.fRight, rect.fTop + 1 }; canvas()->drawRect(topBorder, paint); SkRect bottomBorder = { rect.fLeft, rect.fBottom - 1, rect.fRight, rect.fBottom }; canvas()->drawRect(bottomBorder, paint); SkRect leftBorder = { rect.fLeft, rect.fTop + 1, rect.fLeft + 1, rect.fBottom - 1 }; canvas()->drawRect(leftBorder, paint); SkRect rightBorder = { rect.fRight - 1, rect.fTop + 1, rect.fRight, rect.fBottom - 1 }; canvas()->drawRect(rightBorder, paint); setFillColor(oldFillColor); setFillShader(oldFillShader); oldFillShader->safeUnref(); } }
void PlatformGraphicsContextSkia::drawConvexPolygon(size_t numPoints, const FloatPoint* points, bool shouldAntialias) { if (numPoints <= 1) return; SkPaint paint; SkPath path; path.incReserve(numPoints); path.moveTo(SkFloatToScalar(points[0].x()), SkFloatToScalar(points[0].y())); for (size_t i = 1; i < numPoints; i++) path.lineTo(SkFloatToScalar(points[i].x()), SkFloatToScalar(points[i].y())); if (mCanvas->quickReject(path, shouldAntialias ? SkCanvas::kAA_EdgeType : SkCanvas::kBW_EdgeType)) { return; } if (m_state->fillColor & 0xFF000000) { setupPaintFill(&paint); paint.setAntiAlias(shouldAntialias); mCanvas->drawPath(path, paint); } if (m_state->strokeStyle != NoStroke) { paint.reset(); setupPaintStroke(&paint, 0); paint.setAntiAlias(shouldAntialias); mCanvas->drawPath(path, paint); } }
void PlatformContextSkia::drawRect(SkRect rect) { SkPaint paint; int fillcolorNotTransparent = m_state->m_fillColor & 0xFF000000; if (fillcolorNotTransparent) { setupPaintForFilling(&paint); drawRect(rect, paint); } if (m_state->m_strokeStyle != NoStroke && (m_state->m_strokeColor & 0xFF000000)) { // We do a fill of four rects to simulate the stroke of a border. paint.reset(); setupPaintForFilling(&paint); // need to jam in the strokeColor paint.setColor(this->effectiveStrokeColor()); SkRect topBorder = { rect.fLeft, rect.fTop, rect.fRight, rect.fTop + 1 }; drawRect(topBorder, paint); SkRect bottomBorder = { rect.fLeft, rect.fBottom - 1, rect.fRight, rect.fBottom }; drawRect(bottomBorder, paint); SkRect leftBorder = { rect.fLeft, rect.fTop + 1, rect.fLeft + 1, rect.fBottom - 1 }; drawRect(leftBorder, paint); SkRect rightBorder = { rect.fRight - 1, rect.fTop + 1, rect.fRight, rect.fBottom - 1 }; drawRect(rightBorder, paint); } }
void GraphicsContext::drawConvexPolygon(size_t numPoints, const FloatPoint* points, bool shouldAntialias) { if (paintingDisabled()) return; if (numPoints <= 1) return; platformContext()->prepareForSoftwareDraw(); SkPath path; path.incReserve(numPoints); path.moveTo(WebCoreFloatToSkScalar(points[0].x()), WebCoreFloatToSkScalar(points[0].y())); for (size_t i = 1; i < numPoints; i++) { path.lineTo(WebCoreFloatToSkScalar(points[i].x()), WebCoreFloatToSkScalar(points[i].y())); } if (!isPathSkiaSafe(getCTM(), path)) return; SkPaint paint; platformContext()->setupPaintForFilling(&paint); platformContext()->canvas()->drawPath(path, paint); if (strokeStyle() != NoStroke) { paint.reset(); platformContext()->setupPaintForStroking(&paint, 0, 0); platformContext()->canvas()->drawPath(path, paint); } }
void paintSkiaText(GraphicsContext* context, HFONT hfont, int numGlyphs, const WORD* glyphs, const int* advances, const GOFFSET* offsets, const SkPoint* origin) { PlatformContextSkia* platformContext = context->platformContext(); SkCanvas* canvas = platformContext->canvas(); TextDrawingModeFlags textMode = platformContext->getTextDrawingMode(); // Ensure font load for printing, because PDF device needs it. if (canvas->getTopDevice()->getDeviceCapabilities() & SkDevice::kVector_Capability) PlatformSupport::ensureFontLoaded(hfont); // Filling (if necessary). This is the common case. SkPaint paint; platformContext->setupPaintForFilling(&paint); paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); setupPaintForFont(hfont, &paint, platformContext); bool didFill = false; if ((textMode & TextModeFill) && (SkColorGetA(paint.getColor()) || paint.getLooper())) { skiaDrawText(canvas, *origin, &paint, &glyphs[0], &advances[0], &offsets[0], numGlyphs); didFill = true; } // Stroking on top (if necessary). if ((textMode & TextModeStroke) && platformContext->getStrokeStyle() != NoStroke && platformContext->getStrokeThickness() > 0) { paint.reset(); platformContext->setupPaintForStroking(&paint, 0, 0); paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); setupPaintForFont(hfont, &paint, platformContext); if (didFill) { // If there is a shadow and we filled above, there will already be // a shadow. We don't want to draw it again or it will be too dark // and it will go on top of the fill. // // Note that this isn't strictly correct, since the stroke could be // very thick and the shadow wouldn't account for this. The "right" // thing would be to draw to a new layer and then draw that layer // with a shadow. But this is a lot of extra work for something // that isn't normally an issue. paint.setLooper(0); } skiaDrawText(canvas, *origin, &paint, &glyphs[0], &advances[0], &offsets[0], numGlyphs); } }
static void paintSkiaText(GraphicsContext* context, HFONT hfont, SkTypeface* face, float size, uint32_t textFlags, int numGlyphs, const WORD* glyphs, const int* advances, const GOFFSET* offsets, const SkPoint& origin, const SkRect& textRect) { TextDrawingModeFlags textMode = context->textDrawingMode(); // Ensure font load for printing, because PDF device needs it. if (context->isPrintingDevice()) FontPlatformData::ensureFontLoaded(hfont); // Filling (if necessary). This is the common case. SkPaint paint; context->setupPaintForFilling(&paint); paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); setupPaintForFont(&paint, context, face, size, textFlags); bool didFill = false; if ((textMode & TextModeFill) && (SkColorGetA(paint.getColor()) || paint.getLooper())) { skiaDrawText(context, origin, textRect, &paint, &glyphs[0], &advances[0], &offsets[0], numGlyphs); didFill = true; } // Stroking on top (if necessary). if ((textMode & TextModeStroke) && context->strokeStyle() != NoStroke && context->strokeThickness() > 0) { paint.reset(); context->setupPaintForStroking(&paint); paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); setupPaintForFont(&paint, context, face, size, textFlags); if (didFill) { // If there is a shadow and we filled above, there will already be // a shadow. We don't want to draw it again or it will be too dark // and it will go on top of the fill. // // Note that this isn't strictly correct, since the stroke could be // very thick and the shadow wouldn't account for this. The "right" // thing would be to draw to a new layer and then draw that layer // with a shadow. But this is a lot of extra work for something // that isn't normally an issue. paint.setLooper(0); } skiaDrawText(context, origin, textRect, &paint, &glyphs[0], &advances[0], &offsets[0], numGlyphs); } }
static void paintOp_rp(SkCanvas*, SkReader32* reader, uint32_t op32, SkGPipeState* state) { size_t offset = reader->offset(); size_t stop = offset + PaintOp_unpackData(op32); SkPaint* p = state->editPaint(); do { uint32_t p32 = reader->readU32(); unsigned op = PaintOp_unpackOp(p32); unsigned data = PaintOp_unpackData(p32); // SkDebugf(" read %08X op=%d flags=%d data=%d\n", p32, op, done, data); switch (op) { case kReset_PaintOp: p->reset(); break; case kFlags_PaintOp: p->setFlags(data); break; case kColor_PaintOp: p->setColor(reader->readU32()); break; case kFilterLevel_PaintOp: p->setFilterQuality((SkFilterQuality)data); break; case kStyle_PaintOp: p->setStyle((SkPaint::Style)data); break; case kJoin_PaintOp: p->setStrokeJoin((SkPaint::Join)data); break; case kCap_PaintOp: p->setStrokeCap((SkPaint::Cap)data); break; case kWidth_PaintOp: p->setStrokeWidth(reader->readScalar()); break; case kMiter_PaintOp: p->setStrokeMiter(reader->readScalar()); break; case kEncoding_PaintOp: p->setTextEncoding((SkPaint::TextEncoding)data); break; case kHinting_PaintOp: p->setHinting((SkPaint::Hinting)data); break; case kAlign_PaintOp: p->setTextAlign((SkPaint::Align)data); break; case kTextSize_PaintOp: p->setTextSize(reader->readScalar()); break; case kTextScaleX_PaintOp: p->setTextScaleX(reader->readScalar()); break; case kTextSkewX_PaintOp: p->setTextSkewX(reader->readScalar()); break; case kFlatIndex_PaintOp: { PaintFlats pf = (PaintFlats)PaintOp_unpackFlags(p32); unsigned index = data; set_paintflat(p, state->getFlat(index), pf); break; } case kTypeface_PaintOp: SkASSERT(SkToBool(state->getFlags() & SkGPipeWriter::kCrossProcess_Flag)); p->setTypeface(state->getTypeface(data)); break; default: SkDEBUGFAIL("bad paintop"); return; } SkASSERT(reader->offset() <= stop); } while (reader->offset() < stop); }
void PlatformGraphicsContextSkia::drawEllipse(const IntRect& rect) { SkPaint paint; SkRect oval(rect); if (m_state->fillColor & 0xFF000000) { setupPaintFill(&paint); mCanvas->drawOval(oval, paint); } if (m_state->strokeStyle != NoStroke) { paint.reset(); setupPaintStroke(&paint, &oval); mCanvas->drawOval(oval, paint); } }
void mbe_copy_source(mbe_t *src, mbe_t *dst) { SkPaint *paint = dst->paint; const SkBitmap *bmap; SkXfermode *mode; /* _prepare_paint(dst, SkPaint::kFill_Style); */ mode = SkXfermode::Create(SkXfermode::kSrc_Mode); paint->setXfermode(mode); bmap = &src->canvas->getDevice()->accessBitmap(false); dst->canvas->drawBitmap(*bmap, 0, 0, paint); paint->reset(); mode->unref(); /* _finish_paint(dst); */ }
// This method is only used to draw the little circles used in lists. void GraphicsContext::drawEllipse(const IntRect& elipseRect) { if (paintingDisabled()) return; SkRect rect = elipseRect; SkPaint paint; platformContext()->setupPaintForFilling(&paint); platformContext()->canvas()->drawOval(rect, paint); platformContext()->didDrawBounded(rect, paint); if (strokeStyle() != NoStroke) { paint.reset(); platformContext()->setupPaintForStroking(&paint, &rect, 0); platformContext()->canvas()->drawOval(rect, paint); platformContext()->didDrawBounded(rect, paint); } }
// Draws a filled rectangle with a stroked border. void GraphicsContext::drawRect(const IntRect& rect) { if (paintingDisabled()) return; SkPaint paint; SkRect r(rect); if (fillColor().alpha()) { m_data->setup_paint_fill(&paint); GC2Canvas(this)->drawRect(r, paint); } if (strokeStyle() != NoStroke && strokeColor().alpha()) { paint.reset(); m_data->setup_paint_stroke(&paint, &r); GC2Canvas(this)->drawRect(r, paint); } }
void PlatformContextSkia::drawRect(SkRect rect) { SkPaint paint; int fillcolorNotTransparent = m_state->m_fillColor & 0xFF000000; if (fillcolorNotTransparent) { setupPaintForFilling(&paint); canvas()->drawRect(rect, paint); } if (m_state->m_strokeStyle != WebCore::NoStroke && (m_state->m_strokeColor & 0xFF000000)) { if (fillcolorNotTransparent) { // This call is expensive so don't call it unnecessarily. paint.reset(); } setupPaintForStroking(&paint, &rect, 0); canvas()->drawRect(rect, paint); } }
// This method is only used to draw the little circles used in lists. void GraphicsContext::drawEllipse(const IntRect& elipseRect) { if (paintingDisabled()) return; SkRect rect = elipseRect; if (!isRectSkiaSafe(getCTM(), rect)) return; platformContext()->prepareForSoftwareDraw(); SkPaint paint; platformContext()->setupPaintForFilling(&paint); platformContext()->canvas()->drawOval(rect, paint); if (strokeStyle() != NoStroke) { paint.reset(); platformContext()->setupPaintForStroking(&paint, &rect, 0); platformContext()->canvas()->drawOval(rect, paint); } }
static SkScalar draw_row(SkCanvas* canvas, const SkBitmap& bm) { SkAutoCanvasRestore acr(canvas, true); SkPaint paint; SkScalar x = 0; const int scale = 32; paint.setAntiAlias(true); const char* name = gConfigNames[bm.config()]; canvas->drawText(name, strlen(name), x, SkIntToScalar(bm.height())*scale*5/8, paint); canvas->translate(SkIntToScalar(48), 0); canvas->scale(SkIntToScalar(scale), SkIntToScalar(scale)); x += draw_set(canvas, bm, 0, &paint); paint.reset(); paint.setAlpha(0x80); draw_set(canvas, bm, x, &paint); return x * scale / 3; }
static SkScalar draw_row(SkCanvas* canvas, const SkBitmap& bm) { SkAutoCanvasRestore acr(canvas, true); SkPaint paint; SkScalar x = 0; const int scale = 32; paint.setAntiAlias(true); sk_tool_utils::set_portable_typeface(&paint); const char* name = sk_tool_utils::colortype_name(bm.colorType()); canvas->drawText(name, strlen(name), x, SkIntToScalar(bm.height())*scale*5/8, paint); canvas->translate(SkIntToScalar(48), 0); canvas->scale(SkIntToScalar(scale), SkIntToScalar(scale)); x += draw_set(canvas, bm, 0, &paint); paint.reset(); paint.setAlpha(0x80); draw_set(canvas, bm, x, &paint); return x * scale / 3; }
static void test_backToFront(skiatest::Reporter* reporter) { SkLayerDrawLooper::Builder looperBuilder; SkLayerDrawLooper::LayerInfo layerInfo; // Add the back layer, with the defaults. (void)looperBuilder.addLayerOnTop(layerInfo); // Add the front layer, with some layer info set. layerInfo.fOffset.set(10.0f, 20.0f); layerInfo.fPaintBits |= SkLayerDrawLooper::kXfermode_Bit; SkPaint* layerPaint = looperBuilder.addLayerOnTop(layerInfo); layerPaint->setBlendMode(SkBlendMode::kSrc); FakeDevice device; SkCanvas canvas(&device); SkPaint paint; auto looper(looperBuilder.detach()); SkArenaAlloc alloc{48}; SkDrawLooper::Context* context = looper->makeContext(&canvas, &alloc); // The back layer should come first. REPORTER_ASSERT(reporter, context->next(&canvas, &paint)); REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrcOver); canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint); REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateX()); REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateY()); paint.reset(); // Then the front layer. REPORTER_ASSERT(reporter, context->next(&canvas, &paint)); REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrc); canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint); REPORTER_ASSERT(reporter, 10.0f == device.fLastMatrix.getTranslateX()); REPORTER_ASSERT(reporter, 20.0f == device.fLastMatrix.getTranslateY()); // Only two layers were added, so that should be the end. REPORTER_ASSERT(reporter, !context->next(&canvas, &paint)); }
static SkScalar draw_row(SkCanvas* canvas, const SkBitmap& bm) { SkAutoCanvasRestore acr(canvas, true); SkPaint paint; paint.setAntiAlias(true); SkScalar x = 0; const int scale = 32; SkFont font(ToolUtils::create_portable_typeface()); const char* name = ToolUtils::colortype_name(bm.colorType()); canvas->drawString(name, x, SkIntToScalar(bm.height())*scale*5/8, font, paint); canvas->translate(SkIntToScalar(48), 0); canvas->scale(SkIntToScalar(scale), SkIntToScalar(scale)); x += draw_set(canvas, bm, 0, &paint); paint.reset(); paint.setAlphaf(0.5f); draw_set(canvas, bm, x, &paint); return x * scale / 3; }
// Draws a filled rectangle with a stroked border. void GraphicsContext::drawRect(const IntRect& rect) { if (paintingDisabled()) return; SkPaint paint; SkRect r(rect); if (fillColor().alpha()) { m_data->setupPaintFill(&paint); GC2CANVAS(this)->drawRect(r, paint); } // According to GraphicsContext.h, stroking inside drawRect always means // a stroke of 1 inside the rect. if (strokeStyle() != NoStroke && strokeColor().alpha()) { paint.reset(); m_data->setupPaintStroke(&paint, &r); paint.setPathEffect(0); // No dashing please paint.setStrokeWidth(SK_Scalar1); // Always just 1.0 width r.inset(SK_ScalarHalf, SK_ScalarHalf); // Ensure we're "inside" GC2CANVAS(this)->drawRect(r, paint); } }
bool RenderThemeChromiumSkia::paintMediaSliderTrack(RenderObject* object, const RenderObject::PaintInfo& paintInfo, const IntRect& rect) { #if ENABLE(VIDEO) HTMLMediaElement* mediaElement = mediaElementParent(object->node()); if (!mediaElement) return false; SkCanvas* canvas = paintInfo.context->platformContext()->canvas(); SkRect backgroundRect; backgroundRect.set(rect.x(), rect.y(), rect.x() + rect.width(), rect.y() + rect.height()); SkPaint paint; paint.setAntiAlias(true); // Draw the border of the time bar. The border only has one single color, // width and radius. So use the property of the left border. SkColor borderColor = object->style()->borderLeftColor().rgb(); int borderWidth = object->style()->borderLeftWidth(); IntSize borderRadius = object->style()->borderTopLeftRadius(); paint.setStyle(SkPaint::kStroke_Style); paint.setStrokeWidth(borderWidth); paint.setColor(borderColor); canvas->drawRoundRect(backgroundRect, borderRadius.width(), borderRadius.height(), paint); // Draw the background of the time bar. SkColor backgroundColor = object->style()->backgroundColor().rgb(); paint.setStyle(SkPaint::kFill_Style); paint.setColor(backgroundColor); canvas->drawRoundRect(backgroundRect, borderRadius.width(), borderRadius.height(), paint); if (backgroundRect.width() >= 3 && backgroundRect.height() >= 3) { // Draw the buffered ranges. // FIXME: Draw multiple ranges if there are multiple buffered ranges. SkRect bufferedRect; bufferedRect.set(backgroundRect.fLeft + 2, backgroundRect.fTop + 2, backgroundRect.fRight - 1, backgroundRect.fBottom - 1); int width = static_cast<int>(bufferedRect.width() * mediaElement->percentLoaded()); bufferedRect.fRight = bufferedRect.fLeft + width; SkPoint points[2] = { { 0, bufferedRect.fTop }, { 0, bufferedRect.fBottom } }; SkColor startColor = object->style()->color().rgb(); SkColor endColor = SkColorSetRGB(SkColorGetR(startColor) / 2, SkColorGetG(startColor) / 2, SkColorGetB(startColor) / 2); SkColor colors[2] = { startColor, endColor }; SkShader* gradient = SkGradientShader::CreateLinear(points, colors, 0, sizeof(points) / sizeof(points[0]), SkShader::kMirror_TileMode, 0); paint.reset(); paint.setShader(gradient); paint.setAntiAlias(true); // Check for round rect with zero width or height, otherwise Skia will assert if (bufferedRect.width() > 0 && bufferedRect.height() > 0) canvas->drawRoundRect(bufferedRect, borderRadius.width(), borderRadius.height(), paint); gradient->unref(); } return true; #else UNUSED_PARAM(object); UNUSED_PARAM(paintInfo); UNUSED_PARAM(rect); return false; #endif }