Direct2D (42) : 在文本布局中嵌入图片 IDWriteTextLayout.SetInlineObject()
Direct2D (42) : 在文本布局中嵌入图片 IDWriteTextLayout.SetInlineObject()
涂孟超 发表于3年前
Direct2D (42) : 在文本布局中嵌入图片 IDWriteTextLayout.SetInlineObject()
  • 发表于 3年前
  • 阅读 70
  • 收藏 0
  • 点赞 0
  • 评论 0

腾讯云 新注册用户 域名抢购1元起>>>   


这段代码怎么也过不去了,反反复复找不到原因;有谁知道,万望提醒我一下。

上面是刚碰到错误时的求助信息;现在终于找到错误了:是 D2D1.pas 的代码有问题,修改方法如下:

{ 1、把 D2D1.pas 中 4142 行中的 var 修改为 const 或者去掉 }
function SetInlineObject(var inlineObject: IDWriteInlineObject;
  textRange: TDwriteTextRange): HResult; stdcall;

{ 2、重新编译 Direct2D.pas、D2D1.pas,最好在 Debug 和 Release 两种模式下分别编译 }

{ 3、把编译后的相关 dcu 分别覆盖到 \Program Files\Embarcadero\RAD Studio\8.0\lib\win32\ 的相应目录下 }


unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Direct2D, D2D1, Wincodec, ActiveX;

type
  TForm1 = class(TForm)
    procedure FormPaint(Sender: TObject);
    procedure FormResize(Sender: TObject);
  end;

  {实现 IDWriteInlineObject 的类}
  TDWriteInlineObject = class(TInterfacedObject, IDWriteInlineObject)
  private
    FRenderTarge: ID2D1RenderTarget;
    FBitmap: ID2D1Bitmap;
  public
    constructor Create(ARenderTarge: ID2D1RenderTarget; ABitmap: ID2D1Bitmap);
    function Draw(clientDrawingContext: Pointer; var renderer: IDWriteTextRenderer; originX: Single;
      originY: Single; isSideways: LongBool; isRightToLeft: LongBool;
      const clientDrawingEffect: IInterface): HRESULT; stdcall;
    function GetMetrics(var metrics: DWRITE_INLINE_OBJECT_METRICS): HRESULT; stdcall;
    function GetOverhangMetrics(var overhangs: DWRITE_OVERHANG_METRICS): HRESULT; stdcall;
    function GetBreakConditions(var breakConditionBefore: DWRITE_BREAK_CONDITION;
      var breakConditionAfter: DWRITE_BREAK_CONDITION): HRESULT; stdcall;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{从指定文件建立 ID2D1Bitmap 的函数}
function GetD2D1Bitmap(RenderTarget: ID2D1RenderTarget; imgPath: string): ID2D1Bitmap;
var
  iWicFactory: IWICImagingFactory;
  iWICDecoder: IWICBitmapDecoder;
  iWICFrameDecode: IWICBitmapFrameDecode;
  iFormatConverter: IWICFormatConverter;
begin
  CoCreateInstance(CLSID_WICImagingFactory, nil, CLSCTX_INPROC_SERVER, IID_IWICImagingFactory, iWicFactory);
  iWicFactory.CreateDecoderFromFilename(PWideChar(imgPath), GUID_NULL, GENERIC_READ, WICDecodeMetadataCacheOnLoad, iWICDecoder);
  iWicDecoder.GetFrame(0, iWICFrameDecode);
  iWicFactory.CreateFormatConverter(iFormatConverter);
  iFormatConverter.Initialize(iWICFrameDecode, GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, nil, 0, WICBitmapPaletteTypeMedianCut);
  RenderTarget.CreateBitmapFromWicBitmap(iFormatConverter, nil, Result);
end;

{构建 DWRITE_TEXT_RANGE 结构的函数}
function DWriteTextRange(pos,len: Cardinal): TDwriteTextRange;
begin
  Result.startPosition := pos;
  Result.length := len;
end;

procedure TForm1.FormPaint(Sender: TObject);
var
  cvs: TDirect2DCanvas;
  str: string;
  iTextFormat: IDWriteTextFormat;
  iTextLayout: IDWriteTextLayout;
  iInlineObject: IDWriteInlineObject;
  iBitmap: ID2D1Bitmap;
  iBrush: ID2D1SolidColorBrush;
begin
  str := 'Inline Object * 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
  );

  cvs := TDirect2DCanvas.Create(Canvas, ClientRect);
  cvs.RenderTarget.BeginDraw;
  cvs.RenderTarget.Clear(D2D1ColorF(clWhite));

  iBitmap := GetD2D1Bitmap(cvs.RenderTarget, 'C:\Temp\Test.jpg');
  iInlineObject := TDWriteInlineObject.Create(cvs.RenderTarget, iBitmap);
//  DWriteFactory.CreateEllipsisTrimmingSign(iTextLayout, iInlineObject); //使用这行代码可以生成表示 "..." 符号的 IDWriteInlineObject
  iTextLayout.SetInlineObject(iInlineObject, DWriteTextRange(14, 1)); {!!!}

  cvs.RenderTarget.CreateSolidColorBrush(D2D1ColorF(clBlack), nil, iBrush);
  cvs.RenderTarget.DrawTextLayout(D2D1PointF(0,0), iTextLayout, iBrush);
  cvs.RenderTarget.EndDraw();
  cvs.Free;
end;

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

{ TDWriteInlineObject }

constructor TDWriteInlineObject.Create(ARenderTarge: ID2D1RenderTarget; ABitmap: ID2D1Bitmap);
begin
  inherited Create;
  FRenderTarge := ARenderTarge;
  FBitmap := ABitmap;
end;

function TDWriteInlineObject.Draw(clientDrawingContext: Pointer; var renderer: IDWriteTextRenderer; originX,
  originY: Single; isSideways, isRightToLeft: LongBool; const clientDrawingEffect: IInterface): HRESULT;
var
  rSizeF: TD2DSizeF;
  rRectF: TD2DRectF;
begin
  FBitmap.GetSize(rSizeF);
  rRectF := D2D1RectF(originX, originY, originX+rSizeF.width, originY+rSizeF.height);
  FRenderTarge.DrawBitmap(FBitmap, @rRectF);
  Result := S_OK;
end;

function TDWriteInlineObject.GetBreakConditions(var breakConditionBefore,
  breakConditionAfter: DWRITE_BREAK_CONDITION): HRESULT;
begin
  breakConditionBefore := DWRITE_BREAK_CONDITION_NEUTRAL;
  breakConditionAfter := DWRITE_BREAK_CONDITION_NEUTRAL;
  Result := S_OK;
end;

function TDWriteInlineObject.GetMetrics(var metrics: DWRITE_INLINE_OBJECT_METRICS): HRESULT;
var
  rSizeF: TD2DSizeF;
begin
  FBitmap.GetSize(rSizeF);
  metrics.width := rSizeF.width;
  metrics.height := rSizeF.height;
  metrics.baseline := rSizeF.height;
  Result := S_OK;
end;

function TDWriteInlineObject.GetOverhangMetrics(var overhangs: DWRITE_OVERHANG_METRICS): HRESULT;
begin
  overhangs.left := 0;
  overhangs.top := 0;
  overhangs.right := 0;
  overhangs.bottom := 0;
  Result := S_OK;
end;

end.


效果图:



共有 人打赏支持
粉丝 13
博文 2004
码字总数 14107
×
涂孟超
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: