delphi - Can I generate an anti-aliased font size larger than 149? -


i have noticed, in delphi xe6 (and in other tools/languages produce applications run on windows, , use native gdi font rendering) win32 textout api not seem smooth font larger 149, is, font.size>149. here screenshot showing 2 speedbuttons, both font.quality set fqcleartype, 1 on left font.size set 149, 1 on right set font.size 150. that's 1 point difference. height values -199 , -200 respectively. demonstrate delphi component , form, demonstrated in tpaintbox, use of canvas.font , call win32 api drawtext, or pure win32 api application creates window, , draws device context using drawtext.

the limitation of gdi shown here; note cleartype looks mediocre (horizontal anti-aliasing no vertical) @ size=149 , , cleartype turns off @ 150:

enter image description here

my question is, there way circumvent limitation in win32 api gdi, using raw win32 function available on windows 7 , up, draw text , anti-alias? assume here logical font handling being done properly, inside vcl, because same limit occurs in c# application (using winforms, runs atop gdi) see when try in delphi.

i draw anti-aliased character font size greater 149, gdi canvas, either clear type or classic anti-aliasing. how that?

note have set font.quality explicitly both antialiased , cleartype modes, , win32 gdi api calls ignore these logical font properties size, apparently design. applications microsoft word, have font-rendering capability draw 155 point font or larger, , still anti-alias in case.

update: answered own question showing how easy directwrite+gdi interop is. on windows 7 , windows 8, , later, directwrite provides both horizontal , vertical anti-aliasing, , believe high quality on-screen font rendering mode apps ms word 2013 using. believe answer question showing gdi+ sample, , fit requirements above (as gdi+ included in windows 7 , 8).

a working approach have found interoperates gdi better gdi+ use directwrite, works in windows 7 , 8, , sample code present here has simple gdi fallback mode (plain gdi, no anti-aliasing) covers xp , vista, provide @ least graceful degradation; still paints text on pre-win7 operating systems, using gdi.

the original demo app here, using tform changed twincontrol, , had no gdi fallback, exception.

http://cc.embarcadero.com/item/27491

the discussion/blog post pawel glowacki wrote above demo here:

http://blogs.embarcadero.com/pawelglowacki/2009/12/14/38872

a code snippet including modified d2dutils.pas pawel's demo addition of gdi fall-back feature (instead of blowing exception) shown here.

