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;
效果图: