在 WPF 里面的 GlyphRun 里,有一个令人迷惑的 DeviceFontName 属性,似乎给这个属性传入什么值,结果都不会有变更。通过阅读源代码,可以了解到,这是一个没什么用途的属性。本文将告诉大家这个属性的细节逻辑

在上一篇博客 WPF 简单聊聊如何使用 DrawGlyphRun 绘制文本 里面就提到如何创建 GlyphRun 对象,在创建的时候发现设置的 DeviceFontName 参数,无论设置为什么值,结果都没有变化

官方文档对于 GlyphRun.DeviceFontName 的描述也是比较不清不楚的。中文文档里面是机器翻译,不如看看英文原文吧

When a GlyphRun is rendered on a device that has built-in support for the named device font, the GlyphRun should be rendered using a device specific mechanism for selecting that font, and by sending Unicode code points rather than glyph indices. When rendering onto a device that does not include built-in support for the named device font, DeviceFontName should be ignored.

我本来以为这是一个能用来优化性能的属性,但是我似乎没有在网上找到大佬们讨论过这个属性。好在 WPF 是完全开源的,我就开始阅读源代码。通过阅读源代码发现这个属性其实没有什么作用,属性的定义代码如下

    public class GlyphRun : DUCE.IResource, ISupportInitialize
{
/// <summary>
/// Identifies a specific device font for which the GlyphRun has been optimized. When a GlyphRun is
/// being rendered on a device that has built-in support for this named font, then the GlyphRun should be rendered using a
/// possibly device specific mechanism for selecting that font, and by sending the Unicode codepoints rather than the
/// glyph indices. When rendering onto a device that does not include built-in support for the named font,
/// this property should be ignored.
/// </summary>
public string DeviceFontName
{
get
{
CheckInitialized();
return _deviceFontName;
}
set
{
CheckInitializing(); // This can only be set during initialization.
_deviceFontName = value;
}
} private string _deviceFontName; ...// 忽略其他代码
}

无论是 _deviceFontName 还是 DeviceFontName 属性,唯一的作用就是给自己,也就是给 _deviceFontNameDeviceFontName 提供赋值。完全就是自己玩自己的代码。看看 ReSharper 帮我找到的引用关系图

至于 DeviceFontName 属性,完全只有一个逻辑在使用,那就是用来创建 GlyphRun 副本时作为参数传入,如下面代码

namespace System.Windows.Xps.Serialization
{
internal class VisualSerializer: IMetroDrawingContext
{
private static GlyphRun FilterXmlInvalidChar(GlyphRun glyphRun)
{
...// 忽略其他代码 GlyphRun filtered = new GlyphRun(
glyphRun.GlyphTypeface,
glyphRun.BidiLevel,
glyphRun.IsSideways,
glyphRun.FontRenderingEmSize,
glyphRun.PixelsPerDip,
glyphRun.GlyphIndices,
glyphRun.BaselineOrigin,
glyphRun.AdvanceWidths,
glyphRun.GlyphOffsets,
filteredCharacters,
glyphRun.DeviceFontName,
glyphRun.ClusterMap,
glyphRun.CaretStops,
glyphRun.Language
); return filtered;
}
...// 忽略其他代码
}
}

可以看到,这是一个完全没有实际作用的属性,这也就是为什么传入任何的值,都不会影响结果的原因

我猜测这是在远古的 WPF 存在多个代码版本时,在某些代码版本,这个属性是有实际实现逻辑

但是我好奇的是,在 DX 上是没有任何可以和这个属性对应的,如果有优化,那是如何实现的,还请有了解的大佬教教我

当前的 WPF 在 https://github.com/dotnet/wpf 完全开源,使用友好的 MIT 协议,意味着允许任何人任何组织和企业任意处置,包括使用,复制,修改,合并,发表,分发,再授权,或者销售。在仓库里面包含了完全的构建逻辑,只需要本地的网络足够好(因为需要下载一堆构建工具),即可进行本地构建

