freetype 字形解析



title: freetype 字形解析
date: 2019/3/7 20:17:46
toc: true

freetype 字形解析

字體管理

管理字形,這里可以拆分為兩個部分,一部分為管理字距,一部分為有效數據(位圖信息).

比如字母g,藍色框里的是有效的位圖信息,但是排版的時候,是需要考慮字距的,否則雖然不重疊,但是不太好看.

mark

mark

數據結構

這里記住一個點

我們一般都是先轉換到字符到字形槽,然后從字形槽提取位圖,提取邊界bbox

https://www.freetype.org/freetype2/docs/reference/ft2-index.html

這里有兩個結構去描述

位圖描述

  typedef struct  FT_Bitmap_
  {
    unsigned int    rows;	
    unsigned int    width;	
    int             pitch;	
    unsigned char*  buffer;
    unsigned short  num_grays;
    unsigned char   pixel_mode;
    unsigned char   palette_mode;
    void*           palette;

  } FT_Bitmap;

位圖的定位點描述在字形槽里

  //字形槽
  typedef struct  FT_GlyphSlotRec_
  {
    FT_Library        library;
    FT_Face           face;
    FT_GlyphSlot      next;
    FT_UInt           reserved;       /* retained for binary compatibility */
    FT_Generic        generic;

    FT_Glyph_Metrics  metrics;
    FT_Fixed          linearHoriAdvance;
    FT_Fixed          linearVertAdvance;
    FT_Vector         advance;				//下個邊界的原點

    FT_Glyph_Format   format;

    FT_Bitmap         bitmap;				//位圖的描述
    FT_Int            bitmap_left;			//位圖的左上角點
    FT_Int            bitmap_top;			//位圖的左上角點

    FT_Outline        outline;

    FT_UInt           num_subglyphs;
    FT_SubGlyph       subglyphs;

    void*             control_data;
    long              control_len;

    FT_Pos            lsb_delta;
    FT_Pos            rsb_delta;

    void*             other;

    FT_Slot_Internal  internal;

  } FT_GlyphSlotRec;

位置的邊界需要去手動獲取

這里的參數是FT_Glyph glyph,可以由face中的槽來轉換

//從face的字形槽中取得字形
//FT_EXPORT( FT_Error )FT_Get_Glyph( FT_GlyphSlot  slot,FT_Glyph     *aglyph );
//字形描述
  typedef struct  FT_GlyphRec_
  {
    FT_Library             library;
    const FT_Glyph_Class*  clazz;
    FT_Glyph_Format        format;
    FT_Vector              advance;

  } FT_GlyphRec;
error = FT_Get_Glyph( face->glyph, &glyph );

//從字形中取得bbox邊界
FT_Glyph_Get_CBox( glyph, FT_GLYPH_BBOX_TRUNCATE, &bbox );
  FT_EXPORT( void )
  FT_Glyph_Get_CBox( FT_Glyph  glyph,
                     FT_UInt   bbox_mode,
                     FT_BBox  *acbox );

//傳入參數
  typedef struct  FT_GlyphRec_
  {
    FT_Library             library;
    const FT_Glyph_Class*  clazz;
    FT_Glyph_Format        format;
    FT_Vector              advance;

  } FT_GlyphRec;
// 傳出參數
  typedef struct  FT_BBox_
  {
    FT_Pos  xMin, yMin;
    FT_Pos  xMax, yMax;

  } FT_BBox;

字體抽象

剛開始我想抽象出位圖信息

長 
寬 
每個像素的bpp 
換行像素位置 
位圖數據地址

那么除非我自己去控制字距,同時需要統計這一行的高度,來確定下一行文字的位置,但是這可能會排版成擁擠的上對齊,或者手動計算位圖的大小,去布局,比如先設計一個32*32的邊界,然后根據這個位圖的大小居中擺放…想想就麻煩,而且這樣的話設計字體旋轉就沒轍了

mark

再仔細看下freetype的布局,其實是創建了一個布局,接着再看下旋轉,我們實際刷新數據的時候,一般還是從左到右,從上到下刷新點,沒有顏色的數據應該不去刷新,我們看下之前的字體旋轉,可以發現是遮擋了的,所以遇到沒有顏色的數據,應該去跳過這些點,而不是去繪圖.

藍色框是點陣圖,我們刷新像素的位置

紅色框是邊界,用來描述布局的

mark

我們之前的繪圖是這樣的

void draw_bitmap( FT_Bitmap*  bitmap,
             FT_Int      x,
             FT_Int      y)
{
  FT_Int  i, j, p, q;
  FT_Int  x_max = x + bitmap->width;
  FT_Int  y_max = y + bitmap->rows;
  for ( i = x, p = 0; i < x_max; i++, p++ )
  {
    for ( j = y, q = 0; j < y_max; j++, q++ )
    {
      if ( i < 0      || j < 0       ||
           i >= var.xres || j >= var.yres )
        continue;
		
      // 添加下面這句話即可  
      // if(bitmap->buffer[q * bitmap->width + p])
      lcd_put_pixel(i,j,bitmap->buffer[q * bitmap->width + p]);
    }
  }
}

這里對所有點都進行重繪,所以理論上應該會有字符的遮蓋,上一節的實驗也確實如此,可以看到h會把a遮擋了

mark

修改下代碼,判斷如果沒有顏色,則不需要描點即可,這里可以設置freetype的bpp是1即可,具體字體的顏色另外繪圖指定即可.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM