Skip to content

Commit 98b9b0f

Browse files
authored
Merge pull request #37 from dotnet-campus/t/lindexi/Demo
加上示例代码
2 parents 2b3668c + a562af5 commit 98b9b0f

27 files changed

Lines changed: 2733 additions & 3 deletions

Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,6 @@
1111
<Description>A dotnet tool to assist in editing Office document files</Description>
1212

1313
<RepositoryType>git</RepositoryType>
14-
<Copyright>Copyright © 2020-2021 dotnet campus, All Rights Reserved.</Copyright>
14+
<Copyright>Copyright © 2020-2022 dotnet campus, All Rights Reserved.</Copyright>
1515
</PropertyGroup>
1616
</Project>

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ DLL Pakcage:
9494

9595
### Usage
9696

97-
See [DocumentFormat.OpenXml.Flatten README.md](src/DocumentFormat.OpenXml.Flatten/README.md)
97+
See [DocumentFormat.OpenXml.Flatten README.md](src/DocumentFormat.OpenXml.Flatten/README.md) and the [Demo](demo).
9898

9999

100100
# Thanks

README.zh-cn.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ DLL 包:
103103

104104
### 使用方法
105105

106-
具体使用方法请参阅 [DocumentFormat.OpenXml.Flatten 使用文档](src/DocumentFormat.OpenXml.Flatten/README.md)
106+
具体使用方法请参阅 [DocumentFormat.OpenXml.Flatten 使用文档](src/DocumentFormat.OpenXml.Flatten/README.md)[示例代码](demo)
107107

108108
# 感谢
109109

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using DocumentFormat.OpenXml.Packaging;
2+
using DocumentFormat.OpenXml.Presentation;
3+
4+
namespace MauiPptxViewerCore;
5+
6+
record DocumentModel(PresentationDocument PresentationDocument, Presentation Presentation)
7+
{
8+
public PresentationPart PresentationPart
9+
// 这里能拿到 Presentation 那就一定能拿到 PresentationPart 对象,一定不是空
10+
=> Presentation.PresentationPart!;
11+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net6.0</TargetFramework>
5+
<ImplicitUsings>enable</ImplicitUsings>
6+
<Nullable>enable</Nullable>
7+
</PropertyGroup>
8+
<ItemGroup>
9+
<PackageReference Include="Microsoft.Maui.Graphics" Version="6.0.501" />
10+
</ItemGroup>
11+
<ItemGroup>
12+
<ProjectReference Include="..\..\..\..\src\DocumentFormat.OpenXml.Flatten\DocumentFormat.OpenXml.Flatten\dotnetCampus.DocumentFormat.OpenXml.Flatten.csproj" />
13+
</ItemGroup>
14+
</Project>
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
using System.Diagnostics;
2+
using DocumentFormat.OpenXml.Packaging;
3+
using DocumentFormat.OpenXml.Presentation;
4+
5+
namespace MauiPptxViewerCore;
6+
7+
class PptxDocument
8+
{
9+
public PptxDocument(DocumentModel documentModel)
10+
{
11+
DocumentModel = documentModel;
12+
13+
var slideIdList = documentModel.Presentation.SlideIdList;
14+
15+
if (slideIdList is null)
16+
{
17+
// 这个文档连一页都没有…
18+
throw new ArgumentException($"The Empty document. The number of slide is 0.");
19+
}
20+
21+
var presentationPart = documentModel.PresentationPart;
22+
23+
var pptxSlideList = new List<PptxSlide>();
24+
25+
// [dotnet OpenXML 幻灯片 PPTX 的 Slide Id 和页面序号的关系](https://blog.lindexi.com/post/dotnet-OpenXML-%E5%B9%BB%E7%81%AF%E7%89%87-PPTX-%E7%9A%84-Slide-Id-%E5%92%8C%E9%A1%B5%E9%9D%A2%E5%BA%8F%E5%8F%B7%E7%9A%84%E5%85%B3%E7%B3%BB.html)
26+
foreach (var slideId in slideIdList.ChildElements.OfType<SlideId>())
27+
{
28+
// 获取页面内容
29+
Debug.Assert(slideId.RelationshipId != null, "slideId.RelationshipId != null");
30+
SlidePart slidePart = (SlidePart) presentationPart.GetPartById(slideId.RelationshipId!);
31+
32+
Debug.Assert(slideId.Id is not null, "slideId.Id != null");
33+
var pptxSlide = new PptxSlide(slideId.Id!.Value, slidePart, documentModel);
34+
35+
pptxSlideList.Add(pptxSlide);
36+
}
37+
38+
SlideList = pptxSlideList;
39+
}
40+
41+
public DocumentModel DocumentModel { get; }
42+
43+
public List<PptxSlide> SlideList { get; }
44+
}
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
using DocumentFormat.OpenXml;
2+
using DocumentFormat.OpenXml.Drawing;
3+
using DocumentFormat.OpenXml.Flatten;
4+
using DocumentFormat.OpenXml.Flatten.ElementConverters.CommonElement;
5+
using DocumentFormat.OpenXml.Flatten.ElementConverters.Primitive;
6+
using DocumentFormat.OpenXml.Flatten.ElementConverters.ShapeGeometryConverters;
7+
using DocumentFormat.OpenXml.Flatten.Framework.Context;
8+
using DocumentFormat.OpenXml.Packaging;
9+
10+
using dotnetCampus.OpenXmlUnitConverter;
11+
12+
using MauiPptxViewerCore.Utils;
13+
14+
using Microsoft.Maui.Graphics;
15+
16+
using Shape = DocumentFormat.OpenXml.Presentation.Shape;
17+
18+
namespace MauiPptxViewerCore;
19+
20+
public class PptxSlide
21+
{
22+
internal PptxSlide(uint slideId, SlidePart slidePart, DocumentModel documentModel)
23+
{
24+
SlideId = slideId;
25+
SlidePart = slidePart;
26+
DocumentModel = documentModel;
27+
}
28+
29+
public UInt32 SlideId { get; }
30+
public SlidePart SlidePart { get; }
31+
private DocumentModel DocumentModel { get; }
32+
33+
public void Render(ICanvas canvas)
34+
{
35+
var slide = SlidePart.Slide;
36+
37+
var slideContext = new SlideContext(slide, DocumentModel.PresentationDocument);
38+
39+
foreach (var openXmlElement in slide.CommonSlideData!.ShapeTree!.ChildElements)
40+
{
41+
canvas.SaveState();
42+
43+
var openXmlElementFlatten = new OpenXmlElementFlatten();
44+
var newElement = openXmlElementFlatten.GetFlattenElement(openXmlElement, slideContext, shouldCloneOriginElement: false);
45+
46+
//var rootElement ??= slideContext.RootElement;
47+
48+
//var currentPart = slideContext.GetCurrentPart();
49+
//var colorMap = slideContext.GetColorMap();
50+
//var colorScheme = slideContext.GetColorScheme();
51+
52+
if (newElement is Shape shape)
53+
{
54+
RenderShape(canvas, newElement, slideContext, shape);
55+
}
56+
else
57+
{
58+
// 其他类型的元素
59+
}
60+
61+
canvas.RestoreState();
62+
}
63+
}
64+
65+
private void RenderShape(ICanvas canvas, OpenXmlElement newElement, SlideContext slideContext, Shape shape)
66+
{
67+
var transformData = newElement.GetOrCreateTransformData(slideContext);
68+
69+
// 这里渲染采用像素单位,需要进行转换
70+
// 设置坐标
71+
canvas.Translate((float)transformData.OffsetX.ToPixel().Value, (float)transformData.OffsetY.ToPixel().Value);
72+
73+
var shapeProperties = shape.ShapeProperties;
74+
if (shapeProperties == null)
75+
{
76+
return;
77+
}
78+
79+
var solidFill = shapeProperties.GetFirstChild<SolidFill>();
80+
if (solidFill != null)
81+
{
82+
var aRgbColor = ColorHelper.BuildColor(solidFill, slideContext);
83+
if (aRgbColor != null)
84+
{
85+
canvas.FillColor = ARgbToColor(aRgbColor);
86+
}
87+
}
88+
89+
// 获取线条
90+
var outline = shapeProperties.GetFirstChild<Outline>();
91+
if (outline != null)
92+
{
93+
if (outline.Width is not null)
94+
{
95+
var emu = new Emu(outline.Width);
96+
canvas.StrokeSize = (float)emu.ToPixel().Value;
97+
}
98+
99+
var lineFill = outline.GetFirstChild<SolidFill>();
100+
if (lineFill != null)
101+
{
102+
var aRgbColor = ColorHelper.BuildColor(lineFill, slideContext);
103+
if (aRgbColor != null)
104+
{
105+
canvas.StrokeColor = ARgbToColor(aRgbColor);
106+
}
107+
}
108+
}
109+
110+
var svgPath = shape.ToSvgPath();
111+
var multiShapePaths = svgPath?.MultiShapePaths;
112+
113+
if (multiShapePaths != null)
114+
{
115+
foreach (var multiShapePath in multiShapePaths)
116+
{
117+
PathF path = PathConverter.ToPath(multiShapePath.Path);
118+
119+
if (multiShapePath.IsFilled)
120+
{
121+
canvas.FillPath(path, WindingMode.NonZero);
122+
}
123+
124+
if (multiShapePath.IsStroke)
125+
{
126+
canvas.DrawPath(path);
127+
}
128+
}
129+
}
130+
}
131+
132+
private static Color ARgbToColor(ARgbColor aRgbColor)
133+
{
134+
var color = new Color(aRgbColor.R, aRgbColor.G, aRgbColor.B, aRgbColor.A);
135+
return color;
136+
}
137+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
using DocumentFormat.OpenXml.Flatten.Compatibilities.Packaging;
2+
using DocumentFormat.OpenXml.Packaging;
3+
using DocumentFormat.OpenXml.Presentation;
4+
using Microsoft.Maui.Graphics;
5+
6+
namespace MauiPptxViewerCore;
7+
8+
public class PptxViewer
9+
{
10+
public PptxViewer(FileInfo pptxFile, ICanvas canvas)
11+
{
12+
PptxFile = pptxFile;
13+
Canvas = canvas;
14+
}
15+
16+
public FileInfo PptxFile { get; }
17+
public ICanvas Canvas { get; }
18+
19+
private Stream? _stream; // do not care about dispose it... This is a demo
20+
21+
public void Open()
22+
{
23+
_stream = PptxFile.Open(FileMode.Open, FileAccess.ReadWrite);
24+
25+
// 解析细节请参阅 [Office 使用 OpenXML SDK 解析文档博客目录](https://blog.lindexi.com/post/Office-%E4%BD%BF%E7%94%A8-OpenXML-SDK-%E8%A7%A3%E6%9E%90%E6%96%87%E6%A1%A3%E5%8D%9A%E5%AE%A2%E7%9B%AE%E5%BD%95.html )
26+
var package = CompatiblePackageProvider.OpenPackage(_stream, FileMode.Open, FileAccess.ReadWrite);
27+
28+
PresentationDocument presentationDocument = PresentationDocument.Open(package);
29+
30+
Presentation presentation = presentationDocument.PresentationPart!.Presentation;
31+
32+
var documentModel = new DocumentModel(presentationDocument, presentation);
33+
_pptxDocument = new PptxDocument(documentModel);
34+
35+
var pptxSlide = _pptxDocument.SlideList.FirstOrDefault();
36+
if (pptxSlide != null)
37+
{
38+
pptxSlide.Render(Canvas);
39+
}
40+
}
41+
42+
private PptxDocument? _pptxDocument;
43+
}
44+
45+
46+
//public record PptxViewerBuilder(FileInfo PptxFile, ICanvas Canvas)
47+
//{
48+
//}

0 commit comments

Comments
 (0)