SkInterpolatorBase::Result SkInterpolatorBase::timeToT(SkMSec time, SkScalar* T, int* indexPtr, SkBool* exactPtr) const { SkASSERT(fFrameCount > 0); Result result = kNormal_Result; if (fRepeat != SK_Scalar1) { SkMSec startTime = 0, endTime = 0; // initialize to avoid warning this->getDuration(&startTime, &endTime); SkMSec totalTime = endTime - startTime; SkMSec offsetTime = time - startTime; endTime = SkScalarMulFloor(fRepeat, totalTime); if (offsetTime >= endTime) { SkScalar fraction = SkScalarFraction(fRepeat); offsetTime = fraction == 0 && fRepeat > 0 ? totalTime : SkScalarMulFloor(fraction, totalTime); result = kFreezeEnd_Result; } else { int mirror = fFlags & kMirror; offsetTime = offsetTime % (totalTime << mirror); if (offsetTime > totalTime) { // can only be true if fMirror is true offsetTime = (totalTime << 1) - offsetTime; } } time = offsetTime + startTime; } int index = SkTSearch<SkMSec>(&fTimes[0].fTime, fFrameCount, time, sizeof(SkTimeCode)); bool exact = true; if (index < 0) { index = ~index; if (index == 0) { result = kFreezeStart_Result; } else if (index == fFrameCount) { if (fFlags & kReset) { index = 0; } else { index -= 1; } result = kFreezeEnd_Result; } else { exact = false; } } SkASSERT(index < fFrameCount); const SkTimeCode* nextTime = &fTimes[index]; SkMSec nextT = nextTime[0].fTime; if (exact) { *T = 0; } else { SkMSec prevT = nextTime[-1].fTime; *T = ComputeRelativeT(time, prevT, nextT, nextTime[-1].fBlend); } *indexPtr = index; *exactPtr = exact; return result; }
BlurBench(void* param, SkScalar rad, SkBlurMaskFilter::BlurStyle bs) : INHERITED(param) { fRadius = rad; fStyle = bs; const char* name = rad > 0 ? gStyleName[bs] : "none"; if (SkScalarFraction(rad) != 0) { fName.printf("blur_%.2f_%s", SkScalarToFloat(rad), name); } else { fName.printf("blur_%d_%s", SkScalarRound(rad), name); } }
MorphologyBench(void* param, SkScalar rad, MorphologyType style) : INHERITED(param) { fRadius = rad; fStyle = style; const char* name = rad > 0 ? gStyleName[style] : "none"; if (SkScalarFraction(rad) != 0) { fName.printf("morph_%.2f_%s", SkScalarToFloat(rad), name); } else { fName.printf("morph_%d_%s", SkScalarRound(rad), name); } }
BlurRectDirectBench(SkScalar rad) : INHERITED(rad) { SkString name; if (SkScalarFraction(rad) != 0) { name.printf("blurrect_direct_%.2f", SkScalarToFloat(rad)); } else { name.printf("blurrect_direct_%d", SkScalarRoundToInt(rad)); } this->setName(name); }
BlurBench(SkScalar rad, SkBlurStyle bs) { fRadius = rad; fStyle = bs; const char* name = rad > 0 ? gStyleName[bs] : "none"; const char* quality = "high_quality"; if (SkScalarFraction(rad) != 0) { fName.printf("blur_%.2f_%s_%s", SkScalarToFloat(rad), name, quality); } else { fName.printf("blur_%d_%s_%s", SkScalarRoundToInt(rad), name, quality); } }
BlurBench(SkScalar rad, SkBlurStyle bs, uint32_t flags = 0) { fRadius = rad; fStyle = bs; fFlags = flags; const char* name = rad > 0 ? gStyleName[bs] : "none"; const char* quality = flags & SkBlurMaskFilter::kHighQuality_BlurFlag ? "high_quality" : "low_quality"; if (SkScalarFraction(rad) != 0) { fName.printf("blur_%.2f_%s_%s", SkScalarToFloat(rad), name, quality); } else { fName.printf("blur_%d_%s_%s", SkScalarRoundToInt(rad), name, quality); } }
bool addPathToAtlas(GrVertexBatch::Target* target, FlushInfo* flushInfo, GrBatchAtlas* atlas, ShapeData* shapeData, const GrShape& shape, bool antiAlias, uint32_t dimension, SkScalar scale) const { const SkRect& bounds = shape.bounds(); // generate bounding rect for bitmap draw SkRect scaledBounds = bounds; // scale to mip level size scaledBounds.fLeft *= scale; scaledBounds.fTop *= scale; scaledBounds.fRight *= scale; scaledBounds.fBottom *= scale; // move the origin to an integer boundary (gives better results) SkScalar dx = SkScalarFraction(scaledBounds.fLeft); SkScalar dy = SkScalarFraction(scaledBounds.fTop); scaledBounds.offset(-dx, -dy); // get integer boundary SkIRect devPathBounds; scaledBounds.roundOut(&devPathBounds); // pad to allow room for antialiasing const int intPad = SkScalarCeilToInt(kAntiAliasPad); // pre-move origin (after outset, will be 0,0) int width = devPathBounds.width(); int height = devPathBounds.height(); devPathBounds.fLeft = intPad; devPathBounds.fTop = intPad; devPathBounds.fRight = intPad + width; devPathBounds.fBottom = intPad + height; devPathBounds.outset(intPad, intPad); // draw path to bitmap SkMatrix drawMatrix; drawMatrix.setTranslate(-bounds.left(), -bounds.top()); drawMatrix.postScale(scale, scale); drawMatrix.postTranslate(kAntiAliasPad, kAntiAliasPad); // setup bitmap backing SkASSERT(devPathBounds.fLeft == 0); SkASSERT(devPathBounds.fTop == 0); SkAutoPixmapStorage dst; if (!dst.tryAlloc(SkImageInfo::MakeA8(devPathBounds.width(), devPathBounds.height()))) { return false; } sk_bzero(dst.writable_addr(), dst.getSafeSize()); // rasterize path SkPaint paint; paint.setStyle(SkPaint::kFill_Style); paint.setAntiAlias(antiAlias); SkDraw draw; sk_bzero(&draw, sizeof(draw)); SkRasterClip rasterClip; rasterClip.setRect(devPathBounds); draw.fRC = &rasterClip; draw.fMatrix = &drawMatrix; draw.fDst = dst; SkPath path; shape.asPath(&path); draw.drawPathCoverage(path, paint); // generate signed distance field devPathBounds.outset(SK_DistanceFieldPad, SK_DistanceFieldPad); width = devPathBounds.width(); height = devPathBounds.height(); // TODO We should really generate this directly into the plot somehow SkAutoSMalloc<1024> dfStorage(width * height * sizeof(unsigned char)); // Generate signed distance field SkGenerateDistanceFieldFromA8Image((unsigned char*)dfStorage.get(), (const unsigned char*)dst.addr(), dst.width(), dst.height(), dst.rowBytes()); // add to atlas SkIPoint16 atlasLocation; GrBatchAtlas::AtlasID id; if (!atlas->addToAtlas(&id, target, width, height, dfStorage.get(), &atlasLocation)) { this->flush(target, flushInfo); if (!atlas->addToAtlas(&id, target, width, height, dfStorage.get(), &atlasLocation)) { return false; } } // add to cache shapeData->fKey.set(shape, dimension); shapeData->fScale = scale; shapeData->fID = id; // change the scaled rect to match the size of the inset distance field scaledBounds.fRight = scaledBounds.fLeft + SkIntToScalar(devPathBounds.width() - 2*SK_DistanceFieldInset); scaledBounds.fBottom = scaledBounds.fTop + SkIntToScalar(devPathBounds.height() - 2*SK_DistanceFieldInset); // shift the origin to the correct place relative to the distance field // need to also restore the fractional translation scaledBounds.offset(-SkIntToScalar(SK_DistanceFieldInset) - kAntiAliasPad + dx, -SkIntToScalar(SK_DistanceFieldInset) - kAntiAliasPad + dy); shapeData->fBounds = scaledBounds; // origin we render from is inset from distance field edge atlasLocation.fX += SK_DistanceFieldInset; atlasLocation.fY += SK_DistanceFieldInset; shapeData->fAtlasLocation = atlasLocation; fShapeCache->add(shapeData); fShapeList->addToTail(shapeData); #ifdef DF_PATH_TRACKING ++g_NumCachedPaths; #endif return true; }
JSBool SkJSDisplayable::GetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) { if (JSVAL_IS_INT(id) == 0) return JS_TRUE; SkJSDisplayable *p = (SkJSDisplayable *) JS_GetPrivate(cx, obj); SkDisplayable* displayable = p->fDisplayable; SkDisplayTypes displayableType = displayable->getType(); int members; const SkMemberInfo* info = SkDisplayType::GetMembers(NULL /* fMaker */, displayableType, &members); int idIndex = JSVAL_TO_INT(id); SkASSERT(idIndex >= 0 && idIndex < members); info = &info[idIndex]; SkDisplayTypes infoType = (SkDisplayTypes) info->fType; SkScalar scalar = 0; S32 s32 = 0; SkString* string= NULL; JSString *str; if (infoType == SkType_MemberProperty) { infoType = info->propertyType(); switch (infoType) { case SkType_Scalar: { SkScriptValue scriptValue; bool success = displayable->getProperty(info->propertyIndex(), &scriptValue); SkASSERT(scriptValue.fType == SkType_Scalar); scalar = scriptValue.fOperand.fScalar; } break; default: SkASSERT(0); // !!! unimplemented } } else { SkASSERT(info->fCount == 1); switch (infoType) { case SkType_Boolean: case SkType_Color: case SkType_S32: s32 = *(S32*) info->memberData(displayable); break; case SkType_String: info->getString(displayable, &string); break; case SkType_Scalar: SkOperand operand; info->getValue(displayable, &operand, 1); scalar = operand.fScalar; break; default: SkASSERT(0); // !!! unimplemented } } switch (infoType) { case SkType_Boolean: *vp = BOOLEAN_TO_JSVAL(s32); break; case SkType_Color: case SkType_S32: *vp = INT_TO_JSVAL(s32); break; case SkType_Scalar: if (SkScalarFraction(scalar) == 0) *vp = INT_TO_JSVAL(SkScalarFloor(scalar)); else #ifdef SK_SCALAR_IS_FLOAT *vp = DOUBLE_TO_JSVAL(scalar); #else *vp = DOUBLE_TO_JSVAL(scalar / 65536.0f ); #endif break; case SkType_String: str = JS_NewStringCopyN(cx, string->c_str(), string->size()); *vp = STRING_TO_JSVAL(str); break; default: SkASSERT(0); // !!! unimplemented } return JS_TRUE; }