• [原创] 改善 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):

    参考资料:

  • 相关阅读:
    黑松白鹿
    跨越
    第三年
    Lua windows环境搭建
    Iron man
    水果沙拉
    六周岁
    sqlserver数据库附加报错5120
    [BeiJing2006]狼抓兔子 平面图最小割
    BZOJ2118: 墨墨的等式 思维建图
  • 原文地址:https://www.cnblogs.com/onechen/p/6350096.html
Copyright © 2020-2023  润新知