[FMX]不是所有的高质量绘图都是我们想要的:在 FMX 下使用 Canvas 进行“低质量”绘图

鱼,我所欲也,熊掌,虽我也欲,但我买不起也!FMX 默认的组图模式是 SystemDefault,在 Windows 下,默认是高质量绘图。当然,高质量这个词意味着啥,大家都清楚,使用 TCanvas 的 DrawLine 绘制一条 1 像素的水平直虚线,效果如下:

 

 

怎么样,感觉是不是有点辣眼睛?我实际上想要的是这种:

 

是的,高质量的绘图得出了我们不想要的结果。

TCanvas 本身倒是有一个 Quality 属性,可惜它是只读的!!!!

如果设置窗体的 Quality 直接就是 Perfmance,当然能达到我们想要的效果,但代价就是这个窗体上所有控件的绘图质量都变成差了。所以,通过寻寻觅觅,终于找到了一种折中的办法,我们看 Delphi 中 TCanvasManager 的声明:

 

TCanvasManager = class sealed
  private type
    TCanvasClassRec = record
      CanvasClass: TCanvasClass;
      Default: Boolean;
      PrinterCanvas: Boolean;
    end;
  strict private
    class var FCanvasList: TList<TCanvasClassRec>;
    class var FDefaultCanvasClass: TCanvasClass;
    class var FDefaultPrinterCanvasClass: TCanvasClass;
    class var FMeasureBitmap: TBitmap;
    class var FEnableSoftwareCanvas: Boolean;
  private
    class function GetDefaultCanvas: TCanvasClass; static;
    class function GetMeasureCanvas: TCanvas; static;
    class function GetDefaultPrinterCanvas: TCanvasClass; static;
  public
    // Reserved for internal use only - do not call directly!
    class procedure UnInitialize;
    // Register a rendering Canvas class
    class procedure RegisterCanvas(const CanvasClass: TCanvasClass; const ADefault: Boolean; const APrinterCanvas: Boolean);
    // Return default Canvas
    class property DefaultCanvas: TCanvasClass read GetDefaultCanvas;
    // Return default Canvas
    class property DefaultPrinterCanvas: TCanvasClass read GetDefaultPrinterCanvas;
    // Return canvas instance used for text measuring for example
    class property MeasureCanvas: TCanvas read GetMeasureCanvas;
    // Creation helper
    class function CreateFromWindow(const AParent: TWindowHandle; const AWidth, AHeight: Integer;
      const AQuality: TCanvasQuality = TCanvasQuality.SystemDefault): TCanvas;
    class function CreateFromBitmap(const ABitmap: TBitmap;
      const AQuality: TCanvasQuality = TCanvasQuality.SystemDefault): TCanvas;
    class function CreateFromPrinter(const APrinter: TAbstractPrinter): TCanvas;
    class procedure RecreateFromPrinter(const Canvas: TCanvas; const APrinter: TAbstractPrinter);
    class procedure EnableSoftwareCanvas(const Enable: Boolean);
  end;

看到了啥?有几个好东西:

  • DefaultCanvas 是返回系统中默认的画布的类型的,通过它可以创建默认类型的 TCanvas 实例。
  • MeasureCanvas 这个是一个虚拟的画布,用来计算文本大小的,全局共享。
  • CreateFromWindows 可以从一个窗口中创建一个新的画布对象,它是可以控制这个画布的质量,但是FMX控件,大部分是没有个这 TWindowHandle 实例的(当然,窗体例外),如果使用它创建一个临时的画布,对在窗体上直接绘制点低质量的内容,应该是一个不错的选择。
  • CreateFromBitmap 可以创建一个关联到指定位图的画布,它也有 AQuality 参数来控制画布的绘图质量,这简直就是冷天来了送温暖的。
  • 太激动了,后面的两个大家自己顾名思义,自己看吧,反正官方是没有帮助的:)

通过上面的过程,我们就知道我们该怎么做了:

1、创建一个缓存的位图,然后调用 TCanvasManager.CreateFromBitmap 来创建一个低质量的画布,然后在上面绘图,具体的绘图代码,此处省略500字。

2、使用Canvas.DrawBitmap,将缓存的位图绘制到指定的画布指定位置,由于我们不要高质量绘图,所以 AHighSpeed 参数,请选择 true(默认是false)。

3、释放该释放的对象。

好了,师傅领进门,修行靠各人,看看最终的效果吧(同时绘制了两条同样参数的线,一条是低质量,一条是高质量,Windows 平台):

分享到: