
/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "SkGLTextCache.h"
#include "SkScalerContext.h"
#include "SkTSearch.h"

const GLenum gTextTextureFormat = GL_ALPHA;
const GLenum gTextTextureType = GL_UNSIGNED_BYTE;

SkGLTextCache::Strike::Strike(Strike* next, int width, int height) {
    fStrikeWidth = SkNextPow2(SkMax32(kMinStrikeWidth, width));
    fStrikeHeight = SkNextPow2(height);
    fGlyphCount = 0;
    fNextFreeOffsetX = 0;
    fNext = next;

    fStrikeWidthShift = SkNextLog2(fStrikeWidth);
    fStrikeHeightShift = SkNextLog2(fStrikeHeight);
    
    if (next) {
        SkASSERT(next->fStrikeHeight == fStrikeHeight);
    }

    // create an empty texture to receive glyphs
    fTexName = 0;
    glGenTextures(1, &fTexName);
    glBindTexture(GL_TEXTURE_2D, fTexName);
    glTexImage2D(GL_TEXTURE_2D, 0, gTextTextureFormat, 
                 fStrikeWidth, fStrikeHeight, 0,
                 gTextTextureFormat, gTextTextureType, NULL);
    
    SK_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    SK_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    SK_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    SK_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);    
}

SkGLTextCache::Strike::~Strike() {
    if (fTexName != 0) {
        glDeleteTextures(1, &fTexName);
    }
}

SkGLTextCache::Strike*
SkGLTextCache::Strike::findGlyph(const SkGlyph& glyph, int* offset) {
    Strike* strike = this;
    SkDEBUGCODE(const int height = SkNextPow2(glyph.fHeight);)
    
    do {
        SkASSERT(height == strike->fStrikeHeight);
        
        int index = SkTSearch(strike->fGlyphIDArray, strike->fGlyphCount,
                              glyph.fID, sizeof(strike->fGlyphIDArray[0]));
        if (index >= 0) {
            if (offset) {
                *offset = strike->fGlyphOffsetX[index];
            }
            return strike;
        }
        strike = strike->fNext;
    } while (NULL != strike);
    return NULL;
}

static void make_a_whole(void* buffer, int index, int count, size_t elemSize) {
    SkASSERT(index >= 0 && index <= count);
    size_t offset = index * elemSize;
    memmove((char*)buffer + offset + elemSize,
            (const char*)buffer + offset,
            (count - index) * elemSize);
}

SkGLTextCache::Strike*
SkGLTextCache::Strike::addGlyphAndBind(const SkGlyph& glyph,
                                       const uint8_t image[], int* offset) {
#ifdef SK_DEBUG
    SkASSERT(this->findGlyph(glyph, NULL) == NULL);
    const int height = SkNextPow2(glyph.fHeight);
    SkASSERT(height <= fStrikeHeight && height > (fStrikeHeight >> 1));
#endif

    int rowBytes = glyph.rowBytes();
    SkASSERT(rowBytes >= glyph.fWidth);

    Strike* strike;
    if (fGlyphCount == kMaxGlyphCount ||
            fNextFreeOffsetX + rowBytes >= fStrikeWidth) {
        // this will bind the next texture for us
//        SkDebugf("--- extend strike %p\n", this);
        strike = SkNEW_ARGS(Strike, (this, rowBytes, glyph.fHeight));
    } else {
        glBindTexture(GL_TEXTURE_2D, fTexName);
        strike = this;
    }
    
    uint32_t* idArray = strike->fGlyphIDArray;
    uint16_t* offsetArray = strike->fGlyphOffsetX;
    const int glyphCount = strike->fGlyphCount;

    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glTexSubImage2D(GL_TEXTURE_2D, 0, strike->fNextFreeOffsetX, 0, rowBytes,
                    glyph.fHeight, gTextTextureFormat, gTextTextureType,
                    image);

    // need to insert the offset
    int index = SkTSearch(idArray, glyphCount, glyph.fID, sizeof(idArray[0]));
    SkASSERT(index < 0);
    index = ~index; // this is where we should insert it
    make_a_whole(idArray, index, glyphCount, sizeof(idArray));
    make_a_whole(offsetArray, index, glyphCount, sizeof(offsetArray[0]));
    idArray[index] = glyph.fID;
    offsetArray[index] = strike->fNextFreeOffsetX;
    if (offset) {
        *offset = strike->fNextFreeOffsetX;
    }

#if 0
    SkDebugf("--- strike %p glyph %x [%d %d] offset %d count %d\n",
             strike, glyph.fID, glyph.fWidth, glyph.fHeight,
             strike->fNextFreeOffsetX, glyphCount + 1);
#endif

    // now update our header
    strike->fGlyphCount = glyphCount + 1;
    strike->fNextFreeOffsetX += glyph.fWidth;
    return strike;
}

///////////////////////////////////////////////////////////////////////////////

SkGLTextCache::SkGLTextCache() {
    sk_bzero(fStrikeList, sizeof(fStrikeList));
}

SkGLTextCache::~SkGLTextCache() {
    this->deleteAllStrikes(true);
}

void SkGLTextCache::deleteAllStrikes(bool texturesAreValid) {
    for (size_t i = 0; i < SK_ARRAY_COUNT(fStrikeList); i++) {
        Strike* strike = fStrikeList[i];
        while (strike != NULL) {
            Strike* next = strike->fNext;
            if (!texturesAreValid) {
                strike->abandonTexture();
            }
            SkDELETE(strike);
            strike = next;
        }
    }
    sk_bzero(fStrikeList, sizeof(fStrikeList));
}

SkGLTextCache::Strike* SkGLTextCache::findGlyph(const SkGlyph& glyph,
                                                int* offset) {
    SkASSERT(glyph.fWidth != 0);
    SkASSERT(glyph.fHeight != 0);

    size_t index = SkNextLog2(glyph.fHeight);
    if (index >= SK_ARRAY_COUNT(fStrikeList)) {
        // too big for us to cache;
        return NULL;
    }

    Strike* strike = fStrikeList[index];
    if (strike) {
        strike = strike->findGlyph(glyph, offset);
    }
    return strike;
}

SkGLTextCache::Strike* SkGLTextCache::addGlyphAndBind(const SkGlyph& glyph,
                                        const uint8_t image[], int* offset) {
    SkASSERT(image != NULL);
    SkASSERT(glyph.fWidth != 0);
    SkASSERT(glyph.fHeight != 0);
    
    size_t index = SkNextLog2(glyph.fHeight);
    if (index >= SK_ARRAY_COUNT(fStrikeList)) {
        // too big for us to cache;
        return NULL;
    }
    
    Strike* strike = fStrikeList[index];
    if (NULL == strike) {
        strike = SkNEW_ARGS(Strike, (NULL, glyph.rowBytes(), glyph.fHeight));
//        SkDebugf("--- create strike [%d] %p cache %p\n", index, strike, this);
    }
    strike = strike->addGlyphAndBind(glyph, image, offset);
    fStrikeList[index] = strike;
    return strike;
}

