19cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien/*
29cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * Copyright (C) 2013 The Android Open Source Project
39cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien *
49cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * Licensed under the Apache License, Version 2.0 (the "License");
59cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * you may not use this file except in compliance with the License.
69cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * You may obtain a copy of the License at
79cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien *
89cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien *      http://www.apache.org/licenses/LICENSE-2.0
99cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien *
109cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * Unless required by applicable law or agreed to in writing, software
119cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * distributed under the License is distributed on an "AS IS" BASIS,
129cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * See the License for the specific language governing permissions and
149cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien * limitations under the License.
159cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien */
169cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
179cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien// This is a test program that uses Minikin to layout and draw some text.
189cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien// At the moment, it just draws a string into /data/local/tmp/foo.pgm.
199cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
209cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien#include <stdio.h>
219cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien#include <vector>
229cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien#include <fstream>
239cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
249cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien#include <unicode/unistr.h>
259cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien#include <unicode/utf16.h>
269cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
27bcc3dc5a2591a95a57e379e27cbad69c18e91e67Raph Levien#include <minikin/MinikinFontFreeType.h>
289cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien#include <minikin/Layout.h>
299cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
309cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levienusing std::vector;
319cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
329cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Leviennamespace android {
339cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
349cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph LevienFT_Library library;  // TODO: this should not be a global
359cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
369cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph LevienFontCollection *makeFontCollection() {
379cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    vector<FontFamily *>typefaces;
389cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    const char *fns[] = {
399cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        "/system/fonts/Roboto-Regular.ttf",
409cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        "/system/fonts/Roboto-Italic.ttf",
419cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        "/system/fonts/Roboto-BoldItalic.ttf",
429cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        "/system/fonts/Roboto-Light.ttf",
439cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        "/system/fonts/Roboto-Thin.ttf",
449cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        "/system/fonts/Roboto-Bold.ttf",
459cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        "/system/fonts/Roboto-ThinItalic.ttf",
469cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        "/system/fonts/Roboto-LightItalic.ttf"
479cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    };
489cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
499cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    FontFamily *family = new FontFamily();
509cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    FT_Face face;
519cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    FT_Error error;
529cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    for (size_t i = 0; i < sizeof(fns)/sizeof(fns[0]); i++) {
539cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        const char *fn = fns[i];
549cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        printf("adding %s\n", fn);
559cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        error = FT_New_Face(library, fn, 0, &face);
569cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        if (error != 0) {
579cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien            printf("error loading %s, %d\n", fn, error);
589cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        }
59bcc3dc5a2591a95a57e379e27cbad69c18e91e67Raph Levien        MinikinFont *font = new MinikinFontFreeType(face);
60bcc3dc5a2591a95a57e379e27cbad69c18e91e67Raph Levien        family->addFont(font);
619cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    }
629cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    typefaces.push_back(family);
639cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
64bcc3dc5a2591a95a57e379e27cbad69c18e91e67Raph Levien#if 1
659cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    family = new FontFamily();
669cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    const char *fn = "/system/fonts/DroidSansDevanagari-Regular.ttf";
679cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    error = FT_New_Face(library, fn, 0, &face);
68bcc3dc5a2591a95a57e379e27cbad69c18e91e67Raph Levien    MinikinFont *font = new MinikinFontFreeType(face);
69bcc3dc5a2591a95a57e379e27cbad69c18e91e67Raph Levien    family->addFont(font);
709cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    typefaces.push_back(family);
719cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien#endif
729cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
739cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    return new FontCollection(typefaces);
749cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien}
759cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
769cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levienint runMinikinTest() {
779cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    FT_Error error = FT_Init_FreeType(&library);
789cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    if (error) {
799cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien        return -1;
809cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    }
819cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    Layout::init();
829cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
839cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    FontCollection *collection = makeFontCollection();
849cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    Layout layout;
859cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    layout.setFontCollection(collection);
86bcc3dc5a2591a95a57e379e27cbad69c18e91e67Raph Levien    const char *text = "fine world \xe0\xa4\xa8\xe0\xa4\xae\xe0\xa4\xb8\xe0\xa5\x8d\xe0\xa4\xa4\xe0\xa5\x87";
879802b0dc8e648117ab917e716e81e8a0da909cb3Behdad Esfahbod    int bidiFlags = 0;
889802b0dc8e648117ab917e716e81e8a0da909cb3Behdad Esfahbod    FontStyle fontStyle;
899802b0dc8e648117ab917e716e81e8a0da909cb3Behdad Esfahbod    MinikinPaint paint;
909802b0dc8e648117ab917e716e81e8a0da909cb3Behdad Esfahbod    paint.size = 32;
919cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    icu::UnicodeString icuText = icu::UnicodeString::fromUTF8(text);
929802b0dc8e648117ab917e716e81e8a0da909cb3Behdad Esfahbod    layout.doLayout(icuText.getBuffer(), 0, icuText.length(), icuText.length(), bidiFlags, fontStyle, paint);
939cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    layout.dump();
94bcc3dc5a2591a95a57e379e27cbad69c18e91e67Raph Levien    Bitmap bitmap(250, 50);
954d4e6bc8118d15542f1f2a9218f0f7a91a29474fRaph Levien    layout.draw(&bitmap, 10, 40, 32);
969cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    std::ofstream o;
979cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    o.open("/data/local/tmp/foo.pgm", std::ios::out | std::ios::binary);
989cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    bitmap.writePnm(o);
999cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    return 0;
1009cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien}
1019cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
1029cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien}
1039cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien
1049cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levienint main(int argc, const char** argv) {
1059cc9bbe1461f359f0b27c5e7645c17dda001ab1dRaph Levien    return android::runMinikinTest();
106bcc3dc5a2591a95a57e379e27cbad69c18e91e67Raph Levien}
107