blob: d20cc825cd67614e3a724c676642077a322d8876 [file] [log] [blame]
/*
* 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));
}