说明:

  Fiiremonkey 的跨平台能力,大家有目共睹(一码同介面跨四平台),唯独移动平台在几何绘图方面,质量始终不尽人意,我也曾试着去修正(如:修正曲线平滑问题),也曾找过第三方案(如:AggPas),但都不完美,我一直在想,移动平台有这么强的绘图能力及质量(Android & iOS),如果能直接拿来用,不是很好?为什么 Firemonkey 要自己重写?

  目前网上许多针对此问题的改善方案,但多以控件形式,且需依各平台的绘图函数来绘图,或仅提供固定的几何图形控件,如果能延用现有的 TCanvas.Draw????? 绘图代码,只要加入几行代码(或编译开关),就能达到原生绘图的效果,岂不是很理想,于是开是构想这种方案的可行性,最后证实是可行的。

  要先说明的是,这里提供的只是一种改善方案,而不是修正,最终还是希望能受到 EMB 官方的关注,由官方来改进这个问题。

用法及效果:

FMX 的绘图方法:

procedure TForm1.PaintBox1Paint(Sender: TObject; Canvas: TCanvas);
var Rect, DesRect: TRectF;
begin
Rect := PaintBox1.LocalRect;
Canvas.Stroke.Thickness := ;
Canvas.Stroke.Kind := TBrushKind.Solid;
Canvas.Stroke.Dash := TStrokeDash.DashDotDot; DesRect := Rect;
InflateRect(DesRect, -(Canvas.Stroke.Thickness / ), -(Canvas.Stroke.Thickness / )); // 线在区内
Canvas.FillRect(DesRect, , , AllCorners, );
Canvas.DrawRect(DesRect, , , AllCorners, );
end;
说明 Android iOS Windows macOS

上面的代码,使用 FMX 绘图方法

(移动平台是有问题的)

下面的代码,使用原生绘图方法

(四个平台全部相同了)

下面改成原生绘图方案,只要在原有絵图代码前後加入二行代码(原绘图代码不用更动)

{$i NativeDraw.inc}
uses FMX.Graphics.Native; procedure TForm1.PaintBox1Paint(Sender: TObject; Canvas: TCanvas);
var Rect, DesRect: TRectF;
begin
Rect := PaintBox1.LocalRect;
Canvas.Stroke.Thickness := 10;
Canvas.Stroke.Kind := TBrushKind.Solid;
Canvas.Stroke.Dash := TStrokeDash.DashDotDot; {$IFDEF UseNativeDraw}Canvas.NativeDraw(Rect, procedure begin {$ENDIF} // 原生绘图 by Aone DesRect := Rect;
InflateRect(DesRect, -(Canvas.Stroke.Thickness / 2), -(Canvas.Stroke.Thickness / 2)); // 线在区内
Canvas.FillRect(DesRect, 30, 30, AllCorners, 1);
Canvas.DrawRect(DesRect, 30, 30, AllCorners, 1); {$IFDEF UseNativeDraw}end);{$ENDIF} // 原生绘图 by Aone
end;

