/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "RecordingCanvas.h"

#include "DeferredLayerUpdater.h"
#include "RecordedOp.h"
#include "RenderNode.h"
#include "VectorDrawable.h"

namespace android {
namespace uirenderer {

RecordingCanvas::RecordingCanvas(size_t width, size_t height)
        : mState(*this)
        , mResourceCache(ResourceCache::getInstance()) {
    resetRecording(width, height);
}

RecordingCanvas::~RecordingCanvas() {
    LOG_ALWAYS_FATAL_IF(mDisplayList,
            "Destroyed a RecordingCanvas during a record!");
}

void RecordingCanvas::resetRecording(int width, int height) {
    LOG_ALWAYS_FATAL_IF(mDisplayList,
            "prepareDirty called a second time during a recording!");
    mDisplayList = new DisplayList();

    mState.initializeRecordingSaveStack(width, height);

    mDeferredBarrierType = DeferredBarrierType::InOrder;
    mState.setDirtyClip(false);
}

DisplayList* RecordingCanvas::finishRecording() {
    restoreToCount(1);
    mPaintMap.clear();
    mRegionMap.clear();
    mPathMap.clear();
    DisplayList* displayList = mDisplayList;
    mDisplayList = nullptr;
    mSkiaCanvasProxy.reset(nullptr);
    return displayList;
}

SkCanvas* RecordingCanvas::asSkCanvas() {
    LOG_ALWAYS_FATAL_IF(!mDisplayList,
            "attempting to get an SkCanvas when we are not recording!");
    if (!mSkiaCanvasProxy) {
        mSkiaCanvasProxy.reset(new SkiaCanvasProxy(this));
    }

    // SkCanvas instances default to identity transform, but should inherit
    // the state of this Canvas; if this code was in the SkiaCanvasProxy
    // constructor, we couldn't cache mSkiaCanvasProxy.
    SkMatrix parentTransform;
    getMatrix(&parentTransform);
    mSkiaCanvasProxy.get()->setMatrix(parentTransform);

    return mSkiaCanvasProxy.get();
}

// ----------------------------------------------------------------------------
// CanvasStateClient implementation
// ----------------------------------------------------------------------------

void RecordingCanvas::onViewportInitialized() {
}

void RecordingCanvas::onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) {
    if (removed.flags & Snapshot::kFlagIsFboLayer) {
        addOp(alloc().create_trivial<EndLayerOp>());
    } else if (removed.flags & Snapshot::kFlagIsLayer) {
        addOp(alloc().create_trivial<EndUnclippedLayerOp>());
    }
}

// ----------------------------------------------------------------------------
// android/graphics/Canvas state operations
// ----------------------------------------------------------------------------
// Save (layer)
int RecordingCanvas::save(SaveFlags::Flags flags) {
    return mState.save((int) flags);
}

void RecordingCanvas::RecordingCanvas::restore() {
    mState.restore();
}

void RecordingCanvas::restoreToCount(int saveCount) {
    mState.restoreToCount(saveCount);
}

int RecordingCanvas::saveLayer(float left, float top, float right, float bottom,
        const SkPaint* paint, SaveFlags::Flags flags) {
    // force matrix/clip isolation for layer
    flags |= SaveFlags::MatrixClip;
    bool clippedLayer = flags & SaveFlags::ClipToLayer;

    const Snapshot& previous = *mState.currentSnapshot();

    // initialize the snapshot as though it almost represents an FBO layer so deferred draw
    // operations will be able to store and restore the current clip and transform info, and
    // quick rejection will be correct (for display lists)

    const Rect unmappedBounds(left, top, right, bottom);

    // determine clipped bounds relative to previous viewport.
    Rect visibleBounds = unmappedBounds;
    previous.transform->mapRect(visibleBounds);

    if (CC_UNLIKELY(!clippedLayer
            && previous.transform->rectToRect()
            && visibleBounds.contains(previous.getRenderTargetClip()))) {
        // unlikely case where an unclipped savelayer is recorded with a clip it can use,
        // as none of its unaffected/unclipped area is visible
        clippedLayer = true;
        flags |= SaveFlags::ClipToLayer;
    }

    visibleBounds.doIntersect(previous.getRenderTargetClip());
    visibleBounds.snapToPixelBoundaries();
    visibleBounds.doIntersect(Rect(previous.getViewportWidth(), previous.getViewportHeight()));

    // Map visible bounds back to layer space, and intersect with parameter bounds
    Rect layerBounds = visibleBounds;
    Matrix4 inverse;
    inverse.loadInverse(*previous.transform);
    inverse.mapRect(layerBounds);
    layerBounds.doIntersect(unmappedBounds);

    int saveValue = mState.save((int) flags);
    Snapshot& snapshot = *mState.writableSnapshot();

    // layerBounds is in original bounds space, but clipped by current recording clip
    if (layerBounds.isEmpty() || unmappedBounds.isEmpty()) {
        // Don't bother recording layer, since it's been rejected
        if (CC_LIKELY(clippedLayer)) {
            snapshot.resetClip(0, 0, 0, 0);
        }
        return saveValue;
    }

    if (CC_LIKELY(clippedLayer)) {
        auto previousClip = getRecordedClip(); // note: done before new snapshot's clip has changed

        snapshot.flags |= Snapshot::kFlagIsLayer | Snapshot::kFlagIsFboLayer;
        snapshot.initializeViewport(unmappedBounds.getWidth(), unmappedBounds.getHeight());
        snapshot.transform->loadTranslate(-unmappedBounds.left, -unmappedBounds.top, 0.0f);

        Rect clip = layerBounds;
        clip.translate(-unmappedBounds.left, -unmappedBounds.top);
        snapshot.resetClip(clip.left, clip.top, clip.right, clip.bottom);
        snapshot.roundRectClipState = nullptr;

        addOp(alloc().create_trivial<BeginLayerOp>(
                unmappedBounds,
                *previous.transform, // transform to *draw* with
                previousClip, // clip to *draw* with
                refPaint(paint)));
    } else {
        snapshot.flags |= Snapshot::kFlagIsLayer;

        addOp(alloc().create_trivial<BeginUnclippedLayerOp>(
                unmappedBounds,
                *mState.currentSnapshot()->transform,
                getRecordedClip(),
                refPaint(paint)));
    }

    return saveValue;
}

// Matrix
void RecordingCanvas::rotate(float degrees) {
    if (degrees == 0) return;

    mState.rotate(degrees);
}

void RecordingCanvas::scale(float sx, float sy) {
    if (sx == 1 && sy == 1) return;

    mState.scale(sx, sy);
}

void RecordingCanvas::skew(float sx, float sy) {
    mState.skew(sx, sy);
}

void RecordingCanvas::translate(float dx, float dy) {
    if (dx == 0 && dy == 0) return;

    mState.translate(dx, dy, 0);
}

// Clip
bool RecordingCanvas::getClipBounds(SkRect* outRect) const {
    *outRect = mState.getLocalClipBounds().toSkRect();
    return !(outRect->isEmpty());
}
bool RecordingCanvas::quickRejectRect(float left, float top, float right, float bottom) const {
    return mState.quickRejectConservative(left, top, right, bottom);
}
bool RecordingCanvas::quickRejectPath(const SkPath& path) const {
    SkRect bounds = path.getBounds();
    return mState.quickRejectConservative(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
}
bool RecordingCanvas::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) {
    return mState.clipRect(left, top, right, bottom, op);
}
bool RecordingCanvas::clipPath(const SkPath* path, SkRegion::Op op) {
    return mState.clipPath(path, op);
}
bool RecordingCanvas::clipRegion(const SkRegion* region, SkRegion::Op op) {
    return mState.clipRegion(region, op);
}

// ----------------------------------------------------------------------------
// android/graphics/Canvas draw operations
// ----------------------------------------------------------------------------
void RecordingCanvas::drawColor(int color, SkXfermode::Mode mode) {
    SkPaint paint;
    paint.setColor(color);
    paint.setXfermodeMode(mode);
    drawPaint(paint);
}

void RecordingCanvas::drawPaint(const SkPaint& paint) {
    const ClipBase* clip = getRecordedClip();
    // if there's no current clip, draw a big rect and hope we cover the eventual clip bounds
    Rect bounds = clip ? clip->rect : Rect(-10000, -10000, 10000, 10000);
    addOp(alloc().create_trivial<RectOp>(
            bounds,
            Matrix4::identity(),
            clip,
            refPaint(&paint)));
}

static Rect calcBoundsOfPoints(const float* points, int floatCount) {
    Rect unmappedBounds(points[0], points[1], points[0], points[1]);
    for (int i = 2; i < floatCount; i += 2) {
        unmappedBounds.expandToCover(points[i], points[i + 1]);
    }
    return unmappedBounds;
}

// Geometry
void RecordingCanvas::drawPoints(const float* points, int floatCount, const SkPaint& paint) {
    if (floatCount < 2) return;
    floatCount &= ~0x1; // round down to nearest two

    addOp(alloc().create_trivial<PointsOp>(
            calcBoundsOfPoints(points, floatCount),
            *mState.currentSnapshot()->transform,
            getRecordedClip(),
            refPaint(&paint), refBuffer<float>(points, floatCount), floatCount));
}

void RecordingCanvas::drawLines(const float* points, int floatCount, const SkPaint& paint) {
    if (floatCount < 4) return;
    floatCount &= ~0x3; // round down to nearest four

    addOp(alloc().create_trivial<LinesOp>(
            calcBoundsOfPoints(points, floatCount),
            *mState.currentSnapshot()->transform,
            getRecordedClip(),
            refPaint(&paint), refBuffer<float>(points, floatCount), floatCount));
}

void RecordingCanvas::drawRect(float left, float top, float right, float bottom, const SkPaint& paint) {
    addOp(alloc().create_trivial<RectOp>(
            Rect(left, top, right, bottom),
            *(mState.currentSnapshot()->transform),
            getRecordedClip(),
            refPaint(&paint)));
}

void RecordingCanvas::drawSimpleRects(const float* rects, int vertexCount, const SkPaint* paint) {
    if (rects == nullptr) return;

    Vertex* rectData = (Vertex*) mDisplayList->allocator.create_trivial_array<Vertex>(vertexCount);
    Vertex* vertex = rectData;

    float left = FLT_MAX;
    float top = FLT_MAX;
    float right = FLT_MIN;
    float bottom = FLT_MIN;
    for (int index = 0; index < vertexCount; index += 4) {
        float l = rects[index + 0];
        float t = rects[index + 1];
        float r = rects[index + 2];
        float b = rects[index + 3];

        Vertex::set(vertex++, l, t);
        Vertex::set(vertex++, r, t);
        Vertex::set(vertex++, l, b);
        Vertex::set(vertex++, r, b);

        left = std::min(left, l);
        top = std::min(top, t);
        right = std::max(right, r);
        bottom = std::max(bottom, b);
    }
    addOp(alloc().create_trivial<SimpleRectsOp>(
            Rect(left, top, right, bottom),
            *(mState.currentSnapshot()->transform),
            getRecordedClip(),
            refPaint(paint), rectData, vertexCount));
}

void RecordingCanvas::drawRegion(const SkRegion& region, const SkPaint& paint) {
    if (paint.getStyle() == SkPaint::kFill_Style
            && (!paint.isAntiAlias() || mState.currentTransform()->isSimple())) {
        int count = 0;
        Vector<float> rects;
        SkRegion::Iterator it(region);
        while (!it.done()) {
            const SkIRect& r = it.rect();
            rects.push(r.fLeft);
            rects.push(r.fTop);
            rects.push(r.fRight);
            rects.push(r.fBottom);
            count += 4;
            it.next();
        }
        drawSimpleRects(rects.array(), count, &paint);
    } else {
        SkRegion::Iterator it(region);
        while (!it.done()) {
            const SkIRect& r = it.rect();
            drawRect(r.fLeft, r.fTop, r.fRight, r.fBottom, paint);
            it.next();
        }
    }
}
void RecordingCanvas::drawRoundRect(float left, float top, float right, float bottom,
            float rx, float ry, const SkPaint& paint) {
    addOp(alloc().create_trivial<RoundRectOp>(
            Rect(left, top, right, bottom),
            *(mState.currentSnapshot()->transform),
            getRecordedClip(),
            refPaint(&paint), rx, ry));
}

void RecordingCanvas::drawRoundRect(
        CanvasPropertyPrimitive* left, CanvasPropertyPrimitive* top,
        CanvasPropertyPrimitive* right, CanvasPropertyPrimitive* bottom,
        CanvasPropertyPrimitive* rx, CanvasPropertyPrimitive* ry,
        CanvasPropertyPaint* paint) {
    mDisplayList->ref(left);
    mDisplayList->ref(top);
    mDisplayList->ref(right);
    mDisplayList->ref(bottom);
    mDisplayList->ref(rx);
    mDisplayList->ref(ry);
    mDisplayList->ref(paint);
    refBitmapsInShader(paint->value.getShader());
    addOp(alloc().create_trivial<RoundRectPropsOp>(
            *(mState.currentSnapshot()->transform),
            getRecordedClip(),
            &paint->value,
            &left->value, &top->value, &right->value, &bottom->value,
            &rx->value, &ry->value));
}

void RecordingCanvas::drawCircle(float x, float y, float radius, const SkPaint& paint) {
    // TODO: move to Canvas.h
    if (radius <= 0) return;
    drawOval(x - radius, y - radius, x + radius, y + radius, paint);
}

void RecordingCanvas::drawCircle(
        CanvasPropertyPrimitive* x, CanvasPropertyPrimitive* y,
        CanvasPropertyPrimitive* radius, CanvasPropertyPaint* paint) {
    mDisplayList->ref(x);
    mDisplayList->ref(y);
    mDisplayList->ref(radius);
    mDisplayList->ref(paint);
    refBitmapsInShader(paint->value.getShader());
    addOp(alloc().create_trivial<CirclePropsOp>(
            *(mState.currentSnapshot()->transform),
            getRecordedClip(),
            &paint->value,
            &x->value, &y->value, &radius->value));
}

void RecordingCanvas::drawOval(float left, float top, float right, float bottom, const SkPaint& paint) {
    addOp(alloc().create_trivial<OvalOp>(
            Rect(left, top, right, bottom),
            *(mState.currentSnapshot()->transform),
            getRecordedClip(),
            refPaint(&paint)));
}

void RecordingCanvas::drawArc(float left, float top, float right, float bottom,
        float startAngle, float sweepAngle, bool useCenter, const SkPaint& paint) {
    if (fabs(sweepAngle) >= 360.0f) {
        drawOval(left, top, right, bottom, paint);
    } else {
        addOp(alloc().create_trivial<ArcOp>(
                Rect(left, top, right, bottom),
                *(mState.currentSnapshot()->transform),
                getRecordedClip(),
                refPaint(&paint),
                startAngle, sweepAngle, useCenter));
    }
}

void RecordingCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
    addOp(alloc().create_trivial<PathOp>(
            Rect(path.getBounds()),
            *(mState.currentSnapshot()->transform),
            getRecordedClip(),
            refPaint(&paint), refPath(&path)));
}

