19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "jni.h"
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <android_runtime/AndroidRuntime.h>
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "GraphicsJNI.h"
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "SkStream.h"
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "SkTypeface.h"
7b13b9bdad2baf6ad1ec2e56b6b7598fa20f55fc4Mathias Agopian#include <android_runtime/android_util_AssetManager.h>
8b13b9bdad2baf6ad1ec2e56b6b7598fa20f55fc4Mathias Agopian#include <androidfw/AssetManager.h>
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectusing namespace android;
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass AutoJavaStringToUTF8 {
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic:
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AutoJavaStringToUTF8(JNIEnv* env, jstring str) : fEnv(env), fJStr(str)
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fCStr = env->GetStringUTFChars(str, NULL);
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ~AutoJavaStringToUTF8()
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fEnv->ReleaseStringUTFChars(fJStr, fCStr);
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const char* c_str() const { return fCStr; }
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectprivate:
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    JNIEnv*     fEnv;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jstring     fJStr;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const char* fCStr;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic SkTypeface* Typeface_create(JNIEnv* env, jobject, jstring name,
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                   SkTypeface::Style style) {
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkTypeface* face;
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (NULL == name) {
354df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        face = SkTypeface::CreateFromName(NULL, (SkTypeface::Style)style);
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    else {
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        AutoJavaStringToUTF8    str(env, name);
394df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        face = SkTypeface::CreateFromName(str.c_str(), style);
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return face;
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic SkTypeface* Typeface_createFromTypeface(JNIEnv* env, jobject, SkTypeface* family, int style) {
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return SkTypeface::CreateFromTypeface(family, (SkTypeface::Style)style);
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
474cb1753ec6e90d7e747880c599dc1c164a568cf3Elliott Hughes
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void Typeface_unref(JNIEnv* env, jobject obj, SkTypeface* face) {
4931a69fdbe1edd8d686043e8ca7d278289f65808eMike Reed    SkSafeUnref(face);
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int Typeface_getStyle(JNIEnv* env, jobject obj, SkTypeface* face) {
534df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    return face->style();
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass AssetStream : public SkStream {
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic:
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AssetStream(Asset* asset, bool hasMemoryBase) : fAsset(asset)
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fMemoryBase = hasMemoryBase ? fAsset->getBuffer(false) : NULL;
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    virtual ~AssetStream()
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        delete fAsset;
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
674cb1753ec6e90d7e747880c599dc1c164a568cf3Elliott Hughes
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    virtual const void* getMemoryBase()
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return fMemoryBase;
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project	virtual bool rewind()
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
75ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root        off64_t pos = fAsset->seek(0, SEEK_SET);
76ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root        return pos != (off64_t)-1;
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
784cb1753ec6e90d7e747880c599dc1c164a568cf3Elliott Hughes
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project	virtual size_t read(void* buffer, size_t size)
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ssize_t amount;
824cb1753ec6e90d7e747880c599dc1c164a568cf3Elliott Hughes
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (NULL == buffer)
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        {
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (0 == size)  // caller is asking us for our total length
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return fAsset->getLength();
874cb1753ec6e90d7e747880c599dc1c164a568cf3Elliott Hughes
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // asset->seek returns new total offset
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // we want to return amount that was skipped
904cb1753ec6e90d7e747880c599dc1c164a568cf3Elliott Hughes
91ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root            off64_t oldOffset = fAsset->seek(0, SEEK_CUR);
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (-1 == oldOffset)
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return 0;
94ddb76c4644756b31be948d70aaa8ee541dd94999Kenny Root            off64_t newOffset = fAsset->seek(size, SEEK_CUR);
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (-1 == newOffset)
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return 0;
974cb1753ec6e90d7e747880c599dc1c164a568cf3Elliott Hughes
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            amount = newOffset - oldOffset;
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        else
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        {
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            amount = fAsset->read(buffer, size);
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1044cb1753ec6e90d7e747880c599dc1c164a568cf3Elliott Hughes
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (amount < 0)
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            amount = 0;
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return amount;
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1094cb1753ec6e90d7e747880c599dc1c164a568cf3Elliott Hughes
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectprivate:
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Asset*      fAsset;
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const void* fMemoryBase;
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic SkTypeface* Typeface_createFromAsset(JNIEnv* env, jobject,
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                            jobject jassetMgr,
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                            jstring jpath) {
1184cb1753ec6e90d7e747880c599dc1c164a568cf3Elliott Hughes
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    NPE_CHECK_RETURN_ZERO(env, jassetMgr);
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    NPE_CHECK_RETURN_ZERO(env, jpath);
1214cb1753ec6e90d7e747880c599dc1c164a568cf3Elliott Hughes
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AssetManager* mgr = assetManagerForJavaObject(env, jassetMgr);
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (NULL == mgr) {
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return NULL;
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1264cb1753ec6e90d7e747880c599dc1c164a568cf3Elliott Hughes
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AutoJavaStringToUTF8    str(env, jpath);
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Asset* asset = mgr->open(str.c_str(), Asset::ACCESS_BUFFER);
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (NULL == asset) {
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return NULL;
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1324cb1753ec6e90d7e747880c599dc1c164a568cf3Elliott Hughes
133a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy    SkStream* stream = new AssetStream(asset, true);
134a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy    SkTypeface* face = SkTypeface::CreateFromStream(stream);
135a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy    // SkTypeFace::CreateFromStream calls ref() on the stream, so we
136a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy    // need to unref it here or it won't be freed later on
137a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy    stream->unref();
138a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy
139a1db574036c9bc2d397b69f8200594027e1fff16Romain Guy    return face;
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
142a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guystatic SkTypeface* Typeface_createFromFile(JNIEnv* env, jobject, jstring jpath) {
143a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy    NPE_CHECK_RETURN_ZERO(env, jpath);
144a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy
145a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy    AutoJavaStringToUTF8 str(env, jpath);
146a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy
147a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy    return SkTypeface::CreateFromFile(str.c_str());
148a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy}
149a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy
150dbade9d6a075b1d5b8ebe10ee8961a5de296c93bMike Reed#define MIN_GAMMA   (0.1f)
151dbade9d6a075b1d5b8ebe10ee8961a5de296c93bMike Reed#define MAX_GAMMA   (10.0f)
152dbade9d6a075b1d5b8ebe10ee8961a5de296c93bMike Reedstatic float pinGamma(float gamma) {
153dbade9d6a075b1d5b8ebe10ee8961a5de296c93bMike Reed    if (gamma < MIN_GAMMA) {
154dbade9d6a075b1d5b8ebe10ee8961a5de296c93bMike Reed        gamma = MIN_GAMMA;
155dbade9d6a075b1d5b8ebe10ee8961a5de296c93bMike Reed    } else if (gamma > MAX_GAMMA) {
156dbade9d6a075b1d5b8ebe10ee8961a5de296c93bMike Reed        gamma = MAX_GAMMA;
157dbade9d6a075b1d5b8ebe10ee8961a5de296c93bMike Reed    }
158dbade9d6a075b1d5b8ebe10ee8961a5de296c93bMike Reed    return gamma;
159dbade9d6a075b1d5b8ebe10ee8961a5de296c93bMike Reed}
160dbade9d6a075b1d5b8ebe10ee8961a5de296c93bMike Reed
161dbade9d6a075b1d5b8ebe10ee8961a5de296c93bMike Reedextern void skia_set_text_gamma(float, float);
162dbade9d6a075b1d5b8ebe10ee8961a5de296c93bMike Reed
163dbade9d6a075b1d5b8ebe10ee8961a5de296c93bMike Reedstatic void Typeface_setGammaForText(JNIEnv* env, jobject, jfloat blackGamma,
164dbade9d6a075b1d5b8ebe10ee8961a5de296c93bMike Reed                                     jfloat whiteGamma) {
165dbade9d6a075b1d5b8ebe10ee8961a5de296c93bMike Reed    // Comment this out for release builds. This is only used during development
166dbade9d6a075b1d5b8ebe10ee8961a5de296c93bMike Reed    skia_set_text_gamma(pinGamma(blackGamma), pinGamma(whiteGamma));
167dbade9d6a075b1d5b8ebe10ee8961a5de296c93bMike Reed}
168dbade9d6a075b1d5b8ebe10ee8961a5de296c93bMike Reed
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project///////////////////////////////////////////////////////////////////////////////
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic JNINativeMethod gTypefaceMethods[] = {
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "nativeCreate",        "(Ljava/lang/String;I)I", (void*)Typeface_create },
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "nativeCreateFromTypeface", "(II)I", (void*)Typeface_createFromTypeface },
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "nativeUnref",              "(I)V",  (void*)Typeface_unref },
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "nativeGetStyle",           "(I)I",  (void*)Typeface_getStyle },
176a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy    { "nativeCreateFromAsset",    "(Landroid/content/res/AssetManager;Ljava/lang/String;)I",
177a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy                                           (void*)Typeface_createFromAsset },
1782bb3ea162a58c0f1dddccdbe68b64e02456f11f9Romain Guy    { "nativeCreateFromFile",     "(Ljava/lang/String;)I",
179dbade9d6a075b1d5b8ebe10ee8961a5de296c93bMike Reed                                           (void*)Typeface_createFromFile },
180dbade9d6a075b1d5b8ebe10ee8961a5de296c93bMike Reed    { "setGammaForText", "(FF)V", (void*)Typeface_setGammaForText },
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint register_android_graphics_Typeface(JNIEnv* env)
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return android::AndroidRuntime::registerNativeMethods(env,
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                                       "android/graphics/Typeface",
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                                       gTypefaceMethods,
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                                       SK_ARRAY_COUNT(gTypefaceMethods));
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
190