/*
 * 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 "BakedOpDispatcher.h"

#include "BakedOpRenderer.h"
#include "Caches.h"
#include "Glop.h"
#include "GlopBuilder.h"
#include "Patch.h"
#include "PathTessellator.h"
#include "renderstate/OffscreenBufferPool.h"
#include "renderstate/RenderState.h"
#include "utils/GLUtils.h"
#include "VertexBuffer.h"

#include <algorithm>
#include <math.h>
#include <SkPaintDefaults.h>
#include <SkPathOps.h>

namespace android {
namespace uirenderer {

static void storeTexturedRect(TextureVertex* vertices, const Rect& bounds, const Rect& texCoord) {
    vertices[0] = { bounds.left, bounds.top, texCoord.left, texCoord.top };
    vertices[1] = { bounds.right, bounds.top, texCoord.right, texCoord.top };
    vertices[2] = { bounds.left, bounds.bottom, texCoord.left, texCoord.bottom };
    vertices[3] = { bounds.right, bounds.bottom, texCoord.right, texCoord.bottom };
}

void BakedOpDispatcher::onMergedBitmapOps(BakedOpRenderer& renderer,
        const MergedBakedOpList& opList) {

    const BakedOpState& firstState = *(opList.states[0]);
    const SkBitmap* bitmap = (static_cast<const BitmapOp*>(opList.states[0]->op))->bitmap;

    AssetAtlas::Entry* entry = renderer.renderState().assetAtlas().getEntry(bitmap->pixelRef());
    Texture* texture = entry ? entry->texture : renderer.caches().textureCache.get(bitmap);
    if (!texture) return;
    const AutoTexture autoCleanup(texture);

    TextureVertex vertices[opList.count * 4];
    Rect texCoords(0, 0, 1, 1);
    if (entry) {
        entry->uvMapper.map(texCoords);
    }
    for (size_t i = 0; i < opList.count; i++) {
        const BakedOpState& state = *(opList.states[i]);
        TextureVertex* rectVerts = &vertices[i * 4];

        // calculate unclipped bounds, since they'll determine texture coordinates
        Rect opBounds = state.op->unmappedBounds;
        state.computedState.transform.mapRect(opBounds);
        if (CC_LIKELY(state.computedState.transform.isPureTranslate())) {
            // pure translate, so snap (same behavior as onBitmapOp)
            opBounds.snapToPixelBoundaries();
        }
        storeTexturedRect(rectVerts, opBounds, texCoords);
        renderer.dirtyRenderTarget(opBounds);
    }

    const int textureFillFlags = (bitmap->colorType() == kAlpha_8_SkColorType)
            ? TextureFillFlags::IsAlphaMaskTexture : TextureFillFlags::None;
    Glop glop;
    GlopBuilder(renderer.renderState(), renderer.caches(), &glop)
            .setRoundRectClipState(firstState.roundRectClipState)
            .setMeshTexturedIndexedQuads(vertices, opList.count * 6)
            .setFillTexturePaint(*texture, textureFillFlags, firstState.op->paint, firstState.alpha)
            .setTransform(Matrix4::identity(), TransformFlags::None)
            .setModelViewIdentityEmptyBounds()
            .build();
    ClipRect renderTargetClip(opList.clip);
    const ClipBase* clip = opList.clipSideFlags ? &renderTargetClip : nullptr;
    renderer.renderGlop(nullptr, clip, glop);
}

void BakedOpDispatcher::onMergedPatchOps(BakedOpRenderer& renderer,
        const MergedBakedOpList& opList) {
    const PatchOp& firstOp = *(static_cast<const PatchOp*>(opList.states[0]->op));
    const BakedOpState& firstState = *(opList.states[0]);
    AssetAtlas::Entry* entry = renderer.renderState().assetAtlas().getEntry(
            firstOp.bitmap->pixelRef());

    // Batches will usually contain a small number of items so it's
    // worth performing a first iteration to count the exact number
    // of vertices we need in the new mesh
    uint32_t totalVertices = 0;

    for (size_t i = 0; i < opList.count; i++) {
        const PatchOp& op = *(static_cast<const PatchOp*>(opList.states[i]->op));

        // TODO: cache mesh lookups
        const Patch* opMesh = renderer.caches().patchCache.get(
                entry, op.bitmap->width(), op.bitmap->height(),
                op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight(), op.patch);
        totalVertices += opMesh->verticesCount;
    }

    const bool dirtyRenderTarget = renderer.offscreenRenderTarget();

    uint32_t indexCount = 0;

    TextureVertex vertices[totalVertices];
    TextureVertex* vertex = &vertices[0];
    // Create a mesh that contains the transformed vertices for all the
    // 9-patch objects that are part of the batch. Note that onDefer()
    // enforces ops drawn by this function to have a pure translate or
    // identity matrix
    for (size_t i = 0; i < opList.count; i++) {
        const PatchOp& op = *(static_cast<const PatchOp*>(opList.states[i]->op));
        const BakedOpState& state = *opList.states[i];

        // TODO: cache mesh lookups
        const Patch* opMesh = renderer.caches().patchCache.get(
                entry, op.bitmap->width(), op.bitmap->height(),
                op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight(), op.patch);


        uint32_t vertexCount = opMesh->verticesCount;
        if (vertexCount == 0) continue;

        // We use the bounds to know where to translate our vertices
        // Using patchOp->state.mBounds wouldn't work because these
        // bounds are clipped
        const float tx = floorf(state.computedState.transform.getTranslateX()
                + op.unmappedBounds.left + 0.5f);
        const float ty = floorf(state.computedState.transform.getTranslateY()
                + op.unmappedBounds.top + 0.5f);

        // Copy & transform all the vertices for the current operation
        TextureVertex* opVertices = opMesh->vertices.get();
        for (uint32_t j = 0; j < vertexCount; j++, opVertices++) {
            TextureVertex::set(vertex++,
                    opVertices->x + tx, opVertices->y + ty,
                    opVertices->u, opVertices->v);
        }

        // Dirty the current layer if possible. When the 9-patch does not
        // contain empty quads we can take a shortcut and simply set the
        // dirty rect to the object's bounds.
        if (dirtyRenderTarget) {
            if (!opMesh->hasEmptyQuads) {
                renderer.dirtyRenderTarget(Rect(tx, ty,
                        tx + op.unmappedBounds.getWidth(), ty + op.unmappedBounds.getHeight()));
            } else {
                const size_t count = opMesh->quads.size();
                for (size_t i = 0; i < count; i++) {
                    const Rect& quadBounds = opMesh->quads[i];
                    const float x = tx + quadBounds.left;
                    const float y = ty + quadBounds.top;
                    renderer.dirtyRenderTarget(Rect(x, y,
                            x + quadBounds.getWidth(), y + quadBounds.getHeight()));
                }
            }
        }

        indexCount += opMesh->indexCount;
    }


    Texture* texture = entry ? entry->texture : renderer.caches().textureCache.get(firstOp.bitmap);
    if (!texture) return;
    const AutoTexture autoCleanup(texture);

    // 9 patches are built for stretching - always filter
    int textureFillFlags = TextureFillFlags::ForceFilter;
    if (firstOp.bitmap->colorType() == kAlpha_8_SkColorType) {
        textureFillFlags |= TextureFillFlags::IsAlphaMaskTexture;
    }
    Glop glop;
    GlopBuilder(renderer.renderState(), renderer.caches(), &glop)
            .setRoundRectClipState(firstState.roundRectClipState)
            .setMeshTexturedIndexedQuads(vertices, indexCount)
            .setFillTexturePaint(*texture, textureFillFlags, firstOp.paint, firstState.alpha)
            .setTransform(Matrix4::identity(), TransformFlags::None)
            .setModelViewIdentityEmptyBounds()
            .build();
    ClipRect renderTargetClip(opList.clip);
    const ClipBase* clip = opList.clipSideFlags ? &renderTargetClip : nullptr;
    renderer.renderGlop(nullptr, clip, glop);
}

static void renderTextShadow(BakedOpRenderer& renderer, FontRenderer& fontRenderer,
        const TextOp& op, const BakedOpState& textOpState) {
    renderer.caches().textureState().activateTexture(0);

    PaintUtils::TextShadow textShadow;
    if (!PaintUtils::getTextShadow(op.paint, &textShadow)) {
        LOG_ALWAYS_FATAL("failed to query shadow attributes");
    }

    renderer.caches().dropShadowCache.setFontRenderer(fontRenderer);
    ShadowTexture* texture = renderer.caches().dropShadowCache.get(
            op.paint, op.glyphs, op.glyphCount, textShadow.radius, op.positions);
    // If the drop shadow exceeds the max texture size or couldn't be
    // allocated, skip drawing
    if (!texture) return;
    const AutoTexture autoCleanup(texture);

    const float sx = op.x - texture->left + textShadow.dx;
    const float sy = op.y - texture->top + textShadow.dy;

    Glop glop;
    GlopBuilder(renderer.renderState(), renderer.caches(), &glop)
            .setRoundRectClipState(textOpState.roundRectClipState)
            .setMeshTexturedUnitQuad(nullptr)
            .setFillShadowTexturePaint(*texture, textShadow.color, *op.paint, textOpState.alpha)
            .setTransform(textOpState.computedState.transform, TransformFlags::None)
            .setModelViewMapUnitToRect(Rect(sx, sy, sx + texture->width(), sy + texture->height()))
            .build();

    // Compute damage bounds and clip (since may differ from those in textOpState).
    // Bounds should be same as text op, but with dx/dy offset and radius outset
    // applied in local space.
    auto& transform = textOpState.computedState.transform;
    Rect shadowBounds = op.unmappedBounds; // STROKE
    const bool expandForStroke = op.paint->getStyle() != SkPaint::kFill_Style;
    if (expandForStroke) {
        shadowBounds.outset(op.paint->getStrokeWidth() * 0.5f);
    }
    shadowBounds.translate(textShadow.dx, textShadow.dy);
    shadowBounds.outset(textShadow.radius, textShadow.radius);
    transform.mapRect(shadowBounds);
    if (CC_UNLIKELY(expandForStroke &&
            (!transform.isPureTranslate() || op.paint->getStrokeWidth() < 1.0f))) {
        shadowBounds.outset(0.5f);
    }

    auto clipState = textOpState.computedState.clipState;
    if (clipState->mode != ClipMode::Rectangle
            || !clipState->rect.contains(shadowBounds)) {
        // need clip, so pass it and clip bounds
        shadowBounds.doIntersect(clipState->rect);
    } else {
        // don't need clip, ignore
        clipState = nullptr;
    }

    renderer.renderGlop(&shadowBounds, clipState, glop);
}

enum class TextRenderType {
    Defer,
    Flush
};

static void renderTextOp(BakedOpRenderer& renderer, const TextOp& op, const BakedOpState& state,
        const ClipBase* renderClip, TextRenderType renderType) {
    FontRenderer& fontRenderer = renderer.caches().fontRenderer.getFontRenderer();

    if (CC_UNLIKELY(PaintUtils::hasTextShadow(op.paint))) {
        fontRenderer.setFont(op.paint, SkMatrix::I());
        renderTextShadow(renderer, fontRenderer, op, state);
    }

    float x = op.x;
    float y = op.y;
    const Matrix4& transform = state.computedState.transform;
    const bool pureTranslate = transform.isPureTranslate();
    if (CC_LIKELY(pureTranslate)) {
        x = floorf(x + transform.getTranslateX() + 0.5f);
        y = floorf(y + transform.getTranslateY() + 0.5f);
        fontRenderer.setFont(op.paint, SkMatrix::I());
        fontRenderer.setTextureFiltering(false);
    } else if (CC_UNLIKELY(transform.isPerspective())) {
        fontRenderer.setFont(op.paint, SkMatrix::I());
        fontRenderer.setTextureFiltering(true);
    } else {
        // We only pass a partial transform to the font renderer. That partial
        // matrix defines how glyphs are rasterized. Typically we want glyphs
        // to be rasterized at their final size on screen, which means the partial
        // matrix needs to take the scale factor into account.
        // When a partial matrix is used to transform glyphs during rasterization,
        // the mesh is generated with the inverse transform (in the case of scale,
        // the mesh is generated at 1.0 / scale for instance.) This allows us to
        // apply the full transform matrix at draw time in the vertex shader.
        // Applying the full matrix in the shader is the easiest way to handle
        // rotation and perspective and allows us to always generated quads in the
        // font renderer which greatly simplifies the code, clipping in particular.
        float sx, sy;
        transform.decomposeScale(sx, sy);
        fontRenderer.setFont(op.paint, SkMatrix::MakeScale(
                roundf(std::max(1.0f, sx)),
                roundf(std::max(1.0f, sy))));
        fontRenderer.setTextureFiltering(true);
    }
    Rect layerBounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f);

    int alpha = PaintUtils::getAlphaDirect(op.paint) * state.alpha;
    SkXfermode::Mode mode = PaintUtils::getXfermodeDirect(op.paint);
    TextDrawFunctor functor(&renderer, &state, renderClip,
            x, y, pureTranslate, alpha, mode, op.paint);

    bool forceFinish = (renderType == TextRenderType::Flush);
    bool mustDirtyRenderTarget = renderer.offscreenRenderTarget();
    const Rect* localOpClip = pureTranslate ? &state.computedState.clipRect() : nullptr;
    fontRenderer.renderPosText(op.paint, localOpClip, op.glyphs, op.glyphCount, x, y,
            op.positions, mustDirtyRenderTarget ? &layerBounds : nullptr, &functor, forceFinish);

    if (mustDirtyRenderTarget) {
        if (!pureTranslate) {
            transform.mapRect(layerBounds);
        }
        renderer.dirtyRenderTarget(layerBounds);
    }
}

void BakedOpDispatcher::onMergedTextOps(BakedOpRenderer& renderer,
        const MergedBakedOpList& opList) {
    ClipRect renderTargetClip(opList.clip);
    const ClipBase* clip = opList.clipSideFlags ? &renderTargetClip : nullptr;
    for (size_t i = 0; i < opList.count; i++) {
        const BakedOpState& state = *(opList.states[i]);
        const TextOp& op = *(static_cast<const TextOp*>(state.op));
        TextRenderType renderType = (i + 1 == opList.count)
                ? TextRenderType::Flush : TextRenderType::Defer;
        renderTextOp(renderer, op, state, clip, renderType);
    }
}

namespace VertexBufferRenderFlags {
    enum {
        Offset = 0x1,
        ShadowInterp = 0x2,
    };
}

static void renderVertexBuffer(BakedOpRenderer& renderer, const BakedOpState& state,
        const VertexBuffer& vertexBuffer, float translateX, float translateY,
        const SkPaint& paint, int vertexBufferRenderFlags) {
    if (CC_LIKELY(vertexBuffer.getVertexCount())) {
        bool shadowInterp = vertexBufferRenderFlags & VertexBufferRenderFlags::ShadowInterp;
        const int transformFlags = TransformFlags::OffsetByFudgeFactor;
        Glop glop;
        GlopBuilder(renderer.renderState(), renderer.caches(), &glop)
                .setRoundRectClipState(state.roundRectClipState)
                .setMeshVertexBuffer(vertexBuffer, shadowInterp)
                .setFillPaint(paint, state.alpha)
                .setTransform(state.computedState.transform, transformFlags)
                .setModelViewOffsetRect(translateX, translateY, vertexBuffer.getBounds())
                .build();
        renderer.renderGlop(state, glop);
    }
}

static void renderConvexPath(BakedOpRenderer& renderer, const BakedOpState& state,
        const SkPath& path, const SkPaint& paint) {
    VertexBuffer vertexBuffer;
    // TODO: try clipping large paths to viewport
    PathTessellator::tessellatePath(path, &paint, state.computedState.transform, vertexBuffer);
    renderVertexBuffer(renderer, state, vertexBuffer, 0.0f, 0.0f, paint, 0);
}

static void renderPathTexture(BakedOpRenderer& renderer, const BakedOpState& state,
        float xOffset, float yOffset, PathTexture& texture, const SkPaint& paint) {
    Rect dest(texture.width(), texture.height());
    dest.translate(xOffset + texture.left - texture.offset,
            yOffset + texture.top - texture.offset);
    Glop glop;
    GlopBuilder(renderer.renderState(), renderer.caches(), &glop)
            .setRoundRectClipState(state.roundRectClipState)
            .setMeshTexturedUnitQuad(nullptr)
            .setFillPathTexturePaint(texture, paint, state.alpha)
            .setTransform(state.computedState.transform,  TransformFlags::None)
            .setModelViewMapUnitToRect(dest)
            .build();
    renderer.renderGlop(state, glop);
}

SkRect getBoundsOfFill(const RecordedOp& op) {
    SkRect bounds = op.unmappedBounds.toSkRect();
    if (op.paint->getStyle() == SkPaint::kStrokeAndFill_Style) {
        float outsetDistance = op.paint->getStrokeWidth() / 2;
        bounds.outset(outsetDistance, outsetDistance);
    }
    return bounds;
}

void BakedOpDispatcher::onArcOp(BakedOpRenderer& renderer, const ArcOp& op, const BakedOpState& state) {
    // TODO: support fills (accounting for concavity if useCenter && sweepAngle > 180)
    if (op.paint->getStyle() != SkPaint::kStroke_Style
            || op.paint->getPathEffect() != nullptr
            || op.useCenter) {
        PathTexture* texture = renderer.caches().pathCache.getArc(
                op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight(),
                op.startAngle, op.sweepAngle, op.useCenter, op.paint);
        const AutoTexture holder(texture);
        if (CC_LIKELY(holder.texture)) {
            renderPathTexture(renderer, state, op.unmappedBounds.left, op.unmappedBounds.top,
                    *texture, *(op.paint));
        }
    } else {
        SkRect rect = getBoundsOfFill(op);
        SkPath path;
        if (op.useCenter) {
            path.moveTo(rect.centerX(), rect.centerY());
        }
        path.arcTo(rect, op.startAngle, op.sweepAngle, !op.useCenter);
        if (op.useCenter) {
            path.close();
        }
        renderConvexPath(renderer, state, path, *(op.paint));
    }
}

void BakedOpDispatcher::onBitmapOp(BakedOpRenderer& renderer, const BitmapOp& op, const BakedOpState& state) {
    Texture* texture = renderer.getTexture(op.bitmap);
    if (!texture) return;
    const AutoTexture autoCleanup(texture);

    const int textureFillFlags = (op.bitmap->colorType() == kAlpha_8_SkColorType)
            ? TextureFillFlags::IsAlphaMaskTexture : TextureFillFlags::None;
    Glop glop;
    GlopBuilder(renderer.renderState(), renderer.caches(), &glop)
            .setRoundRectClipState(state.roundRectClipState)
            .setMeshTexturedUnitQuad(texture->uvMapper)
            .setFillTexturePaint(*texture, textureFillFlags, op.paint, state.alpha)
            .setTransform(state.computedState.transform, TransformFlags::None)
            .setModelViewMapUnitToRectSnap(Rect(texture->width(), texture->height()))
            .build();
    renderer.renderGlop(state, glop);
}

void BakedOpDispatcher::onBitmapMeshOp(BakedOpRenderer& renderer, const BitmapMeshOp& op, const BakedOpState& state) {
    const static UvMapper defaultUvMapper;
    const uint32_t elementCount = op.meshWidth * op.meshHeight * 6;

    std::unique_ptr<ColorTextureVertex[]> mesh(new ColorTextureVertex[elementCount]);
    ColorTextureVertex* vertex = &mesh[0];

    const int* colors = op.colors;
    std::unique_ptr<int[]> tempColors;
    if (!colors) {
        uint32_t colorsCount = (op.meshWidth + 1) * (op.meshHeight + 1);
        tempColors.reset(new int[colorsCount]);
        memset(tempColors.get(), 0xff, colorsCount * sizeof(int));
        colors = tempColors.get();
    }

    Texture* texture = renderer.renderState().assetAtlas().getEntryTexture(op.bitmap->pixelRef());
    const UvMapper& mapper(texture && texture->uvMapper ? *texture->uvMapper : defaultUvMapper);

    for (int32_t y = 0; y < op.meshHeight; y++) {
        for (int32_t x = 0; x < op.meshWidth; x++) {
            uint32_t i = (y * (op.meshWidth + 1) + x) * 2;

            float u1 = float(x) / op.meshWidth;
            float u2 = float(x + 1) / op.meshWidth;
            float v1 = float(y) / op.meshHeight;
            float v2 = float(y + 1) / op.meshHeight;

            mapper.map(u1, v1, u2, v2);

            int ax = i + (op.meshWidth + 1) * 2;
            int ay = ax + 1;
            int bx = i;
            int by = bx + 1;
            int cx = i + 2;
            int cy = cx + 1;
            int dx = i + (op.meshWidth + 1) * 2 + 2;
            int dy = dx + 1;

            const float* vertices = op.vertices;
            ColorTextureVertex::set(vertex++, vertices[dx], vertices[dy], u2, v2, colors[dx / 2]);
            ColorTextureVertex::set(vertex++, vertices[ax], vertices[ay], u1, v2, colors[ax / 2]);
            ColorTextureVertex::set(vertex++, vertices[bx], vertices[by], u1, v1, colors[bx / 2]);

            ColorTextureVertex::set(vertex++, vertices[dx], vertices[dy], u2, v2, colors[dx / 2]);
            ColorTextureVertex::set(vertex++, vertices[bx], vertices[by], u1, v1, colors[bx / 2]);
            ColorTextureVertex::set(vertex++, vertices[cx], vertices[cy], u2, v1, colors[cx / 2]);
        }
    }

    if (!texture) {
        texture = renderer.caches().textureCache.get(op.bitmap);
        if (!texture) {
            return;
        }
    }
    const AutoTexture autoCleanup(texture);

    /*
     * TODO: handle alpha_8 textures correctly by applying paint color, but *not*
     * shader in that case to mimic the behavior in SkiaCanvas::drawBitmapMesh.
     */
    const int textureFillFlags = TextureFillFlags::None;
    Glop glop;
    GlopBuilder(renderer.renderState(), renderer.caches(), &glop)
            .setRoundRectClipState(state.roundRectClipState)
            .setMeshColoredTexturedMesh(mesh.get(), elementCount)
            .setFillTexturePaint(*texture, textureFillFlags, op.paint, state.alpha)
            .setTransform(state.computedState.transform,  TransformFlags::None)
            .setModelViewOffsetRect(0, 0, op.unmappedBounds)
            .build();
    renderer.renderGlop(state, glop);
}

