zoukankan      html  css  js  c++  java
  • [原创] 改善 Firemonkey Canvas 几何绘图质量问题(移动平台)

    说明:

      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 := 10;
      Canvas.Stroke.Kind := TBrushKind.Solid;
      Canvas.Stroke.Dash := TStrokeDash.DashDotDot;
    
      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);
    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 := 10;
        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 / 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;

    已知问题:

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

    文件下载:

     

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

    参考资料:

  • 相关阅读:
    服务部署 RPC vs RESTful
    模拟浏览器之从 Selenium 到splinter
    windows程序设计 vs2012 新建win32项目
    ubuntu python 安装numpy,scipy.pandas.....
    vmvare 将主机的文件复制到虚拟机系统中 安装WMware tools
    ubuntu 修改root密码
    python 定义类 简单使用
    python 定义函数 两个文件调用函数
    python 定义函数 调用函数
    python windows 安装gensim
  • 原文地址:https://www.cnblogs.com/onechen/p/6350096.html
Copyright © 2011-2022 走看看