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 
38 using std::vector;
39 
40 namespace android {
41 
42 FT_Library library;  // TODO: this should not be a global
43 
makeFontCollection()44 FontCollection *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 
drawToSkia(SkCanvas * canvas,SkPaint * paint,Layout * layout,float x,float y)80 void 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 
runMinikinTest()108 int 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 
main(int argc,const char ** argv)150 int main(int argc, const char** argv) {
151     return android::runMinikinTest();
152 }
153