void BakedOpDispatcher::onBitmapRectOp(BakedOpRenderer& renderer, const BitmapRectOp& op, const BakedOpState& state) {
    Texture* texture = renderer.getTexture(op.bitmap);
    if (!texture) return;
    const AutoTexture autoCleanup(texture);

    Rect uv(std::max(0.0f, op.src.left / texture->width()),
            std::max(0.0f, op.src.top / texture->height()),
            std::min(1.0f, op.src.right / texture->width()),
            std::min(1.0f, op.src.bottom / texture->height()));

    const int textureFillFlags = (op.bitmap->colorType() == kAlpha_8_SkColorType)
            ? TextureFillFlags::IsAlphaMaskTexture : TextureFillFlags::None;
    const bool tryToSnap = MathUtils::areEqual(op.src.getWidth(), op.unmappedBounds.getWidth())
            && MathUtils::areEqual(op.src.getHeight(), op.unmappedBounds.getHeight());
    Glop glop;
    GlopBuilder(renderer.renderState(), renderer.caches(), &glop)
            .setRoundRectClipState(state.roundRectClipState)
            .setMeshTexturedUvQuad(texture->uvMapper, uv)
            .setFillTexturePaint(*texture, textureFillFlags, op.paint, state.alpha)
            .setTransform(state.computedState.transform, TransformFlags::None)
            .setModelViewMapUnitToRectOptionalSnap(tryToSnap, op.unmappedBounds)
            .build();
    renderer.renderGlop(state, glop);
}

