一、实现思路
通过继承IDWriteTextRenderer定义自己的文本渲染类并重写DrawGlyphRun方法,最终将该类实例作为 IDWriteTextLayout::Draw的参数传入进行文本的绘制。

二、代码实现
1、自定义文本渲染类

class CustomTextRenderer : public IDWriteTextRenderer
{
protected:ULONG m_cRef;ID2D1Factory* m_pD2DFactory;ID2D1RenderTarget *m_pRenderTarget;ID2D1Brush *m_pTextBodyBrush;ID2D1SolidColorBrush *m_pTextOutlineBrush;float mStrokeWidth;public:CustomTextRenderer(ID2D1Factory* pD2DFactory, ID2D1RenderTarget* pRenderTarget,ID2D1Brush *pTextBodyBrush, ID2D1SolidColorBrush *pTextOutlineBrush, float strokeWidth = 1.0f);~CustomTextRenderer();STDMETHOD(DrawGlyphRun)(void                               *clientDrawingContext,FLOAT                              baselineOriginX,FLOAT                              baselineOriginY,DWRITE_MEASURING_MODE              measuringMode,DWRITE_GLYPH_RUN const             *glyphRun,DWRITE_GLYPH_RUN_DESCRIPTION const *glyphRunDescription,IUnknown                           *clientDrawingEffect);STDMETHOD(DrawUnderline)(void                   *clientDrawingContext,FLOAT                  baselineOriginX,FLOAT                  baselineOriginY,DWRITE_UNDERLINE const *underline,IUnknown               *clientDrawingEffect);STDMETHOD(DrawStrikethrough)(void                       *clientDrawingContext,FLOAT                      baselineOriginX,FLOAT                      baselineOriginY,DWRITE_STRIKETHROUGH const *strikethrough,IUnknown                   *clientDrawingEffect);STDMETHOD(DrawInlineObject)(void                *clientDrawingContext,FLOAT               originX,FLOAT               originY,IDWriteInlineObject *inlineObject,BOOL                isSideways,BOOL                isRightToLeft,IUnknown            *clientDrawingEffect){return E_NOTIMPL;}STDMETHOD(IsPixelSnappingDisabled)(void* clientDrawingContext,BOOL* isDisabled){*isDisabled = FALSE;return S_OK;}STDMETHOD(GetCurrentTransform)(void* clientDrawingContext,DWRITE_MATRIX* transform){m_pRenderTarget->GetTransform(reinterpret_cast<D2D1_MATRIX_3X2_F*>(transform));return S_OK;}STDMETHOD(GetPixelsPerDip)(void* clientDrawingContext,FLOAT* pixelsPerDip){float x, yUnused;m_pRenderTarget->GetDpi(&x, &yUnused);*pixelsPerDip = x / 96;return S_OK;}HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void FAR* FAR* ppvObj){if (iid == IID_IUnknown /*|| iid == IID_IDWritePixelSnapping || iid == IID_IDWriteTextRenderer*/){*ppvObj = this;AddRef();return NOERROR;}return E_NOINTERFACE;}ULONG STDMETHODCALLTYPE AddRef(){      return ++m_cRef;}ULONG STDMETHODCALLTYPE Release(){// Decrement the object's internal counter.if (0 == --m_cRef){delete this;}return m_cRef;}
};

2、DrawGlyphRun方法实现

HRESULT CustomTextRenderer::DrawGlyphRun(void *clientDrawingContext, FLOAT baselineOriginX, FLOAT baselineOriginY,DWRITE_MEASURING_MODE measuringMode, DWRITE_GLYPH_RUN const *glyphRun,DWRITE_GLYPH_RUN_DESCRIPTION const *glyphRunDescription, IUnknown *clientDrawingEffect)
{HRESULT hr = S_OK;ID2D1PathGeometry* pPathGeometry = nullptr;hr = m_pD2DFactory->CreatePathGeometry(&pPathGeometry);ID2D1GeometrySink* pSink = nullptr;     hr = pPathGeometry->Open(&pSink);hr = glyphRun->fontFace->GetGlyphRunOutline(glyphRun->fontEmSize,glyphRun->glyphIndices,glyphRun->glyphAdvances,glyphRun->glyphOffsets,glyphRun->glyphCount,glyphRun->isSideways,glyphRun->bidiLevel,pSink);hr = pSink->Close();// Initialize a matrix to translate the origin of the glyph run.D2D1::Matrix3x2F const matrix = D2D1::Matrix3x2F(1.0f, 0.0f,0.0f, 1.0f,baselineOriginX, baselineOriginY);ID2D1TransformedGeometry *pTransformedGeometry = nullptr;hr = m_pD2DFactory->CreateTransformedGeometry(pPathGeometry, &matrix, &pTransformedGeometry);// 绘制文字描边部分m_pRenderTarget->DrawGeometry(pTransformedGeometry, m_pTextOutlineBrush, mStrokeWidth);// 绘制文字填充部分m_pRenderTarget->FillGeometry(pTransformedGeometry, m_pTextBodyBrush);SafeRelease(&pPathGeometry);SafeRelease(&pSink);SafeRelease(&pTransformedGeometry);return hr;
}

3、使用自定义渲染对象绘制文本

m_pTextRenderer = new CustomTextRenderer(
m_pDirect2dFactory, m_pRenderTarget,
m_pTextBodyBrush, m_pTextOutlineBrush, strokeWidth);m_pRenderTarget->BeginDraw();
m_pRenderTarget->SetTransform(D2D1::Matrix3x2F::Identity());
m_pTextLayout->Draw(nullptr, m_pTextRenderer, 0.0f, 0.0f);
m_pRenderTarget->EndDraw();

