IDWriteGdiInterop 接口的主要用途是它提供 IDWriteBitmapRenderTarget 留出了 HDC 接口,以与 GDI、GDI+ 交互;
另提供了 LOGFONT 结构与 IDWriteFont、IDWriteFontFace 的相互转换的方法。

IDWriteGdiInterop = interface(IUnknown)
  function CreateFontFromLOGFONT( { LOGFONT -> IDWriteFont }
    var logFont: LOGFONTW; //
    out font: IDWriteFont  //
  ): HResult; stdcall;

  function ConvertFontToLOGFONT( { IDWriteFont -> LOGFONT }
    font: IDWriteFont;     //
    var logFont: LOGFONTW; //
    var isSystemFont: BOOL //如果指定的字体对象是系统字体集合的一部分则返回 True
  ): HResult; stdcall;

  function ConvertFontFaceToLOGFONT( { IDWriteFontFace -> LOGFONT }
    var font: IDWriteFontFace; //
    var logFont: LOGFONTW      //
  ): HResult; stdcall;

  function CreateFontFaceFromHdc( { HDC -> IDWriteFontFace }
    hdc: HDC;                     //
    out fontFace: IDWriteFontFace //
  ): HResult; stdcall;

  function CreateBitmapRenderTarget( { Create IDWriteBitmapRenderTarget }
    hdc: HDC;         //
    width: Cardinal;  //
    height: Cardinal; //
    out renderTarget: IDWriteBitmapRenderTarget //
  ): HResult; stdcall;
end;

{ 封装可用于呈现字形的位图和内存 DC }
IDWriteBitmapRenderTarget = interface(IUnknown)
  function DrawGlyphRun( { 将字形串绘制到位图中的指定黑框矩形中 }
    baselineOriginX: Single;                 //水平位置(DIP)
    baselineOriginY: Single;                 //垂直位置(DIP)
    measuringMode: TDWriteMeasuringMode;     //用于字形串中各字形的度量方法
    var glyphRun: TDwriteGlyphRun;           //包含字形串属性的结构
    renderingParams: IDWriteRenderingParams; //控制呈现行为的对象
    textColor: COLORREF;                     //文本的前景色
    blackBoxRect: PRect                      //黑框矩形(单位像素), 可选
  ): HResult; stdcall;

  function GetMemoryDC: HDC; stdcall; { 获取内存设备上下文的句柄 }
  function GetPixelsPerDip: Single; stdcall; { 设置每个 DIP 的位图像素数;1 DIP(与设备无关的像素) = 1/96 英寸 }
  function SetPixelsPerDip(pixelsPerDip: Single): HResult; stdcall; { 获取每个 DIP 的位图像素数 }
  function GetCurrentTransform(var transform: TDwriteMatrix): HResult; stdcall; { 获取将抽象坐标映射为 DIP 的转换, 和世界转换无关 }
  function SetCurrentTransform(var transform: TDwriteMatrix): HResult; stdcall; { 设置将抽象坐标映射为 DIP 的转换, 和世界转换无关 }
  function GetSize(var size: TSize): HResult; stdcall; { 获取位图尺寸 }
  function Resize(width: Cardinal; height: Cardinal): HResult; stdcall; { 调整位图大小 }
end;

{LOGFONTW 结构}
tagLOGFONTW = record
  lfHeight: Longint;      //指定字体的字符单元或字符的高度
  lfWidth: Longint;       //指定字体中的字符的平均宽度
  lfEscapement: Longint;  //指定设备的行距向量和 x 轴之间的角度, 单位 1/10 度
  lfOrientation: Longint; //指定设备的每个字符的基线和 x 轴之间的角度, 单位 1/10 度
  lfWeight: Longint;      //粗细
  lfItalic: Byte;         //斜体
  lfUnderline: Byte;      //下划线
  lfStrikeOut: Byte;      //删除线
  lfCharSet: Byte;        //字符集
  lfOutPrecision: Byte;   //输出精度
  lfClipPrecision: Byte;  //剪辑精度
  lfQuality: Byte;        //输出质量
  lfPitchAndFamily: Byte; //字体系列
  lfFaceName: array[0..LF_FACESIZE - 1] of WideChar; //字体名称
end;


练习从 GDI 结构获取 IDWriteFont 和 IDWriteFontFace

uses Direct2D, D2D1;

{ IDWriteGdiInterop.CreateFontFromLOGFONT() 方法测试 }
procedure TForm1.Button1Click(Sender: TObject);
var
  iGdiInterop: IDWriteGdiInterop;
  iFontFace: IDWriteFontFace;
begin
  Self.Font.Name := '宋体';
  DWriteFactory.GetGdiInterop(iGdiInterop);                    //获取 IDWriteGdiInterop 接口
  iGdiInterop.CreateFontFaceFromHdc(Canvas.Handle, iFontFace); //TLogFont -> IDWriteFont

  {获取当前字体的字形总数}
  ShowMessage(IntToStr(iFontFace.GetGlyphCount)); //22141
end;

