Home | History | Annotate | Download | only in sample
      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