博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Direct2D (39) : 使用 IDWriteTextLayout.Draw() 方法绘制文本
阅读量:6986 次
发布时间:2019-06-27

本文共 15192 字,大约阅读时间需要 50 分钟。

  hot3.png

使用 IDWriteTextLayout.Draw() 方法绘制文本主要是实现 IDWriteTextRenderer 接口。
IDWriteTextRenderer 接口只能是手动实现,很灵活。

unit Unit1;interfaceuses  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  Dialogs, Direct2D, D2D1;type  TForm1 = class(TForm)    procedure FormPaint(Sender: TObject);    procedure FormResize(Sender: TObject);  end;  TMyWriteTextRenderer = class(TInterfacedObject, IDWriteTextRenderer)  private    FRenderTarge: ID2D1RenderTarget;    FOutLineBrush,FFillBrush: ID2D1Brush;  public    constructor Create(ARenderTarge: ID2D1RenderTarget; AOutLineBrush,AFillBrush: ID2D1Brush);    function IsPixelSnappingDisabled(clientDrawingContext: Pointer; var isDisabled: LongBool): HRESULT;      stdcall;    function GetCurrentTransform(clientDrawingContext: Pointer; var transform: DWRITE_MATRIX): HRESULT;      stdcall;    function GetPixelsPerDip(clientDrawingContext: Pointer; var pixelsPerDip: Single): HRESULT; stdcall;    function DrawGlyphRun(clientDrawingContext: Pointer; baselineOriginX: Single; baselineOriginY: Single;      measuringMode: DWRITE_MEASURING_MODE; var glyphRun: DWRITE_GLYPH_RUN;      var glyphRunDescription: DWRITE_GLYPH_RUN_DESCRIPTION; const clientDrawingEffect: IInterface): HRESULT;      stdcall;    function DrawUnderline(clientDrawingContext: Pointer; baselineOriginX: Single; baselineOriginY: Single;      var underline: DWRITE_UNDERLINE; const clientDrawingEffect: IInterface): HRESULT; stdcall;    function DrawStrikethrough(clientDrawingContext: Pointer; baselineOriginX: Single;      baselineOriginY: Single; var strikethrough: DWRITE_STRIKETHROUGH;      const clientDrawingEffect: IInterface): HRESULT; stdcall;    function DrawInlineObject(clientDrawingContext: Pointer; originX: Single; originY: Single;      var inlineObject: IDWriteInlineObject; isSideways: LongBool; isRightToLeft: LongBool;      const clientDrawingEffect: IInterface): HRESULT; stdcall;  end;var  Form1: TForm1;implementation{$R *.dfm}{构建 DWRITE_TEXT_RANGE 结构的函数}function DWriteTextRange(pos,len: Cardinal): TDwriteTextRange;begin  Result.startPosition := pos;  Result.length := len;end;{构建 DWRITE_FONT_FEATURE 结构的函数}function DWriteFontFeature(nameTag: Integer; parameter: Cardinal): TDwriteFontFeature;begin  Result.nameTag := nameTag;  Result.parameter := parameter;end;{建立位图画刷的函数}function GetBitmapBrush(Canvas: TDirect2DCanvas; filePath: string): ID2D1BitmapBrush;var  rBBP: TD2D1BitmapBrushProperties;  bit: TBitmap;begin  bit := TBitmap.Create;  bit.LoadFromFile(filePath);  rBBP.extendModeX := D2D1_EXTEND_MODE_WRAP;  rBBP.extendModeY := D2D1_EXTEND_MODE_WRAP;  rBBP.interpolationMode := D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR;  Canvas.RenderTarget.CreateBitmapBrush(Canvas.CreateBitmap(bit), @rBBP, nil, Result);  bit.Free;end;procedure TForm1.FormPaint(Sender: TObject);var  cvs: TDirect2DCanvas;  str: string;  iTextFormat: IDWriteTextFormat;  iSolidColorBrush: ID2D1SolidColorBrush;  iBitmapBrush: ID2D1BitmapBrush;  iTextLayout: IDWriteTextLayout;  iTypography: IDWriteTypography;  iTextRenderer: IDWriteTextRenderer;begin  str := 'Hello World using DirectWrite!';  DWriteFactory.CreateTextFormat(    'Gabriola',    nil,    DWRITE_FONT_WEIGHT_REGULAR,    DWRITE_FONT_STYLE_NORMAL,    DWRITE_FONT_STRETCH_NORMAL,    72.0,    'en-us',    iTextFormat  );  iTextFormat.SetTextAlignment(DWRITE_TEXT_ALIGNMENT_CENTER);  iTextFormat.SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_CENTER);  DWriteFactory.CreateTextLayout(    PWideChar(str),    Length(str),    iTextFormat,    ClientWidth,    ClientHeight,    iTextLayout  );  iTextLayout.SetFontSize(100.0, DWriteTextRange(18, 6));  iTextLayout.SetUnderline(True, DWriteTextRange(18, 11));  iTextLayout.SetFontWeight(DWRITE_FONT_WEIGHT_BOLD, DWriteTextRange(18, 11));  DWriteFactory.CreateTypography(iTypography);  iTypography.AddFontFeature(DWriteFontFeature(DWRITE_FONT_FEATURE_TAG_STYLISTIC_SET_6, 1));  iTextLayout.SetTypography(iTypography, DWriteTextRange(0, Length(str)));  cvs := TDirect2DCanvas.Create(Canvas, ClientRect);  cvs.RenderTarget.CreateSolidColorBrush(D2D1ColorF(clBlack), nil, iSolidColorBrush);  iBitmapBrush := GetBitmapBrush(cvs, 'C:\Temp\Test.bmp');  iTextRenderer := TMyWriteTextRenderer.Create(cvs.RenderTarget, iSolidColorBrush, iBitmapBrush);  cvs.RenderTarget.BeginDraw;  cvs.RenderTarget.Clear(D2D1ColorF(clWhite));  iTextLayout.Draw(nil, iTextRenderer, 0, 0);  cvs.RenderTarget.EndDraw();  cvs.Free;end;procedure TForm1.FormResize(Sender: TObject);begin  Repaint;end;{ TMyWriteTextRenderer }constructor TMyWriteTextRenderer.Create(ARenderTarge: ID2D1RenderTarget; AOutLineBrush,  AFillBrush: ID2D1Brush);begin  FRenderTarge := ARenderTarge;  FOutLineBrush := AOutLineBrush;  FFillBrush := AFillBrush;end;function TMyWriteTextRenderer.DrawGlyphRun(clientDrawingContext: Pointer; baselineOriginX,  baselineOriginY: Single; measuringMode: DWRITE_MEASURING_MODE; var glyphRun: DWRITE_GLYPH_RUN;  var glyphRunDescription: DWRITE_GLYPH_RUN_DESCRIPTION; const clientDrawingEffect: IInterface): HRESULT;var  iPathGeometry: ID2D1PathGeometry;  iGeometrySink: ID2D1GeometrySink;  iTransformedGeometry: ID2D1TransformedGeometry;begin  D2DFactory.CreatePathGeometry(iPathGeometry);  iPathGeometry.Open(iGeometrySink);  glyphRun.fontFace.GetGlyphRunOutline(    glyphRun.fontEmSize,    glyphRun.glyphIndices,    glyphRun.glyphAdvances,    glyphRun.glyphOffsets,    glyphRun.glyphCount,    glyphRun.isSideways,    longBool(glyphRun.bidiLevel div 2),    iGeometrySink  );  iGeometrySink.Close;  D2DFactory.CreateTransformedGeometry(    iPathGeometry,    TD2DMatrix3x2F.Translation(baselineOriginX, baselineOriginY),    iTransformedGeometry  );  FRenderTarge.DrawGeometry(iTransformedGeometry, FOutLineBrush);  FRenderTarge.FillGeometry(iTransformedGeometry, FFillBrush);  Result := S_OK;end;function TMyWriteTextRenderer.DrawInlineObject(clientDrawingContext: Pointer; originX, originY: Single;  var inlineObject: IDWriteInlineObject; isSideways, isRightToLeft: LongBool;  const clientDrawingEffect: IInterface): HRESULT;begin  Result := E_NOTIMPL; //未实现end;function TMyWriteTextRenderer.DrawStrikethrough(clientDrawingContext: Pointer; baselineOriginX,  baselineOriginY: Single; var strikethrough: DWRITE_STRIKETHROUGH;  const clientDrawingEffect: IInterface): HRESULT;var  rRectF: TD2DRectF;  iRectangleGeometry: ID2D1RectangleGeometry;  iTransformedGeometry: ID2D1TransformedGeometry;begin  rRectF := D2D1RectF(    0,    strikethrough.offset,    strikethrough.width,    strikethrough.offset + strikethrough.thickness  );  D2DFactory.CreateRectangleGeometry(rRectF, iRectangleGeometry);  D2DFactory.CreateTransformedGeometry(    iRectangleGeometry,    TD2DMatrix3x2F.Translation(baselineOriginX, baselineOriginY),    iTransformedGeometry  );  FRenderTarge.DrawGeometry(iTransformedGeometry, FOutLineBrush);  FRenderTarge.FillGeometry(iTransformedGeometry, FFillBrush);  Result := S_OK;end;function TMyWriteTextRenderer.DrawUnderline(clientDrawingContext: Pointer; baselineOriginX,  baselineOriginY: Single; var underline: DWRITE_UNDERLINE; const clientDrawingEffect: IInterface): HRESULT;var  rRectF: TD2DRectF;  iRectangleGeometry: ID2D1RectangleGeometry;  iTransformedGeometry: ID2D1TransformedGeometry;begin  rRectF := D2D1RectF(    0,    underline.offset,    underline.width,    underline.offset + underline.thickness  );  D2DFactory.CreateRectangleGeometry(rRectF, iRectangleGeometry);  D2DFactory.CreateTransformedGeometry(    iRectangleGeometry,    TD2DMatrix3x2F.Translation(baselineOriginX, baselineOriginY),    iTransformedGeometry  );  FRenderTarge.DrawGeometry(iTransformedGeometry, FOutLineBrush);  FRenderTarge.FillGeometry(iTransformedGeometry, FFillBrush);  Result := S_OK;end;function TMyWriteTextRenderer.GetCurrentTransform(clientDrawingContext: Pointer;  var transform: DWRITE_MATRIX): HRESULT;begin  FRenderTarge.GetTransform(TD2D1Matrix3x2F(transform));  Result := S_OK;end;function TMyWriteTextRenderer.GetPixelsPerDip(clientDrawingContext: Pointer;  var pixelsPerDip: Single): HRESULT;var  x,y: Single;begin  FRenderTarge.GetDpi(x, y);  pixelsPerDip := x / 96;  Result := S_OK;end;function TMyWriteTextRenderer.IsPixelSnappingDisabled(clientDrawingContext: Pointer;  var isDisabled: LongBool): HRESULT;begin  isDisabled := False;  Result := S_OK;end;end.

