
/*
 * 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 "SkScalerContext.h"
#include "SkBitmap.h"
#include "SkCanvas.h"
#include "SkDescriptor.h"
#include "SkFDot6.h"
#include "SkFontHost.h"
#include "SkMask.h"
#include "SkStream.h"
#include "SkString.h"
#include "SkThread.h"
#include "SkTemplates.h"

#include <acaapi.h>

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

#include "SkMMapStream.h"

class SkScalerContext_Ascender : public SkScalerContext {
public:
    SkScalerContext_Ascender(const SkDescriptor* desc);
    virtual ~SkScalerContext_Ascender();

protected:
    virtual unsigned generateGlyphCount();
    virtual uint16_t generateCharToGlyph(SkUnichar uni);
    virtual void generateMetrics(SkGlyph* glyph);
    virtual void generateImage(const SkGlyph& glyph);
    virtual void generatePath(const SkGlyph& glyph, SkPath* path);
    virtual void generateFontMetrics(SkPaint::FontMetrics* mx, SkPaint::FontMetrics* my);

private:
    aca_FontHandle  fHandle;
    void*   fWorkspace;
    void*   fGlyphWorkspace;
    SkStream*   fFontStream;
    SkStream*   fHintStream;
};

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

SkScalerContext_Ascender::SkScalerContext_Ascender(const SkDescriptor* desc)
    : SkScalerContext(desc)
{
    int size = aca_Get_FontHandleRec_Size();
    fHandle = (aca_FontHandle)sk_malloc_throw(size);
    
    // get the pointer to the font
    
    fFontStream = new SkMMAPStream("/UcsGB2312-Hei-H.FDL");
    fHintStream = new SkMMAPStream("/genv6-23.bin");
    
    void* hints = sk_malloc_throw(fHintStream->getLength());
    memcpy(hints, fHintStream->getMemoryBase(), fHintStream->getLength());
    
    aca_Create_Font_Handle(fHandle,
                           (void*)fFontStream->getMemoryBase(), fFontStream->getLength(),
                           "fred",
                           hints, fHintStream->getLength());
    
    // compute our factors from the record

    SkMatrix    m;

    fRec.getSingleMatrix(&m);

    //  now compute our scale factors
    SkScalar    sx = m.getScaleX();
    SkScalar    sy = m.getScaleY();
    
    int ppemX = SkScalarRound(sx);
    int ppemY = SkScalarRound(sy);
    
    size = aca_Find_Font_Memory_Required(fHandle, ppemX, ppemY);
    size *= 8;  // Jeff suggests this :)
    fWorkspace = sk_malloc_throw(size);
    aca_Set_Font_Memory(fHandle, (uint8_t*)fWorkspace, size);

    aca_GlyphAttribsRec rec;
    
    memset(&rec, 0, sizeof(rec));
    rec.xSize = ppemX;
    rec.ySize = ppemY;
    rec.doAdjust = true;
    rec.doExceptions = true;
    rec.doGlyphHints = true;
    rec.doInterpolate = true;
    rec.grayMode = 2;
    aca_Set_Font_Attributes(fHandle, &rec, &size);
    
    fGlyphWorkspace = sk_malloc_throw(size);
    aca_Set_Glyph_Memory(fHandle, fGlyphWorkspace);
}

SkScalerContext_Ascender::~SkScalerContext_Ascender()
{
    delete fHintStream;
    delete fFontStream;
    sk_free(fGlyphWorkspace);
    sk_free(fWorkspace);
    sk_free(fHandle);
}

unsigned SkScalerContext_Ascender::generateGlyphCount()
{
    return 1000;
}

uint16_t SkScalerContext_Ascender::generateCharToGlyph(SkUnichar uni)
{
    return (uint16_t)(uni & 0xFFFF);
}

void SkScalerContext_Ascender::generateMetrics(SkGlyph* glyph)
{
    glyph->fRsbDelta = 0;
    glyph->fLsbDelta = 0;
    
    aca_GlyphImageRec   rec;
    aca_Vector          topLeft;
    
    int adv = aca_Get_Adv_Width(fHandle, glyph->getGlyphID());
    if (aca_GLYPH_NOT_PRESENT == adv)
        goto ERROR;

    aca_Rasterize(glyph->getGlyphID(), fHandle, &rec, &topLeft);

    if (false)  // error
    {
ERROR:
        glyph->fWidth   = 0;
        glyph->fHeight  = 0;
        glyph->fTop     = 0;
        glyph->fLeft    = 0;
        glyph->fAdvanceX = 0;
        glyph->fAdvanceY = 0;
        return;
    }
    
    glyph->fWidth = rec.width;
    glyph->fHeight = rec.rows;
    glyph->fRowBytes = rec.width;
    glyph->fTop = -topLeft.y;
    glyph->fLeft = topLeft.x;
    glyph->fAdvanceX = SkIntToFixed(adv);
    glyph->fAdvanceY = SkIntToFixed(0);
}

void SkScalerContext_Ascender::generateImage(const SkGlyph& glyph)
{
    aca_GlyphImageRec   rec;
    aca_Vector          topLeft;
    
    aca_Rasterize(glyph.getGlyphID(), fHandle, &rec, &topLeft);
    
    const uint8_t* src = (const uint8_t*)rec.buffer;
    uint8_t* dst = (uint8_t*)glyph.fImage;
    int height = glyph.fHeight;
    
    src += rec.y0 * rec.pitch + rec.x0;
    while (--height >= 0)
    {
        memcpy(dst, src, glyph.fWidth);
        src += rec.pitch;
        dst += glyph.fRowBytes;
    }
}

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

void SkScalerContext_Ascender::generatePath(const SkGlyph& glyph, SkPath* path)
{
    SkRect r;
    
    r.set(0, 0, SkIntToScalar(4), SkIntToScalar(4));
    path->reset();
    path->addRect(r);
}

void SkScalerContext_Ascender::generateFontMetrics(SkPaint::FontMetrics* mx, SkPaint::FontMetrics* my)
{
    if (NULL == mx && NULL == my)
        return;

    if (mx)
    {
        mx->fTop = SkIntToScalar(-16);
        mx->fAscent = SkIntToScalar(-16);
        mx->fDescent = SkIntToScalar(4);
        mx->fBottom = SkIntToScalar(4);
        mx->fLeading = 0;

        // FIXME:
        mx->fAvgCharWidth = 0;
        mx->fXMin = 0;
        mx->fXMax = 0;
        mx->fXHeight = 0;
    }
    if (my)
    {
        my->fTop = SkIntToScalar(-16);
        my->fAscent = SkIntToScalar(-16);
        my->fDescent = SkIntToScalar(4);
        my->fBottom = SkIntToScalar(4);
        my->fLeading = 0;

        // FIXME:
        my->fAvgCharWidth = 0;
        my->fXMin = 0;
        my->fXMax = 0;
        my->fXHeight = 0;
    }
}

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

SkScalerContext* SkFontHost::CreateScalerContext(const SkDescriptor* desc)
{
    return SkNEW_ARGS(SkScalerContext_Ascender, (desc));
}

