Firemonkey’s abstract TCanvas class has been providing the dimensions of the bounding rectangle of some text on itself. On recent updates it has deprecated providing text rectangle directly in the canvas, in stead encouraged users to use TTextLayout abstract class which handles several text-based operations on the native context of the platforms. So it is possible to get the bounding rectangle of a string on any canvas. Is this enough? Though I am sure this class will improve to involve many new textual features, at current time it lacks some major needs of a developer who designs text drawing applications.

When words in different sizes aligned from top you can’t get a proper sentence view

For the first time, I have faced a feature lack when I saw even TMS’s HTML Text was unable to align words in an HTML notation that have got different sizes. Because having text rectangle is not enough to locate words in different sizes because of the missing baseline information. If you align the words from the top the smaller word’s baseline will be upper (as in the above image), if you align the bottoms the baseline will be lower, so to make a correct match you should know where are the baselines of each word exactly located. So we need to know the Ascent value of the text. If have got the ascent value, we can easily align the words on the baseline as seen on following image. For a complete information on typography see this article on Wikipedia.

For a proper drawing of words in different sizes you should align them on their baselines.

As seen on the above image, having the information of ascent values for each word we can align them properly on the baseline of the sentence. However FMX TTextLayout doesn’t provide this information. So I decided to add a new function to my PlatformExtensions unit to provide metrics information that are gathered from the drawing of that specific font in a specific size. The new function is GetTextMetrics and hast this following structure.

1
2
3
Class Procedure GetTextMetrics(Text:String; Font:TFont; var TextRect:TRectF;
                               var Ascent,Descent:Single;
                               var CapHeight,XHeight:Single);virtual;abstract;

Getting Text Metrics in Windows

Firemonkey uses two different context types on Windows platform that are Windows GDIP and Direct2D. The default one is Windows GDI plus context which is a set of device independent drawing API based on the old GDI. Because of its device independency GDIP lacks of some important drawing features such as XOR brush, but it is always possible to handle these extra operations by locking the context to device dependent HDC and doing things on the device bitmap. What I mean is; getting font metrics is not as easy as it was old GDI based on HDC, so I used the limited information of the GDIP and estimated some others like (x height  of text) by using statistical multipliers. However someone other can collapse the context to HDC level and calculate more detailed font metrics on that level. I didn’t prefer it to be consistent with the design logic of GDIP, and used TGPFontFamily class of GDIP to get the information about the font. Note that the metrics values gathered from this class is in logical units so should be converted to pixels using the proportions.

Here are my calculations:

1
2
3
4
5
6
7
8
9
10
11
fSize := FGPFont.GetHeight(FGraphics);
cAscent := FGpFamily.GetCellAscent(FontStyle);
cDescent := FGpFamily.GetCellDescent(FontStyle);
emHeight := FGpFamily.GetEmHeight(FontStyle);
lSpacing := FGPFamily.GetLineSpacing(FontStyle);
iLeading := cAscent+cDescent - emHeight;
eLeading := lSpacing - cAscent-cDescent;
Ascent := fSize * (cAscent)/lSpacing;
Descent := fSize * (descent)/lSpacing;
CapHeight := fSize * (cAscent-iLeading)/lSpacing;
XHeight :=  fsize * (cAscent-iLeading) *(7/10) /lSpacing;

Note that the calculations use TGPFont, TGPFontFamily and TGPGraphics classes to deal with font metrics. The FGPFont and FGPGraphics objects are not accessible through standard class hierarchy, however we can use RTTI functions to access them.

1
2
3
4
5
6
7
8
9
10
11
12
RttiField := RttiContext.GetType(Layout.ClassType).GetField('FGPFont');
if assigned(RttiField) then
begin
  FGPFont := TGpFont(RttiField.GetValue(Layout).AsObject);
  RttiField := RttiContext.GetType(Layout.ClassType).GetField('FGraphics');
  FGraphics := TGpGraphics(RttiField.GetValue(Layout).AsObject);
 
  FGPFamily := TGPFontFamily.Create;
  FGPFont.GetFamily(FGPFamily);
  // Get Metrics
  // ...
end;

Another point to be mentioned here is that, above calculations work only if the DefaultCanvas is a GDIP canvas. If the developer selects to use the D2D canvas, because of the absence of the FGPFont object in RTTI the text metrics will not be updated. Since I don’t have any experience on Direct2D I haven’t worked on it, but I will be happy if someone does it and send me so that I can put it in the class code by giving credits to his/her name.

Getting Text Metrics in Mac OS X

Things are always easier for programmers in Mac side. You can see below how it is easy getting font metrics using CoreText API of Cocoa.

1
2
3
4
5
6
LFontRef := CTFontCreateWithName(CFSTR(Layout.Font.Family), Layout.Font.Size, nil);
Ascent := CTFontGetAscent(LFontRef);
Descent := CTFontGetDescent(LFontRef);
CapHeight := CTFontGetCapHeight(LFontRef);
XHeight := CTFontGetXHeight(LFontRef);
CFRelease(LFontRef);

You can see all the details of using TTextLayout class and how to extend it to get Text/Font Metrics in my PlatformExtensions units. You can get the source code of the PlatformExtensions classes with the demo application from this SVN link. For non-programmers the compiledWin32Win64MacOSX (Thanks to Firemonkey) applications are also available to download.

https://delphiscience.wordpress.com/2013/01/06/getting-text-metrics-in-firemonkey/