三、绘制结果
1、只有描边部分

2、只有填充部分

3、描边和填充

四、总结
1、自定义文本渲染类的核心是重写IDWriteTextRenderer::DrawGlyphRun这个回调函数。
2、使用自定义文本渲染类绘制文字必须调用IDWriteTextLayout::Draw,而不是ID2D1RenderTarget::DrawText和ID2D1RenderTarget::DrawTextLayout。

PS:
本文代码是基于微软官方文档示例所实现,详情可参考:
how-to-implement-a-custom-text-renderer
direct2d-quickstart

Direct2D实现文字的描边和填充相关推荐

  1. Ai 文字正确描边 文字描边

    Ai 文字正确描边 文字描边 每次制作宣传材料的时候,这个问题都困扰着我.我一般都是文字转曲后再操作,但这样在再次修改文字的时候会变的非常麻烦,需要重新新一遍,或在转曲的时候备份一份. 现在终于解决了 ...

  2. html文字加描边效果,怎么用css给文字加描边?

    怎么用css给文字加描边?下面本篇文章给大家介绍一下使用CSS给文字添加描边效果的方法.有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助. 方法1:使用text-shadow属性给文字加 ...

  3. 3 photolemur 样式_css3怎么给文字加描边?css3实现字体描边样式的方法(代码详解)...

    css3怎么给文字加描边?本篇文章就给大家介绍css3给文字加描边的方法,让大家了解css text-stroke属性实现字体描边样式的具体方法.有一定的参考价值,有需要的朋友可以参考一下,希望对你们 ...

  4. html给图片加描边,photoshop中如何给图片文字加描边

    在图片的后期处理中,图片上的文字就如男人的手表.女人的首饰一样,适当而精彩的文字能给图片起到点睛的装饰作用.当然文字的添加,并不是单纯地打 字上图那么简单,无论是构图.编排.修饰都要反复斟酌,很多软件 ...

  5. html语言填充没有只有描边,HTML5 Canvas笔记——交互绘制文本(描边、填充、阴影、渐变填充、图案填充、文本的属性设置)...

    (1)文本的描边.填充.阴影 (2)文本的渐变填充 (3)文本的图案填充 (4)文本的属性设置及效果呈现 交互绘制文本.html 交互绘制文本 body { background: #eeeeee; ...

  6. Illustrator 描边,填充,扩展

    Illustrator 首先 ai中的是以线为形状的. 视图→轮廓中可以看到都是一条条线 视图,轮廓在这 描边 ai中的描边是对于线进行描边. 填充 ai中的填充是封闭图形进行填充 对比 一样的正方形 ...

  7. css字体描边加阴影,css text-shadow 轻松实现文字投影/描边/浮雕/剪纸/发光效果

    css3很多知识值得我们去了解,一些我们惯常用图片制作出来的效果,也许用CSS3几行代码就能实现,正如本文介绍的,使用css text-shadow 属性,就能轻松实现文字投影/描边/浮雕/剪纸/发光 ...

  8. 2020.9.25--PS--图片合成、图片描边和填充、变形

    图片合成 把一张图片中的物体抠出来放到另一张的合适位置进行调整 图片描边和填充 打开一张图片,用矩形选框工具或椭圆选框工具画出矩形选区或圆形选区,点"编辑"中"描边&qu ...

  9. 2020.10.10--PS--路径运算、路径总结、路径描边和填充

    路径运算 路径组合.路径加减:画出需要的路径形状在菜单栏下面一行进行组合,加减 路径总结 一个图形可以用多个锚点组成最少可以用两个锚点组成,控制锚点的手柄进行制作 路径描边.填充 用钢笔工具画出路径, ...

最新文章

  1. Linux下root密码忘记的解决办法
  2. itstime后面跟什么_一文讲透什么是引流
  3. 网站SEO优化中长尾关键词的特征有哪些?
  4. 2018\National _C_C++_B\1.换零钞
  5. 为什么我放弃饿了么产品总监,却要从事自由职业?
  6. springMVC接受参数总结
  7. 如何自定义FusionCharts图表上的工具提示?
  8. 5动态显示图片_单片机入门 数码管的静态显示和动态显示 壁纸
  9. python中spider的用法_Spider-PyQuery基本用法(示例代码)
  10. 从数据库中读取数据,创建XML文件并更新维护XML
  11. 文档交接说明书(模板)
  12. apple tv 开发_如何在Apple TV上播放计算机中的视频文件
  13. finereport与finebi差别_FineBI与FineReport对比
  14. C++ 常用数学函数
  15. Eclips IDE安装Python
  16. 阿龙的学习笔记---如何用C++ STL 实现一个 LRU缓存
  17. UE4.26源码版学习广域网独立服务器时遇到的客户端运行黑屏问题
  18. vim教程之基本使用
  19. Python采集二手房源数据信息 基础版, 多线程版
  20. 数字图像处理知识点梳理——第二章 数字图像基础

热门文章

  1. 第一、二、三代半导体的区别
  2. 【论文】一张图了解理学硕士论文中图表尺寸规范(适用于一般性情况)
  3. Proteus8.9程序安装及注意事项
  4. linux的火墙管理
  5. gdc服务器是什么系统,gdc设置服务器地址
  6. 结构体 计算平均成绩
  7. 司马懿的6句人生真谛
  8. 现代操作系统之多处理机系统(上)
  9. 在不同的时间段在页面上显示不同图片和不同的问候语。
  10. Word中批量设置参考文献为上标