Android图形库Skia 三 -结合Freetype显示文字

               

在图像是显示字体,Skiaapi中就有,直接可以将文字显示出现。如下代码:

SkTypeface *font = SkTypeface::CreateFromFile("NotoSansHans-Regular.otf");if ( font ){    paint.setARGB(255, 255, 0, 0);    paint.setTypeface( font );    paint.setTextSize(25);    canvas.drawText("平凡之路!", 14, 0, 25, paint);}

显示效果(字号为25)

 Android图形库Skia 三 -结合Freetype显示文字

 

       除了上述的方法还可以使用SkTypeface::CreateFromName创建face,但要注意,Skia是遍历SK_FONT_FILE_PREFIX(当前版本为:/usr/share/fonts/truetype/msttcorefonts)宏所指示的目录下所有*.ttf字库文件,并将其加载内存的。它的原型如下:

SkTypeface* SkTypeface::CreateFromName(const char name[], Style style) {    return SkFontHost::CreateTypeface(NULL, name, NULL, 0, style);}

       其中第一个参数namettf字体的Font Family name,查看方法是使用gnome-font-viewer查看到“Name”一项的内容,和具体的文件的名字没有关系。如下图:

Android图形库Skia 三 -结合Freetype显示文字 

       另外一个要注意的是,当前版本的skia并不会遍历子目录,参考Skia中遍历Linux系统字库文件

代码如下:

/* Simple Chinese Font demo utilizing Skia toolkit. * Authored by kangear <[email protected]> */#include "SkBitmap.h"#include "SkDevice.h"#include "SkPaint.h"#include "SkRect.h"#include "SkImageEncoder.h"#include "SkTypeface.h"//draw_content()int main(){    // Declare a raster bitmap, which has an integer width and height,    // and a format (config), and a pointer to the actual pixels.    // Bitmaps can be drawn into a SkCanvas, but they are also used to    // specify the target of a SkCanvas' drawing operations.    SkBitmap bitmap;    bitmap.setConfig(SkBitmap::kARGB_8888_Config, 200, 200);    bitmap.allocPixels();    // A Canvas encapsulates all of the state about drawing into a    // device (bitmap).  This includes a reference to the device itself,    // and a stack of matrix/clip values. For any given draw call (e.g.    // drawRect), the geometry of the object being drawn is transformed    // by the concatenation of all the matrices in the stack. The    // transformed geometry is clipped by the intersection of all of the    // clips in the stack.    SkCanvas canvas(bitmap);    // SkPaint class holds the style and color information about how to    // draw geometries, text and bitmaps.    SkPaint paint;    const char gText[] = "123平34凡之路12!";    //SkTypeface *font = SkTypeface::CreateFromFile("DroidSansFallbackFull.ttf");    //usr/share/fonts/truetype/msttcorefonts/DroidSansFallbackFull.ttf    SkTypeface *font = SkTypeface::CreateFromName("Droid Sans Fallback", SkTypeface::kNormal);    if ( font )    {      paint.setARGB(255, 255, 0, 0);      paint.setTypeface( font );      paint.setTextSize(25);      canvas.drawText(gText, sizeof(gText)/sizeof(gText[0]), 0, 25, paint);    }    else    {      printf("font ==null !\n");    }    // SkImageEncoder is the base class for encoding compressed images    // from a specific SkBitmap.    SkImageEncoder::EncodeFile("snapshot.png", bitmap,    SkImageEncoder::kPNG_Type,    /* Quality ranges from 0..100 */ 100);    return 0;}/*build:g++ \-I./include \-I./include/core \-I./include/images  \-I./include/config \-I./include/pdf/ \-Wall -o test-skia ./test-skia.cpp \out/src/images/SkImageDecoder_libpng.o \out/libskia.a \`pkg-config freetype2 --libs --cflags` \`pkg-config libpng --libs --cflags` \-lpthread -grun:./test-skia*/

生成的图片效果

Android图形库Skia 三 -结合Freetype显示文字


       调用api固然简单,我最终的目的是尽量接近Android的显示方式。开始是看android文本布局引擎讲解是大概这样做的。他的文章中是基于使用PyhoneFreetype写的例子,我这里使用skiaFreetype写的例子,他文章的重点是Text Layout Engine TextLayoutShaper,就是排版引擎,所以这里的工作只算是完成了Android中的skiafreetype的工作。TextLayoutShaper重点是排版。不过经过它这么重重的计算,似乎Android中并像本例子中的那样直接调用skia的文字绘制api来实现。这一关先到这里,至少稍微了解了一下。

       上边的问题稍有见解了,Freetype使用方式有两种,一种是使用Skia封装好的Api;另一种是直接调用Freetype的标准Api如下:

...SkFontHost_FreeType.cpp:(.text+0x2185): undefined reference to `FT_Get_Advances'SkFontHost_FreeType.cpp:(.text+0x23e7): undefined reference to `FT_Get_Glyph_Name'SkFontHost_FreeType.cpp:(.text+0x2420): undefined reference to `FT_Get_FSType_Flags'SkFontHost_FreeType.cpp:(.text+0x244e): undefined reference to `FT_Done_FreeType'...

        尽管我现在还没有对freetype有深刻的理解,根据这些个api也能明白个大概了,顾名思义。Android中很可能是直接基于Freetype的Api来实现的更高级的字体显示和排版效果,目前这个也是猜测,得好好的研究一番,才能下结论。

        skia库显示中文的问题中讲到需要将中文转换成UTF8才能显示,我在Linux中的实验结果并没有这个需求,可能是那个要求只是在Windows上。如果写成专门的API供上层调用,我建议采用和Android一样的使用UTF-16作为统一接口。参见Android底层开发之字符绘制TextLayoutCache


        我真希望快点引出harfbuzz我知道更是一个主角关于文字显示,闲聊文本渲染技术的近期发展讲解了它与它的邻居们的关系。

           

再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.****.net/jiangjunshow