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 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 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 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 153 int main(int argc, const char** argv) { 154 return android::runMinikinTest(); 155 } 156