运作原理:

  • 它的运作原理很简单,就是先配置一个原生的绘图区域 Bitmap,再将几何图形画在这个区域里,最后将这个区域里的内容,转回 TBitmap,再显示到 Canvas 里
  • 利用 Delphi Pascal Helper 语言特性,针对 TCanvas 来做扩展,如此才能达到不改动原有的绘图代码
  • 目前这个作法,相同的绘图代码,可以跨四个平台:
    • Android, iOS:使用原生绘图 TCanvasHelper 方法

    • Windows, masOS:使用原来 TCanvas 方法(这二个平台本来就没有质量问题,所以不用重写)
  • 我们无法触及 FMX 的最核心,只能利用这种 Bitmap 方式来变通,要知道这种方式可能带来的问题(记忆体及效能),才不致错用

  • 注意:如果引用了 FMX.Graphics.Native 就必需使用下面的方式来写绘图代码,否则请不要引用:
    {$i NativeDraw.inc}
    uses FMX.Graphics.Native; {$IFDEF UseNativeDraw}Canvas.NativeDraw(Rect, procedure begin {$ENDIF} // 原生绘图 by Aone // 绘图代码 {$IFDEF UseNativeDraw}end);{$ENDIF} // 原生绘图 by Aone

调用原生绘图的 TCanvas 函数:(仅有下面函数有质量问题)

DrawLine 画线 
FillRect 圆距区 
DrawRect 圆距框线 
FillPath 路径区 
DrawPath 路径框线 
FillEllipse 椭圆区 
DrawEllipse 椭圆框线
FillArc 孤线区
DrawArc 孤框线 
FillPolygon 多边形区 
DrawPolygon 多边形框线 
IntersectClipRect 相交剪裁区
ExcludeClipRect 其它剪裁区

TBrush 涂刷 & TStrokeBrush 线刷:

  • 支持所有涂刷特性,除了 Bitmap 涂色尚未支持(若有此需求,可自行修改源码,加入此特性)
  • FMX 在移动平台是不支持画线加渐层涂色,使用原生绘图,已经可以轻松实现(支持 Linear 线渐层及 Radial 圆渐层效果):
    原生 FMX
  • procedure TForm1.PaintBox1Paint(Sender: TObject; Canvas: TCanvas);
    var Rect, DesRect: TRectF;
    begin
    Rect := PaintBox1.LocalRect;
    Canvas.Stroke.Thickness := ;
    Canvas.Stroke.Kind := TBrushKind.Gradient;
    Canvas.Stroke.Dash := TStrokeDash.DashDotDot;
    Canvas.Stroke.Gradient.Color := TAlphaColorRec.Blue;
    Canvas.Stroke.Gradient.Color1 := TAlphaColorRec.Gold; {$IFDEF UseNativeDraw}Canvas.NativeDraw(Rect, procedure begin {$ENDIF} // 原生绘图 by Aone DesRect := Rect;
    InflateRect(DesRect, -(Canvas.Stroke.Thickness / ), -(Canvas.Stroke.Thickness / )); // 线在区内
    Canvas.FillRect(DesRect, , , AllCorners, );
    Canvas.DrawRect(DesRect, , , AllCorners, ); {$IFDEF UseNativeDraw}end);{$ENDIF} // 原生绘图 by Aone
    end;

已知问题:

  • 真机 iOS 64bit 无法显示虚线(虚拟机没问题)
  • 未完成的函数功能及特性,欢迎大家一起完善

文件下载:

2017.06.22 新增 TestArc Demo(已更新到 GitHub):

参考资料:

[原创] 改善 Firemonkey Canvas 几何绘图质量问题(移动平台)的更多相关文章

  1. HTML5 Canvas 2D绘图

    为了防止无良网站的爬虫抓取文章,特此标识,转载请注明文章出处.LaplaceDemon/ShiJiaqi. http://www.cnblogs.com/shijiaqi1066/p/4851774. ...

  2. Microsoft.VisualBasic.dll的妙用and 改善C#公共程序类库质量的10种方法

    Microsoft.VisualBasic.dll的妙用(开发中肯定会用到哦) 前言 做过VB开发的都知道,有一些VB里面的好的函数在.NET里面都没有,而Microsoft.VisualBasic. ...

  3. 【原创】C#搭建足球赛事资料库与预测平台(6) 赔率数据表设计2

            本博客所有文章分类的总目录:[总目录]本博客博文总目录-实时更新 开源C#彩票数据资料库系列文章总目录:[目录]C#搭建足球赛事资料库与预测平台与彩票数据分析目录 本篇文章开始将逐步介 ...

  4. 【原创】C#搭建足球赛事资料库与预测平台(2) 数据库与XCode组件

            本博客所有文章分类的总目录:[总目录]本博客博文总目录-实时更新 开源C#彩票数据资料库系列文章总目录:[目录]C#搭建足球赛事资料库与预测平台与彩票数据分析目录  本篇文章开始将逐步 ...

  5. sonar+Jenkins 构建代码质量自动化分析平台

    1.Sonar 介绍 Sonar 是一个用于管理代码质量的开源工具,可以分析代码中的bug和漏洞以及Code Smells,支持20多种编程语言的检测,如java,c/c++,python,php等语 ...

  6. html --- canvas --- javascript --- 绘图方法

    Canvas元素是HTML5的一部分,允许脚本语言动态渲染位图像. 如有疑问请访问链接:http://javascript.ruanyifeng.com/htmlapi/canvas.html < ...

  7. H5新特性——--第三方绘图工具库 echarts(canvas)---SVG绘图

    今天学习的内容 3.1:h5新特性---第三方绘图工具库 echarts(canvas) 百度 echarts;d3;two.js;.... 3.2:h5新特性---SVG绘图 3.2:h5新特性-- ...

  8. (第一章)改善JavaScript,编写高质量代码。

    根据<编写高质量代码改善JavaScript程序的188个建议>这本书,来记录我目前所了解的建议方式. 建议1:警惕Unicode乱码 根据ECMA标准规定JavaScript语言可以使用 ...

  9. Opengl编程指南第二章:状态管理、几何绘图

    //http://blog.csdn.net/longhuihu/article/details/7701874 1.绘图基础 清除窗口 glClearColor(0.0, 0.0, 0.0, 0.0 ...

随机推荐

  1. [Z] SVN的trunk、branch、tag

    Subversion有一个很标准的目录结构,是这样的.比如项目是proj,svn地址为svn://proj/,那么标准的svn布局是 svn://proj/|+-trunk+-branches+-ta ...

  2. LeetCode题解 #8 String to Integer (atoi)

    又是一道恶心的简单题. 一开始没想到这么多情况的,幸好LeetCode是个很人性化的oj,能让你知道你在哪个case上错了,否则一辈子都过不了. 考虑不周到只能一个个补了. 列举一下恶心的case / ...

  3. django html模板继承 {%block 标记名} {%endblock%}

    对于url文件 url(r'^tp1/', views.tp1) 对于views文件,跳转到tp1.html 同时将list列表传到前端 def tp1(request): list = [1, 2, ...

  4. Linux实战教学笔记46:NoSQL数据库之redis持久化存储 (二)

    第3章 Redis数据类型详解 3.1 Redis键/值介绍 Redis key值是二进制安全的,这意味着可以用任何二进制序列作为key值,从形如"foo"的简单字符串到一个JPG ...

  5. FP寻源报错

    ERROR [HY000] [Oracle][ODBC][Ora]ORA-01114: IO error writing block to file  (block # )  ORA-01114: I ...

  6. java web框架发展的新趋势--跨界轻型App

    “跨界(cross over)在汽车界已然成风,将轿车.SUV.跑车和MPV等多种不同元素融为一体的混搭跨界车型,正在成为汽车设计领域的新趋势.从个人而言,当包容.多元的审美要求和物质要求越来越强烈时 ...

  7. OpenNebula 4.0 Beta 新特性介绍

    http://blog.chinaunix.net/uid-20940095-id-3561376.html 2013年3月26号,OpenNebula社区发布了OpenNebula 4.0 Beta ...

  8. spring4-2-bean配置-3-自动装配

  9. Linux buffer and cache

    A buffer is something that has yet to be "written" to disk. A cache is something that has ...

  10. code1225 搭积木

    题目分析:将当前层定义为第h层,共用了n块积木,本层积木数为m,f(h,n,m) 那么可以扩展数两种状态:f(h-1,n-m,m-1),f(h-1,n-m,m+1) 直接搜索可能的数据达到h^m,超时 ...