Getting Text Metrics in Firemonkey(delphiscience的博客)的更多相关文章

  1. 博客代码美化(SyntaxHighlighter)

    这篇博文主要讲解自己使用SyntaxHighlighter对代码进行美工中遇见的问题以及如何使用SyntaxHighlighter? 首先来看看SyntaxHighlighter对代码美工的效果吧! ...

  2. python实战--csdn博客专栏下载器

    打算利用业余时间好好研究Python的web框架--web.py,深入剖析其实现原理,体会web.py精巧之美.但在研究源码的基础上至少得会用web.py.思前想后,没有好的Idea,于是打算开发一个 ...

  3. 【实战】如何通过html+css+mysql+php来快速的制作动态网页(以制作一个博客网站为列)

    一.开发环境的搭建 (1)apache+php+mysql环境搭建 因为要用apache来做服务器,mysql作为数据库来存储数据,php来写代码以此实现网页与数据库的交互数据,所以需要下载上述软件, ...

  4. Sublime Text博客插件 --- iblog

    iblog是一款 sublime 博客插件,目前只支持cnblog. 项目地址:https://github.com/iskeeter/iblog 功能介绍 新建和更新cnblog的博客 支持mark ...

  5. 一步步开发自己的博客 .NET版(10、前端对话框和消息框的实现)

    关于前端对话框.消息框的优秀插件多不胜数.造轮子是为了更好的使用轮子,并不是说自己造的轮子肯定好.所以,这个博客系统基本上都是自己实现的,包括日志记录.响应式布局.评论功能等等一些本可以使用插件的.好 ...

  6. 一步步开发自己的博客 .NET版(1、基本显示)

    前言 我们每个猿都有一个搭建自己独立博客的梦,我也不例外.以前想 现在想 以后也想.之所以一直迟迟没有着手,是因为难以跨出第一步.每次心里想着,等我以后技术好了再说,然后就没有然后了.以前用过word ...

  7. 一步步开发自己的博客 .NET版(3、注册登录功能)

    前言 这次开发的博客主要功能或特点:    第一:可以兼容各终端,特别是手机端.    第二:到时会用到大量html5,炫啊.    第三:导入博客园的精华文章,并做分类.(不要封我)    第四:做 ...

  8. 一步步开发自己的博客 .NET版(4、文章发布功能)百度编辑器

    前言 这次开发的博客主要功能或特点: 第一:可以兼容各终端,特别是手机端. 第二:到时会用到大量html5,炫啊. 第三:导入博客园的精华文章,并做分类.(不要封我) 第四:做个插件,任何网站上的技术 ...

  9. 一步步开发自己的博客 .NET版(5、Lucenne.Net 和 必应站内搜索)

    前言 这次开发的博客主要功能或特点:    第一:可以兼容各终端,特别是手机端.    第二:到时会用到大量html5,炫啊.    第三:导入博客园的精华文章,并做分类.(不要封我)    第四:做 ...

随机推荐

  1. 微设计(www.weidesigner.com)介绍系列文章(二)

    微设计(www.weidesigner.com)是一个专门针对微信公众账号提供营销推广服务而打造的第三方平台. 2.1 怎样注冊微信公众号? 登录mp.weixin.qq.com,点击注冊填写相关信息 ...

  2. QT 仓库管理系统 开放源代码

    IT 要走多久,要怎么走. IT 要走多久,要怎么走.这些问题,在我已经快毕业了一个年头的如今,又又一次浮如今我的脑海里.一边是工作的了了模块,一边是能够自己无聊打发的时间.这不是我当初要的路,如今的 ...

  3. [Typescript] Introduction to Generics in Typescript

    If Typescript is the first language in which you've encountered generics, the concept can be quite d ...

  4. 异步tcp通信——APM.Core 服务端概述

    为什么使用异步 异步线程是由线程池负责管理,而多线程,我们可以自己控制,当然在多线程中我们也可以使用线程池.就拿网络扒虫而言,如果使用异步模式去实现,它使用线程池进行管理.异步操作执行时,会将操作丢给 ...

  5. hdu 2111

    #include <iostream> #include <algorithm> using namespace std; struct money { int s; int ...

  6. 从BufferedImage到InputStream,实现绘图后进行下载(生成二维码图片并下载)

    @SuppressWarnings("resource") public void download() throws Exception{ String filename = & ...

  7. sunny day

    初始学习记录 基于http://www.htmleaf.com/html5/html5muban/20141121552.html模板 <!DOCTYPE html> <html l ...

  8. Android - Error parsing XML: unbound prefix

    概述 这个问题,虽然看起来不是问题,但是如果不知道的人,还会花点时间,有的人甚至重新安装ADT. 我一开始还以为是排版的问题(Layout),因为初学,弄来弄去,最好还是到网上搜. 其实就不是什么问题 ...

  9. MSSQL 字符串替换语句

    MSSQL替换语句:update 表名 set 字段名=replace(cast(字段名 as varchar(8000)),'abc.com','123.com')例如:update PE_Arti ...

  10. 系统管理中 bash shell 脚本常用方法总结

    在日常系统管理工作中,需要编写脚本来完成特定的功能,编写shell脚本是一个基本功了!在编写的过程中,掌握一些常用的技巧和语法就可以完成大部分功能了,也就是2/8原则 1. 单引号和双引号的区别 单引 ...