khmer的顯示實現_1

由於工作的需要,分配添加支持khmer,痛苦的煎熬了一個月,終於把它給整出來了,方便以後大家開發中提供一點點的幫助。

本次的開發主要採用開源的代碼來實現的。採用了兩種:harfbuzz跟freetype。

首先:介紹一下harfbuzz的基礎知識:

Harfbuzz 是一個開源的text opentype layout 引擎,它被應用於很多的開源項目中,如Pango,Filefox,Webkit,android等。

可以參考:http://my.oschina.net/wolfcs/blog/107635 ,文檔的介紹,我們就不必詳細的介紹了。

本次中主要是通過harfbuzz 獲取到glyph id,獲取到這個值。因時間比較緊張,暫時採用demo上的某些例子參考,並進行相應的修改。然後獲取到glyph id後,再通過freetype獲取到所需要字符的信息,其實獲取的這個字符image的信息,然後調用顯示的函數進行顯示出來。

代碼如下:

int GetKhmerStringInfo(int iLan, unsigned char *pucBuf, int iBufWidth, int iBufHeight, int iX, int iY, \
		char *pcShowString, unsigned int uiFrontColor, int iXTimes, int iYTimes)
{
	int iPenPos = 0;
	int iFontMaxHeight = 0;
	int iDrawHeight = 0;
	unsigned int uiCount = 0;
	unsigned int iLoop = 0;
	const int FONT_MAX_SIZE = MaxFontSize();
	int bError = 0;
	hb_buffer_t *buffer;
	hb_glyph_info_t *infos;
	hb_glyph_position_t *positions;
	hb_glyph_info_t *info;
	hb_glyph_position_t *pos;
	GS_TT_BITMAP stBitmap;

	if (strlen(pcShowString) <= 0)
	{
		return -1;
	}
	iX = GetXPos(iX);
	iY = GetYPos(iY);
	iBufWidth = GetXPos(iBufWidth);
	iBufHeight = GetYPos(iBufHeight);
	iPenPos = iX;

	GetttfFileData();
	buffer = hb_buffer_create();
	hb_buffer_add_utf8(buffer, (const char *)pcShowString, -1, 0, -1);
	hb_buffer_guess_segment_properties(buffer);
	hb_shape(font, buffer, NULL, 0);
	uiCount = hb_buffer_get_length(buffer);
	infos = hb_buffer_get_glyph_infos(buffer, NULL);
	positions = hb_buffer_get_glyph_positions(buffer, NULL);
	stBitmap.pucBuffer = GSOS_Malloc(FONT_MAX_SIZE);
	if (NULL == stBitmap.pucBuffer)
	{
		return 0;
	}
	for (iLoop = 0; iLoop < uiCount; iLoop++)
	{
		info = &infos[iLoop];
		pos = &positions[iLoop];
		bError = FT_Load_Glyph(stFTFace, info->codepoint, FT_LOAD_DEFAULT);
		if (stFTFace->glyph->format != FT_GLYPH_FORMAT_BITMAP)
		{
			bError = FT_Render_Glyph(stFTFace->glyph, FT_RENDER_MODE_NORMAL);
		}
		memset (stBitmap.pucBuffer, 0, FONT_MAX_SIZE);
		RenderGlyphInternal(&(stFTFace->glyph->outline), &stBitmap);
		if (iPenPos == iX && stBitmap.iLeft < 0)
		{
			stBitmap.iLeft = 0;
		}
#if HD_OSD || OSD_NAME == SUPER
		iDrawHeight = GetYPos(28 - iFontMaxHeight)/2;
#endif
		DrawFontBitmap(pucBuf, iBufWidth, iBufHeight, iPenPos + stBitmap.iLeft, \
				iY+4 - stBitmap.iTop + iDrawHeight, &stBitmap, uiFrontColor);
		iPenPos += (stFTFace->glyph->metrics.horiAdvance >> 6)*iXTimes;
	}
	hb_buffer_destroy(buffer);
	GSOS_Free(stBitmap.pucBuffer);
	return GetHD2SDXPos(iPenPos - iX);
}


因爲freetype需要每次傳入一個字符進入索引到對應的圖形,獲取到字符的等信息,因每次都需要malloc or read or create,使用一個全局的變量控制。

int GetttfFileData(void)
{
	if (iOpenFileOnlyOnce > 0)
	{
		iOpenFileOnlyOnce--;
		FILE *fpttf;
		hb_blob_t *blob = NULL;
		hb_destroy_func_t destroy;
		unsigned int upem = 0;
		void *user_data = NULL;
		char *font_data = NULL;
		hb_memory_mode_t mm = HB_MEMORY_MODE_WRITABLE;

		fpttf = fopen(TTF_SAVE_FALSH_PATCH, "rb");
		if (NULL == fpttf)
		{
			printf("open ttf file faild!, [%s, %d]\r\n", __FUNCTION__, __LINE__);
			return 0;
		}
		fseek(fpttf, 0, SEEK_END);
		uifpLen = ftell(fpttf);
		fseek(fpttf, 0, SEEK_SET);
		if (NULL != font_data)
		{
			GSOS_Free(font_data);
			font_data = NULL;
		}
		font_data = GSOS_Malloc(uifpLen);
		uifpLen = fread(font_data, 1, uifpLen, fpttf);
		fclose(fpttf);
		user_data = (void *)font_data;
		blob = hb_blob_create((const char *)font_data, uifpLen, mm, user_data, destroy);
		face = hb_face_create(blob, 0);
		hb_blob_destroy(blob);
		blob = NULL;
		upem = hb_face_get_upem(face);
		font = hb_font_create(face);
		hb_font_set_scale(font, upem, upem);
		hb_ft_font_set_funcs(font);
		GetFreetypeFace(TTF_SAVE_FALSH_PATCH, KHMER_FONT_SIZE, &stFTFace);
	}
	return uifpLen;
}


當切換到其他的語言時,就可以free掉了。

void FreeHarfbuzzMem(void)
{
	if (NULL != font)
	{
		hb_font_destroy(font);
		font = NULL;
	}
	if (face)
	{
		hb_face_destroy(face);
		face = NULL;
	}
	iOpenFileOnlyOnce = 1;
}

以下就是初始化freetype

static int GetFreetypeFace(char *ttf, int font_size, FT_Face *face)
{
	FT_Library library;

	if (font_size < 1 || font_size > 72)
	{
		return -1;
	}
	if (FT_Init_FreeType(&library) != 0)
	{
		return -2;
	}
	if (FT_New_Face(library, ttf, 0, face) != 0)
	{
		return -3;
	}
	FT_Set_Char_Size(*face, 0, font_size * 64, 96, 96);
	return 0;
}



至於一些定義,我就不提供了,可以參考其他,至於修改的lib後期再共享一下。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章