/*
 * Copyright (C) 2010 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 "FontRenderer.h"

#include "BakedOpDispatcher.h"
#include "BakedOpRenderer.h"
#include "BakedOpState.h"
#include "Caches.h"
#include "Debug.h"
#include "Extensions.h"
#include "font/Font.h"
#include "Glop.h"
#include "GlopBuilder.h"
#include "PixelBuffer.h"
#include "Rect.h"
#include "renderstate/RenderState.h"
#include "utils/Blur.h"
#include "utils/Timing.h"

#include <algorithm>
#include <RenderScript.h>
#include <SkGlyph.h>
#include <SkUtils.h>
#include <utils/Log.h>

namespace android {
namespace uirenderer {

// blur inputs smaller than this constant will bypass renderscript
#define RS_MIN_INPUT_CUTOFF 10000

///////////////////////////////////////////////////////////////////////////////
// TextSetupFunctor
///////////////////////////////////////////////////////////////////////////////

void TextDrawFunctor::draw(CacheTexture& texture, bool linearFiltering) {
    int textureFillFlags = TextureFillFlags::None;
    if (texture.getFormat() == GL_ALPHA) {
        textureFillFlags |= TextureFillFlags::IsAlphaMaskTexture;
    }
    if (linearFiltering) {
        textureFillFlags |= TextureFillFlags::ForceFilter;
    }
    int transformFlags = pureTranslate
            ? TransformFlags::MeshIgnoresCanvasTransform : TransformFlags::None;
#ifdef ANDROID_ENABLE_LINEAR_BLENDING
    bool gammaCorrection = true;
#else
    bool gammaCorrection = false;
#endif
    Glop glop;
    GlopBuilder(renderer->renderState(), renderer->caches(), &glop)
            .setRoundRectClipState(bakedState->roundRectClipState)
            .setMeshTexturedIndexedQuads(texture.mesh(), texture.meshElementCount())
            .setFillTexturePaint(texture.getTexture(), textureFillFlags, paint, bakedState->alpha)
            .setGammaCorrection(gammaCorrection)
            .setTransform(bakedState->computedState.transform, transformFlags)
            .setModelViewIdentityEmptyBounds()
            .build();
    // Note: don't pass dirty bounds here, so user must manage passing dirty bounds to renderer
    renderer->renderGlop(nullptr, clip, glop);
}

///////////////////////////////////////////////////////////////////////////////
// FontRenderer
///////////////////////////////////////////////////////////////////////////////

static bool sLogFontRendererCreate = true;

FontRenderer::FontRenderer(const uint8_t* gammaTable)
        : mGammaTable(gammaTable)
        , mCurrentFont(nullptr)
        , mActiveFonts(LruCache<Font::FontDescription, Font*>::kUnlimitedCapacity)
        , mCurrentCacheTexture(nullptr)
        , mUploadTexture(false)
        , mFunctor(nullptr)
        , mClip(nullptr)
        , mBounds(nullptr)
        , mDrawn(false)
        , mInitialized(false)
        , mLinearFiltering(false) {

    if (sLogFontRendererCreate) {
        INIT_LOGD("Creating FontRenderer");
    }

    auto deviceInfo = DeviceInfo::get();
    auto displayInfo = deviceInfo->displayInfo();
    int maxTextureSize = deviceInfo->maxTextureSize();

    // Adjust cache size based on Pixel's desnsity.
    constexpr float PIXEL_DENSITY = 2.6;
    const float densityRatio = displayInfo.density / PIXEL_DENSITY;

    // TODO: Most devices are hardcoded with this configuration, does it need to be dynamic?
    mSmallCacheWidth =
            OffscreenBuffer::computeIdealDimension(std::min(1024, maxTextureSize) * densityRatio);
    mSmallCacheHeight =
            OffscreenBuffer::computeIdealDimension(std::min(1024, maxTextureSize) * densityRatio);
    mLargeCacheWidth =
            OffscreenBuffer::computeIdealDimension(std::min(2048, maxTextureSize) * densityRatio);
    mLargeCacheHeight =
            OffscreenBuffer::computeIdealDimension(std::min(1024, maxTextureSize) * densityRatio);

    if (sLogFontRendererCreate) {
        INIT_LOGD("  Text cache sizes, in pixels: %i x %i, %i x %i, %i x %i, %i x %i",
                mSmallCacheWidth, mSmallCacheHeight,
                mLargeCacheWidth, mLargeCacheHeight >> 1,
                mLargeCacheWidth, mLargeCacheHeight >> 1,
                mLargeCacheWidth, mLargeCacheHeight);
    }

    sLogFontRendererCreate = false;
}

void clearCacheTextures(std::vector<CacheTexture*>& cacheTextures) {
    for (uint32_t i = 0; i < cacheTextures.size(); i++) {
        delete cacheTextures[i];
    }
    cacheTextures.clear();
}

FontRenderer::~FontRenderer() {
    clearCacheTextures(mACacheTextures);
    clearCacheTextures(mRGBACacheTextures);

    LruCache<Font::FontDescription, Font*>::Iterator it(mActiveFonts);
    while (it.next()) {
        delete it.value();
    }
    mActiveFonts.clear();
}

void FontRenderer::flushAllAndInvalidate() {
    issueDrawCommand();

    LruCache<Font::FontDescription, Font*>::Iterator it(mActiveFonts);
    while (it.next()) {
        it.value()->invalidateTextureCache();
    }

    for (uint32_t i = 0; i < mACacheTextures.size(); i++) {
        mACacheTextures[i]->init();

#ifdef BUGREPORT_FONT_CACHE_USAGE
        mHistoryTracker.glyphsCleared(mACacheTextures[i]);
#endif
    }

    for (uint32_t i = 0; i < mRGBACacheTextures.size(); i++) {
        mRGBACacheTextures[i]->init();
#ifdef BUGREPORT_FONT_CACHE_USAGE
        mHistoryTracker.glyphsCleared(mRGBACacheTextures[i]);
#endif
    }

    mDrawn = false;
}

void FontRenderer::flushLargeCaches(std::vector<CacheTexture*>& cacheTextures) {
    // Start from 1; don't deallocate smallest/default texture
    for (uint32_t i = 1; i < cacheTextures.size(); i++) {
        CacheTexture* cacheTexture = cacheTextures[i];
        if (cacheTexture->getPixelBuffer()) {
            cacheTexture->init();
#ifdef BUGREPORT_FONT_CACHE_USAGE
            mHistoryTracker.glyphsCleared(cacheTexture);
#endif
            LruCache<Font::FontDescription, Font*>::Iterator it(mActiveFonts);
            while (it.next()) {
                it.value()->invalidateTextureCache(cacheTexture);
            }
            cacheTexture->releasePixelBuffer();
        }
    }
}

void FontRenderer::flushLargeCaches() {
    flushLargeCaches(mACacheTextures);
    flushLargeCaches(mRGBACacheTextures);
}

CacheTexture* FontRenderer::cacheBitmapInTexture(std::vector<CacheTexture*>& cacheTextures,
        const SkGlyph& glyph, uint32_t* startX, uint32_t* startY) {
    for (uint32_t i = 0; i < cacheTextures.size(); i++) {
        if (cacheTextures[i]->fitBitmap(glyph, startX, startY)) {
            return cacheTextures[i];
        }
    }
    // Could not fit glyph into current cache textures
    return nullptr;
}

void FontRenderer::cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyph,
        uint32_t* retOriginX, uint32_t* retOriginY, bool precaching) {
    checkInit();

    // If the glyph bitmap is empty let's assum the glyph is valid
    // so we can avoid doing extra work later on
    if (glyph.fWidth == 0 || glyph.fHeight == 0) {
        cachedGlyph->mIsValid = true;
        cachedGlyph->mCacheTexture = nullptr;
        return;
    }

    cachedGlyph->mIsValid = false;

    // choose an appropriate cache texture list for this glyph format
    SkMask::Format format = static_cast<SkMask::Format>(glyph.fMaskFormat);
    std::vector<CacheTexture*>* cacheTextures = nullptr;
    switch (format) {
        case SkMask::kA8_Format:
        case SkMask::kBW_Format:
            cacheTextures = &mACacheTextures;
            break;
        case SkMask::kARGB32_Format:
            cacheTextures = &mRGBACacheTextures;
            break;
        default:
#if DEBUG_FONT_RENDERER
            ALOGD("getCacheTexturesForFormat: unknown SkMask format %x", format);
#endif
        return;
    }

    // If the glyph is too tall, don't cache it
    if (glyph.fHeight + TEXTURE_BORDER_SIZE * 2 >
                (*cacheTextures)[cacheTextures->size() - 1]->getHeight()) {
        ALOGE("Font size too large to fit in cache. width, height = %i, %i",
                (int) glyph.fWidth, (int) glyph.fHeight);
        return;
    }

    // Now copy the bitmap into the cache texture
    uint32_t startX = 0;
    uint32_t startY = 0;

    CacheTexture* cacheTexture = cacheBitmapInTexture(*cacheTextures, glyph, &startX, &startY);

    if (!cacheTexture) {
        if (!precaching) {
            // If the new glyph didn't fit and we are not just trying to precache it,
            // clear out the cache and try again
            flushAllAndInvalidate();
            cacheTexture = cacheBitmapInTexture(*cacheTextures, glyph, &startX, &startY);
        }

        if (!cacheTexture) {
            // either the glyph didn't fit or we're precaching and will cache it when we draw
            return;
        }
    }

    cachedGlyph->mCacheTexture = cacheTexture;

    *retOriginX = startX;
    *retOriginY = startY;

    uint32_t endX = startX + glyph.fWidth;
    uint32_t endY = startY + glyph.fHeight;

    uint32_t cacheWidth = cacheTexture->getWidth();

    if (!cacheTexture->getPixelBuffer()) {
        Caches::getInstance().textureState().activateTexture(0);
        // Large-glyph texture memory is allocated only as needed
        cacheTexture->allocatePixelBuffer();
    }
    if (!cacheTexture->mesh()) {
        cacheTexture->allocateMesh();
    }

    uint8_t* cacheBuffer = cacheTexture->getPixelBuffer()->map();
    uint8_t* bitmapBuffer = (uint8_t*) glyph.fImage;
    int srcStride = glyph.rowBytes();

    // Copy the glyph image, taking the mask format into account
    switch (format) {
        case SkMask::kA8_Format: {
            uint32_t row = (startY - TEXTURE_BORDER_SIZE) * cacheWidth + startX
                    - TEXTURE_BORDER_SIZE;
            // write leading border line
            memset(&cacheBuffer[row], 0, glyph.fWidth + 2 * TEXTURE_BORDER_SIZE);
            // write glyph data
            if (mGammaTable) {
                for (uint32_t cacheY = startY, bY = 0; cacheY < endY; cacheY++, bY += srcStride) {
                    row = cacheY * cacheWidth;
                    cacheBuffer[row + startX - TEXTURE_BORDER_SIZE] = 0;
                    for (uint32_t cacheX = startX, bX = 0; cacheX < endX; cacheX++, bX++) {
                        uint8_t tempCol = bitmapBuffer[bY + bX];
                        cacheBuffer[row + cacheX] = mGammaTable[tempCol];
                    }
                    cacheBuffer[row + endX + TEXTURE_BORDER_SIZE - 1] = 0;
                }
            } else {
                for (uint32_t cacheY = startY, bY = 0; cacheY < endY; cacheY++, bY += srcStride) {
                    row = cacheY * cacheWidth;
                    memcpy(&cacheBuffer[row + startX], &bitmapBuffer[bY], glyph.fWidth);
                    cacheBuffer[row + startX - TEXTURE_BORDER_SIZE] = 0;
                    cacheBuffer[row + endX + TEXTURE_BORDER_SIZE - 1] = 0;
                }
            }
            // write trailing border line
            row = (endY + TEXTURE_BORDER_SIZE - 1) * cacheWidth + startX - TEXTURE_BORDER_SIZE;
            memset(&cacheBuffer[row], 0, glyph.fWidth + 2 * TEXTURE_BORDER_SIZE);
            break;
        }
        case SkMask::kARGB32_Format: {
            // prep data lengths
            const size_t formatSize = PixelBuffer::formatSize(GL_RGBA);
            const size_t borderSize = formatSize * TEXTURE_BORDER_SIZE;
            size_t rowSize = formatSize * glyph.fWidth;
            // prep advances
            size_t dstStride = formatSize * cacheWidth;
            // prep indices
            // - we actually start one row early, and then increment before first copy
            uint8_t* src = &bitmapBuffer[0 - srcStride];
            uint8_t* dst = &cacheBuffer[cacheTexture->getOffset(startX, startY - 1)];
            uint8_t* dstEnd = &cacheBuffer[cacheTexture->getOffset(startX, endY - 1)];
            uint8_t* dstL = dst - borderSize;
            uint8_t* dstR = dst + rowSize;
            // write leading border line
            memset(dstL, 0, rowSize + 2 * borderSize);
            // write glyph data
            while (dst < dstEnd) {
                memset(dstL += dstStride, 0, borderSize); // leading border column
                memcpy(dst += dstStride, src += srcStride, rowSize); // glyph data
                memset(dstR += dstStride, 0, borderSize); // trailing border column
            }
            // write trailing border line
            memset(dstL += dstStride, 0, rowSize + 2 * borderSize);
            break;
        }
        case SkMask::kBW_Format: {
            uint32_t cacheX = 0, cacheY = 0;
            uint32_t row = (startY - TEXTURE_BORDER_SIZE) * cacheWidth + startX
                    - TEXTURE_BORDER_SIZE;
            static const uint8_t COLORS[2] = { 0, 255 };
            // write leading border line
            memset(&cacheBuffer[row], 0, glyph.fWidth + 2 * TEXTURE_BORDER_SIZE);
            // write glyph data
            for (cacheY = startY; cacheY < endY; cacheY++) {
                cacheX = startX;
                int rowBytes = srcStride;
                uint8_t* buffer = bitmapBuffer;

                row = cacheY * cacheWidth;
                cacheBuffer[row + startX - TEXTURE_BORDER_SIZE] = 0;
                while (--rowBytes >= 0) {
                    uint8_t b = *buffer++;
                    for (int8_t mask = 7; mask >= 0 && cacheX < endX; mask--) {
                        cacheBuffer[cacheY * cacheWidth + cacheX++] = COLORS[(b >> mask) & 0x1];
                    }
                }
                cacheBuffer[row + endX + TEXTURE_BORDER_SIZE - 1] = 0;

                bitmapBuffer += srcStride;
            }
            // write trailing border line
            row = (endY + TEXTURE_BORDER_SIZE - 1) * cacheWidth + startX - TEXTURE_BORDER_SIZE;
            memset(&cacheBuffer[row], 0, glyph.fWidth + 2 * TEXTURE_BORDER_SIZE);
            break;
        }
        default:
            ALOGW("Unknown glyph format: 0x%x", format);
            break;
    }

    cachedGlyph->mIsValid = true;

#ifdef BUGREPORT_FONT_CACHE_USAGE
    mHistoryTracker.glyphUploaded(cacheTexture, startX, startY, glyph.fWidth, glyph.fHeight);
#endif
}

CacheTexture* FontRenderer::createCacheTexture(int width, int height, GLenum format,
        bool allocate) {
    CacheTexture* cacheTexture = new CacheTexture(width, height, format, kMaxNumberOfQuads);

    if (allocate) {
        Caches::getInstance().textureState().activateTexture(0);
        cacheTexture->allocatePixelBuffer();
        cacheTexture->allocateMesh();
    }

    return cacheTexture;
}

void FontRenderer::initTextTexture() {
    clearCacheTextures(mACacheTextures);
    clearCacheTextures(mRGBACacheTextures);

    mUploadTexture = false;
    mACacheTextures.push_back(createCacheTexture(mSmallCacheWidth, mSmallCacheHeight,
            GL_ALPHA, true));
    mACacheTextures.push_back(createCacheTexture(mLargeCacheWidth, mLargeCacheHeight >> 1,
            GL_ALPHA, false));
    mACacheTextures.push_back(createCacheTexture(mLargeCacheWidth, mLargeCacheHeight >> 1,
            GL_ALPHA, false));
    mACacheTextures.push_back(createCacheTexture(mLargeCacheWidth, mLargeCacheHeight,
            GL_ALPHA, false));
    mRGBACacheTextures.push_back(createCacheTexture(mSmallCacheWidth, mSmallCacheHeight,
            GL_RGBA, false));
    mRGBACacheTextures.push_back(createCacheTexture(mLargeCacheWidth, mLargeCacheHeight >> 1,
            GL_RGBA, false));
    mCurrentCacheTexture = mACacheTextures[0];
}

// We don't want to allocate anything unless we actually draw text
void FontRenderer::checkInit() {
    if (mInitialized) {
        return;
    }

    initTextTexture();

    mInitialized = true;
}

void checkTextureUpdateForCache(Caches& caches, std::vector<CacheTexture*>& cacheTextures,
        bool& resetPixelStore, GLuint& lastTextureId) {
    for (uint32_t i = 0; i < cacheTextures.size(); i++) {
        CacheTexture* cacheTexture = cacheTextures[i];
        if (cacheTexture->isDirty() && cacheTexture->getPixelBuffer()) {
            if (cacheTexture->getTextureId() != lastTextureId) {
                lastTextureId = cacheTexture->getTextureId();
                caches.textureState().activateTexture(0);
                caches.textureState().bindTexture(lastTextureId);
            }

            if (cacheTexture->upload()) {
                resetPixelStore = true;
            }
        }
    }
}

void FontRenderer::checkTextureUpdate() {
    if (!mUploadTexture) {
        return;
    }

    Caches& caches = Caches::getInstance();
    GLuint lastTextureId = 0;

    bool resetPixelStore = false;

    // Iterate over all the cache textures and see which ones need to be updated
    checkTextureUpdateForCache(caches, mACacheTextures, resetPixelStore, lastTextureId);
    checkTextureUpdateForCache(caches, mRGBACacheTextures, resetPixelStore, lastTextureId);

    // Unbind any PBO we might have used to update textures
    caches.pixelBufferState().unbind();

    // Reset to default unpack row length to avoid affecting texture
    // uploads in other parts of the renderer
    if (resetPixelStore) {
        glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
    }

    mUploadTexture = false;
}

void FontRenderer::issueDrawCommand(std::vector<CacheTexture*>& cacheTextures) {
    if (!mFunctor) return;

    bool first = true;
    for (uint32_t i = 0; i < cacheTextures.size(); i++) {
        CacheTexture* texture = cacheTextures[i];
        if (texture->canDraw()) {
            if (first) {
                checkTextureUpdate();
                first = false;
                mDrawn = true;
            }

            mFunctor->draw(*texture, mLinearFiltering);

            texture->resetMesh();
        }
    }
}

void FontRenderer::issueDrawCommand() {
    issueDrawCommand(mACacheTextures);
    issueDrawCommand(mRGBACacheTextures);
}

void FontRenderer::appendMeshQuadNoClip(float x1, float y1, float u1, float v1,
        float x2, float y2, float u2, float v2, float x3, float y3, float u3, float v3,
        float x4, float y4, float u4, float v4, CacheTexture* texture) {
    if (texture != mCurrentCacheTexture) {
        // Now use the new texture id
        mCurrentCacheTexture = texture;
    }

    mCurrentCacheTexture->addQuad(x1, y1, u1, v1, x2, y2, u2, v2,
            x3, y3, u3, v3, x4, y4, u4, v4);
}

void FontRenderer::appendMeshQuad(float x1, float y1, float u1, float v1,
        float x2, float y2, float u2, float v2, float x3, float y3, float u3, float v3,
        float x4, float y4, float u4, float v4, CacheTexture* texture) {

    if (mClip &&
            (x1 > mClip->right || y1 < mClip->top || x2 < mClip->left || y4 > mClip->bottom)) {
        return;
    }

    appendMeshQuadNoClip(x1, y1, u1, v1, x2, y2, u2, v2, x3, y3, u3, v3, x4, y4, u4, v4, texture);

    if (mBounds) {
        mBounds->left = std::min(mBounds->left, x1);
        mBounds->top = std::min(mBounds->top, y3);
        mBounds->right = std::max(mBounds->right, x3);
        mBounds->bottom = std::max(mBounds->bottom, y1);
    }

    if (mCurrentCacheTexture->endOfMesh()) {
        issueDrawCommand();
    }
}

void FontRenderer::appendRotatedMeshQuad(float x1, float y1, float u1, float v1,
        float x2, float y2, float u2, float v2, float x3, float y3, float u3, float v3,
        float x4, float y4, float u4, float v4, CacheTexture* texture) {

    appendMeshQuadNoClip(x1, y1, u1, v1, x2, y2, u2, v2, x3, y3, u3, v3, x4, y4, u4, v4, texture);

    if (mBounds) {
        mBounds->left = std::min(mBounds->left, std::min(x1, std::min(x2, std::min(x3, x4))));
        mBounds->top = std::min(mBounds->top, std::min(y1, std::min(y2, std::min(y3, y4))));
        mBounds->right = std::max(mBounds->right, std::max(x1, std::max(x2, std::max(x3, x4))));
        mBounds->bottom = std::max(mBounds->bottom, std::max(y1, std::max(y2, std::max(y3, y4))));
    }

    if (mCurrentCacheTexture->endOfMesh()) {
        issueDrawCommand();
    }
}

void FontRenderer::setFont(const SkPaint* paint, const SkMatrix& matrix) {
    mCurrentFont = Font::create(this, paint, matrix);
}

FontRenderer::DropShadow FontRenderer::renderDropShadow(const SkPaint* paint, const glyph_t *glyphs,
        int numGlyphs, float radius, const float* positions) {
    checkInit();

    DropShadow image;
    image.width = 0;
    image.height = 0;
    image.image = nullptr;
    image.penX = 0;
    image.penY = 0;

    if (!mCurrentFont) {
        return image;
    }

    mDrawn = false;
    mClip = nullptr;
    mBounds = nullptr;

    Rect bounds;
    mCurrentFont->measure(paint, glyphs, numGlyphs, &bounds, positions);

    uint32_t intRadius = Blur::convertRadiusToInt(radius);
    uint32_t paddedWidth = (uint32_t) (bounds.right - bounds.left) + 2 * intRadius;
    uint32_t paddedHeight = (uint32_t) (bounds.top - bounds.bottom) + 2 * intRadius;

    uint32_t maxSize = Caches::getInstance().maxTextureSize;
    if (paddedWidth > maxSize || paddedHeight > maxSize) {
        return image;
    }

    // Align buffers for renderscript usage
    if (paddedWidth & (RS_CPU_ALLOCATION_ALIGNMENT - 1)) {
        paddedWidth += RS_CPU_ALLOCATION_ALIGNMENT - paddedWidth % RS_CPU_ALLOCATION_ALIGNMENT;
    }
    int size = paddedWidth * paddedHeight;
    uint8_t* dataBuffer = (uint8_t*) memalign(RS_CPU_ALLOCATION_ALIGNMENT, size);

    memset(dataBuffer, 0, size);

    int penX = intRadius - bounds.left;
    int penY = intRadius - bounds.bottom;

    if ((bounds.right > bounds.left) && (bounds.top > bounds.bottom)) {
        // text has non-whitespace, so draw and blur to create the shadow
        // NOTE: bounds.isEmpty() can't be used here, since vertical coordinates are inverted
        // TODO: don't draw pure whitespace in the first place, and avoid needing this check
        mCurrentFont->render(paint, glyphs, numGlyphs, penX, penY,
                Font::BITMAP, dataBuffer, paddedWidth, paddedHeight, nullptr, positions);

        // Unbind any PBO we might have used
        Caches::getInstance().pixelBufferState().unbind();

        blurImage(&dataBuffer, paddedWidth, paddedHeight, radius);
    }

    image.width = paddedWidth;
    image.height = paddedHeight;
    image.image = dataBuffer;
    image.penX = penX;
    image.penY = penY;

    return image;
}

void FontRenderer::initRender(const Rect* clip, Rect* bounds, TextDrawFunctor* functor) {
    checkInit();

    mDrawn = false;
    mBounds = bounds;
    mFunctor = functor;
    mClip = clip;
}

void FontRenderer::finishRender() {
    mBounds = nullptr;
    mClip = nullptr;

    issueDrawCommand();
}

void FontRenderer::precache(const SkPaint* paint, const glyph_t* glyphs, int numGlyphs,
        const SkMatrix& matrix) {
    Font* font = Font::create(this, paint, matrix);
    font->precache(paint, glyphs, numGlyphs);
}

void FontRenderer::endPrecaching() {
    checkTextureUpdate();
}

bool FontRenderer::renderPosText(const SkPaint* paint, const Rect* clip, const glyph_t* glyphs,
        int numGlyphs, int x, int y, const float* positions,
        Rect* bounds, TextDrawFunctor* functor, bool forceFinish) {
    if (!mCurrentFont) {
        ALOGE("No font set");
        return false;
    }

    initRender(clip, bounds, functor);
    mCurrentFont->render(paint, glyphs, numGlyphs, x, y, positions);

    if (forceFinish) {
        finishRender();
    }

    return mDrawn;
}

bool FontRenderer::renderTextOnPath(const SkPaint* paint, const Rect* clip, const glyph_t* glyphs,
        int numGlyphs, const SkPath* path, float hOffset, float vOffset,
        Rect* bounds, TextDrawFunctor* functor) {
    if (!mCurrentFont) {
        ALOGE("No font set");
        return false;
    }

    initRender(clip, bounds, functor);
    mCurrentFont->render(paint, glyphs, numGlyphs, path, hOffset, vOffset);
    finishRender();

    return mDrawn;
}

void FontRenderer::blurImage(uint8_t** image, int32_t width, int32_t height, float radius) {
    uint32_t intRadius = Blur::convertRadiusToInt(radius);
    if (width * height * intRadius >= RS_MIN_INPUT_CUTOFF && radius <= 25.0f) {
        uint8_t* outImage = (uint8_t*) memalign(RS_CPU_ALLOCATION_ALIGNMENT, width * height);

        if (mRs == nullptr) {
            mRs = new RSC::RS();
            // a null path is OK because there are no custom kernels used
            // hence nothing gets cached by RS
            if (!mRs->init("", RSC::RS_INIT_LOW_LATENCY | RSC::RS_INIT_SYNCHRONOUS)) {
                mRs.clear();
                ALOGE("blur RS failed to init");
            } else {
                mRsElement = RSC::Element::A_8(mRs);
                mRsScript = RSC::ScriptIntrinsicBlur::create(mRs, mRsElement);
            }
        }
        if (mRs != nullptr) {
            RSC::sp<const RSC::Type> t = RSC::Type::create(mRs, mRsElement, width, height, 0);
            RSC::sp<RSC::Allocation> ain = RSC::Allocation::createTyped(mRs, t,
                    RS_ALLOCATION_MIPMAP_NONE,
                    RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_SHARED,
                    *image);
            RSC::sp<RSC::Allocation> aout = RSC::Allocation::createTyped(mRs, t,
                    RS_ALLOCATION_MIPMAP_NONE,
                    RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_SHARED,
                    outImage);

            mRsScript->setRadius(radius);
            mRsScript->setInput(ain);
            mRsScript->forEach(aout);

            // replace the original image's pointer, avoiding a copy back to the original buffer
            free(*image);
            *image = outImage;

            return;
        }
    }

    std::unique_ptr<float[]> gaussian(new float[2 * intRadius + 1]);
    Blur::generateGaussianWeights(gaussian.get(), radius);

    std::unique_ptr<uint8_t[]> scratch(new uint8_t[width * height]);
    Blur::horizontal(gaussian.get(), intRadius, *image, scratch.get(), width, height);
    Blur::vertical(gaussian.get(), intRadius, scratch.get(), *image, width, height);
}

static uint32_t calculateCacheSize(const std::vector<CacheTexture*>& cacheTextures) {
    uint32_t size = 0;
    for (uint32_t i = 0; i < cacheTextures.size(); i++) {
        CacheTexture* cacheTexture = cacheTextures[i];
        if (cacheTexture && cacheTexture->getPixelBuffer()) {
            size += cacheTexture->getPixelBuffer()->getSize();
        }
    }
    return size;
}

static uint32_t calculateFreeCacheSize(const std::vector<CacheTexture*>& cacheTextures) {
    uint32_t size = 0;
    for (uint32_t i = 0; i < cacheTextures.size(); i++) {
        CacheTexture* cacheTexture = cacheTextures[i];
        if (cacheTexture && cacheTexture->getPixelBuffer()) {
            size += cacheTexture->calculateFreeMemory();
        }
    }
    return size;
}

const std::vector<CacheTexture*>& FontRenderer::cacheTexturesForFormat(GLenum format) const {
    switch (format) {
        case GL_ALPHA: {
            return mACacheTextures;
        }
        case GL_RGBA: {
            return mRGBACacheTextures;
        }
        default: {
            LOG_ALWAYS_FATAL("Unsupported format: %d", format);
            // Impossible to hit this, but the compiler doesn't know that
            return *(new std::vector<CacheTexture*>());
        }
    }
}

static void dumpTextures(String8& log, const char* tag,
        const std::vector<CacheTexture*>& cacheTextures) {
    for (uint32_t i = 0; i < cacheTextures.size(); i++) {
        CacheTexture* cacheTexture = cacheTextures[i];
        if (cacheTexture && cacheTexture->getPixelBuffer()) {
            uint32_t free = cacheTexture->calculateFreeMemory();
            uint32_t total = cacheTexture->getPixelBuffer()->getSize();
            log.appendFormat("    %-4s texture %d     %8d / %8d\n", tag, i, total - free, total);
        }
    }
}

void FontRenderer::dumpMemoryUsage(String8& log) const {
    const uint32_t sizeA8 = getCacheSize(GL_ALPHA);
    const uint32_t usedA8 = sizeA8 - getFreeCacheSize(GL_ALPHA);
    const uint32_t sizeRGBA = getCacheSize(GL_RGBA);
    const uint32_t usedRGBA = sizeRGBA - getFreeCacheSize(GL_RGBA);
    log.appendFormat("  FontRenderer A8      %8d / %8d\n", usedA8, sizeA8);
    dumpTextures(log, "A8", cacheTexturesForFormat(GL_ALPHA));
    log.appendFormat("  FontRenderer RGBA    %8d / %8d\n", usedRGBA, sizeRGBA);
    dumpTextures(log, "RGBA", cacheTexturesForFormat(GL_RGBA));
    log.appendFormat("  FontRenderer total   %8d / %8d\n", usedA8 + usedRGBA, sizeA8 + sizeRGBA);
}

uint32_t FontRenderer::getCacheSize(GLenum format) const {
    return calculateCacheSize(cacheTexturesForFormat(format));
}

uint32_t FontRenderer::getFreeCacheSize(GLenum format) const {
    return calculateFreeCacheSize(cacheTexturesForFormat(format));
}

uint32_t FontRenderer::getSize() const {
    return getCacheSize(GL_ALPHA) + getCacheSize(GL_RGBA);
}

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