void BakedOpDispatcher::onColorOp(BakedOpRenderer& renderer, const ColorOp& op, const BakedOpState& state) {
    SkPaint paint;
    paint.setColor(op.color);
    paint.setXfermodeMode(op.mode);

    Glop glop;
    GlopBuilder(renderer.renderState(), renderer.caches(), &glop)
            .setRoundRectClipState(state.roundRectClipState)
            .setMeshUnitQuad()
            .setFillPaint(paint, state.alpha)
            .setTransform(Matrix4::identity(), TransformFlags::None)
            .setModelViewMapUnitToRect(state.computedState.clipState->rect)
            .build();
    renderer.renderGlop(state, glop);
}

void BakedOpDispatcher::onFunctorOp(BakedOpRenderer& renderer, const FunctorOp& op, const BakedOpState& state) {
    renderer.renderFunctor(op, state);
}

void BakedOpDispatcher::onLinesOp(BakedOpRenderer& renderer, const LinesOp& op, const BakedOpState& state) {
    VertexBuffer buffer;
    PathTessellator::tessellateLines(op.points, op.floatCount, op.paint,
            state.computedState.transform, buffer);
    int displayFlags = op.paint->isAntiAlias() ? 0 : VertexBufferRenderFlags::Offset;
    renderVertexBuffer(renderer, state, buffer, 0, 0, *(op.paint), displayFlags);
}

void BakedOpDispatcher::onOvalOp(BakedOpRenderer& renderer, const OvalOp& op, const BakedOpState& state) {
    if (op.paint->getPathEffect() != nullptr) {
        PathTexture* texture = renderer.caches().pathCache.getOval(
                op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight(), op.paint);
        const AutoTexture holder(texture);
        if (CC_LIKELY(holder.texture)) {
            renderPathTexture(renderer, state, op.unmappedBounds.left, op.unmappedBounds.right,
                    *texture, *(op.paint));
        }
    } else {
        SkPath path;
        SkRect rect = getBoundsOfFill(op);
        path.addOval(rect);

        if (state.computedState.localProjectionPathMask != nullptr) {
            // Mask the ripple path by the local space projection mask in local space.
            // Note that this can create CCW paths.
            Op(path, *state.computedState.localProjectionPathMask, kIntersect_SkPathOp, &path);
        }
        renderConvexPath(renderer, state, path, *(op.paint));
    }
}

void BakedOpDispatcher::onPatchOp(BakedOpRenderer& renderer, const PatchOp& op, const BakedOpState& state) {
    // 9 patches are built for stretching - always filter
    int textureFillFlags = TextureFillFlags::ForceFilter;
    if (op.bitmap->colorType() == kAlpha_8_SkColorType) {
        textureFillFlags |= TextureFillFlags::IsAlphaMaskTexture;
    }

    // TODO: avoid redoing the below work each frame:
    AssetAtlas::Entry* entry = renderer.renderState().assetAtlas().getEntry(op.bitmap->pixelRef());
    const Patch* mesh = renderer.caches().patchCache.get(
            entry, op.bitmap->width(), op.bitmap->height(),
            op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight(), op.patch);

    Texture* texture = entry ? entry->texture : renderer.caches().textureCache.get(op.bitmap);
    if (CC_LIKELY(texture)) {
        const AutoTexture autoCleanup(texture);
        Glop glop;
        GlopBuilder(renderer.renderState(), renderer.caches(), &glop)
                .setRoundRectClipState(state.roundRectClipState)
                .setMeshPatchQuads(*mesh)
                .setFillTexturePaint(*texture, textureFillFlags, op.paint, state.alpha)
                .setTransform(state.computedState.transform, TransformFlags::None)
                .setModelViewOffsetRectSnap(op.unmappedBounds.left, op.unmappedBounds.top,
                        Rect(op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight()))
                .build();
        renderer.renderGlop(state, glop);
    }
}

void BakedOpDispatcher::onPathOp(BakedOpRenderer& renderer, const PathOp& op, const BakedOpState& state) {
    PathTexture* texture = renderer.caches().pathCache.get(op.path, op.paint);
    const AutoTexture holder(texture);
    if (CC_LIKELY(holder.texture)) {
        // Unlike other callers to renderPathTexture, no offsets are used because PathOp doesn't
        // have any translate built in, other than what's in the SkPath itself
        renderPathTexture(renderer, state, 0, 0, *texture, *(op.paint));
    }
}

void BakedOpDispatcher::onPointsOp(BakedOpRenderer& renderer, const PointsOp& op, const BakedOpState& state) {
    VertexBuffer buffer;
    PathTessellator::tessellatePoints(op.points, op.floatCount, op.paint,
            state.computedState.transform, buffer);
    int displayFlags = op.paint->isAntiAlias() ? 0 : VertexBufferRenderFlags::Offset;
    renderVertexBuffer(renderer, state, buffer, 0, 0, *(op.paint), displayFlags);
}

// See SkPaintDefaults.h
#define SkPaintDefaults_MiterLimit SkIntToScalar(4)

void BakedOpDispatcher::onRectOp(BakedOpRenderer& renderer, const RectOp& op, const BakedOpState& state) {
    if (op.paint->getStyle() != SkPaint::kFill_Style) {
        // only fill + default miter is supported by drawConvexPath, since others must handle joins
        static_assert(SkPaintDefaults_MiterLimit == 4.0f, "Miter limit has changed");
        if (CC_UNLIKELY(op.paint->getPathEffect() != nullptr
                || op.paint->getStrokeJoin() != SkPaint::kMiter_Join
                || op.paint->getStrokeMiter() != SkPaintDefaults_MiterLimit)) {
             PathTexture* texture = renderer.caches().pathCache.getRect(
                     op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight(), op.paint);
             const AutoTexture holder(texture);
             if (CC_LIKELY(holder.texture)) {
                 renderPathTexture(renderer, state, op.unmappedBounds.left, op.unmappedBounds.top,
                         *texture, *(op.paint));
             }
        } else {
            SkPath path;
            path.addRect(getBoundsOfFill(op));
            renderConvexPath(renderer, state, path, *(op.paint));
        }
    } else {
        if (op.paint->isAntiAlias() && !state.computedState.transform.isSimple()) {
            SkPath path;
            path.addRect(op.unmappedBounds.toSkRect());
            renderConvexPath(renderer, state, path, *(op.paint));
        } else {
            // render simple unit quad, no tessellation required
            Glop glop;
            GlopBuilder(renderer.renderState(), renderer.caches(), &glop)
                    .setRoundRectClipState(state.roundRectClipState)
                    .setMeshUnitQuad()
                    .setFillPaint(*op.paint, state.alpha)
                    .setTransform(state.computedState.transform, TransformFlags::None)
                    .setModelViewMapUnitToRect(op.unmappedBounds)
                    .build();
            renderer.renderGlop(state, glop);
        }
    }
}

void BakedOpDispatcher::onRoundRectOp(BakedOpRenderer& renderer, const RoundRectOp& op, const BakedOpState& state) {
    if (op.paint->getPathEffect() != nullptr) {
        PathTexture* texture = renderer.caches().pathCache.getRoundRect(
                op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight(),
                op.rx, op.ry, op.paint);
        const AutoTexture holder(texture);
        if (CC_LIKELY(holder.texture)) {
            renderPathTexture(renderer, state, op.unmappedBounds.left, op.unmappedBounds.top,
                    *texture, *(op.paint));
        }
    } else {
        const VertexBuffer* buffer = renderer.caches().tessellationCache.getRoundRect(
                state.computedState.transform, *(op.paint),
                op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight(), op.rx, op.ry);
        renderVertexBuffer(renderer, state, *buffer,
                op.unmappedBounds.left, op.unmappedBounds.top, *(op.paint), 0);
    }
}

static void renderShadow(BakedOpRenderer& renderer, const BakedOpState& state, float casterAlpha,
        const VertexBuffer* ambientShadowVertexBuffer, const VertexBuffer* spotShadowVertexBuffer) {
    SkPaint paint;
    paint.setAntiAlias(true); // want to use AlphaVertex

    // The caller has made sure casterAlpha > 0.
    uint8_t ambientShadowAlpha = renderer.getLightInfo().ambientShadowAlpha;
    if (CC_UNLIKELY(Properties::overrideAmbientShadowStrength >= 0)) {
        ambientShadowAlpha = Properties::overrideAmbientShadowStrength;
    }
    if (ambientShadowVertexBuffer && ambientShadowAlpha > 0) {
        paint.setAlpha((uint8_t)(casterAlpha * ambientShadowAlpha));
        renderVertexBuffer(renderer, state, *ambientShadowVertexBuffer, 0, 0,
                paint, VertexBufferRenderFlags::ShadowInterp);
    }

    uint8_t spotShadowAlpha = renderer.getLightInfo().spotShadowAlpha;
    if (CC_UNLIKELY(Properties::overrideSpotShadowStrength >= 0)) {
        spotShadowAlpha = Properties::overrideSpotShadowStrength;
    }
    if (spotShadowVertexBuffer && spotShadowAlpha > 0) {
        paint.setAlpha((uint8_t)(casterAlpha * spotShadowAlpha));
        renderVertexBuffer(renderer, state, *spotShadowVertexBuffer, 0, 0,
                paint, VertexBufferRenderFlags::ShadowInterp);
    }
}

