1
2/*
3 * Copyright 2011 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8#include "SkScalerContext.h"
9#include "SkBitmap.h"
10#include "SkCanvas.h"
11#include "SkDescriptor.h"
12#include "SkFDot6.h"
13#include "SkFontHost.h"
14#include "SkMask.h"
15#include "SkStream.h"
16#include "SkString.h"
17#include "SkThread.h"
18#include "SkTemplates.h"
19
20#include <acaapi.h>
21
22//////////////////////////////////////////////////////////////////////////
23
24#include "SkMMapStream.h"
25
26class SkScalerContext_Ascender : public SkScalerContext {
27public:
28    SkScalerContext_Ascender(const SkDescriptor* desc);
29    virtual ~SkScalerContext_Ascender();
30
31protected:
32    virtual unsigned generateGlyphCount();
33    virtual uint16_t generateCharToGlyph(SkUnichar uni);
34    virtual void generateMetrics(SkGlyph* glyph);
35    virtual void generateImage(const SkGlyph& glyph);
36    virtual void generatePath(const SkGlyph& glyph, SkPath* path);
37    virtual void generateFontMetrics(SkPaint::FontMetrics* mx, SkPaint::FontMetrics* my);
38
39private:
40    aca_FontHandle  fHandle;
41    void*   fWorkspace;
42    void*   fGlyphWorkspace;
43    SkStream*   fFontStream;
44    SkStream*   fHintStream;
45};
46
47///////////////////////////////////////////////////////////////////////////
48///////////////////////////////////////////////////////////////////////////
49
50SkScalerContext_Ascender::SkScalerContext_Ascender(const SkDescriptor* desc)
51    : SkScalerContext(desc)
52{
53    int size = aca_Get_FontHandleRec_Size();
54    fHandle = (aca_FontHandle)sk_malloc_throw(size);
55
56    // get the pointer to the font
57
58    fFontStream = new SkMMAPStream("/UcsGB2312-Hei-H.FDL");
59    fHintStream = new SkMMAPStream("/genv6-23.bin");
60
61    void* hints = sk_malloc_throw(fHintStream->getLength());
62    memcpy(hints, fHintStream->getMemoryBase(), fHintStream->getLength());
63
64    aca_Create_Font_Handle(fHandle,
65                           (void*)fFontStream->getMemoryBase(), fFontStream->getLength(),
66                           "fred",
67                           hints, fHintStream->getLength());
68
69    // compute our factors from the record
70
71    SkMatrix    m;
72
73    fRec.getSingleMatrix(&m);
74
75    //  now compute our scale factors
76    SkScalar    sx = m.getScaleX();
77    SkScalar    sy = m.getScaleY();
78
79    int ppemX = SkScalarRound(sx);
80    int ppemY = SkScalarRound(sy);
81
82    size = aca_Find_Font_Memory_Required(fHandle, ppemX, ppemY);
83    size *= 8;  // Jeff suggests this :)
84    fWorkspace = sk_malloc_throw(size);
85    aca_Set_Font_Memory(fHandle, (uint8_t*)fWorkspace, size);
86
87    aca_GlyphAttribsRec rec;
88
89    memset(&rec, 0, sizeof(rec));
90    rec.xSize = ppemX;
91    rec.ySize = ppemY;
92    rec.doAdjust = true;
93    rec.doExceptions = true;
94    rec.doGlyphHints = true;
95    rec.doInterpolate = true;
96    rec.grayMode = 2;
97    aca_Set_Font_Attributes(fHandle, &rec, &size);
98
99    fGlyphWorkspace = sk_malloc_throw(size);
100    aca_Set_Glyph_Memory(fHandle, fGlyphWorkspace);
101}
102
103SkScalerContext_Ascender::~SkScalerContext_Ascender()
104{
105    delete fHintStream;
106    delete fFontStream;
107    sk_free(fGlyphWorkspace);
108    sk_free(fWorkspace);
109    sk_free(fHandle);
110}
111
112unsigned SkScalerContext_Ascender::generateGlyphCount()
113{
114    return 1000;
115}
116
117uint16_t SkScalerContext_Ascender::generateCharToGlyph(SkUnichar uni)
118{
119    return (uint16_t)(uni & 0xFFFF);
120}
121
122void SkScalerContext_Ascender::generateMetrics(SkGlyph* glyph)
123{
124    glyph->fRsbDelta = 0;
125    glyph->fLsbDelta = 0;
126
127    aca_GlyphImageRec   rec;
128    aca_Vector          topLeft;
129
130    int adv = aca_Get_Adv_Width(fHandle, glyph->getGlyphID());
131    if (aca_GLYPH_NOT_PRESENT == adv)
132        goto ERROR;
133
134    aca_Rasterize(glyph->getGlyphID(), fHandle, &rec, &topLeft);
135
136    if (false)  // error
137    {
138ERROR:
139        glyph->fWidth   = 0;
140        glyph->fHeight  = 0;
141        glyph->fTop     = 0;
142        glyph->fLeft    = 0;
143        glyph->fAdvanceX = 0;
144        glyph->fAdvanceY = 0;
145        return;
146    }
147
148    glyph->fWidth = rec.width;
149    glyph->fHeight = rec.rows;
150    glyph->fRowBytes = rec.width;
151    glyph->fTop = -topLeft.y;
152    glyph->fLeft = topLeft.x;
153    glyph->fAdvanceX = SkIntToFixed(adv);
154    glyph->fAdvanceY = SkIntToFixed(0);
155}
156
157void SkScalerContext_Ascender::generateImage(const SkGlyph& glyph)
158{
159    aca_GlyphImageRec   rec;
160    aca_Vector          topLeft;
161
162    aca_Rasterize(glyph.getGlyphID(), fHandle, &rec, &topLeft);
163
164    const uint8_t* src = (const uint8_t*)rec.buffer;
165    uint8_t* dst = (uint8_t*)glyph.fImage;
166    int height = glyph.fHeight;
167
168    src += rec.y0 * rec.pitch + rec.x0;
169    while (--height >= 0)
170    {
171        memcpy(dst, src, glyph.fWidth);
172        src += rec.pitch;
173        dst += glyph.fRowBytes;
174    }
175}
176
177///////////////////////////////////////////////////////////////////////////////////////////
178
179void SkScalerContext_Ascender::generatePath(const SkGlyph& glyph, SkPath* path)
180{
181    SkRect r;
182
183    r.set(0, 0, SkIntToScalar(4), SkIntToScalar(4));
184    path->reset();
185    path->addRect(r);
186}
187
188void SkScalerContext_Ascender::generateFontMetrics(SkPaint::FontMetrics* mx, SkPaint::FontMetrics* my)
189{
190    if (NULL == mx && NULL == my)
191        return;
192
193    if (mx)
194    {
195        mx->fTop = SkIntToScalar(-16);
196        mx->fAscent = SkIntToScalar(-16);
197        mx->fDescent = SkIntToScalar(4);
198        mx->fBottom = SkIntToScalar(4);
199        mx->fLeading = 0;
200
201        // FIXME:
202        mx->fAvgCharWidth = 0;
203        mx->fXMin = 0;
204        mx->fXMax = 0;
205        mx->fXHeight = 0;
206    }
207    if (my)
208    {
209        my->fTop = SkIntToScalar(-16);
210        my->fAscent = SkIntToScalar(-16);
211        my->fDescent = SkIntToScalar(4);
212        my->fBottom = SkIntToScalar(4);
213        my->fLeading = 0;
214
215        // FIXME:
216        my->fAvgCharWidth = 0;
217        my->fXMin = 0;
218        my->fXMax = 0;
219        my->fXHeight = 0;
220    }
221}
222
223////////////////////////////////////////////////////////////////////////
224////////////////////////////////////////////////////////////////////////
225
226SkScalerContext* SkFontHost::CreateScalerContext(const SkDescriptor* desc)
227{
228    return SkNEW_ARGS(SkScalerContext_Ascender, (desc));
229}
230
231