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;
}
Example #2
0
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;
}
Example #3
0
    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);
    }
Example #4
0
    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();
    }
Example #5
0
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());
}
Example #6
0
        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);
                            }
                        }
                    }
                }
            }
Example #7
0
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;
}
Example #8
0
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;
}
Example #9
0
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);
}
Example #12
0
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);
    }
}
Example #13
0
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());
}
Example #14
0
    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);
    }
Example #15
0
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;
}
Example #16
0
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;
}
Example #17
0
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;
}
Example #18
0
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);
    }
}
Example #20
0
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());
}