(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, , 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(, , ));
SetBkColor(Bitmap.DC, RGB(, , )); {
设置文字对齐方式
}
SetTextAlign(Bitmap.DC, TA_TOP);
{
将字符绘制在Bitmap的画布上
}
SelectObject(Bitmap.DC, FFont);
TextOut(Bitmap.DC, -Trunc(Abc.abcfA), , @Char, ); {
找到最小的,不透明的位置
}
GlyphRect := TRect.Create(Bitmap.Width, CharSize.cy, , );
for I := to Bitmap.Width - do
for J := to CharSize.cy - do
begin
C := Bitmap.Bits[J * Bitmap.Width + I].R;
if C > then
begin
if J < GlyphRect.Top then
GlyphRect.Top := J;
if I < GlyphRect.Left then
GlyphRect.Left := I;
end;
end;
for I := Bitmap.Width - downto GlyphRect.Left do
for J := CharSize.cy - downto GlyphRect.Top do
begin
C := Bitmap.Bits[J * Bitmap.Width + I].R;
if C > 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 + );
GlyphRect.Bottom := Max(CharSize.cy, GlyphRect.Bottom + );
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 - do
for J := GlyphRect.Top to GlyphRect.Bottom - do
begin
Color := Bitmap.Bits[J * Bitmap.Width + I];
if Color.R < then
begin
{ Faster integer variant of formula:
Result = R * 0.2126 + G * 0.7152 + B * 0.0722 }
C := - ((Integer(Color.R * ) + Integer(Color.G * ) + Integer(Color.B * )) div );
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 :=
else
dwItalic := ;
{
Windows的API创建Font
}
FFont := CreateFont(Height, , , , dwBold, dwItalic,
, , DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
DEFAULT_PITCH or FF_DONTCARE, PChar(CurrentSettings.Family));
if FFont = 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;

FireMonkey 源码学习(6)的更多相关文章

  1. FireMonkey 源码学习(5)

    (5)UpdateCharRec 该函数的源码分析如下: procedure TTextLayoutNG.UpdateCharRec(const ACanvas: TCanvas; NeedBitma ...

  2. FireMonkey 源码学习(1)

    FireMonkey采用了与VCL不同的机制,很多基础类已经重新编写了,好在一如既往地提供了源代码,故此有机会学习一下. 一.图形引擎 FireMonkey采用了纯图形化技术解决可视化控件,而不是使用 ...

  3. FireMonkey 源码学习(3)

    五.TTextLayoutNG 在FMX.TextLayout.GPU.pas文件中,实现了几个基础功能,其中: (1)渲染单元 在TextLayout中,每一批同字体和颜色的1~n个字符,组成一个最 ...

  4. FireMonkey 源码学习(2)

    三.TControl FireMonkey重写了TControl的代码,实现了众多接口,如下图: 基类上实现了众多功能,这里不详细描述. 四.TEdit 编辑框是从TControl—TStyledCo ...

  5. FireMonkey 源码学习(4)

    (4)DoDrawLayout DoDrawLayout函数的源代码分析如下: procedure TTextLayoutNG.DoDrawLayout(const ACanvas: TCanvas) ...

  6. Java集合专题总结(1):HashMap 和 HashTable 源码学习和面试总结

    2017年的秋招彻底结束了,感觉Java上面的最常见的集合相关的问题就是hash--系列和一些常用并发集合和队列,堆等结合算法一起考察,不完全统计,本人经历:先后百度.唯品会.58同城.新浪微博.趣分 ...

  7. jQuery源码学习感想

    还记得去年(2015)九月份的时候,作为一个大四的学生去参加美团霸面,结果被美团技术总监教育了一番,那次问了我很多jQuery源码的知识点,以前虽然喜欢研究框架,但水平还不足够来研究jQuery源码, ...

  8. MVC系列——MVC源码学习:打造自己的MVC框架(四:了解神奇的视图引擎)

    前言:通过之前的三篇介绍,我们基本上完成了从请求发出到路由匹配.再到控制器的激活,再到Action的执行这些个过程.今天还是趁热打铁,将我们的View也来完善下,也让整个系列相对完整,博主不希望烂尾. ...

  9. MVC系列——MVC源码学习:打造自己的MVC框架(三:自定义路由规则)

    前言:上篇介绍了下自己的MVC框架前两个版本,经过两天的整理,版本三基本已经完成,今天还是发出来供大家参考和学习.虽然微软的Routing功能已经非常强大,完全没有必要再“重复造轮子”了,但博主还是觉 ...

随机推荐

  1. filename

    package com.enjoyor.soa.traffic.server.tms.controller; import java.io.BufferedReader;import java.io. ...

  2. DateTime.Compare(t1,t2)比较两个日期大小

    DateTime.Compare(t1,t2)比较两个日期大小,排前面的小,排在后面的大,比如:2011-2-1就小于2012-3-2返回值小于零:  t1 小于 t2. 返回值等于零 : t1 等于 ...

  3. URL List by Category

    URLs List AI https://www.cnblogs.com/zlel/p/8882129.html Javascript Promise http://liubin.org/promis ...

  4. Redis实现分布式Session

    相关博客: http://www.cnblogs.com/yanweidie/p/4763556.html http://www.cnblogs.com/lori/p/5368722.html?utm ...

  5. 导入javax.servlet。伺服登记无法解决:The import javax.servlet.MultipartConfigElement cannot be resolved

    解决办法:

  6. MyBatis学习笔记(二)——使用MyBatis对表执行CRUD操作

    转自孤傲苍狼的博客:http://www.cnblogs.com/xdp-gacl/p/4262895.html 上一篇博文MyBatis学习总结(一)——MyBatis快速入门中我们讲了如何使用My ...

  7. python 正则re.search

    re.search 扫描整个字符串并返回第一个成功的匹配. 上码: import re line = "Cats are smarter than dogs"; searchObj ...

  8. Axis2之异步调用

    本章主要介绍axis2接口的异步调用方式. 一般情况下,我们使用同步方法(invokeBlocking)调用axis2接口,如果被调用的WebService方法长时间不返回,客户端将一直被阻塞,直到该 ...

  9. 一篇关于蓝牙SDP和L2CAP协议的文章

    SDP地址:http://www.cnblogs.com/strive-forever/archive/2011/11/04/2236640.html L2CAP地址:http://www.cnblo ...

  10. 今天2.4寸tft触摸屏到手--刷屏驱动小结

    2010-04-29 21:28:00 根据给的51程序改成了iccavr,结果改错了2处.导致我找原因找了n久.不过也是一件好事,让我对80i更加熟悉了. 通过protues的逻辑分析仪,找到了问题 ...