void SkBaseDevice::drawAtlas(const SkDraw& draw, const SkImage* atlas, const SkRSXform xform[], const SkRect tex[], const SkColor colors[], int count, SkXfermode::Mode mode, const SkPaint& paint) { SkPath path; path.setIsVolatile(true); for (int i = 0; i < count; ++i) { SkPoint quad[4]; xform[i].toQuad(tex[i].width(), tex[i].height(), quad); SkMatrix localM; localM.setRSXform(xform[i]); localM.preTranslate(-tex[i].left(), -tex[i].top()); SkPaint pnt(paint); sk_sp<SkShader> shader = atlas->makeShader(SkShader::kClamp_TileMode, SkShader::kClamp_TileMode, &localM); if (!shader) { break; } pnt.setShader(std::move(shader)); if (colors) { pnt.setColorFilter(SkColorFilter::MakeModeFilter(colors[i], mode)); } path.rewind(); path.addPoly(quad, 4, true); path.setConvexity(SkPath::kConvex_Convexity); this->drawPath(draw, path, pnt, nullptr, true); } }
// Test out the normal blur style with a wide range of sigmas DEF_GPUTEST_FOR_RENDERING_CONTEXTS(BlurSigmaRange, reporter, context) { static const int kSize = 100; // The geometry is offset a smidge to trigger: // https://code.google.com/p/chromium/issues/detail?id=282418 SkPath rectPath; rectPath.addRect(0.3f, 0.3f, 100.3f, 100.3f); SkPoint polyPts[] = { { 0.3f, 0.3f }, { 100.3f, 0.3f }, { 100.3f, 100.3f }, { 0.3f, 100.3f }, { 2.3f, 50.3f } // a little divet to throw off the rect special case }; SkPath polyPath; polyPath.addPoly(polyPts, SK_ARRAY_COUNT(polyPts), true); int rectSpecialCaseResult[kSize]; int generalCaseResult[kSize]; int groundTruthResult[kSize]; int bruteForce1DResult[kSize]; SkScalar sigma = 10.0f; for (int i = 0; i < 4; ++i, sigma /= 10) { cpu_blur_path(rectPath, sigma, rectSpecialCaseResult, kSize); cpu_blur_path(polyPath, sigma, generalCaseResult, kSize); ground_truth_2d(100, 100, sigma, groundTruthResult, kSize); brute_force_1d(-50.0f, 50.0f, sigma, bruteForce1DResult, kSize); REPORTER_ASSERT(reporter, match(rectSpecialCaseResult, bruteForce1DResult, kSize, 5)); REPORTER_ASSERT(reporter, match(generalCaseResult, bruteForce1DResult, kSize, 15)); #if SK_SUPPORT_GPU #if 0 int gpuResult[kSize]; bool haveGPUResult = gpu_blur_path(context, rectPath, sigma, gpuResult, kSize); // Disabling this test for now -- I don't think it's a legit comparison. // Will continue to investigate this. if (haveGPUResult) { // 1 works everywhere but: Ubuntu13 & Nexus4 REPORTER_ASSERT(reporter, match(gpuResult, bruteForce1DResult, kSize, 10)); } #endif #endif REPORTER_ASSERT(reporter, match(groundTruthResult, bruteForce1DResult, kSize, 1)); #if WRITE_CSV write_as_csv("RectSpecialCase", sigma, rectSpecialCaseResult, kSize); write_as_csv("GeneralCase", sigma, generalCaseResult, kSize); #if SK_SUPPORT_GPU write_as_csv("GPU", sigma, gpuResult, kSize); #endif write_as_csv("GroundTruth2D", sigma, groundTruthResult, kSize); write_as_csv("BruteForce1D", sigma, bruteForce1DResult, kSize); #endif } }
void SkSVGDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint) { SkPath path; switch (mode) { // todo case SkCanvas::kPoints_PointMode: SkDebugf("unsupported operation: drawPoints(kPoints_PointMode)\n"); break; case SkCanvas::kLines_PointMode: count -= 1; for (size_t i = 0; i < count; i += 2) { path.rewind(); path.moveTo(pts[i]); path.lineTo(pts[i+1]); AutoElement elem("path", fWriter, fResourceBucket, draw, paint); elem.addPathAttributes(path); } break; case SkCanvas::kPolygon_PointMode: if (count > 1) { path.addPoly(pts, SkToInt(count), false); path.moveTo(pts[0]); AutoElement elem("path", fWriter, fResourceBucket, draw, paint); elem.addPathAttributes(path); } break; } }
void SkBaseDevice::drawAtlas(const SkDraw& draw, const SkImage* atlas, const SkRSXform xform[], const SkRect tex[], const SkColor colors[], int count, SkXfermode::Mode mode, const SkPaint& paint) { SkPath path; path.setIsVolatile(true); for (int i = 0; i < count; ++i) { SkPoint quad[4]; xform[i].toQuad(tex[i].width(), tex[i].height(), quad); SkMatrix localM; localM.setRSXform(xform[i]); localM.preTranslate(-tex[i].left(), -tex[i].top()); SkPaint pnt(paint); pnt.setShader(atlas->newShader(SkShader::kClamp_TileMode, SkShader::kClamp_TileMode, &localM))->unref(); if (colors && colors[i] != SK_ColorWHITE) { SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter(colors[i], mode)); pnt.setColorFilter(cf); } path.rewind(); path.addPoly(quad, 4, true); path.setConvexity(SkPath::kConvex_Convexity); this->drawPath(draw, path, pnt, NULL, true); } }
void draw(SkCanvas* canvas) { SkPaint paint; paint.setStrokeWidth(15); paint.setStrokeCap(SkPaint::kRound_Cap); SkPath path; const SkPoint points[] = {{20, 20}, {70, 20}, {40, 90}}; path.addPoly(points, SK_ARRAY_COUNT(points), false); for (int loop = 0; loop < 2; ++loop) { for (auto style : {SkPaint::kStroke_Style, SkPaint::kFill_Style, SkPaint::kStrokeAndFill_Style} ) { paint.setStyle(style); canvas->drawPath(path, paint); canvas->translate(85, 0); } path.close(); canvas->translate(-255, 128); } }
void draw(SkCanvas* canvas) { SkCanvas device(256, 256); canvas = &device; SkIRect bounds = canvas->getDeviceClipBounds(); SkDebugf("left:%d top:%d right:%d bottom:%d\n", bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom); SkPoint clipPoints[] = {{30, 130}, {120, 130}, {120, 230} }; SkPath clipPath; clipPath.addPoly(clipPoints, SK_ARRAY_COUNT(clipPoints), true); canvas->save(); canvas->clipPath(clipPath); bounds = canvas->getDeviceClipBounds(); SkDebugf("left:%d top:%d right:%d bottom:%d\n", bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom); canvas->restore(); canvas->scale(1.f/2, 1.f/2); canvas->clipPath(clipPath); bounds = canvas->getDeviceClipBounds(); SkDebugf("left:%d top:%d right:%d bottom:%d\n", bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom); }
void SkScan::FillTriangle(const SkPoint pts[], const SkRasterClip& clip, SkBlitter* blitter) { if (clip.isEmpty()) { return; } SkRect r; r.set(pts, 3); // If r is too large (larger than can easily fit in SkFixed) then we need perform geometric // clipping. This is a bit of work, so we just call the general FillPath() to handle it. // Use FixedMax/2 as the limit so we can subtract two edges and still store that in Fixed. const SkScalar limit = SK_MaxS16 >> 1; if (!SkRect::MakeLTRB(-limit, -limit, limit, limit).contains(r)) { SkPath path; path.addPoly(pts, 3, false); FillPath(path, clip, blitter); return; } SkIRect ir = conservative_round_to_int(r); if (ir.isEmpty() || !SkIRect::Intersects(ir, clip.getBounds())) { return; } SkAAClipBlitterWrapper wrap; const SkRegion* clipRgn; if (clip.isBW()) { clipRgn = &clip.bwRgn(); } else { wrap.init(clip, blitter); clipRgn = &wrap.getRgn(); blitter = wrap.getBlitter(); } SkScanClipper clipper(blitter, clipRgn, ir); blitter = clipper.getBlitter(); if (blitter) { sk_fill_triangle(pts, clipper.getClipRect(), blitter, ir); } }
SkPath makePath() { SkPath path; for (uint32_t cIndex = 0; cIndex < fPathContourCount; ++cIndex) { uint32_t segments = makeSegmentCount(); for (uint32_t sIndex = 0; sIndex < segments; ++sIndex) { RandomAddPath addPathType = makeAddPathType(); ++fAddCount; if (fPrintName) { SkDebugf("%.*s%s\n", fPathDepth * 3, fTab, gRandomAddPathNames[addPathType]); } switch (addPathType) { case kAddArc: { SkRect oval = makeRect(); SkScalar startAngle = makeAngle(); SkScalar sweepAngle = makeAngle(); path.addArc(oval, startAngle, sweepAngle); validate(path); } break; case kAddRoundRect1: { SkRect rect = makeRect(); SkScalar rx = makeScalar(), ry = makeScalar(); SkPath::Direction dir = makeDirection(); path.addRoundRect(rect, rx, ry, dir); validate(path); } break; case kAddRoundRect2: { SkRect rect = makeRect(); SkScalar radii[8]; makeScalarArray(SK_ARRAY_COUNT(radii), radii); SkPath::Direction dir = makeDirection(); path.addRoundRect(rect, radii, dir); validate(path); } break; case kAddRRect: { SkRRect rrect = makeRRect(); SkPath::Direction dir = makeDirection(); path.addRRect(rrect, dir); validate(path); } break; case kAddPoly: { SkTDArray<SkPoint> points; makePointArray(&points); bool close = makeBool(); path.addPoly(&points[0], points.count(), close); validate(path); } break; case kAddPath1: if (fPathDepth < fPathDepthLimit) { ++fPathDepth; SkPath src = makePath(); validate(src); SkScalar dx = makeScalar(); SkScalar dy = makeScalar(); SkPath::AddPathMode mode = makeAddPathMode(); path.addPath(src, dx, dy, mode); --fPathDepth; validate(path); } break; case kAddPath2: if (fPathDepth < fPathDepthLimit) { ++fPathDepth; SkPath src = makePath(); validate(src); SkPath::AddPathMode mode = makeAddPathMode(); path.addPath(src, mode); --fPathDepth; validate(path); } break; case kAddPath3: if (fPathDepth < fPathDepthLimit) { ++fPathDepth; SkPath src = makePath(); validate(src); SkMatrix matrix = makeMatrix(); SkPath::AddPathMode mode = makeAddPathMode(); path.addPath(src, matrix, mode); --fPathDepth; validate(path); } break; case kReverseAddPath: if (fPathDepth < fPathDepthLimit) { ++fPathDepth; SkPath src = makePath(); validate(src); path.reverseAddPath(src); --fPathDepth; validate(path); } break; case kMoveToPath: { SkScalar x = makeScalar(); SkScalar y = makeScalar(); path.moveTo(x, y); validate(path); } break; case kRMoveToPath: { SkScalar x = makeScalar(); SkScalar y = makeScalar(); path.rMoveTo(x, y); validate(path); } break; case kLineToPath: { SkScalar x = makeScalar(); SkScalar y = makeScalar(); path.lineTo(x, y); validate(path); } break; case kRLineToPath: { SkScalar x = makeScalar(); SkScalar y = makeScalar(); path.rLineTo(x, y); validate(path); } break; case kQuadToPath: { SkPoint pt[2]; makePointArray(SK_ARRAY_COUNT(pt), pt); path.quadTo(pt[0], pt[1]); validate(path); } break; case kRQuadToPath: { SkPoint pt[2]; makePointArray(SK_ARRAY_COUNT(pt), pt); path.rQuadTo(pt[0].fX, pt[0].fY, pt[1].fX, pt[1].fY); validate(path); } break; case kConicToPath: { SkPoint pt[2]; makePointArray(SK_ARRAY_COUNT(pt), pt); SkScalar weight = makeScalar(); path.conicTo(pt[0], pt[1], weight); validate(path); } break; case kRConicToPath: { SkPoint pt[2]; makePointArray(SK_ARRAY_COUNT(pt), pt); SkScalar weight = makeScalar(); path.rConicTo(pt[0].fX, pt[0].fY, pt[1].fX, pt[1].fY, weight); validate(path); } break; case kCubicToPath: { SkPoint pt[3]; makePointArray(SK_ARRAY_COUNT(pt), pt); path.cubicTo(pt[0], pt[1], pt[2]); validate(path); } break; case kRCubicToPath: { SkPoint pt[3]; makePointArray(SK_ARRAY_COUNT(pt), pt); path.rCubicTo(pt[0].fX, pt[0].fY, pt[1].fX, pt[1].fY, pt[2].fX, pt[2].fY); validate(path); } break; case kArcToPath: { SkPoint pt[2]; makePointArray(SK_ARRAY_COUNT(pt), pt); SkScalar radius = makeScalar(); path.arcTo(pt[0], pt[1], radius); validate(path); } break; case kArcTo2Path: { SkRect oval = makeRect(); SkScalar startAngle = makeAngle(); SkScalar sweepAngle = makeAngle(); bool forceMoveTo = makeBool(); path.arcTo(oval, startAngle, sweepAngle, forceMoveTo); validate(path); } break; case kClosePath: path.close(); validate(path); break; } } } return path; }
static void drawInBitmap(SkBitmap &bitmap) { SkCanvas canvas(bitmap); canvas.clear(SK_ColorWHITE); SkPaint myPaint; myPaint.setAntiAlias(true); myPaint.setColor(SK_ColorBLACK); myPaint.setStrokeWidth(SkIntToScalar(1)); canvas.translate(SkIntToScalar(36), SkIntToScalar(36)); canvas.scale(SkIntToScalar(1), SkIntToScalar(-1)); canvas.scale(SkDoubleToScalar(0.17), SkDoubleToScalar(0.17)); { SkPoint linearPoints[] = { {SkIntToScalar(-58), SkIntToScalar(13)}, {SkIntToScalar(-58+(116/2)), SkIntToScalar(13)} }; SkColor linearColors[] = {SK_ColorBLACK, SK_ColorLTGRAY}; SkShader* shader = SkGradientShader::CreateLinear( linearPoints, linearColors, NULL, 2, SkShader::kMirror_TileMode); SkAutoUnref shader_deleter(shader); myPaint.setShader(shader); myPaint.setFlags(SkPaint::kAntiAlias_Flag); SkRect rect0; rect0.setXYWH(SkIntToScalar(-58), SkIntToScalar(13), SkIntToScalar(116), SkIntToScalar(76)); canvas.drawRect(rect0,myPaint); // Detach shader myPaint.setShader(NULL); } myPaint.setColor(SK_ColorBLACK); myPaint.setStyle(SkPaint::kStrokeAndFill_Style); SkRect rect; rect.setXYWH(SkIntToScalar(-60), SkIntToScalar(75), SkIntToScalar(120), SkIntToScalar(6)); canvas.drawRect(rect, myPaint); SkRect rect1; rect1.setXYWH(SkIntToScalar(-60), SkIntToScalar(61), SkIntToScalar(120), SkIntToScalar(6)); canvas.drawRect(rect1, myPaint); SkRect rect2; rect2.setXYWH(SkIntToScalar(-60), SkIntToScalar(49), SkIntToScalar(120), SkIntToScalar(6)); canvas.drawRect(rect2, myPaint); SkPoint pts0[] = { {-60,11}, {-42,23}, {38,23}, {56,11}, {-60,11} }; myPaint.setColor(SK_ColorBLUE); myPaint.setStyle(SkPaint::kStroke_Style); SkPath path0; path0.addPoly(pts0, 5, true); canvas.drawPath(path0, myPaint); path0.addPoly(pts0, 5, true); myPaint.setColor(SK_ColorWHITE); myPaint.setStyle(SkPaint::kFill_Style); canvas.drawPath(path0, myPaint); myPaint.setColor(SK_ColorBLACK); myPaint.setStyle(SkPaint::kStroke_Style); canvas.drawLine(SkIntToScalar(-100), SkIntToScalar(-90), SkIntToScalar(100), SkIntToScalar(-91), myPaint); canvas.drawLine(SkIntToScalar(0), SkIntToScalar(-90), SkIntToScalar(26), SkIntToScalar(-58), myPaint); canvas.drawLine(SkIntToScalar(26), SkIntToScalar(-58), SkIntToScalar(-2), SkIntToScalar(37), myPaint); myPaint.setStyle(SkPaint::kStrokeAndFill_Style); canvas.drawCircle(SkIntToScalar(0), SkIntToScalar(33), SkIntToScalar(4), myPaint); myPaint.setStyle(SkPaint::kStroke_Style); canvas.drawCircle(SkDoubleToScalar(0), SkDoubleToScalar(-(129+49)/2), SkIntToScalar(40), myPaint); myPaint.setColor(SK_ColorLTGRAY); myPaint.setStyle(SkPaint::kStrokeAndFill_Style); SkPoint pts[9]; pts[0].set(-60, -50); pts[1].set(-60, 100); pts[2].set( 60, 100); pts[3].set(60, -52); pts[4].set(100, -52); pts[5].set(100, 150); pts[6].set(-100, 150); pts[7].set(-100, -50); pts[8].set(-60, -50); SkPath path; path.addPoly(pts, 9, false); canvas.drawPath(path, myPaint); myPaint.setColor(SK_ColorBLACK); myPaint.setStyle(SkPaint::kStroke_Style); canvas.drawPath(path, myPaint); SkRect inrect; inrect.setXYWH(SkIntToScalar(-105), SkIntToScalar(100), SkIntToScalar(15), SkIntToScalar(45)); myPaint.setColor(SK_ColorLTGRAY); myPaint.setStyle(SkPaint::kFill_Style); canvas.drawRect(inrect, myPaint); myPaint.setColor(SK_ColorGRAY); myPaint.setStyle(SkPaint::kStroke_Style); canvas.drawRect(inrect, myPaint); SkRect inrect1; inrect1.setXYWH(SkIntToScalar(90), SkIntToScalar(100), SkIntToScalar(15), SkIntToScalar(45)); myPaint.setColor(SK_ColorLTGRAY); myPaint.setStyle(SkPaint::kFill_Style); canvas.drawRect(inrect1, myPaint); myPaint.setColor(SK_ColorGRAY); myPaint.setStyle(SkPaint::kStroke_Style); canvas.drawRect(inrect1, myPaint); SkRect inrect2; inrect2.setXYWH(SkIntToScalar(-105), SkIntToScalar(-115), SkIntToScalar(15), SkIntToScalar(45)); myPaint.setColor(SK_ColorLTGRAY); myPaint.setStyle(SkPaint::kFill_Style); canvas.drawRect(inrect2, myPaint); myPaint.setColor(SK_ColorGRAY); myPaint.setStyle(SkPaint::kStroke_Style); canvas.drawRect(inrect2, myPaint); SkRect inrect3; inrect3.setXYWH(SkIntToScalar(90), SkIntToScalar(-115), SkIntToScalar(15), SkIntToScalar(45)); myPaint.setColor(SK_ColorLTGRAY); myPaint.setStyle(SkPaint::kFill_Style); canvas.drawRect(inrect3, myPaint); myPaint.setColor(SK_ColorGRAY); myPaint.setStyle(SkPaint::kStroke_Style); canvas.drawRect(inrect3, myPaint); }