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)

 

 

       除了上述的方法还可以使用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”一项的内容,和具体的文件的名字没有关系。如下图:

 

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

代码如下:

/* Simple Chinese Font demo utilizing Skia toolkit.
 * Authored by kangear <kangear@163.com>
 */

#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 -g

run:
./test-skia
*/

生成的图片效果:



       调用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我知道更是一个主角关于文字显示,闲聊文本渲染技术的近期发展讲解了它与它的邻居们的关系。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

袁保康

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值