Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit aff6ea95 authored by Raph Levien's avatar Raph Levien Committed by Android (Google) Code Review
Browse files

Merge "Initial integration of Minikin to framework"

parents f60b86ec a033630e
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -115,6 +115,7 @@ LOCAL_SRC_FILES:= \
	android/graphics/TextLayout.cpp \
	android/graphics/TextLayoutCache.cpp \
	android/graphics/Typeface.cpp \
	android/graphics/TypefaceImpl.cpp \
	android/graphics/Utils.cpp \
	android/graphics/Xfermode.cpp \
	android/graphics/YuvToJpegEncoder.cpp \
@@ -217,6 +218,16 @@ ifeq ($(USE_OPENGL_RENDERER),true)
	LOCAL_SHARED_LIBRARIES += libhwui
endif

ifeq ($(USE_MINIKIN), true)
	LOCAL_CFLAGS += -DUSE_MINIKIN
	LOCAL_C_INCLUDES += frameworks/minikin/include \
		external/freetype/include
	LOCAL_SRC_FILES += 	android/graphics/MinikinSkia.cpp
# note: the freetype include is spurious; minikin itself probably
# shouldn't depend on it
	LOCAL_SHARED_LIBRARIES += libminikin libstlport
endif

LOCAL_SHARED_LIBRARIES += \
	libdl
# we need to access the private Bionic header
+81 −24
Original line number Diff line number Diff line
@@ -27,8 +27,14 @@
#include "SkShader.h"
#include "SkTemplates.h"

#ifdef USE_MINIKIN
#include <minikin/Layout.h>
#include "MinikinSkia.h"
#endif

#include "TextLayout.h"
#include "TextLayoutCache.h"
#include "TypefaceImpl.h"

