bool SkDisplayXMLParser::onEndElement(const char elem[]) { int parentIndex = fParents.count() - 1; if (parentIndex >= 0) { Parent& container = fParents[parentIndex]; SkDisplayable* displayable = container.fDisplayable; fMaker.fEndDepth = parentIndex; displayable->onEndElement(fMaker); if (fMaker.fError.hasError()) return true; if (parentIndex > 0) { SkDisplayable* parent = fParents[parentIndex - 1].fDisplayable; bool result = parent->add(fMaker, displayable); if (fMaker.hasError()) return true; if (result == false) { int infoCount; const SkMemberInfo* info = SkDisplayType::GetMembers(&fMaker, fParents[parentIndex - 1].fType, &infoCount); const SkMemberInfo* foundInfo; if ((foundInfo = searchContainer(info, infoCount)) != NULL) { parent->setReference(foundInfo, displayable); // if (displayable->isHelper() == false) fMaker.helperAdd(displayable); } else { fMaker.setErrorCode(SkDisplayXMLParserError::kElementTypeNotAllowedInParent); return true; } } if (parent->childrenNeedDisposing()) delete displayable; } fParents.remove(parentIndex); } fCurrDisplayable = NULL; if (fInInclude == false && strcasecmp(elem, "screenplay") == 0) { if (fMaker.fInMovie == false) { fMaker.fEnableTime = fMaker.getAppTime(); #if defined SK_DEBUG && defined SK_DEBUG_ANIMATION_TIMING if (fMaker.fDebugTimeBase == (SkMSec) -1) fMaker.fDebugTimeBase = fMaker.fEnableTime; SkString debugOut; SkMSec time = fMaker.getAppTime(); debugOut.appendS32(time - fMaker.fDebugTimeBase); debugOut.append(" onLoad enable="); debugOut.appendS32(fMaker.fEnableTime - fMaker.fDebugTimeBase); SkDebugf("%s\n", debugOut.c_str()); #endif fMaker.fEvents.doEvent(fMaker, SkDisplayEvent::kOnload, NULL); if (fMaker.fError.hasError()) return true; fMaker.fEvents.removeEvent(SkDisplayEvent::kOnload, NULL); } fInSkia = false; } return false; }
SkString* SkObjectParser::IRectToString(const SkIRect& rect) { SkString* mRect = new SkString("SkIRect: "); mRect->append("L: "); mRect->appendS32(rect.left()); mRect->append(", T: "); mRect->appendS32(rect.top()); mRect->append(", R: "); mRect->appendS32(rect.right()); mRect->append(", B: "); mRect->appendS32(rect.bottom()); return mRect; }
static void draw_label(SkCanvas* canvas, const SkRect& rect, int start, int sweep) { SkPaint paint; paint.setAntiAlias(true); paint.setTextAlign(SkPaint::kCenter_Align); SkString str; str.appendS32(start); str.append(", "); str.appendS32(sweep); canvas->drawText(str.c_str(), str.size(), rect.centerX(), rect.fBottom + paint.getTextSize() * 5/4, paint); }
static void doDraw(SkCanvas* canvas, SkPaint* paint, const int isrc[], const int idst[], int count) { SkMatrix matrix; SkPoint src[4], dst[4]; for (int i = 0; i < count; i++) { src[i].set(SkIntToScalar(isrc[2*i+0]), SkIntToScalar(isrc[2*i+1])); dst[i].set(SkIntToScalar(idst[2*i+0]), SkIntToScalar(idst[2*i+1])); } canvas->save(); matrix.setPolyToPoly(src, dst, count); canvas->concat(matrix); paint->setColor(SK_ColorGRAY); paint->setStyle(SkPaint::kStroke_Style); const SkScalar D = SkIntToScalar(64); canvas->drawRectCoords(0, 0, D, D, *paint); canvas->drawLine(0, 0, D, D, *paint); canvas->drawLine(0, D, D, 0, *paint); SkPaint::FontMetrics fm; paint->getFontMetrics(&fm); paint->setColor(SK_ColorRED); paint->setStyle(SkPaint::kFill_Style); SkScalar x = D/2; float y = D/2 - (fm.fAscent + fm.fDescent)/2; SkString str; str.appendS32(count); canvas->drawText(str.c_str(), str.size(), x, y, *paint); canvas->restore(); }
void GrGLConvolutionEffect::emitCode(EmitArgs& args) { const GrConvolutionEffect& ce = args.fFp.cast<GrConvolutionEffect>(); GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; fImageIncrementUni = uniformHandler->addUniform(GrGLSLUniformHandler::kFragment_Visibility, kVec2f_GrSLType, kDefault_GrSLPrecision, "ImageIncrement"); if (ce.useBounds()) { fBoundsUni = uniformHandler->addUniform(GrGLSLUniformHandler::kFragment_Visibility, kVec2f_GrSLType, kDefault_GrSLPrecision, "Bounds"); } int width = Gr1DKernelEffect::WidthFromRadius(ce.radius()); fKernelUni = uniformHandler->addUniformArray(GrGLSLUniformHandler::kFragment_Visibility, kFloat_GrSLType, kDefault_GrSLPrecision, "Kernel", width); GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder; SkString coords2D = fragBuilder->ensureFSCoords2D(args.fCoords, 0); fragBuilder->codeAppendf("%s = vec4(0, 0, 0, 0);", args.fOutputColor); const GrGLSLShaderVar& kernel = uniformHandler->getUniformVariable(fKernelUni); const char* imgInc = uniformHandler->getUniformCStr(fImageIncrementUni); fragBuilder->codeAppendf("vec2 coord = %s - %d.0 * %s;", coords2D.c_str(), ce.radius(), imgInc); // Manually unroll loop because some drivers don't; yields 20-30% speedup. for (int i = 0; i < width; i++) { SkString index; SkString kernelIndex; index.appendS32(i); kernel.appendArrayAccess(index.c_str(), &kernelIndex); if (ce.useBounds()) { // We used to compute a bool indicating whether we're in bounds or not, cast it to a // float, and then mul weight*texture_sample by the float. However, the Adreno 430 seems // to have a bug that caused corruption. const char* bounds = uniformHandler->getUniformCStr(fBoundsUni); const char* component = ce.direction() == Gr1DKernelEffect::kY_Direction ? "y" : "x"; fragBuilder->codeAppendf("if (coord.%s >= %s.x && coord.%s <= %s.y) {", component, bounds, component, bounds); } fragBuilder->codeAppendf("\t\t%s += ", args.fOutputColor); fragBuilder->appendTextureLookup(args.fSamplers[0], "coord"); fragBuilder->codeAppendf(" * %s;\n", kernelIndex.c_str()); if (ce.useBounds()) { fragBuilder->codeAppend("}"); } fragBuilder->codeAppendf("\t\tcoord += %s;\n", imgInc); } SkString modulate; GrGLSLMulVarBy4f(&modulate, args.fOutputColor, args.fInputColor); fragBuilder->codeAppend(modulate.c_str()); }
virtual void onDrawContent(SkCanvas* canvas) { canvas->translate(SkIntToScalar(10), SkIntToScalar(50)); const SkScalar W = SkIntToScalar(fBitmaps[0].width() + 1); const SkScalar H = SkIntToScalar(fBitmaps[0].height() + 1); SkPaint paint; const SkScalar scale = SkFloatToScalar(0.897917f); canvas->scale(SK_Scalar1, scale); for (int k = 0; k < 2; k++) { paint.setFilterBitmap(k == 1); for (int j = 0; j < 2; j++) { paint.setDither(j == 1); for (int i = 0; i < fBitmapCount; i++) { SkScalar x = (k * fBitmapCount + j) * W; SkScalar y = i * H; x = SkIntToScalar(SkScalarRound(x)); y = SkIntToScalar(SkScalarRound(y)); canvas->drawBitmap(fBitmaps[i], x, y, &paint); if (i == 0) { SkPaint p; p.setAntiAlias(true); p.setTextAlign(SkPaint::kCenter_Align); p.setTextSize(SkIntToScalar(18)); SkString s("dither="); s.appendS32(paint.isDither()); s.append(" filter="); s.appendS32(paint.isFilterBitmap()); canvas->drawText(s.c_str(), s.size(), x + W/2, y - p.getTextSize(), p); } if (k+j == 2) { SkPaint p; p.setAntiAlias(true); p.setTextSize(SkIntToScalar(18)); SkString s; s.append(" depth="); s.appendS32(fBitmaps[i].config() == SkBitmap::kRGB_565_Config ? 16 : 32); canvas->drawText(s.c_str(), s.size(), x + W + SkIntToScalar(4), y + H/2, p); } } } } }
SkString* SkObjectParser::ImageToString(const SkImage* image) { SkString* str = new SkString("SkImage: "); if (!image) { return str; } str->append("W: "); str->appendS32(image->width()); str->append(" H: "); str->appendS32(image->height()); if (image->isOpaque()) { str->append(" opaque"); } else { str->append(" not-opaque"); } str->append(" uniqueID: "); str->appendS32(image->uniqueID()); return str; }
SkString* SkObjectParser::BitmapToString(const SkBitmap& bitmap) { SkString* mBitmap = new SkString("SkBitmap: "); mBitmap->append("W: "); mBitmap->appendS32(bitmap.width()); mBitmap->append(" H: "); mBitmap->appendS32(bitmap.height()); const char* gColorTypeStrings[] = { "None", "A8", "565", "4444", "RGBA", "BGRA", "Index8", "G8", "RGBAf16" }; static_assert(kLastEnum_SkColorType + 1 == SK_ARRAY_COUNT(gColorTypeStrings), "colortype names do not match colortype enum"); mBitmap->append(" ColorType: "); mBitmap->append(gColorTypeStrings[bitmap.colorType()]); if (bitmap.isOpaque()) { mBitmap->append(" opaque"); } else { mBitmap->append(" not-opaque"); } if (bitmap.isImmutable()) { mBitmap->append(" immutable"); } else { mBitmap->append(" not-immutable"); } if (bitmap.isVolatile()) { mBitmap->append(" volatile"); } else { mBitmap->append(" not-volatile"); } mBitmap->append(" genID: "); mBitmap->appendS32(bitmap.getGenerationID()); return mBitmap; }
void GrGLConvolutionEffect::emitCode(GrGLFPBuilder* builder, const GrFragmentProcessor&, const char* outputColor, const char* inputColor, const TransformedCoordsArray& coords, const TextureSamplerArray& samplers) { fImageIncrementUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec2f_GrSLType, kDefault_GrSLPrecision, "ImageIncrement"); if (this->useBounds()) { fBoundsUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec2f_GrSLType, kDefault_GrSLPrecision, "Bounds"); } fKernelUni = builder->addUniformArray(GrGLProgramBuilder::kFragment_Visibility, kFloat_GrSLType, kDefault_GrSLPrecision, "Kernel", this->width()); GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder(); SkString coords2D = fsBuilder->ensureFSCoords2D(coords, 0); fsBuilder->codeAppendf("\t\t%s = vec4(0, 0, 0, 0);\n", outputColor); int width = this->width(); const GrGLShaderVar& kernel = builder->getUniformVariable(fKernelUni); const char* imgInc = builder->getUniformCStr(fImageIncrementUni); fsBuilder->codeAppendf("\t\tvec2 coord = %s - %d.0 * %s;\n", coords2D.c_str(), fRadius, imgInc); // Manually unroll loop because some drivers don't; yields 20-30% speedup. for (int i = 0; i < width; i++) { SkString index; SkString kernelIndex; index.appendS32(i); kernel.appendArrayAccess(index.c_str(), &kernelIndex); fsBuilder->codeAppendf("\t\t%s += ", outputColor); fsBuilder->appendTextureLookup(samplers[0], "coord"); if (this->useBounds()) { const char* bounds = builder->getUniformCStr(fBoundsUni); const char* component = this->direction() == Gr1DKernelEffect::kY_Direction ? "y" : "x"; fsBuilder->codeAppendf(" * float(coord.%s >= %s.x && coord.%s <= %s.y)", component, bounds, component, bounds); } fsBuilder->codeAppendf(" * %s;\n", kernelIndex.c_str()); fsBuilder->codeAppendf("\t\tcoord += %s;\n", imgInc); } SkString modulate; GrGLSLMulVarBy4f(&modulate, outputColor, inputColor); fsBuilder->codeAppend(modulate.c_str()); }
SkString* SkObjectParser::BitmapToString(const SkBitmap& bitmap) { SkString* mBitmap = new SkString("SkBitmap: "); mBitmap->append("W: "); mBitmap->appendS32(bitmap.width()); mBitmap->append(" H: "); mBitmap->appendS32(bitmap.height()); const char* gConfigStrings[] = { "None", "A8", "Index8", "RGB565", "ARGB4444", "ARGB8888" }; SkASSERT(SkBitmap::kConfigCount == SK_ARRAY_COUNT(gConfigStrings)); mBitmap->append(" Config: "); mBitmap->append(gConfigStrings[bitmap.config()]); if (bitmap.isOpaque()) { mBitmap->append(" opaque"); } else { mBitmap->append(" not-opaque"); } if (bitmap.isImmutable()) { mBitmap->append(" immutable"); } else { mBitmap->append(" not-immutable"); } if (bitmap.isVolatile()) { mBitmap->append(" volatile"); } else { mBitmap->append(" not-volatile"); } mBitmap->append(" genID: "); mBitmap->appendS32(bitmap.getGenerationID()); return mBitmap; }
JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_init(JNIEnv* env, jobject thiz, jobject jsampleActivity, jint msaaSampleCount) { // setup jni hooks to the java activity gActivityGlue.m_env = env; jclass clazz = env->FindClass("com/skia/SkiaSampleActivity"); gActivityGlue.m_obj = env->NewWeakGlobalRef(jsampleActivity); gActivityGlue.m_setTitle = GetJMethod(env, clazz, "setTitle", "(Ljava/lang/CharSequence;)V"); gActivityGlue.m_setSlideList = GetJMethod(env, clazz, "setSlideList", "([Ljava/lang/String;)V"); gActivityGlue.m_addToDownloads = GetJMethod(env, clazz, "addToDownloads", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); env->DeleteLocalRef(clazz); // setup jni hooks to the java renderer clazz = env->FindClass("com/skia/SkiaSampleRenderer"); gWindowGlue.m_obj = env->NewWeakGlobalRef(thiz); gWindowGlue.m_inval = GetJMethod(env, clazz, "requestRender", "()V"); gWindowGlue.m_queueSkEvent = GetJMethod(env, clazz, "queueSkEvent", "()V"); gWindowGlue.m_startTimer = GetJMethod(env, clazz, "startTimer", "(I)V"); gWindowGlue.m_getMSAASampleCount = GetJMethod(env, clazz, "getMSAASampleCount", "()I"); env->DeleteLocalRef(clazz); application_init(); SkTArray<const char*> args; args.push_back("SampleApp"); // TODO: push ability to select skp dir into the UI args.push_back("--pictureDir"); args.push_back("/sdcard/skiabot/skia_skp"); SkString msaaSampleCountString; if (msaaSampleCount > 0) { args.push_back("--msaa"); msaaSampleCountString.appendS32(static_cast<uint32_t>(msaaSampleCount)); args.push_back(msaaSampleCountString.c_str()); } gWindow = new SampleWindow(NULL, args.count(), const_cast<char**>(args.begin()), NULL); // send the list of slides up to the activity const int slideCount = gWindow->sampleCount(); jobjectArray slideList = env->NewObjectArray(slideCount, env->FindClass("java/lang/String"), env->NewStringUTF("")); for (int i = 0; i < slideCount; i++) { jstring slideTitle = env->NewStringUTF(gWindow->getSampleTitle(i).c_str()); env->SetObjectArrayElement(slideList, i, slideTitle); env->DeleteLocalRef(slideTitle); } env->CallVoidMethod(gActivityGlue.m_obj, gActivityGlue.m_setSlideList, slideList); env->DeleteLocalRef(slideList); }
void SkAnimateMaker::setEnableTime(SkMSec appTime, SkMSec expectedTime) { #if defined SK_DEBUG && defined SK_DEBUG_ANIMATION_TIMING SkString debugOut; SkMSec time = getAppTime(); debugOut.appendS32(time - fDebugTimeBase); debugOut.append(" set enable old enable="); debugOut.appendS32(fEnableTime - fDebugTimeBase); debugOut.append(" old adjust="); debugOut.appendS32(fAdjustedStart); debugOut.append(" new enable="); debugOut.appendS32(expectedTime - fDebugTimeBase); debugOut.append(" new adjust="); debugOut.appendS32(appTime - expectedTime); SkDebugf("%s\n", debugOut.c_str()); #endif fAdjustedStart = appTime - expectedTime; fEnableTime = expectedTime; SkDisplayable** firstMovie = fMovies.begin(); SkDisplayable** endMovie = fMovies.end(); for (SkDisplayable** ptr = firstMovie; ptr < endMovie; ptr++) { SkDisplayMovie* movie = (SkDisplayMovie*) *ptr; movie->fMovie.fMaker->setEnableTime(appTime, expectedTime); } }
void SkActive::start() { int count = fState.count(); SkASSERT(count == fAnimators.count()); SkASSERT(count == fInterpolators.count()); for (int index = 0; index < count; index++) { SkState& state = fState[index]; if (state.fStarted) continue; state.fStarted = true; #if defined SK_DEBUG && defined SK_DEBUG_ANIMATION_TIMING SkString debugOut; SkMSec time = fMaker.getAppTime(); debugOut.appendS32(time - fMaker.fDebugTimeBase); debugOut.append(" active start adjust delay id="); debugOut.append(fApply._id); debugOut.append("; "); debugOut.append(fAnimators[index]->_id); debugOut.append("="); debugOut.appendS32(fAnimators[index]->fStart - fMaker.fDebugTimeBase); debugOut.append(":"); debugOut.appendS32(state.fStartTime); #endif if (state.fStartTime > 0) { SkMSec future = fAnimators[index]->fStart + state.fStartTime; if (future > fMaker.fEnableTime) fMaker.notifyInvalTime(future); else fMaker.notifyInval(); #if defined SK_DEBUG && defined SK_DEBUG_ANIMATION_TIMING debugOut.append(":"); debugOut.appendS32(future - fMaker.fDebugTimeBase); #endif } if (state.fStartTime >= fMaker.fAdjustedStart) { state.fStartTime -= fMaker.fAdjustedStart; #if defined SK_DEBUG && defined SK_DEBUG_ANIMATION_TIMING debugOut.append(" (less adjust = "); debugOut.appendS32(fMaker.fAdjustedStart); #endif } state.fStartTime += fAnimators[index]->fStart; #if defined SK_DEBUG && defined SK_DEBUG_ANIMATION_TIMING debugOut.append(") new start = "); debugOut.appendS32(state.fStartTime - fMaker.fDebugTimeBase); SkDebugf("%s\n", debugOut.c_str()); // SkASSERT((int) (state.fStartTime - fMaker.fDebugTimeBase) >= 0); #endif } SkASSERT(fAnimators.count() == fInterpolators.count()); }
void onDrawContent(SkCanvas* canvas) override { SkASSERT(fParent); int numChoices = fMax - fMin + 1; fSlider.offsetTo(fSliderRange * ( (*fOutput)/SkIntToScalar(numChoices) + 1.0f/(2.0f * numChoices) ), fSlider.fTop); SkString valueStr; valueStr.appendS32(*fOutput); this->drawLabel(canvas, valueStr); SkPaint sliderPaint; sliderPaint.setColor(0xFFF3F3F3); canvas->drawRect(fSlider, sliderPaint); SkPaint ctrlRegionPaint; ctrlRegionPaint.setColor(0xFFFFFFFF); ctrlRegionPaint.setStyle(SkPaint::kStroke_Style); ctrlRegionPaint.setStrokeWidth(2.0f); canvas->drawRect(fCtrlRegion, ctrlRegionPaint); }
bool SkAnimator::onEvent(const SkEvent& evt) { #ifdef SK_DEBUG SkAnimator* root = fMaker->getRoot(); if (root == NULL) root = this; if (root->isTrackingEvents()) root->eventDone(evt); #endif if (evt.isType(SK_EventType_OnEnd)) { SkEventState eventState; bool success = evt.findPtr("anim", (void**) &eventState.fDisplayable); SkASSERT(success); success = evt.findS32("time", (int32_t*) &fMaker->fEnableTime); SkASSERT(success); fMaker->fAdjustedStart = fMaker->getAppTime() - fMaker->fEnableTime; fMaker->fEvents.doEvent(*fMaker, SkDisplayEvent::kOnEnd, &eventState); fMaker->fAdjustedStart = 0; goto inval; } if (evt.isType(SK_EventType_Delay)) { fMaker->doDelayedEvent(); goto inval; } { const char* id = evt.findString("id"); if (id == NULL) return false; SkDisplayable** firstMovie = fMaker->fMovies.begin(); SkDisplayable** endMovie = fMaker->fMovies.end(); for (SkDisplayable** ptr = firstMovie; ptr < endMovie; ptr++) { SkDisplayMovie* movie = (SkDisplayMovie*) *ptr; movie->doEvent(evt); } { SkDisplayable* event; if (fMaker->find(id, &event) == false) return false; #if defined SK_DEBUG && defined SK_DEBUG_ANIMATION_TIMING SkString debugOut; SkMSec realTime = fMaker->getAppTime(); debugOut.appendS32(realTime - fMaker->fDebugTimeBase); debugOut.append(" onEvent id="); debugOut.append(id); #endif SkMSec time = evt.getFast32(); if (time != 0) { SkMSec app = fMaker->getAppTime(); fMaker->setEnableTime(app, time); #if defined SK_DEBUG && defined SK_DEBUG_ANIMATION_TIMING debugOut.append(" time="); debugOut.appendS32(time - fMaker->fDebugTimeBase); debugOut.append(" adjust="); debugOut.appendS32(fMaker->fAdjustedStart); #endif } #if defined SK_DEBUG && defined SK_DEBUG_ANIMATION_TIMING SkDebugf("%s\n", debugOut.c_str()); #endif SkASSERT(event->isEvent()); SkDisplayEvent* displayEvent = (SkDisplayEvent*) event; displayEvent->populateInput(*fMaker, evt); displayEvent->enableEvent(*fMaker); } } inval: fMaker->notifyInval(); return true; }
SkString* SkObjectParser::PathToString(const SkPath& path) { SkString* mPath = new SkString("Path ("); static const char* gFillStrings[] = { "Winding", "EvenOdd", "InverseWinding", "InverseEvenOdd" }; mPath->append(gFillStrings[path.getFillType()]); mPath->append(", "); static const char* gConvexityStrings[] = { "Unknown", "Convex", "Concave" }; SkASSERT(SkPath::kConcave_Convexity == 2); mPath->append(gConvexityStrings[path.getConvexity()]); mPath->append(", "); if (path.isRect(nullptr)) { mPath->append("isRect, "); } else { mPath->append("isNotRect, "); } mPath->appendS32(path.countVerbs()); mPath->append("V, "); mPath->appendS32(path.countPoints()); mPath->append("P): "); static const char* gVerbStrings[] = { "Move", "Line", "Quad", "Conic", "Cubic", "Close", "Done" }; static const int gPtsPerVerb[] = { 1, 1, 2, 2, 3, 0, 0 }; static const int gPtOffsetPerVerb[] = { 0, 1, 1, 1, 1, 0, 0 }; SkASSERT(SkPath::kDone_Verb == 6); SkPath::Iter iter(const_cast<SkPath&>(path), false); SkPath::Verb verb; SkPoint points[4]; for(verb = iter.next(points, false); verb != SkPath::kDone_Verb; verb = iter.next(points, false)) { mPath->append(gVerbStrings[verb]); mPath->append(" "); for (int i = 0; i < gPtsPerVerb[verb]; ++i) { mPath->append("("); mPath->appendScalar(points[gPtOffsetPerVerb[verb]+i].fX); mPath->append(", "); mPath->appendScalar(points[gPtOffsetPerVerb[verb]+i].fY); mPath->append(")"); } if (SkPath::kConic_Verb == verb) { mPath->append("("); mPath->appendScalar(iter.conicWeight()); mPath->append(")"); } mPath->append(" "); } SkString* boundStr = SkObjectParser::RectToString(path.getBounds(), " Bound: "); if (boundStr) { mPath->append(*boundStr); delete boundStr; } return mPath; }
bool SkApply::enable(SkAnimateMaker& maker) { fEnabled = true; bool initialized = fActive != NULL; if (dynamicScope.size() > 0) enableDynamic(maker); if (maker.fError.hasError()) return false; int animators = fAnimators.count(); int index; for (index = 0; index < animators; index++) { SkAnimateBase* animator = fAnimators[index]; animator->fStart = maker.fEnableTime; animator->fResetPending = animator->fReset; } if (scope && scope->isApply()) ((SkApply*) scope)->setEmbedded(); /* if (mode == kMode_once) { if (scope) { activate(maker); interpolate(maker, maker.fEnableTime); inactivate(maker); } return true; }*/ if ((mode == kMode_immediate || mode == kMode_create) && scope == NULL) return false; // !!! error? bool enableMe = scope && (scope->hasEnable() || scope->isApply() || scope->isDrawable() == false); if (mode == kMode_immediate && enableMe || mode == kMode_create) activate(maker); // for non-drawables like post, prime them here if (mode == kMode_immediate && enableMe) fActive->enable(); if (mode == kMode_create && scope != NULL) { enableCreate(maker); return true; } if (mode == kMode_immediate) { return scope->isApply() || scope->isDrawable() == false; } refresh(maker); SkDisplayList& displayList = maker.fDisplayList; SkDrawable* drawable; #if defined SK_DEBUG && defined SK_DEBUG_ANIMATION_TIMING SkString debugOut; SkMSec time = maker.getAppTime(); debugOut.appendS32(time - maker.fDebugTimeBase); debugOut.append(" apply enable id="); debugOut.append(_id); debugOut.append("; start="); debugOut.appendS32(maker.fEnableTime - maker.fDebugTimeBase); SkDebugf("%s\n", debugOut.c_str()); #endif if (scope == NULL || scope->isApply() || scope->getType() == SkType_Movie || scope->isDrawable() == false) { activate(maker); // for non-drawables like post, prime them here if (initialized) { append(this); } fEnabling = true; interpolate(maker, maker.fEnableTime); fEnabling = false; if (scope != NULL && dontDraw == false) scope->enable(maker); return true; } else if (initialized && restore == false) append(this); #if 0 bool wasActive = inactivate(maker); // start fresh if (wasActive) { activate(maker); interpolate(maker, maker.fEnableTime); return true; } #endif // start here; // now that one apply might embed another, only the parent apply should replace the scope // or get appended to the display list // similarly, an apply added by an add immediate has already been located in the display list // and should not get moved or added again here if (fEmbedded) { return false; // already added to display list by embedder } drawable = (SkDrawable*) scope; SkTDDrawableArray* parentList; SkTDDrawableArray* grandList; SkGroup* parentGroup; SkGroup* thisGroup; int old = displayList.findGroup(drawable, &parentList, &parentGroup, &thisGroup, &grandList); if (old < 0) goto append; else if (fContainsScope) { if ((*parentList)[old] != this || restore == true) { append: if (parentGroup) parentGroup->markCopySize(old); if (parentList->count() < 10000) { fAppended = true; *parentList->append() = this; } else maker.setErrorCode(SkDisplayXMLParserError::kDisplayTreeTooDeep); old = -1; } else reset(); } else { SkASSERT(old < parentList->count()); if ((*parentList)[old]->isApply()) { SkApply* apply = (SkApply*) (*parentList)[old]; if (apply != this && apply->fActive == NULL) apply->activate(maker); apply->append(this); parentGroup = NULL; } else { if (parentGroup) parentGroup->markCopySize(old); SkDrawable** newApplyLocation = &(*parentList)[old]; SkGroup* pGroup; int oldApply = displayList.findGroup(this, &parentList, &pGroup, &thisGroup, &grandList); if (oldApply >= 0) { (*parentList)[oldApply] = (SkDrawable*) SkDisplayType::CreateInstance(&maker, SkType_Apply); parentGroup = NULL; fDeleteScope = true; } *newApplyLocation = this; } } if (parentGroup) { parentGroup->markCopySet(old); fDeleteScope = dynamicScope.size() == 0; } return true; }
bool SkApply::interpolate(SkAnimateMaker& maker, SkMSec rawTime) { if (fActive == NULL) return false; bool result = false; #if defined SK_DEBUG && defined SK_DEBUG_ANIMATION_TIMING SkMSec time = maker.getAppTime(); if (lastTime == (SkMSec) -1) lastTime = rawTime - 1; if (fActive != NULL && strcmp(id, "a3") == 0 && rawTime > lastTime) { lastTime += 1000; SkString debugOut; debugOut.appendS32(time - maker.fDebugTimeBase); debugOut.append(" apply id="); debugOut.append(_id); debugOut.append("; "); debugOut.append(fActive->fAnimators[0]->_id); debugOut.append("="); debugOut.appendS32(rawTime - fActive->fState[0].fStartTime); debugOut.append(")"); SkDebugf("%s\n", debugOut.c_str()); } #endif fActive->start(); if (restore) fActive->initializeSave(); int animators = fActive->fAnimators.count(); for (int inner = 0; inner < animators; inner++) { SkAnimateBase* animate = fActive->fAnimators[inner]; if (animate->fChanged) { animate->fChanged = false; animate->fStart = rawTime; // SkTypedArray values; // int count = animate->fValues.count(); // values.setCount(count); // memcpy(values.begin(), animate->fValues.begin(), sizeof(SkOperand) * count); animate->onEndElement(maker); // if (memcmp(values.begin(), animate->fValues.begin(), sizeof(SkOperand) * count) != 0) { fActive->append(this); fActive->start(); // } } SkMSec time = fActive->getTime(rawTime, inner); SkActive::SkState& state = fActive->fState[inner]; if (SkMSec_LT(rawTime, state.fStartTime)) { if (fEnabling) { animate->fDelayed = true; maker.delayEnable(this, state.fStartTime); } continue; } else animate->fDelayed = false; SkMSec innerTime = fLastTime = state.getRelativeTime(time); if (restore) fActive->restoreInterpolatorValues(inner); if (animate->fReset) { if (transition != SkApply::kTransition_reverse) { if (SkMSec_LT(state.fBegin + state.fDuration, innerTime)) { if (animate->fResetPending) { innerTime = 0; animate->fResetPending = false; } else continue; } } else if (innerTime == 0) { if (animate->fResetPending) { innerTime = state.fBegin + state.fDuration; animate->fResetPending = false; } else continue; } } int count = animate->components(); SkAutoSTMalloc<16, SkOperand> values(count); SkInterpolatorBase::Result interpResult = fActive->fInterpolators[inner]->timeToValues( innerTime, values.get()); result |= (interpResult != SkInterpolatorBase::kFreezeEnd_Result); if ((transition != SkApply::kTransition_reverse && interpResult == SkInterpolatorBase::kFreezeEnd_Result || transition == SkApply::kTransition_reverse && fLastTime == 0) && state.fUnpostedEndEvent) { // SkDEBUGF(("interpolate: post on end\n")); state.fUnpostedEndEvent = false; maker.postOnEnd(animate, state.fBegin + state.fDuration); maker.fAdjustedStart = 0; // !!! left over from synchronizing animation days, undoubtably out of date (and broken) } if (animate->formula.size() > 0) { if (fLastTime > animate->dur) fLastTime = animate->dur; SkTypedArray formulaValues; formulaValues.setCount(count); bool success = animate->fFieldInfo->setValue(maker, &formulaValues, 0, 0, NULL, animate->getValuesType(), animate->formula); SkASSERT(success); if (restore) save(inner); // save existing value applyValues(inner, formulaValues.begin(), count, animate->getValuesType(), innerTime); } else { if (restore) save(inner); // save existing value applyValues(inner, values.get(), count, animate->getValuesType(), innerTime); } } return result; }
/** * Write the canvas to an image file and/or JSON summary. * * @param canvas Must be non-null. Canvas to be written to a file. * @param writePath If nonempty, write the binary image to a file within this directory. * @param mismatchPath If nonempty, write the binary image to a file within this directory, * but only if the image does not match expectations. * @param inputFilename If we are writing out a binary image, use this to build its filename. * @param jsonSummaryPtr If not null, add image results (checksum) to this summary. * @param useChecksumBasedFilenames If true, use checksum-based filenames when writing to disk. * @param tileNumberPtr If not null, which tile number this image contains. * * @return bool True if the operation completed successfully. */ static bool write(SkCanvas* canvas, const SkString& writePath, const SkString& mismatchPath, const SkString& inputFilename, ImageResultsAndExpectations *jsonSummaryPtr, bool useChecksumBasedFilenames, const int* tileNumberPtr=NULL) { SkASSERT(canvas != NULL); if (NULL == canvas) { return false; } SkBitmap bitmap; SkISize size = canvas->getDeviceSize(); setup_bitmap(&bitmap, size.width(), size.height()); canvas->readPixels(&bitmap, 0, 0); force_all_opaque(bitmap); BitmapAndDigest bitmapAndDigest(bitmap); SkString escapedInputFilename(inputFilename); replace_char(&escapedInputFilename, '.', '_'); // TODO(epoger): what about including the config type within outputFilename? That way, // we could combine results of different config types without conflicting filenames. SkString outputFilename; const char *outputSubdirPtr = NULL; if (useChecksumBasedFilenames) { ImageDigest *imageDigestPtr = bitmapAndDigest.getImageDigestPtr(); outputSubdirPtr = escapedInputFilename.c_str(); outputFilename.set(imageDigestPtr->getHashType()); outputFilename.append("_"); outputFilename.appendU64(imageDigestPtr->getHashValue()); } else { outputFilename.set(escapedInputFilename); if (tileNumberPtr) { outputFilename.append("-tile"); outputFilename.appendS32(*tileNumberPtr); } } outputFilename.append(".png"); if (jsonSummaryPtr) { ImageDigest *imageDigestPtr = bitmapAndDigest.getImageDigestPtr(); SkString outputRelativePath; if (outputSubdirPtr) { outputRelativePath.set(outputSubdirPtr); outputRelativePath.append("/"); // always use "/", even on Windows outputRelativePath.append(outputFilename); } else { outputRelativePath.set(outputFilename); } jsonSummaryPtr->add(inputFilename.c_str(), outputRelativePath.c_str(), *imageDigestPtr, tileNumberPtr); if (!mismatchPath.isEmpty() && !jsonSummaryPtr->getExpectation(inputFilename.c_str(), tileNumberPtr).matches(*imageDigestPtr)) { if (!write_bitmap_to_disk(bitmap, mismatchPath, outputSubdirPtr, outputFilename)) { return false; } } } if (writePath.isEmpty()) { return true; } else { return write_bitmap_to_disk(bitmap, writePath, outputSubdirPtr, outputFilename); } }
bool SkScriptRuntime::executeTokens(unsigned char* opCode) { SkOperand2 operand[2]; // 1=accumulator and 2=operand SkScriptEngine2::TypeOp op; size_t ref; int index, size; int registerLoad; SkScriptCallBack* callBack SK_INIT_TO_AVOID_WARNING; do { switch ((op = (SkScriptEngine2::TypeOp) *opCode++)) { case SkScriptEngine2::kArrayToken: // create an array operand[0].fArray = new SkOpArray(SkOperand2::kNoType /*fReturnType*/); break; case SkScriptEngine2::kArrayIndex: // array accessor index = operand[1].fS32; if (index >= operand[0].fArray->count()) { fError = kArrayIndexOutOfBounds; return false; } operand[0] = operand[0].fArray->begin()[index]; break; case SkScriptEngine2::kArrayParam: // array initializer, or function param *operand[0].fArray->append() = operand[1]; break; case SkScriptEngine2::kCallback: memcpy(&index, opCode, sizeof(index)); opCode += sizeof(index); callBack = fCallBackArray[index]; break; case SkScriptEngine2::kFunctionCall: { memcpy(&ref, opCode, sizeof(ref)); opCode += sizeof(ref); SkScriptCallBackFunction* callBackFunction = (SkScriptCallBackFunction*) callBack; if (callBackFunction->invoke(ref, operand[0].fArray, /* params */ &operand[0] /* result */) == false) { fError = kFunctionCallFailed; return false; } } break; case SkScriptEngine2::kMemberOp: { memcpy(&ref, opCode, sizeof(ref)); opCode += sizeof(ref); SkScriptCallBackMember* callBackMember = (SkScriptCallBackMember*) callBack; if (callBackMember->invoke(ref, operand[0].fObject, &operand[0]) == false) { fError = kMemberOpFailed; return false; } } break; case SkScriptEngine2::kPropertyOp: { memcpy(&ref, opCode, sizeof(ref)); opCode += sizeof(ref); SkScriptCallBackProperty* callBackProperty = (SkScriptCallBackProperty*) callBack; if (callBackProperty->getResult(ref, &operand[0])== false) { fError = kPropertyOpFailed; return false; } } break; case SkScriptEngine2::kAccumulatorPop: fRunStack.pop(&operand[0]); break; case SkScriptEngine2::kAccumulatorPush: *fRunStack.push() = operand[0]; break; case SkScriptEngine2::kIntegerAccumulator: case SkScriptEngine2::kIntegerOperand: registerLoad = op - SkScriptEngine2::kIntegerAccumulator; memcpy(&operand[registerLoad].fS32, opCode, sizeof(int32_t)); opCode += sizeof(int32_t); break; case SkScriptEngine2::kScalarAccumulator: case SkScriptEngine2::kScalarOperand: registerLoad = op - SkScriptEngine2::kScalarAccumulator; memcpy(&operand[registerLoad].fScalar, opCode, sizeof(SkScalar)); opCode += sizeof(SkScalar); break; case SkScriptEngine2::kStringAccumulator: case SkScriptEngine2::kStringOperand: { SkString* strPtr = new SkString(); track(strPtr); registerLoad = op - SkScriptEngine2::kStringAccumulator; memcpy(&size, opCode, sizeof(size)); opCode += sizeof(size); strPtr->set((char*) opCode, size); opCode += size; operand[registerLoad].fString = strPtr; } break; case SkScriptEngine2::kStringTrack: // call after kObjectToValue track(operand[0].fString); break; case SkScriptEngine2::kBoxToken: { SkOperand2::OpType type; memcpy(&type, opCode, sizeof(type)); opCode += sizeof(type); SkScriptCallBackConvert* callBackBox = (SkScriptCallBackConvert*) callBack; if (callBackBox->convert(type, &operand[0]) == false) return false; } break; case SkScriptEngine2::kUnboxToken: case SkScriptEngine2::kUnboxToken2: { SkScriptCallBackConvert* callBackUnbox = (SkScriptCallBackConvert*) callBack; if (callBackUnbox->convert(SkOperand2::kObject, &operand[0]) == false) return false; } break; case SkScriptEngine2::kIfOp: case SkScriptEngine2::kLogicalAndInt: memcpy(&size, opCode, sizeof(size)); opCode += sizeof(size); if (operand[0].fS32 == 0) opCode += size; // skip to else (or end of if predicate) break; case SkScriptEngine2::kElseOp: memcpy(&size, opCode, sizeof(size)); opCode += sizeof(size); opCode += size; // if true: after predicate, always skip to end of else break; case SkScriptEngine2::kLogicalOrInt: memcpy(&size, opCode, sizeof(size)); opCode += sizeof(size); if (operand[0].fS32 != 0) opCode += size; // skip to kToBool opcode after || predicate break; // arithmetic conversion ops case SkScriptEngine2::kFlipOpsOp: SkTSwap(operand[0], operand[1]); break; case SkScriptEngine2::kIntToString: case SkScriptEngine2::kIntToString2: case SkScriptEngine2::kScalarToString: case SkScriptEngine2::kScalarToString2: { SkString* strPtr = new SkString(); track(strPtr); if (op == SkScriptEngine2::kIntToString || op == SkScriptEngine2::kIntToString2) strPtr->appendS32(operand[op - SkScriptEngine2::kIntToString].fS32); else strPtr->appendScalar(operand[op - SkScriptEngine2::kScalarToString].fScalar); operand[0].fString = strPtr; } break; case SkScriptEngine2::kIntToScalar: case SkScriptEngine2::kIntToScalar2: operand[0].fScalar = SkScriptEngine2::IntToScalar(operand[op - SkScriptEngine2::kIntToScalar].fS32); break; case SkScriptEngine2::kStringToInt: if (SkParse::FindS32(operand[0].fString->c_str(), &operand[0].fS32) == NULL) return false; break; case SkScriptEngine2::kStringToScalar: case SkScriptEngine2::kStringToScalar2: if (SkParse::FindScalar(operand[0].fString->c_str(), &operand[op - SkScriptEngine2::kStringToScalar].fScalar) == NULL) return false; break; case SkScriptEngine2::kScalarToInt: operand[0].fS32 = SkScalarFloorToInt(operand[0].fScalar); break; // arithmetic ops case SkScriptEngine2::kAddInt: operand[0].fS32 += operand[1].fS32; break; case SkScriptEngine2::kAddScalar: operand[0].fScalar += operand[1].fScalar; break; case SkScriptEngine2::kAddString: // if (fTrackString.find(operand[1].fString) < 0) { // operand[1].fString = SkNEW_ARGS(SkString, (*operand[1].fString)); // track(operand[1].fString); // } operand[0].fString->append(*operand[1].fString); break; case SkScriptEngine2::kBitAndInt: operand[0].fS32 &= operand[1].fS32; break; case SkScriptEngine2::kBitNotInt: operand[0].fS32 = ~operand[0].fS32; break; case SkScriptEngine2::kBitOrInt: operand[0].fS32 |= operand[1].fS32; break; case SkScriptEngine2::kDivideInt: SkASSERT(operand[1].fS32 != 0); if (operand[1].fS32 == 0) operand[0].fS32 = operand[0].fS32 == 0 ? SK_NaN32 : operand[0].fS32 > 0 ? SK_MaxS32 : -SK_MaxS32; else if (operand[1].fS32 != 0) // throw error on divide by zero? operand[0].fS32 /= operand[1].fS32; break; case SkScriptEngine2::kDivideScalar: if (operand[1].fScalar == 0) operand[0].fScalar = operand[0].fScalar == 0 ? SK_ScalarNaN : operand[0].fScalar > 0 ? SK_ScalarMax : -SK_ScalarMax; else operand[0].fScalar = SkScalarDiv(operand[0].fScalar, operand[1].fScalar); break; case SkScriptEngine2::kEqualInt: operand[0].fS32 = operand[0].fS32 == operand[1].fS32; break; case SkScriptEngine2::kEqualScalar: operand[0].fS32 = operand[0].fScalar == operand[1].fScalar; break; case SkScriptEngine2::kEqualString: operand[0].fS32 = *operand[0].fString == *operand[1].fString; break; case SkScriptEngine2::kGreaterEqualInt: operand[0].fS32 = operand[0].fS32 >= operand[1].fS32; break; case SkScriptEngine2::kGreaterEqualScalar: operand[0].fS32 = operand[0].fScalar >= operand[1].fScalar; break; case SkScriptEngine2::kGreaterEqualString: operand[0].fS32 = strcmp(operand[0].fString->c_str(), operand[1].fString->c_str()) >= 0; break; case SkScriptEngine2::kToBool: operand[0].fS32 = !! operand[0].fS32; break; case SkScriptEngine2::kLogicalNotInt: operand[0].fS32 = ! operand[0].fS32; break; case SkScriptEngine2::kMinusInt: operand[0].fS32 = -operand[0].fS32; break; case SkScriptEngine2::kMinusScalar: operand[0].fScalar = -operand[0].fScalar; break; case SkScriptEngine2::kModuloInt: operand[0].fS32 %= operand[1].fS32; break; case SkScriptEngine2::kModuloScalar: operand[0].fScalar = SkScalarMod(operand[0].fScalar, operand[1].fScalar); break; case SkScriptEngine2::kMultiplyInt: operand[0].fS32 *= operand[1].fS32; break; case SkScriptEngine2::kMultiplyScalar: operand[0].fScalar = SkScalarMul(operand[0].fScalar, operand[1].fScalar); break; case SkScriptEngine2::kShiftLeftInt: operand[0].fS32 <<= operand[1].fS32; break; case SkScriptEngine2::kShiftRightInt: operand[0].fS32 >>= operand[1].fS32; break; case SkScriptEngine2::kSubtractInt: operand[0].fS32 -= operand[1].fS32; break; case SkScriptEngine2::kSubtractScalar: operand[0].fScalar -= operand[1].fScalar; break; case SkScriptEngine2::kXorInt: operand[0].fS32 ^= operand[1].fS32; break; case SkScriptEngine2::kEnd: goto done; case SkScriptEngine2::kNop: SkASSERT(0); default: break; } } while (true); done: fRunStack.push(operand[0]); return true; }
void SkXMLWriter::addS32Attribute(const char name[], int32_t value) { SkString tmp; tmp.appendS32(value); this->addAttribute(name, tmp.c_str()); }
bool SkWStream::writeDecAsText(int32_t dec) { SkString tmp; tmp.appendS32(dec); return this->write(tmp.c_str(), tmp.size()); }