void RecordingCanvas::drawVectorDrawable(VectorDrawableRoot* tree) {
    mDisplayList->ref(tree);
    addOp(alloc().create_trivial<VectorDrawableOp>(
            tree,
            Rect(tree->getBounds()),
            *(mState.currentSnapshot()->transform),
            getRecordedClip()));
}

// Bitmap-based
void RecordingCanvas::drawBitmap(const SkBitmap& bitmap, float left, float top, const SkPaint* paint) {
    save(SaveFlags::Matrix);
    translate(left, top);
    drawBitmap(&bitmap, paint);
    restore();
}

void RecordingCanvas::drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix,
                            const SkPaint* paint) {
    if (matrix.isIdentity()) {
        drawBitmap(&bitmap, paint);
    } else if (!(matrix.getType() & ~(SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask))
            && MathUtils::isPositive(matrix.getScaleX())
            && MathUtils::isPositive(matrix.getScaleY())) {
        // SkMatrix::isScaleTranslate() not available in L
        SkRect src;
        SkRect dst;
        bitmap.getBounds(&src);
        matrix.mapRect(&dst, src);
        drawBitmap(bitmap, src.fLeft, src.fTop, src.fRight, src.fBottom,
                   dst.fLeft, dst.fTop, dst.fRight, dst.fBottom, paint);
    } else {
        save(SaveFlags::Matrix);
        concat(matrix);
        drawBitmap(&bitmap, paint);
        restore();
    }
}