void BakedOpDispatcher::onShadowOp(BakedOpRenderer& renderer, const ShadowOp& op, const BakedOpState& state) {
    TessellationCache::vertexBuffer_pair_t buffers = op.shadowTask->getResult();
    renderShadow(renderer, state, op.casterAlpha, buffers.first, buffers.second);
}

void BakedOpDispatcher::onSimpleRectsOp(BakedOpRenderer& renderer, const SimpleRectsOp& op, const BakedOpState& state) {
    Glop glop;
    GlopBuilder(renderer.renderState(), renderer.caches(), &glop)
            .setRoundRectClipState(state.roundRectClipState)
            .setMeshIndexedQuads(&op.vertices[0], op.vertexCount / 4)
            .setFillPaint(*op.paint, state.alpha)
            .setTransform(state.computedState.transform, TransformFlags::None)
            .setModelViewOffsetRect(0, 0, op.unmappedBounds)
            .build();
    renderer.renderGlop(state, glop);
}

void BakedOpDispatcher::onTextOp(BakedOpRenderer& renderer, const TextOp& op, const BakedOpState& state) {
    renderTextOp(renderer, op, state, state.computedState.getClipIfNeeded(), TextRenderType::Flush);
}

void BakedOpDispatcher::onTextOnPathOp(BakedOpRenderer& renderer, const TextOnPathOp& op, const BakedOpState& state) {
    // Note: can't trust clipSideFlags since we record with unmappedBounds == clip.
    // TODO: respect clipSideFlags, once we record with bounds
    auto renderTargetClip = state.computedState.clipState;

    FontRenderer& fontRenderer = renderer.caches().fontRenderer.getFontRenderer();
    fontRenderer.setFont(op.paint, SkMatrix::I());
    fontRenderer.setTextureFiltering(true);

    Rect layerBounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f);

    int alpha = PaintUtils::getAlphaDirect(op.paint) * state.alpha;
    SkXfermode::Mode mode = PaintUtils::getXfermodeDirect(op.paint);
    TextDrawFunctor functor(&renderer, &state, renderTargetClip,
            0.0f, 0.0f, false, alpha, mode, op.paint);

    bool mustDirtyRenderTarget = renderer.offscreenRenderTarget();
    const Rect localSpaceClip = state.computedState.computeLocalSpaceClip();
    if (fontRenderer.renderTextOnPath(op.paint, &localSpaceClip, op.glyphs, op.glyphCount,
            op.path, op.hOffset, op.vOffset,
            mustDirtyRenderTarget ? &layerBounds : nullptr, &functor)) {
        if (mustDirtyRenderTarget) {
            // manually dirty render target, since TextDrawFunctor won't
            state.computedState.transform.mapRect(layerBounds);
            renderer.dirtyRenderTarget(layerBounds);
        }
    }
}

