Skip to main content

dotnet 读 WPF 源代码笔记 了解 WPF 已知问题 用户设备上不存在 Arial 字体将导致应用闪退

dotnet 读 WPF 源代码笔记 了解 WPF 已知问题 用户设备上不存在 Arial 字体将导致应用闪退 - Hi friends, I hope you are all in good healthkanakoroku, In the article you are reading this time with the title dotnet 读 WPF 源代码笔记 了解 WPF 已知问题 用户设备上不存在 Arial 字体将导致应用闪退 , We have prepared this article well for you to read and take information in it. hopefully the contents of the post what we write you can understand. ok, happy reading.

Title : dotnet 读 WPF 源代码笔记 了解 WPF 已知问题 用户设备上不存在 Arial 字体将导致应用闪退
link : dotnet 读 WPF 源代码笔记 了解 WPF 已知问题 用户设备上不存在 Arial 字体将导致应用闪退

Baca juga


dotnet 读 WPF 源代码笔记 了解 WPF 已知问题 用户设备上不存在 Arial 字体将导致应用闪退

本文来告诉大家 WPF 已知问题,在用户的设备上,如果不存在 Arial 字体,同时安装了一些诡异的字体,那么也许就会让应用在使用到诡异的字体的时候,软件闪退

本文来告诉大家 WPF 已知问题,在用户的设备上,如果不存在 Arial 字体,同时安装了一些诡异的字体,那么也许就会让应用在使用到诡异的字体的时候,软件闪退

