- 新增 LightTheme.xaml 浅色主题资源 - 标题栏添加主题切换按钮(☀️/🌙) - Manager 支持深浅主题互换 - 发布 Manager.exe (292KB) 和 Installer.exe (171KB) - 插件安装包 Better-Seewo.2.0.0.exe (11.6MB)
143 lines
4.6 KiB
C#
143 lines
4.6 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using DocumentFormat.OpenXml.Packaging;
|
|
using DocumentFormat.OpenXml.Presentation;
|
|
using D = DocumentFormat.OpenXml.Drawing;
|
|
|
|
namespace BetterEN5.Services.Conversion;
|
|
|
|
public class PptxImporter
|
|
{
|
|
public DocumentModel Import(string pptxPath)
|
|
{
|
|
var doc = new DocumentModel();
|
|
|
|
using var presentation = PresentationDocument.Open(pptxPath, false);
|
|
var presPart = presentation.PresentationPart!;
|
|
var pres = presPart.Presentation;
|
|
|
|
var slideSize = pres.SlideSize!;
|
|
doc.SlideWidth = slideSize.Cx!.Value;
|
|
doc.SlideHeight = slideSize.Cy!.Value;
|
|
|
|
int slideIndex = 0;
|
|
foreach (var slideId in pres.SlideIdList!.ChildElements.OfType<SlideId>())
|
|
{
|
|
slideIndex++;
|
|
var slidePart = presPart.GetPartById(slideId.RelationshipId!) as SlidePart;
|
|
if (slidePart == null) continue;
|
|
|
|
var slide = slidePart.Slide;
|
|
var slideModel = new SlideModel
|
|
{
|
|
Name = $"Slide{slideIndex}",
|
|
Width = doc.SlideWidth,
|
|
Height = doc.SlideHeight
|
|
};
|
|
|
|
ParseSlideElements(slidePart, slide, slideModel, doc);
|
|
|
|
doc.Slides.Add(slideModel);
|
|
}
|
|
|
|
return doc;
|
|
}
|
|
|
|
private void ParseSlideElements(SlidePart slidePart, Slide slide, SlideModel slideModel, DocumentModel doc)
|
|
{
|
|
if (slide.CommonSlideData?.ShapeTree == null) return;
|
|
|
|
foreach (var element in slide.CommonSlideData.ShapeTree.ChildElements)
|
|
{
|
|
switch (element)
|
|
{
|
|
case Picture pic:
|
|
ParsePicture(slidePart, pic, slideModel);
|
|
break;
|
|
case Shape shape:
|
|
ParseShape(shape, slideModel);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void ParsePicture(SlidePart slidePart, Picture pic, SlideModel slideModel)
|
|
{
|
|
var blipFill = pic.BlipFill;
|
|
if (blipFill?.Blip == null) return;
|
|
|
|
var embed = blipFill.Blip.Embed?.Value;
|
|
if (string.IsNullOrEmpty(embed)) return;
|
|
|
|
var imagePart = slidePart.GetPartById(embed) as ImagePart;
|
|
if (imagePart == null) return;
|
|
|
|
using var stream = imagePart.GetStream();
|
|
var data = new byte[stream.Length];
|
|
stream.Read(data, 0, data.Length);
|
|
|
|
var transform = pic.ShapeProperties?.Transform2D;
|
|
var img = new ImageElement
|
|
{
|
|
Data = data,
|
|
ContentType = imagePart.ContentType,
|
|
FileName = $"image{slideModel.Elements.Count + 1}{GetExtension(imagePart.ContentType)}",
|
|
X = transform?.Offset?.X?.Value ?? 0,
|
|
Y = transform?.Offset?.Y?.Value ?? 0,
|
|
Width = transform?.Extents?.Cx?.Value ?? 0,
|
|
Height = transform?.Extents?.Cy?.Value ?? 0
|
|
};
|
|
slideModel.Elements.Add(img);
|
|
}
|
|
|
|
private void ParseShape(Shape shape, SlideModel slideModel)
|
|
{
|
|
var textBody = shape.TextBody;
|
|
if (textBody == null) return;
|
|
|
|
var text = string.Concat(
|
|
textBody.Descendants<D.Text>().Select(t => t.Text));
|
|
if (string.IsNullOrWhiteSpace(text)) return;
|
|
|
|
var transform = shape.ShapeProperties?.Transform2D;
|
|
var textElem = new TextElement
|
|
{
|
|
Text = text.Trim(),
|
|
X = transform?.Offset?.X?.Value ?? 0,
|
|
Y = transform?.Offset?.Y?.Value ?? 0,
|
|
Width = transform?.Extents?.Cx?.Value ?? 0,
|
|
Height = transform?.Extents?.Cy?.Value ?? 0
|
|
};
|
|
|
|
var firstRun = textBody.Descendants<D.Run>().FirstOrDefault();
|
|
if (firstRun?.RunProperties != null)
|
|
{
|
|
var rp = firstRun.RunProperties;
|
|
textElem.FontSize = (rp.FontSize?.Value ?? 1800) / 100.0;
|
|
textElem.IsBold = rp.Bold?.Value ?? false;
|
|
|
|
var solidFill = rp.GetFirstChild<D.SolidFill>();
|
|
if (solidFill?.RgbColorModelHex?.Val?.Value != null)
|
|
textElem.FontColor = $"#{solidFill.RgbColorModelHex.Val.Value}";
|
|
else if (solidFill?.SchemeColor?.Val?.Value != null)
|
|
textElem.FontColor = $"#{solidFill.SchemeColor.Val}";
|
|
}
|
|
|
|
slideModel.Elements.Add(textElem);
|
|
}
|
|
|
|
private static string GetExtension(string contentType)
|
|
{
|
|
return contentType switch
|
|
{
|
|
"image/png" => ".png",
|
|
"image/jpeg" => ".jpg",
|
|
"image/gif" => ".gif",
|
|
"image/bmp" => ".bmp",
|
|
"image/tiff" => ".tiff",
|
|
_ => ".bin"
|
|
};
|
|
}
|
|
}
|