zoukankan      html  css  js  c++  java
  • Direct2D (40) : 分别设置 IDWriteTextLayout 中文本的颜色


    function SetDrawingEffect(
      const drawingEffect: IUnknown; //颜色接口; 该接口需自己定义和实现, 只要能存取颜色即可
      textRange: TDwriteTextRange    //要设置的范围
    ): HResult; stdcall;
    


    测试代码:

    unit Unit1;
    
    interface
    
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, Direct2D, D2D1;
    
    const
      SID_IColorDrawingEffect = '{22FBE54E-5058-47C4-9A7C-6482827713A6}'; //这是使用 Ctri+Shift+G 随意产生的
      IID_IColorDrawingEffect: TGUID = SID_IColorDrawingEffect;
    
    type
      TForm1 = class(TForm)
        procedure FormPaint(Sender: TObject);
        procedure FormResize(Sender: TObject);
      end;
    
      {自定义的颜色接口}
      IColorDrawingEffect = interface
      [SID_IColorDrawingEffect]
        function GetColor: TD2D1ColorF;
      end;
    
      {实现 IColorDrawingEffect 的类}
      TColorDrawingEffect = class(TInterfacedObject, IColorDrawingEffect)
      private
        FColor: TD2D1ColorF;
      public
        constructor Create(const AColor: TD2D1ColorF);
        function GetColor: TD2D1ColorF;
      end;
    
      {实现 IWriteTextRenderer 接口}
      TMyWriteTextRenderer = class(TInterfacedObject, IDWriteTextRenderer)
      private
        FRenderTarge: ID2D1RenderTarget;
      public
        constructor Create(ARenderTarge: ID2D1RenderTarget);
        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;
      iTextLayout: IDWriteTextLayout;
      iTypography: IDWriteTypography;
      iTextRenderer: IDWriteTextRenderer;
      iColor1,iColor2,iColor3: IColorDrawingEffect;
    begin
      str := 'Client Drawing Effect Example!';
    
      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
      );
    
      DWriteFactory.CreateTypography(iTypography);
      iTypography.AddFontFeature(DWriteFontFeature(DWRITE_FONT_FEATURE_TAG_STYLISTIC_SET_7, 1));
      iTextLayout.SetTypography(iTypography, DWriteTextRange(0, Length(str)));
    
      {分段设置颜色; 算上没有设置的范围, 下面的设置将会有四种颜色}
      iColor1 := TColorDrawingEffect.Create(D2D1ColorF(clRed));
      iColor2 := TColorDrawingEffect.Create(D2D1ColorF(clBlue));
      iColor3 := TColorDrawingEffect.Create(D2D1ColorF(clGreen));
      iTextLayout.SetDrawingEffect(iColor1, DWriteTextRange(0, 14));
      iTextLayout.SetDrawingEffect(iColor2, DWriteTextRange(14, 7));
      iTextLayout.SetDrawingEffect(iColor3, DWriteTextRange(21, 8));
    
      cvs := TDirect2DCanvas.Create(Canvas, ClientRect);
      iTextRenderer := TMyWriteTextRenderer.Create(cvs.RenderTarget);
      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;
    
    { TColorDrawingEffect }
    constructor TColorDrawingEffect.Create(const AColor: TD2D1ColorF);
    begin
      inherited Create;
      FColor := AColor;
    end;
    
    function TColorDrawingEffect.GetColor: TD2D1ColorF;
    begin
      Result := FColor;
    end;
    
    { TMyWriteTextRenderer }
    
    constructor TMyWriteTextRenderer.Create(ARenderTarge: ID2D1RenderTarget);
    begin
      FRenderTarge := ARenderTarge;
    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;
      iBrush: ID2D1SolidColorBrush;
      iColorEffect: IColorDrawingEffect; //供注释掉的代码使用
      rColor: TD2D1ColorF;
    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
      );
    
      {获取颜色}
      rColor := D2D1ColorF(clBlack);
      if Assigned(clientDrawingEffect) then rColor := IColorDrawingEffect(clientDrawingEffect).GetColor;
      {下面是官方获取颜色的写法}
    //  if clientDrawingEffect <> nil then
    //  begin
    //    clientDrawingEffect.QueryInterface(IID_IColorDrawingEffect, iColorEffect);
    //    rColor := iColorEffect.GetColor;
    //  end else
    //    rColor := D2D1ColorF(clBlack);
    
      FRenderTarge.CreateSolidColorBrush(rColor, nil, iBrush);
      FRenderTarge.DrawGeometry(iTransformedGeometry, iBrush);
      FRenderTarge.FillGeometry(iTransformedGeometry, iBrush);
      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;
      iBrush: ID2D1SolidColorBrush;
      rColor: TD2D1ColorF;
    begin
      rRectF := D2D1RectF(
        0,
        strikethrough.offset,
        strikethrough.width,
        strikethrough.offset + strikethrough.thickness
      );
      D2DFactory.CreateRectangleGeometry(rRectF, iRectangleGeometry);
    
      D2DFactory.CreateTransformedGeometry(
        iRectangleGeometry,
        TD2DMatrix3x2F.Translation(baselineOriginX, baselineOriginY),
        iTransformedGeometry
      );
    
      rColor := D2D1ColorF(clBlack); //没有设置的部分默认使用黑色
      if Assigned(clientDrawingEffect) then rColor := IColorDrawingEffect(clientDrawingEffect).GetColor;
      FRenderTarge.CreateSolidColorBrush(rColor, nil, iBrush);
      FRenderTarge.DrawGeometry(iTransformedGeometry, iBrush);
      FRenderTarge.FillGeometry(iTransformedGeometry, iBrush);
      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;
      iBrush: ID2D1SolidColorBrush;
      rColor: TD2D1ColorF;
    begin
      rRectF := D2D1RectF(
        0,
        underline.offset,
        underline.width,
        underline.offset + underline.thickness
      );
      D2DFactory.CreateRectangleGeometry(rRectF, iRectangleGeometry);
    
      D2DFactory.CreateTransformedGeometry(
        iRectangleGeometry,
        TD2DMatrix3x2F.Translation(baselineOriginX, baselineOriginY),
        iTransformedGeometry
      );
    
      rColor := D2D1ColorF(clBlack);
      if Assigned(clientDrawingEffect) then rColor := IColorDrawingEffect(clientDrawingEffect).GetColor;
      FRenderTarge.CreateSolidColorBrush(rColor, nil, iBrush);
      FRenderTarge.DrawGeometry(iTransformedGeometry, iBrush);
      FRenderTarge.FillGeometry(iTransformedGeometry, iBrush);
      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.
    


    效果图:



  • 相关阅读:
    @hdu
    @51nod
    @51nod
    @51nod
    JS-正则表达式常规运用
    CSS-复选框默认样式修改
    Vue-路由传参query与params
    Vue-阻止页面回退
    Vue-表单提交
    JS-原生的ajax
  • 原文地址:https://www.cnblogs.com/del/p/2015631.html
Copyright © 2011-2022 走看看