这个函数使用GDI plus实现将文本进行简单的排版,写入内存DC ,保存为透明的png图片。
文本格式自动根据行宽分行,并保持原有换行格式。
//一些定义
#define BITMAP_WIDTH = 256;
#define BITMAP_HEIGHT = 256;
#define MAX_TEXT_WIDTH 240 // must <= BITMAP_WIDTH
#define MAX_TEXT_HEIGHT 240 // must <= BITMAP_HEIGHT
//函数声明
void DrawFont(
CStringW dstFilePath,//保存文件的全路径
CStringW text, // 要写入的文本
float size, // 字体大小
UINT32 fgcolor = 0xffffffff,//字体颜色
UINT32 bgcolor = 0x00000000,//背景颜色,透明mask用
CStringW family = L"MS Pゴシック" //字体
);
函数实现
void PiaResUtils::DrawFont(
CStringW dstFilePath,
CStringW text,
float size,
UINT32 fgcolor,
UINT32 bgcolor,
CStringW family)
{
CStringW str = text;
Status ret = Ok;
FontFamily fontFamily(family);
Font font(&fontFamily, size, FontStyleRegular, UnitPixel);
Graphics g(0, 0);
UINT32 width = BITMAP_WIDTH;
UINT32 height = BITMAP_HEIGHT;
INT32 pitch = INT32(width * 4);
RectF fontRect;
ret = g.MeasureString(L"函", -1, &font, RectF(0, 0, 0, 0), &fontRect);
UINT32 fontH = (UINT32) (fontRect.Height);
UINT32 fontW = (UINT32) (fontRect.Width);
UINT32 maxCharInLine = (UINT32)(MAX_TEXT_WIDTH/fontW);
std::auto_ptr<Bitmap> bitmap(new Bitmap(width, height, &g));
{
std::auto_ptr<Graphics> g(Graphics::FromImage(bitmap.get()));
g->Clear(Color(ARGB(bgcolor)));
g->SetTextRenderingHint(TextRenderingHintAntiAlias);
PointF pointF;
pointF.X = (BITMAP_WIDTH - MAX_TEXT_WIDTH)/2;
pointF.Y = (BITMAP_HEIGHT - MAX_TEXT_HEIGHT)/2;
SolidBrush solidBrush = Color(ARGB(fgcolor));
UINT32 pos = 0;
UINT32 len = 0;
RectF rect;
UINT32 strW = 0;
CStringW temp = L"";
while (str != L"") {
pos = str.Find(L'/n');
len = str.GetLength();
if (pos == -1) {
pos = str.GetLength();
if (pos <= maxCharInLine) {
temp = str;
str = L"";
}
else {
pos = maxCharInLine;
BOOL ret = FALSE;
while (!ret) {
temp = str.Left(pos);
ret = g->MeasureString(temp, -1, &font, RectF(0, 0, 0, 0), &rect);
if ((UINT32) (rect.Width) <= MAX_TEXT_WIDTH) {
pos += 1;
if (pos > len) {
pos = len;
ret = TRUE;
}
}
else {
pos -= 1;
ret = TRUE;
}
}
temp = str.Left(pos);
str = str.Right(len - pos);
}
}
else if (pos <= maxCharInLine) {
temp = str.Left(pos);
if (len - pos - 1 > 0) {
str = str.Right(len - pos - 1);
}
else {
str = L"";
}
}
else if (pos > maxCharInLine) {
UINT32 posTo = maxCharInLine;
BOOL ret = FALSE;
while (!ret) {
temp = str.Left(posTo);
ret = g->MeasureString(temp, -1, &font, RectF(0, 0, 0, 0), &rect);
if ((UINT32) (rect.Width) <= MAX_TEXT_WIDTH) {
posTo += 1;
if (posTo > pos) {
posTo = pos;
ret = TRUE;
}
}
else {
posTo -= 1;
ret = TRUE;
}
}
temp = str.Left(posTo);
str = str.Right(len - posTo);
}
g->DrawString(temp, -1, &font, pointF, &solidBrush);
pointF.Y += fontH;
if ((UINT32)(pointF.Y + fontH )> MAX_TEXT_HEIGHT){
str = L"";
}
}
}
{
Rect rect(0, 0, width, height);
BitmapData data;
Status ret = bitmap->LockBits(&rect, ImageLockModeRead, PixelFormat32bppARGB, &data);
if (ret != Ok) {
throw std::exception("Gdiplus::Bitmap::LockBits failed.");
}
bitmap->UnlockBits(&data);
}
CLSID clsid;
GetEncoderClsid(L"image/png", &clsid);
bitmap->Save(dstFilePath, &clsid);
}