首页 > 代码库 > [原创] Firemonkey 解决 Canvas 几何绘图质量问题(移动平台)

[原创] Firemonkey 解决 Canvas 几何绘图质量问题(移动平台)

原由说明:

  之前使用 Obj-C 开发 iOS 的 App 时,使用几何绘图是家常便饭,质量更是好的没话说,因跨平台需求,转用 Delphi Firemonkey 来开发,它的跨平台能力还算满意(一份代码及介面可以轻松跨四个平台),唯独移动平台在几何绘图方面,质量总是不尽人意,我也曾试着去修正(如:修正曲线平滑问题),也曾找过第三方案(如:AggPas),但始终不完美,我一直在想,移动平台有这么强的绘图能力及质量,如果能直接拿来用,不是很好?为什么 Firemonkey 要自己重写(移动平台线段处理计算单元在 FMX.StrokeBuilder.pas 有兴趣可以自己研究,质量问题可能就出在这里?!)?

 

实做方法:

  大家都喜欢简单,如果能不更动原来绘图代码,只要加入几行代码,或编译开关,那是最理想的,就以这个构想出发,做出了目前的原生绘图方案:

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, 昵名函数里加入绘图方法, 内部会先画到 Bitmap

  // 距形
  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, 结束后会显示这个 Bitmap
end;

 

实作原理:

  • 它的原理很简单,就是先配置一个原生的绘图区域 Bitmap,再将几何图形画在这个区域里,最后将这个区域里的内容,转回 TBitmap,再显示到 Canvas 里
  • 这种方法仅是一种变通方式,建议用在需要高质量的绘图上,才不会影响程序整体的效能 

 

已实做 Canvas 函数:

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

 

涂色及线色笔刷:

  • 支持渐层涂色
  • 不支持 Bitmap 涂色

 

已知问题:

  • 未完成的函数功能及特性,欢迎大家一起完善
  • 真机 iOS 64bit 无法显示虚线(虚拟机没问题)(原因不明,TMS iCL 控件也有此问题)
  • 几何绘图只有在移动平台 Android & iOS 上有问题,Windows & macOS 没有问题

 

参考资料:

  • https://sourceforge.net/projects/dpfdelphiios/
  • https://sourceforge.net/projects/alcinoe/
  • http://www.applyingcode.com/

 

源码下载:(预计年后分享)

 

[原创] Firemonkey 解决 Canvas 几何绘图质量问题(移动平台)