void RecordingCanvas::drawBitmap(const SkBitmap& bitmap, float srcLeft, float srcTop,
            float srcRight, float srcBottom, float dstLeft, float dstTop,
            float dstRight, float dstBottom, const SkPaint* paint) {
    if (srcLeft == 0 && srcTop == 0
            && srcRight == bitmap.width()
            && srcBottom == bitmap.height()
            && (srcBottom - srcTop == dstBottom - dstTop)
            && (srcRight - srcLeft == dstRight - dstLeft)) {
        // transform simple rect to rect drawing case into position bitmap ops, since they merge
        save(SaveFlags::Matrix);
        translate(dstLeft, dstTop);
        drawBitmap(&bitmap, paint);
        restore();
    } else {
        addOp(alloc().create_trivial<BitmapRectOp>(
                Rect(dstLeft, dstTop, dstRight, dstBottom),
                *(mState.currentSnapshot()->transform),
                getRecordedClip(),
                refPaint(paint), refBitmap(bitmap),
                Rect(srcLeft, srcTop, srcRight, srcBottom)));
    }
}

void RecordingCanvas::drawBitmapMesh(const SkBitmap& bitmap, int meshWidth, int meshHeight,
            const float* vertices, const int* colors, const SkPaint* paint) {
    int vertexCount = (meshWidth + 1) * (meshHeight + 1);
    addOp(alloc().create_trivial<BitmapMeshOp>(
            calcBoundsOfPoints(vertices, vertexCount * 2),
            *(mState.currentSnapshot()->transform),
            getRecordedClip(),
            refPaint(paint), refBitmap(bitmap), meshWidth, meshHeight,
            refBuffer<float>(vertices, vertexCount * 2), // 2 floats per vertex
            refBuffer<int>(colors, vertexCount))); // 1 color per vertex
}

void RecordingCanvas::drawNinePatch(const SkBitmap& bitmap, const android::Res_png_9patch& patch,
            float dstLeft, float dstTop, float dstRight, float dstBottom,
            const SkPaint* paint) {
    addOp(alloc().create_trivial<PatchOp>(
            Rect(dstLeft, dstTop, dstRight, dstBottom),
            *(mState.currentSnapshot()->transform),
            getRecordedClip(),
            refPaint(paint), refBitmap(bitmap), refPatch(&patch)));
}

// Text
void RecordingCanvas::drawText(const uint16_t* glyphs, const float* positions, int glyphCount,
            const SkPaint& paint, float x, float y, float boundsLeft, float boundsTop,
            float boundsRight, float boundsBottom, float totalAdvance) {
    if (!glyphs || !positions || glyphCount <= 0 || PaintUtils::paintWillNotDrawText(paint)) return;
    glyphs = refBuffer<glyph_t>(glyphs, glyphCount);
    positions = refBuffer<float>(positions, glyphCount * 2);

    // TODO: either must account for text shadow in bounds, or record separate ops for text shadows
    addOp(alloc().create_trivial<TextOp>(
            Rect(boundsLeft, boundsTop, boundsRight, boundsBottom),
            *(mState.currentSnapshot()->transform),
            getRecordedClip(),
            refPaint(&paint), glyphs, positions, glyphCount, x, y));
    drawTextDecorations(x, y, totalAdvance, paint);
}

