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, , 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)的更多相关文章
- FireMonkey 源码学习(5)
(5)UpdateCharRec 该函数的源码分析如下: procedure TTextLayoutNG.UpdateCharRec(const ACanvas: TCanvas; NeedBitma ...
- FireMonkey 源码学习(1)
FireMonkey采用了与VCL不同的机制,很多基础类已经重新编写了,好在一如既往地提供了源代码,故此有机会学习一下. 一.图形引擎 FireMonkey采用了纯图形化技术解决可视化控件,而不是使用 ...
- FireMonkey 源码学习(3)
五.TTextLayoutNG 在FMX.TextLayout.GPU.pas文件中,实现了几个基础功能,其中: (1)渲染单元 在TextLayout中,每一批同字体和颜色的1~n个字符,组成一个最 ...
- FireMonkey 源码学习(2)
三.TControl FireMonkey重写了TControl的代码,实现了众多接口,如下图: 基类上实现了众多功能,这里不详细描述. 四.TEdit 编辑框是从TControl—TStyledCo ...
- FireMonkey 源码学习(4)
(4)DoDrawLayout DoDrawLayout函数的源代码分析如下: procedure TTextLayoutNG.DoDrawLayout(const ACanvas: TCanvas) ...
- Java集合专题总结(1):HashMap 和 HashTable 源码学习和面试总结
2017年的秋招彻底结束了,感觉Java上面的最常见的集合相关的问题就是hash--系列和一些常用并发集合和队列,堆等结合算法一起考察,不完全统计,本人经历:先后百度.唯品会.58同城.新浪微博.趣分 ...
- jQuery源码学习感想
还记得去年(2015)九月份的时候,作为一个大四的学生去参加美团霸面,结果被美团技术总监教育了一番,那次问了我很多jQuery源码的知识点,以前虽然喜欢研究框架,但水平还不足够来研究jQuery源码, ...
- MVC系列——MVC源码学习:打造自己的MVC框架(四:了解神奇的视图引擎)
前言:通过之前的三篇介绍,我们基本上完成了从请求发出到路由匹配.再到控制器的激活,再到Action的执行这些个过程.今天还是趁热打铁,将我们的View也来完善下,也让整个系列相对完整,博主不希望烂尾. ...
- MVC系列——MVC源码学习:打造自己的MVC框架(三:自定义路由规则)
前言:上篇介绍了下自己的MVC框架前两个版本,经过两天的整理,版本三基本已经完成,今天还是发出来供大家参考和学习.虽然微软的Routing功能已经非常强大,完全没有必要再“重复造轮子”了,但博主还是觉 ...
随机推荐
- c#除掉字符串最后一个字符几种方法
有一数组:转换为字符串后为 aaa|bbb|ccc|ddd| 现要去掉最后一个| 第一种方法: 语句为:str1=aaa|bbb|ccc|ddd| str=str1.substring(0,lasti ...
- Oil Deposits HDU 1241
The GeoSurvComp geologic survey company is responsible for detecting underground oil deposits. GeoSu ...
- GBDT:梯度提升决策树
http://www.jianshu.com/p/005a4e6ac775 综述 GBDT(Gradient Boosting Decision Tree) 又叫 MART(Multiple Ad ...
- 即时通讯(I)
网络通讯三要素: 网络七层协议划分: 网络五层协议的划分: 要记网络层的5层协议,可以把它想像为一枚洋葱.学过计算机网络的,看到这个网络协议的套接字,大概就会明白了!它是一层一层的进行包裹的,然后交由 ...
- quick player no exit
QuickXDev插件自动升级后player no exist 昨晚上QuickXDev插件运行还ok,今天打开电脑启动sublime text2后,右键run with player提示player ...
- kalinux 换源
1.系统使用第一步建议先换源,否则将出现很多未知问题 #以下两个2选1,打开要编辑的源 sudo leafpad /etc/apt/sources.list sudo gedit /etc/apt/s ...
- python 序列化,反序列化
附: pickle 有大量的配置选项和一些棘手的问题.对于最常见的使用场景,你不需要去担心这个,是如果你要在一个重要的程序中使用pickle 去做序列化的话,最好去查阅一下官方文档. https:// ...
- Linux Shell入门
转自:http://www.mamicode.com/info-detail-605431.html
- hive 常见时间日期函数的使用
1.时间戳函数 日期转时间戳:从1970-01-01 00:00:00 UTC到指定时间的秒数 获得当前时区的UNIX时间戳: select unix_timestamp(); 1533716607 ...
- jquery操作节点
var v= $("input[type='checkbox'][name='ids']:checked").closest('tr').find('td:eq(2)').map( ...