This article is a PowerPoint series blog using WPF. This article tells you how to analyze the text stroke effect in PPT and draw it in WPF applications to achieve the same pixel level.
background knowledge
在开始之前,期望你了解了 PPT 解析的入门知识。如对 PPT 解析了解很少,请参阅 C# dotnet 使用 OpenXml 解析 PPT 文件
In PPT, you can set stroke effects on some text. The stroke effect is not a special effect from the OpenXML layer, but only a border attribute. In PPT, you can add the Outline border attribute to text to make the text stroke
effect
Before we start, let's let's show the effect first

parsing
Before starting, read the document first, the code is as follows. The following code and test files can be obtained at the end of this article
var file = new FileInfo("Test.pptx");
using var presentationDocument = PresentationDocument.Open(file.FullName, false);
var slide = presentationDocument.PresentationPart!.SlideParts.First().Slide;
In order to tell you the core logic easily, the following code in this article will make the judgment of ignoring many parameters based on the Test.pptx document. In actual projects, please also make your own parameter judgment logic.
This test document has only one element on the first page, which is the element with text strokes in this article. The obtained code is as follows
var shape = slide.CommonSlideData!.ShapeTree!.GetFirstChild<Shape>()!;
The OpenXML content of this Shape is roughly as follows
<p:sp>
<p:spPr>
<a:prstGeom prst="rect">
</a:prstGeom>
<a:noFill />
</p:spPr>
<p:txBody>
<a:bodyPr wrap="square" rtlCol="0">
<a:spAutoFit />
</a:bodyPr>
<a:lstStyle />
<a:p>
<a:r>
<a:rPr lang="zh-CN" altLang="en-US" sz="10000">
<a:ln w="9525">
<a:solidFill>
<a:srgbClr val="00FF00" />
</a:solidFill>
</a:ln>
</a:rPr>
<a:t>一行文本</a:t>
</a:r>
<a:endParaRPr lang="en-US" sz="10000" dirty="0" />
</a:p>
</p:txBody>
</p:sp>
The text box inside PPT is also a shape, which is the default rectangle.
var shapeProperties = shape.ShapeProperties!;
var presetGeometry = shapeProperties.GetFirstChild<PresetGeometry>()!;
// 这是一个文本框
Debug.Assert(presetGeometry.Preset?.Value == ShapeTypeValues.Rectangle);
Debug.Assert(shapeProperties.GetFirstChild<NoFill>() is not null);
The above only tells you how to get the shape, you need to judge it in your own business code.
Get the text of the text box, you can use the following code
var textBody = shape.TextBody!;
Debug.Assert(textBody != null);
There are many paragraphs in a text. In paragraphs, the text has different styles. For example, a paragraph can have different bold text. The same style of text is placed in a TextRun. Different styles of text are placed in different TextRuns
Therefore, parsing requires first traversing the paragraph and then traversing the TextRun element
foreach (var paragraph in textBody.Elements<DocumentFormat.OpenXml.Drawing.Paragraph>())
{
// 这个文本段落是没有属性的,为了方便样式,就不写代码
//if (paragraph.ParagraphProperties != null)
foreach (var run in paragraph.Elements<DocumentFormat.OpenXml.Drawing.Run>())
{
}
}
Get the following properties for TextRun
var runProperties = run.RunProperties!;
You can get information such as the font size of the current text on this property, and the code is as follows
var fontSize = new PoundHundredfold(runProperties.FontSize!.Value).ToPound();
Next is the core of this article. Get the Outline attribute, the code is as follows
var outline = runProperties.Outline!;
The corresponding OpenXML code is as follows
<a:ln w="9525"> <a:solidFill>
<a:srgbClr val="00FF00" />
</a:solidFill>
</a:ln>
We only focus on thickness and color, and the acquisition methods are as follows
var outlineWidth = new Emu(outline.Width!.Value);
The code to get the color is as follows
var solidFill = outline.GetFirstChild<SolidFill>()!;
var rgbColorModelHex = solidFill.GetFirstChild<RgbColorModelHex>()!;
var colorText = rgbColorModelHex.Val!;
通过 win10 uwp 颜色转换 的方法可以将 colorText 转换为 SolidColorBrush 对象
Then get the text content, and you will probably be done
// 默认字体前景色是黑色
var text = run.Text!.Text;
The next step is to draw in the interface
drawn
如 WPF 文字描边 博客,先通过 FormattedText 构建出 Geometry 对象,再通过 Geometry 对象进行绘制
code is as follows
var formattedText = new FormattedText(text, CultureInfo.CurrentCulture,
FlowDirection.LeftToRight,
new Typeface
(
// 默认是宋体
new FontFamily("宋体"),
FontStyles.Normal,
FontWeights.Normal,
FontStretches.Normal
),
// 在 WPF 里面,采用的是 EM 单位,约等于像素单位
fontSize.ToPixel().Value,
Brushes.Black, 96);
The code to build the Geometry object through FormatedText is as follows
var geometry = formattedText.BuildGeometry(new ());
Then draw the Geometry onto the interface through System.Windows.Shapes.Path
var path = new System.Windows.Shapes.Path
{
Data = geometry,
Fill = Brushes.Black,
Stroke = BrushCreator.CreateSolidColorBrush(colorText),
StrokeThickness = outlineWidth.ToPixel().Value,
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center,
};
Root.Children.Add(path);
With the above code, you can draw the same interface as PPT on the interface
code
本文所有代码和测试文件放在github 和 gitee 欢迎访问
You can obtain the source code of this article by creating an empty folder first, then using the command line cd command to enter the empty folder, and entering the following code on the command line to obtain the code of this article
git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin 71af5b0e47493ff7f5f43be33583265805da9d84
The above is the source of gitee. If gitee cannot be accessed, please replace it with the source of github
git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git
After getting the code, go to the Pptx folder
reference
Blog in the Blog Park is only backed up and will not be updated when published. If you want to see the latest blogs, please visit https://blog.lindexi.com/
Creative Commons license
本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名林德熙(包含链接:http://blog.csdn.net/lindexi_gd ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系。