skia⼩例⼦之⽂字排版
近来⽤skia试着做⽂字的相关排版,当然安卓上⾯已经有相关的接⼝了,但出于学习⽬的(安卓底层调⽤的也是skia),这⾥就⾃⼰写⼀个极其简单的,其中功能包括设置⾏间距,对齐⽅式等等,⽬前只能实现从左到右排版,⾄于垂直排版因为我在调⽤skia的⼀个接⼝时遇到⼀个问题,⽬前还不能解决(我在后⾯也将问题贴了出来,希望有⼤佬可以帮我解决⼀下),下⾯就直接分享⼀下代码,很low,但作为初学者拿来学习skia还多少有点⽤途吧。(⾄于怎么在vs中建⽴⼯程使之运⾏起来,可以参考前⼀篇⽂章“”),后续已有更新更多内容,,,,,
// HelloSkia.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "SkBitmap.h"
#include "SkDevice.h"
#include "SkPaint.h"
#include "SkRect.h"
#include "SkImageEncoder.h"
#include "SkTypeface.h"
#include "SkCanvas.h"
#include "iostream"
/*
void drawtext(char text[], size_t byteLength,float testhighth, const SkPaint& paint, SkCanvas canvas,const int width, const int height) {
SkScalar measuredWidth;
int partialBytes = paint.breakText(text, byteLength, width, &measuredWidth);
if (partialBytes < byteLength) {
canvas.drawText(text, partialBytes, 0.0f, testhighth, paint);
int j = 0;
for (int i = partialBytes; i < byteLength; i++) {
text[j] = text[i];
j++;
}
text[j] = '\0';
testhighth += testhighth;
drawtext(text, strlen(text), testhighth, paint, canvas, width, height);
}
else
canvas.drawText(text, partialBytes, 0.0f, testhighth, paint);
}
*/
void ConversionText(char text[], int partialBytes, int byteLength) {
int j = 0;
for (int i = partialBytes; i < byteLength; i++) {
text[j] = text[i];
j++;
}
text[j] = '\0';
}
void setTypeText(char text[],  SkPaint& paint, float LineSpacing,char Alignment) {
const int width = 512;
const int height = 512;
bool flag = true;
SkBitmap bitmap;
SkImageInfo ii = SkImageInfo::Make(width, height, kBGRA_8888_SkColorType, kPremul_SkAlphaType);
bitmap.allocPixels(ii, ii.minRowBytes());
bitmap.allocPixels();
bitmap.allocPixels();
SkCanvas canvas(bitmap);
canvas.clear(0x00000000);// 背景为透明⾊
{
SkRect bounds;
float y = bounds.fBottom - bounds.fTop;
while (flag) {
int partialBytes = paint.breakText(text, strlen(text), width);
//SkDebugf("%d/n", partialBytes);
if (partialBytes < strlen(text)) {
SkRect bounds;
float testwidth = bounds.fRight - bounds.fLeft;
switch (Alignment)
{
case 'L':case 'l':
canvas.drawText(text, partialBytes, 0.0f, y, paint);
break;
case 'R':case 'r':
canvas.drawText(text, partialBytes, width - testwidth, y, paint);    break;
case 'C':case 'c':
paint.setTextAlign(SkPaint::kCenter_Align);
canvas.drawText(text, partialBytes, width / 2.0, y, paint);
break;
default:
canvas.drawText(text, partialBytes, 0.0f, y, paint);
}
ConversionText(text, partialBytes, strlen(text));
SkRect bounds2;
text asureText(text, strlen(text), &bounds2);
y += (bounds2.fBottom - bounds2.fTop) + LineSpacing;
if (y > height) {
flag = false;
}
}
else {
SkRect bounds;
float testwidth = bounds.fRight - bounds.fLeft;
switch (Alignment)
{
case 'L':case 'l':
canvas.drawText(text, partialBytes, 0.0f, y, paint);
break;
case 'R':case 'r':
canvas.drawText(text, partialBytes, width - testwidth, y, paint);    break;
case 'C':case 'c':
paint.setTextAlign(SkPaint::kCenter_Align);
canvas.drawText(text, partialBytes, width / 2.0, y, paint);
break;
default:
canvas.drawText(text, partialBytes, 0.0f, y, paint);
}
flag = false;
}
}
}
}
SkFILEWStream stream("D:\\Image\\board.jpg");
SkEncodeImage(&stream, bitmap, SkEncodedImageFormat::kPNG, 100);
}
int main(int argc, _TCHAR* argv[])
{
char text[] = "Life needs one person to struggle.Only by continuous learning can you improve yourself.";
SkPaint paint;
paint.setTextSize(70.0);
paint.setAntiAlias(true);
paint.setColor(0xff4281A4);
paint.setStyle(SkPaint::kFill_Style);
paint.setTextSkewX(-.3f);
//paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
//第三个参数是⾏间隔,第四个参数是对齐⽅式,有r,R右对齐,l,L左对齐,C,c居中三种⽅式
//输⼊关键字不正确时按左对齐处理
setTypeText(text, paint, 5.0, 'R');
return 0;
}
运⾏结果为:
其中还有很多问题有待解决,⽐如单词的连续性,如果是中⽂怎么办等等,有时间的话后续我会继续做相关的⼯作。
下⾯来说⼀下开头说的问题即遇到使⽤paint.setFlags(SkPaint::kVerticalText_Flag)或paint.setVerticalText⽆效,
官⽹给出的类⼦是这样的,在使⽤了paint.setVerticalText(true)之后,可以竖着draw出字,然⽽我加上后缺没有什么变化
我的就是这样:
没加之前如下,这算正常吧
可是加上之后,并没有什么卵⽤:
就是这个问题搞了很久。。。。。还是⽆果,不知道是怎么回事
更新,,,,,,,,
这次解决了输出中⽂,因为每个中⽂占两个字节,⽽每个英⽂字母占⼀个字节,所以⼀段话中如果既有中⽂⼜有英⽂会在处理宽度等等⽅⾯会⽐较难弄,这⾥我采⽤的是wchar_t类型,paint.setTextEncoding(SkPaint::kUTF16_TextEncoding)编码,注意wchar_t字符串中即使是英⽂字母其也是按照两个字节来处理的,所以这样的话就可以统⼀来处理了,反正都是两个字节对吧,另⼀个问题就是对齐⽅式中的居中⽅式,在之前的英⽂版中是调⽤skia接⼝的paint.setTextAlign(SkPaint::kCenter_Align);这个接⼝的作⽤就是将字符串的中间对准canvas.drawText中指定的坐标,但是当有中⽂、标点符号混在⼀起的话,标点符号在视觉上是⼀个字节但却按两个字节处理,所以如果还是采⽤⽼办法那么居中效果看起来并不是很居中,如下:其中红⾊下标线的两⾏就是不理想的结果
为了解决这⼀问题,在这⾥抛弃了前⾯的⽅法,直接采⽤了简单粗暴的⽅式(对⽐之前的代码就可以看到哪⾥不同)
// HelloSkia.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "SkBitmap.h"
#include "SkDevice.h"
#include "SkPaint.h"
#include "SkRect.h"
#include "SkImageEncoder.h"

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。