⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 step2.html

📁 嵌入式freetype库的应用文档包含freetype的简要说明和应用example
💻 HTML
📖 第 1 页 / 共 4 页
字号:
      described in a previous chapter.  It is a enumeration that indicates      how the kerning distances are expressed in the target vector.</p>      <p>The default value is <tt>FT_KERNING_DEFAULT</tt> which has      value&nbsp;0.  It corresponds to kerning distances expressed in 26.6      grid-fitted pixels (which means that the values are multiples of 64).       For scalable formats, this means that the design kerning distance is      scaled, then rounded.</p>      <p>The value <tt>FT_KERNING_UNFITTED</tt> corresponds to kerning      distances expressed in 26.6 unfitted pixels (i.e., that do not      correspond to integer coordinates).  It is the design kerning distance      that is scaled without rounding.</p>      <p>Finally, the value <tt>FT_KERNING_UNSCALED</tt> is used to return      the design kerning distance, expressed in font units.  You can later      scale it to the device space using the computations explained in the      last chapter of this section.</p>      <p>Note that the &lsquo;left&rsquo; and &lsquo;right&rsquo; positions      correspond to the <em>visual order</em> of the glyphs in the string of      text.  This is important for bidirectional text, or simply when      writing right-to-left text.</p>    <hr>    <h3>      4.&nbsp;Simple text rendering: kerning + centering    </h3>    <p>In order to show off what we just learned, we will now demonstrate    how to modify the example code that was provided in section&nbsp;I to    render a string of text, and enhance it to support kerning and delayed    rendering.</p>      <h4>       a.&nbsp;Kerning support      </h4>      <p>Adding support for kerning to our code is trivial, as long as we      consider that we are still dealing with a left-to-right script like      Latin.  We simply need to retrieve the kerning distance between two      glyphs in order to alter the pen position appropriately.  The code      looks like:</p>      <div class="pre">  FT_GlyphSlot  slot = face-&gt;glyph;  <span class="comment">/* a small shortcut */</span>      FT_UInt       glyph_index;  FT_Bool       use_kerning;  FT_UInt       previous;  int           pen_x, pen_y, n;  ... initialize library ...  ... create face object ...  ... set character size ...  pen_x = 300;  pen_y = 200;  use_kerning = FT_HAS_KERNING( face );  previous    = 0;  for ( n = 0; n &lt; num_chars; n++ )  {    <span class="comment">/* convert character code to glyph index */</span>        glyph_index = FT_Get_Char_Index( face, text[n] );    <span class="comment">/* retrieve kerning distance and move pen position */</span>        if ( use_kerning &amp;&amp; previous &amp;&amp; glyph_index )    {      FT_Vector  delta;      FT_Get_Kerning( face, previous, glyph_index,                      ft_kerning_mode_default, &amp;delta );      pen_x += delta.x &gt;&gt; 6;    }    <span class="comment">/* load glyph image into the slot (erase previous one) */</span>        error = FT_Load_Glyph( face, glyph_index, FT_LOAD_RENDER );    if ( error )      continue;  <span class="comment">/* ignore errors */</span>        <span class="comment">/* now draw to our target surface */</span>        my_draw_bitmap( &amp;slot-&gt;bitmap,                    pen_x + slot-&gt;bitmap_left,                    pen_y - slot-&gt;bitmap_top );    <span class="comment">/* increment pen position */</span>        pen_x += slot->advance.x &gt;&gt; 6;    <span class="comment">/* record current glyph index */</span>        previous = glyph_index;  }      </div>      <p>We are done.  Some notes:</p>      <ul>        <li>          <p>As kerning is determined from glyph indices, we need to          explicitely convert our character codes into a glyph indices, then          later call <tt>FT_Load_Glyph</tt> instead of          <tt>FT_Load_Char</tt>.</p>        </li>        <li>          <p>We use a boolean named <tt>use_kerning</tt> which is set with          the result of the macro <tt>FT_HAS_KERNING</tt>.  It is certainly          faster not to call <tt>FT_Get_Kerning</tt> when we know that the          font face does not contain kerning information.</p>        </li>       <li>          <p>We move the position of the pen <em>before</em> a new glyph is          drawn.</p>        </li>       <li>          <p>We initialize the variable <tt>previous</tt> with the          value&nbsp;0, which always corresponds to the &lsquo;missing          glyph&rsquo; (also called <tt>.notdef</tt> in the Postscript          world).  There is never any kerning distance associated with this          glyph.</p>        </li>        <li>          <p>We do not check the error code returned by          <tt>FT_Get_Kerning</tt>.  This is because the function always sets          the content of <tt>delta</tt> to (0,0) when an error occurs.</p>        </li>      </ul>      <h4>        b.&nbsp;Centering      </h4>      <p>Our code begins to become interesting but it is still a bit too      simple for normal use.  For example, the position of the pen is      determined before we do the rendering; normally, you would rather      layout the text and measure it before computing its final position      (centering, etc.) or perform things like word-wrapping.</p>      <p>Let us now decompose our text rendering function into two distinct      but successive parts: The first one will position individual glyph      images on the baseline, while the second one will render the glyphs.       As we will see, this has many advantages.</p>      <p>We will thus start by storing individual glyph images, as well as      their position on the baseline.  This can be done with code like:</p>      <div class="pre">  FT_GlyphSlot  slot = face-&gt;glyph;   <span class="comment">/* a small shortcut */</span>      FT_UInt       glyph_index;  FT_Bool       use_kerning;  FT_UInt       previous;  int           pen_x, pen_y, n;  FT_Glyph      glyphs[MAX_GLYPHS];   <span class="comment">/* glyph image    */</span>      FT_Vector     pos   [MAX_GLYPHS];   <span class="comment">/* glyph position */</span>      FT_UInt       num_glyphs;  ... initialize library ...  ... create face object ...  ... set character size ...  pen_x = 0;   <span class="comment">/* start at (0,0) */</span>      pen_y = 0;  num_glyphs  = 0;  use_kerning = FT_HAS_KERNING( face );  previous    = 0;  for ( n = 0; n &lt; num_chars; n++ )  {    <span class="comment">/* convert character code to glyph index */</span>        glyph_index = FT_Get_Char_Index( face, text[n] );    <span class="comment">/* retrieve kerning distance and move pen position */</span>        if ( use_kerning &amp;&amp; previous &amp;&amp; glyph_index )    {      FT_Vector  delta;      FT_Get_Kerning( face, previous, glyph_index,                      FT_KERNING_DEFAULT, &amp;delta );      pen_x += delta.x &gt;&gt; 6;    }    <span class="comment">/* store current pen position */</span>        pos[num_glyphs].x = pen_x;    pos[num_glyphs].y = pen_y;    <span class="comment">/* load glyph image into the slot without rendering */</span>        error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT );    if ( error )      continue;  <span class="comment">/* ignore errors, jump to next glyph */</span>        <span class="comment">/* extract glyph image and store it in our table */</span>        error = FT_Get_Glyph( face-&gt;glyph, &amp;glyphs[num_glyphs] );    if ( error )      continue;  <span class="comment">/* ignore errors, jump to next glyph */</span>        <span class="comment">/* increment pen position */</span>        pen_x += slot->advance.x &gt;&gt; 6;    <span class="comment">/* record current glyph index */</span>        previous = glyph_index;    <span class="comment">/* increment number of glyphs */</span>        num_glyphs++;  }      </div>      <p>This is a very slight variation of our previous code where we      extract each glyph image from the slot, and store it, along with the      corresponding position, in our tables.</p>      <p>Note also that <tt>pen_x</tt> contains the total advance for the      string of text.  We can now compute the bounding box of the text      string with a simple function like:</p>      <div class="pre">  void  compute_string_bbox( FT_BBox  *abbox )  {    FT_BBox  bbox;    <span class="comment">/* initialize string bbox to "empty" values */</span>        bbox.xMin = bbox.yMin =  32000;    bbox.xMax = bbox.yMax = -32000;    <span class="comment">/* for each glyph image, compute its bounding box, */</span>        <span class="comment">/* translate it, and grow the string bbox          */</span>        for ( n = 0; n &lt; num_glyphs; n++ )    {      FT_BBox  glyph_bbox;      FT_Glyph_Get_CBox( glyphs[n], ft_glyph_bbox_pixels,                         &amp;glyph_bbox );      glyph_bbox.xMin += pos[n].x;      glyph_bbox.xMax += pos[n].x;      glyph_bbox.yMin += pos[n].y;      glyph_bbox.yMax += pos[n].y;      if ( glyph_bbox.xMin &lt; bbox.xMin )        bbox.xMin = glyph_bbox.xMin;      if ( glyph_bbox.yMin &lt; bbox.yMin )        bbox.yMin = glyph_bbox.yMin;      if ( glyph_bbox.xMax &gt; bbox.xMax )        bbox.xMax = glyph_bbox.xMax;      if ( glyph_bbox.yMax &gt; bbox.yMax )        bbox.yMax = glyph_bbox.yMax;    }    <span class="comment">/* check that we really grew the string bbox */</span>        if ( bbox.xMin &gt; bbox.xMax )    {      bbox.xMin = 0;      bbox.yMin = 0;      bbox.xMax = 0;      bbox.yMax = 0;    }    <span class="comment">/* return string bbox */</span>            *abbox = bbox;  }      </div>      <p>The resulting bounding box dimensions are expressed in integer      pixels and can then be used to compute the final pen position before      rendering the string as in:</p>      <div class="pre">  <span class="comment">/* compute string dimensions in integer pixels */</span>      string_width  = string_bbox.xMax - string_bbox.xMin;  string_height = string_bbox.yMax - string_bbox.yMin;  <span class="comment">/* compute start pen position in 26.6 cartesian pixels */</span>      start_x = ( ( my_target_width  - string_width  ) / 2 ) * 64;  start_y = ( ( my_target_height - string_height ) / 2 ) * 64;  for ( n = 0; n &lt; num_glyphs; n++ )  {    FT_Glyph   image;    FT_Vector  pen;    image = glyphs[n];    pen.x = start_x + pos[n].x;    pen.y = start_y + pos[n].y;    error = FT_Glyph_To_Bitmap( &amp;image, FT_RENDER_MODE_NORMAL,                                &amp;pen, 0 );    if ( !error )    {      FT_BitmapGlyph  bit = (FT_BitmapGlyph)image;      my_draw_bitmap( bit-&gt;bitmap,                      bit-&gt;left,                      my_target_height - bit-&gt;top );      FT_Done_Glyph( image );    }  }      </div>      <p>Some remarks:</p>      <ul>        <li>          <p>The pen position is expressed in the cartesian space (i.e.,          y&nbsp;upwards).</p>        </li>        <li>          <p>We call <tt>FT_Glyph_To_Bitmap</tt> with the <tt>destroy</tt>          parameter set to&nbsp;0 (false), in order to avoid destroying the          original glyph image.  The new glyph bitmap is accessed through          <tt>image</tt> after the call and is typecasted to          <tt>FT_BitmapGlyph</tt>.</p>        </li>        <li>          <p>We use translation when calling <tt>FT_Glyph_To_Bitmap</tt>.           This ensures that the <tt>left</tt> and <tt>top</tt> fields of the          bitmap glyph object are already set to the correct pixel          coordinates in the cartesian space.</p>        </li>        <li>          <p>Of course, we still need to convert pixel coordinates from          cartesian to device space before rendering, hence the          <tt>my_target_height - bitmap->top</tt> in the call to          <tt>my_draw_bitmap</tt>.</p>        </li>      </ul>      <p>The same loop can be used to render the string anywhere on our      display surface, without the need to reload our glyph images each      time.  We could also decide to implement word wrapping, and only      draw</p>    <hr>    <h3>      5.&nbsp;Advanced text rendering: transformation + centering + kerning    </h3>    <p>We are now going to modify our code in order to be able to easily    transform the rendered string, for example to rotate it.  We will start    by performing a few minor improvements:</p>      <h4>        a.&nbsp;packing &amp; translating glyphs      </h4>      <p>We start by packing the information related to a single glyph image      into a single structure instead of parallel arrays.  We thus define      the following structure type:</p>      <div class="pre">  typedef struct  TGlyph_  {    FT_UInt    index;  <span class="comment">/* glyph index                  */</span>        FT_Vector  pos;    <span class="comment">/* glyph origin on the baseline */</span>        FT_Glyph   image;  <span class="comment">/* glyph image                  */</span>      } TGlyph, *PGlyph;      </div>      <p>We also translate each glyph image directly after it is loaded to      its position on the baseline at load time.  As we will see, this as      several advantages.  Our glyph sequence loader thus becomes:</p>      <div class="pre">  FT_GlyphSlot  slot = face-&gt;glyph;  <span class="comment">/* a small shortcut */</span>      FT_UInt       glyph_index;  FT_Bool       use_kerning;  FT_UInt       previous;  int           pen_x, pen_y, n;  TGlyph        glyphs[MAX_GLYPHS];  <span class="comment">/* glyphs table */</span>      PGlyph        glyph;               <span class="comment">/* current glyph in table */</span>      FT_UInt       num_glyphs;  ... initialize library ...  ... create face object ...  ... set character size ...  pen_x = 0;   <span class="comment">/* start at (0,0) */</span>      pen_y = 0;  num_glyphs  = 0;  use_kerning = FT_HAS_KERNING( face );  previous    = 0;  glyph = glyphs;  for ( n = 0; n &lt; num_chars; n++ )  {    glyph-&gt;index = FT_Get_Char_Index( face, text[n] );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -