本記事は、WPFを使用してPowerPointのような機能を実現するシリーズの一部です。今回は、PPT内のテキストに設定された輪郭効果(テキストの縁取り)を解析し、WPFアプリケーションでピクセル単位で同じように描画する方法を解説します。
背景知識
始める前に、PPT解析の基本的な知識を理解していることを前提とします。PPT解析について詳しくない場合は、C# dotnet 使用 OpenXml 解析 PPT 文件 を参照してください。
PPTでは、テキストの一部の文字に輪郭効果を設定できます。この輪郭効果は、OpenXMLのレベルでは特殊効果(エフェクト)ではなく、単なる枠線(ボーダー)プロパティです。PPTでは、テキストに Outline 枠線プロパティを追加することで、文字に輪郭を付けることができます。
効果
本題に入る前に、実際の効果をご確認ください。

解析
まず、ドキュメントを読み込むコードから始めます。以下のコードとテストファイルは、この記事の末尾で入手できます。
var file = new FileInfo("Test.pptx");
using var presentationDocument = PresentationDocument.Open(file.FullName, false);
var slide = presentationDocument.PresentationPart!.SlideParts.First().Slide;
以降のコードでは、核心部分のロジックを分かりやすく説明するため、Test.pptx ドキュメントに基づいて多くのパラメータチェックを省略しています。実際のプロジェクトでは、適切なパラメータチェックロジックを追加してください。
このテストドキュメントの最初のページには、本記事で説明するテキスト輪郭効果を持つ要素のみが配置されています。この要素を取得するコードは以下の通りです。
var shape = slide.CommonSlideData!.ShapeTree!.GetFirstChild<Shape>()!;
この Shape の OpenXML の内容は以下のようになります。
<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>
PPT内のテキストボックスも図形(Shape)であり、デフォルトでは矩形です。
var shapeProperties = shape.ShapeProperties!;
var presetGeometry = shapeProperties.GetFirstChild<PresetGeometry>()!;
// これはテキストボックスです
Debug.Assert(presetGeometry.Preset?.Value == ShapeTypeValues.Rectangle);
Debug.Assert(shapeProperties.GetFirstChild<NoFill>() is not null);
上記は図形を取得する方法を示しているだけです。実際の業務コードでは、適切な判断を加えてください。
テキストボックスのテキストを取得するには、以下のコードを使用します。
var textBody = shape.TextBody!;
Debug.Assert(textBody != null);
テキストには複数の段落が含まれ、段落内ではテキストに異なるスタイル(例:一部だけ太字)を適用できます。同じスタイルのテキストは1つの TextRun にまとめられ、異なるスタイルのテキストは別々の TextRun に格納されます。
そのため、解析ではまず段落を反復処理し、次に TextRun 要素を反復処理する必要があります。
foreach (var paragraph in textBody.Elements<DocumentFormat.OpenXml.Drawing.Paragraph>())
{
// このテキスト段落にはプロパティがありません。スタイルのためにコードは書きません
//if (paragraph.ParagraphProperties != null)
foreach (var run in paragraph.Elements<DocumentFormat.OpenXml.Drawing.Run>())
{
}
}
TextRun のプロパティを取得するには、以下のコードを使用します。
var runProperties = run.RunProperties!;
このプロパティから現在のテキストのフォントサイズなどの情報を取得できます。コードは以下の通りです。
var fontSize = new PoundHundredfold(runProperties.FontSize!.Value).ToPound();
次に、この記事の核心である Outline プロパティを取得します。コードは以下の通りです。
var outline = runProperties.Outline!;
対応する OpenXML コードは以下の通りです。
<a:ln w="9525"> <a:solidFill>
<a:srgbClr val="00FF00" />
</a:solidFill>
</a:ln>
ここで注目する基本情報は太さと色だけです。それぞれの取得方法は以下の通りです。
var outlineWidth = new Emu(outline.Width!.Value);
色を取得するコードは以下の通りです。
var solidFill = outline.GetFirstChild<SolidFill>()!;
var rgbColorModelHex = solidFill.GetFirstChild<RgbColorModelHex>()!;
var colorText = rgbColorModelHex.Val!;
win10 uwp 颜色转换 の方法を使用して、colorText を SolidColorBrush オブジェクトに変換できます。
最後にテキストの内容を取得すれば、おおむね完了です。
// デフォルトのフォント前景色は黒です
var text = run.Text!.Text;
次は、UIに描画する段階です。
描画
WPF 文字描边 のブログ記事と同様に、まず FormattedText を使用して Geometry オブジェクトを構築し、次にその Geometry オブジェクトを使用して描画します。
コードは以下の通りです。
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);
FormattedText から Geometry オブジェクトを構築するコードは以下の通りです。
var geometry = formattedText.BuildGeometry(new ());
次に、System.Windows.Shapes.Path を使用して Geometry をUIに描画します。
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);
上記のコードにより、PPTと同じ外観のテキストをUIに描画できます。
コード
この記事のすべてのコードとテストファイルは、github および gitee で入手できます。ぜひアクセスしてください。
以下の方法でこの記事のソースコードを取得できます。まず空のフォルダを作成し、次にコマンドラインで cd コマンドを使用してこの空のフォルダに移動し、コマンドラインで以下のコードを入力すると、この記事のコードを取得できます。
git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin 71af5b0e47493ff7f5f43be33583265805da9d84
上記は gitee のソースを使用しています。gitee にアクセスできない場合は、github のソースに置き換えてください。
git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git
コードを取得したら、Pptx フォルダに移動してください。
参考
- WPF 文字描边
- 詳細については、Office 使用 OpenXML SDK 解析文档博客目录 を参照してください。
このブログ記事はバックアップです。公開後は更新されません。最新のブログをご覧になりたい場合は、https://blog.lindexi.com/ にアクセスしてください。
クリエイティブ・コモンズ・ライセンス
この作品は、クリエイティブ・コモンズ 表示 - 非営利 - 継承 4.0 国際 ライセンス の下に提供されています。転載、使用、再公開は自由ですが、記事の著者名 林德熙 (リンク: http://blog.csdn.net/lindexi_gd を含む) を必ず明記し、営利目的での使用は禁止し、この記事に基づいて修正された作品は同じライセンスで公開する必要があります。ご質問がある場合は、メール でご連絡ください。