效果图:
26153723_HBWh.png

简化一下,只描绘文本的轮廓:

unit Unit1;interfaceuses  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  Dialogs, Direct2D, D2D1;type  TForm1 = class(TForm)    procedure FormPaint(Sender: TObject);    procedure FormResize(Sender: TObject);  end;  TMyWriteTextRenderer = class(TInterfacedObject, IDWriteTextRenderer)  private    FRenderTarge: ID2D1RenderTarget;    FOutLineBrush: ID2D1Brush;  public    constructor Create(ARenderTarge: ID2D1RenderTarget; AOutLineBrush: ID2D1Brush);    function IsPixelSnappingDisabled(clientDrawingContext: Pointer; var isDisabled: LongBool): HRESULT;      stdcall;    function GetCurrentTransform(clientDrawingContext: Pointer; var transform: DWRITE_MATRIX): HRESULT;      stdcall;    function GetPixelsPerDip(clientDrawingContext: Pointer; var pixelsPerDip: Single): HRESULT; stdcall;    function DrawGlyphRun(clientDrawingContext: Pointer; baselineOriginX: Single; baselineOriginY: Single;      measuringMode: DWRITE_MEASURING_MODE; var glyphRun: DWRITE_GLYPH_RUN;      var glyphRunDescription: DWRITE_GLYPH_RUN_DESCRIPTION; const clientDrawingEffect: IInterface): HRESULT;      stdcall;    function DrawUnderline(clientDrawingContext: Pointer; baselineOriginX: Single; baselineOriginY: Single;      var underline: DWRITE_UNDERLINE; const clientDrawingEffect: IInterface): HRESULT; stdcall;    function DrawStrikethrough(clientDrawingContext: Pointer; baselineOriginX: Single;      baselineOriginY: Single; var strikethrough: DWRITE_STRIKETHROUGH;      const clientDrawingEffect: IInterface): HRESULT; stdcall;    function DrawInlineObject(clientDrawingContext: Pointer; originX: Single; originY: Single;      var inlineObject: IDWriteInlineObject; isSideways: LongBool; isRightToLeft: LongBool;      const clientDrawingEffect: IInterface): HRESULT; stdcall;  end;var  Form1: TForm1;implementation{$R *.dfm}{构建 DWRITE_TEXT_RANGE 结构的函数}function DWriteTextRange(pos,len: Cardinal): TDwriteTextRange;begin  Result.startPosition := pos;  Result.length := len;end;{构建 DWRITE_FONT_FEATURE 结构的函数}function DWriteFontFeature(nameTag: Integer; parameter: Cardinal): TDwriteFontFeature;begin  Result.nameTag := nameTag;  Result.parameter := parameter;end;procedure TForm1.FormPaint(Sender: TObject);var  cvs: TDirect2DCanvas;  str: string;  iTextFormat: IDWriteTextFormat;  iSolidColorBrush: ID2D1SolidColorBrush;  iTextLayout: IDWriteTextLayout;  iTypography: IDWriteTypography;  iTextRenderer: IDWriteTextRenderer;begin  str := 'Hello World using DirectWrite!';  DWriteFactory.CreateTextFormat(    'Gabriola',    nil,    DWRITE_FONT_WEIGHT_ULTRA_BLACK,    DWRITE_FONT_STYLE_NORMAL,    DWRITE_FONT_STRETCH_NORMAL,    72.0,    'en-us',    iTextFormat  );  iTextFormat.SetTextAlignment(DWRITE_TEXT_ALIGNMENT_CENTER);  iTextFormat.SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_CENTER);  DWriteFactory.CreateTextLayout(    PWideChar(str),    Length(str),    iTextFormat,    ClientWidth,    ClientHeight,    iTextLayout  );  iTextLayout.SetFontSize(100.0, DWriteTextRange(18, 6));  iTextLayout.SetUnderline(True, DWriteTextRange(18, 11));  iTextLayout.SetFontWeight(DWRITE_FONT_WEIGHT_BOLD, DWriteTextRange(18, 11));  DWriteFactory.CreateTypography(iTypography);  iTypography.AddFontFeature(DWriteFontFeature(DWRITE_FONT_FEATURE_TAG_STYLISTIC_SET_6, 1));  iTextLayout.SetTypography(iTypography, DWriteTextRange(0, Length(str)));  cvs := TDirect2DCanvas.Create(Canvas, ClientRect);  cvs.RenderTarget.CreateSolidColorBrush(D2D1ColorF(clRed), nil, iSolidColorBrush);  iTextRenderer := TMyWriteTextRenderer.Create(cvs.RenderTarget, iSolidColorBrush);  cvs.RenderTarget.BeginDraw;  cvs.RenderTarget.Clear(D2D1ColorF(clWhite));  iTextLayout.Draw(nil, iTextRenderer, 0, 0);  cvs.RenderTarget.EndDraw();  cvs.Free;end;procedure TForm1.FormResize(Sender: TObject);begin  Repaint;end;{ TMyWriteTextRenderer }constructor TMyWriteTextRenderer.Create(ARenderTarge: ID2D1RenderTarget; AOutLineBrush: ID2D1Brush);begin  FRenderTarge := ARenderTarge;  FOutLineBrush := AOutLineBrush;end;function TMyWriteTextRenderer.DrawGlyphRun(clientDrawingContext: Pointer; baselineOriginX,  baselineOriginY: Single; measuringMode: DWRITE_MEASURING_MODE; var glyphRun: DWRITE_GLYPH_RUN;  var glyphRunDescription: DWRITE_GLYPH_RUN_DESCRIPTION; const clientDrawingEffect: IInterface): HRESULT;var  iPathGeometry: ID2D1PathGeometry;  iGeometrySink: ID2D1GeometrySink;  iTransformedGeometry: ID2D1TransformedGeometry;begin  D2DFactory.CreatePathGeometry(iPathGeometry);  iPathGeometry.Open(iGeometrySink);  glyphRun.fontFace.GetGlyphRunOutline(    glyphRun.fontEmSize,    glyphRun.glyphIndices,    glyphRun.glyphAdvances,    glyphRun.glyphOffsets,    glyphRun.glyphCount,    glyphRun.isSideways,    longBool(glyphRun.bidiLevel div 2),    iGeometrySink  );  iGeometrySink.Close;  D2DFactory.CreateTransformedGeometry(    iPathGeometry,    TD2DMatrix3x2F.Translation(baselineOriginX, baselineOriginY),    iTransformedGeometry  );  FRenderTarge.DrawGeometry(iTransformedGeometry, FOutLineBrush);  Result := S_OK;end;function TMyWriteTextRenderer.DrawInlineObject(clientDrawingContext: Pointer; originX, originY: Single;  var inlineObject: IDWriteInlineObject; isSideways, isRightToLeft: LongBool;  const clientDrawingEffect: IInterface): HRESULT;begin  Result := E_NOTIMPL;end;function TMyWriteTextRenderer.DrawStrikethrough(clientDrawingContext: Pointer; baselineOriginX,  baselineOriginY: Single; var strikethrough: DWRITE_STRIKETHROUGH;  const clientDrawingEffect: IInterface): HRESULT;begin  Result := E_NOTIMPL;end;function TMyWriteTextRenderer.DrawUnderline(clientDrawingContext: Pointer; baselineOriginX,  baselineOriginY: Single; var underline: DWRITE_UNDERLINE; const clientDrawingEffect: IInterface): HRESULT;var  rRectF: TD2DRectF;  iRectangleGeometry: ID2D1RectangleGeometry;  iTransformedGeometry: ID2D1TransformedGeometry;begin  rRectF := D2D1RectF(    0,    underline.offset,    underline.width,    underline.offset + underline.thickness  );  D2DFactory.CreateRectangleGeometry(rRectF, iRectangleGeometry);  D2DFactory.CreateTransformedGeometry(    iRectangleGeometry,    TD2DMatrix3x2F.Translation(baselineOriginX, baselineOriginY),    iTransformedGeometry  );  FRenderTarge.DrawGeometry(iTransformedGeometry, FOutLineBrush);  Result := S_OK;end;function TMyWriteTextRenderer.GetCurrentTransform(clientDrawingContext: Pointer;  var transform: DWRITE_MATRIX): HRESULT;begin  FRenderTarge.GetTransform(TD2D1Matrix3x2F(transform));  Result := S_OK;end;function TMyWriteTextRenderer.GetPixelsPerDip(clientDrawingContext: Pointer;  var pixelsPerDip: Single): HRESULT;var  x,y: Single;begin  FRenderTarge.GetDpi(x, y);  pixelsPerDip := x / 96;  Result := S_OK;end;function TMyWriteTextRenderer.IsPixelSnappingDisabled(clientDrawingContext: Pointer;  var isDisabled: LongBool): HRESULT;begin  isDisabled := False;  Result := S_OK;end;end.

效果图:
26153723_uBUk.png

转载于:https://my.oschina.net/hermer/blog/320448

你可能感兴趣的文章
Linux的起源与各发行版的基本知识
查看>>
单播包、广播包、组播包、洪泛包
查看>>
iptables命令结构之命令
查看>>
RabbitMQ之Exchange分类
查看>>
综合布线系统的构成
查看>>
计算机硬件 — 计算机简介
查看>>
关于重写session实现的时候可能会导至nginx 502的问题
查看>>
7z(p7zip)压缩软件在Linux下的安装和使用
查看>>
jetbrick-template 1.1.0 发布,支持 #tag, #macro, layout
查看>>
TCP的六个控制位
查看>>
进制转换
查看>>
我的友情链接
查看>>
新书上市:《FLUENT 14.0超级学习手册》
查看>>
mysql数据库query cache
查看>>
使用docker commit 来扩展一个image
查看>>
jsp 防止sql注入 之 preparestatement篇(转载)
查看>>
Linux之Ansible入门用法(实验解析)
查看>>
Linux系统如何在开机时修改root密码
查看>>
Anychat的绝对路径与相对路径
查看>>
我的友情链接
查看>>