summaryrefslogtreecommitdiffstats
path: root/sample
diff options
context:
space:
mode:
authorRaph Levien <raph@google.com>2013-07-15 14:19:59 -0700
committerRaph Levien <raph@google.com>2014-05-12 09:08:15 -0700
commitecc2d34ac23a497988f21e5f415b53c007b9d8c5 (patch)
tree876b3c943b7841c9600db636738cd0e59b5f2a7c /sample
parent5adafc0d84d238948b5d257ec5311030ca04271c (diff)
downloadandroid_frameworks_minikin-ecc2d34ac23a497988f21e5f415b53c007b9d8c5.tar.gz
android_frameworks_minikin-ecc2d34ac23a497988f21e5f415b53c007b9d8c5.tar.bz2
android_frameworks_minikin-ecc2d34ac23a497988f21e5f415b53c007b9d8c5.zip
A basket of features: itemization, bounds, refcount
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
Diffstat (limited to 'sample')
-rw-r--r--sample/Android.mk36
-rw-r--r--sample/MinikinSkia.cpp64
-rw-r--r--sample/MinikinSkia.h26
-rw-r--r--sample/example_skia.cpp152
4 files changed, 275 insertions, 3 deletions
diff --git a/sample/Android.mk b/sample/Android.mk
index 939aca4..a19019a 100644
--- a/sample/Android.mk
+++ b/sample/Android.mk
@@ -36,10 +36,40 @@ LOCAL_SHARED_LIBRARIES += \
libicuuc \
libft2 \
libpng \
- libz
-
-LOCAL_STATIC_LIBRARIES += libminikin
+ libz \
+ libminikin
LOCAL_MODULE:= minikin_example
include $(BUILD_EXECUTABLE)
+
+
+include $(CLEAR_VARS)
+include external/stlport/libstlport.mk
+
+LOCAL_MODULE_TAG := tests
+
+LOCAL_C_INCLUDES += \
+ external/harfbuzz_ng/src \
+ external/freetype/include \
+ external/icu4c/common \
+ frameworks/minikin/include \
+ external/skia/src/core
+
+LOCAL_SRC_FILES:= example_skia.cpp \
+ MinikinSkia.cpp
+
+LOCAL_SHARED_LIBRARIES += \
+ libutils \
+ liblog \
+ libcutils \
+ libstlport \
+ libharfbuzz_ng \
+ libicuuc \
+ libskia \
+ libminikin \
+ libft2
+
+LOCAL_MODULE:= minikin_skia_example
+
+include $(BUILD_EXECUTABLE)
diff --git a/sample/MinikinSkia.cpp b/sample/MinikinSkia.cpp
new file mode 100644
index 0000000..d67e59f
--- /dev/null
+++ b/sample/MinikinSkia.cpp
@@ -0,0 +1,64 @@
+#include <SkTypeface.h>
+#include <SkPaint.h>
+
+#include <minikin/MinikinFont.h>
+#include "MinikinSkia.h"
+
+namespace android {
+
+MinikinFontSkia::MinikinFontSkia(SkTypeface *typeface) :
+ mTypeface(typeface) {
+}
+
+MinikinFontSkia::~MinikinFontSkia() {
+ SkSafeUnref(mTypeface);
+}
+
+bool MinikinFontSkia::GetGlyph(uint32_t codepoint, uint32_t *glyph) const {
+ SkPaint paint;
+ paint.setTypeface(mTypeface);
+ paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
+ uint16_t glyph16;
+ paint.textToGlyphs(&codepoint, sizeof(codepoint), &glyph16);
+ *glyph = glyph16;
+ //printf("glyph for U+%04x = %d\n", codepoint, glyph16);
+ return !!glyph;
+}
+
+float MinikinFontSkia::GetHorizontalAdvance(uint32_t glyph_id,
+ const MinikinPaint &paint) const {
+ SkPaint skpaint;
+ skpaint.setTypeface(mTypeface);
+ skpaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+ // TODO: set paint from Minikin
+ skpaint.setTextSize(100);
+ uint16_t glyph16 = glyph_id;
+ SkScalar skWidth;
+ SkRect skBounds;
+ skpaint.getTextWidths(&glyph16, sizeof(glyph16), &skWidth, &skBounds);
+ // bounds?
+ //printf("advance for glyph %d = %f\n", glyph_id, SkScalarToFP(skWidth));
+ return skWidth;
+}
+
+bool MinikinFontSkia::GetTable(uint32_t tag, uint8_t *buf, size_t *size) {
+ if (buf == NULL) {
+ const size_t tableSize = mTypeface->getTableSize(tag);
+ *size = tableSize;
+ return tableSize != 0;
+ } else {
+ const size_t actualSize = mTypeface->getTableData(tag, 0, *size, buf);
+ *size = actualSize;
+ return actualSize != 0;
+ }
+}
+
+SkTypeface *MinikinFontSkia::GetSkTypeface() {
+ return mTypeface;
+}
+
+int32_t MinikinFontSkia::GetUniqueId() const {
+ return mTypeface->uniqueID();
+}
+
+}
diff --git a/sample/MinikinSkia.h b/sample/MinikinSkia.h
new file mode 100644
index 0000000..8286a4c
--- /dev/null
+++ b/sample/MinikinSkia.h
@@ -0,0 +1,26 @@
+namespace android {
+
+class MinikinFontSkia : public MinikinFont {
+public:
+ explicit MinikinFontSkia(SkTypeface *typeface);
+
+ ~MinikinFontSkia();
+
+ bool GetGlyph(uint32_t codepoint, uint32_t *glyph) const;
+
+ float GetHorizontalAdvance(uint32_t glyph_id,
+ const MinikinPaint &paint) const;
+
+ // If buf is NULL, just update size
+ bool GetTable(uint32_t tag, uint8_t *buf, size_t *size);
+
+ int32_t GetUniqueId() const;
+
+ SkTypeface *GetSkTypeface();
+
+private:
+ SkTypeface *mTypeface;
+
+};
+
+} // namespace android \ No newline at end of file
diff --git a/sample/example_skia.cpp b/sample/example_skia.cpp
new file mode 100644
index 0000000..ff13b5c
--- /dev/null
+++ b/sample/example_skia.cpp
@@ -0,0 +1,152 @@
+/*
+ * 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();
+}