11a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien/*
21a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien * Copyright (C) 2014 The Android Open Source Project
31a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien *
41a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien * Licensed under the Apache License, Version 2.0 (the "License");
51a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien * you may not use this file except in compliance with the License.
61a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien * You may obtain a copy of the License at
71a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien *
81a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien *      http://www.apache.org/licenses/LICENSE-2.0
91a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien *
101a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien * Unless required by applicable law or agreed to in writing, software
111a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien * distributed under the License is distributed on an "AS IS" BASIS,
121a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien * See the License for the specific language governing permissions and
141a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien * limitations under the License.
151a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien */
161a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien
171a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien#define LOG_TAG "Minikin"
181a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien
191a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien#include "JNIHelp.h"
201a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien#include <android_runtime/AndroidRuntime.h>
211a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien
221a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien#include "SkTypeface.h"
231a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien#include "GraphicsJNI.h"
241a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien#include <ScopedPrimitiveArray.h>
251a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien#include <ScopedUtfChars.h>
26d573794d83a049fe59e289944f0cd77406dd776aRaph Levien#include <android_runtime/android_util_AssetManager.h>
27d573794d83a049fe59e289944f0cd77406dd776aRaph Levien#include <androidfw/AssetManager.h>
28d573794d83a049fe59e289944f0cd77406dd776aRaph Levien#include "Utils.h"
291a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien
303d528c403c8945cc326bb656ff0c2e11373401daRaph Levien#include "TypefaceImpl.h"
311a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien#include <minikin/FontFamily.h>
321a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien#include "MinikinSkia.h"
331a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien
341a73f732f91e97c9c66b808c245ddda36a10e987Raph Leviennamespace android {
351a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien
36f9e3d311275c37fe5f2562993687a1627780a6d0Raph Levienstatic jlong FontFamily_create(JNIEnv* env, jobject clazz, jstring lang, jint variant) {
37f9e3d311275c37fe5f2562993687a1627780a6d0Raph Levien    FontLanguage fontLanguage;
38f9e3d311275c37fe5f2562993687a1627780a6d0Raph Levien    if (lang != NULL) {
39f9e3d311275c37fe5f2562993687a1627780a6d0Raph Levien        ScopedUtfChars str(env, lang);
40f9e3d311275c37fe5f2562993687a1627780a6d0Raph Levien        fontLanguage = FontLanguage(str.c_str(), str.size());
41f9e3d311275c37fe5f2562993687a1627780a6d0Raph Levien    }
42f9e3d311275c37fe5f2562993687a1627780a6d0Raph Levien    return (jlong)new FontFamily(fontLanguage, variant);
431a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien}
441a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien
4515cf4757dc0099301662f8a26da561434cc07cfaRaph Levienstatic void FontFamily_unref(JNIEnv* env, jobject clazz, jlong familyPtr) {
4615cf4757dc0099301662f8a26da561434cc07cfaRaph Levien    FontFamily* fontFamily = reinterpret_cast<FontFamily*>(familyPtr);
4715cf4757dc0099301662f8a26da561434cc07cfaRaph Levien    fontFamily->Unref();
481a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien}
491a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien
50d573794d83a049fe59e289944f0cd77406dd776aRaph Levienstatic jboolean addSkTypeface(FontFamily* family, SkTypeface* face) {
51d573794d83a049fe59e289944f0cd77406dd776aRaph Levien    MinikinFont* minikinFont = new MinikinFontSkia(face);
52d573794d83a049fe59e289944f0cd77406dd776aRaph Levien    bool result = family->addFont(minikinFont);
53d573794d83a049fe59e289944f0cd77406dd776aRaph Levien    minikinFont->Unref();
54d573794d83a049fe59e289944f0cd77406dd776aRaph Levien    return result;
55d573794d83a049fe59e289944f0cd77406dd776aRaph Levien}
56d573794d83a049fe59e289944f0cd77406dd776aRaph Levien
571a73f732f91e97c9c66b808c245ddda36a10e987Raph Levienstatic jboolean FontFamily_addFont(JNIEnv* env, jobject clazz, jlong familyPtr, jstring path) {
581a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien    NPE_CHECK_RETURN_ZERO(env, path);
591a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien    ScopedUtfChars str(env, path);
601a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien    SkTypeface* face = SkTypeface::CreateFromFile(str.c_str());
619a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien    if (face == NULL) {
629a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien        ALOGE("addFont failed to create font %s", str.c_str());
639a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien        return false;
649a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien    }
65117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien    FontFamily* fontFamily = reinterpret_cast<FontFamily*>(familyPtr);
66d573794d83a049fe59e289944f0cd77406dd776aRaph Levien    return addSkTypeface(fontFamily, face);
67d573794d83a049fe59e289944f0cd77406dd776aRaph Levien}
68d573794d83a049fe59e289944f0cd77406dd776aRaph Levien
69117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levienstatic jboolean FontFamily_addFontWeightStyle(JNIEnv* env, jobject clazz, jlong familyPtr,
70117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien        jstring path, jint weight, jboolean isItalic) {
71117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien    NPE_CHECK_RETURN_ZERO(env, path);
72117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien    ScopedUtfChars str(env, path);
73117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien    SkTypeface* face = SkTypeface::CreateFromFile(str.c_str());
74117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien    if (face == NULL) {
75117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien        ALOGE("addFont failed to create font %s", str.c_str());
76117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien        return false;
77117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien    }
78117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien    FontFamily* fontFamily = reinterpret_cast<FontFamily*>(familyPtr);
79117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien    MinikinFont* minikinFont = new MinikinFontSkia(face);
80117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien    fontFamily->addFont(minikinFont, FontStyle(weight / 100, isItalic));
81117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien    minikinFont->Unref();
82117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien    return true;
83117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien}
84117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien
85d573794d83a049fe59e289944f0cd77406dd776aRaph Levienstatic jboolean FontFamily_addFontFromAsset(JNIEnv* env, jobject, jlong familyPtr,
86d573794d83a049fe59e289944f0cd77406dd776aRaph Levien        jobject jassetMgr, jstring jpath) {
87d573794d83a049fe59e289944f0cd77406dd776aRaph Levien    NPE_CHECK_RETURN_ZERO(env, jassetMgr);
88d573794d83a049fe59e289944f0cd77406dd776aRaph Levien    NPE_CHECK_RETURN_ZERO(env, jpath);
89d573794d83a049fe59e289944f0cd77406dd776aRaph Levien
90d573794d83a049fe59e289944f0cd77406dd776aRaph Levien    AssetManager* mgr = assetManagerForJavaObject(env, jassetMgr);
91d573794d83a049fe59e289944f0cd77406dd776aRaph Levien    if (NULL == mgr) {
92d573794d83a049fe59e289944f0cd77406dd776aRaph Levien        return false;
93d573794d83a049fe59e289944f0cd77406dd776aRaph Levien    }
94d573794d83a049fe59e289944f0cd77406dd776aRaph Levien
95d573794d83a049fe59e289944f0cd77406dd776aRaph Levien    ScopedUtfChars str(env, jpath);
96d573794d83a049fe59e289944f0cd77406dd776aRaph Levien    Asset* asset = mgr->open(str.c_str(), Asset::ACCESS_BUFFER);
97d573794d83a049fe59e289944f0cd77406dd776aRaph Levien    if (NULL == asset) {
98d573794d83a049fe59e289944f0cd77406dd776aRaph Levien        return false;
99d573794d83a049fe59e289944f0cd77406dd776aRaph Levien    }
100d573794d83a049fe59e289944f0cd77406dd776aRaph Levien
101d573794d83a049fe59e289944f0cd77406dd776aRaph Levien    SkStream* stream = new AssetStreamAdaptor(asset,
102d573794d83a049fe59e289944f0cd77406dd776aRaph Levien                                              AssetStreamAdaptor::kYes_OwnAsset,
103d573794d83a049fe59e289944f0cd77406dd776aRaph Levien                                              AssetStreamAdaptor::kYes_HasMemoryBase);
104d573794d83a049fe59e289944f0cd77406dd776aRaph Levien    SkTypeface* face = SkTypeface::CreateFromStream(stream);
105d573794d83a049fe59e289944f0cd77406dd776aRaph Levien    // Note: SkTypeface::CreateFromStream holds its own reference to the stream
106d573794d83a049fe59e289944f0cd77406dd776aRaph Levien    stream->unref();
107d573794d83a049fe59e289944f0cd77406dd776aRaph Levien    if (face == NULL) {
108d573794d83a049fe59e289944f0cd77406dd776aRaph Levien        ALOGE("addFontFromAsset failed to create font %s", str.c_str());
109d573794d83a049fe59e289944f0cd77406dd776aRaph Levien        return false;
110d573794d83a049fe59e289944f0cd77406dd776aRaph Levien    }
111117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien    FontFamily* fontFamily = reinterpret_cast<FontFamily*>(familyPtr);
112d573794d83a049fe59e289944f0cd77406dd776aRaph Levien    return addSkTypeface(fontFamily, face);
1131a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien}
1141a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien
1151a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien///////////////////////////////////////////////////////////////////////////////
1161a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien
1171a73f732f91e97c9c66b808c245ddda36a10e987Raph Levienstatic JNINativeMethod gFontFamilyMethods[] = {
118117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien    { "nCreateFamily",         "(Ljava/lang/String;I)J", (void*)FontFamily_create },
119117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien    { "nUnrefFamily",          "(J)V", (void*)FontFamily_unref },
120117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien    { "nAddFont",              "(JLjava/lang/String;)Z", (void*)FontFamily_addFont },
121117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien    { "nAddFontWeightStyle",   "(JLjava/lang/String;IZ)Z", (void*)FontFamily_addFontWeightStyle },
122117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien    { "nAddFontFromAsset",     "(JLandroid/content/res/AssetManager;Ljava/lang/String;)Z",
123d573794d83a049fe59e289944f0cd77406dd776aRaph Levien                                           (void*)FontFamily_addFontFromAsset },
1241a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien};
1251a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien
1261a73f732f91e97c9c66b808c245ddda36a10e987Raph Levienint register_android_graphics_FontFamily(JNIEnv* env)
1271a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien{
1281a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien    return android::AndroidRuntime::registerNativeMethods(env,
1291a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien        "android/graphics/FontFamily",
1301a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien        gFontFamilyMethods, NELEM(gFontFamilyMethods));
1311a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien}
1321a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien
1331a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien}
134