From 41f07b825b8c8c88ef4b9d07f3cf09923b66d6f3 Mon Sep 17 00:00:00 2001 From: jasonwei1002 Date: Fri, 17 Jul 2026 17:19:21 +0800 Subject: [PATCH] fix(pptx): reject adjust handles undeclared by the preset geometry (#235) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PowerPoint reports a file as corrupt (0x80070570) when a shape's avLst contains a whose name is not declared by the preset's ECMA-376 definition — most commonly an adj value on a preset with no adjust handles at all (rect, ellipse, line, ...). officecli previously wrote such files without complaint and validate stayed green. Replace the two hand-maintained partial tables (MultiGuidePresetDefaults, CanonicalAdjName) with PresetAdjustGuides, a complete table of all 187 preset geometries' declared guide names and spec-default formulas, generated from ECMA-376 presetShapeDefinitions.xml. ApplyAdjustHandles now: - rejects any adj= spec on a preset that declares no adjust handles, with an actionable error instead of an unopenable file; - rejects guide names not declared by multi-guide presets, listing the valid names; - generalizes the single-guide remap (donut/noSmoking special case) to every single-guide preset; - emits the complete guide set for every multi-guide preset (previously only hexagon/star5/star6/star7/star10), fixing the same 0x80070570 subset corruption for e.g. round2SameRect authored with only adj1. Fixes #235 --- .../PowerPointHandler.Helpers.Geometry.cs | 119 ++++------ .../PowerPointHandler.PresetAdjustGuides.cs | 209 ++++++++++++++++++ 2 files changed, 255 insertions(+), 73 deletions(-) create mode 100644 src/officecli/Handlers/Pptx/PowerPointHandler.PresetAdjustGuides.cs diff --git a/src/officecli/Handlers/Pptx/PowerPointHandler.Helpers.Geometry.cs b/src/officecli/Handlers/Pptx/PowerPointHandler.Helpers.Geometry.cs index 26736c0b1..b5aaa5da1 100644 --- a/src/officecli/Handlers/Pptx/PowerPointHandler.Helpers.Geometry.cs +++ b/src/officecli/Handlers/Pptx/PowerPointHandler.Helpers.Geometry.cs @@ -298,6 +298,20 @@ internal static void ApplyAdjustHandles(Drawing.AdjustValueList avLst, string sp // guides keyed by canonical name, then emit the preset's full guide set // in declaration order, using the user formula where given and the // preset's default formula for the rest. + (string Name, string Fmla)[]? declared = null; + if (preset != null && PresetAdjustGuides.TryGetValue(PresetToken(preset.Value), out var declaredGuides)) + declared = declaredGuides; + + // R18 BUG B: a preset that declares NO adjust guides (rect, ellipse, + // line, …) corrupts the file in real PowerPoint (0x80070570) if the + // authored avLst contains any — even though the OpenXML SDK + // validates it. Reject up front instead of writing an unopenable file. + if (declared is { Length: 0 }) + throw new ArgumentException( + $"Preset geometry '{PresetToken(preset!.Value)}' has no adjust handles; " + + "remove the adj= property. PowerPoint reports files that carry adjust " + + "values on this preset as corrupt."); + var supplied = new Dictionary(StringComparer.Ordinal); var orderSupplied = new List(); int idx = 0; @@ -321,23 +335,40 @@ internal static void ApplyAdjustHandles(Drawing.AdjustValueList avLst, string sp // PowerPoint refuses the file (0x80070570) when fmla isn't a // well-formed ECMA-376 guide formula. ValidateGuideFormula(entry, fmla); - // R18 BUG A: PowerPoint validates each against the - // names the preset's own definition declares; an unknown name (e.g. - // "adj1" on a single-handle preset whose guide is literally "adj") - // makes real PowerPoint refuse the file (0x80070570) even though the - // OpenXML SDK considers it schema-valid. Remap the supplied name to - // the canonical handle name expected at this position for the preset. - name = CanonicalAdjName(preset, idx, name); + // R18 BUG A (generalized): PowerPoint validates each + // against the names the preset's own definition declares; an unknown + // name (e.g. "adj1" on a single-handle preset whose guide is literally + // "adj") makes real PowerPoint refuse the file (0x80070570) even + // though the OpenXML SDK considers it schema-valid. Single-guide + // presets: remap position 0 to the declared name (previously + // special-cased for donut / noSmoking only). Multi-guide presets: + // reject undeclared names outright. + if (declared is { Length: 1 }) + { + if (idx > 0) + throw new ArgumentException( + $"Preset geometry '{PresetToken(preset!.Value)}' declares a single adjust " + + $"handle ('{declared[0].Name}'); got extra handle '{name}'."); + name = declared[0].Name; + } + else if (declared is { Length: > 1 } && !declared.Any(g => g.Name == name)) + { + throw new ArgumentException( + $"Adjust handle '{name}' is not declared by preset geometry " + + $"'{PresetToken(preset!.Value)}'. Valid handles: " + + string.Join(", ", declared.Select(g => g.Name)) + "."); + } if (supplied.TryAdd(name, fmla)) orderSupplied.Add(name); else supplied[name] = fmla; idx++; } - // If this preset has a known multi-guide definition, always emit the - // full guide set so PowerPoint accepts the authored avLst. - if (preset != null && MultiGuidePresetDefaults.TryGetValue(preset.Value, out var defaults)) + // If this preset declares more than one guide, always emit the full + // guide set so PowerPoint accepts the authored avLst (R19b: a subset + // of a multi-guide preset's guides is rejected with 0x80070570). + if (declared is { Length: > 1 }) { - foreach (var (name, defFmla) in defaults) + foreach (var (name, defFmla) in declared) { var fmla = supplied.TryGetValue(name, out var userFmla) ? userFmla : defFmla; avLst.AppendChild(new Drawing.ShapeGuide { Name = name, Formula = fmla }); @@ -373,67 +404,9 @@ private static void ValidateGuideFormula(string entry, string fmla) } /// - /// Authoritative full adjust-guide set for presets whose ECMA-376 - /// presetShapeDefinition declares MORE THAN ONE adjust guide. Maps the - /// preset to its ordered (guide name → default formula) list. Real - /// PowerPoint rejects (0x80070570) an avLst that contains a subset of a - /// multi-guide preset's guides, so when the user authors an `adj=...` on - /// any of these we must emit the complete set, filling unspecified guides - /// with these defaults. Formulas use the ECMA-376 default values; the - /// star adjust handles are the literal `` defaults - /// from the spec's presetShapeDefinitions. Single-guide presets are - /// deliberately ABSENT — they round-trip fine as a lone `adj`. + /// OOXML token for a preset geometry (e.g. roundRect), used as the + /// key into . /// - private static readonly IReadOnlyDictionary - MultiGuidePresetDefaults = new Dictionary - { - [Drawing.ShapeTypeValues.Hexagon] = new[] - { - ("adj", "val 25000"), - ("vf", "val 115470"), - }, - [Drawing.ShapeTypeValues.Star5] = new[] - { - ("adj", "val 19098"), - ("hf", "val 105146"), - ("vf", "val 110557"), - }, - [Drawing.ShapeTypeValues.Star6] = new[] - { - ("adj", "val 28868"), - ("hf", "val 115470"), - }, - [Drawing.ShapeTypeValues.Star7] = new[] - { - ("adj", "val 34601"), - ("hf", "val 102572"), - ("vf", "val 105210"), - }, - [Drawing.ShapeTypeValues.Star10] = new[] - { - ("adj", "val 42533"), - ("hf", "val 105146"), - }, - }; - - /// - /// Map the adjust-handle name at to the name the - /// given actually declares. Presets that define a - /// single adjust handle name it adj (donut, noSmoking, …); writing the - /// generic adj1 there yields a file real PowerPoint rejects. Presets - /// with multiple handles use adj1/adj2/… and pass through. - /// Unknown presets keep the caller-supplied name verbatim. - /// - private static string CanonicalAdjName(Drawing.ShapeTypeValues? preset, int index, string supplied) - { - if (preset == null) return supplied; - // Single-handle presets: the one and only guide is named "adj". - if (index == 0 && - (preset == Drawing.ShapeTypeValues.Donut - || preset == Drawing.ShapeTypeValues.NoSmoking)) - { - return "adj"; - } - return supplied; - } + private static string PresetToken(Drawing.ShapeTypeValues preset) + => ((IEnumValue)preset).Value; } diff --git a/src/officecli/Handlers/Pptx/PowerPointHandler.PresetAdjustGuides.cs b/src/officecli/Handlers/Pptx/PowerPointHandler.PresetAdjustGuides.cs new file mode 100644 index 000000000..f3cb7f3cb --- /dev/null +++ b/src/officecli/Handlers/Pptx/PowerPointHandler.PresetAdjustGuides.cs @@ -0,0 +1,209 @@ +// Copyright 2026 OfficeCLI (https://OfficeCLI.AI) +// SPDX-License-Identifier: Apache-2.0 + +namespace OfficeCli.Handlers; + +public partial class PowerPointHandler +{ + /// + /// Declared adjust guides for every ECMA-376 preset geometry, generated + /// from the spec's presetShapeDefinitions.xml (ECMA-376 Part 1, + /// §20.1.10.56): each preset's <avLst> guide names in declaration + /// order, paired with the spec-default formula. A zero-length entry means + /// the preset declares NO adjust handles — real PowerPoint reports the + /// file as corrupt (0x80070570) if such a preset carries any authored + /// <a:gd>. Used by ApplyAdjustHandles to reject undeclared guide + /// names and to emit the complete guide set for multi-guide presets. + /// + private static readonly IReadOnlyDictionary + PresetAdjustGuides = new Dictionary(StringComparer.Ordinal) + { + ["accentBorderCallout1"] = new[] { ("adj1", "val 18750"), ("adj2", "val -8333"), ("adj3", "val 112500"), ("adj4", "val -38333") }, + ["accentBorderCallout2"] = new[] { ("adj1", "val 18750"), ("adj2", "val -8333"), ("adj3", "val 18750"), ("adj4", "val -16667"), ("adj5", "val 112500"), ("adj6", "val -46667") }, + ["accentBorderCallout3"] = new[] { ("adj1", "val 18750"), ("adj2", "val -8333"), ("adj3", "val 18750"), ("adj4", "val -16667"), ("adj5", "val 100000"), ("adj6", "val -16667"), ("adj7", "val 112963"), ("adj8", "val -8333") }, + ["accentCallout1"] = new[] { ("adj1", "val 18750"), ("adj2", "val -8333"), ("adj3", "val 112500"), ("adj4", "val -38333") }, + ["accentCallout2"] = new[] { ("adj1", "val 18750"), ("adj2", "val -8333"), ("adj3", "val 18750"), ("adj4", "val -16667"), ("adj5", "val 112500"), ("adj6", "val -46667") }, + ["accentCallout3"] = new[] { ("adj1", "val 18750"), ("adj2", "val -8333"), ("adj3", "val 18750"), ("adj4", "val -16667"), ("adj5", "val 100000"), ("adj6", "val -16667"), ("adj7", "val 112963"), ("adj8", "val -8333") }, + ["actionButtonBackPrevious"] = System.Array.Empty<(string, string)>(), + ["actionButtonBeginning"] = System.Array.Empty<(string, string)>(), + ["actionButtonBlank"] = System.Array.Empty<(string, string)>(), + ["actionButtonDocument"] = System.Array.Empty<(string, string)>(), + ["actionButtonEnd"] = System.Array.Empty<(string, string)>(), + ["actionButtonForwardNext"] = System.Array.Empty<(string, string)>(), + ["actionButtonHelp"] = System.Array.Empty<(string, string)>(), + ["actionButtonHome"] = System.Array.Empty<(string, string)>(), + ["actionButtonInformation"] = System.Array.Empty<(string, string)>(), + ["actionButtonMovie"] = System.Array.Empty<(string, string)>(), + ["actionButtonReturn"] = System.Array.Empty<(string, string)>(), + ["actionButtonSound"] = System.Array.Empty<(string, string)>(), + ["arc"] = new[] { ("adj1", "val 16200000"), ("adj2", "val 0") }, + ["bentArrow"] = new[] { ("adj1", "val 25000"), ("adj2", "val 25000"), ("adj3", "val 25000"), ("adj4", "val 43750") }, + ["bentConnector2"] = System.Array.Empty<(string, string)>(), + ["bentConnector3"] = new[] { ("adj1", "val 50000") }, + ["bentConnector4"] = new[] { ("adj1", "val 50000"), ("adj2", "val 50000") }, + ["bentConnector5"] = new[] { ("adj1", "val 50000"), ("adj2", "val 50000"), ("adj3", "val 50000") }, + ["bentUpArrow"] = new[] { ("adj1", "val 25000"), ("adj2", "val 25000"), ("adj3", "val 25000") }, + ["bevel"] = new[] { ("adj", "val 12500") }, + ["blockArc"] = new[] { ("adj1", "val 10800000"), ("adj2", "val 0"), ("adj3", "val 25000") }, + ["borderCallout1"] = new[] { ("adj1", "val 18750"), ("adj2", "val -8333"), ("adj3", "val 112500"), ("adj4", "val -38333") }, + ["borderCallout2"] = new[] { ("adj1", "val 18750"), ("adj2", "val -8333"), ("adj3", "val 18750"), ("adj4", "val -16667"), ("adj5", "val 112500"), ("adj6", "val -46667") }, + ["borderCallout3"] = new[] { ("adj1", "val 18750"), ("adj2", "val -8333"), ("adj3", "val 18750"), ("adj4", "val -16667"), ("adj5", "val 100000"), ("adj6", "val -16667"), ("adj7", "val 112963"), ("adj8", "val -8333") }, + ["bracePair"] = new[] { ("adj", "val 8333") }, + ["bracketPair"] = new[] { ("adj", "val 16667") }, + ["callout1"] = new[] { ("adj1", "val 18750"), ("adj2", "val -8333"), ("adj3", "val 112500"), ("adj4", "val -38333") }, + ["callout2"] = new[] { ("adj1", "val 18750"), ("adj2", "val -8333"), ("adj3", "val 18750"), ("adj4", "val -16667"), ("adj5", "val 112500"), ("adj6", "val -46667") }, + ["callout3"] = new[] { ("adj1", "val 18750"), ("adj2", "val -8333"), ("adj3", "val 18750"), ("adj4", "val -16667"), ("adj5", "val 100000"), ("adj6", "val -16667"), ("adj7", "val 112963"), ("adj8", "val -8333") }, + ["can"] = new[] { ("adj", "val 25000") }, + ["chartPlus"] = System.Array.Empty<(string, string)>(), + ["chartStar"] = System.Array.Empty<(string, string)>(), + ["chartX"] = System.Array.Empty<(string, string)>(), + ["chevron"] = new[] { ("adj", "val 50000") }, + ["chord"] = new[] { ("adj1", "val 2700000"), ("adj2", "val 16200000") }, + ["circularArrow"] = new[] { ("adj1", "val 12500"), ("adj2", "val 1142319"), ("adj3", "val 20457681"), ("adj4", "val 10800000"), ("adj5", "val 12500") }, + ["cloud"] = System.Array.Empty<(string, string)>(), + ["cloudCallout"] = new[] { ("adj1", "val -20833"), ("adj2", "val 62500") }, + ["corner"] = new[] { ("adj1", "val 50000"), ("adj2", "val 50000") }, + ["cornerTabs"] = System.Array.Empty<(string, string)>(), + ["cube"] = new[] { ("adj", "val 25000") }, + ["curvedConnector2"] = System.Array.Empty<(string, string)>(), + ["curvedConnector3"] = new[] { ("adj1", "val 50000") }, + ["curvedConnector4"] = new[] { ("adj1", "val 50000"), ("adj2", "val 50000") }, + ["curvedConnector5"] = new[] { ("adj1", "val 50000"), ("adj2", "val 50000"), ("adj3", "val 50000") }, + ["curvedDownArrow"] = new[] { ("adj1", "val 25000"), ("adj2", "val 50000"), ("adj3", "val 25000") }, + ["curvedLeftArrow"] = new[] { ("adj1", "val 25000"), ("adj2", "val 50000"), ("adj3", "val 25000") }, + ["curvedRightArrow"] = new[] { ("adj1", "val 25000"), ("adj2", "val 50000"), ("adj3", "val 25000") }, + ["curvedUpArrow"] = new[] { ("adj1", "val 25000"), ("adj2", "val 50000"), ("adj3", "val 25000") }, + ["decagon"] = new[] { ("vf", "val 105146") }, + ["diagStripe"] = new[] { ("adj", "val 50000") }, + ["diamond"] = System.Array.Empty<(string, string)>(), + ["dodecagon"] = System.Array.Empty<(string, string)>(), + ["donut"] = new[] { ("adj", "val 25000") }, + ["doubleWave"] = new[] { ("adj1", "val 6250"), ("adj2", "val 0") }, + ["downArrow"] = new[] { ("adj1", "val 50000"), ("adj2", "val 50000") }, + ["downArrowCallout"] = new[] { ("adj1", "val 25000"), ("adj2", "val 25000"), ("adj3", "val 25000"), ("adj4", "val 64977") }, + ["ellipse"] = System.Array.Empty<(string, string)>(), + ["ellipseRibbon"] = new[] { ("adj1", "val 25000"), ("adj2", "val 50000"), ("adj3", "val 12500") }, + ["ellipseRibbon2"] = new[] { ("adj1", "val 25000"), ("adj2", "val 50000"), ("adj3", "val 12500") }, + ["flowChartAlternateProcess"] = System.Array.Empty<(string, string)>(), + ["flowChartCollate"] = System.Array.Empty<(string, string)>(), + ["flowChartConnector"] = System.Array.Empty<(string, string)>(), + ["flowChartDecision"] = System.Array.Empty<(string, string)>(), + ["flowChartDelay"] = System.Array.Empty<(string, string)>(), + ["flowChartDisplay"] = System.Array.Empty<(string, string)>(), + ["flowChartDocument"] = System.Array.Empty<(string, string)>(), + ["flowChartExtract"] = System.Array.Empty<(string, string)>(), + ["flowChartInputOutput"] = System.Array.Empty<(string, string)>(), + ["flowChartInternalStorage"] = System.Array.Empty<(string, string)>(), + ["flowChartMagneticDisk"] = System.Array.Empty<(string, string)>(), + ["flowChartMagneticDrum"] = System.Array.Empty<(string, string)>(), + ["flowChartMagneticTape"] = System.Array.Empty<(string, string)>(), + ["flowChartManualInput"] = System.Array.Empty<(string, string)>(), + ["flowChartManualOperation"] = System.Array.Empty<(string, string)>(), + ["flowChartMerge"] = System.Array.Empty<(string, string)>(), + ["flowChartMultidocument"] = System.Array.Empty<(string, string)>(), + ["flowChartOfflineStorage"] = System.Array.Empty<(string, string)>(), + ["flowChartOffpageConnector"] = System.Array.Empty<(string, string)>(), + ["flowChartOnlineStorage"] = System.Array.Empty<(string, string)>(), + ["flowChartOr"] = System.Array.Empty<(string, string)>(), + ["flowChartPredefinedProcess"] = System.Array.Empty<(string, string)>(), + ["flowChartPreparation"] = System.Array.Empty<(string, string)>(), + ["flowChartProcess"] = System.Array.Empty<(string, string)>(), + ["flowChartPunchedCard"] = System.Array.Empty<(string, string)>(), + ["flowChartPunchedTape"] = System.Array.Empty<(string, string)>(), + ["flowChartSort"] = System.Array.Empty<(string, string)>(), + ["flowChartSummingJunction"] = System.Array.Empty<(string, string)>(), + ["flowChartTerminator"] = System.Array.Empty<(string, string)>(), + ["foldedCorner"] = new[] { ("adj", "val 16667") }, + ["frame"] = new[] { ("adj1", "val 12500") }, + ["funnel"] = System.Array.Empty<(string, string)>(), + ["gear6"] = new[] { ("adj1", "val 15000"), ("adj2", "val 3526") }, + ["gear9"] = new[] { ("adj1", "val 10000"), ("adj2", "val 1763") }, + ["halfFrame"] = new[] { ("adj1", "val 33333"), ("adj2", "val 33333") }, + ["heart"] = System.Array.Empty<(string, string)>(), + ["heptagon"] = new[] { ("hf", "val 102572"), ("vf", "val 105210") }, + ["hexagon"] = new[] { ("adj", "val 25000"), ("vf", "val 115470") }, + ["homePlate"] = new[] { ("adj", "val 50000") }, + ["horizontalScroll"] = new[] { ("adj", "val 12500") }, + ["irregularSeal1"] = System.Array.Empty<(string, string)>(), + ["irregularSeal2"] = System.Array.Empty<(string, string)>(), + ["leftArrow"] = new[] { ("adj1", "val 50000"), ("adj2", "val 50000") }, + ["leftArrowCallout"] = new[] { ("adj1", "val 25000"), ("adj2", "val 25000"), ("adj3", "val 25000"), ("adj4", "val 64977") }, + ["leftBrace"] = new[] { ("adj1", "val 8333"), ("adj2", "val 50000") }, + ["leftBracket"] = new[] { ("adj", "val 8333") }, + ["leftCircularArrow"] = new[] { ("adj1", "val 12500"), ("adj2", "val -1142319"), ("adj3", "val 1142319"), ("adj4", "val 10800000"), ("adj5", "val 12500") }, + ["leftRightArrow"] = new[] { ("adj1", "val 50000"), ("adj2", "val 50000") }, + ["leftRightArrowCallout"] = new[] { ("adj1", "val 25000"), ("adj2", "val 25000"), ("adj3", "val 25000"), ("adj4", "val 48123") }, + ["leftRightCircularArrow"] = new[] { ("adj1", "val 12500"), ("adj2", "val 1142319"), ("adj3", "val 20457681"), ("adj4", "val 11942319"), ("adj5", "val 12500") }, + ["leftRightRibbon"] = new[] { ("adj1", "val 50000"), ("adj2", "val 50000"), ("adj3", "val 16667") }, + ["leftRightUpArrow"] = new[] { ("adj1", "val 25000"), ("adj2", "val 25000"), ("adj3", "val 25000") }, + ["leftUpArrow"] = new[] { ("adj1", "val 25000"), ("adj2", "val 25000"), ("adj3", "val 25000") }, + ["lightningBolt"] = System.Array.Empty<(string, string)>(), + ["line"] = System.Array.Empty<(string, string)>(), + ["lineInv"] = System.Array.Empty<(string, string)>(), + ["mathDivide"] = new[] { ("adj1", "val 23520"), ("adj2", "val 5880"), ("adj3", "val 11760") }, + ["mathEqual"] = new[] { ("adj1", "val 23520"), ("adj2", "val 11760") }, + ["mathMinus"] = new[] { ("adj1", "val 23520") }, + ["mathMultiply"] = new[] { ("adj1", "val 23520") }, + ["mathNotEqual"] = new[] { ("adj1", "val 23520"), ("adj2", "val 6600000"), ("adj3", "val 11760") }, + ["mathPlus"] = new[] { ("adj1", "val 23520") }, + ["moon"] = new[] { ("adj", "val 50000") }, + ["noSmoking"] = new[] { ("adj", "val 18750") }, + ["nonIsoscelesTrapezoid"] = new[] { ("adj1", "val 25000"), ("adj2", "val 25000") }, + ["notchedRightArrow"] = new[] { ("adj1", "val 50000"), ("adj2", "val 50000") }, + ["octagon"] = new[] { ("adj", "val 29289") }, + ["parallelogram"] = new[] { ("adj", "val 25000") }, + ["pentagon"] = new[] { ("hf", "val 105146"), ("vf", "val 110557") }, + ["pie"] = new[] { ("adj1", "val 0"), ("adj2", "val 16200000") }, + ["pieWedge"] = System.Array.Empty<(string, string)>(), + ["plaque"] = new[] { ("adj", "val 16667") }, + ["plaqueTabs"] = System.Array.Empty<(string, string)>(), + ["plus"] = new[] { ("adj", "val 25000") }, + ["quadArrow"] = new[] { ("adj1", "val 22500"), ("adj2", "val 22500"), ("adj3", "val 22500") }, + ["quadArrowCallout"] = new[] { ("adj1", "val 18515"), ("adj2", "val 18515"), ("adj3", "val 18515"), ("adj4", "val 48123") }, + ["rect"] = System.Array.Empty<(string, string)>(), + ["ribbon"] = new[] { ("adj1", "val 16667"), ("adj2", "val 50000") }, + ["ribbon2"] = new[] { ("adj1", "val 16667"), ("adj2", "val 50000") }, + ["rightArrow"] = new[] { ("adj1", "val 50000"), ("adj2", "val 50000") }, + ["rightArrowCallout"] = new[] { ("adj1", "val 25000"), ("adj2", "val 25000"), ("adj3", "val 25000"), ("adj4", "val 64977") }, + ["rightBrace"] = new[] { ("adj1", "val 8333"), ("adj2", "val 50000") }, + ["rightBracket"] = new[] { ("adj", "val 8333") }, + ["round1Rect"] = new[] { ("adj", "val 16667") }, + ["round2DiagRect"] = new[] { ("adj1", "val 16667"), ("adj2", "val 0") }, + ["round2SameRect"] = new[] { ("adj1", "val 16667"), ("adj2", "val 0") }, + ["roundRect"] = new[] { ("adj", "val 16667") }, + ["rtTriangle"] = System.Array.Empty<(string, string)>(), + ["smileyFace"] = new[] { ("adj", "val 4653") }, + ["snip1Rect"] = new[] { ("adj", "val 16667") }, + ["snip2DiagRect"] = new[] { ("adj1", "val 0"), ("adj2", "val 16667") }, + ["snip2SameRect"] = new[] { ("adj1", "val 16667"), ("adj2", "val 0") }, + ["snipRoundRect"] = new[] { ("adj1", "val 16667"), ("adj2", "val 16667") }, + ["squareTabs"] = System.Array.Empty<(string, string)>(), + ["star10"] = new[] { ("adj", "val 42533"), ("hf", "val 105146") }, + ["star12"] = new[] { ("adj", "val 37500") }, + ["star16"] = new[] { ("adj", "val 37500") }, + ["star24"] = new[] { ("adj", "val 37500") }, + ["star32"] = new[] { ("adj", "val 37500") }, + ["star4"] = new[] { ("adj", "val 12500") }, + ["star5"] = new[] { ("adj", "val 19098"), ("hf", "val 105146"), ("vf", "val 110557") }, + ["star6"] = new[] { ("adj", "val 28868"), ("hf", "val 115470") }, + ["star7"] = new[] { ("adj", "val 34601"), ("hf", "val 102572"), ("vf", "val 105210") }, + ["star8"] = new[] { ("adj", "val 37500") }, + ["straightConnector1"] = System.Array.Empty<(string, string)>(), + ["stripedRightArrow"] = new[] { ("adj1", "val 50000"), ("adj2", "val 50000") }, + ["sun"] = new[] { ("adj", "val 25000") }, + ["swooshArrow"] = new[] { ("adj1", "val 25000"), ("adj2", "val 16667") }, + ["teardrop"] = new[] { ("adj", "val 100000") }, + ["trapezoid"] = new[] { ("adj", "val 25000") }, + ["triangle"] = new[] { ("adj", "val 50000") }, + ["upArrow"] = new[] { ("adj1", "val 50000"), ("adj2", "val 50000") }, + ["upArrowCallout"] = new[] { ("adj1", "val 25000"), ("adj2", "val 25000"), ("adj3", "val 25000"), ("adj4", "val 64977") }, + ["upDownArrow"] = new[] { ("adj1", "val 50000"), ("adj2", "val 50000") }, + ["upDownArrowCallout"] = new[] { ("adj1", "val 25000"), ("adj2", "val 25000"), ("adj3", "val 25000"), ("adj4", "val 48123") }, + ["uturnArrow"] = new[] { ("adj1", "val 25000"), ("adj2", "val 25000"), ("adj3", "val 25000"), ("adj4", "val 43750"), ("adj5", "val 75000") }, + ["verticalScroll"] = new[] { ("adj", "val 12500") }, + ["wave"] = new[] { ("adj1", "val 12500"), ("adj2", "val 0") }, + ["wedgeEllipseCallout"] = new[] { ("adj1", "val -20833"), ("adj2", "val 62500") }, + ["wedgeRectCallout"] = new[] { ("adj1", "val -20833"), ("adj2", "val 62500") }, + ["wedgeRoundRectCallout"] = new[] { ("adj1", "val -20833"), ("adj2", "val 62500"), ("adj3", "val 16667") }, + }; +}