{ IDWriteGdiInterop.CreateFontFromLOGFONT() 方法测试 }
procedure TForm1.Button2Click(Sender: TObject);
var
  logFont: TLogFont;
  iGdiInterop: IDWriteGdiInterop;
  iFont: IDWriteFont;
  iFontFace: IDWriteFontFace;
  iFontFamily: IDWriteFontFamily;
  iLocalizedStrings: IDWriteLocalizedStrings;
  buf: array[0..LF_FACESIZE] of Char;
begin
  Self.Font.Name := '宋体';
  GetObject(Self.Font.Handle, SizeOf(TLogFont), @logFont); //获取当前窗口使用的 TLogFont 结构
  DWriteFactory.GetGdiInterop(iGdiInterop);                //获取 IDWriteGdiInterop 接口
  iGdiInterop.CreateFontFromLOGFONT(logFont, iFont);       //TLogFont -> IDWriteFont

  {从 IDWriteFont 获取字体名称}
  iFont.GetFontFamily(iFontFamily);
  iFontFamily.GetFamilyNames(iLocalizedStrings);
  iLocalizedStrings.GetString(iLocalizedStrings.GetCount-1, buf, Length(buf));
  ShowMessage(buf); //宋体

  iFont.CreateFontFace(iFontFace); //IDWriteFont -> IDWriteFontFace
  {获取当前字体的字形总数}
  ShowMessage(IntToStr(iFontFace.GetGlyphCount)); //22141
end;


使用 IDWriteBitmapRenderTarget

uses Direct2D, D2D1;

procedure TForm1.FormPaint(Sender: TObject);
var
  str1,str2: string;
  logFont: TLogFont;
  iGdiInterop: IDWriteGdiInterop;
  iFont: IDWriteFont;
  iTextFormat: IDWriteTextFormat;
  iTextLayout: IDWriteTextLayout;
  rTextRange: TDwriteTextRange;
  iBitmapRenderTarget: IDWriteBitmapRenderTarget;
  cvs: TDirect2DCanvas;
  iBrush: ID2D1SolidColorBrush;
  rRect: TRect;
  gdiCVS: TCanvas;
begin
  str1 := 'Sample text using GDI TextOut.';
  str2 := 'Sample text using DirectWrite.';

  Canvas.Font.Name := '微软雅黑';
  Canvas.Font.Size := 32;
  rRect := Bounds(0, 0, ClientWidth, ClientHeight div 2);

  {从 IDWriteGdiInterop.IDWriteBitmapRenderTarget 获取 DC, 并以 GDI 的方式输出文本}
  DWriteFactory.GetGdiInterop(iGdiInterop);
  iGdiInterop.CreateBitmapRenderTarget(Canvas.Handle, ClientWidth, ClientHeight div 2, iBitmapRenderTarget);
  gdiCVS := TCanvas.Create;
  gdiCVS.Handle := iBitmapRenderTarget.GetMemoryDC;
  gdiCVS.Font := Canvas.Font;
  gdiCVS.Rectangle(rRect);
  gdiCVS.TextRect(rRect, str1, [tfSingleLine, tfCenter, tfVerticalCenter]);
  gdiCVS.Free;

  {把 IDWriteBitmapRenderTarget 中的绘制结果复制到当前窗口}
  BitBlt(
    Canvas.Handle,
    0, 0,
    ClientWidth, ClientHeight div 2,
    iBitmapRenderTarget.GetMemoryDC,
    0, 0,
    SRCCOPY
  );

  {根据当前窗口的 Font 建立 IDWriteFont}
  GetObject(Canvas.Font.Handle, SizeOf(TLogFont), @logFont);
  iGdiInterop.CreateFontFromLOGFONT(logFont, iFont);

  {以 DirectWrite 方式输出文本}
  DWriteFactory.CreateTextFormat(
    PWideChar(Canvas.Font.Name),
    nil,
    iFont.GetWeight,
    iFont.GetStyle,
    iFont.GetStretch,
    -MulDiv(logFont.lfHeight, 96, GetDeviceCaps(Canvas.Handle, LOGPIXELSX)), //FontSize
    '',
    iTextFormat
  );
  iTextFormat.SetTextAlignment(DWRITE_TEXT_ALIGNMENT_CENTER);
  iTextFormat.SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_CENTER);

  DWriteFactory.CreateTextLayout(
    PWideChar(str2),
    Length(str2),
    iTextFormat,
    ClientWidth,
    ClientHeight div 2,
    iTextLayout
  );

  rTextRange.startPosition := 0;
  rTextRange.length := Length(str1);
//  iTextLayout.SetUnderline(True, rTextRange);
  iTextLayout.SetStrikethrough(True, rTextRange);

  OffsetRect(rRect, 0, ClientHeight div 2);
  cvs := TDirect2DCanvas.Create(Canvas, rRect);
  cvs.RenderTarget.CreateSolidColorBrush(D2D1ColorF(clRed), nil, iBrush);
  cvs.RenderTarget.BeginDraw;
  cvs.RenderTarget.DrawTextLayout(D2D1PointF(0, 0), iTextLayout, iBrush);
  cvs.RenderTarget.EndDraw;
  cvs.Free;
end;

procedure TForm1.FormResize(Sender: TObject);
begin
  Repaint;
end;


效果图:



posted on 2011-04-16 13:00  万一  阅读(2716)  评论(1编辑  收藏  举报