/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// This is a test program that uses Minikin to layout and draw some text.
// At the moment, it just draws a string into /data/local/tmp/foo.pgm.
#include <stdio.h>
#include <vector>
#include <fstream>
#include <unicode/unistr.h>
#include <unicode/utf16.h>
#include <minikin/MinikinFontFreeType.h>
#include <minikin/Layout.h>
#include <SkCanvas.h>
#include <SkGraphics.h>
#include <SkImageEncoder.h>
#include <SkTypeface.h>
#include <SkPaint.h>
#include "MinikinSkia.h"
using std::vector;
namespace android {
FT_Library library; // TODO: this should not be a global
FontCollection *makeFontCollection() {
vector<FontFamily *>typefaces;
const char *fns[] = {
"/system/fonts/Roboto-Regular.ttf",
"/system/fonts/Roboto-Italic.ttf",
"/system/fonts/Roboto-BoldItalic.ttf",
"/system/fonts/Roboto-Light.ttf",
"/system/fonts/Roboto-Thin.ttf",
"/system/fonts/Roboto-Bold.ttf",
"/system/fonts/Roboto-ThinItalic.ttf",
"/system/fonts/Roboto-LightItalic.ttf"
};
FontFamily *family = new FontFamily();
FT_Face face;
FT_Error error;
for (size_t i = 0; i < sizeof(fns)/sizeof(fns[0]); i++) {
const char *fn = fns[i];
SkTypeface *skFace = SkTypeface::CreateFromFile(fn);
MinikinFont *font = new MinikinFontSkia(skFace);
family->addFont(font);
}
typefaces.push_back(family);
#if 1
family = new FontFamily();
const char *fn = "/system/fonts/DroidSansDevanagari-Regular.ttf";
SkTypeface *skFace = SkTypeface::CreateFromFile(fn);
MinikinFont *font = new MinikinFontSkia(skFace);
family->addFont(font);
typefaces.push_back(family);
#endif
return new FontCollection(typefaces);
}
// Maybe move to MinikinSkia (esp. instead of opening GetSkTypeface publicly)?
void drawToSkia(SkCanvas *canvas, SkPaint *paint, Layout *layout, float x, float y) {
size_t nGlyphs = layout->nGlyphs();
uint16_t *glyphs = new uint16_t[nGlyphs];
SkPoint *pos = new SkPoint[nGlyphs];
SkTypeface *lastFace = NULL;
SkTypeface *skFace = NULL;
size_t start = 0;
paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding);
for (size_t i = 0; i < nGlyphs; i++) {
MinikinFontSkia *mfs = static_cast<MinikinFontSkia *>(layout->getFont(i));
skFace = mfs->GetSkTypeface();
glyphs[i] = layout->getGlyphId(i);
pos[i].fX = x + layout->getX(i);
pos[i].fY = y + layout->getY(i);
if (i > 0 && skFace != lastFace) {
paint->setTypeface(lastFace);
canvas->drawPosText(glyphs + start, (i - start) << 1, pos + start, *paint);
start = i;
}
lastFace = skFace;
}
paint->setTypeface(skFace);
canvas->drawPosText(glyphs + start, (nGlyphs - start) << 1, pos + start, *paint);
delete[] glyphs;
delete[] pos;
}
int runMinikinTest() {
FT_Error error = FT_Init_FreeType(&library);
if (error) {
return -1;
}
Layout::init();
FontCollection *collection = makeFontCollection();
Layout layout;
layout.setFontCollection(collection);
const char *text = "fine world \xe0\xa4\xa8\xe0\xa4\xae\xe0\xa4\xb8\xe0\xa5\x8d\xe0\xa4\xa4\xe0\xa5\x87";
const char *style = "font-size: 32; font-weight: 700;";
int bidiFlags = 0;
FontStyle fontStyle(7);
MinikinPaint minikinPaint;
minikinPaint.size = 32;
icu::UnicodeString icuText = icu::UnicodeString::fromUTF8(text);
layout.doLayout(icuText.getBuffer(), 0, icuText.length(), icuText.length(), bidiFlags, fontStyle, minikinPaint);
layout.dump();
SkAutoGraphics ag;
int width = 800;
int height = 600;
SkBitmap bitmap;
bitmap.allocN32Pixels(width, height);
SkCanvas canvas(bitmap);
SkPaint paint;
paint.setARGB(255, 0, 0, 128);
paint.setStyle(SkPaint::kStroke_Style);
paint.setStrokeWidth(2);
paint.setTextSize(100);
paint.setAntiAlias(true);
canvas.drawLine(10, 300, 10 + layout.getAdvance(), 300, paint);
paint.setStyle(SkPaint::kFill_Style);
drawToSkia(&canvas, &paint, &layout, 10, 300);
SkImageEncoder::EncodeFile("/data/local/tmp/foo.png", bitmap, SkImageEncoder::kPNG_Type, 100);
return 0;
}
}
int main(int argc, const char** argv) {
return android::runMinikinTest();
}