dotnet 读 WPF 源代码笔记 GlyphRun 的 DeviceFontName 的功能是什么的更多相关文章

  1. dotnet 读 WPF 源代码笔记 布局时 Arrange 如何影响元素渲染坐标

    大家是否好奇,在 WPF 里面,对 UIElement 重写 OnRender 方法进行渲染的内容,是如何受到上层容器控件的布局而进行坐标偏移.如有两个放入到 StackPanel 的自定义 UIEl ...

  2. dotnet 读 WPF 源代码笔记 渲染收集是如何触发

    在 WPF 里面,渲染可以从架构上划分为两层.上层是 WPF 框架的 OnRender 之类的函数,作用是收集应用程序渲染的命令.上层将收集到的应用程序绘制渲染的命令传给下层,下层是 WPF 的 GF ...

  3. 读Flask源代码学习Python--config原理

    读Flask源代码学习Python--config原理 个人学习笔记,水平有限.如果理解错误的地方,请大家指出来,谢谢!第一次写文章,发现好累--!. 起因   莫名其妙在第一份工作中使用了从来没有接 ...

  4. 《深入浅出WPF》笔记——绘画与动画

    <深入浅出WPF>笔记——绘画与动画   本篇将记录一下如何在WPF中绘画和设计动画,这方面一直都不是VS的强项,然而它有一套利器Blend:这方面也不是我的优势,幸好我有博客园,能记录一 ...

  5. 《深入浅出WPF》笔记——资源篇

    原文:<深入浅出WPF>笔记--资源篇 前面的记录有的地方已经用到了资源,本文就来详细的记录一下WPF中的资源.我们平时的“资源”一词是指“资财之源”,是创造人类社会财富的源泉.在计算机程 ...

  6. 在Linux上编译dotnet cli的源代码生成.NET Core SDK的安装包

    .NET 的开源,有了更多的DIY乐趣.这篇博文记录一下在新安装的 Linux Ubuntu 14.04 上通过自己动手编译 dotnet cli 的源代码生成 .net core sdk 的 deb ...

  7. [WPF源代码]QQ空间相册下载工具

    放一个WPF源代码,源代码地址 http://download.csdn.net/detail/witch_soya/6195987 代码没多少技术含量,就是用WPF做的一个QQ空间相册下载工具,效果 ...

  8. WPF学习笔记-用Expression Design制作矢量图然后导出为XAML

    WPF学习笔记-用Expression Design制作矢量图然后导出为XAML 第一次用Windows live writer写东西,感觉不错,哈哈~~ 1.在白纸上完全凭感觉,想象来画图难度很大, ...

  9. WPF 学习笔记-在WPF下创建托盘图标

    原文:WPF 学习笔记-在WPF下创建托盘图标 首先需要在项目中引用System.Windows.Forms,System.Drawing; using System; using System.Co ...

  10. WPF 学习笔记-设置属性使窗口不可改变大小

    原文:WPF 学习笔记-设置属性使窗口不可改变大小 调整Windows下的ResizeMode属性: ResizeMode = NoResize Resize属性是控制Windows是否可以改变大小, ...

随机推荐

  1. 懂一点前端—Vue快速入门

    01. 什么是 Vue Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架,是当下很火的一个 JavaScript MVVM 库,是以 数据驱动和组件化 的思想构建的 ...

  2. 基于quartus的高级时序分析

    基于quartus的高级时序分析 一.派生时钟和异步存储器 派生时钟就是和独立时钟存在频率或者相位关系的时钟,异步存储器就是具有存储读写异步功能的存储器.在时序分析中,这两个部分的静态时序分析是需要设 ...

  3. 【已解决】Hadoop_01 Linux修改hosts文件

    设置主机名 [root@localhost ~]# hostnamectl set-hostname s1[root@localhost ~]# reboot 修改hosts文件 [root@mast ...

  4. Luna likes Love 题解

    Problem Link 简要题意 题目很清楚. 分析 定理 两个人中左边的人一直向右运动,和两人向中间走所用的 步数相同 证明 假设有两组人为 \(a_l , a_r , b_l , b_r (a_ ...

  5. io_utils/time_utils

    io_utils.h #pragma once #include<stdio.h> #include<stdarg.h> void PrintBinary(unsigned i ...

  6. 关于 ThreadLocalRandom 随机数生成器

    ThreadLocalRandom 线程安全随机数获取. 示例随机整数:java.util.concurrent.ThreadLocalRandom.current().nextInt(); 线程Th ...

  7. 冲刺 NOIP2024 之动态规划专题

    专题链接 B - Birds \(3.19\) . 混合背包 \(DP\) . 定义 \(f_{i,j}\) 表示取到鸟巢 \(i\) ,获得 \(j\) 只小鸟时所剩的魔力值. 显然有 \(f_{0 ...

  8. #离线,倒序,线段树#Comet OJ - Contest #15 E 栈的数据结构题

    题目 初始时有 \(N\) 个空的栈,编号为 \(1 \sim N\),有以下三种类型的指令: push \(L\) \(R\) \(v\):把编号 \(L \sim R\) 这连续 \(R-L+1\ ...

  9. #构造#B 连通子图

    题目 给定正整数\(k\),构造一棵树,使得包含了\(1\)号点的连通子图个数恰好为\(k\). 连通子图就是点集的一个子集(可以为全集),使得该点集中任意两个点均可以经过该点集中的点相互到达. 分析 ...

  10. 使用Python的turtle模块绘制美丽的樱花树

    引言 Python的turtle模块是一个直观的图形化编程工具,让用户通过控制海龟在屏幕上的移动来绘制各种形状和图案.turtle模块的独特之处在于其简洁易懂的操作方式以及与用户的互动性.用户可以轻松 ...