#include "unicode/ubidi.h"
#include "unicode/ushape.h"
@@ -742,35 +748,83 @@ public:
    }


    static void drawText___CIIFFIPaint(JNIEnv* env, jobject, SkCanvas* canvas,
    static void drawText___CIIFFIPaintTypeface(JNIEnv* env, jobject, SkCanvas* canvas,
                                      jcharArray text, int index, int count,
                                      jfloat x, jfloat y, int flags, SkPaint* paint) {
                                      jfloat x, jfloat y, int flags, SkPaint* paint,
                                      TypefaceImpl *typeface) {
        jchar* textArray = env->GetCharArrayElements(text, NULL);
        drawTextWithGlyphs(canvas, textArray + index, 0, count, x, y, flags, paint);
        drawTextWithGlyphs(canvas, textArray + index, 0, count, x, y, flags, paint, typeface);
        env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
    }

    static void drawText__StringIIFFIPaint(JNIEnv* env, jobject,
    static void drawText__StringIIFFIPaintTypeface(JNIEnv* env, jobject,
                                          SkCanvas* canvas, jstring text,
                                          int start, int end,
                                          jfloat x, jfloat y, int flags, SkPaint* paint) {
                                          jfloat x, jfloat y, int flags, SkPaint* paint,
                                          TypefaceImpl *typeface) {
        const jchar* textArray = env->GetStringChars(text, NULL);
        drawTextWithGlyphs(canvas, textArray, start, end, x, y, flags, paint);
        drawTextWithGlyphs(canvas, textArray, start, end, x, y, flags, paint, typeface);
        env->ReleaseStringChars(text, textArray);
    }

#ifdef USE_MINIKIN
    static void drawGlyphsToSkia(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;
        }
        if (skFace != NULL) {
            paint->setTypeface(skFace);
            canvas->drawPosText(glyphs + start, (nGlyphs - start) << 1, pos + start, *paint);
        }
        delete[] glyphs;
        delete[] pos;
    }
#endif

    static void drawTextWithGlyphs(SkCanvas* canvas, const jchar* textArray,
            int start, int end,
            jfloat x, jfloat y, int flags, SkPaint* paint) {
            jfloat x, jfloat y, int flags, SkPaint* paint, TypefaceImpl* typeface) {

        jint count = end - start;
        drawTextWithGlyphs(canvas, textArray + start, 0, count, count, x, y, flags, paint);
        drawTextWithGlyphs(canvas, textArray + start, 0, count, count, x, y, flags, paint, typeface);
    }

    static void drawTextWithGlyphs(SkCanvas* canvas, const jchar* textArray,
            int start, int count, int contextCount,
            jfloat x, jfloat y, int flags, SkPaint* paint) {

            jfloat x, jfloat y, int flags, SkPaint* paint, TypefaceImpl* typeface) {

#ifdef USE_MINIKIN
        Layout layout;
        TypefaceImpl* resolvedFace = TypefaceImpl_resolveDefault(typeface);
        layout.setFontCollection(resolvedFace->fFontCollection);
        FontStyle style = resolvedFace->fStyle;
        char css[256];
        sprintf(css, "font-size: %d; font-weight: %d; font-style: %s",
            (int)paint->getTextSize(),
            style.getWeight() * 100,
            style.getItalic() ? "italic" : "normal");
        layout.setProperties(css);
        layout.doLayout(textArray + start, count);
        drawGlyphsToSkia(canvas, paint, &layout, x, y);
#else
        sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(paint,
                textArray, start, count, contextCount, flags);
        if (value == NULL) {
@@ -786,6 +840,7 @@ public:
        doDrawGlyphsPos(canvas, value->getGlyphs(), value->getPos(), 0, value->getGlyphsCount(), x, y, flags, paint);
        doDrawTextDecorations(canvas, x, y, value->getTotalAdvance(), paint);
        paint->setTextAlign(align);
#endif
    }

// Same values used by Skia
@@ -842,27 +897,29 @@ static void doDrawTextDecorations(SkCanvas* canvas, jfloat x, jfloat y, jfloat l
        delete[] posPtr;
    }

    static void drawTextRun___CIIIIFFIPaint(
    static void drawTextRun___CIIIIFFIPaintTypeface(
        JNIEnv* env, jobject, SkCanvas* canvas, jcharArray text, int index,
        int count, int contextIndex, int contextCount,
        jfloat x, jfloat y, int dirFlags, SkPaint* paint) {
        jfloat x, jfloat y, int dirFlags, SkPaint* paint,
        TypefaceImpl* typeface) {

        jchar* chars = env->GetCharArrayElements(text, NULL);
        drawTextWithGlyphs(canvas, chars + contextIndex, index - contextIndex,
                count, contextCount, x, y, dirFlags, paint);
                count, contextCount, x, y, dirFlags, paint, typeface);
        env->ReleaseCharArrayElements(text, chars, JNI_ABORT);
    }

    static void drawTextRun__StringIIIIFFIPaint(
    static void drawTextRun__StringIIIIFFIPaintTypeface(
        JNIEnv* env, jobject obj, SkCanvas* canvas, jstring text, jint start,
        jint end, jint contextStart, jint contextEnd,
        jfloat x, jfloat y, jint dirFlags, SkPaint* paint) {
        jfloat x, jfloat y, jint dirFlags, SkPaint* paint,
        TypefaceImpl* typeface) {

        jint count = end - start;
        jint contextCount = contextEnd - contextStart;
        const jchar* chars = env->GetStringChars(text, NULL);
        drawTextWithGlyphs(canvas, chars + contextStart, start - contextStart,
                count, contextCount, x, y, dirFlags, paint);
                count, contextCount, x, y, dirFlags, paint, typeface);
        env->ReleaseStringChars(text, chars);
    }

@@ -1070,14 +1127,14 @@ static JNINativeMethod gCanvasMethods[] = {
        (void*)SkCanvasGlue::drawBitmapMesh},
    {"nativeDrawVertices", "(III[FI[FI[II[SIII)V",
        (void*)SkCanvasGlue::drawVertices},
    {"native_drawText","(I[CIIFFII)V",
        (void*) SkCanvasGlue::drawText___CIIFFIPaint},
    {"native_drawText","(ILjava/lang/String;IIFFII)V",
        (void*) SkCanvasGlue::drawText__StringIIFFIPaint},
    {"native_drawTextRun","(I[CIIIIFFII)V",
        (void*) SkCanvasGlue::drawTextRun___CIIIIFFIPaint},
    {"native_drawTextRun","(ILjava/lang/String;IIIIFFII)V",
        (void*) SkCanvasGlue::drawTextRun__StringIIIIFFIPaint},
    {"native_drawText","(I[CIIFFIII)V",
        (void*) SkCanvasGlue::drawText___CIIFFIPaintTypeface},
    {"native_drawText","(ILjava/lang/String;IIFFIII)V",
        (void*) SkCanvasGlue::drawText__StringIIFFIPaintTypeface},
    {"native_drawTextRun","(I[CIIIIFFIII)V",
        (void*) SkCanvasGlue::drawTextRun___CIIIIFFIPaintTypeface},
    {"native_drawTextRun","(ILjava/lang/String;IIIIFFIII)V",
        (void*) SkCanvasGlue::drawTextRun__StringIIIIFFIPaintTypeface},
    {"native_drawPosText","(I[CII[FI)V",
        (void*) SkCanvasGlue::drawPosText___CII_FPaint},
    {"native_drawPosText","(ILjava/lang/String;[FI)V",
+82 −0
Original line number Diff line number Diff line
/*
 * 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.
 */

#include <SkTypeface.h>
#include <SkPaint.h>
#include <SkFP.h>

#define LOG_TAG "Minikin"
#include <cutils/log.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;
    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 more paint parameters from Minikin
    skpaint.setTextSize(paint.size);
    uint16_t glyph16 = glyph_id;
    SkScalar skWidth;
    SkRect skBounds;
    skpaint.getTextWidths(&glyph16, sizeof(glyph16), &skWidth, &skBounds);
    // TODO: get bounds information
    return SkScalarToFP(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();
}

}
+42 −0
Original line number Diff line number Diff line
/*
 * 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.
 */

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
+5 −0
Original line number Diff line number Diff line
@@ -245,7 +245,12 @@ public:
    }

    static SkTypeface* setTypeface(JNIEnv* env, jobject clazz, SkPaint* obj, SkTypeface* typeface) {
#ifndef USE_MINIKIN
        return obj->setTypeface(typeface);
#else
        // TODO(raph): not yet implemented
        return NULL;
#endif
    }

    static SkRasterizer* setRasterizer(JNIEnv* env, jobject clazz, SkPaint* obj, SkRasterizer* rasterizer) {
Loading