mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
This patch improves script run itemization and also exposes metrics and bounds for layouts. In addition, there is a fair amount of internal cleanup, including ref counting, and making the MinikinFont abstraction strong enough to support both FreeType and Skia implementations. There is also a sample implementation using Skia, in the sample directory. As part of its functionality, his patch measures the bounds of the layout and gives access through Layout::GetBounds(). The corresponding method is not implemented in the FreeType-only implementation of MinikinFont, so that will probably have to be fixed. Change-Id: Ib1a3fe9d7c90519ac651fb4aa957848e4bb758ec
153 lines
4.7 KiB
C++
153 lines
4.7 KiB
C++
/*
|
|
* 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 = SkFloatToScalar(x + layout->getX(i));
|
|
pos[i].fY = SkFloatToScalar(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);
|
|
layout.setProperties("font-size: 32; font-weight: 700;");
|
|
const char *text = "fine world \xe0\xa4\xa8\xe0\xa4\xae\xe0\xa4\xb8\xe0\xa5\x8d\xe0\xa4\xa4\xe0\xa5\x87";
|
|
icu::UnicodeString icuText = icu::UnicodeString::fromUTF8(text);
|
|
layout.doLayout(icuText.getBuffer(), icuText.length());
|
|
layout.dump();
|
|
|
|
SkAutoGraphics ag;
|
|
|
|
SkScalar width = 800;
|
|
SkScalar height = 600;
|
|
SkBitmap bitmap;
|
|
bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height);
|
|
bitmap.allocPixels();
|
|
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();
|
|
}
|