Skip to content

Commit 63b2ec4

Browse files
committed
完成测试应用
1 parent 04f20de commit 63b2ec4

7 files changed

Lines changed: 761 additions & 9 deletions

File tree

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: 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: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
1-
using System;
2-
using System.Collections.Generic;
3-
using System.Linq;
4-
using System.Text;
5-
using System.Threading.Tasks;
6-
1+
using DocumentFormat.OpenXml.Flatten.Compatibilities.Packaging;
2+
using DocumentFormat.OpenXml.Packaging;
3+
using DocumentFormat.OpenXml.Presentation;
74
using Microsoft.Maui.Graphics;
85

96
namespace MauiPptxViewerCore;
@@ -17,14 +14,35 @@ public PptxViewer(FileInfo pptxFile, ICanvas canvas)
1714
}
1815

1916
public FileInfo PptxFile { get; }
20-
public ICanvas Canvas { get; }
17+
public ICanvas Canvas { get; }
18+
19+
private Stream? _stream; // do not care about dispose it... This is a demo
2120

2221
public void Open()
2322
{
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);
2429

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+
}
2540
}
41+
42+
private PptxDocument? _pptxDocument;
2643
}
2744

45+
2846
//public record PptxViewerBuilder(FileInfo PptxFile, ICanvas Canvas)
2947
//{
3048
//}

0 commit comments

Comments
 (0)