void BakedOpDispatcher::onTextureLayerOp(BakedOpRenderer& renderer, const TextureLayerOp& op, const BakedOpState& state) {
    const bool tryToSnap = !op.layer->getForceFilter();
    float alpha = (op.layer->getAlpha() / 255.0f) * state.alpha;
    Glop glop;
    GlopBuilder(renderer.renderState(), renderer.caches(), &glop)
            .setRoundRectClipState(state.roundRectClipState)
            .setMeshTexturedUvQuad(nullptr, Rect(0, 1, 1, 0)) // TODO: simplify with VBO
            .setFillTextureLayer(*(op.layer), alpha)
            .setTransform(state.computedState.transform, TransformFlags::None)
            .setModelViewMapUnitToRectOptionalSnap(tryToSnap, Rect(op.layer->getWidth(), op.layer->getHeight()))
            .build();
    renderer.renderGlop(state, glop);
}

void BakedOpDispatcher::onLayerOp(BakedOpRenderer& renderer, const LayerOp& op, const BakedOpState& state) {
    // Note that we don't use op->paint in this function - it's never set on a LayerOp
    OffscreenBuffer* buffer = *op.layerHandle;

    if (CC_UNLIKELY(!buffer)) {
        // Layer was not allocated, which can occur if there were no draw ops inside. We draw the
        // equivalent by drawing a rect with the same layer properties (alpha/xfer/filter).
        SkPaint paint;
        paint.setAlpha(op.alpha * 255);
        paint.setXfermodeMode(op.mode);
        paint.setColorFilter(op.colorFilter);
        RectOp rectOp(op.unmappedBounds, op.localMatrix, op.localClip, &paint);
        BakedOpDispatcher::onRectOp(renderer, rectOp, state);
    } else {
        float layerAlpha = op.alpha * state.alpha;
        Glop glop;
        GlopBuilder(renderer.renderState(), renderer.caches(), &glop)
                .setRoundRectClipState(state.roundRectClipState)
                .setMeshTexturedIndexedVbo(buffer->vbo, buffer->elementCount)
                .setFillLayer(buffer->texture, op.colorFilter, layerAlpha, op.mode, Blend::ModeOrderSwap::NoSwap)
                .setTransform(state.computedState.transform, TransformFlags::None)
                .setModelViewOffsetRectSnap(op.unmappedBounds.left, op.unmappedBounds.top,
                        Rect(op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight()))
                .build();
        renderer.renderGlop(state, glop);

        if (op.destroy) {
            renderer.renderState().layerPool().putOrDelete(buffer);
        }
    }
}

void BakedOpDispatcher::onCopyToLayerOp(BakedOpRenderer& renderer, const CopyToLayerOp& op, const BakedOpState& state) {
    LOG_ALWAYS_FATAL_IF(*(op.layerHandle) != nullptr, "layer already exists!");
    *(op.layerHandle) = renderer.copyToLayer(state.computedState.clippedBounds);
    LOG_ALWAYS_FATAL_IF(*op.layerHandle == nullptr, "layer copy failed");
}

void BakedOpDispatcher::onCopyFromLayerOp(BakedOpRenderer& renderer, const CopyFromLayerOp& op, const BakedOpState& state) {
    LOG_ALWAYS_FATAL_IF(*op.layerHandle == nullptr, "no layer to draw underneath!");
    if (!state.computedState.clippedBounds.isEmpty()) {
        if (op.paint && op.paint->getAlpha() < 255) {
            SkPaint layerPaint;
            layerPaint.setAlpha(op.paint->getAlpha());
            layerPaint.setXfermodeMode(SkXfermode::kDstIn_Mode);
            layerPaint.setColorFilter(op.paint->getColorFilter());
            RectOp rectOp(state.computedState.clippedBounds, Matrix4::identity(), nullptr, &layerPaint);
            BakedOpDispatcher::onRectOp(renderer, rectOp, state);
        }

        OffscreenBuffer& layer = **(op.layerHandle);
        auto mode = PaintUtils::getXfermodeDirect(op.paint);
        Glop glop;
        GlopBuilder(renderer.renderState(), renderer.caches(), &glop)
                .setRoundRectClipState(state.roundRectClipState)
                .setMeshTexturedUvQuad(nullptr, layer.getTextureCoordinates())
                .setFillLayer(layer.texture, nullptr, 1.0f, mode, Blend::ModeOrderSwap::Swap)
                .setTransform(state.computedState.transform, TransformFlags::None)
                .setModelViewMapUnitToRect(state.computedState.clippedBounds)
                .build();
        renderer.renderGlop(state, glop);
    }
    renderer.renderState().layerPool().putOrDelete(*op.layerHandle);
}

} // namespace uirenderer
} // namespace android
