void onDraw(SkCanvas* canvas) override { // There's a black pixel at 40, 40 for reference. canvas->drawPoint(40.0f, 40.0f, SK_ColorBLACK); // Two reference images. canvas->translate(50.0f, 50.0f); drawTestCase(canvas, 1.0f); canvas->translate(0.0f, 50.0f); drawTestCase(canvas, 3.0f); // Uniform scaling test. canvas->translate(0.0f, 100.0f); canvas->save(); canvas->scale(3.0f, 3.0f); drawTestCase(canvas, 1.0f); canvas->restore(); // Non-uniform scaling test. canvas->translate(0.0f, 100.0f); canvas->save(); canvas->scale(3.0f, 6.0f); drawTestCase(canvas, 1.0f); canvas->restore(); // Skew test. canvas->translate(0.0f, 80.0f); canvas->save(); canvas->scale(3.0f, 3.0f); SkMatrix skew; skew.setIdentity(); skew.setSkewX(8.0f / 25.0f); skew.setSkewY(2.0f / 25.0f); canvas->concat(skew); drawTestCase(canvas, 1.0f); canvas->restore(); // Perspective test. canvas->translate(0.0f, 80.0f); canvas->save(); SkMatrix perspective; perspective.setIdentity(); perspective.setPerspX(-SkScalarInvert(340)); perspective.setSkewX(8.0f / 25.0f); perspective.setSkewY(2.0f / 25.0f); canvas->concat(perspective); drawTestCase(canvas, 1.0f); canvas->restore(); }
void anchor_handle_renderer::draw_anchor (SkCanvas &canvas, const SkRect &rect, SkPaint &paint) const { switch (m_node_type) { case handle_type::DIAMOND: { canvas.save (); canvas.translate (rect.centerX (), rect.centerY ()); canvas.rotate (45); SkRect moved_rect = rect; moved_rect.offset (-rect.centerX (), -rect.centerY ()); paint.setAntiAlias (true); canvas.drawRect (moved_rect, paint); canvas.restore (); break; } case handle_type::SQUARE: canvas.drawRect (rect, paint); break; case handle_type::CIRCLE: canvas.drawOval (rect, paint); break; case handle_type::DOUBLE_HEADED_ARROW: case handle_type::ROTATE_ARROW: SkPath path = qt2skia::path (*m_paths.at (m_node_type)); SkMatrix trans; trans.setIdentity (); trans.postRotate (m_rotation_angle, 32, 32); // TODO: change all these to use info from path_storage (bounding box and center (possibly should be made 0)) trans.postConcat (qt2skia::matrix (geom::rect2rect (QRectF (0, 0, 64, 64), qt2skia::rect (rect)))); path.transform (trans); paint.setAntiAlias (true); canvas.drawPath (path, paint); break; } }
virtual void onDraw(SkCanvas* canvas) { SkPoint pts[2] = { { 0, 0 }, { SkIntToScalar(100), SkIntToScalar(100) } }; SkShader::TileMode tm = SkShader::kClamp_TileMode; SkRect r = { 0, 0, SkIntToScalar(100), SkIntToScalar(100) }; SkPaint paint; paint.setAntiAlias(true); canvas->translate(SkIntToScalar(20), SkIntToScalar(20)); for (size_t i = 0; i < SK_ARRAY_COUNT(gGradData); i++) { canvas->save(); for (size_t j = 0; j < SK_ARRAY_COUNT(gGradMakers); j++) { SkShader* shader = gGradMakers[j](pts, gGradData[i], tm, NULL); // apply an increasing y perspective as we move to the right SkMatrix perspective; perspective.setIdentity(); perspective.setPerspY(SkScalarDiv(SkIntToScalar((unsigned) i+1), SkIntToScalar(500))); perspective.setSkewX(SkScalarDiv(SkIntToScalar((unsigned) i+1), SkIntToScalar(10))); shader->setLocalMatrix(perspective); paint.setShader(shader); canvas->drawRect(r, paint); shader->unref(); canvas->translate(0, SkIntToScalar(120)); } canvas->restore(); canvas->translate(SkIntToScalar(120), 0); } }
sk_shader_t* sk_shader_new_two_point_conical_gradient(const sk_point_t* start, float startRadius, const sk_point_t* end, float endRadius, const sk_color_t colors[], const float colorPos[], int colorCount, sk_shader_tilemode_t cmode, const sk_matrix_t* cmatrix) { SkTileMode mode; if (!from_c_tilemode(cmode, &mode)) { return nullptr; } SkMatrix matrix; if (cmatrix) { from_c_matrix(cmatrix, &matrix); } else { matrix.setIdentity(); } SkPoint skstart = to_skpoint(*start); SkPoint skend = to_skpoint(*end); return (sk_shader_t*)SkGradientShader::MakeTwoPointConical(skstart, (SkScalar)startRadius, skend, (SkScalar)endRadius, reinterpret_cast<const SkColor*>(colors), reinterpret_cast<const SkScalar*>(colorPos), colorCount, mode, 0, &matrix).release(); }
GiantDashBench(LineType lt, SkScalar width) { fName.printf("giantdashline_%s_%g", LineTypeName(lt), width); fStrokeWidth = width; // deliberately pick intervals that won't be caught by asPoints(), so // we can test the filterPath code-path. const SkScalar intervals[] = { 20, 10, 10, 10 }; fPathEffect.reset(SkDashPathEffect::Create(intervals, SK_ARRAY_COUNT(intervals), 0)); SkScalar cx = 640 / 2; // center X SkScalar cy = 480 / 2; // center Y SkMatrix matrix; switch (lt) { case kHori_LineType: matrix.setIdentity(); break; case kVert_LineType: matrix.setRotate(90, cx, cy); break; case kDiag_LineType: matrix.setRotate(45, cx, cy); break; case kLineTypeCount: // Not a real enum value. break; } const SkScalar overshoot = 100*1000; const SkPoint pts[2] = { { -overshoot, cy }, { 640 + overshoot, cy } }; matrix.mapPoints(fPts, pts, 2); }
void onDraw(int loops, SkCanvas* canvas) override { SkPaint paint; paint.setAntiAlias(fAA); paint.setBlendMode(fMode); SkColor color = start_color(fColorType); int w = this->getSize().x(); int h = this->getSize().y(); static const SkScalar kRectW = 25.1f; static const SkScalar kRectH = 25.9f; if (fColorType == kShaderOpaque_ColorType) { // The only requirement for the shader is that it requires local coordinates SkPoint pts[2] = { {0.0f, 0.0f}, {kRectW, kRectH} }; SkColor colors[] = { color, SK_ColorBLUE }; paint.setShader(SkGradientShader::MakeLinear(pts, colors, nullptr, 2, SkTileMode::kClamp)); } SkMatrix rotate; // This value was chosen so that we frequently hit the axis-aligned case. rotate.setRotate(30.f, kRectW / 2, kRectH / 2); SkMatrix m = rotate; SkScalar tx = 0, ty = 0; if (fPerspective) { // Apply some fixed perspective to change how ops may draw the rects SkMatrix perspective; perspective.setIdentity(); perspective.setPerspX(1e-4f); perspective.setPerspY(1e-3f); perspective.setSkewX(0.1f); canvas->concat(perspective); } for (int i = 0; i < loops; ++i) { canvas->save(); canvas->translate(tx, ty); canvas->concat(m); paint.setColor(color); color = advance_color(color, fColorType, i); canvas->drawRect(SkRect::MakeWH(kRectW, kRectH), paint); canvas->restore(); tx += kRectW + 2; if (tx > w) { tx = 0; ty += kRectH + 2; if (ty > h) { ty = 0; } } m.postConcat(rotate); } }
virtual void onDraw(SkCanvas* canvas) { SkMatrix perspective; perspective.setIdentity(); perspective.setPerspY(SkScalarDiv(SK_Scalar1, SkIntToScalar(1000))); perspective.setSkewX(SkScalarDiv(SkIntToScalar(8), SkIntToScalar(25))); canvas->concat(perspective); INHERITED::onDraw(canvas); }
void draw(SkCanvas* canvas) { SkPaint paint; paint.setAntiAlias(true); paint.setTextSize(24); canvas->drawString("normal", 12, 24, paint); SkMatrix matrix; matrix.setIdentity(); matrix.setSkewX(-.7f); canvas->concat(matrix); canvas->drawString("x skew", 36, 48, paint); }
static void android_view_RenderNode_getInverseTransformMatrix(JNIEnv* env, jobject clazz, jlong renderNodePtr, jlong outMatrixPtr) { // load transform matrix android_view_RenderNode_getTransformMatrix(env, clazz, renderNodePtr, outMatrixPtr); SkMatrix* outMatrix = reinterpret_cast<SkMatrix*>(outMatrixPtr); // return it inverted if (!outMatrix->invert(outMatrix)) { // failed to load inverse, pass back identity outMatrix->setIdentity(); } }
void OsmAnd::MapRasterizer_P::rasterizePolylineIcons( const Context& context, SkCanvas& canvas, const SkPath& path, const MapStyleEvaluationResult& evalResult) { bool ok; QString pathIconName; ok = evalResult.getStringValue(context.env->styleBuiltinValueDefs->id_OUTPUT_PATH_ICON, pathIconName); if (!ok || pathIconName.isEmpty()) return; float pathIconStep = 0.0f; ok = evalResult.getFloatValue(context.env->styleBuiltinValueDefs->id_OUTPUT_PATH_ICON_STEP, pathIconStep); if (!ok || pathIconStep <= 0.0f) return; std::shared_ptr<const SkBitmap> pathIcon; ok = context.env->obtainMapIcon(pathIconName, pathIcon); if (!ok || !pathIcon) return; SkMatrix mIconTransform; mIconTransform.setIdentity(); mIconTransform.setTranslate(-0.5f * pathIcon->width(), -0.5f * pathIcon->height()); mIconTransform.postRotate(90.0f); SkPathMeasure pathMeasure(path, false); const auto length = pathMeasure.getLength(); auto iconOffset = 0.5f * pathIconStep; const auto iconInstancesCount = static_cast<int>((length - iconOffset) / pathIconStep) + 1; if (iconInstancesCount < 1) return; SkMatrix mIconInstanceTransform; for (auto iconInstanceIdx = 0; iconInstanceIdx < iconInstancesCount; iconInstanceIdx++, iconOffset += pathIconStep) { SkMatrix mPinPoint; ok = pathMeasure.getMatrix(iconOffset, &mPinPoint); if (!ok) break; mIconInstanceTransform.setConcat(mPinPoint, mIconTransform); canvas.save(); canvas.concat(mIconInstanceTransform); canvas.drawBitmap(*pathIcon, 0, 0, &_defaultPaint); canvas.restore(); } }
static void android_view_RenderNode_getTransformMatrix(JNIEnv* env, jobject clazz, jlong renderNodePtr, jlong outMatrixPtr) { RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); SkMatrix* outMatrix = reinterpret_cast<SkMatrix*>(outMatrixPtr); renderNode->mutateStagingProperties().updateMatrix(); const SkMatrix* transformMatrix = renderNode->stagingProperties().getTransformMatrix(); if (transformMatrix) { *outMatrix = *transformMatrix; } else { outMatrix->setIdentity(); } }
void makeMatrices() { { SkMatrix m; m.setIdentity(); fMatrices.push_back(m); } { SkMatrix m; m.setScale(SkIntToScalar(3), SkIntToScalar(2)); fMatrices.push_back(m); } { SkMatrix m; m.setScale(SkIntToScalar(2), SkIntToScalar(2)); fMatrices.push_back(m); } { SkMatrix m; m.setScale(SkIntToScalar(1), SkIntToScalar(2)); fMatrices.push_back(m); } { SkMatrix m; m.setScale(SkIntToScalar(4), SkIntToScalar(1)); fMatrices.push_back(m); } { SkMatrix m; m.setRotate(SkIntToScalar(90)); fMatrices.push_back(m); } { SkMatrix m; m.setSkew(SkIntToScalar(2), SkIntToScalar(3)); fMatrices.push_back(m); } { SkMatrix m; m.setRotate(SkIntToScalar(60)); fMatrices.push_back(m); } }
void draw(SkCanvas* canvas) { SkMatrix m; m.setIdentity(); m.set(SkMatrix::kMPersp0, -0.004f); SkAutoCanvasRestore autoRestore(canvas, true); canvas->translate(22, 144); SkPaint black; black.setAntiAlias(true); black.setTextSize(24); SkPaint gray = black; gray.setColor(0xFF9f9f9f); SkString string; string.appendScalar(m.getPerspX()); canvas->drawString(string, 0, -72, gray); canvas->concat(m); canvas->drawString(string, 0, 0, black); }
sk_shader_t* sk_shader_new_sweep_gradient(const sk_point_t* ccenter, const sk_color_t colors[], const float colorPos[], int colorCount, const sk_matrix_t* cmatrix) { SkMatrix matrix; if (cmatrix) { from_c_matrix(cmatrix, &matrix); } else { matrix.setIdentity(); } return (sk_shader_t*)SkGradientShader::MakeSweep((SkScalar)(ccenter->x), (SkScalar)(ccenter->y), reinterpret_cast<const SkColor*>(colors), reinterpret_cast<const SkScalar*>(colorPos), colorCount, 0, &matrix).release(); }
void draw(SkCanvas* canvas) { SkPaint black; black.setAntiAlias(true); black.setTextSize(48); SkPaint gray = black; gray.setColor(0xFF9f9f9f); SkScalar offset[] = { 1.5f, 1.5f, 20, 1.5f, 1.5f, 20, .03f, .01f, 2 }; for (int i : { SkMatrix::kMScaleX, SkMatrix::kMSkewX, SkMatrix::kMTransX, SkMatrix::kMSkewY, SkMatrix::kMScaleY, SkMatrix::kMTransY, SkMatrix::kMPersp0, SkMatrix::kMPersp1, SkMatrix::kMPersp2 } ) { SkMatrix m; m.setIdentity(); m.set(i, offset[i]); SkAutoCanvasRestore autoRestore(canvas, true); canvas->translate(22 + (i % 3) * 88, 44 + (i / 3) * 88); canvas->drawString("&", 0, 0, gray); canvas->concat(m); canvas->drawString("&", 0, 0, black); } }
sk_shader_t* sk_shader_new_linear_gradient(const sk_point_t pts[2], const sk_color_t colors[], const float colorPos[], int colorCount, sk_shader_tilemode_t cmode, const sk_matrix_t* cmatrix) { SkShader::TileMode mode; if (!from_c_tilemode(cmode, &mode)) { return NULL; } SkMatrix matrix; if (cmatrix) { from_c_matrix(cmatrix, &matrix); } else { matrix.setIdentity(); } SkShader* s = SkGradientShader::CreateLinear(reinterpret_cast<const SkPoint*>(pts), reinterpret_cast<const SkColor*>(colors), colorPos, colorCount, mode, 0, &matrix); return (sk_shader_t*)s; }
sk_shader_t* sk_shader_new_radial_gradient(const sk_point_t* ccenter, float radius, const sk_color_t colors[], const float colorPos[], int colorCount, sk_shader_tilemode_t cmode, const sk_matrix_t* cmatrix) { SkTileMode mode; if (!from_c_tilemode(cmode, &mode)) { return nullptr; } SkMatrix matrix; if (cmatrix) { from_c_matrix(cmatrix, &matrix); } else { matrix.setIdentity(); } SkPoint center = to_skpoint(*ccenter); return (sk_shader_t*)SkGradientShader::MakeRadial(center, (SkScalar)radius, reinterpret_cast<const SkColor*>(colors), reinterpret_cast<const SkScalar*>(colorPos), colorCount, mode, 0, &matrix).release(); }
static void test_matrix_is_similarity(skiatest::Reporter* reporter) { SkMatrix mat; // identity mat.setIdentity(); REPORTER_ASSERT(reporter, mat.isSimilarity()); // translation only mat.reset(); mat.setTranslate(SkIntToScalar(100), SkIntToScalar(100)); REPORTER_ASSERT(reporter, mat.isSimilarity()); // scale with same size mat.reset(); mat.setScale(SkIntToScalar(15), SkIntToScalar(15)); REPORTER_ASSERT(reporter, mat.isSimilarity()); // scale with one negative mat.reset(); mat.setScale(SkIntToScalar(-15), SkIntToScalar(15)); REPORTER_ASSERT(reporter, mat.isSimilarity()); // scale with different size mat.reset(); mat.setScale(SkIntToScalar(15), SkIntToScalar(20)); REPORTER_ASSERT(reporter, !mat.isSimilarity()); // scale with same size at a pivot point mat.reset(); mat.setScale(SkIntToScalar(15), SkIntToScalar(15), SkIntToScalar(2), SkIntToScalar(2)); REPORTER_ASSERT(reporter, mat.isSimilarity()); // scale with different size at a pivot point mat.reset(); mat.setScale(SkIntToScalar(15), SkIntToScalar(20), SkIntToScalar(2), SkIntToScalar(2)); REPORTER_ASSERT(reporter, !mat.isSimilarity()); // skew with same size mat.reset(); mat.setSkew(SkIntToScalar(15), SkIntToScalar(15)); REPORTER_ASSERT(reporter, !mat.isSimilarity()); // skew with different size mat.reset(); mat.setSkew(SkIntToScalar(15), SkIntToScalar(20)); REPORTER_ASSERT(reporter, !mat.isSimilarity()); // skew with same size at a pivot point mat.reset(); mat.setSkew(SkIntToScalar(15), SkIntToScalar(15), SkIntToScalar(2), SkIntToScalar(2)); REPORTER_ASSERT(reporter, !mat.isSimilarity()); // skew with different size at a pivot point mat.reset(); mat.setSkew(SkIntToScalar(15), SkIntToScalar(20), SkIntToScalar(2), SkIntToScalar(2)); REPORTER_ASSERT(reporter, !mat.isSimilarity()); // perspective x mat.reset(); mat.setPerspX(SkScalarToPersp(SK_Scalar1 / 2)); REPORTER_ASSERT(reporter, !mat.isSimilarity()); // perspective y mat.reset(); mat.setPerspY(SkScalarToPersp(SK_Scalar1 / 2)); REPORTER_ASSERT(reporter, !mat.isSimilarity()); // rotate for (int angle = 0; angle < 360; ++angle) { mat.reset(); mat.setRotate(SkIntToScalar(angle)); REPORTER_ASSERT(reporter, mat.isSimilarity()); } // see if there are any accumulated precision issues mat.reset(); for (int i = 1; i < 360; i++) { mat.postRotate(SkIntToScalar(1)); } REPORTER_ASSERT(reporter, mat.isSimilarity()); // rotate + translate mat.reset(); mat.setRotate(SkIntToScalar(30)); mat.postTranslate(SkIntToScalar(10), SkIntToScalar(20)); REPORTER_ASSERT(reporter, mat.isSimilarity()); // rotate + uniform scale mat.reset(); mat.setRotate(SkIntToScalar(30)); mat.postScale(SkIntToScalar(2), SkIntToScalar(2)); REPORTER_ASSERT(reporter, mat.isSimilarity()); // rotate + non-uniform scale mat.reset(); mat.setRotate(SkIntToScalar(30)); mat.postScale(SkIntToScalar(3), SkIntToScalar(2)); REPORTER_ASSERT(reporter, !mat.isSimilarity()); // all zero mat.setAll(0, 0, 0, 0, 0, 0, 0, 0, 0); REPORTER_ASSERT(reporter, !mat.isSimilarity()); // all zero except perspective mat.setAll(0, 0, 0, 0, 0, 0, 0, 0, SK_Scalar1); REPORTER_ASSERT(reporter, !mat.isSimilarity()); // scales zero, only skews mat.setAll(0, SK_Scalar1, 0, SK_Scalar1, 0, 0, 0, 0, SkMatrix::I()[8]); REPORTER_ASSERT(reporter, mat.isSimilarity()); }
void TextArtView::onDrawContent(SkCanvas* canvas) { const std::string TEXT = "Helpo TextArt Effects"; SkTypeface* typeface = SkTypeface::CreateFromName("Georgia", SkTypeface::kBold); if (!initialized) { initialized = true; WarpFrameT warpFrame; SkMatrix warpMatrix; warpMatrix.setIdentity(); getWarpParams(warpFrame, warpMatrix); bSkeleton_ = warpFrame[0]; if (warpFrame.size()>1) tSkeleton_ = warpFrame[1]; TextArt::EnvelopeWarp textArt(bSkeleton_, warpMatrix); textArt.setTopSkeleton(tSkeleton_); textArt.setIsNormalRotated(getIsNormalRotated()); textArt.setIsSymmetric(getIsSymmetric()); textArt.setIsTopBased(getIsTopBased()); path_ = textArt.warp(TEXT, typeface); } SkPaint paint; paint.setAntiAlias(true); paint.setTextSize(SkIntToScalar(64)); paint.setStyle(SkPaint::kStroke_Style); paint.setTypeface(typeface); canvas->save(); //center path on the cnavas const SkRect& pathBounds = path_.getBounds(); SkISize screenSize = canvas->getDeviceSize(); SkScalar xOffset = SkScalarHalf( SkIntToScalar(screenSize.width()) ) - pathBounds.centerX(); SkScalar yOffset = SkScalarHalf( SkIntToScalar(screenSize.height()) ) - pathBounds.centerY(); canvas->translate(xOffset, yOffset); paint.setColor(0x33FF3333); // canvas->drawRect(pathBounds, paint); /* paint.setColor(SK_ColorGREEN); canvas->drawPath(textArt.bSkeleton_, paint); canvas->drawPath(textArt.bWarped_, paint); paint.setColor(SK_ColorCYAN); canvas->drawPath(textArt.tSkeleton_, paint); canvas->drawPath(textArt.tWarped_, paint); */ //draw the skeleton path paint.setColor(SK_ColorBLUE); canvas->drawPath(bSkeleton_, paint); canvas->drawPath(tSkeleton_, paint); //draw the path paint.setColor(SK_ColorBLACK); paint.setStyle(SkPaint::kFill_Style); canvas->drawPath(path_, paint); /* paint.setColor(SK_ColorRED); canvas->drawPath(textArt.normal, paint); canvas->drawPath(textArt.tFlattern, paint); for(int i=0; i<textArt.intersections.size(); ++i) { canvas->drawCircle(textArt.intersections[i].fX, textArt.intersections[i].fY, 1.5, paint); } */ canvas->restore(); }
static void test_matrix_is_similarity(skiatest::Reporter* reporter) { SkMatrix mat; // identity mat.setIdentity(); REPORTER_ASSERT(reporter, mat.isSimilarity()); // translation only mat.reset(); mat.setTranslate(SkIntToScalar(100), SkIntToScalar(100)); REPORTER_ASSERT(reporter, mat.isSimilarity()); // scale with same size mat.reset(); mat.setScale(SkIntToScalar(15), SkIntToScalar(15)); REPORTER_ASSERT(reporter, mat.isSimilarity()); // scale with one negative mat.reset(); mat.setScale(SkIntToScalar(-15), SkIntToScalar(15)); REPORTER_ASSERT(reporter, mat.isSimilarity()); // scale with different size mat.reset(); mat.setScale(SkIntToScalar(15), SkIntToScalar(20)); REPORTER_ASSERT(reporter, !mat.isSimilarity()); // scale with same size at a pivot point mat.reset(); mat.setScale(SkIntToScalar(15), SkIntToScalar(15), SkIntToScalar(2), SkIntToScalar(2)); REPORTER_ASSERT(reporter, mat.isSimilarity()); // scale with different size at a pivot point mat.reset(); mat.setScale(SkIntToScalar(15), SkIntToScalar(20), SkIntToScalar(2), SkIntToScalar(2)); REPORTER_ASSERT(reporter, !mat.isSimilarity()); // skew with same size mat.reset(); mat.setSkew(SkIntToScalar(15), SkIntToScalar(15)); REPORTER_ASSERT(reporter, !mat.isSimilarity()); // skew with different size mat.reset(); mat.setSkew(SkIntToScalar(15), SkIntToScalar(20)); REPORTER_ASSERT(reporter, !mat.isSimilarity()); // skew with same size at a pivot point mat.reset(); mat.setSkew(SkIntToScalar(15), SkIntToScalar(15), SkIntToScalar(2), SkIntToScalar(2)); REPORTER_ASSERT(reporter, !mat.isSimilarity()); // skew with different size at a pivot point mat.reset(); mat.setSkew(SkIntToScalar(15), SkIntToScalar(20), SkIntToScalar(2), SkIntToScalar(2)); REPORTER_ASSERT(reporter, !mat.isSimilarity()); // perspective x mat.reset(); mat.setPerspX(SkScalarToPersp(SK_Scalar1 / 2)); REPORTER_ASSERT(reporter, !mat.isSimilarity()); // perspective y mat.reset(); mat.setPerspY(SkScalarToPersp(SK_Scalar1 / 2)); REPORTER_ASSERT(reporter, !mat.isSimilarity()); #ifdef SK_SCALAR_IS_FLOAT /* We bypass the following tests for SK_SCALAR_IS_FIXED build. * The long discussion can be found in this issue: * http://codereview.appspot.com/5999050/ * In short, we haven't found a perfect way to fix the precision * issue, i.e. the way we use tolerance in isSimilarityTransformation * is incorrect. The situation becomes worse in fixed build, so * we disabled rotation related tests for fixed build. */ // rotate for (int angle = 0; angle < 360; ++angle) { mat.reset(); mat.setRotate(SkIntToScalar(angle)); REPORTER_ASSERT(reporter, mat.isSimilarity()); } // see if there are any accumulated precision issues mat.reset(); for (int i = 1; i < 360; i++) { mat.postRotate(SkIntToScalar(1)); } REPORTER_ASSERT(reporter, mat.isSimilarity()); // rotate + translate mat.reset(); mat.setRotate(SkIntToScalar(30)); mat.postTranslate(SkIntToScalar(10), SkIntToScalar(20)); REPORTER_ASSERT(reporter, mat.isSimilarity()); // rotate + uniform scale mat.reset(); mat.setRotate(SkIntToScalar(30)); mat.postScale(SkIntToScalar(2), SkIntToScalar(2)); REPORTER_ASSERT(reporter, mat.isSimilarity()); // rotate + non-uniform scale mat.reset(); mat.setRotate(SkIntToScalar(30)); mat.postScale(SkIntToScalar(3), SkIntToScalar(2)); REPORTER_ASSERT(reporter, !mat.isSimilarity()); #endif // all zero mat.setAll(0, 0, 0, 0, 0, 0, 0, 0, 0); REPORTER_ASSERT(reporter, !mat.isSimilarity()); // all zero except perspective mat.setAll(0, 0, 0, 0, 0, 0, 0, 0, SK_Scalar1); REPORTER_ASSERT(reporter, !mat.isSimilarity()); // scales zero, only skews mat.setAll(0, SK_Scalar1, 0, SK_Scalar1, 0, 0, 0, 0, SkMatrix::I()[8]); REPORTER_ASSERT(reporter, mat.isSimilarity()); }
SkPath TextArt::EnvelopeWarp::warp(const std::string& text, SkTypeface* typeface) { SkPath warpedPath; if (text.empty()) return warpedPath; //prepare paint SkPaint paint; paint.setTextSize(SkIntToScalar(64)); paint.setTypeface(typeface); paint.setTextAlign(SkPaint::kCenter_Align); //measure Bottom path to center text on it SkPathMeasure bMeasure(bSkeleton_, false); SkScalar hBOffset = 0; if (paint.getTextAlign() != SkPaint::kLeft_Align) { SkScalar pathLen = bMeasure.getLength(); if (paint.getTextAlign() == SkPaint::kCenter_Align) { pathLen = SkScalarHalf(pathLen); } hBOffset += pathLen; } //get text boundaries on normal(non-warped) state { SkMatrix scaleMartix; scaleMartix.setIdentity(); SkTextToPathIter iter(text.c_str(), text.size(), paint, true); const SkPath* glypthPath; SkScalar xpos; SkScalar scale = iter.getPathScale(); scaleMartix.setScale(scale, scale); while (iter.next(&glypthPath, &xpos)) { if (glypthPath) { //prepare resulting transformatiom Matrix SkMatrix compositeMatrix(scaleMartix); compositeMatrix.postTranslate(xpos + hBOffset, 0); SkPath p; (*glypthPath).transform(compositeMatrix, &p); //get normal(without any warps) text boundaries boundsRect_.join( p.getBounds() ); } } } //center text on Top skeleton SkPathMeasure tMeasure(tSkeleton_, false); SkScalar hTOffset = 0; { if (paint.getTextAlign() != SkPaint::kLeft_Align) { SkScalar pathLen = tMeasure.getLength(); if (paint.getTextAlign() == SkPaint::kCenter_Align) { pathLen = SkScalarHalf(pathLen); } hTOffset += pathLen; } } //warp text on Bottom and Top skeletons { SkTextToPathIter iter(text.c_str(), text.size(), paint, true); SkScalar xpos; SkMatrix scaleMartix; SkScalar scale = iter.getPathScale(); scaleMartix.setScale(scale, scale); SkPath line; line.lineTo(SkIntToScalar(100), SkIntToScalar(0)); SkPathMeasure lineMeasure(line, false); SkPathCrossing bCrossing(bSkeleton_); SkPathCrossing tCrossing(tSkeleton_); const SkPath* glypthPathOrig; while (iter.next(&glypthPathOrig, &xpos)) { if (glypthPathOrig) { SkPath glypthPath; SkRect glypthBound; glypthBound = (*glypthPathOrig).getBounds(); glypthPathOrig->offset(-glypthBound.fLeft, 0, &glypthPath); morph(bSkeleton_, bMeasure, bCrossing, tSkeleton_, tMeasure, tCrossing, glypthPath, lineMeasure, scaleMartix, xpos, hBOffset, hTOffset, warpedPath); } } } return warpedPath; }
static void test_matrix_is_similarity(skiatest::Reporter* reporter) { SkMatrix mat; // identity mat.setIdentity(); REPORTER_ASSERT(reporter, mat.isSimilarity()); // translation only mat.reset(); mat.setTranslate(SkIntToScalar(100), SkIntToScalar(100)); REPORTER_ASSERT(reporter, mat.isSimilarity()); // scale with same size mat.reset(); mat.setScale(SkIntToScalar(15), SkIntToScalar(15)); REPORTER_ASSERT(reporter, mat.isSimilarity()); // scale with one negative mat.reset(); mat.setScale(SkIntToScalar(-15), SkIntToScalar(15)); REPORTER_ASSERT(reporter, mat.isSimilarity()); // scale with different size mat.reset(); mat.setScale(SkIntToScalar(15), SkIntToScalar(20)); REPORTER_ASSERT(reporter, !mat.isSimilarity()); // scale with same size at a pivot point mat.reset(); mat.setScale(SkIntToScalar(15), SkIntToScalar(15), SkIntToScalar(2), SkIntToScalar(2)); REPORTER_ASSERT(reporter, mat.isSimilarity()); // scale with different size at a pivot point mat.reset(); mat.setScale(SkIntToScalar(15), SkIntToScalar(20), SkIntToScalar(2), SkIntToScalar(2)); REPORTER_ASSERT(reporter, !mat.isSimilarity()); // skew with same size mat.reset(); mat.setSkew(SkIntToScalar(15), SkIntToScalar(15)); REPORTER_ASSERT(reporter, !mat.isSimilarity()); // skew with different size mat.reset(); mat.setSkew(SkIntToScalar(15), SkIntToScalar(20)); REPORTER_ASSERT(reporter, !mat.isSimilarity()); // skew with same size at a pivot point mat.reset(); mat.setSkew(SkIntToScalar(15), SkIntToScalar(15), SkIntToScalar(2), SkIntToScalar(2)); REPORTER_ASSERT(reporter, !mat.isSimilarity()); // skew with different size at a pivot point mat.reset(); mat.setSkew(SkIntToScalar(15), SkIntToScalar(20), SkIntToScalar(2), SkIntToScalar(2)); REPORTER_ASSERT(reporter, !mat.isSimilarity()); // perspective x mat.reset(); mat.setPerspX(SkScalarToPersp(SK_Scalar1 / 2)); REPORTER_ASSERT(reporter, !mat.isSimilarity()); // perspective y mat.reset(); mat.setPerspY(SkScalarToPersp(SK_Scalar1 / 2)); REPORTER_ASSERT(reporter, !mat.isSimilarity()); // rotate for (int angle = 0; angle < 360; ++angle) { mat.reset(); mat.setRotate(SkIntToScalar(angle)); #ifndef SK_CPU_ARM64 REPORTER_ASSERT(reporter, mat.isSimilarity()); #else // 64-bit ARM devices built with -O2 and -ffp-contract=fast have a loss // of precision and require that we have a higher tolerance REPORTER_ASSERT(reporter, mat.isSimilarity(SK_ScalarNearlyZero + 0.00010113f)); #endif } // see if there are any accumulated precision issues mat.reset(); for (int i = 1; i < 360; i++) { mat.postRotate(SkIntToScalar(1)); } REPORTER_ASSERT(reporter, mat.isSimilarity()); // rotate + translate mat.reset(); mat.setRotate(SkIntToScalar(30)); mat.postTranslate(SkIntToScalar(10), SkIntToScalar(20)); REPORTER_ASSERT(reporter, mat.isSimilarity()); // rotate + uniform scale mat.reset(); mat.setRotate(SkIntToScalar(30)); mat.postScale(SkIntToScalar(2), SkIntToScalar(2)); REPORTER_ASSERT(reporter, mat.isSimilarity()); // rotate + non-uniform scale mat.reset(); mat.setRotate(SkIntToScalar(30)); mat.postScale(SkIntToScalar(3), SkIntToScalar(2)); REPORTER_ASSERT(reporter, !mat.isSimilarity()); // all zero mat.setAll(0, 0, 0, 0, 0, 0, 0, 0, 0); REPORTER_ASSERT(reporter, !mat.isSimilarity()); // all zero except perspective mat.setAll(0, 0, 0, 0, 0, 0, 0, 0, SK_Scalar1); REPORTER_ASSERT(reporter, !mat.isSimilarity()); // scales zero, only skews mat.setAll(0, SK_Scalar1, 0, SK_Scalar1, 0, 0, 0, 0, SkMatrix::I()[8]); REPORTER_ASSERT(reporter, mat.isSimilarity()); }