• Direct2D (43) : IDWriteGdiInterop 接口



    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;         //
         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( 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;
    


    效果图:



  • 相关阅读:
    打破 Serverless 落地边界,阿里云 SAE 发布 5 大新特性
    2021云栖大会|东方通正式加入阿里云云原生合作伙伴计划,强强联手共创国产数字化转型新风向!
    跨越行业绊脚石,阿里云函数计算发布 7 大技术突破
    OpenYurt 深度解读|开启边缘设备的云原生管理能力
    云原生网关开源、自研、商业化三位一体战略背后的思考
    云栖发布|企业级互联网架构全新升级 ,助力数字创新
    云栖收官:想跟远道而来的朋友们说
    阿里云容器服务多项重磅发布:高效智能、安全无界的新一代平台
    云栖掠影|回首开源十年,RocketMQ 焕发新生
    云栖大会第二天:ACK Anywhere 来了
  • 原文地址:https://www.cnblogs.com/del/p/2016973.html
Copyright © 2020-2023  润新知