在 WPF 的 FontFamily.cs 字体类里面,有一个叫 FirstFontFamily 的属性,这个属性的逻辑代码里面将包括在当前字体太过诡异时,自动 Fallback 到默认的字体,而默认的字体就是 Arial 字体。这个属性将会在很多逻辑被调用,如获取 FamilyNames 时

  public LanguageSpecificStringDictionary FamilyNames  {   get   {    CompositeFontFamily compositeFont = FirstFontFamily as CompositeFontFamily;    if (compositeFont != null)    {     // Return the read/write dictionary of family names.     return compositeFont.FamilyNames;    }    else    {     // Return a wrapper for the cached family's read-only dictionary.     return new LanguageSpecificStringDictionary(FirstFontFamily.Names);    }   }  }

在进入到寻找 Fallback 字体将会进入到 Invariant 的 Assert 判断方法,在这里面找不到 Arial 字体时,将会进入 Environment.FailFast 让应用程序闪退

以下是 FirstFontFamily 属性的代码,代码我删除了不关键部分

 if (family == null) {  FontStyle style  = FontStyles.Normal;  FontWeight weight = FontWeights.Normal;  FontStretch stretch = FontStretches.Normal;  family = FindFirstFontFamilyAndFace(ref style, ref weight, ref stretch);  if (family == null)  {  	 // 进入这里的逻辑将会去寻找 Fallback 字体   // fall back to null font   family = LookupFontFamily(NullFontFamilyCanonicalName);   Invariant.Assert(family != null);  } 

在 LookupFontFamily 函数里面,将会尝试去寻找 Arial 字体,上面代码的 NullFontFamilyCanonicalName 默认就是使用 Arial 字体

  internal static readonly CanonicalFontFamilyReference NullFontFamilyCanonicalName = CanonicalFontFamilyReference.Create(null, "#ARIAL");

在 LookupFontFamily 函数里面将会调用 LookupFontFamilyAndFace 函数去寻找传入的字体,寻找的方法是从 _defaultFamilyCollection 去寻找传入的字体

这里的 _defaultFamilyCollection 是在静态构造时获取的,代码如下

  private static volatile FamilyCollection _defaultFamilyCollection = PreCreateDefaultFamilyCollection();

以上的 PreCreateDefaultFamilyCollection 函数,实际就是读取 WindowsFontsUriObject 列表,这里的 Windows 指的不是窗口,而是指 Windows 系统

  private static FamilyCollection PreCreateDefaultFamilyCollection()  {   FamilyCollection familyCollection = FamilyCollection.FromWindowsFonts(Util.WindowsFontsUriObject);   return familyCollection;  }

以上的 WindowsFontsUriObject 定义如下

  private const string WinDir = "windir";   string s = Environment.GetEnvironmentVariable(WinDir) + @"\Fonts\";   _windowsFontsLocalPath = s.ToUpperInvariant();   _windowsFontsUriObject = new Uri(_windowsFontsLocalPath, UriKind.Absolute);

也就是说读取的就是 windir 文件夹下的 Fonts 文件夹,也就是 C:\Windows\Fonts\ 文件夹

在 LookupFontFamilyAndFace 将会尝试去从 C:\Windows\Fonts\ 文件夹寻找字体

    IFontFamily fontFamily = familyCollection.LookupFamily    (     canonicalFamilyReference.FamilyName,     ref style,     ref weight,     ref stretch    );

假定用户从 C:\Windows\Fonts\ 文件夹删除了 Arial 字体,那么将找不到字体,返回是空

也就是 LookupFontFamily 将返回空

  internal static IFontFamily LookupFontFamily(CanonicalFontFamilyReference canonicalName)  {   FontStyle style  = FontStyles.Normal;   FontWeight weight = FontWeights.Normal;   FontStretch stretch = FontStretches.Normal;   return LookupFontFamilyAndFace(canonicalName, ref style, ref weight, ref stretch);  }

在 FirstFontFamily 属性里面,判断字体存在的代码如下

 family = LookupFontFamily(NullFontFamilyCanonicalName); Invariant.Assert(family != null); 

在用户删除了 Arial 字体,将会让 family 是空,而在 Invariant 的定义代码如下

 internal static void Assert(bool condition) {  if (!condition)  {   FailFast(null, null);  } } 

以上的 FailFast 方法将会调用 Environment.FailFast 方法

 private // DO NOT MAKE PUBLIC OR INTERNAL -- See security note  static void FailFast(string message, string detailMessage) {  if (Invariant.IsDialogOverrideEnabled)  {   // This is the override for stress and other automation.   // Automated systems can't handle a popup-dialog, so let   // them jump straight into the debugger.   Debugger.Break();  }  Debug.Assert(false, "Invariant failure: " + message, detailMessage);  Environment.FailFast(SR.Get(SRID.InvariantFailure)); } 

调用 Environment.FailFast 之后,应用程序就闪退了,只有在系统事件里面看到记录

我认为这是一个不合理的设计,至少在框架层不应该有这样的逻辑,作为一个十分成熟的 UI 框架,应该能兼容各个诡异的系统,我将这个问题报告给官方,请看 WPF known issues: Application will FailFast when not find the Arial font from system · Issue #4464 · dotnet/wpf









原文转载:http://www.shaoqun.com/a/728775.html

跨境电商:https://www.ikjzd.com/

tiki:https://www.ikjzd.com/w/2053

新蛋:https://www.ikjzd.com/w/79


本文来告诉大家WPF已知问题,在用户的设备上,如果不存在Arial字体,同时安装了一些诡异的字体,那么也许就会让应用在使用到诡异的字体的时候,软件闪退本文来告诉大家WPF已知问题,在用户的设备上,如果不存在Arial字体,同时安装了一些诡异的字体,那么也许就会让应用在使用到诡异的字体的时候,软件闪退在WPF的FontFamily.cs字体类里面,有一个叫FirstFontFamily的属性,这个属
邮乐网购:https://www.ikjzd.com/w/1776
萌店:https://www.ikjzd.com/w/1538
zappos.com:https://www.ikjzd.com/w/330
卖家侵权案件频发,如何规避出口产品侵权问题?:https://www.ikjzd.com/home/99350
老公偷拍闺蜜艳照存手机里观赏:http://lady.shaoqun.com/m/a/271242.html
小天在厨房插杨伯母 寄住在父母朋友家的刺激经历:http://lady.shaoqun.com/a/274567.html


That's the article dotnet 读 WPF 源代码笔记 了解 WPF 已知问题 用户设备上不存在 Arial 字体将导致应用闪退

That's it for the article dotnet 读 WPF 源代码笔记 了解 WPF 已知问题 用户设备上不存在 Arial 字体将导致应用闪退 this time, hopefully can be useful for all of you. okay, see you in another article post.

You are now reading the article dotnet 读 WPF 源代码笔记 了解 WPF 已知问题 用户设备上不存在 Arial 字体将导致应用闪退 with link address https://kanakoroku.blogspot.com/2021/05/dotnet-wpf-wpf-arial.html
Comment Policy: Please write your comments that match the topic of this page post. Comments containing links will not be displayed until they are approved.
Open Comments
Close Comment