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功能已经非常强大,完全没有必要再“重复造轮子”了,但博主还是觉 ...
随机推荐
- 导入转储文件的时候:Error Code: 1406. Data too long for column - MySQL
MySQL will truncate any insert value that exceeds the specified column width. to make this without e ...
- vue-cli 脚手架搭建
1,下载node.js node.js 集成npm 管理器 2,打开命令行工具(win+R) node -v npm -v 出现对应版本号,则安装完成 3,配置代理信息 详见代理设定:https:// ...
- Redis入门——安装与基本命令
1. Redis安装 下载地址:https://github.com/MSOpenTech/redis/releases 下载zip文件后直接解压 2. 启动Redis服务端 解压目录下执行redis ...
- highchart 柱状图 分组样例
var chart = Highcharts.chart('container',{ chart: { type: 'column' }, title: { text: '月平均降雨量' }, sub ...
- Qt介绍1---QPA(Qt Platform Abstraction)
Qt是一个夸平台的库(一直宣称“Qt everywhere”),但是Qt底层不是夸平台的.比如:Qt中Gui部件的核心类QWidget,该类除了qwidget.h 和 qwidget.cpp两个原文件 ...
- AtCoder Beginner Contest 044 A - 高橋君とホテルイージー / Tak and Hotels (ABC Edit)
Time limit : 2sec / Memory limit : 256MB Score : 100 points Problem Statement There is a hotel with ...
- P2800 又上锁妖塔
P2800 又上锁妖塔 [温馨提示]使用仙术时飞过一层塔不花费时间,若爬过去,该层有多高,就要花费多长时间 我们可以用 f [ i ] 表示到达第 i 层时所用最短时间 到达第 i 层可 ...
- kubernetes install for centos
官方的文档写的很清楚 https://kubernetes.io/docs/getting-started-guides/centos/centos_manual_config/ 如果已经安装过doc ...
- node 读取多个文件、合并多个文件、读写多个文件
一.读取文件 1.找文件中匹配的内容 let fs = require('fs') let content = fs.readFileSync('/Users/**/desktop/Test.txt' ...
- webpack 创建vue项目过程中遇到的问题和解决方法
目录 1 webpack简介 2 webpack实现多个输入输出多个html 3 webpack 中的module下rules 下的use和loader选项 4 webpack 文件更新,如何使页面 ...