void RecordingCanvas::drawTextOnPath(const uint16_t* glyphs, int glyphCount, const SkPath& path,
            float hOffset, float vOffset, const SkPaint& paint) {
    if (!glyphs || glyphCount <= 0 || PaintUtils::paintWillNotDrawText(paint)) return;
    glyphs = refBuffer<glyph_t>(glyphs, glyphCount);
    addOp(alloc().create_trivial<TextOnPathOp>(
            mState.getLocalClipBounds(), // TODO: explicitly define bounds
            *(mState.currentSnapshot()->transform),
            getRecordedClip(),
            refPaint(&paint), glyphs, glyphCount, refPath(&path), hOffset, vOffset));
}

void RecordingCanvas::drawBitmap(const SkBitmap* bitmap, const SkPaint* paint) {
    addOp(alloc().create_trivial<BitmapOp>(
            Rect(bitmap->width(), bitmap->height()),
            *(mState.currentSnapshot()->transform),
            getRecordedClip(),
            refPaint(paint), refBitmap(*bitmap)));
}

void RecordingCanvas::drawRenderNode(RenderNode* renderNode) {
    auto&& stagingProps = renderNode->stagingProperties();
    RenderNodeOp* op = alloc().create_trivial<RenderNodeOp>(
            Rect(stagingProps.getWidth(), stagingProps.getHeight()),
            *(mState.currentSnapshot()->transform),
            getRecordedClip(),
            renderNode);
    int opIndex = addOp(op);
    int childIndex = mDisplayList->addChild(op);

    // update the chunk's child indices
    DisplayList::Chunk& chunk = mDisplayList->chunks.back();
    chunk.endChildIndex = childIndex + 1;

    if (renderNode->stagingProperties().isProjectionReceiver()) {
        // use staging property, since recording on UI thread
        mDisplayList->projectionReceiveIndex = opIndex;
    }
}

void RecordingCanvas::drawLayer(DeferredLayerUpdater* layerHandle) {
    // We ref the DeferredLayerUpdater due to its thread-safe ref-counting semantics.
    mDisplayList->ref(layerHandle);

    Layer* layer = layerHandle->backingLayer();
    Matrix4 totalTransform(*(mState.currentSnapshot()->transform));
    totalTransform.multiply(layer->getTransform());

    addOp(alloc().create_trivial<TextureLayerOp>(
            Rect(layer->getWidth(), layer->getHeight()),
            totalTransform,
            getRecordedClip(),
            layer));
}

void RecordingCanvas::callDrawGLFunction(Functor* functor) {
    mDisplayList->functors.push_back(functor);
    addOp(alloc().create_trivial<FunctorOp>(
            mState.getLocalClipBounds(), // TODO: explicitly define bounds
            *(mState.currentSnapshot()->transform),
            getRecordedClip(),
            functor));
}

size_t RecordingCanvas::addOp(RecordedOp* op) {
    // skip op with empty clip
    if (op->localClip && op->localClip->rect.isEmpty()) {
        // NOTE: this rejection happens after op construction/content ref-ing, so content ref'd
        // and held by renderthread isn't affected by clip rejection.
        // Could rewind alloc here if desired, but callers would have to not touch op afterwards.
        return -1;
    }

    int insertIndex = mDisplayList->ops.size();
    mDisplayList->ops.push_back(op);
    if (mDeferredBarrierType != DeferredBarrierType::None) {
        // op is first in new chunk
        mDisplayList->chunks.emplace_back();
        DisplayList::Chunk& newChunk = mDisplayList->chunks.back();
        newChunk.beginOpIndex = insertIndex;
        newChunk.endOpIndex = insertIndex + 1;
        newChunk.reorderChildren = (mDeferredBarrierType == DeferredBarrierType::OutOfOrder);

        int nextChildIndex = mDisplayList->children.size();
        newChunk.beginChildIndex = newChunk.endChildIndex = nextChildIndex;
        mDeferredBarrierType = DeferredBarrierType::None;
    } else {
        // standard case - append to existing chunk
        mDisplayList->chunks.back().endOpIndex = insertIndex + 1;
    }
    return insertIndex;
}

void RecordingCanvas::refBitmapsInShader(const SkShader* shader) {
    if (!shader) return;

    // If this paint has an SkShader that has an SkBitmap add
    // it to the bitmap pile
    SkBitmap bitmap;
    SkShader::TileMode xy[2];
    if (shader->isABitmap(&bitmap, nullptr, xy)) {
        refBitmap(bitmap);
        return;
    }
    SkShader::ComposeRec rec;
    if (shader->asACompose(&rec)) {
        refBitmapsInShader(rec.fShaderA);
        refBitmapsInShader(rec.fShaderB);
        return;
    }
}

}; // namespace uirenderer
}; // namespace android
