void Path2D::Oval(const v8::FunctionCallbackInfo<Value>& args) { if (args.Length() != 4 && args.Length() != 5) { args.GetIsolate()->ThrowException( v8::String::NewFromUtf8( args.GetIsolate(), "Error: 4 or 5 args required.")); return; } double x = args[0]->NumberValue(); double y = args[1]->NumberValue(); double radiusX = args[2]->NumberValue(); double radiusY = args[3]->NumberValue(); SkPath::Direction dir = SkPath::kCW_Direction; if (args.Length() == 5 && !args[4]->BooleanValue()) { dir = SkPath::kCCW_Direction; } Path2D* path = Unwrap(args); SkRect rect = { SkDoubleToScalar(x-radiusX), SkDoubleToScalar(y-radiusX), SkDoubleToScalar(x+radiusY), SkDoubleToScalar(y+radiusY) }; path->fSkPath.addOval(rect, dir); }
DEF_TEST(PathOpsAngleFindQuadEpsilon, reporter) { if (gDisableAngleTests) { return; } SkRandom ran; int maxEpsilon = 0; double maxAngle = 0; for (int index = 0; index < 100000; ++index) { SkDLine line = {{{0, 0}, {ran.nextRangeF(0.0001f, 1000), ran.nextRangeF(0.0001f, 1000)}}}; float t = ran.nextRangeF(0.0001f, 1); SkDPoint dPt = line.ptAtT(t); float t2 = ran.nextRangeF(0.0001f, 1); SkDPoint qPt = line.ptAtT(t2); float t3 = ran.nextRangeF(0.0001f, 1); SkDPoint qPt2 = line.ptAtT(t3); qPt.fX += qPt2.fY; qPt.fY -= qPt2.fX; QuadPts q = {{line[0], dPt, qPt}}; SkDQuad quad; quad.debugSet(q.fPts); // binary search for maximum movement of quad[1] towards test that still has 1 intersection double moveT = 0.5f; double deltaT = moveT / 2; SkDPoint last; do { last = quad[1]; quad[1].fX = dPt.fX - line[1].fY * moveT; quad[1].fY = dPt.fY + line[1].fX * moveT; SkIntersections i; i.intersect(quad, line); REPORTER_ASSERT(reporter, i.used() > 0); if (i.used() == 1) { moveT += deltaT; } else { moveT -= deltaT; } deltaT /= 2; } while (last.asSkPoint() != quad[1].asSkPoint()); float p1 = SkDoubleToScalar(line[1].fX * last.fY); float p2 = SkDoubleToScalar(line[1].fY * last.fX); int p1Bits = SkFloatAs2sCompliment(p1); int p2Bits = SkFloatAs2sCompliment(p2); int epsilon = SkTAbs(p1Bits - p2Bits); if (maxEpsilon < epsilon) { SkDebugf("line={{0, 0}, {%1.7g, %1.7g}} t=%1.7g/%1.7g/%1.7g moveT=%1.7g" " pt={%1.7g, %1.7g} epsilon=%d\n", line[1].fX, line[1].fY, t, t2, t3, moveT, last.fX, last.fY, epsilon); maxEpsilon = epsilon; } double a1 = atan2(line[1].fY, line[1].fX); double a2 = atan2(last.fY, last.fX); double angle = fabs(a1 - a2); if (maxAngle < angle) { SkDebugf("line={{0, 0}, {%1.7g, %1.7g}} t=%1.7g/%1.7g/%1.7g moveT=%1.7g" " pt={%1.7g, %1.7g} angle=%1.7g\n", line[1].fX, line[1].fY, t, t2, t3, moveT, last.fX, last.fY, angle); maxAngle = angle; } } }
virtual void onDraw(SkCanvas* canvas) { canvas->clear(SK_ColorBLACK); SkMatrix matrix; SkScalar margin = SkIntToScalar(10); matrix.setSkew(SkDoubleToScalar(0.5), SkDoubleToScalar(0.2)); SkBitmap checkerboard; make_checkerboard(&checkerboard); SkRect srcRect = SkRect::MakeWH(96, 96); canvas->translate(margin, margin); draw(canvas, srcRect, checkerboard, matrix, kNone_SkFilterQuality); canvas->translate(srcRect.width() + margin, 0); draw(canvas, srcRect, checkerboard, matrix, kLow_SkFilterQuality); #if 0 // This may be causing Mac 10.6 to barf. canvas->translate(srcRect.width() + margin, 0); draw(canvas, srcRect, checkerboard, matrix, kMedium_SkFilterQuality); canvas->translate(srcRect.width() + margin, 0); draw(canvas, srcRect, checkerboard, matrix, kHigh_SkFilterQuality); #endif }
DEF_TEST(PathOpsAngleFindCrossEpsilon, reporter) { if (gDisableAngleTests) { return; } SkRandom ran; int maxEpsilon = 0; for (int index = 0; index < 10000000; ++index) { SkDLine line = {{{0, 0}, {ran.nextRangeF(0.0001f, 1000), ran.nextRangeF(0.0001f, 1000)}}}; for (int inner = 0; inner < 10; ++inner) { float t = ran.nextRangeF(0.0001f, 1); SkDPoint dPt = line.ptAtT(t); SkPoint pt = dPt.asSkPoint(); float xs[3] = { prev(pt.fX), pt.fX, next(pt.fX) }; float ys[3] = { prev(pt.fY), pt.fY, next(pt.fY) }; for (int xIdx = 0; xIdx < 3; ++xIdx) { for (int yIdx = 0; yIdx < 3; ++yIdx) { SkPoint test = { xs[xIdx], ys[yIdx] }; float p1 = SkDoubleToScalar(line[1].fX * test.fY); float p2 = SkDoubleToScalar(line[1].fY * test.fX); int p1Bits = SkFloatAs2sCompliment(p1); int p2Bits = SkFloatAs2sCompliment(p2); int epsilon = SkTAbs(p1Bits - p2Bits); if (maxEpsilon < epsilon) { SkDebugf("line={{0, 0}, {%1.7g, %1.7g}} t=%1.7g pt={%1.7g, %1.7g}" " epsilon=%d\n", line[1].fX, line[1].fY, t, test.fX, test.fY, epsilon); maxEpsilon = epsilon; } } } } } }
void Path2D::Arc(const v8::FunctionCallbackInfo<Value>& args) { if (args.Length() != 5 && args.Length() != 6) { args.GetIsolate()->ThrowException( v8::String::NewFromUtf8( args.GetIsolate(), "Error: 5 or 6 args required.")); return; } double x = args[0]->NumberValue(); double y = args[1]->NumberValue(); double radius = args[2]->NumberValue(); double startAngle = args[3]->NumberValue(); double endAngle = args[4]->NumberValue(); bool antiClockwise = false; if (args.Length() == 6) { antiClockwise = args[5]->BooleanValue(); } double sweepAngle; if (!antiClockwise) { sweepAngle = endAngle - startAngle; } else { sweepAngle = startAngle - endAngle; startAngle = endAngle; } Path2D* path = Unwrap(args); SkRect rect = { SkDoubleToScalar(x-radius), SkDoubleToScalar(y-radius), SkDoubleToScalar(x+radius), SkDoubleToScalar(y+radius) }; path->fSkPath.addArc(rect, SkRadiansToDegrees(startAngle), SkRadiansToDegrees(sweepAngle)); }
static SkBitmap createBitmap(const SkPath& path) { SkBitmap bitmap; bitmap.setConfig(SkBitmap::kARGB_8888_Config, SkImageWidget::kImageWidgetWidth, SkImageWidget::kImageWidgetHeight); bitmap.allocPixels(); bitmap.eraseColor(SK_ColorWHITE); SkDevice* device = new SkDevice(bitmap); SkCanvas canvas(device); device->unref(); const SkRect& bounds = path.getBounds(); if (bounds.width() > bounds.height()) { canvas.scale(SkDoubleToScalar((0.9*SkImageWidget::kImageWidgetWidth)/bounds.width()), SkDoubleToScalar((0.9*SkImageWidget::kImageWidgetHeight)/bounds.width())); } else { canvas.scale(SkDoubleToScalar((0.9*SkImageWidget::kImageWidgetWidth)/bounds.height()), SkDoubleToScalar((0.9*SkImageWidget::kImageWidgetHeight)/bounds.height())); } canvas.translate(-bounds.fLeft+2, -bounds.fTop+2); SkPaint p; p.setColor(SK_ColorBLACK); p.setStyle(SkPaint::kStroke_Style); canvas.drawPath(path, p); return bitmap; }
int sk_test_linear_gradient(caskbench_context_t *ctx) { int w = ctx->canvas_width; int h = ctx->canvas_height; int stops = 10; SkPoint pts[2]; pts[0].iset(0, 0); pts[1].iset(100, 100); SkColor colors[10]; SkScalar pos[10]; for (int i = 0; i < stops; i++) { pos[i] = i / SkIntToScalar(stops - 1); colors[i] = skiaRandomColor(); } SkShader *shader = SkGradientShader::CreateLinear(pts, colors, pos, stops, SkShader::kClamp_TileMode); ctx->skia_paint->setShader(shader); shapes_t shape; shape_copy(&ctx->shape_defaults, &shape); for (int i=0; i<ctx->size; i++) { double x1 = (double)rnd()/RAND_MAX * w; double x2 = (double)rnd()/RAND_MAX * w; double y1 = (double)rnd()/RAND_MAX * h; double y2 = (double)rnd()/RAND_MAX * h; double xx = MIN(x1, x2); double yy = MIN(x1, x2); double ww = abs(x2 - x1); double hh = abs(y2 - y1); ctx->skia_canvas->save(); ctx->skia_canvas->translate(SkDoubleToScalar(xx), SkDoubleToScalar(yy)); ctx->skia_canvas->scale(SkDoubleToScalar(ww/100), SkDoubleToScalar(hh/100)); // transform(shape.width/100, 0, 0, shape.height/100, 0, 0) shape.x = 0; shape.y = 0; shape.width = 100; shape.height = 100; shape.fill_type = CB_FILL_LINEAR_GRADIENT; ctx->skia_paint->setStyle(SkPaint::kFill_Style); ctx->skia_paint->setShader(shader); skiaDrawRectangle(ctx, &shape); ctx->skia_canvas->restore(); } if (shader) shader->unref(); return 1; }
static void writeFrames() { const int scale = 5; for (int index = 0; index < (int) SK_ARRAY_COUNT(frameSizes); ++index) { SkDRect bounds; bool boundsSet = false; int frameSize = frameSizes[index]; for (int fIndex = 0; fIndex < frameSize; ++fIndex) { const SkDConic& dC = frames[index][fIndex]; SkDConic dConic = {{{ {dC.fPts[0].fX * scale, dC.fPts[0].fY * scale }, {dC.fPts[1].fX * scale, dC.fPts[1].fY * scale }, {dC.fPts[2].fX * scale, dC.fPts[2].fY * scale }}}, dC.fWeight }; SkDRect dBounds; dBounds.setBounds(dConic); if (!boundsSet) { bounds = dBounds; boundsSet = true; } else { bounds.add((SkDPoint&) dBounds.fLeft); bounds.add((SkDPoint&) dBounds.fRight); } } bounds.fLeft -= 10; bounds.fTop -= 10; bounds.fRight += 10; bounds.fBottom += 10; SkBitmap bitmap; bitmap.tryAllocPixels(SkImageInfo::MakeN32Premul( SkScalarRoundToInt(SkDoubleToScalar(bounds.width())), SkScalarRoundToInt(SkDoubleToScalar(bounds.height())))); SkCanvas canvas(bitmap); SkPaint paint; paint.setAntiAlias(true); paint.setStyle(SkPaint::kStroke_Style); canvas.translate(SkDoubleToScalar(-bounds.fLeft), SkDoubleToScalar(-bounds.fTop)); canvas.drawColor(SK_ColorWHITE); for (int fIndex = 0; fIndex < frameSize; ++fIndex) { const SkDConic& dC = frames[index][fIndex]; SkDConic dConic = {{{ {dC.fPts[0].fX * scale, dC.fPts[0].fY * scale }, {dC.fPts[1].fX * scale, dC.fPts[1].fY * scale }, {dC.fPts[2].fX * scale, dC.fPts[2].fY * scale }}}, dC.fWeight }; SkPath path; path.moveTo(dConic.fPts[0].asSkPoint()); path.conicTo(dConic.fPts[1].asSkPoint(), dConic.fPts[2].asSkPoint(), dConic.fWeight); if (fIndex < 2) { paint.setARGB(0x80, 0xFF, 0, 0); } else { paint.setARGB(0x80, 0, 0, 0xFF); } canvas.drawPath(path, paint); } SkString filename("c:\\Users\\caryclark\\Documents\\"); filename.appendf("f%d.png", index); SkImageEncoder::EncodeFile(filename.c_str(), bitmap, SkImageEncoder::kPNG_Type, 100); } }
FontMgrBoundsGM(double scale, double skew) : fScaleX(SkDoubleToScalar(scale)) , fSkewX(SkDoubleToScalar(skew)) { fName.set("fontmgr_bounds"); if (scale != 1 || skew != 0) { fName.appendf("_%g_%g", scale, skew); } fFM.reset(SkFontMgr::RefDefault()); }
void Path2D::LineTo(const v8::FunctionCallbackInfo<Value>& args) { if (args.Length() != 2) { args.GetIsolate()->ThrowException( v8::String::NewFromUtf8( args.GetIsolate(), "Error: 2 arguments required.")); return; } double x = args[0]->NumberValue(); double y = args[1]->NumberValue(); Path2D* path = Unwrap(args); path->fSkPath.lineTo(SkDoubleToScalar(x), SkDoubleToScalar(y)); }
FontMgrBoundsGM(double scale, double skew) : fScaleX(SkDoubleToScalar(scale)) , fSkewX(SkDoubleToScalar(skew)) { fName.set("fontmgr_bounds"); if (scale != 1 || skew != 0) { fName.appendf("_%g_%g", scale, skew); } fName.append(sk_tool_utils::platform_os_name()); fName.append(sk_tool_utils::platform_extra_config("GDI")); fFM.reset(SkFontMgr::RefDefault()); }
void WRasterImage::drawImage(const WRectF& rect, const std::string& imgUri, int imgWidth, int imgHeight, const WRectF& srect) { SkBitmap bitmap; bool success = false; if (DataUri::isDataUri(imgUri)) { DataUri uri(imgUri); success = SkImageDecoder::DecodeMemory(&uri.data[0], uri.data.size(), &bitmap, SkBitmap::kARGB_8888_Config, SkImageDecoder::kDecodePixels_Mode, 0); if (!success) throw WException("WRasterImage: could not decode data URL (mime type " + uri.mimeType); } else { success = SkImageDecoder::DecodeFile(imgUri.c_str(), &bitmap, SkBitmap::kARGB_8888_Config, SkImageDecoder::kDecodePixels_Mode, 0); if (!success) throw WException("WRasterImage: could not load file " + imgUri); } SkRect src = SkRect::MakeLTRB(SkDoubleToScalar(srect.left()), SkDoubleToScalar(srect.top()), SkDoubleToScalar(srect.right()), SkDoubleToScalar(srect.bottom())); SkRect dst = SkRect::MakeLTRB(SkDoubleToScalar(rect.left()), SkDoubleToScalar(rect.top()), SkDoubleToScalar(rect.right()), SkDoubleToScalar(rect.bottom())); impl_->canvas_->drawBitmapRectToRect(bitmap, &src, dst); }
int sk_test_image_rotate(caskbench_context_t *ctx) { static int counter = 0; int w = ctx->canvas_width; int h = ctx->canvas_height; int iw = bitmap.width(); int ih = bitmap.height(); int pw = w - iw; int ph = h - ih; for (int i=0; i<ctx->size; i++) { double x = (double)rnd()/RAND_MAX * pw; double y = (double)rnd()/RAND_MAX * ph; ctx->skia_canvas->save(); ctx->skia_canvas->translate(w/2, h/2); ctx->skia_canvas->rotate(SkDoubleToScalar(counter/(50.0))); ctx->skia_canvas->translate(-iw/2, -ih/2); ctx->skia_canvas->drawBitmap(bitmap, 0, 0); ctx->skia_canvas->restore(); counter++; } return 1; }
bool SkDCubic::toFloatPoints(SkPoint* pts) const { const double* dCubic = &fPts[0].fX; SkScalar* cubic = &pts[0].fX; for (int index = 0; index < kPointCount * 2; ++index) { *cubic++ = SkDoubleToScalar(*dCubic++); } return SkScalarsAreFinite(&pts->fX, kPointCount * 2); }
void Path2D::QuadraticCurveTo(const v8::FunctionCallbackInfo<Value>& args) { if (args.Length() != 4) { args.GetIsolate()->ThrowException( v8::String::NewFromUtf8( args.GetIsolate(), "Error: 4 arguments required.")); return; } double cpx = args[0]->NumberValue(); double cpy = args[1]->NumberValue(); double x = args[2]->NumberValue(); double y = args[3]->NumberValue(); Path2D* path = Unwrap(args); // TODO(jcgregorio) Doesn't handle the empty last path case correctly per // the HTML 5 spec. path->fSkPath.quadTo( SkDoubleToScalar(cpx), SkDoubleToScalar(cpy), SkDoubleToScalar(x), SkDoubleToScalar(y)); }
SkScalar get_anim_sin(double secs, SkScalar amplitude, SkScalar periodInSec, SkScalar phaseInSec) { if (!periodInSec) { return 0; } double t = secs + phaseInSec; t *= SkScalarToFloat(2 * SK_ScalarPI) / periodInSec; amplitude = SK_ScalarHalf * amplitude; return amplitude * SkDoubleToScalar(sin(t)) + amplitude; }
GrStrokeInfo TestStrokeInfo(SkRandom* random) { SkStrokeRec::InitStyle style = SkStrokeRec::InitStyle(random->nextULessThan(SkStrokeRec::kFill_InitStyle + 1)); GrStrokeInfo strokeInfo(style); randomize_stroke_rec(&strokeInfo, random); SkPathEffect::DashInfo dashInfo; dashInfo.fCount = random->nextRangeU(1, 50) * 2; SkAutoTDeleteArray<SkScalar> intervals(SkNEW_ARRAY(SkScalar, dashInfo.fCount)); dashInfo.fIntervals = intervals.get(); SkScalar sum = 0; for (int i = 0; i < dashInfo.fCount; i++) { dashInfo.fIntervals[i] = random->nextRangeScalar(SkDoubleToScalar(0.01), SkDoubleToScalar(10.0)); sum += dashInfo.fIntervals[i]; } dashInfo.fPhase = random->nextRangeScalar(0, sum); strokeInfo.setDashInfo(dashInfo); return strokeInfo; }
static void unit_axis_align(SkVector* unit) { const SkScalar TOLERANCE = SkDoubleToScalar(0.15); if (SkScalarAbs(unit->fX) < TOLERANCE) { unit->fX = 0; unit->fY = SkScalarSign(unit->fY); } else if (SkScalarAbs(unit->fY) < TOLERANCE) { unit->fX = SkScalarSign(unit->fX); unit->fY = 0; } }
/** * Takes argc,argv along with one of the benchmark functions defined above. * Will loop along all skp files and perform measurments. * * Returns a SkScalar representing CPU time taken during benchmark. * As a side effect, it spits the timer result to stdout. * Will return -1.0 on error. */ static bool benchmark_loop( int argc, char **argv, const BenchmarkControl& benchControl, SkTArray<Histogram>& histogram) { static const SkString timeFormat("%f"); TimerData timerData(argc - 1); for (int index = 1; index < argc; ++index) { BenchTimer timer; SkString path(argv[index]); SkAutoTUnref<SkPicture> pic(pic_from_path(path.c_str())); if (NULL == pic) { SkDebugf("Couldn't create picture. Ignoring path: %s\n", path.c_str()); continue; } benchControl.fFunction(benchControl.fType, benchControl.fTileSize, path, pic, &timer); SkAssertResult(timerData.appendTimes(&timer)); histogram[index - 1].fPath = path; histogram[index - 1].fCpuTime = SkDoubleToScalar(timer.fCpu); } const SkString timerResult = timerData.getResult( /*doubleFormat = */ timeFormat.c_str(), /*result = */ TimerData::kAvg_Result, /*configName = */ benchControl.fName.c_str(), /*timerFlags = */ TimerData::kCpu_Flag); const char findStr[] = "= "; int pos = timerResult.find(findStr); if (-1 == pos) { SkDebugf("Unexpected output from TimerData::getResult(...). Unable to parse."); return false; } SkScalar cpuTime = SkDoubleToScalar(atof(timerResult.c_str() + pos + sizeof(findStr) - 1)); if (cpuTime == 0) { // atof returns 0.0 on error. SkDebugf("Unable to read value from timer result.\n"); return false; } return true; }
void SkConvertQuadToCubic(const SkPoint src[3], SkPoint dst[4]) { Sk2s scale(SkDoubleToScalar(2.0 / 3.0)); Sk2s s0 = from_point(src[0]); Sk2s s1 = from_point(src[1]); Sk2s s2 = from_point(src[2]); dst[0] = src[0]; dst[1] = to_point(s0 + (s1 - s0) * scale); dst[2] = to_point(s2 + (s1 - s2) * scale); dst[3] = src[2]; }
SkScalar SampleCode::GetAnimScalar(SkScalar speed, SkScalar period) { // since gAnimTime can be up to 32 bits, we can't convert it to a float // or we'll lose the low bits. Hence we use doubles for the intermediate // calculations double seconds = (double)gAnimTime / 1000.0; double value = SkScalarToDouble(speed) * seconds; if (period) { value = ::fmod(value, SkScalarToDouble(period)); } return SkDoubleToScalar(value); }
void TestStyle(SkRandom* random, GrStyle* style) { SkStrokeRec::InitStyle initStyle = SkStrokeRec::InitStyle(random->nextULessThan(SkStrokeRec::kFill_InitStyle + 1)); SkStrokeRec stroke(initStyle); randomize_stroke_rec(&stroke, random); sk_sp<SkPathEffect> pe; if (random->nextBool()) { int cnt = random->nextRangeU(1, 50) * 2; std::unique_ptr<SkScalar[]> intervals(new SkScalar[cnt]); SkScalar sum = 0; for (int i = 0; i < cnt; i++) { intervals[i] = random->nextRangeScalar(SkDoubleToScalar(0.01), SkDoubleToScalar(10.0)); sum += intervals[i]; } SkScalar phase = random->nextRangeScalar(0, sum); pe = TestDashPathEffect::Make(intervals.get(), cnt, phase); } *style = GrStyle(stroke, std::move(pe)); }
static void writeDPng(const SkDConic& dC, const char* name) { const int scale = 5; SkDConic dConic = {{{ {dC.fPts[0].fX * scale, dC.fPts[0].fY * scale }, {dC.fPts[1].fX * scale, dC.fPts[1].fY * scale }, {dC.fPts[2].fX * scale, dC.fPts[2].fY * scale }}}, dC.fWeight }; SkBitmap bitmap; SkDRect bounds; bounds.setBounds(dConic); bounds.fLeft -= 10; bounds.fTop -= 10; bounds.fRight += 10; bounds.fBottom += 10; bitmap.tryAllocPixels(SkImageInfo::MakeN32Premul( SkScalarRoundToInt(SkDoubleToScalar(bounds.width())), SkScalarRoundToInt(SkDoubleToScalar(bounds.height())))); SkCanvas canvas(bitmap); SkPaint paint; paint.setAntiAlias(true); paint.setStyle(SkPaint::kStroke_Style); canvas.translate(SkDoubleToScalar(-bounds.fLeft), SkDoubleToScalar(-bounds.fTop)); canvas.drawColor(SK_ColorWHITE); SkPath path; path.moveTo(dConic.fPts[0].asSkPoint()); path.conicTo(dConic.fPts[1].asSkPoint(), dConic.fPts[2].asSkPoint(), dConic.fWeight); paint.setARGB(0x80, 0xFF, 0, 0); canvas.drawPath(path, paint); path.reset(); const int chops = 2; for (int tIndex = 0; tIndex < chops; ++tIndex) { SkDConic chopped = dConic.subDivide(tIndex / (double) chops, (tIndex + 1) / (double) chops); path.moveTo(chopped.fPts[0].asSkPoint()); path.conicTo(chopped.fPts[1].asSkPoint(), chopped.fPts[2].asSkPoint(), chopped.fWeight); } paint.setARGB(0x80, 0, 0, 0xFF); canvas.drawPath(path, paint); SkString filename("c:\\Users\\caryclark\\Documents\\"); filename.appendf("%s.png", name); SkImageEncoder::EncodeFile(filename.c_str(), bitmap, SkImageEncoder::kPNG_Type, 100); }
void Path2D::ConicTo(const v8::FunctionCallbackInfo<Value>& args) { if (args.Length() != 5) { args.GetIsolate()->ThrowException( v8::String::NewFromUtf8( args.GetIsolate(), "Error: 5 args required.")); return; } double x1 = args[0]->NumberValue(); double y1 = args[1]->NumberValue(); double x2 = args[2]->NumberValue(); double y2 = args[3]->NumberValue(); double w = args[4]->NumberValue(); Path2D* path = Unwrap(args); path->fSkPath.conicTo( SkDoubleToScalar(x1), SkDoubleToScalar(y1), SkDoubleToScalar(x2), SkDoubleToScalar(y2), SkDoubleToScalar(w) ); }
void WRasterImage::Impl::applyTransform(const WTransform& t) { SkMatrix sm; sm.setAll(SkDoubleToScalar(t.m11()), SkDoubleToScalar(t.m12()), SkDoubleToScalar(t.dx()), SkDoubleToScalar(t.m21()), SkDoubleToScalar(t.m22()), SkDoubleToScalar(t.dy()), 0, 0, SkDoubleToScalar(1.0)); canvas_->concat(sm); }
void onDraw(SkCanvas* canvas) override { SkPaint paint; paint.setAntiAlias(true); paint.setLCDRenderText(true); SkAutoTUnref<SkFontMgr> fontMgr(SkFontMgr::RefDefault()); SkAutoTDelete<SkStreamAsset> distortable(GetResourceAsStream("/fonts/Distortable.ttf")); if (!distortable) { return; } const char* text = "abc"; const size_t textLen = strlen(text); for (int j = 0; j < 2; ++j) { for (int i = 0; i < 5; ++i) { SkScalar x = SkIntToScalar(10); SkScalar y = SkIntToScalar(20); SkFourByteTag tag = SkSetFourByteTag('w','g','h','t'); SkScalar styleValue = SkDoubleToScalar(0.5 + (5*j + i) * ((2.0 - 0.5) / (2 * 5))); SkFontMgr::FontParameters::Axis axes[] = { { tag, styleValue } }; paint.setTypeface(sk_sp<SkTypeface>(fontMgr->createFromStream( distortable->duplicate(), SkFontMgr::FontParameters().setAxes(axes, 1)))); SkAutoCanvasRestore acr(canvas, true); canvas->translate(SkIntToScalar(30 + i * 100), SkIntToScalar(20)); rotate_about(canvas, SkIntToScalar(i * 5), x, y * 10); { SkPaint p; p.setAntiAlias(true); SkRect r; r.set(x - SkIntToScalar(3), SkIntToScalar(15), x - SkIntToScalar(1), SkIntToScalar(280)); canvas->drawRect(r, p); } for (int ps = 6; ps <= 22; ps++) { paint.setTextSize(SkIntToScalar(ps)); canvas->drawText(text, textLen, x, y, paint); y += paint.getFontMetrics(nullptr); } } canvas->translate(0, SkIntToScalar(360)); paint.setSubpixelText(true); } }
void WRasterImage::drawArc(const WRectF& rect, double startAngle, double spanAngle) { SkRect r = SkRect::MakeLTRB(SkDoubleToScalar(rect.left()), SkDoubleToScalar(rect.top()), SkDoubleToScalar(rect.right()), SkDoubleToScalar(rect.bottom())); if (painter()->brush().style() != NoBrush) { impl_->canvas_->drawArc(r, SkDoubleToScalar(-startAngle), SkDoubleToScalar(-spanAngle), false, impl_->fillPaint_); } if (painter()->pen().style() != NoPen) { impl_->canvas_->drawArc(r, SkDoubleToScalar(-startAngle), SkDoubleToScalar(-spanAngle), false, impl_->strokePaint_); } }
static void chopBothWays(const SkDConic& dConic, double t, const char* name) { SkConic conic; for (int index = 0; index < 3; ++index) { conic.fPts[index] = dConic.fPts[index].asSkPoint(); } conic.fW = dConic.fWeight; SkConic chopped[2]; SkDConic dChopped[2]; conic.chopAt(SkDoubleToScalar(t), chopped); dChopped[0] = dConic.subDivide(0, t); dChopped[1] = dConic.subDivide(t, 1); #if DEBUG_VISUALIZE_CONICS dConic.dump(); #endif chopCompare(chopped, dChopped); #if DEBUG_VISUALIZE_CONICS writePng(conic, chopped, name); #endif }
/* see quad subdivide for rationale */ SkDConic SkDConic::subDivide(double t1, double t2) const { double ax, ay, az; if (t1 == 0) { ax = fPts[0].fX; ay = fPts[0].fY; az = 1; } else if (t1 != 1) { ax = conic_eval_numerator(&fPts[0].fX, fWeight, t1); ay = conic_eval_numerator(&fPts[0].fY, fWeight, t1); az = conic_eval_denominator(fWeight, t1); } else { ax = fPts[2].fX; ay = fPts[2].fY; az = 1; } double midT = (t1 + t2) / 2; double dx = conic_eval_numerator(&fPts[0].fX, fWeight, midT); double dy = conic_eval_numerator(&fPts[0].fY, fWeight, midT); double dz = conic_eval_denominator(fWeight, midT); double cx, cy, cz; if (t2 == 1) { cx = fPts[2].fX; cy = fPts[2].fY; cz = 1; } else if (t2 != 0) { cx = conic_eval_numerator(&fPts[0].fX, fWeight, t2); cy = conic_eval_numerator(&fPts[0].fY, fWeight, t2); cz = conic_eval_denominator(fWeight, t2); } else { cx = fPts[0].fX; cy = fPts[0].fY; cz = 1; } double bx = 2 * dx - (ax + cx) / 2; double by = 2 * dy - (ay + cy) / 2; double bz = 2 * dz - (az + cz) / 2; double dt = t2 - t1; double dt_1 = 1 - dt; SkScalar w = SkDoubleToScalar((1 + dt * (fWeight - 1)) / sqrt(dt * dt + 2 * dt * dt_1 * fWeight + dt_1 * dt_1)); SkDConic dst = {{{{ax / az, ay / az}, {bx / bz, by / bz}, {cx / cz, cy / cz}}}, w }; return dst; }
void onDraw(SkCanvas* canvas) override { SkAutoTUnref<SkImageFilter> gradient(SkImageSource::Create(fGradientCircle)); SkAutoTUnref<SkImageFilter> checkerboard(SkImageSource::Create(fCheckerboard)); SkImageFilter* filters[] = { SkBlurImageFilter::Create(12, 0), SkDropShadowImageFilter::Create(0, 15, 8, 0, SK_ColorGREEN, SkDropShadowImageFilter::kDrawShadowAndForeground_ShadowMode), SkDisplacementMapEffect::Create(SkDisplacementMapEffect::kR_ChannelSelectorType, SkDisplacementMapEffect::kR_ChannelSelectorType, 12, gradient.get(), checkerboard.get()), SkDilateImageFilter::Create(2, 2, checkerboard.get()), SkErodeImageFilter::Create(2, 2, checkerboard.get()), }; const SkScalar margin = SkIntToScalar(20); const SkScalar size = SkIntToScalar(60); for (size_t j = 0; j < 3; j++) { canvas->save(); canvas->translate(margin, 0); for (size_t i = 0; i < SK_ARRAY_COUNT(filters); ++i) { SkPaint paint; paint.setColor(SK_ColorWHITE); paint.setImageFilter(filters[i]); paint.setAntiAlias(true); canvas->save(); canvas->translate(size * SK_ScalarHalf, size * SK_ScalarHalf); canvas->scale(SkDoubleToScalar(0.8), SkDoubleToScalar(0.8)); if (j == 1) { canvas->rotate(SkIntToScalar(45)); } else if (j == 2) { canvas->skew(SkDoubleToScalar(0.5), SkDoubleToScalar(0.2)); } canvas->translate(-size * SK_ScalarHalf, -size * SK_ScalarHalf); canvas->drawOval(SkRect::MakeXYWH(0, size * SkDoubleToScalar(0.1), size, size * SkDoubleToScalar(0.6)), paint); canvas->restore(); canvas->translate(size + margin, 0); } canvas->restore(); canvas->translate(0, size + margin); } for (size_t i = 0; i < SK_ARRAY_COUNT(filters); ++i) { SkSafeUnref(filters[i]); } }