1/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17// This is a test program that uses Minikin to layout and draw some text.
18// At the moment, it just draws a string into /data/local/tmp/foo.pgm.
19
20#include <stdio.h>
21#include <vector>
22#include <fstream>
23
24#include <unicode/unistr.h>
25#include <unicode/utf16.h>
26
27#include <minikin/MinikinFontFreeType.h>
28#include <minikin/Layout.h>
29
30#include <SkCanvas.h>
31#include <SkGraphics.h>
32#include <SkImageEncoder.h>
33#include <SkTypeface.h>
34#include <SkPaint.h>
35
36#include "MinikinSkia.h"
37
38using std::vector;
39
40namespace android {
41
42FT_Library library;  // TODO: this should not be a global
43
44FontCollection *makeFontCollection() {
45    vector<FontFamily *>typefaces;
46    const char *fns[] = {
47        "/system/fonts/Roboto-Regular.ttf",
48        "/system/fonts/Roboto-Italic.ttf",
49        "/system/fonts/Roboto-BoldItalic.ttf",
50        "/system/fonts/Roboto-Light.ttf",
51        "/system/fonts/Roboto-Thin.ttf",
52        "/system/fonts/Roboto-Bold.ttf",
53        "/system/fonts/Roboto-ThinItalic.ttf",
54        "/system/fonts/Roboto-LightItalic.ttf"
55    };
56
57    FontFamily *family = new FontFamily();
58    for (size_t i = 0; i < sizeof(fns)/sizeof(fns[0]); i++) {
59        const char *fn = fns[i];
60        SkTypeface *skFace = SkTypeface::CreateFromFile(fn);
61        MinikinFont *font = new MinikinFontSkia(skFace);
62        family->addFont(font);
63    }
64    typefaces.push_back(family);
65
66#if 1
67    family = new FontFamily();
68    const char *fn = "/system/fonts/DroidSansDevanagari-Regular.ttf";
69    SkTypeface *skFace = SkTypeface::CreateFromFile(fn);
70    MinikinFont *font = new MinikinFontSkia(skFace);
71    family->addFont(font);
72    typefaces.push_back(family);
73#endif
74
75    return new FontCollection(typefaces);
76}
77
78// Maybe move to MinikinSkia (esp. instead of opening GetSkTypeface publicly)?
79
80void drawToSkia(SkCanvas *canvas, SkPaint *paint, Layout *layout, float x, float y) {
81    size_t nGlyphs = layout->nGlyphs();
82    uint16_t *glyphs = new uint16_t[nGlyphs];
83    SkPoint *pos = new SkPoint[nGlyphs];
84    SkTypeface *lastFace = NULL;
85    SkTypeface *skFace = NULL;
86    size_t start = 0;
87
88    paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding);
89    for (size_t i = 0; i < nGlyphs; i++) {
90        MinikinFontSkia *mfs = static_cast<MinikinFontSkia *>(layout->getFont(i));
91        skFace = mfs->GetSkTypeface();
92        glyphs[i] = layout->getGlyphId(i);
93        pos[i].fX = x + layout->getX(i);
94        pos[i].fY = y + layout->getY(i);
95        if (i > 0 && skFace != lastFace) {
96            paint->setTypeface(lastFace);
97            canvas->drawPosText(glyphs + start, (i - start) << 1, pos + start, *paint);
98            start = i;
99        }
100        lastFace = skFace;
101    }
102    paint->setTypeface(skFace);
103    canvas->drawPosText(glyphs + start, (nGlyphs - start) << 1, pos + start, *paint);
104    delete[] glyphs;
105    delete[] pos;
106}
107
108int runMinikinTest() {
109    FT_Error error = FT_Init_FreeType(&library);
110    if (error) {
111        return -1;
112    }
113    Layout::init();
114
115    FontCollection *collection = makeFontCollection();
116    Layout layout;
117    layout.setFontCollection(collection);
118    const char *text = "fine world \xe0\xa4\xa8\xe0\xa4\xae\xe0\xa4\xb8\xe0\xa5\x8d\xe0\xa4\xa4\xe0\xa5\x87";
119    int bidiFlags = 0;
120    FontStyle fontStyle(7);
121    MinikinPaint minikinPaint;
122    minikinPaint.size = 32;
123    icu::UnicodeString icuText = icu::UnicodeString::fromUTF8(text);
124    layout.doLayout(icuText.getBuffer(), 0, icuText.length(), icuText.length(), bidiFlags, fontStyle, minikinPaint);
125    layout.dump();
126
127    SkAutoGraphics ag;
128
129    int width = 800;
130    int height = 600;
131    SkBitmap bitmap;
132    bitmap.allocN32Pixels(width, height);
133    SkCanvas canvas(bitmap);
134    SkPaint paint;
135    paint.setARGB(255, 0, 0, 128);
136    paint.setStyle(SkPaint::kStroke_Style);
137    paint.setStrokeWidth(2);
138    paint.setTextSize(100);
139    paint.setAntiAlias(true);
140    canvas.drawLine(10, 300, 10 + layout.getAdvance(), 300, paint);
141    paint.setStyle(SkPaint::kFill_Style);
142    drawToSkia(&canvas, &paint, &layout, 10, 300);
143
144    SkImageEncoder::EncodeFile("/data/local/tmp/foo.png", bitmap, SkImageEncoder::kPNG_Type, 100);
145    return 0;
146}
147
148}
149
150int main(int argc, const char** argv) {
151    return android::runMinikinTest();
152}
153