uses   windows,   messages,   sysutils,   variants,   classes,   graphics,   controls,   forms,   dialogs,   winapi.d2d1,   vcl.direct2d;   type    tcanvasd2d = class(twincontrol) // base class, using twincontrol instead of tform.    private       finitflag: boolean;       fgdimode: boolean; { fallback }       fd2dcanvas: tdirect2dcanvas; { used when d2d available , gdimode=false }       fgdicanvas: tcanvas; { fallback canvas, used when fgdimode=true }       procedure wmerasebkgnd(var message: twmerasebkgnd); message wm_erasebkgnd;    protected       procedure resize; override;        procedure dopaint(ahdc: hdc); virtual;        procedure created2dresources; virtual;        procedure paintd2d; virtual;       procedure paintgdi; virtual;        function rendertarget: id2d1rendertarget; // convenience function used during d2d paints.        procedure paintwindow(dc: hdc); override;     public       constructor create(aowner: tcomponent); override;       destructor destroy; override;        procedure init;       property d2dcanvas: tdirect2dcanvas read fd2dcanvas;       property gdicanvas: tcanvas read fgdicanvas;        property gdimode: boolean read fgdimode write fgdimode;       { set true force gdi fallback, automatically set true if d2d not available, }    end;   tcanvasd2dsample = class(tcanvasd2d) // subclass of tcanvasd2d primitive "tlabel"     private     ffontbrush: id2d1solidcolorbrush;// brush generated current value of ffontcolor     fbackgroundcolor:tcolor; // clwhite     ffontcolor:tcolor; //clblack;     ftextformat: idwritetextformat;     ffontname: string;     ffontsize: integer;  { units?}     fdisplaytext: string;     flocale: string;       procedure setfontname(const value: string);     procedure setfontsize(const value: integer);     procedure setdisplaytext(const value: string);    protected     procedure paintd2d; override;     procedure paintgdi; override;     procedure created2dresources; override;      function fontsizetodip(fontsize:integer ):double;    public     constructor create(aowner: tcomponent); override;      property textformat:idwritetextformat read ftextformat;     property fontsize:integer read ffontsize write setfontsize;     property fontname:string read ffontname write setfontname;     property displaytext: string read fdisplaytext write setdisplaytext;      property backgroundcolor:tcolor read fbackgroundcolor write fbackgroundcolor;     property fontcolor:tcolor read ffontcolor write ffontcolor; //clblack;       property locale: string read flocale write flocale; // string 'en-us'    end;  implementation  constructor tcanvasd2d.create(aowner: tcomponent); begin    inherited;  end;  destructor tcanvasd2d.destroy; begin    fd2dcanvas.free;    fd2dcanvas := nil;    fgdicanvas.free;    fgdicanvas := nil;     inherited; end;  procedure tcanvasd2d.init; begin    if not finitflag    begin       finitflag := true;        if (not fgdimode) , (tdirect2dcanvas.supported)       begin          if assigned(fd2dcanvas)             fd2dcanvas.free;          fd2dcanvas := tdirect2dcanvas.create(handle);          created2dresources;       end       else       begin          fgdimode := true;          if assigned(fgdicanvas)             fgdicanvas.free;          fgdicanvas := tcanvas.create;          fgdicanvas.handle := getdc(self.handle);       end;    end; end;  procedure tcanvasd2d.created2dresources; begin    // create direct2d resources in descendant class end;  function tcanvasd2d.rendertarget: id2d1rendertarget; begin    result := d2dcanvas.rendertarget; end;  procedure tcanvasd2d.resize; var    hwndtarget: id2d1hwndrendertarget;    asize: td2d1sizeu; begin    inherited;     if assigned(d2dcanvas)       if supports(rendertarget, id2d1hwndrendertarget, hwndtarget)       begin          asize := d2d1sizeu(clientwidth, clientheight);          hwndtarget.resize(asize);       end;     invalidate; end;  procedure tcanvasd2d.wmerasebkgnd(var message: twmerasebkgnd); begin    if (not fgdimode)       // avoid flicker described here:       // http://chrisbensen.blogspot.com/2009/09/touch-demo-part-i.html       message.result := 1    else       inherited; end;  procedure tcanvasd2d.dopaint(ahdc: hdc); begin    init;    if fgdimode    begin       fgdicanvas.handle := ahdc;       paintgdi;    end    else    begin       d2dcanvas.begindraw;       try          paintd2d;                d2dcanvas.enddraw;       end;    end; end;  procedure tcanvasd2d.paintd2d; begin    // implement painting code in descendant class end;  procedure tcanvasd2d.paintgdi; begin    // implement in descendant. end;  procedure tcanvasd2d.paintwindow(dc: hdc); begin    dopaint(dc);    inherited;  end;     { custom control subclass } procedure tcanvasd2dsample.created2dresources;  begin   inherited;    d2dcanvas.rendertarget.createsolidcolorbrush(     d2d1colorf(ffontcolor, 1),     nil,     ffontbrush     );    dwritefactory.createtextformat(     pwidechar(fontname),     nil,     dwrite_font_weight_regular,     dwrite_font_style_normal,     dwrite_font_stretch_normal,     fontsizetodip( fontsize),     pwidechar(flocale),     ftextformat    );     ftextformat.settextalignment(dwrite_text_alignment_center);    ftextformat.setparagraphalignment(dwrite_paragraph_alignment_center); end;    function tcanvasd2dsample.fontsizetodip(fontsize: integer): double; begin    result := fontsize * (96.0 / 72.0); { todo: 96.0 should not hard coded? } end;  procedure tcanvasd2dsample.paintd2d; var   arect: td2d1rectf; //  asize:d2d_size_f; begin    // fill white color whole window   rendertarget.clear(d2d1colorf(fbackgroundcolor));      rendertarget.drawtext(     pwidechar(fdisplaytext),     length(fdisplaytext),     ftextformat,     d2d1rectf(0, 0, clientwidth, clientheight),     ffontbrush     );    //  rendertarget.getsize(asize); end;  procedure tcanvasd2dsample.paintgdi; begin   { fallback paint mode}   gdicanvas.lock;   gdicanvas.font.name := ffontname;   gdicanvas.font.size := ffontsize;   gdicanvas.font.color := ffontcolor;   gdicanvas.brush.style := bssolid;   gdicanvas.brush.color := fbackgroundcolor;   gdicanvas.rectangle(self.clientrect);     gdicanvas.textout(0,0, fdisplaytext); gdicanvas.unlock; end;  procedure tcanvasd2dsample.setdisplaytext(const value: string); begin    if value<>fdisplaytext    begin     fdisplaytext := value;     invalidate;    end; end;  procedure tcanvasd2dsample.setfontname(const value: string); begin   ffontname := value; end;  procedure tcanvasd2dsample.setfontsize(const value: integer); begin   ffontsize := value; end; 

Comments

Popular posts from this blog

javascript - Jquery show_hide, what to add in order to make the page scroll to the bottom of the hidden field once button is clicked -

javascript - Highcharts multi-color line -

javascript - Enter key does not work in search box -