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 FT_Face face;
59 FT_Error error;
60 for (size_t i = 0; i < sizeof(fns)/sizeof(fns[0]); i++) {
61 const char *fn = fns[i];
62 SkTypeface *skFace = SkTypeface::CreateFromFile(fn);
63 MinikinFont *font = new MinikinFontSkia(skFace);
64 family->addFont(font);
65 }
66 typefaces.push_back(family);
67
68 #if 1
69 family = new FontFamily();
70 const char *fn = "/system/fonts/DroidSansDevanagari-Regular.ttf";
71 SkTypeface *skFace = SkTypeface::CreateFromFile(fn);
72 MinikinFont *font = new MinikinFontSkia(skFace);
73 family->addFont(font);
74 typefaces.push_back(family);
75 #endif
76
77 return new FontCollection(typefaces);
78 }
79
80 // Maybe move to MinikinSkia (esp. instead of opening GetSkTypeface publicly)?
81
drawToSkia(SkCanvas * canvas,SkPaint * paint,Layout * layout,float x,float y)82 void drawToSkia(SkCanvas *canvas, SkPaint *paint, Layout *layout, float x, float y) {
83 size_t nGlyphs = layout->nGlyphs();
84 uint16_t *glyphs = new uint16_t[nGlyphs];
85 SkPoint *pos = new SkPoint[nGlyphs];
86 SkTypeface *lastFace = NULL;
87 SkTypeface *skFace = NULL;
88 size_t start = 0;
89
90 paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding);
91 for (size_t i = 0; i < nGlyphs; i++) {
92 MinikinFontSkia *mfs = static_cast<MinikinFontSkia *>(layout->getFont(i));
93 skFace = mfs->GetSkTypeface();
94 glyphs[i] = layout->getGlyphId(i);
95 pos[i].fX = x + layout->getX(i);
96 pos[i].fY = y + layout->getY(i);
97 if (i > 0 && skFace != lastFace) {
98 paint->setTypeface(lastFace);
99 canvas->drawPosText(glyphs + start, (i - start) << 1, pos + start, *paint);
100 start = i;
101 }
102 lastFace = skFace;
103 }
104 paint->setTypeface(skFace);
105 canvas->drawPosText(glyphs + start, (nGlyphs - start) << 1, pos + start, *paint);
106 delete[] glyphs;
107 delete[] pos;
108 }
109
runMinikinTest()110 int runMinikinTest() {
111 FT_Error error = FT_Init_FreeType(&library);
112 if (error) {
113 return -1;
114 }
115 Layout::init();
116
117 FontCollection *collection = makeFontCollection();
118 Layout layout;
119 layout.setFontCollection(collection);
120 const char *text = "fine world \xe0\xa4\xa8\xe0\xa4\xae\xe0\xa4\xb8\xe0\xa5\x8d\xe0\xa4\xa4\xe0\xa5\x87";
121 const char *style = "font-size: 32; font-weight: 700;";
122 int bidiFlags = 0;
123 FontStyle fontStyle(7);
124 MinikinPaint minikinPaint;
125 minikinPaint.size = 32;
126 icu::UnicodeString icuText = icu::UnicodeString::fromUTF8(text);
127 layout.doLayout(icuText.getBuffer(), 0, icuText.length(), icuText.length(), bidiFlags, fontStyle, minikinPaint);
128 layout.dump();
129
130 SkAutoGraphics ag;
131
132 int width = 800;
133 int height = 600;
134 SkBitmap bitmap;
135 bitmap.allocN32Pixels(width, height);
136 SkCanvas canvas(bitmap);
137 SkPaint paint;
138 paint.setARGB(255, 0, 0, 128);
139 paint.setStyle(SkPaint::kStroke_Style);
140 paint.setStrokeWidth(2);
141 paint.setTextSize(100);
142 paint.setAntiAlias(true);
143 canvas.drawLine(10, 300, 10 + layout.getAdvance(), 300, paint);
144 paint.setStyle(SkPaint::kFill_Style);
145 drawToSkia(&canvas, &paint, &layout, 10, 300);
146
147 SkImageEncoder::EncodeFile("/data/local/tmp/foo.png", bitmap, SkImageEncoder::kPNG_Type, 100);
148 return 0;
149 }
150
151 }
152
main(int argc,const char ** argv)153 int main(int argc, const char** argv) {
154 return android::runMinikinTest();
155 }
156