static SkShader* make_radial_gradient(const SkPoint pts[2], const SkMatrix& localMatrix) { SkPoint center; center.set(SkScalarAve(pts[0].fX, pts[1].fX), SkScalarAve(pts[0].fY, pts[1].fY)); float radius = (center - pts[0]).length(); return SkGradientShader::CreateRadial(center, radius, gColors, NULL, SK_ARRAY_COUNT(gColors), SkShader::kClamp_TileMode, 0, &localMatrix); }
void SkAnnotateNamedDestination(SkCanvas* canvas, const SkPoint& point, SkData* name) { if (nullptr == name) { return; } SkPaint paint; annotate_paint(paint, SkAnnotationKeys::Define_Named_Dest_Key(), name); canvas->drawPoint(point.x(), point.y(), paint); }
static SkShader* MakeSweep(const SkPoint pts[2], const GradData& data, SkShader::TileMode, const SkMatrix& localMatrix) { SkPoint center; center.set(SkScalarAve(pts[0].fX, pts[1].fX), SkScalarAve(pts[0].fY, pts[1].fY)); return SkGradientShader::CreateSweep(center.fX, center.fY, data.fColors, data.fPos, data.fCount, 0, &localMatrix); }
virtual void onDraw(SkCanvas* canvas) { SkMatrix m; m.reset(); m.setRotate(33 * SK_Scalar1); m.postScale(3000 * SK_Scalar1, 3000 * SK_Scalar1); m.postTranslate(6000 * SK_Scalar1, -5000 * SK_Scalar1); canvas->concat(m); SkPaint paint; paint.setColor(SK_ColorRED); paint.setAntiAlias(true); bool success = m.invert(&m); SkASSERT(success); (void) success; // silence compiler :( SkPath path; SkPoint pt = {10 * SK_Scalar1, 10 * SK_Scalar1}; SkScalar small = 1 / (500 * SK_Scalar1); m.mapPoints(&pt, 1); path.addCircle(pt.fX, pt.fY, small); canvas->drawPath(path, paint); pt.set(30 * SK_Scalar1, 10 * SK_Scalar1); m.mapPoints(&pt, 1); SkRect rect = {pt.fX - small, pt.fY - small, pt.fX + small, pt.fY + small}; canvas->drawRect(rect, paint); SkBitmap bmp; bmp.setConfig(SkBitmap::kARGB_8888_Config, 2, 2); bmp.allocPixels(); bmp.lockPixels(); uint32_t* pixels = reinterpret_cast<uint32_t*>(bmp.getPixels()); pixels[0] = SkPackARGB32(0xFF, 0xFF, 0x00, 0x00); pixels[1] = SkPackARGB32(0xFF, 0x00, 0xFF, 0x00); pixels[2] = SkPackARGB32(0x80, 0x00, 0x00, 0x00); pixels[3] = SkPackARGB32(0xFF, 0x00, 0x00, 0xFF); bmp.unlockPixels(); pt.set(30 * SK_Scalar1, 30 * SK_Scalar1); m.mapPoints(&pt, 1); SkShader* shader = SkShader::CreateBitmapShader( bmp, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode); SkMatrix s; s.reset(); s.setScale(SK_Scalar1 / 1000, SK_Scalar1 / 1000); shader->setLocalMatrix(s); paint.setShader(shader)->unref(); paint.setAntiAlias(false); paint.setFilterLevel(SkPaint::kLow_FilterLevel); rect.setLTRB(pt.fX - small, pt.fY - small, pt.fX + small, pt.fY + small); canvas->drawRect(rect, paint); }
/// Ignores scale static SkShader* MakeSweep(const SkPoint pts[2], const GradData& data, SkShader::TileMode tm, SkUnitMapper* mapper, float scale) { SkPoint center; center.set(SkScalarAve(pts[0].fX, pts[1].fX), SkScalarAve(pts[0].fY, pts[1].fY)); return SkGradientShader::CreateSweep(center.fX, center.fY, data.fColors, data.fPos, data.fCount, mapper); }
void onDrawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint) override { if (!paint.getAnnotation()) return; ASSERT_EQ(1u, count); // Only called from drawPoint(). SkPoint point = getTotalMatrix().mapXY(pts[0].x(), pts[0].y()); Operation operation = { DrawPoint, SkRect::MakeXYWH(point.x(), point.y(), 0, 0) }; m_recordedOperations.append(operation); }
static sk_sp<SkShader> MakeSweep4f(const SkPoint pts[2], const GradData& data, SkShader::TileMode, const SkMatrix& localMatrix) { SkPoint center; center.set(SkScalarAve(pts[0].fX, pts[1].fX), SkScalarAve(pts[0].fY, pts[1].fY)); auto srgb = SkColorSpace::MakeSRGBLinear(); return SkGradientShader::MakeSweep(center.fX, center.fY, data.fColors4f, srgb, data.fPos, data.fCount, 0, &localMatrix); }
SkFlattenable* SkSweepGradient::CreateProc(SkReadBuffer& buffer) { DescriptorScope desc; if (!desc.unflatten(buffer)) { return NULL; } const SkPoint center = buffer.readPoint(); return SkGradientShader::CreateSweep(center.x(), center.y(), desc.fColors, desc.fPos, desc.fCount, desc.fGradFlags, desc.fLocalMatrix); }
SkScalar SkPerlinNoiseShader::PerlinNoiseShaderContext::noise2D( int channel, const StitchData& stitchData, const SkPoint& noiseVector) const { struct Noise { int noisePositionIntegerValue; int nextNoisePositionIntegerValue; SkScalar noisePositionFractionValue; Noise(SkScalar component) { SkScalar position = component + kPerlinNoise; noisePositionIntegerValue = SkScalarFloorToInt(position); noisePositionFractionValue = position - SkIntToScalar(noisePositionIntegerValue); nextNoisePositionIntegerValue = noisePositionIntegerValue + 1; } }; Noise noiseX(noiseVector.x()); Noise noiseY(noiseVector.y()); SkScalar u, v; const SkPerlinNoiseShader& perlinNoiseShader = static_cast<const SkPerlinNoiseShader&>(fShader); // If stitching, adjust lattice points accordingly. if (perlinNoiseShader.fStitchTiles) { noiseX.noisePositionIntegerValue = checkNoise(noiseX.noisePositionIntegerValue, stitchData.fWrapX, stitchData.fWidth); noiseY.noisePositionIntegerValue = checkNoise(noiseY.noisePositionIntegerValue, stitchData.fWrapY, stitchData.fHeight); noiseX.nextNoisePositionIntegerValue = checkNoise(noiseX.nextNoisePositionIntegerValue, stitchData.fWrapX, stitchData.fWidth); noiseY.nextNoisePositionIntegerValue = checkNoise(noiseY.nextNoisePositionIntegerValue, stitchData.fWrapY, stitchData.fHeight); } noiseX.noisePositionIntegerValue &= kBlockMask; noiseY.noisePositionIntegerValue &= kBlockMask; noiseX.nextNoisePositionIntegerValue &= kBlockMask; noiseY.nextNoisePositionIntegerValue &= kBlockMask; int i = fPaintingData->fLatticeSelector[noiseX.noisePositionIntegerValue]; int j = fPaintingData->fLatticeSelector[noiseX.nextNoisePositionIntegerValue]; int b00 = (i + noiseY.noisePositionIntegerValue) & kBlockMask; int b10 = (j + noiseY.noisePositionIntegerValue) & kBlockMask; int b01 = (i + noiseY.nextNoisePositionIntegerValue) & kBlockMask; int b11 = (j + noiseY.nextNoisePositionIntegerValue) & kBlockMask; SkScalar sx = smoothCurve(noiseX.noisePositionFractionValue); SkScalar sy = smoothCurve(noiseY.noisePositionFractionValue); // This is taken 1:1 from SVG spec: http://www.w3.org/TR/SVG11/filters.html#feTurbulenceElement SkPoint fractionValue = SkPoint::Make(noiseX.noisePositionFractionValue, noiseY.noisePositionFractionValue); // Offset (0,0) u = fPaintingData->fGradient[channel][b00].dot(fractionValue); fractionValue.fX -= SK_Scalar1; // Offset (-1,0) v = fPaintingData->fGradient[channel][b10].dot(fractionValue); SkScalar a = SkScalarInterp(u, v, sx); fractionValue.fY -= SK_Scalar1; // Offset (-1,-1) v = fPaintingData->fGradient[channel][b11].dot(fractionValue); fractionValue.fX = noiseX.noisePositionFractionValue; // Offset (0,-1) u = fPaintingData->fGradient[channel][b01].dot(fractionValue); SkScalar b = SkScalarInterp(u, v, sx); return SkScalarInterp(a, b, sy); }
static void draw_label(SkCanvas* canvas, const char* label, const SkPoint& offset) { SkPaint paint; size_t len = strlen(label); SkScalar width = paint.measureText(label, len); canvas->drawText(label, len, offset.x() - width / 2, offset.y(), paint); }
void onPrepareDraws(Target* target) override { SkAutoTUnref<const GrGeometryProcessor> gp(create_gp(fOverrides.readsCoverage())); if (!gp) { SkDebugf("Couldn't create GrGeometryProcessor\n"); return; } target->initDraw(gp, this->pipeline()); size_t vertexStride = gp->getVertexStride(); int instanceCount = fGeoData.count(); SkAutoTUnref<const GrIndexBuffer> indexBuffer( target->resourceProvider()->refQuadIndexBuffer()); InstancedHelper helper; void* vertices = helper.init(target, kTriangles_GrPrimitiveType, vertexStride, indexBuffer, kVertsPerRect, kIndicesPerRect, instanceCount * kRectsPerInstance); if (!vertices || !indexBuffer) { SkDebugf("Could not allocate vertices\n"); return; } for (int i = 0; i < instanceCount; i++) { intptr_t verts = reinterpret_cast<intptr_t>(vertices) + i * kRectsPerInstance * kVertsPerRect * vertexStride; Geometry& geo = fGeoData[i]; SkNinePatchIter iter(fImageWidth, fImageHeight, geo.fCenter, geo.fDst); SkRect srcR, dstR; while (iter.next(&srcR, &dstR)) { SkPoint* positions = reinterpret_cast<SkPoint*>(verts); positions->setRectFan(dstR.fLeft, dstR.fTop, dstR.fRight, dstR.fBottom, vertexStride); SkASSERT(!geo.fViewMatrix.hasPerspective()); geo.fViewMatrix.mapPointsWithStride(positions, vertexStride, kVertsPerRect); // Setup local coords static const int kLocalOffset = sizeof(SkPoint) + sizeof(GrColor); SkPoint* coords = reinterpret_cast<SkPoint*>(verts + kLocalOffset); coords->setRectFan(srcR.fLeft, srcR.fTop, srcR.fRight, srcR.fBottom, vertexStride); static const int kColorOffset = sizeof(SkPoint); GrColor* vertColor = reinterpret_cast<GrColor*>(verts + kColorOffset); for (int j = 0; j < 4; ++j) { *vertColor = geo.fColor; vertColor = (GrColor*) ((intptr_t) vertColor + vertexStride); } verts += kVertsPerRect * vertexStride; } } helper.recordDraw(target); }
static SkShader* Make2ConicalConcentric(const SkPoint pts[2], const GradData& data, SkShader::TileMode tm) { SkPoint center; center.set(SkScalarAve(pts[0].fX, pts[1].fX), SkScalarAve(pts[0].fY, pts[1].fY)); return SkGradientShader::CreateTwoPointConical( center, (pts[1].fX - pts[0].fX) / 7, center, (pts[1].fX - pts[0].fX) / 2, data.fColors, data.fPos, data.fCount, tm); }
void updateDom() { const SkPoint corner = pos - SkPoint::Make(size.width() / 2, size.height() / 2); update_pos(objectNode, corner); // Simulate parallax shadow for a centered light source. SkPoint shadowOffset = pos - SkPoint::Make(kBounds.centerX(), kBounds.centerY()); shadowOffset.scale(kShadowParallax); const SkPoint shadowCorner = corner + shadowOffset; update_pos(shadowNode, shadowCorner); }
void generateGeometry(GrBatchTarget* batchTarget) override { SkAutoTUnref<const GrGeometryProcessor> gp(this->createRectGP()); if (!gp) { SkDebugf("Could not create GrGeometryProcessor\n"); return; } batchTarget->initDraw(gp, this->pipeline()); int instanceCount = fGeoData.count(); size_t vertexStride = gp->getVertexStride(); SkASSERT(this->hasLocalRect() ? vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorLocalCoordAttr) : vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAttr)); QuadHelper helper; void* vertices = helper.init(batchTarget, vertexStride, instanceCount); if (!vertices) { return; } for (int i = 0; i < instanceCount; i++) { const Geometry& geom = fGeoData[i]; intptr_t offset = reinterpret_cast<intptr_t>(vertices) + kVerticesPerQuad * i * vertexStride; SkPoint* positions = reinterpret_cast<SkPoint*>(offset); positions->setRectFan(geom.fRect.fLeft, geom.fRect.fTop, geom.fRect.fRight, geom.fRect.fBottom, vertexStride); geom.fViewMatrix.mapPointsWithStride(positions, vertexStride, kVerticesPerQuad); // TODO we should only do this if local coords are being read if (geom.fHasLocalRect) { static const int kLocalOffset = sizeof(SkPoint) + sizeof(GrColor); SkPoint* coords = reinterpret_cast<SkPoint*>(offset + kLocalOffset); coords->setRectFan(geom.fLocalRect.fLeft, geom.fLocalRect.fTop, geom.fLocalRect.fRight, geom.fLocalRect.fBottom, vertexStride); if (geom.fHasLocalMatrix) { geom.fLocalMatrix.mapPointsWithStride(coords, vertexStride, kVerticesPerQuad); } } static const int kColorOffset = sizeof(SkPoint); GrColor* vertColor = reinterpret_cast<GrColor*>(offset + kColorOffset); for (int j = 0; j < 4; ++j) { *vertColor = geom.fColor; vertColor = (GrColor*) ((intptr_t) vertColor + vertexStride); } } helper.issueDraw(batchTarget); }
SkShader* SkPictureShader::refBitmapShader(const SkMatrix& matrix, const SkMatrix* localM) const { SkASSERT(fPicture && fPicture->width() > 0 && fPicture->height() > 0); SkMatrix m; m.setConcat(matrix, this->getLocalMatrix()); if (localM) { m.preConcat(*localM); } // Use a rotation-invariant scale SkPoint scale; if (!SkDecomposeUpper2x2(m, NULL, &scale, NULL)) { // Decomposition failed, use an approximation. scale.set(SkScalarSqrt(m.getScaleX() * m.getScaleX() + m.getSkewX() * m.getSkewX()), SkScalarSqrt(m.getScaleY() * m.getScaleY() + m.getSkewY() * m.getSkewY())); } SkSize scaledSize = SkSize::Make(scale.x() * fPicture->width(), scale.y() * fPicture->height()); SkISize tileSize = scaledSize.toRound(); if (tileSize.isEmpty()) { return NULL; } // The actual scale, compensating for rounding. SkSize tileScale = SkSize::Make(SkIntToScalar(tileSize.width()) / fPicture->width(), SkIntToScalar(tileSize.height()) / fPicture->height()); SkAutoMutexAcquire ama(fCachedBitmapShaderMutex); if (!fCachedBitmapShader || tileScale != fCachedTileScale) { SkBitmap bm; if (!bm.allocN32Pixels(tileSize.width(), tileSize.height())) { return NULL; } bm.eraseColor(SK_ColorTRANSPARENT); SkCanvas canvas(bm); canvas.scale(tileScale.width(), tileScale.height()); canvas.drawPicture(fPicture); fCachedTileScale = tileScale; SkMatrix shaderMatrix = this->getLocalMatrix(); shaderMatrix.preScale(1 / tileScale.width(), 1 / tileScale.height()); fCachedBitmapShader.reset(CreateBitmapShader(bm, fTmx, fTmy, &shaderMatrix)); } // Increment the ref counter inside the mutex to ensure the returned pointer is still valid. // Otherwise, the pointer may have been overwritten on a different thread before the object's // ref count was incremented. fCachedBitmapShader.get()->ref(); return fCachedBitmapShader; }
inline void GrStencilAndCoverTextContext::appendGlyph(const SkGlyph& glyph, const SkPoint& pos) { if (fQueuedGlyphCount >= fFallbackGlyphsIdx) { SkASSERT(fQueuedGlyphCount == fFallbackGlyphsIdx); this->flush(); } // Stick the glyphs we can't draw at the end of the buffer, growing backwards. int index = (SkMask::kARGB32_Format == glyph.fMaskFormat) ? --fFallbackGlyphsIdx : fQueuedGlyphCount++; fGlyphIndices[index] = glyph.getGlyphID(); fGlyphPositions[index].set(fTextInverseRatio * pos.x(), -fTextInverseRatio * pos.y()); }
void onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) override { if (rect.width() == 0 && rect.height() == 0) { SkPoint point = getTotalMatrix().mapXY(rect.x(), rect.y()); Operation operation = { DrawPoint, SkRect::MakeXYWH(point.x(), point.y(), 0, 0) }; m_recordedOperations.append(operation); } else { Operation operation = { DrawRect, rect }; getTotalMatrix().mapRect(&operation.rect); m_recordedOperations.append(operation); } }
void onDrawContent(SkCanvas* canvas) override { SkScalar trans[2]; fTrans.timeToValues(SkTime::GetMSecs(), trans); SkPoint offset; offset.set(trans[0], trans[1]); int saveCount = canvas->save(); this->drawGeometry(canvas, offset, false); canvas->restoreToCount(saveCount); this->inval(nullptr); }
/* Used by bloat_tri; outsets a single point. */ static bool outset(SkPoint* p1, SkPoint line1, SkPoint line2) { // rotate the two line vectors 90 degrees to form the normals, and compute // the dot product of the normals SkScalar dotProd = line1.fY * line2.fY + line1.fX * line2.fX; SkScalar lengthSq = 1.0f / ((1.0f - dotProd) / 2.0f); if (lengthSq > kBloatLimit) { return false; } SkPoint bisector = line1 + line2; bisector.setLength(SkScalarSqrt(lengthSq) * kBloatSize); *p1 += bisector; return true; }
SkPath quadPath(SkPoint p1, SkPoint p2) { SkASSERT(p1.y() == p2.y()); SkPath path; path.moveTo(p1); path.lineTo(p2); SkPoint p3 = SkPoint::Make((p1.x() + p2.x()) / 2.0f, p1.y() * 0.7f); path.quadTo(p3, p1); return path; }
mbe_pattern_t * mbe_pattern_create_radial(co_aix cx0, co_aix cy0, co_aix radius0, co_aix cx1, co_aix cy1, co_aix radius1, grad_stop_t *stops, int stop_cnt) { mbe_pattern_t *ptn; SkColor *colors; SkScalar *poses; grad_stop_t *stop; SkPoint center; int i; ptn = (mbe_pattern_t *)malloc(sizeof(mbe_pattern_t)); colors = new SkColor[stop_cnt]; poses = new SkScalar[stop_cnt]; if(ptn == NULL || colors == NULL || poses == NULL) goto fail; center.set(CO_AIX_2_SKSCALAR(cx1), CO_AIX_2_SKSCALAR(cy1)); stop = stops; for(i = 0; i < stop_cnt; i++) { colors[i] = MBSTOP_2_SKCOLOR(stop); poses[i] = CO_AIX_2_SKSCALAR(stop->offset); } /* * cx0, cy0 and radius0 is not used. Since Skia is still not * support two circles radial. And, SVG 1.2 is also not support * two circles. */ ptn->shader = SkGradientShader::CreateRadial(center, CO_AIX_2_SKSCALAR(radius1), colors, poses, stop_cnt, SkShader::kClamp_TileMode); if(ptn->shader == NULL) goto fail; memcpy(ptn->matrix, id_matrix, sizeof(co_aix) * 6); ptn->bitmap = NULL; delete colors; delete poses; return ptn; fail: if(ptn) free(ptn); if(colors) delete colors; if(poses) delete poses; return NULL; }
inline void GrStencilAndCoverTextContext::TextRun::appendGlyph(const SkGlyph& glyph, const SkPoint& pos, FallbackBlobBuilder* fallback) { // Stick the glyphs we can't draw into the fallback text blob. if (SkMask::kARGB32_Format == glyph.fMaskFormat) { if (!fallback->isInitialized()) { fallback->init(fFont, fTextRatio); } fallback->appendGlyph(glyph.getGlyphID(), pos); } else { fInstanceData->append(glyph.getGlyphID(), fTextInverseRatio * pos.x(), fTextInverseRatio * pos.y()); } }
static jlong RadialGradient_create2(JNIEnv* env, jobject, jfloat x, jfloat y, jfloat radius, jint color0, jint color1, jint tileMode) { SkPoint center; center.set(x, y); SkColor colors[2]; colors[0] = color0; colors[1] = color1; SkShader* s = SkGradientShader::CreateRadial(center, radius, colors, NULL, 2, (SkShader::TileMode)tileMode); ThrowIAE_IfNull(env, s); return reinterpret_cast<jlong>(s); }
static void center_of_mass(const SegmentArray& segments, SkPoint* c) { SkScalar area = 0; SkPoint center = {0, 0}; int count = segments.count(); SkPoint p0 = {0, 0}; if (count > 2) { // We translate the polygon so that the first point is at the origin. // This avoids some precision issues with small area polygons far away // from the origin. p0 = segments[0].endPt(); SkPoint pi; SkPoint pj; // the first and last iteration of the below loop would compute // zeros since the starting / ending point is (0,0). So instead we start // at i=1 and make the last iteration i=count-2. pj = segments[1].endPt() - p0; for (int i = 1; i < count - 1; ++i) { pi = pj; const SkPoint pj = segments[i + 1].endPt() - p0; SkScalar t = SkScalarMul(pi.fX, pj.fY) - SkScalarMul(pj.fX, pi.fY); area += t; center.fX += (pi.fX + pj.fX) * t; center.fY += (pi.fY + pj.fY) * t; } } // If the poly has no area then we instead return the average of // its points. if (SkScalarNearlyZero(area)) { SkPoint avg; avg.set(0, 0); for (int i = 0; i < count; ++i) { const SkPoint& pt = segments[i].endPt(); avg.fX += pt.fX; avg.fY += pt.fY; } SkScalar denom = SK_Scalar1 / count; avg.scale(denom); *c = avg; } else { area *= 3; area = SkScalarDiv(SK_Scalar1, area); center.fX = SkScalarMul(center.fX, area); center.fY = SkScalarMul(center.fY, area); // undo the translate of p0 to the origin. *c = center + p0; } SkASSERT(!SkScalarIsNaN(c->fX) && !SkScalarIsNaN(c->fY)); }
void SkLinearGradient:: LinearGradient4fContext::shadeSpanInternal(int x, int y, dstType dst[], int count, float bias0, float bias1) const { SkPoint pt; fDstToPosProc(fDstToPos, x + SK_ScalarHalf, y + SK_ScalarHalf, &pt); const SkScalar fx = pinFx<tileMode>(pt.x()); const SkScalar dx = fDstToPos.getScaleX(); LinearIntervalProcessor<dstType, premul, tileMode> proc(fIntervals->begin(), fIntervals->end() - 1, this->findInterval(fx), fx, dx, SkScalarNearlyZero(dx * count)); Sk4f bias4f0(bias0), bias4f1(bias1); while (count > 0) { // What we really want here is SkTPin(advance, 1, count) // but that's a significant perf hit for >> stops; investigate. const int n = SkScalarTruncToInt( SkTMin<SkScalar>(proc.currentAdvance() + 1, SkIntToScalar(count))); // The current interval advance can be +inf (e.g. when reaching // the clamp mode end intervals) - when that happens, we expect to // a) consume all remaining count in one swoop // b) return a zero color gradient SkASSERT(SkScalarIsFinite(proc.currentAdvance()) || (n == count && proc.currentRampIsZero())); if (proc.currentRampIsZero()) { DstTraits<dstType, premul>::store(proc.currentColor(), dst, n); } else { ramp<dstType, premul>(proc.currentColor(), proc.currentColorGrad(), dst, n, bias4f0, bias4f1); } proc.advance(SkIntToScalar(n)); count -= n; dst += n; if (n & 1) { SkTSwap(bias4f0, bias4f1); } } }
void onOnceBeforeDraw() override { SkRandom rand; int steps = 20; SkScalar dist = SkIntToScalar(400); SkScalar x = SkIntToScalar(20); SkScalar y = SkIntToScalar(50); fPath.moveTo(x, y); for (int i = 0; i < steps; i++) { x += dist/steps; SkScalar tmpY = y + SkIntToScalar(rand.nextS() % 25); if (i == steps/2) { fPath.moveTo(x, tmpY); } else { fPath.lineTo(x, tmpY); } } { SkRect oval; oval.set(SkIntToScalar(20), SkIntToScalar(30), SkIntToScalar(100), SkIntToScalar(60)); oval.offset(x, 0); fPath.addRoundRect(oval, SkIntToScalar(8), SkIntToScalar(8)); } fClickPt.set(SkIntToScalar(200), SkIntToScalar(200)); this->setBGColor(0xFFDDDDDD); }
SkScalar SkPoint::distanceToLineSegmentBetweenSqd(const SkPoint& a, const SkPoint& b) const { // See comments to distanceToLineBetweenSqd. If the projection of c onto // u is between a and b then this returns the same result as that // function. Otherwise, it returns the distance to the closer of a and // b. Let the projection of v onto u be v'. There are three cases: // 1. v' points opposite to u. c is not between a and b and is closer // to a than b. // 2. v' points along u and has magnitude less than y. c is between // a and b and the distance to the segment is the same as distance // to the line ab. // 3. v' points along u and has greater magnitude than u. c is not // not between a and b and is closer to b than a. // v' = (u dot v) * u / |u|. So if (u dot v)/|u| is less than zero we're // in case 1. If (u dot v)/|u| is > |u| we are in case 3. Otherwise // we're in case 2. We actually compare (u dot v) to 0 and |u|^2 to // avoid a sqrt to compute |u|. SkVector u = b - a; SkVector v = *this - a; SkScalar uLengthSqd = u.lengthSqd(); SkScalar uDotV = SkPoint::DotProduct(u, v); if (uDotV <= 0) { return v.lengthSqd(); } else if (uDotV > uLengthSqd) { return b.distanceToSqd(*this); } else { SkScalar det = u.cross(v); return SkScalarMulDiv(det, det, uLengthSqd); } }
PathEffectView() { SkRandom rand; int steps = 20; SkScalar dist = SkIntToScalar(400); SkScalar x = SkIntToScalar(20); SkScalar y = SkIntToScalar(50); fPath.moveTo(x, y); for (int i = 0; i < steps; i++) { x += dist/steps; SkScalar tmpY = y + SkIntToScalar(rand.nextS() % 25); if (i == steps/2) { fPath.moveTo(x, tmpY); } else { fPath.lineTo(x, tmpY); } } { SkRect oval; oval.set(SkIntToScalar(20), SkIntToScalar(30), SkIntToScalar(100), SkIntToScalar(60)); oval.offset(x, 0); fPath.addRoundRect(oval, SkIntToScalar(8), SkIntToScalar(8)); } fClickPt.set(SkIntToScalar(200), SkIntToScalar(200)); }
static SkShader* RadialGradient_create2(JNIEnv* env, jobject, float x, float y, float radius, int color0, int color1, int tileMode) { SkPoint center; center.set(SkFloatToScalar(x), SkFloatToScalar(y)); SkColor colors[2]; colors[0] = color0; colors[1] = color1; SkShader* s = SkGradientShader::CreateRadial(center, SkFloatToScalar(radius), colors, NULL, 2, (SkShader::TileMode)tileMode); ThrowIAE_IfNull(env, s); return s; }
static void update_degenerate_test(DegenerateTestData* data, const SkPoint& pt) { switch (data->fStage) { case DegenerateTestData::kInitial: data->fFirstPoint = pt; data->fStage = DegenerateTestData::kPoint; break; case DegenerateTestData::kPoint: if (pt.distanceToSqd(data->fFirstPoint) > kCloseSqd) { data->fLineNormal = pt - data->fFirstPoint; data->fLineNormal.normalize(); data->fLineNormal.setOrthog(data->fLineNormal); data->fLineC = -data->fLineNormal.dot(data->fFirstPoint); data->fStage = DegenerateTestData::kLine; } break; case DegenerateTestData::kLine: if (SkScalarAbs(data->fLineNormal.dot(pt) + data->fLineC) > kClose) { data->fStage = DegenerateTestData::kNonDegenerate; } case DegenerateTestData::kNonDegenerate: break; default: SkFAIL("Unexpected degenerate test stage."); } }