Android Chromium:不成功的尝试,无法从Typeface.java类获得C++ SkTypeface对象

这也就是说,Java Activity层的用户自定义默认字体通过标准framework/JNI的途径是无法传递应用到Chromium内核的。

本来的基本想法是:通过Typeface.DEFAULT获得Java层的系统当前默认字体设置,通过Java动态反射调用获得native_instance句柄,然后尝试用JNI C++代码获得SkTypeface*指针,调用SkTypeface::serialize序列化到一个临时字体文件,然后将此路径回传Java,再重新传到Chromium内核代码。

帖2段核心demo代码:

AwSettings.java:

//#if ENABLE_USER_OVERRIDES_FONTFALLBACK
    //hacker techniques to get current system's default typeface and apply it to chromium/skia kernel code:
    @CalledByNative
    private static long getDefaultTypefaceNativePointer() {
        try{
            android.graphics.Typeface defaultTypeface = android.graphics.Typeface.DEFAULT;
            java.lang.reflect.Field field = null;
            field = android.graphics.Typeface.class.getDeclaredField("native_instance");
            long ret = 0;
            if (android.os.Build.VERSION.SDK_INT>=21) {
                //5.0+
                ret = field.getLong(defaultTypeface);
            }else{
                //4.4-
                ret = field.getInt(defaultTypeface);//boost to long
            }
            Log.i(TAG, "android.graphics.Typeface.DEFAULT.native_instance="+ret);
            return ret;
        }catch(Exception e){
            Log.e(TAG, e.getMessage(), e);
            return 0;
        }
    }
    //private boolean sUserOverridesFontFallbackEnabled = false;
    private static native String nativeGetTempUserOverridesFontFallbackPath();
    public void setUserOverridesFontFallbackEnabled(boolean enable) {
        if (enable) {
            String path = AwSettings.nativeGetTempUserOverridesFontFallbackPath();
            setUserOverridesFontFallback(true, path);
        }else{
            setUserOverridesFontFallback(false, "");
        }
    }
 //#if

aw_settings.cc:

#if ENABLE_USER_OVERRIDES_FONTFALLBACK
static jstring GetTempUserOverridesFontFallbackPath(JNIEnv* env, jclass clazz) {
    VLOG(0)<<"GetTempUserOverridesFontFallbackPath enter";
    jlong native_instance_pointer = Java_AwSettings_getDefaultTypefaceNativePointer(env);
    if(native_instance_pointer==0){
      VLOG(0)<<"GetTempUserOverridesFontFallbackPath getDefaultTypefaceNativePointer failed!";
      return 0;
    }
    //SkTypeface* typeface = (SkTypeface*)(int)native_instance_pointer;
    //  //ALERT: this C++ SkTypeface is got from framework layer, it may not have the same ABI compatibility with chromioum's internal skia library
    TypefaceImpl* typefaceImpl = (TypefaceImpl*)native_instance_pointer;
    SkTypeface* typeface = 0; //TODO: cannot get SkTypeface* from TypefaceImpl*

    //i need a writable path!
    FilePath cache_dir_filepath;
    /*bool ret = */base::android::GetCacheDirectory(&cache_dir_filepath);
    FilePath temp_filepath = cache_dir_filepath.Append( FilePath("test.ttf.ser") ); //<-- TODO: generate this
    std::string gen_temp_path = temp_filepath.AsUTF8Unsafe();

    const char* temp_path = gen_temp_path.c_str(); //"/data/local/test.ttf.ser";
    VLOG(0)<<"GetTempUserOverridesFontFallbackPath gen_temp_path="<<temp_path;
    SkFILEWStream wstream(temp_path);
    typeface->serialize(&wstream);//may fail, but we don't know!

    ScopedJavaLocalRef<jstring> jpath = ConvertUTF8ToJavaString(env, temp_path);
    return jpath.Release();
  }
#endif

遗憾的是,native_instance实际上对应于不透明的TypefaceImpl*,在JNI下可能也是无法访问的。即使能访问,从TypefaceImpl*也得不到SkTypeface*。

时间: 2024-12-10 05:30:27

Android Chromium:不成功的尝试,无法从Typeface.java类获得C++ SkTypeface对象的相关文章

Android Chromium:成功地获取到用户自定义的系统默认字体设置

这个事情的原理是这样的:Android系统官方是不支持修改系统默认字体的,所有能够修改的情况都是OEM产商修改了framework层的代码,同时集成了高权限的预安装应用服务. 怎么做的呢? 其实很简单:修改android.content.res.Configuration类,Configuration类保存系统级别影响所有的Activity View显示的设置.如果Configuration类有改变,则会自动重新启动所有的Activity. 比方说,可以加一个String fontPath或者T

Android 电子邮件发送成功与失败的提示

前言 欢迎大家我分享和推荐好用的代码段~~ 声明          欢迎转载,但请保留文章原始出处: CSDN:http://www.csdn.net 雨季o莫忧离:http://blog.csdn.net/luckkof 正文 For imap/pop: EmailServiceStub.java#sendMaillImpl(),其中statement: sender.sendMessage(messageId)去send mail,您可以详细看下该方法的实现,在适当的地方加成功或者失败的to

Android Chromium WebView学习启动篇

Android从4.4起提供基于Chromium实现的WebView.此前WebView基于WebKit实现.WebKit提供网页解析.布局和绘制以及JS运行等基础功能.Chromium在WebKit基础上为WebView提供进程.线程和渲染等基础构架.因此基于Chromium实现的WebView更好地提供了网页浏览功能.从本文开始我们启动对Android Chromium WebView的学习. 老罗的新浪微博:http://weibo.com/shengyangluo,欢迎关注! 学习Web

从序列查找下载(NCBI)处理到多序列比对----记录一次不太成功的尝试

一.问题呈现 找到Streptomyces属里hrdb基因的启动子(hrdbp)的保守序列,希望以此推断出-10区和-35区. 二.过程 1.下载15-20条hrdb基因的启动子序列,并处理形成一个fasta文件 1.1.以coelicolor A3(2)的hrdb基因为源头,通过blast找到得分最高的前50条序列.Download下载Hit Table(txt)格式的文件,这个文件表头会告诉你每一列显示的是什么. 接下来用excel打开这个文件,首先把 alignment length小于1

Android NDK开发(五)--C代码回调Java代码【转】

转载请注明出处:http://blog.csdn.net/allen315410/article/details/41862479 在上篇博客里了解了Java层是怎样传递数据到C层代码,并且熟悉了大部分的实际开发知识,基本上掌握这些就可以做一个基本的NDK开发了,但是光是了解Java回调C层的数据是不是还不够啊,考虑问题要考虑可逆性,Java能回调C,那么C能否反过来回调Java呢?答案是肯定可以的,这篇博客就介绍一个C语言如何调用Java层的代码.以下是一些问题场景,我们带着这个问题场景来分析

android启动时报错Unable to instantiate application xxxx:java.lang.NullPointerException

如果程序已经运行,再安装到手机的时候总是报以下错误.而且是在打开特定的Activity的情况下才会报错. 06-26 09:45:16.971: E/AndroidRuntime(29733): java.lang.RuntimeException: Unable to instantiate application com.css.promotiontool.ui.CSSAppliction: java.lang.NullPointerException06-26 09:45:16.971:

Android Asynchronous Http Client--Android 开源的网络异步加载类

整理Android Asynchronous Http Client的使用 Android Asynchronous Http Client(AHC) 一个回调式的Android网络请求库 概括: AHC是基于Apache的HttpClient 库,所有的网络请求过程在UI线程之外进行,而回调是在Handler里面处理.也可以再Service或者后台程序里面使用,这个库会自动识别并在相应的Context进行处理. 特点: 异步发送HTTP请求,在回调函数中处理响应 HTTP请求过程不在UI线程进

Android JNI和NDK学习(09)--JNI实例二 传递类对象

1 应用层代码 NdkParam.java是JNI函数的调用类,它的代码如下: package com.skywang.ndk; import android.app.Activity; import android.os.Bundle; import android.util.Log; public class NdkParam extends Activity { public static final String TAG="skywang--NdkParam"; /** Cal

Android之2D图形(圆、直线、点)工具类 (持续更新)

public class Circle { private PointF centerPoint; private float radius; public PointF getCenterPoint() { return centerPoint; } public void setCenterPoint(PointF centerPoint) { this.centerPoint = centerPoint; } public float getRadius() { return radius