FireMonkey 源码学习(5)

(5)UpdateCharRec

该函数的源码分析如下:

procedure TTextLayoutNG.UpdateCharRec(const ACanvas: TCanvas; NeedBitmap: Boolean; var NewRec: PCharRec;
  HasItem: Boolean; const CharDic: TCharDic; const AFont: TFont; const Ch: UCS4Char; const NeedPath: Boolean = False);
var
  Map: TBitmapData;
  J: Integer;
  Bitmap: TBitmap;
  LFont: TFont;
  GlyphSettings: TFontGlyphSettings;
begin
  {
    新建一个记录,或释放原记录中的图形对象
  }
  if not HasItem then
    New(NewRec)
  else
  begin
    FreeAndNil(NewRec.Glyph);
    FreeAndNil(NewRec.Bitmap);
  end;
  
  {
    如果指定了字体则使用之,否则使用缺省字体
  }
  if not Assigned(AFont) then
    LFont := Self.Font
  else
    LFont := AFont;

  {
    使用Bitmap形式存储,或使用Path存储渲染过程
  }
  GlyphSettings := [];
  if NeedBitmap then
    GlyphSettings := [TFontGlyphSetting.Bitmap, TFontGlyphSetting.PremultipliedAlpha];
  if NeedPath then
    GlyphSettings := GlyphSettings + [TFontGlyphSetting.Path];

  {
    在TFontGlyphManager中使用当前的FontGlyph生成缺省图形
  }
  NewRec.Glyph := TFontGlyphManager.Current.GetGlyph(Ch, LFont, FScale, GlyphSettings);
  {
    计算基准线的位置
  }
  CharDic.Baseline := TFontGlyphManager.Current.GetBaseline(LFont, FScale);

  {
    如果采用图形模式,则生成之
  }
  if not (TFontGlyphStyle.NoGlyph in NewRec.Glyph.Style) and Assigned(NewRec.Glyph.Bitmap) and (NewRec.Glyph.Bitmap.Width > 0) and (NewRec.Glyph.Bitmap.Height > 0) then
  begin
    {
      采用图形渲染模式,生成Bitmap
    }
    if FRendering > 0 then
    begin
      Bitmap := TBitmap.Create(NewRec.Glyph.Bitmap.Width + AntiAliasMargin * 2, NewRec.Glyph.Bitmap.Height + AntiAliasMargin * 2);
      Bitmap.BitmapScale := FScale;
      {
        将Glyph中的图形复制到Bitmap中
      }
      if Bitmap.Map(TMapAccess.Write, Map) then
      try
        FillChar(Map.Data^, Map.Pitch * Map.Height, 0);
        NewRec.Bitmap := Bitmap;
        NewRec.SrcRect := RectF(0, 0, NewRec.Glyph.Bitmap.Width, NewRec.Glyph.Bitmap.Height);
        NewRec.SrcRect.Offset(AntiAliasMargin, AntiAliasMargin);
for J := 0 to NewRec.Glyph.Bitmap.Height - 1 do
          Move(NewRec.Glyph.Bitmap.Scanline[J]^, Map.GetPixelAddr(AntiAliasMargin, J + AntiAliasMargin)^, NewRec.Glyph.Bitmap.Pitch);
      finally
        Bitmap.Unmap(Map);
      end;
      {
        构建图形列表,并将其放入
      }
      if not Assigned(FNewGlyphList) then
        FNewGlyphList := TList<PCharRec>.Create;
      FNewGlyphList.Add(NewRec);
    end
    else
      {
        直接将Glyph映射到Bitmap中
      }
      MapGlyphToCache(NewRec);
  end
  else
  {
    采用Path模式
  }
  begin
    NewRec.Bitmap := nil;
    NewRec.SrcRect := RectF(0, 0, 0, 0);
  end;
  
  {
    加入到列表中
  }
  if not HasItem then
    CharDic.Add(Ch, NewRec);
end;

其中2个重要的函数是:

TFontGlyphManager.Current.GetGlyph

TFontGlyphManager.Current.GetBaseline

posted @ 2014-06-17 22:06  玻璃城市  阅读(1069)  评论(0编辑  收藏  举报