zoukankan      html  css  js  c++  java
  • FireMonkey 源码学习(6)

    (6)GetGlyph和GetBaseline

    TFontGlyphManager是一个抽象类,在不同平台上的实现是不同的,以Windows为例,在FMX.FontGlyphs.Win.pas文件中定义了:

    TWinFontGlyphManager = class(TFontGlyphManager)
       ...
      protected
        function DoGetGlyph(const Char: UCS4Char; const Settings: TFontGlyphSettings): TFontGlyph; override;
        function DoGetBaseline: Single; override;
      ...

    DoGetGlyph的实现代码如下:

    function TWinFontGlyphManager.DoGetGlyph(const Char: UCS4Char; const Settings: TFontGlyphSettings): TFontGlyph;
    var
      CharsString: string;
      Abc: TABCFLOAT;
      CharSize: TSize;
      GlyphRect: TRect;
      I, J: Integer;
      C: Byte;
      Color: TAlphaColorRec;
      GlyphStyle: TFontGlyphStyles;
      Bitmap: TWinBitmap;
    begin
      {
        获取字符在画布上的宽度和高度
      }
      CharsString := System.Char.ConvertFromUtf32(Char);
      GetTextExtentPoint32W(FMeasureBitmap.DC, CharsString, 1, CharSize);
      GetCharABCWidthsFloat(FMeasureBitmap.DC, Char, Char, Abc);
    
      {
        采用Bitmap模式
      }
      if TFontGlyphSetting.Bitmap in Settings then
      begin
        {
          构建Bitmap
        }
        Bitmap := CreateBitmap(Max(Ceil(Abs(Abc.abcfA) + Abs(Abc.abcfB) + Abs(Abc.abcfC)), CharSize.cx), CharSize.cy);
        FillLongword(Bitmap.Bits, Bitmap.Width * Bitmap.Height, TAlphaColorRec.White);
    
        {
          设置颜色
        }
        SetTextColor(Bitmap.DC, RGB(0, 0, 0));
        SetBkColor(Bitmap.DC, RGB(255, 255, 255));
    
        {
           设置文字对齐方式
        }
        SetTextAlign(Bitmap.DC, TA_TOP);
        {
           将字符绘制在Bitmap的画布上
        }
        SelectObject(Bitmap.DC, FFont);
        TextOut(Bitmap.DC, -Trunc(Abc.abcfA), 0, @Char, 1);
    
        {
          找到最小的,不透明的位置
        }
        GlyphRect := TRect.Create(Bitmap.Width, CharSize.cy, 0, 0);
        for I := 0 to Bitmap.Width - 1 do
          for J := 0 to CharSize.cy - 1 do
          begin
            C := Bitmap.Bits[J * Bitmap.Width + I].R;
            if C > 0 then
            begin
              if J < GlyphRect.Top then
                GlyphRect.Top := J;
              if I < GlyphRect.Left then
                GlyphRect.Left := I;
            end;
          end;
        for I := Bitmap.Width - 1 downto GlyphRect.Left do
          for J := CharSize.cy - 1 downto GlyphRect.Top do
          begin
            C := Bitmap.Bits[J * Bitmap.Width + I].R;
            if C > 0 then
            begin
              if J > GlyphRect.Bottom then
                GlyphRect.Bottom := J;
              if I > GlyphRect.Right then
                GlyphRect.Right := I;
            end;
          end;
        GlyphRect.Left := Min(CharSize.cx, GlyphRect.Left);
        GlyphRect.Top := Min(CharSize.cy, GlyphRect.Top);
        GlyphRect.Right := Max(CharSize.cx, GlyphRect.Right + 1);
        GlyphRect.Bottom := Max(CharSize.cy, GlyphRect.Bottom + 1);
      end;
    
      {
        判断是否存在Glyph
      }
      GlyphStyle := [];
      if not HasGlyph(Char) then
        GlyphStyle := [TFontGlyphStyle.NoGlyph];
    
      {
        构建该字体下、该字符的Glyph
      }
      Result := TFontGlyph.Create(TPoint.Create(GlyphRect.Left + Trunc(Abc.abcfA), GlyphRect.Top),
        Abc.abcfA + Abc.abcfB + Abc.abcfC, CharSize.Height, GlyphStyle);
    
      {
        Bitmap模式下,将Glyph复制到Bitmap
      }
      if TFontGlyphSetting.Bitmap in Settings then
      begin
        Result.Bitmap.SetSize(Max(GlyphRect.Width, GlyphRect.Right), GlyphRect.Height, TPixelFormat.BGRA);
    
        for I := GlyphRect.Left to GlyphRect.Right - 1 do
          for J := GlyphRect.Top to GlyphRect.Bottom - 1 do
          begin
            Color := Bitmap.Bits[J * Bitmap.Width + I];
            if Color.R < 255 then
            begin
              { Faster integer variant of formula:
                Result = R * 0.2126 + G * 0.7152 + B * 0.0722 }
              C := 255 - ((Integer(Color.R * 54) + Integer(Color.G * 183) + Integer(Color.B * 19)) div 256);
              if TFontGlyphSetting.PremultipliedAlpha in Settings then
                Result.Bitmap.Pixels[I - GlyphRect.Left, J - GlyphRect.Top] := MakeColor(C, C, C, C)
              else
                Result.Bitmap.Pixels[I - GlyphRect.Left, J - GlyphRect.Top] := MakeColor($FF, $FF, $FF, C);
            end;
          end;
        DestroyBitmap(Bitmap);
      end;
    end;

    DoGetBaseline的实现代码直接返回了FBaseline的值,FBaseline是在载入资源时生成,其核心函数为LoadResource,代码分析如下:

    procedure TWinFontGlyphManager.LoadResource;
    var
      Height: Integer;
      dwBold, dwItalic: Cardinal;
      Metrics: TTextMetric;
    begin
      {
        字体高度、Style属性等
      }
      Height := -Round(CurrentSettings.Size * CurrentSettings.Scale);
      if TFontStyle.fsBold in CurrentSettings.Style then
        dwBold := FW_BOLD
      else
        dwBold := FW_NORMAL;
      if TFontStyle.fsItalic in CurrentSettings.Style then
        dwItalic := 1
      else
        dwItalic := 0;
      {
        Windows的API创建Font
      }
      FFont := CreateFont(Height, 0, 0, 0, dwBold, dwItalic,
        0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
        CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
        DEFAULT_PITCH or FF_DONTCARE, PChar(CurrentSettings.Family));
      if FFont = 0 then
        Exit;
      SelectObject(FMeasureBitmap.DC, FFont);
      {
        获取画布的字体各种信息,其中Metrics的定义如下:    
      tagTEXTMETRICW = record
        tmHeight: Longint;
        tmAscent: Longint;   //Specifies the ascent (units above the base line) of characters. 
        tmDescent: Longint;
        tmInternalLeading: Longint;
        tmExternalLeading: Longint;
        tmAveCharWidth: Longint;
        tmMaxCharWidth: Longint;
        tmWeight: Longint;
        tmOverhang: Longint;
        tmDigitizedAspectX: Longint;
        tmDigitizedAspectY: Longint;
        tmFirstChar: WideChar;
        tmLastChar: WideChar;
        tmDefaultChar: WideChar;
        tmBreakChar: WideChar;
        tmItalic: Byte;
        tmUnderlined: Byte;
        tmStruckOut: Byte;
        tmPitchAndFamily: Byte;
        tmCharSet: Byte;
      end;
      }
      GetTextMetrics(FMeasureBitmap.DC, Metrics);
      FBaseline := Metrics.tmAscent;
    end;
  • 相关阅读:
    Mali 水题
    树状数组求区间最值
    POJ1125 Stockbroker Grapevine 最短路
    jquery radio取值,checkbox取值,select取值 及选中(引用)
    过滤注入代码的存储过程
    怎么进行项目管理
    现在已经不喜欢注释而喜欢直接看代码了
    风潮唱片总目录及下载地址2009年2月9日更新
    什么时候用存储过程
    sql server 外键 更新(删除)规则
  • 原文地址:https://www.cnblogs.com/ChinaEHR/p/3793632.html
Copyright © 2011-2022 走看看