在华为手机上,如果用户修改了系统字体,应用设置的字体就无效了,用freetype可以自己绘制字体,不受系统限制。后面有个例子工程,亲测在华为手机可行。
freetype可以解析字体文件提取字形,这里给出在安卓上使用freetype的方法。
编译freetype
这里提供的编译方式是用freetype源码编译出.a和.so文件,放到安卓工程使用。
编译准备
源码下载,有源码下载地址,这里用到的是2.9.1版本。 准备安卓ndk,一般情况下,在Android Studio里面就可以下载到最新的ndk,ndk的目录在/Users/<username>/Library/Android/sdk/ndk-bundle
,如果是需要其他版本的ndk需要自己到安卓官网下载解压。 解压了源码之后到源码根目录进行编译。
编译toolchain
使用下面的命令编译toolchain,<path-to-ndk>
指ndk路径,platform
使用的android-17
,编译出来的toolchain放在/tmp/ndk/17/
目录下,这个目录是可以随意指定的,下一步会用到
/build/tools/make-standalone-toolchain.sh --platform=android-17 --install-dir=/tmp/ndk/17/ --arch=arm复制代码
设置编译环境
将下面/tmp/ndk/17/
目录修改为上一步toolchain编译输出路径
export PATH=$PATH:/tmp/ndk/17/binexport CC=arm-linux-androideabi-gccexport CXX=arm-linux-androideabi-g++复制代码
配置freetype编译参数
./configure --host=arm-linux-androideabi --prefix=/freetype --without-zlib --with-png=no --with-harfbuzz=no复制代码
编译
编译出来的文件会在freetype/目录下
make -j4make install DESTDIR=$(pwd)复制代码
编译输出
编译成功之后,在freetype目录应该可以看到
freetype├── include│ └── freetype2├── lib│ ├── libfreetype.a│ ├── libfreetype.la│ ├── libfreetype.so│ └── ***└── ***复制代码
其中include/包含一些头文件,可以直接整体复制到安卓工程对应的jni/目录下,lib/下一个.a和.so复制到安卓工程对应的jni/lib/目录下。如果编译出来的文件有问题,最好是从编译ndk toolchain重新开始。
安卓工程配置
这个给出的是使用ndk-build编译的配置方式。
jni
在src/main目录新建jni目录,将上面编译出的include/目录复制到jni/include/,libfreetype.a和libfreetype.so复制到jni/lib/目录下。在jni目录新建Android.mk和Application.mk文件
jni├── Android.mk├── Application.mk├── include│ └── freetype2└── lib ├── libfreetype.a └── libfreetype.so复制代码
Android.mk
在Android.mk文件里面指定引用libfreetype.a:LOCAL_LDFLAGS := $(LOCAL_PATH)/lib/libfreetype.a
然后将include/下的文件夹都加到编译里面,大致内容如下:
LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_ARM_MODE := armLOCAL_MODULE := libfontdecodeLOCAL_SRC_FILES :=LOCAL_LDLIBS := -llog -landroidLOCAL_LDFLAGS := $(LOCAL_PATH)/lib/libfreetype.aLOCAL_CFLAGS += -I$(LOCAL_PATH)/include \ -I$(LOCAL_PATH)/include/freetype2 \ -I$(LOCAL_PATH)/include/freetype2/freetype \ -I$(LOCAL_PATH)/include/freetype2/freetype/config \ -I$(LOCAL_PATH)/include/freetype2/freetype/internalLOCAL_CPPFLAGS += -I$(LOCAL_PATH)/include \ -I$(LOCAL_PATH)/include/freetype2 \ -I$(LOCAL_PATH)/include/freetype2/freetype \ -I$(LOCAL_PATH)/include/freetype2/freetype/config \ -I$(LOCAL_PATH)/include/freetype2/freetype/internalinclude $(BUILD_SHARED_LIBRARY)复制代码
Application.mk如下,没有什么需要做的 需要注意的是ndk17之后不支持armeabi编译了,需要改为armeabi-v7a。
APP_ABI := armeabiAPP_PLATFORM := android-17APP_STL := stlport_static复制代码
build.gradle
在build.gradle的android标签下增加ndk编译配置,在defaultConfig标签下指定编译的架构
android { ... defaultConfig { ... ndk { abiFilters 'armeabi', 'armeabi-v7a' } } ... externalNativeBuild { ndkBuild { ndkBuild { path "src/main/jni/Android.mk" } } }}复制代码
编译
在jni/src/目录添加自己的c或者cpp文件,替换Android.mk里面<your-c/cpp-files>
。在jni目录下执行<path-to-ndk>/ndk-build
就会在../libs/
下生成需要的so文件。