Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

同步11月版本 #41

Merged
merged 1 commit into from
Dec 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -697,8 +697,10 @@ internal void AddContentType(CompatiblePackage.PackUriHelper.ValidatedPartUri pa
//partUri provided. Override takes precedence over the default entries
if (_overrideDictionary != null)
{
if (_overrideDictionary.ContainsKey(partUri))
return _overrideDictionary[partUri];
if (_overrideDictionary.TryGetValue(partUri, out var result))
{
return result;
}
}

//Step 2: Check if there is a default entry corresponding to the
Expand Down Expand Up @@ -789,9 +791,11 @@ private void EnsureOverrideDictionary()
{
// The part Uris are stored in the Override Dictionary in their original form , but they are compared
// in a normalized manner using the PartUriComparer
if (_overrideDictionary == null)
_overrideDictionary =
new Dictionary<CompatiblePackage.PackUriHelper.ValidatedPartUri, CompatiblePackage.ContentType>(OverrideDictionaryInitialSize);
_overrideDictionary ??= new Dictionary<CompatiblePackage.PackUriHelper.ValidatedPartUri, CompatiblePackage.ContentType>(
OverrideDictionaryInitialSize,
// 这里需要忽略字符串的大小写
// 修复 https://github.com/dotnet/Open-XML-SDK/issues/1355
lindexi marked this conversation as resolved.
Show resolved Hide resolved
new ValidatedPartUriIgnoreCaseEqualityComparer());
}

private void ParseContentTypesFile(
Expand Down Expand Up @@ -1097,5 +1101,19 @@ private void ThrowIfXmlAttributeMissing(string attributeName, string? attributeV
private const string PartNameAttributeName = "PartName";
private const string TemporaryPartNameWithoutExtension = "/tempfiles/sample.";
}

class ValidatedPartUriIgnoreCaseEqualityComparer : IEqualityComparer<
CompatiblePackage.PackUriHelper.ValidatedPartUri>
{
public bool Equals(PackUriHelper.ValidatedPartUri x, PackUriHelper.ValidatedPartUri y)
{
return StringComparer.OrdinalIgnoreCase.Equals(x.NormalizedPartUriString, y.NormalizedPartUriString);
}

public int GetHashCode(PackUriHelper.ValidatedPartUri obj)
{
return StringComparer.OrdinalIgnoreCase.GetHashCode(obj.NormalizedPartUriString);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ protected override string GetContentTypeCore()
//Step 2: 通过路径进行特殊判断
// 例如 Slide 几的页面路径
var uri = partUri.OriginalString;
if (Regex.IsMatch(uri, @"/ppt/slides/slide\d+.xml"))
if (Regex.IsMatch(uri, @"/ppt/slides/slide\d+\.xml"))
{
// "/ppt/slides/slide0.xml"
return new CompatiblePackage.ContentType(
Expand Down Expand Up @@ -84,6 +84,20 @@ protected override string GetContentTypeCore()
return new CompatiblePackage.ContentType("application/vnd.openxmlformats-officedocument.presentationml.notesMaster+xml");
}

if (Regex.IsMatch(uri, @"/ppt/diagrams/drawing\d+\.xml"))
{
// /ppt/diagrams/drawing0.xml
// application/vnd.ms-office.drawingml.diagramDrawing+xml
return new CompatiblePackage.ContentType("application/vnd.ms-office.drawingml.diagramDrawing+xml");
}

if (Regex.IsMatch(uri, @"/tags/tag\d+\.xml"))
{
// /tags/tag0.xml
// application/vnd.openxmlformats-officedocument.presentationml.tags+xml
return new CompatiblePackage.ContentType("application/vnd.openxmlformats-officedocument.presentationml.tags+xml");
}

//Step 3: Check if there is a default entry corresponding to the
//extension of the partUri provided.
string extension = partUri.PartUriExtension;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,19 @@ public readonly struct ShapePath
/// 创建PPT的Geometry Path
/// </summary>
/// <param name="path">OpenXml Path字符串</param>
/// <param name="fillMode">OpenXml的Path Fill Mode </param>
/// <param name="isStroke">是否有轮廓</param>
/// <param name="isExtrusionOk">指定使用 3D 拉伸可能在此路径</param>
/// <param name="fillMode">OpenXml的Path Fill Mode:默认为Norm </param>
/// <param name="isStroke">是否有轮廓:默认为True</param>
/// <param name="isExtrusionOk">指定使用 3D 拉伸可能在此路径:默认为False</param>
/// <param name="emuWidth">指定的宽度或在路径坐标系统中应在使用的最大的 x 坐标</param>
/// <param name="emuHeight">指定框架的高度或在路径坐标系统中应在使用的最大的 y 坐标</param>
public ShapePath(string path, PathFillModeValues fillMode = PathFillModeValues.Norm, bool isStroke = true, bool isExtrusionOk = false, double? emuWidth = null, double? emuHeight = null)
/// <remarks>参考文档:Ecma Office Open XML Part 1 - Fundamentals And Markup Language Reference - 20.1.9.15 path (Shape Path)</remarks>
public ShapePath(string path, PathFillModeValues? fillMode = PathFillModeValues.Norm, bool? isStroke = true, bool? isExtrusionOk = false, double? emuWidth = null, double? emuHeight = null)
{
Path = path;
IsStroke = isStroke;
FillMode = fillMode;
IsStroke = isStroke ?? true;
FillMode = fillMode ?? PathFillModeValues.Norm;
IsFilled = fillMode is not PathFillModeValues.None;
IsExtrusionOk = isExtrusionOk;
IsExtrusionOk = isExtrusionOk ?? false;
Width = emuWidth.HasValue ? new Emu(emuWidth.Value) : null;
Height = emuHeight.HasValue ? new Emu(emuHeight.Value) : null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,17 @@ internal static ITransformData CreateTransformData(this OpenXmlElement element,
return transformData;
}

var alternateContentTransform2D = element.GetFirstChild<ContentPart>()?.GetFirstChild<DocumentFormat.OpenXml.Office2010.PowerPoint.Transform2D>();
if (alternateContentTransform2D is not null)
{
FillOffset(alternateContentTransform2D.Offset, transformData);
FillExtents(alternateContentTransform2D.Extents, transformData);
FillRotation(alternateContentTransform2D.Rotation, transformData);
FillFlip(alternateContentTransform2D.HorizontalFlip, alternateContentTransform2D.VerticalFlip, transformData);
return transformData;
}


return transformData;

void FillOffset(Offset? offset, TransformData transformData2)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Globalization;
using System.Diagnostics;
using System.Globalization;

using DocumentFormat.OpenXml.Drawing;
using DocumentFormat.OpenXml.Flatten.Framework.Context;
Expand Down Expand Up @@ -295,14 +296,37 @@ public static class ColorHelper
/// <returns></returns>
public static Color? ToColor(this RgbColorModelHex color)
{
if (color.Val is not null)
if (color.Val is null)
{
if (uint.TryParse(color.Val.Value, NumberStyles.HexNumber, null, out var result))
{
var solidColor = result.HexToColor();
var modifiedColor = ColorTransform.AppendColorModify(solidColor, color.ChildElements);
return modifiedColor;
}
return null;
}

var solidColor = ToColor(color.Val.Value);
if (solidColor is null)
{
return null;
}
var modifiedColor = ColorTransform.AppendColorModify(solidColor, color.ChildElements);
return modifiedColor;

}

/// <summary>
/// 将<see cref="string" />颜色值转换为<see cref="Color" />
/// </summary>
/// <param name="colorValue">颜色值:例如#E71224</param>
/// <returns></returns>
public static Color? ToColor(this string? colorValue)
{
if (string.IsNullOrEmpty(colorValue))
{
return null;
}

var (success, a, r, g, b) = ConvertToColor(colorValue!);
if (success)
{
return new(a, r, g, b);
}

return null;
Expand Down Expand Up @@ -358,6 +382,121 @@ private static Color HexToColor(this uint rgb)
return color;
}

/// <summary>
/// 将传入的颜色字符串转换为颜色输出
/// </summary>
/// <param name="hexColorText">颜色字符串,格式如 “#FFDFD991” 或 “#DFD991”等,规则和 WPF 的 XAML 颜色相同,其中 “#” 是可选的</param>
/// <returns></returns>
public static (bool success, byte a, byte r, byte g, byte b) ConvertToColor(string hexColorText)
{
#if NET6_0_OR_GREATER
bool startWithPoundSign = hexColorText.StartsWith('#');
#else
bool startWithPoundSign = hexColorText.StartsWith("#");
#endif
var colorStringLength = hexColorText.Length;
if (startWithPoundSign) colorStringLength -= 1;
int currentOffset = startWithPoundSign ? 1 : 0;
// 可以采用的格式如下
// #FFDFD991 8 个字符 存在 Alpha 通道
// #DFD991 6 个字符
// #FD92 4 个字符 存在 Alpha 通道
// #DAC 3 个字符
if (colorStringLength == 8
|| colorStringLength == 6
|| colorStringLength == 4
|| colorStringLength == 3)
{
bool success;
byte result;
byte a;

int readCount;
// #DFD991 6 个字符
// #FFDFD991 8 个字符 存在 Alpha 通道
//if (colorStringLength == 8 || colorStringLength == 6)
if (colorStringLength > 5)
{
readCount = 2;
}
else
{
readCount = 1;
}

bool includeAlphaChannel = colorStringLength == 8 || colorStringLength == 4;

if (includeAlphaChannel)
{
(success, result) = HexCharToNumber(hexColorText, currentOffset, readCount);
if (!success) return default;
a = result;
currentOffset += readCount;
}
else
{
a = 0xFF;
}

(success, result) = HexCharToNumber(hexColorText, currentOffset, readCount);
if (!success) return default;
byte r = result;
currentOffset += readCount;

(success, result) = HexCharToNumber(hexColorText, currentOffset, readCount);
if (!success) return default;
byte g = result;
currentOffset += readCount;

(success, result) = HexCharToNumber(hexColorText, currentOffset, readCount);
if (!success) return default;
byte b = result;

return (true, a, r, g, b);
}

return default;
}

static (bool success, byte result) HexCharToNumber(string input, int offset, int readCount)
{
Debug.Assert(readCount == 1 || readCount == 2, "要求 readCount 只能是 1 或者 2 的值,这是框架限制,因此不做判断");

byte result = 0;

for (int i = 0; i < readCount; i++, offset++)
{
var c = input[offset];
byte n;
if (c >= '0' && c <= '9')
{
n = (byte) (c - '0');
}
else if (c >= 'a' && c <= 'f')
{
n = (byte) (c - 'a' + 10);
}
else if (c >= 'A' && c <= 'F')
{
n = (byte) (c - 'A' + 10);
}
else
{
return default;
}

result *= 16;
result += n;
}

if (readCount == 1)
{
result = (byte) (result * 16 + result);
}

return (true, result);
}

//private static ColorBrush? ToColorBrush([CanBeNull] this Color? color)
//{
// if (color == null) return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public CustomGeometryConverter(CustomGeometry customGeometry, ElementEmuSize emu
/// <returns></returns>
public SvgPath? Convert()
{
ConvertAdjustValueList();
ConvertShapeGuideList();
ConvertShapeTextRectangle();
return ConvertPathList();
Expand Down Expand Up @@ -67,6 +68,25 @@ private void ConvertShapeTextRectangle()
ShapeTextRectangle = new EmuShapeTextRectangle(left, top, right, bottom);
}

private void ConvertAdjustValueList()
{
var adjustValueList = _customGeometry.AdjustValueList;
if (adjustValueList is not null)
{
foreach (var shapeGuide in adjustValueList.Elements().OfType<ShapeGuide>())
{
var name = shapeGuide.Name?.Value;
var formula = shapeGuide.Formula?.Value;

if (!string.IsNullOrEmpty(name) && !string.IsNullOrEmpty(formula))
{
ShapeGeometryFormulaCalculator.Calculate(name!, formula!);
}
}
}
}


private void ConvertShapeGuideList()
{
var shapeGuideList = _customGeometry.ShapeGuideList;
Expand All @@ -83,6 +103,7 @@ private void ConvertShapeGuideList()
}
}
}

}

private SvgPath? ConvertPathList()
Expand Down Expand Up @@ -134,7 +155,13 @@ void TryClosePath()
}
}

svgPathList.Add(new ShapePath(stringPath.ToString()));
var pathFillModeValues = path.Fill?.Value;
var isStroke = path.Stroke?.Value;
var width = path.Width?.Value;
var height = path.Height?.Value;
var isExtrusionOk = path.ExtrusionOk?.Value;

svgPathList.Add(new ShapePath(stringPath.ToString(), pathFillModeValues, isStroke, isExtrusionOk, width, height));
stringPath.Clear();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Xml.Linq;

using DocumentFormat.OpenXml.Drawing;
Expand Down Expand Up @@ -268,11 +269,27 @@ public static class ShapeGeometryConverterHelper
return default;
}

var path = shapeGeometryBase.ToGeometryPathString(emuSize, adjustList);
var multiGeometryPaths = shapeGeometryBase.GetMultiShapePaths(emuSize, adjustList);

var pathString = shapeGeometryBase.ToGeometryPathString(emuSize, adjustList);
var path = string.IsNullOrWhiteSpace(pathString) ? GetSvgPath(multiGeometryPaths) : pathString;
return new SvgPath(geometryShapeTypeValues, path, shapeGeometryBase.ShapeTextRectangle, multiGeometryPaths);
}

private static string? GetSvgPath(ShapePath[]? shapePaths)
{
if (shapePaths is not null)
{
var sb = new StringBuilder();
foreach (var shapePath in shapePaths)
{
sb.Append(shapePath.Path);
}
return sb.ToString();
}
return default;
}

/// <summary>
/// 根据调整点Name获取调整点的Value
/// </summary>
Expand Down
Loading
Loading