From e9fb57cbbedb86ab733aa3aa3104f2ecb4ec9250 Mon Sep 17 00:00:00 2001 From: Arnaud Roques Date: Thu, 7 May 2020 16:12:08 +0200 Subject: [PATCH] Adding contribution from Hisashi Miyashita for SysML v2 support --- .../sourceforge/plantuml/AnnotatedWorker.java | 14 +- src/net/sourceforge/plantuml/FileFormat.java | 13 +- src/net/sourceforge/plantuml/Run.java | 7 +- src/net/sourceforge/plantuml/SkinParam.java | 11 +- .../plantuml/SourceStringReader.java | 21 +- .../sourceforge/plantuml/StringLocated.java | 4 + src/net/sourceforge/plantuml/StringUtils.java | 27 +- src/net/sourceforge/plantuml/UmlDiagram.java | 7 +- .../sourceforge/plantuml/UmlDiagramType.java | 36 +- .../command/CommandLinkLongActivity.java | 6 +- .../activitydiagram3/ActivityDiagram3.java | 56 +-- .../command/CommandActivity3.java | 25 +- .../command/CommandActivityLong3.java | 6 +- .../command/CommandArrowLong3.java | 4 +- .../command/CommandBackward3.java | 2 +- .../command/CommandNoteLong3.java | 2 +- .../command/CommandRepeat3.java | 2 +- .../CommandRepeatWhile3Multilines.java | 6 +- .../ftile/CollisionDetector.java | 2 +- .../ftile/FtileAssemblySimple.java | 4 +- .../activitydiagram3/ftile/FtileGeometry.java | 4 + ...xed.java => FtileHeightFixedCentered.java} | 4 +- .../ftile/FtileHeightFixedMarged.java | 94 +++++ ...nWidth.java => FtileMinWidthCentered.java} | 4 +- .../{SwimlanesAAA.java => Swimlanes.java} | 4 +- .../activitydiagram3/ftile/SwimlanesA.java | 333 ------------------ .../activitydiagram3/ftile/SwimlanesB.java | 144 -------- .../activitydiagram3/ftile/SwimlanesC.java | 93 ----- .../plantuml/activitydiagram3/ftile/Worm.java | 17 +- .../activitydiagram3/ftile/ZadBuilder.java | 2 +- .../AbstractParallelFtilesBuilder.java | 68 ++-- .../FtileFactoryDelegatorCreateParallel.java | 33 +- ...ryDelegatorCreateParallelAddingMargin.java | 73 ---- .../vcompact/FtileFactoryDelegatorSwitch.java | 8 +- .../ftile/vcompact/FtileIfLongHorizontal.java | 36 +- .../ftile/vcompact/FtileIfLongVertical.java | 6 +- .../ftile/vcompact/FtileSwitch.java | 4 +- .../ftile/vcompact/ParallelBuilderFork.java | 136 +++++-- .../ftile/vcompact/ParallelBuilderMerge.java | 16 +- .../ftile/vcompact/ParallelBuilderSplit.java | 22 +- .../vcompact/cond/ConditionalBuilder.java | 10 +- .../ftile/vertical/FtileBox.java | 26 +- .../sourceforge/plantuml/bpm/BpmDiagram.java | 16 +- .../plantuml/braille/UGraphicBraille.java | 4 +- .../plantuml/classdiagram/ClassDiagram.java | 17 +- .../command/CommandCreateClassMultilines.java | 2 +- .../command/CommandCreateElementFull2.java | 4 + .../command/CommandLinkClass.java | 19 +- .../code/ArobaseStringCompressor.java | 2 +- .../code/ArobaseStringCompressor2.java | 6 +- .../ISwimlanesA.java => code/ByteArray.java} | 43 ++- .../plantuml/code/Compression.java | 8 +- .../plantuml/code/CompressionBrotli.java | 19 +- .../plantuml/code/CompressionHuffman.java | 27 +- .../plantuml/code/CompressionNone.java | 4 +- .../plantuml/code/CompressionZlib.java | 54 +-- .../plantuml/code/CompressionZlibPure.java | 88 +++++ .../plantuml/code/CompressionZopfliZlib.java | 4 +- .../sourceforge/plantuml/code/Keywords.java | 183 ++++++++++ .../code/NoPlantumlCompressionException.java | 50 +++ .../plantuml/code/StringCompressor.java | 2 +- .../plantuml/code/StringCompressorNone.java | 2 +- .../sourceforge/plantuml/code/Transcoder.java | 2 +- .../plantuml/code/TranscoderImpl.java | 51 +-- .../plantuml/code/TranscoderSmart.java | 51 +-- .../plantuml/code/TranscoderSmart2.java | 21 +- .../plantuml/code/TranscoderSmartAttic.java | 108 ++++++ .../code/TranscoderSmartProtected.java | 181 ++++++++++ .../code/TranscoderSmartProtectedPure.java | 181 ++++++++++ .../plantuml/code/TranscoderUtil.java | 8 +- src/net/sourceforge/plantuml/code/Upf9.java | 156 ++++++++ .../plantuml/code/deflate/BitInputStream.java | 62 ++++ .../code/deflate/ByteBitInputStream.java | 98 ++++++ .../plantuml/code/deflate/ByteHistory.java | 92 +++++ .../plantuml/code/deflate/CanonicalCode.java | 174 +++++++++ .../plantuml/code/deflate/Decompressor.java | 300 ++++++++++++++++ .../code/deflate/OutputStreamProtected.java | 38 ++ .../plantuml/command/BlocLines.java | 71 ++-- .../command/CommandDecoratorMultine.java | 2 +- .../command/CommandFactorySprite.java | 54 +-- .../plantuml/command/CommandMultilines.java | 4 +- .../plantuml/command/CommandMultilines2.java | 12 +- .../plantuml/command/CommandMultilines3.java | 8 +- .../command/CommandMultilinesBracket.java | 2 +- .../command/CommandMultilinesCaption.java | 66 ++++ .../command/CommandMultilinesFooter.java | 4 +- .../command/CommandMultilinesHeader.java | 4 +- .../command/CommandMultilinesLegend.java | 2 +- .../command/CommandSkinParamMultilines.java | 2 +- .../plantuml/command/SingleLineCommand2.java | 14 +- .../plantuml/command/SkinLoader.java | 2 +- .../plantuml/command/UmlDiagramFactory.java | 9 +- .../command/note/CommandFactoryNote.java | 2 +- .../note/CommandFactoryNoteActivity.java | 2 +- .../note/CommandFactoryNoteOnEntity.java | 32 +- .../note/CommandFactoryNoteOnLink.java | 2 +- .../note/CommandFactoryTipOnEntity.java | 2 +- .../FactorySequenceNoteAcrossCommand.java | 2 +- .../sequence/FactorySequenceNoteCommand.java | 2 +- .../FactorySequenceNoteOnArrowCommand.java | 2 +- ...FactorySequenceNoteOverSeveralCommand.java | 2 +- .../plantuml/creole/PSystemCreole.java | 4 +- .../plantuml/creole/SheetBlock2.java | 6 +- .../plantuml/cucadiagram/EntityPosition.java | 20 +- .../plantuml/cucadiagram/LeafType.java | 4 +- .../plantuml/cucadiagram/LinkDecor.java | 96 ++--- .../plantuml/cucadiagram/LinkType.java | 10 +- .../cucadiagram/MethodsOrFieldsArea.java | 39 +- .../plantuml/cucadiagram/dot/DotData.java | 2 +- .../cucadiagram/entity/EntityImpl.java | 11 +- .../plantuml/cute/PSystemCute.java | 15 +- .../dedication/PSystemDedication.java | 4 +- .../definition/PSystemDefinition.java | 4 +- .../command/CommandArchimateMultilines.java | 4 +- .../command/CommandCreateElementFull.java | 22 +- .../CommandCreateElementMultilines.java | 14 +- .../command/CommandLinkElement.java | 48 +-- .../plantuml/donors/PSystemDonors.java | 57 +-- .../donors/PSystemSkinparameterList.java | 4 +- .../plantuml/eggs/PSystemAppleTwo.java | 4 +- .../plantuml/eggs/PSystemCharlie.java | 4 +- .../plantuml/eggs/PSystemColors.java | 4 +- .../sourceforge/plantuml/eggs/PSystemEgg.java | 4 +- .../plantuml/eggs/PSystemLost.java | 4 +- .../sourceforge/plantuml/eggs/PSystemRIP.java | 4 +- .../plantuml/eggs/PSystemWelcome.java | 4 +- .../plantuml/error/PSystemError.java | 4 +- .../plantuml/font/PSystemListFonts.java | 4 +- .../plantuml/graphic/FontConfiguration.java | 26 +- .../plantuml/graphic/HtmlColorAndStyle.java | 2 +- .../plantuml/graphic/QuoteUtils.java | 8 +- .../plantuml/graphic/SkinParameter.java | 116 +++--- .../plantuml/graphic/TextBlockBordered.java | 35 +- .../plantuml/graphic/TextBlockMarged.java | 35 +- .../plantuml/graphic/TextBlockUtils.java | 14 +- src/net/sourceforge/plantuml/help/Help.java | 4 +- .../jdot/CucaDiagramFileMakerJDot.java | 16 +- .../plantuml/jungle/PSystemTree.java | 15 +- .../plantuml/math/ScientificEquationSafe.java | 4 +- .../CommandMindMapOrgmodeMultiline.java | 25 +- .../plantuml/mindmap/FingerImpl.java | 31 +- .../sourceforge/plantuml/mindmap/Idea.java | 4 +- .../plantuml/mindmap/MindMapDiagram.java | 37 +- .../plantuml/nwdiag/NwDiagram.java | 15 +- .../CommandCreateEntityObjectMultilines.java | 4 +- .../command/CommandCreateMap.java | 4 +- .../openiconic/PSystemListOpenIconic.java | 4 +- .../openiconic/PSystemOpenIconic.java | 15 +- .../plantuml/oregon/PSystemOregon.java | 4 +- .../plantuml/project/GanttDiagram.java | 16 +- .../plantuml/salt/PSystemSalt.java | 17 +- .../SequenceDiagramFactory.java | 6 +- ...CommandReferenceMultilinesOverSeveral.java | 2 +- .../SequenceDiagramFileMakerPuma2.java | 47 ++- .../teoz/SequenceDiagramFileMakerTeoz.java | 14 +- .../plantuml/sprite/ListSpriteDiagram.java | 22 +- .../sprite/PSystemListInternalSprites.java | 4 +- .../plantuml/sprite/SpriteGrayLevel.java | 23 +- .../plantuml/sprite/StdlibDiagram.java | 19 +- .../plantuml/stats/PSystemStats.java | 4 +- .../style/ClockwiseTopRightBottomLeft.java | 79 ++++- .../style/CommandStyleMultilinesCSS.java | 1 + src/net/sourceforge/plantuml/style/SName.java | 117 +++--- src/net/sourceforge/plantuml/style/Style.java | 17 +- .../plantuml/style/StyleBuilder.java | 3 - .../plantuml/style/StyleSignature.java | 18 +- .../plantuml/svek/AbstractEntityImage.java | 6 +- .../sourceforge/plantuml/svek/Cluster.java | 216 +++++++----- .../svek/CucaDiagramFileMakerSvek.java | 23 +- .../plantuml/svek/GeneralImageBuilder.java | 36 +- .../plantuml/svek/GroupPngMakerActivity.java | 8 +- .../plantuml/svek/GroupPngMakerState.java | 5 +- .../plantuml/svek/IShapePseudo.java | 2 + src/net/sourceforge/plantuml/svek/Node.java | 11 +- .../plantuml/svek/ShapePseudoImpl.java | 4 + .../sourceforge/plantuml/svek/SvekResult.java | 21 +- .../svek/extremity/ExtremityExtendsLike.java | 173 +++++++++ .../ExtremityFactoryExtendsLike.java | 72 ++++ .../svek/image/AbstractEntityImageBorder.java | 95 +++++ .../svek/image/EntityImageDescription.java | 51 ++- .../svek/image/EntityImageEmptyPackage.java | 18 +- .../plantuml/svek/image/EntityImagePort.java | 114 ++++++ .../svek/image/EntityImageStateBorder.java | 56 +-- .../plantuml/swing/ImageWindow2.java | 4 +- .../plantuml/syntax/LanguageDescriptor.java | 7 +- .../plantuml/tim/VariableManager.java | 10 +- .../plantuml/timingdiagram/Player.java | 5 +- .../plantuml/timingdiagram/PlayerAnalog.java | 289 +++++++++++++++ .../plantuml/timingdiagram/PlayerBinary.java | 8 +- .../plantuml/timingdiagram/PlayerClock.java | 3 +- .../timingdiagram/PlayerRobustConcise.java | 5 +- .../plantuml/timingdiagram/TimingDiagram.java | 25 +- .../timingdiagram/TimingDiagramFactory.java | 6 + .../plantuml/timingdiagram/TimingRuler.java | 4 +- .../timingdiagram/command/CommandAnalog.java | 94 +++++ .../command/CommandNoteLong.java | 2 +- .../command/CommandPixelHeight.java | 80 +++++ .../timingdiagram/command/CommandTicks.java | 84 +++++ .../timingdiagram/graphic/Histogram.java | 17 +- .../timingdiagram/graphic/Ribbon.java | 10 +- .../plantuml/ugraphic/FontChecker.java | 4 +- .../plantuml/ugraphic/ImageBuilder.java | 165 +++++---- .../sourceforge/plantuml/ugraphic/MinMax.java | 12 + .../plantuml/ugraphic/MinMaxMutable.java | 24 ++ .../ugraphic/g2d/DriverPolygonG2d.java | 20 +- .../plantuml/ugraphic/g2d/DriverTextG2d.java | 18 +- .../plantuml/version/PSystemKeycheck.java | 4 +- .../plantuml/version/PSystemKeygen.java | 4 +- .../plantuml/version/PSystemLicense.java | 4 +- .../plantuml/version/PSystemVersion.java | 4 +- .../sourceforge/plantuml/version/Version.java | 2 +- .../sourceforge/plantuml/wbs/ITFComposed.java | 10 +- .../sourceforge/plantuml/wbs/WBSDiagram.java | 22 +- .../plantuml/wire/WireDiagram.java | 17 +- stdlib/elastic-abx.repx | Bin 1459 -> 1446 bytes 215 files changed, 4976 insertions(+), 1898 deletions(-) rename src/net/sourceforge/plantuml/activitydiagram3/ftile/{FtileHeightFixed.java => FtileHeightFixedCentered.java} (95%) create mode 100644 src/net/sourceforge/plantuml/activitydiagram3/ftile/FtileHeightFixedMarged.java rename src/net/sourceforge/plantuml/activitydiagram3/ftile/{FtileMinWidth.java => FtileMinWidthCentered.java} (96%) rename src/net/sourceforge/plantuml/activitydiagram3/ftile/{SwimlanesAAA.java => Swimlanes.java} (99%) delete mode 100644 src/net/sourceforge/plantuml/activitydiagram3/ftile/SwimlanesA.java delete mode 100644 src/net/sourceforge/plantuml/activitydiagram3/ftile/SwimlanesB.java delete mode 100644 src/net/sourceforge/plantuml/activitydiagram3/ftile/SwimlanesC.java delete mode 100644 src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/FtileFactoryDelegatorCreateParallelAddingMargin.java rename src/net/sourceforge/plantuml/{activitydiagram3/ftile/ISwimlanesA.java => code/ByteArray.java} (60%) create mode 100644 src/net/sourceforge/plantuml/code/CompressionZlibPure.java create mode 100644 src/net/sourceforge/plantuml/code/Keywords.java create mode 100644 src/net/sourceforge/plantuml/code/NoPlantumlCompressionException.java create mode 100644 src/net/sourceforge/plantuml/code/TranscoderSmartAttic.java create mode 100644 src/net/sourceforge/plantuml/code/TranscoderSmartProtected.java create mode 100644 src/net/sourceforge/plantuml/code/TranscoderSmartProtectedPure.java create mode 100644 src/net/sourceforge/plantuml/code/Upf9.java create mode 100644 src/net/sourceforge/plantuml/code/deflate/BitInputStream.java create mode 100644 src/net/sourceforge/plantuml/code/deflate/ByteBitInputStream.java create mode 100644 src/net/sourceforge/plantuml/code/deflate/ByteHistory.java create mode 100644 src/net/sourceforge/plantuml/code/deflate/CanonicalCode.java create mode 100644 src/net/sourceforge/plantuml/code/deflate/Decompressor.java create mode 100644 src/net/sourceforge/plantuml/code/deflate/OutputStreamProtected.java create mode 100644 src/net/sourceforge/plantuml/command/CommandMultilinesCaption.java create mode 100644 src/net/sourceforge/plantuml/svek/extremity/ExtremityExtendsLike.java create mode 100644 src/net/sourceforge/plantuml/svek/extremity/ExtremityFactoryExtendsLike.java create mode 100644 src/net/sourceforge/plantuml/svek/image/AbstractEntityImageBorder.java create mode 100644 src/net/sourceforge/plantuml/svek/image/EntityImagePort.java create mode 100644 src/net/sourceforge/plantuml/timingdiagram/PlayerAnalog.java create mode 100644 src/net/sourceforge/plantuml/timingdiagram/command/CommandAnalog.java create mode 100644 src/net/sourceforge/plantuml/timingdiagram/command/CommandPixelHeight.java create mode 100644 src/net/sourceforge/plantuml/timingdiagram/command/CommandTicks.java diff --git a/src/net/sourceforge/plantuml/AnnotatedWorker.java b/src/net/sourceforge/plantuml/AnnotatedWorker.java index e70643fc6..265578202 100644 --- a/src/net/sourceforge/plantuml/AnnotatedWorker.java +++ b/src/net/sourceforge/plantuml/AnnotatedWorker.java @@ -97,7 +97,7 @@ public class AnnotatedWorker { final double y1 = 10; final double y2 = 10; - final SymbolContext symbolContext = new SymbolContext(getSkinParam().getBackgroundColor(false), HColorUtils.BLACK) + final SymbolContext symbolContext = new SymbolContext(getBackgroundColor(), HColorUtils.BLACK) .withShadow(getSkinParam().shadowing(null) ? 3 : 0); final MinMax originalMinMax = TextBlockUtils.getMinMax(original, stringBounder, false); final TextBlock title = mainFrame.create(new FontConfiguration(getSkinParam(), FontParam.CAPTION, null), @@ -137,6 +137,10 @@ public class AnnotatedWorker { }; } + private HColor getBackgroundColor() { + return getSkinParam().getBackgroundColor(false); + } + private TextBlock addLegend(TextBlock original) { final DisplayPositionned legend = annotated.getLegend(); if (legend.isNull()) { @@ -166,8 +170,8 @@ public class AnnotatedWorker { return TextBlockUtils.empty(0, 0); } if (SkinParam.USE_STYLES()) { - final Style style = StyleSignature.of(SName.root, SName.caption).getMergedStyle( - skinParam.getCurrentStyleBuilder()); + final Style style = StyleSignature.of(SName.root, SName.caption) + .getMergedStyle(skinParam.getCurrentStyleBuilder()); return style.createTextBlockBordered(caption.getDisplay(), skinParam.getIHtmlColorSet(), skinParam); } return caption.getDisplay().create(new FontConfiguration(getSkinParam(), FontParam.CAPTION, null), @@ -182,8 +186,8 @@ public class AnnotatedWorker { final TextBlock block; if (SkinParam.USE_STYLES()) { - final Style style = StyleSignature.of(SName.root, SName.title).getMergedStyle( - skinParam.getCurrentStyleBuilder()); + final Style style = StyleSignature.of(SName.root, SName.title) + .getMergedStyle(skinParam.getCurrentStyleBuilder()); block = style.createTextBlockBordered(title.getDisplay(), skinParam.getIHtmlColorSet(), skinParam); } else { final ISkinParam skinParam = getSkinParam(); diff --git a/src/net/sourceforge/plantuml/FileFormat.java b/src/net/sourceforge/plantuml/FileFormat.java index 0b5ecccd0..47548eca5 100644 --- a/src/net/sourceforge/plantuml/FileFormat.java +++ b/src/net/sourceforge/plantuml/FileFormat.java @@ -38,6 +38,7 @@ package net.sourceforge.plantuml; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics2D; +import java.awt.RenderingHints; import java.awt.geom.Dimension2D; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; @@ -58,7 +59,8 @@ import net.sourceforge.plantuml.ugraphic.UFont; * */ public enum FileFormat { - PNG, SVG, EPS, EPS_TEXT, ATXT, UTXT, XMI_STANDARD, XMI_STAR, XMI_ARGO, SCXML, PDF, MJPEG, ANIMATED_GIF, HTML, HTML5, VDX, LATEX, LATEX_NO_PREAMBLE, BASE64, BRAILLE_PNG, PREPROC; + PNG, SVG, EPS, EPS_TEXT, ATXT, UTXT, XMI_STANDARD, XMI_STAR, XMI_ARGO, SCXML, PDF, MJPEG, ANIMATED_GIF, HTML, HTML5, + VDX, LATEX, LATEX_NO_PREAMBLE, BASE64, BRAILLE_PNG, PREPROC; /** * Returns the file format to be used for that format. @@ -89,6 +91,10 @@ public enum FileFormat { final static private BufferedImage imDummy = new BufferedImage(800, 100, BufferedImage.TYPE_INT_RGB); final static private Graphics2D gg = imDummy.createGraphics(); + static { + // KEY_FRACTIONALMETRICS + gg.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + } public StringBounder getDefaultStringBounder(TikzFontDistortion tikzFontDistortion) { if (this == LATEX || this == LATEX_NO_PREAMBLE) { @@ -178,8 +184,8 @@ public enum FileFormat { if (cpt == 0) { return changeName(fileName, getFileSuffix()); } - return changeName(fileName, OptionFlags.getInstance().getFileSeparator() + String.format("%03d", cpt) - + getFileSuffix()); + return changeName(fileName, + OptionFlags.getInstance().getFileSeparator() + String.format("%03d", cpt) + getFileSuffix()); } private File computeFilename(File pngFile, int i) { @@ -233,4 +239,5 @@ public enum FileFormat { } return false; } + } diff --git a/src/net/sourceforge/plantuml/Run.java b/src/net/sourceforge/plantuml/Run.java index 6bc6d4960..40d8139c2 100644 --- a/src/net/sourceforge/plantuml/Run.java +++ b/src/net/sourceforge/plantuml/Run.java @@ -57,6 +57,7 @@ import javax.swing.UIManager; import net.sourceforge.plantuml.activitydiagram.ActivityDiagramFactory; import net.sourceforge.plantuml.classdiagram.ClassDiagramFactory; +import net.sourceforge.plantuml.code.NoPlantumlCompressionException; import net.sourceforge.plantuml.code.Transcoder; import net.sourceforge.plantuml.code.TranscoderUtil; import net.sourceforge.plantuml.command.UmlDiagramFactory; @@ -78,7 +79,7 @@ public class Run { private static Cypher cypher; - public static void main(String[] argsArray) throws IOException, InterruptedException { + public static void main(String[] argsArray) throws NoPlantumlCompressionException, IOException, InterruptedException { System.setProperty("log4j.debug", "false"); final long start = System.currentTimeMillis(); if (argsArray.length > 0 && argsArray[0].equalsIgnoreCase("-headless")) { @@ -358,7 +359,7 @@ public class Run { new Pipe(option, System.out, System.in, charset).managePipe(error); } - private static void manageAllFiles(Option option, ErrorStatus error) throws IOException, InterruptedException { + private static void manageAllFiles(Option option, ErrorStatus error) throws NoPlantumlCompressionException, InterruptedException { File lockFile = null; try { @@ -377,7 +378,7 @@ public class Run { } - private static void processArgs(Option option, ErrorStatus error) throws IOException, InterruptedException { + private static void processArgs(Option option, ErrorStatus error) throws NoPlantumlCompressionException, InterruptedException { if (option.isDecodeurl() == false && option.getNbThreads() > 1 && option.isCheckOnly() == false && OptionFlags.getInstance().isExtractFromMetadata() == false) { multithread(option, error); diff --git a/src/net/sourceforge/plantuml/SkinParam.java b/src/net/sourceforge/plantuml/SkinParam.java index f05477894..b4fd8cb47 100644 --- a/src/net/sourceforge/plantuml/SkinParam.java +++ b/src/net/sourceforge/plantuml/SkinParam.java @@ -156,6 +156,14 @@ public class SkinParam implements ISkinParam { return result; } + static public void setBetaStyle(boolean betastyle) { + USE_STYLE2.set(betastyle); + } + + public static int zeroMargin(int defaultValue) { + return defaultValue; + } + private static final String stereoPatternString = "\\<\\<(.*?)\\>\\>"; private static final Pattern2 stereoPattern = MyPattern.cmpile(stereoPatternString); @@ -176,7 +184,8 @@ public class SkinParam implements ISkinParam { for (String key2 : cleanForKey(key)) { params.put(key2, StringUtils.trin(value)); if (key2.startsWith("usebetastyle")) { - USE_STYLE2.set("true".equalsIgnoreCase(value)); + final boolean betastyle = "true".equalsIgnoreCase(value); + setBetaStyle(betastyle); } if (USE_STYLES()) { final FromSkinparamToStyle convertor = new FromSkinparamToStyle(key2, value, getCurrentStyleBuilder()); diff --git a/src/net/sourceforge/plantuml/SourceStringReader.java b/src/net/sourceforge/plantuml/SourceStringReader.java index d2bcbbac2..2a5c4cda4 100644 --- a/src/net/sourceforge/plantuml/SourceStringReader.java +++ b/src/net/sourceforge/plantuml/SourceStringReader.java @@ -59,11 +59,11 @@ public class SourceStringReader { final private List blocks; public SourceStringReader(String source) { - this(Defines.createEmpty(), source, Collections. emptyList()); + this(Defines.createEmpty(), source, Collections.emptyList()); } public SourceStringReader(String source, String charset) { - this(Defines.createEmpty(), source, "UTF-8", Collections. emptyList()); + this(Defines.createEmpty(), source, "UTF-8", Collections.emptyList()); } public SourceStringReader(Defines defines, String source, List config) { @@ -71,11 +71,11 @@ public class SourceStringReader { } public SourceStringReader(Defines defines, String source) { - this(defines, source, "UTF-8", Collections. emptyList()); + this(defines, source, "UTF-8", Collections.emptyList()); } public SourceStringReader(String source, File newCurrentDir) { - this(Defines.createEmpty(), source, "UTF-8", Collections. emptyList(), newCurrentDir); + this(Defines.createEmpty(), source, "UTF-8", Collections.emptyList(), newCurrentDir); } public SourceStringReader(Defines defines, String source, String charset, List config) { @@ -157,7 +157,8 @@ public class SourceStringReader { // final CMapData cmap = new CMapData(); final ImageData imageData = system.exportDiagram(os, numImage, fileFormatOption); // if (imageData.containsCMapData()) { - // return system.getDescription().getDescription() + BackSlash.BS_N + imageData.getCMapData("plantuml"); + // return system.getDescription().getDescription() + BackSlash.BS_N + + // imageData.getCMapData("plantuml"); // } return system.getDescription(); } @@ -176,9 +177,11 @@ public class SourceStringReader { final Diagram system = b.getDiagram(); final int nbInSystem = system.getNbImages(); if (numImage < nbInSystem) { - // final ImageData imageData = system.exportDiagram(os, numImage, fileFormatOption); + // final ImageData imageData = system.exportDiagram(os, numImage, + // fileFormatOption); // if (imageData.containsCMapData()) { - // return system.getDescription().withCMapData(imageData.getCMapData("plantuml")); + // return + // system.getDescription().withCMapData(imageData.getCMapData("plantuml")); // } return system.getDescription(); } @@ -223,8 +226,8 @@ public class SourceStringReader { private void noStartumlFound(OutputStream os, FileFormatOption fileFormatOption, long seed) throws IOException { final TextBlockBackcolored error = GraphicStrings.createForError(Arrays.asList("No @startuml/@enduml found"), fileFormatOption.isUseRedForError()); - final ImageBuilder imageBuilder = new ImageBuilder(new ColorMapperIdentity(), 1.0, error.getBackcolor(), null, - null, 0, 0, null, false); + final ImageBuilder imageBuilder = ImageBuilder.buildA(new ColorMapperIdentity(), false, null, null, null, + 1.0, error.getBackcolor()); imageBuilder.setUDrawable(error); imageBuilder.writeImageTOBEMOVED(fileFormatOption, seed, os); } diff --git a/src/net/sourceforge/plantuml/StringLocated.java b/src/net/sourceforge/plantuml/StringLocated.java index 140a71808..54b93d92d 100644 --- a/src/net/sourceforge/plantuml/StringLocated.java +++ b/src/net/sourceforge/plantuml/StringLocated.java @@ -99,6 +99,10 @@ final public class StringLocated { return trimmed; } +// public StringLocated getTrimmedRight() { +// return new StringLocated(StringUtils.trinEnding(this.getString()), location, preprocessorError); +// } + public StringLocated removeInnerComment() { final String string = s.toString(); final String trim = string.replace('\t', ' ').trim(); diff --git a/src/net/sourceforge/plantuml/StringUtils.java b/src/net/sourceforge/plantuml/StringUtils.java index 9a508ce1c..e75cdface 100644 --- a/src/net/sourceforge/plantuml/StringUtils.java +++ b/src/net/sourceforge/plantuml/StringUtils.java @@ -456,18 +456,33 @@ public class StringUtils { if (arg.length() == 0) { return arg; } + return trinEndingInternal(arg, getPositionStartNonSpace(arg)); + } + + private static int getPositionStartNonSpace(String arg) { int i = 0; while (i < arg.length() && isSpaceOrTabOrNull(arg.charAt(i))) { i++; } - int j = arg.length() - 1; - while (j >= i && isSpaceOrTabOrNull(arg.charAt(j))) { - j--; - } - if (i == 0 && j == arg.length() - 1) { + return i; + } + + private static String trinEnding(String arg) { + if (arg.length() == 0) { return arg; } - return arg.substring(i, j + 1); + return trinEndingInternal(arg, 0); + } + + private static String trinEndingInternal(String arg, int from) { + int j = arg.length() - 1; + while (j >= from && isSpaceOrTabOrNull(arg.charAt(j))) { + j--; + } + if (from == 0 && j == arg.length() - 1) { + return arg; + } + return arg.substring(from, j + 1); } private static boolean isSpaceOrTabOrNull(char c) { diff --git a/src/net/sourceforge/plantuml/UmlDiagram.java b/src/net/sourceforge/plantuml/UmlDiagram.java index c735de6b2..8f8beb03d 100644 --- a/src/net/sourceforge/plantuml/UmlDiagram.java +++ b/src/net/sourceforge/plantuml/UmlDiagram.java @@ -207,6 +207,9 @@ public abstract class UmlDiagram extends TitledDiagram implements Diagram, Annot } catch (Exception e) { e.printStackTrace(); exportDiagramError(os, e, fileFormatOption, seed, null); + } catch (Error e) { + e.printStackTrace(); + exportDiagramError(os, e, fileFormatOption, seed, null); } return ImageDataSimple.error(); } @@ -227,8 +230,8 @@ public abstract class UmlDiagram extends TitledDiagram implements Diagram, Annot strings.addAll(CommandExecutionResult.getStackTrace(exception)); - final ImageBuilder imageBuilder = new ImageBuilder(new ColorMapperIdentity(), 1.0, HColorUtils.WHITE, metadata, - null, 0, 0, null, false); + final ImageBuilder imageBuilder = ImageBuilder.buildA(new ColorMapperIdentity(), false, + null, metadata, null, 1.0, HColorUtils.WHITE); final FlashCodeUtils utils = FlashCodeFactory.getFlashCodeUtils(); final BufferedImage im = utils.exportFlashcode(flash, Color.BLACK, Color.WHITE); diff --git a/src/net/sourceforge/plantuml/UmlDiagramType.java b/src/net/sourceforge/plantuml/UmlDiagramType.java index 68947c1cc..4d93c28e1 100644 --- a/src/net/sourceforge/plantuml/UmlDiagramType.java +++ b/src/net/sourceforge/plantuml/UmlDiagramType.java @@ -35,6 +35,40 @@ */ package net.sourceforge.plantuml; +import net.sourceforge.plantuml.style.SName; + public enum UmlDiagramType { - SEQUENCE, STATE, CLASS, OBJECT, ACTIVITY, DESCRIPTION, COMPOSITE, FLOW, TIMING, BPM, NWDIAG, MINDMAP, WBS, WIRE, HELP + SEQUENCE, STATE, CLASS, OBJECT, ACTIVITY, DESCRIPTION, COMPOSITE, FLOW, TIMING, BPM, NWDIAG, MINDMAP, WBS, WIRE, + HELP; + + public SName getStyleName() { + if (this == SEQUENCE) { + return SName.sequenceDiagram; + } + if (this == STATE) { + return SName.stateDiagram; + } + if (this == CLASS) { + return SName.classDiagram; + } + if (this == OBJECT) { + return SName.objectDiagram; + } + if (this == ACTIVITY) { + return SName.activityDiagram; + } + if (this == DESCRIPTION) { + return SName.componentDiagram; + } + if (this == COMPOSITE) { + return SName.componentDiagram; + } + if (this == MINDMAP) { + return SName.mindmapDiagram; + } + if (this == WBS) { + return SName.wbsDiagram; + } + return SName.activityDiagram; + } } diff --git a/src/net/sourceforge/plantuml/activitydiagram/command/CommandLinkLongActivity.java b/src/net/sourceforge/plantuml/activitydiagram/command/CommandLinkLongActivity.java index 6b253da61..84fb2273c 100644 --- a/src/net/sourceforge/plantuml/activitydiagram/command/CommandLinkLongActivity.java +++ b/src/net/sourceforge/plantuml/activitydiagram/command/CommandLinkLongActivity.java @@ -115,8 +115,8 @@ public class CommandLinkLongActivity extends CommandMultilines2 @Override protected CommandExecutionResult executeNow(final ActivityDiagram diagram, BlocLines lines) { - lines = lines.trim(false); - final RegexResult line0 = getStartingPattern().matcher(lines.getFirst499().getTrimmed().getString()); + lines = lines.trim(); + final RegexResult line0 = getStartingPattern().matcher(lines.getFirst().getTrimmed().getString()); final IEntity entity1 = CommandLinkActivity.getEntity(diagram, line0, true); if (entity1 == null) { @@ -157,7 +157,7 @@ public class CommandLinkLongActivity extends CommandMultilines2 } } - final List lineLast = StringUtils.getSplit(MyPattern.cmpile(getPatternEnd()), lines.getLast499() + final List lineLast = StringUtils.getSplit(MyPattern.cmpile(getPatternEnd()), lines.getLast() .getString()); if (StringUtils.isNotEmpty(lineLast.get(0))) { if (sb.length() > 0 && sb.toString().endsWith(BackSlash.BS_BS_N) == false) { diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ActivityDiagram3.java b/src/net/sourceforge/plantuml/activitydiagram3/ActivityDiagram3.java index 6afcc348e..779d2635b 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/ActivityDiagram3.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/ActivityDiagram3.java @@ -45,13 +45,12 @@ import net.sourceforge.plantuml.FileFormatOption; import net.sourceforge.plantuml.ISkinParam; import net.sourceforge.plantuml.ISkinSimple; import net.sourceforge.plantuml.Scale; +import net.sourceforge.plantuml.SkinParam; import net.sourceforge.plantuml.UmlDiagram; import net.sourceforge.plantuml.UmlDiagramType; import net.sourceforge.plantuml.Url; import net.sourceforge.plantuml.activitydiagram3.ftile.BoxStyle; -import net.sourceforge.plantuml.activitydiagram3.ftile.ISwimlanesA; -import net.sourceforge.plantuml.activitydiagram3.ftile.SwimlanesAAA; -import net.sourceforge.plantuml.activitydiagram3.ftile.SwimlanesC; +import net.sourceforge.plantuml.activitydiagram3.ftile.Swimlanes; import net.sourceforge.plantuml.command.CommandExecutionResult; import net.sourceforge.plantuml.core.DiagramDescription; import net.sourceforge.plantuml.core.ImageData; @@ -63,6 +62,7 @@ import net.sourceforge.plantuml.graphic.USymbol; import net.sourceforge.plantuml.graphic.color.Colors; import net.sourceforge.plantuml.sequencediagram.NotePosition; import net.sourceforge.plantuml.sequencediagram.NoteType; +import net.sourceforge.plantuml.style.ClockwiseTopRightBottomLeft; import net.sourceforge.plantuml.ugraphic.ImageBuilder; import net.sourceforge.plantuml.ugraphic.color.HColor; import net.sourceforge.plantuml.ugraphic.comp.CompressionMode; @@ -76,36 +76,7 @@ public class ActivityDiagram3 extends UmlDiagram { private SwimlaneStrategy swimlaneStrategy; - private final ISwimlanesA swinlanes = new SwimlanesAAA(getSkinParam(), getPragma()); - // private final ISwimlanesA swinlanes = new SwimlanesC(getSkinParam(), - // getPragma()); - - private ImageData exportDiagramInternalAAA(OutputStream os, int index, FileFormatOption fileFormatOption) - throws IOException { - // BUG42 - // COMPRESSION - swinlanes.computeSize(fileFormatOption.getDefaultStringBounder()); - TextBlock result = swinlanes; - - result = CompressionXorYBuilder.build(CompressionMode.ON_X, result, fileFormatOption.getDefaultStringBounder()); - result = CompressionXorYBuilder.build(CompressionMode.ON_Y, result, fileFormatOption.getDefaultStringBounder()); - - result = new TextBlockRecentred(result); - final ISkinParam skinParam = getSkinParam(); - result = new AnnotatedWorker(this, skinParam, fileFormatOption.getDefaultStringBounder()).addAdd(result); - - final Dimension2D dim = result.getMinMax(fileFormatOption.getDefaultStringBounder()).getDimension(); - final double margin = 10; - final double dpiFactor = getDpiFactor(fileFormatOption, Dimension2DDouble.delta(dim, 2 * margin, 0)); - - final ImageBuilder imageBuilder = new ImageBuilder(getSkinParam(), dpiFactor, - fileFormatOption.isWithMetadata() ? getMetadata() : null, getWarningOrError(), margin, margin, - getAnimation()); - imageBuilder.setUDrawable(result); - - return imageBuilder.writeImageTOBEMOVED(fileFormatOption, seed(), os); - - } + private final Swimlanes swinlanes = new Swimlanes(getSkinParam(), getPragma()); public ActivityDiagram3(ISkinSimple skinParam) { super(skinParam); @@ -233,9 +204,6 @@ public class ActivityDiagram3 extends UmlDiagram { @Override protected ImageData exportDiagramInternal(OutputStream os, int index, FileFormatOption fileFormatOption) throws IOException { - if (swinlanes instanceof SwimlanesC == false || swinlanes instanceof SwimlanesAAA) { - return exportDiagramInternalAAA(os, index, fileFormatOption); - } // BUG42 // COMPRESSION swinlanes.computeSize(fileFormatOption.getDefaultStringBounder()); @@ -249,12 +217,18 @@ public class ActivityDiagram3 extends UmlDiagram { result = new AnnotatedWorker(this, skinParam, fileFormatOption.getDefaultStringBounder()).addAdd(result); final Dimension2D dim = result.getMinMax(fileFormatOption.getDefaultStringBounder()).getDimension(); - final double margin = 10; - final double dpiFactor = getDpiFactor(fileFormatOption, Dimension2DDouble.delta(dim, 2 * margin, 0)); + final ClockwiseTopRightBottomLeft margins; + if (SkinParam.USE_STYLES()) { + margins = ClockwiseTopRightBottomLeft.marginForDocument(skinParam.getCurrentStyleBuilder()); + } else { + margins = ClockwiseTopRightBottomLeft.margin1margin2(10, 10); + } - final ImageBuilder imageBuilder = new ImageBuilder(getSkinParam(), dpiFactor, - fileFormatOption.isWithMetadata() ? getMetadata() : null, getWarningOrError(), margin, margin, - getAnimation()); + final double dpiFactor = getDpiFactor(fileFormatOption, + Dimension2DDouble.delta(dim, margins.getLeft() + margins.getRight(), 0)); + + final ImageBuilder imageBuilder = ImageBuilder.buildD(getSkinParam(), margins, getAnimation(), + fileFormatOption.isWithMetadata() ? getMetadata() : null, getWarningOrError(), dpiFactor); imageBuilder.setUDrawable(result); return imageBuilder.writeImageTOBEMOVED(fileFormatOption, seed(), os); diff --git a/src/net/sourceforge/plantuml/activitydiagram3/command/CommandActivity3.java b/src/net/sourceforge/plantuml/activitydiagram3/command/CommandActivity3.java index 9a9fa7813..86510d8f9 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/command/CommandActivity3.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/command/CommandActivity3.java @@ -35,6 +35,8 @@ */ package net.sourceforge.plantuml.activitydiagram3.command; +import java.util.regex.Matcher; + import net.sourceforge.plantuml.ColorParam; import net.sourceforge.plantuml.LineLocation; import net.sourceforge.plantuml.Url; @@ -56,7 +58,26 @@ import net.sourceforge.plantuml.graphic.color.Colors; public class CommandActivity3 extends SingleLineCommand2 { - public static final String ENDING_GROUP = "(;|\\\\\\\\|(?}\\]])(?:[/<}\\]])|(?]{1,999})(?)(?:\\>)|(?}\\]])[/<}]" // About /<} + + "|" // + + "(?]{1,999})(?)\\>" // About > + + "|" // + + "(? { RegexLeaf.spaceZeroOrMore(), // new RegexLeaf(":"), // new RegexLeaf("LABEL", "(.*)"), // - new RegexLeaf("STYLE", ENDING_GROUP), // + new RegexLeaf("STYLE", endingGroup()), // RegexLeaf.end()); } diff --git a/src/net/sourceforge/plantuml/activitydiagram3/command/CommandActivityLong3.java b/src/net/sourceforge/plantuml/activitydiagram3/command/CommandActivityLong3.java index 76c8312a2..d108882ce 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/command/CommandActivityLong3.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/command/CommandActivityLong3.java @@ -57,7 +57,7 @@ public class CommandActivityLong3 extends CommandMultilines2 { @Override public String getPatternEnd() { - return "^(.*)" + CommandActivity3.ENDING_GROUP + "$"; + return "^(.*)" + CommandActivity3.endingGroup() + "$"; } private static ColorParser color() { @@ -75,11 +75,11 @@ public class CommandActivityLong3 extends CommandMultilines2 { @Override protected CommandExecutionResult executeNow(ActivityDiagram3 diagram, BlocLines lines) { lines = lines.removeEmptyColumns(); - final RegexResult line0 = getStartingPattern().matcher(lines.getFirst499().getTrimmed().getString()); + final RegexResult line0 = getStartingPattern().matcher(lines.getFirst().getTrimmed().getString()); final Colors colors = color().getColor(line0, diagram.getSkinParam().getIHtmlColorSet()); // final HtmlColor color = diagram.getSkinParam().getIHtmlColorSet().getColorIfValid(line0.get("COLOR", 0)); final BoxStyle style = BoxStyle.fromChar(lines.getLastChar()); - lines = lines.removeStartingAndEnding2(line0.get("DATA", 0)); + lines = lines.removeStartingAndEnding(line0.get("DATA", 0), 1); diagram.addActivity(lines.toDisplay(), style, null, colors); return CommandExecutionResult.ok(); } diff --git a/src/net/sourceforge/plantuml/activitydiagram3/command/CommandArrowLong3.java b/src/net/sourceforge/plantuml/activitydiagram3/command/CommandArrowLong3.java index d41d3690d..44b0db219 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/command/CommandArrowLong3.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/command/CommandArrowLong3.java @@ -74,7 +74,7 @@ public class CommandArrowLong3 extends CommandMultilines2 { @Override protected CommandExecutionResult executeNow(ActivityDiagram3 diagram, BlocLines lines) { lines = lines.removeEmptyColumns(); - final RegexResult line0 = getStartingPattern().matcher(lines.getFirst499().getTrimmed().getString()); + final RegexResult line0 = getStartingPattern().matcher(lines.getFirst().getTrimmed().getString()); // final HtmlColor color = diagram.getSkinParam().getIHtmlColorSet().getColorIfValid(line0.get("COLOR", 0)); // diagram.setColorNextArrow(Rainbow.fromColor(color)); final String colorString = line0.get("COLOR", 0); @@ -83,7 +83,7 @@ public class CommandArrowLong3 extends CommandMultilines2 { .colorArrowSeparationSpace()); diagram.setColorNextArrow(rainbow); } - lines = lines.removeStartingAndEnding2(line0.get("LABEL", 0)); + lines = lines.removeStartingAndEnding(line0.get("LABEL", 0), 1); diagram.setLabelNextArrow(lines.toDisplay()); return CommandExecutionResult.ok(); } diff --git a/src/net/sourceforge/plantuml/activitydiagram3/command/CommandBackward3.java b/src/net/sourceforge/plantuml/activitydiagram3/command/CommandBackward3.java index 566c9bca9..4d786b424 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/command/CommandBackward3.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/command/CommandBackward3.java @@ -58,7 +58,7 @@ public class CommandBackward3 extends SingleLineCommand2 { RegexLeaf.spaceZeroOrMore(), // new RegexLeaf(":"), // new RegexLeaf("LABEL", "(.*)"), // - new RegexLeaf("STYLE", CommandActivity3.ENDING_GROUP), // + new RegexLeaf("STYLE", CommandActivity3.endingGroup()), // RegexLeaf.end()); } diff --git a/src/net/sourceforge/plantuml/activitydiagram3/command/CommandNoteLong3.java b/src/net/sourceforge/plantuml/activitydiagram3/command/CommandNoteLong3.java index 967eba88c..91ee7ca92 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/command/CommandNoteLong3.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/command/CommandNoteLong3.java @@ -69,7 +69,7 @@ public class CommandNoteLong3 extends CommandMultilines2 { @Override protected CommandExecutionResult executeNow(final ActivityDiagram3 diagram, BlocLines lines) { // final List in = StringUtils.removeEmptyColumns2(lines.subList(1, lines.size() - 1)); - final RegexResult line0 = getStartingPattern().matcher(lines.getFirst499().getTrimmed().getString()); + final RegexResult line0 = getStartingPattern().matcher(lines.getFirst().getTrimmed().getString()); lines = lines.subExtract(1, 1); lines = lines.removeEmptyColumns(); final NotePosition position = NotePosition.defaultLeft(line0.get("POSITION", 0)); diff --git a/src/net/sourceforge/plantuml/activitydiagram3/command/CommandRepeat3.java b/src/net/sourceforge/plantuml/activitydiagram3/command/CommandRepeat3.java index 2812bac5c..51afc90de 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/command/CommandRepeat3.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/command/CommandRepeat3.java @@ -66,7 +66,7 @@ public class CommandRepeat3 extends SingleLineCommand2 { new RegexLeaf("repeat"), // RegexLeaf.spaceZeroOrMore(), // new RegexOptional(new RegexLeaf("LABEL", ":(.*?)")), // - new RegexOptional(new RegexLeaf("STYLE", CommandActivity3.ENDING_GROUP)), // + new RegexOptional(new RegexLeaf("STYLE", CommandActivity3.endingGroup())), // // new RegexLeaf(";?"), // RegexLeaf.end()); } diff --git a/src/net/sourceforge/plantuml/activitydiagram3/command/CommandRepeatWhile3Multilines.java b/src/net/sourceforge/plantuml/activitydiagram3/command/CommandRepeatWhile3Multilines.java index 285eeff46..57a1d80d4 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/command/CommandRepeatWhile3Multilines.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/command/CommandRepeatWhile3Multilines.java @@ -80,9 +80,9 @@ public class CommandRepeatWhile3Multilines extends CommandMultilines3 0 ? titlesHeight + 5 : 0); - } - - private double getTitlesHeight(StringBounder stringBounder) { - double titlesHeight = 0; - for (Swimlane swimlane : swimlanes) { - final TextBlock swTitle = getTitle(swimlane); - titlesHeight = Math.max(titlesHeight, swTitle.calculateDimension(stringBounder).getHeight()); - } - return titlesHeight; - } - -} diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/SwimlanesC.java b/src/net/sourceforge/plantuml/activitydiagram3/ftile/SwimlanesC.java deleted file mode 100644 index 30ce71381..000000000 --- a/src/net/sourceforge/plantuml/activitydiagram3/ftile/SwimlanesC.java +++ /dev/null @@ -1,93 +0,0 @@ -/* ======================================================================== - * PlantUML : a free UML diagram generator - * ======================================================================== - * - * (C) Copyright 2009-2020, Arnaud Roques - * - * Project Info: http://plantuml.com - * - * If you like this project or if you find it useful, you can support us at: - * - * http://plantuml.com/patreon (only 1$ per month!) - * http://plantuml.com/paypal - * - * This file is part of PlantUML. - * - * PlantUML is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * PlantUML distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - * License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA. - * - * - * Original Author: Arnaud Roques - * - * - */ -package net.sourceforge.plantuml.activitydiagram3.ftile; - -import java.awt.geom.Dimension2D; - -import net.sourceforge.plantuml.ColorParam; -import net.sourceforge.plantuml.ISkinParam; -import net.sourceforge.plantuml.LineParam; -import net.sourceforge.plantuml.Pragma; -import net.sourceforge.plantuml.SkinParam; -import net.sourceforge.plantuml.graphic.StringBounder; -import net.sourceforge.plantuml.graphic.TextBlock; -import net.sourceforge.plantuml.skin.rose.Rose; -import net.sourceforge.plantuml.style.PName; -import net.sourceforge.plantuml.ugraphic.UGraphic; -import net.sourceforge.plantuml.ugraphic.ULine; -import net.sourceforge.plantuml.ugraphic.UStroke; -import net.sourceforge.plantuml.ugraphic.UTranslate; -import net.sourceforge.plantuml.ugraphic.color.HColor; - -public class SwimlanesC extends SwimlanesB { - - public SwimlanesC(ISkinParam skinParam, Pragma pragma) { - super(skinParam, pragma); - } - - @Override - protected void drawWhenSwimlanes(UGraphic ug, TextBlock full) { - super.drawWhenSwimlanes(ug, full); - double x2 = 0; - - final StringBounder stringBounder = ug.getStringBounder(); - final Dimension2D dimensionFull = full.calculateDimension(stringBounder); - - final UTranslate titleHeightTranslate = getTitleHeightTranslate(stringBounder); - - for (Swimlane swimlane : swimlanes) { - drawSeparation(ug.apply(UTranslate.dx(x2)), dimensionFull.getHeight() + titleHeightTranslate.getDy()); - - x2 += swimlane.getActualWidth(); - - } - drawSeparation(ug.apply(UTranslate.dx(x2)), dimensionFull.getHeight() + titleHeightTranslate.getDy()); - - } - - private void drawSeparation(UGraphic ug, double height) { - HColor color = skinParam.getHtmlColor(ColorParam.swimlaneBorder, null, false); - if (color == null) { - color = ColorParam.swimlaneBorder.getDefaultValue(); - } - UStroke thickness = Rose.getStroke(skinParam, LineParam.swimlaneBorder, 2); - if (SkinParam.USE_STYLES()) { - color = getStyle().value(PName.LineColor).asColor(skinParam.getIHtmlColorSet()); - thickness = getStyle().getStroke(); - } - ug.apply(thickness).apply(color).draw(ULine.vline(height)); - } -} diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/Worm.java b/src/net/sourceforge/plantuml/activitydiagram3/ftile/Worm.java index 72ae426cf..7308ebbfd 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/ftile/Worm.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/ftile/Worm.java @@ -53,7 +53,6 @@ import net.sourceforge.plantuml.ugraphic.UPolygon; import net.sourceforge.plantuml.ugraphic.UStroke; import net.sourceforge.plantuml.ugraphic.UTranslate; import net.sourceforge.plantuml.ugraphic.color.HColor; -import net.sourceforge.plantuml.ugraphic.color.HColorUtils; import net.sourceforge.plantuml.ugraphic.comp.CompressionMode; public class Worm implements Iterable { @@ -101,10 +100,14 @@ public class Worm implements Iterable { } final HColor arrowHeadColor = colorAndStyle.getArrowHeadColor(); - if (arrowHeadColor != null && arrowHeadColor.equals(HColorUtils.transparent()) == false) { - ug = ug.apply(arrowHeadColor); - ug = ug.apply(arrowHeadColor.bg()); + if (arrowHeadColor == null) { + throw new IllegalStateException(); } +// if (arrowHeadColor == null || arrowHeadColor.equals(HColorUtils.transparent())) { +// return; +// } + ug = ug.apply(arrowHeadColor); + ug = ug.apply(arrowHeadColor.bg()); if (startDecoration != null) { ug = ug.apply(new UStroke(1.5)); @@ -212,6 +215,12 @@ public class Worm implements Iterable { } public void addPoint(double x, double y) { + if (Double.isNaN(x)) { + throw new IllegalArgumentException(); + } + if (Double.isNaN(y)) { + throw new IllegalArgumentException(); + } if (points.size() > 0) { final Point2D last = getLast(); if (last.getX() == x && last.getY() == y) { diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/ZadBuilder.java b/src/net/sourceforge/plantuml/activitydiagram3/ftile/ZadBuilder.java index 933ac1a51..5a7d3f82a 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/ftile/ZadBuilder.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/ftile/ZadBuilder.java @@ -38,8 +38,8 @@ package net.sourceforge.plantuml.activitydiagram3.ftile; import net.sourceforge.plantuml.Url; import net.sourceforge.plantuml.graphic.StringBounder; import net.sourceforge.plantuml.ugraphic.MinMax; -import net.sourceforge.plantuml.ugraphic.UChange; import net.sourceforge.plantuml.ugraphic.UBackground; +import net.sourceforge.plantuml.ugraphic.UChange; import net.sourceforge.plantuml.ugraphic.UGraphic; import net.sourceforge.plantuml.ugraphic.UParam; import net.sourceforge.plantuml.ugraphic.UParamNull; diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/AbstractParallelFtilesBuilder.java b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/AbstractParallelFtilesBuilder.java index cf787e45e..b1b2a46ba 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/AbstractParallelFtilesBuilder.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/AbstractParallelFtilesBuilder.java @@ -35,7 +35,7 @@ */ package net.sourceforge.plantuml.activitydiagram3.ftile.vcompact; -import java.util.Collections; +import java.util.ArrayList; import java.util.List; import net.sourceforge.plantuml.FontParam; @@ -43,7 +43,8 @@ import net.sourceforge.plantuml.ISkinParam; import net.sourceforge.plantuml.SkinParam; import net.sourceforge.plantuml.activitydiagram3.LinkRendering; import net.sourceforge.plantuml.activitydiagram3.ftile.Ftile; -import net.sourceforge.plantuml.activitydiagram3.ftile.FtileGeometry; +import net.sourceforge.plantuml.activitydiagram3.ftile.FtileHeightFixedCentered; +import net.sourceforge.plantuml.activitydiagram3.ftile.FtileUtils; import net.sourceforge.plantuml.activitydiagram3.ftile.Swimlane; import net.sourceforge.plantuml.creole.CreoleMode; import net.sourceforge.plantuml.cucadiagram.Display; @@ -64,10 +65,7 @@ public abstract class AbstractParallelFtilesBuilder { private final ISkinParam skinParam; private final StringBounder stringBounder; - - private final List list; - private final Ftile middle; - private final FtileGeometry middleDimension; + protected final List list99 = new ArrayList(); public StyleSignature getDefaultStyleDefinition() { return StyleSignature.of(SName.root, SName.element, SName.activityDiagram, SName.activity); @@ -77,23 +75,47 @@ public abstract class AbstractParallelFtilesBuilder { return StyleSignature.of(SName.root, SName.element, SName.activityDiagram, SName.arrow); } - public AbstractParallelFtilesBuilder(ISkinParam skinParam, StringBounder stringBounder, final List list, - Ftile middle) { + public AbstractParallelFtilesBuilder(ISkinParam skinParam, StringBounder stringBounder, List all) { this.skinParam = skinParam; this.stringBounder = stringBounder; - this.list = list; - this.middle = middle; - this.middleDimension = middle.calculateDimension(getStringBounder()); + this.list99.addAll(getFoo2(all)); } - public final Ftile build() { - final Ftile step1 = doStep1(); - return doStep2(step1); + protected List getFoo2(List all) { + final double maxHeight = computeMaxHeight(all); + final List result = new ArrayList(); + for (Ftile ftile : all) { + final Ftile newFtile = computeNewFtile(ftile, maxHeight); + result.add(newFtile); + } + return result; } - protected abstract Ftile doStep1(); + private Ftile computeNewFtile(Ftile ftile, double maxHeight) { + final double spaceArroundBlackBar = 20; + final double xMargin = 14; + Ftile tmp; + tmp = FtileUtils.addHorizontalMargin(ftile, xMargin); + tmp = new FtileHeightFixedCentered(tmp, maxHeight + 2 * spaceArroundBlackBar); + return tmp; + } - protected abstract Ftile doStep2(Ftile step1); + final protected double computeMaxHeight(List all) { + double height = 0; + for (Ftile tmp : all) { + height = Math.max(height, tmp.calculateDimension(getStringBounder()).getHeight()); + } + return height; + } + + public final Ftile build(Ftile inner) { + final Ftile step1 = doStep1(inner); + return doStep2(inner, step1); + } + + protected abstract Ftile doStep1(Ftile inner); + + protected abstract Ftile doStep2(Ftile inner, Ftile step1); protected StringBounder getStringBounder() { return stringBounder; @@ -128,20 +150,12 @@ public abstract class AbstractParallelFtilesBuilder { return getTextBlock(display); } - protected final List getList() { - return Collections.unmodifiableList(list); - } - - protected final Ftile getMiddle() { - return middle; - } - - protected final double getHeightOfMiddle() { - return middleDimension.getHeight(); + protected final double getHeightOfMiddle(Ftile middle) { + return middle.calculateDimension(getStringBounder()).getHeight(); } protected Swimlane swimlaneOutForStep2() { - return list.get(list.size() - 1).getSwimlaneOut(); + return list99.get(list99.size() - 1).getSwimlaneOut(); } } diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/FtileFactoryDelegatorCreateParallel.java b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/FtileFactoryDelegatorCreateParallel.java index 10236813e..8c7576241 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/FtileFactoryDelegatorCreateParallel.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/FtileFactoryDelegatorCreateParallel.java @@ -35,56 +35,35 @@ */ package net.sourceforge.plantuml.activitydiagram3.ftile.vcompact; -import java.awt.geom.Dimension2D; -import java.util.ArrayList; import java.util.List; import net.sourceforge.plantuml.activitydiagram3.ForkStyle; import net.sourceforge.plantuml.activitydiagram3.ftile.Ftile; import net.sourceforge.plantuml.activitydiagram3.ftile.FtileFactory; import net.sourceforge.plantuml.activitydiagram3.ftile.FtileFactoryDelegator; -import net.sourceforge.plantuml.activitydiagram3.ftile.FtileHeightFixed; -import net.sourceforge.plantuml.activitydiagram3.ftile.FtileUtils; import net.sourceforge.plantuml.activitydiagram3.ftile.Swimlane; -public class FtileFactoryDelegatorCreateParallel extends FtileFactoryDelegator { - - private final double spaceArroundBlackBar = 20; - private final double xMargin = 14; +public final class FtileFactoryDelegatorCreateParallel extends FtileFactoryDelegator { public FtileFactoryDelegatorCreateParallel(FtileFactory factory) { super(factory); } - private Ftile allOverlapped(Swimlane swimlane, List all, ForkStyle style, String label) { - return new FtileForkInnerOverlapped(all); - } - @Override public Ftile createParallel(List all, ForkStyle style, String label, Swimlane in, Swimlane out) { - final Dimension2D dimSuper = super.createParallel(all, style, label, in, out).calculateDimension( - getStringBounder()); - final double height1 = dimSuper.getHeight() + 2 * spaceArroundBlackBar; - - final List list = new ArrayList(); - for (Ftile tmp : all) { - list.add(new FtileHeightFixed(FtileUtils.addHorizontalMargin(tmp, xMargin), height1)); - } - final Ftile inner = super.createParallel(list, style, label, in, out); - AbstractParallelFtilesBuilder builder; - if (style == ForkStyle.SPLIT) { - builder = new ParallelBuilderSplit(skinParam(), getStringBounder(), list, inner); + builder = new ParallelBuilderSplit(skinParam(), getStringBounder(), all); } else if (style == ForkStyle.MERGE) { - builder = new ParallelBuilderMerge(skinParam(), getStringBounder(), list, inner); + builder = new ParallelBuilderMerge(skinParam(), getStringBounder(), all); } else if (style == ForkStyle.FORK) { - builder = new ParallelBuilderFork(skinParam(), getStringBounder(), list, inner, label, in, out); + builder = new ParallelBuilderFork(skinParam(), getStringBounder(), label, in, out, all); } else { throw new IllegalStateException(); } - return builder.build(); + final Ftile inner = super.createParallel(builder.list99, style, label, in, out); + return builder.build(inner); } } diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/FtileFactoryDelegatorCreateParallelAddingMargin.java b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/FtileFactoryDelegatorCreateParallelAddingMargin.java deleted file mode 100644 index b26904f8a..000000000 --- a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/FtileFactoryDelegatorCreateParallelAddingMargin.java +++ /dev/null @@ -1,73 +0,0 @@ -/* ======================================================================== - * PlantUML : a free UML diagram generator - * ======================================================================== - * - * (C) Copyright 2009-2020, Arnaud Roques - * - * Project Info: http://plantuml.com - * - * If you like this project or if you find it useful, you can support us at: - * - * http://plantuml.com/patreon (only 1$ per month!) - * http://plantuml.com/paypal - * - * This file is part of PlantUML. - * - * PlantUML is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * PlantUML distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - * License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA. - * - * - * Original Author: Arnaud Roques - * - * - */ -package net.sourceforge.plantuml.activitydiagram3.ftile.vcompact; - -import java.awt.geom.Dimension2D; -import java.util.ArrayList; -import java.util.List; - -import net.sourceforge.plantuml.activitydiagram3.ForkStyle; -import net.sourceforge.plantuml.activitydiagram3.ftile.Ftile; -import net.sourceforge.plantuml.activitydiagram3.ftile.FtileFactory; -import net.sourceforge.plantuml.activitydiagram3.ftile.FtileFactoryDelegator; -import net.sourceforge.plantuml.activitydiagram3.ftile.FtileHeightFixed; -import net.sourceforge.plantuml.activitydiagram3.ftile.FtileUtils; -import net.sourceforge.plantuml.activitydiagram3.ftile.Swimlane; - -public class FtileFactoryDelegatorCreateParallelAddingMargin extends FtileFactoryDelegator { - - private final double spaceArroundBlackBar = 20; - private final double xMargin = 14; - - public FtileFactoryDelegatorCreateParallelAddingMargin(FtileFactory factory) { - super(factory); - } - - @Override - public Ftile createParallel(List all, ForkStyle style, String label, Swimlane in, Swimlane out) { - - final Dimension2D dimSuper = super.createParallel(all, style, label, in, out).calculateDimension( - getStringBounder()); - final double height1 = dimSuper.getHeight() + 2 * spaceArroundBlackBar; - - final List list = new ArrayList(); - for (Ftile tmp : all) { - list.add(new FtileHeightFixed(FtileUtils.addHorizontalMargin(tmp, xMargin), height1)); - } - return super.createParallel(list, style, label, in, out); - } - -} diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/FtileFactoryDelegatorSwitch.java b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/FtileFactoryDelegatorSwitch.java index 83ce01867..b2af8b90e 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/FtileFactoryDelegatorSwitch.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/FtileFactoryDelegatorSwitch.java @@ -45,7 +45,7 @@ import net.sourceforge.plantuml.activitydiagram3.LinkRendering; import net.sourceforge.plantuml.activitydiagram3.ftile.Ftile; import net.sourceforge.plantuml.activitydiagram3.ftile.FtileFactory; import net.sourceforge.plantuml.activitydiagram3.ftile.FtileFactoryDelegator; -import net.sourceforge.plantuml.activitydiagram3.ftile.FtileMinWidth; +import net.sourceforge.plantuml.activitydiagram3.ftile.FtileMinWidthCentered; import net.sourceforge.plantuml.activitydiagram3.ftile.Swimlane; import net.sourceforge.plantuml.activitydiagram3.ftile.vcompact.cond.FtileSwitchNude; import net.sourceforge.plantuml.activitydiagram3.ftile.vcompact.cond.FtileSwitchWithDiamonds; @@ -77,7 +77,7 @@ public class FtileFactoryDelegatorSwitch extends FtileFactoryDelegator { private Ftile createNude(Swimlane swimlane, List branches) { final List ftiles = new ArrayList(); for (Branch branch : branches) { - ftiles.add(new FtileMinWidth(branch.getFtile(), 30)); + ftiles.add(new FtileMinWidthCentered(branch.getFtile(), 30)); } return new FtileSwitchNude(ftiles, swimlane); } @@ -85,7 +85,7 @@ public class FtileFactoryDelegatorSwitch extends FtileFactoryDelegator { private Ftile createWithDiamonds(Swimlane swimlane, List branches, Display labelTest) { final List ftiles = new ArrayList(); for (Branch branch : branches) { - ftiles.add(new FtileMinWidth(branch.getFtile(), 30)); + ftiles.add(new FtileMinWidthCentered(branch.getFtile(), 30)); } final Ftile diamond1 = getDiamond1(swimlane, branches.get(0), labelTest); final Ftile diamond2 = getDiamond2(swimlane, branches.get(0)); @@ -98,7 +98,7 @@ public class FtileFactoryDelegatorSwitch extends FtileFactoryDelegator { final Ftile diamond1 = getDiamond1(swimlane, branches.get(0), labelTest); final Ftile diamond2 = getDiamond2(swimlane, branches.get(0)); for (Branch branch : branches) { - ftiles.add(new FtileMinWidth(branch.getFtile(), 30)); + ftiles.add(new FtileMinWidthCentered(branch.getFtile(), 30)); } final Rainbow arrowColor = Rainbow.build(skinParam()); if (ftiles.size() == 1) { diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/FtileIfLongHorizontal.java b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/FtileIfLongHorizontal.java index bfedada7c..a3e8f898e 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/FtileIfLongHorizontal.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/FtileIfLongHorizontal.java @@ -37,7 +37,6 @@ package net.sourceforge.plantuml.activitydiagram3.ftile.vcompact; import java.awt.geom.Dimension2D; import java.awt.geom.Point2D; -import java.nio.channels.IllegalSelectorException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -46,7 +45,6 @@ import java.util.List; import java.util.Set; import net.sourceforge.plantuml.Dimension2DDouble; -import net.sourceforge.plantuml.ISkinParam; import net.sourceforge.plantuml.activitydiagram3.Branch; import net.sourceforge.plantuml.activitydiagram3.LinkRendering; import net.sourceforge.plantuml.activitydiagram3.ftile.AbstractConnection; @@ -58,7 +56,7 @@ import net.sourceforge.plantuml.activitydiagram3.ftile.Ftile; import net.sourceforge.plantuml.activitydiagram3.ftile.FtileAssemblySimple; import net.sourceforge.plantuml.activitydiagram3.ftile.FtileFactory; import net.sourceforge.plantuml.activitydiagram3.ftile.FtileGeometry; -import net.sourceforge.plantuml.activitydiagram3.ftile.FtileMinWidth; +import net.sourceforge.plantuml.activitydiagram3.ftile.FtileMinWidthCentered; import net.sourceforge.plantuml.activitydiagram3.ftile.FtileUtils; import net.sourceforge.plantuml.activitydiagram3.ftile.MergeStrategy; import net.sourceforge.plantuml.activitydiagram3.ftile.Snake; @@ -152,10 +150,10 @@ class FtileIfLongHorizontal extends AbstractFtile { final List tiles = new ArrayList(); for (Branch branch : thens) { - tiles.add(new FtileMinWidth(branch.getFtile(), 30)); + tiles.add(new FtileMinWidthCentered(branch.getFtile(), 30)); } - final Ftile tile2 = new FtileMinWidth(branch2.getFtile(), 30); + final Ftile tile2 = new FtileMinWidthCentered(branch2.getFtile(), 30); List diamonds = new ArrayList(); List inlabelSizes = new ArrayList(); @@ -237,13 +235,6 @@ class FtileIfLongHorizontal extends AbstractFtile { return FtileUtils.addConnection(result, conns); } - static private TextBlock getSpecial(Branch branch, FontConfiguration fcTest, ISkinParam skinParam) { - if (branch.getSpecial() == null) { - return null; - } - return branch.getSpecial().getDisplay().create(fcTest, HorizontalAlignment.LEFT, skinParam); - } - class ConnectionHorizontal extends AbstractConnection { private final Rainbow color; @@ -487,7 +478,7 @@ class FtileIfLongHorizontal extends AbstractFtile { final double minX = minmax[0]; final double maxX = minmax[1]; - if (minX == Double.NaN || maxX == Double.NaN) { + if (Double.isNaN(minX) || Double.isNaN(maxX)) { return; } @@ -498,9 +489,21 @@ class FtileIfLongHorizontal extends AbstractFtile { ug.draw(s); } + private Double getLeftOut(final StringBounder stringBounder) { + final FtileGeometry dim = calculateDimension(stringBounder); + if (dim.hasPointOut()) { + return dim.getLeft(); + } + return null; + } + private double[] getMinmax(StringBounder stringBounder, double width, List allTiles, Swimlane intoSw, List allSwimlanes) { final int current = allSwimlanes.indexOf(intoSw); + final Double leftOut = getLeftOut(stringBounder); + if (leftOut == null) + return new double[] { Double.NaN, Double.NaN }; + if (current == -1) { throw new IllegalStateException(); } @@ -510,6 +513,8 @@ class FtileIfLongHorizontal extends AbstractFtile { return new double[] { Double.NaN, Double.NaN }; double minX = current != first ? 0 : width; double maxX = current != last ? width : 0; + minX = Math.min(minX, leftOut); + maxX = Math.max(maxX, leftOut); for (Ftile tmp : allTiles) { if (tmp.calculateDimension(stringBounder).hasPointOut() == false) { continue; @@ -526,8 +531,13 @@ class FtileIfLongHorizontal extends AbstractFtile { } private double[] getMinmaxSimple(StringBounder stringBounder, double width, List allTiles) { + final Double leftOut = getLeftOut(stringBounder); + if (leftOut == null) + return new double[] { Double.NaN, Double.NaN }; double minX = width / 2; double maxX = width / 2; + minX = Math.min(minX, leftOut); + maxX = Math.max(maxX, leftOut); for (Ftile tmp : allTiles) { if (tmp.calculateDimension(stringBounder).hasPointOut() == false) { continue; diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/FtileIfLongVertical.java b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/FtileIfLongVertical.java index b001bd70d..3faa9a3ab 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/FtileIfLongVertical.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/FtileIfLongVertical.java @@ -53,7 +53,7 @@ import net.sourceforge.plantuml.activitydiagram3.ftile.Connection; import net.sourceforge.plantuml.activitydiagram3.ftile.Ftile; import net.sourceforge.plantuml.activitydiagram3.ftile.FtileFactory; import net.sourceforge.plantuml.activitydiagram3.ftile.FtileGeometry; -import net.sourceforge.plantuml.activitydiagram3.ftile.FtileMinWidth; +import net.sourceforge.plantuml.activitydiagram3.ftile.FtileMinWidthCentered; import net.sourceforge.plantuml.activitydiagram3.ftile.FtileOverpassing; import net.sourceforge.plantuml.activitydiagram3.ftile.FtileUtils; import net.sourceforge.plantuml.activitydiagram3.ftile.Snake; @@ -133,10 +133,10 @@ class FtileIfLongVertical extends AbstractFtile { final List tiles = new ArrayList(); for (Branch branch : thens) { - tiles.add(new FtileMinWidth(branch.getFtile(), 30)); + tiles.add(new FtileMinWidthCentered(branch.getFtile(), 30)); } - final Ftile tile2 = new FtileMinWidth(branch2.getFtile(), 30); + final Ftile tile2 = new FtileMinWidthCentered(branch2.getFtile(), 30); List diamonds = new ArrayList(); for (Branch branch : thens) { diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/FtileSwitch.java b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/FtileSwitch.java index 14802f4fa..eb901e43a 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/FtileSwitch.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/FtileSwitch.java @@ -50,7 +50,7 @@ import net.sourceforge.plantuml.activitydiagram3.ftile.AbstractFtile; import net.sourceforge.plantuml.activitydiagram3.ftile.Ftile; import net.sourceforge.plantuml.activitydiagram3.ftile.FtileFactory; import net.sourceforge.plantuml.activitydiagram3.ftile.FtileGeometry; -import net.sourceforge.plantuml.activitydiagram3.ftile.FtileMinWidth; +import net.sourceforge.plantuml.activitydiagram3.ftile.FtileMinWidthCentered; import net.sourceforge.plantuml.activitydiagram3.ftile.Swimlane; import net.sourceforge.plantuml.activitydiagram3.ftile.vertical.FtileDiamondInside2; import net.sourceforge.plantuml.cucadiagram.Display; @@ -104,7 +104,7 @@ class FtileSwitch extends AbstractFtile { final List tiles = new ArrayList(); for (Branch branch : thens) { - tiles.add(new FtileMinWidth(branch.getFtile(), 30)); + tiles.add(new FtileMinWidthCentered(branch.getFtile(), 30)); } List inlabelSizes = new ArrayList(); diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/ParallelBuilderFork.java b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/ParallelBuilderFork.java index c8060dc6b..29415d76f 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/ParallelBuilderFork.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/ParallelBuilderFork.java @@ -50,6 +50,8 @@ import net.sourceforge.plantuml.activitydiagram3.ftile.ConnectionTranslatable; import net.sourceforge.plantuml.activitydiagram3.ftile.Ftile; import net.sourceforge.plantuml.activitydiagram3.ftile.FtileAssemblySimple; import net.sourceforge.plantuml.activitydiagram3.ftile.FtileGeometry; +import net.sourceforge.plantuml.activitydiagram3.ftile.FtileHeightFixedCentered; +import net.sourceforge.plantuml.activitydiagram3.ftile.FtileHeightFixedMarged; import net.sourceforge.plantuml.activitydiagram3.ftile.FtileUtils; import net.sourceforge.plantuml.activitydiagram3.ftile.Snake; import net.sourceforge.plantuml.activitydiagram3.ftile.Swimlane; @@ -57,6 +59,7 @@ import net.sourceforge.plantuml.activitydiagram3.ftile.vertical.FtileBlackBlock; import net.sourceforge.plantuml.cucadiagram.Display; import net.sourceforge.plantuml.graphic.Rainbow; import net.sourceforge.plantuml.graphic.StringBounder; +import net.sourceforge.plantuml.graphic.TextBlock; import net.sourceforge.plantuml.style.Style; import net.sourceforge.plantuml.ugraphic.UGraphic; import net.sourceforge.plantuml.ugraphic.UTranslate; @@ -67,28 +70,70 @@ public class ParallelBuilderFork extends AbstractParallelFtilesBuilder { private final Swimlane in; private final Swimlane out; - public ParallelBuilderFork(ISkinParam skinParam, StringBounder stringBounder, final List list, Ftile inner, - String label, Swimlane in, Swimlane out) { - super(skinParam, stringBounder, list, inner); + public ParallelBuilderFork(ISkinParam skinParam, StringBounder stringBounder, String label, Swimlane in, + Swimlane out, List all) { + super(skinParam, stringBounder, all); this.label = label; this.in = in; this.out = out; } + protected List getFoo2(List all) { + final double maxHeight = computeMaxHeight(all); + final double ymargin1 = getSuppSpace1(all, getStringBounder()); + final double ymargin2 = getSuppSpace2(all, getStringBounder()); + final List result = new ArrayList(); + for (Ftile ftile : all) { + final Ftile newFtile = computeNewFtile(ftile, maxHeight, ymargin1, ymargin2); + result.add(newFtile); + } + return result; + } + + private Ftile computeNewFtile(Ftile ftile, double maxHeight, double ymargin1, double ymargin2) { + final double spaceArroundBlackBar = 20; + final double xMargin = 14; + Ftile tmp; + tmp = FtileUtils.addHorizontalMargin(ftile, xMargin, xMargin + getSuppForIncomingArrow(ftile)); + tmp = new FtileHeightFixedCentered(tmp, maxHeight + 2 * spaceArroundBlackBar); + tmp = new FtileHeightFixedMarged(ymargin1, tmp, ymargin2); + return tmp; + } + + private double getSuppForIncomingArrow(Ftile ftile) { + final double x1 = getXSuppForDisplay(ftile, ftile.getInLinkRendering().getDisplay()); + final double x2 = getXSuppForDisplay(ftile, ftile.getOutLinkRendering().getDisplay()); + return Math.max(x1, x2); + } + + private double getXSuppForDisplay(Ftile ftile, Display label) { + final TextBlock text = getTextBlock(label); + if (text == null) { + return 0; + } + final double textWidth = text.calculateDimension(getStringBounder()).getWidth(); + final FtileGeometry ftileDim = ftile.calculateDimension(getStringBounder()); + final double pos2 = ftileDim.getLeft() + textWidth; + if (pos2 > ftileDim.getWidth()) { + return pos2 - ftileDim.getWidth(); + } + return 0; + } + @Override protected Swimlane swimlaneOutForStep2() { return out; } @Override - protected Ftile doStep1() { - Ftile result = getMiddle(); + protected Ftile doStep1(Ftile middle) { + Ftile result = middle; final List conns = new ArrayList(); final Swimlane swimlaneBlack = in; - final Ftile black = new FtileBlackBlock(skinParam(), getRose() - .getHtmlColor(skinParam(), ColorParam.activityBar), swimlaneBlack); + final Ftile black = new FtileBlackBlock(skinParam(), + getRose().getHtmlColor(skinParam(), ColorParam.activityBar), swimlaneBlack); double x = 0; - for (Ftile tmp : getList()) { + for (Ftile tmp : list99) { final Dimension2D dim = tmp.calculateDimension(getStringBounder()); final Rainbow def; if (SkinParam.USE_STYLES()) { @@ -109,8 +154,39 @@ public class ParallelBuilderFork extends AbstractParallelFtilesBuilder { return new FtileAssemblySimple(black, result); } + private double getSuppSpace1(List all, StringBounder stringBounder) { + double result = 0; + for (Ftile child : all) { + final TextBlock text = getTextBlock(child.getInLinkRendering().getDisplay()); + if (text == null) { + continue; + } + final Dimension2D dim = text.calculateDimension(stringBounder); + result = Math.max(result, dim.getHeight()); + + } + return result; + } + + private double getSuppSpace2(List all, StringBounder stringBounder) { + double result = 0; + for (Ftile child : all) { + final TextBlock text = getTextBlock(child.getOutLinkRendering().getDisplay()); + if (text == null) { + continue; + } + final Dimension2D dim = text.calculateDimension(stringBounder); + result = Math.max(result, dim.getHeight()); + } + return result; + } + + private double getJustBeforeBar2(Ftile middle, StringBounder stringBounder) { + return barHeight + getHeightOfMiddle(middle); + } + @Override - protected Ftile doStep2(Ftile result) { + protected Ftile doStep2(Ftile middle, Ftile result) { final Swimlane swimlaneBlack = out; final Ftile out = new FtileBlackBlock(skinParam(), getRose().getHtmlColor(skinParam(), ColorParam.activityBar), swimlaneBlack); @@ -122,8 +198,7 @@ public class ParallelBuilderFork extends AbstractParallelFtilesBuilder { result = new FtileAssemblySimple(result, out); final List conns = new ArrayList(); double x = 0; - for (Ftile tmp : getList()) { - final UTranslate translate0 = UTranslate.dy(barHeight); + for (Ftile tmp : list99) { final Dimension2D dim = tmp.calculateDimension(getStringBounder()); final Rainbow def; if (SkinParam.USE_STYLES()) { @@ -133,7 +208,7 @@ public class ParallelBuilderFork extends AbstractParallelFtilesBuilder { def = Rainbow.build(skinParam()); } final Rainbow rainbow = tmp.getOutLinkRendering().getRainbow(def); - conns.add(new ConnectionOut(translate0, tmp, out, x, rainbow, getHeightOfMiddle())); + conns.add(new ConnectionOut(tmp, out, x, rainbow, getJustBeforeBar2(middle, getStringBounder()))); x += dim.getWidth(); } result = FtileUtils.addConnection(result, conns); @@ -148,28 +223,30 @@ public class ParallelBuilderFork extends AbstractParallelFtilesBuilder { public ConnectionIn(Ftile ftile1, Ftile ftile2, double x, Rainbow arrowColor) { super(ftile1, ftile2); - label = ftile2.getInLinkRendering().getDisplay(); + this.label = ftile2.getInLinkRendering().getDisplay(); this.x = x; this.arrowColor = arrowColor; } public void drawU(UGraphic ug) { ug = ug.apply(UTranslate.dx(x)); - final FtileGeometry geo = getFtile2().calculateDimension(getStringBounder()); + final FtileGeometry geo2 = getFtile2().calculateDimension(getStringBounder()); final Snake snake = new Snake(arrowHorizontalAlignment(), arrowColor, Arrows.asToDown()); if (Display.isNull(label) == false) { snake.setLabel(getTextBlock(label)); } - snake.addPoint(geo.getLeft(), 0); - snake.addPoint(geo.getLeft(), geo.getInY()); + final Point2D p1 = new Point2D.Double(geo2.getLeft(), 0); + final Point2D p2 = new Point2D.Double(geo2.getLeft(), geo2.getInY()); + snake.addPoint(p1); + snake.addPoint(p2); ug.draw(snake); } public void drawTranslate(UGraphic ug, UTranslate translate1, UTranslate translate2) { ug = ug.apply(UTranslate.dx(x)); - final FtileGeometry geo = getFtile2().calculateDimension(getStringBounder()); - final Point2D p1 = new Point2D.Double(geo.getLeft(), 0); - final Point2D p2 = new Point2D.Double(geo.getLeft(), geo.getInY()); + final FtileGeometry geo2 = getFtile2().calculateDimension(getStringBounder()); + final Point2D p1 = new Point2D.Double(geo2.getLeft(), 0); + final Point2D p2 = new Point2D.Double(geo2.getLeft(), geo2.getInY()); final Snake snake = new Snake(arrowHorizontalAlignment(), arrowColor, Arrows.asToDown()); if (Display.isNull(label) == false) { @@ -191,32 +268,29 @@ public class ParallelBuilderFork extends AbstractParallelFtilesBuilder { private final double x; private final Rainbow arrowColor; - private final double height; private final Display label; - private final UTranslate translate0; + private final double justBeforeBar2; - public ConnectionOut(UTranslate translate0, Ftile ftile1, Ftile ftile2, double x, Rainbow arrowColor, - double height) { + public ConnectionOut(Ftile ftile1, Ftile ftile2, double x, Rainbow arrowColor, double justBeforeBar2) { super(ftile1, ftile2); - this.translate0 = translate0; + this.justBeforeBar2 = justBeforeBar2; this.label = ftile1.getOutLinkRendering().getDisplay(); this.x = x; this.arrowColor = arrowColor; - this.height = height; } public void drawU(UGraphic ug) { ug = ug.apply(UTranslate.dx(x)); - final FtileGeometry geo = getFtile1().calculateDimension(getStringBounder()); - if (geo.hasPointOut() == false) { + final FtileGeometry geo1 = getFtile1().calculateDimension(getStringBounder()); + if (geo1.hasPointOut() == false) { return; } final Snake snake = new Snake(arrowHorizontalAlignment(), arrowColor, Arrows.asToDown()); if (Display.isNull(label) == false) { snake.setLabel(getTextBlock(label)); } - final Point2D p1 = translate0.getTranslated(new Point2D.Double(geo.getLeft(), geo.getOutY())); - final Point2D p2 = translate0.getTranslated(new Point2D.Double(geo.getLeft(), height)); + final Point2D p1 = new Point2D.Double(geo1.getLeft(), barHeight + geo1.getOutY()); + final Point2D p2 = new Point2D.Double(geo1.getLeft(), justBeforeBar2); snake.addPoint(p1); snake.addPoint(p2); ug.draw(snake); @@ -228,8 +302,8 @@ public class ParallelBuilderFork extends AbstractParallelFtilesBuilder { if (geo.hasPointOut() == false) { return; } - final Point2D p1 = translate0.getTranslated(new Point2D.Double(geo.getLeft(), geo.getOutY())); - final Point2D p2 = translate0.getTranslated(new Point2D.Double(geo.getLeft(), height)); + final Point2D p1 = new Point2D.Double(geo.getLeft(), barHeight + geo.getOutY()); + final Point2D p2 = new Point2D.Double(geo.getLeft(), justBeforeBar2); final Snake snake = new Snake(arrowHorizontalAlignment(), arrowColor, Arrows.asToDown()); if (Display.isNull(label) == false) { diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/ParallelBuilderMerge.java b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/ParallelBuilderMerge.java index e76311e94..eba09e2bf 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/ParallelBuilderMerge.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/ParallelBuilderMerge.java @@ -65,19 +65,19 @@ import net.sourceforge.plantuml.ugraphic.color.HColor; public class ParallelBuilderMerge extends AbstractParallelFtilesBuilder { - public ParallelBuilderMerge(ISkinParam skinParam, StringBounder stringBounder, final List list, Ftile inner) { - super(skinParam, stringBounder, list, inner); + public ParallelBuilderMerge(ISkinParam skinParam, StringBounder stringBounder, List all) { + super(skinParam, stringBounder, all); } @Override - protected Ftile doStep1() { - Ftile result = getMiddle(); + protected Ftile doStep1(Ftile inner) { + Ftile result = inner; final List conns = new ArrayList(); final HColor colorBar = getRose().getHtmlColor(skinParam(), ColorParam.activityBar); - final Ftile black = new FtileBlackBlock(skinParam(), colorBar, getList().get(0).getSwimlaneIn()); + final Ftile black = new FtileBlackBlock(skinParam(), colorBar, list99.get(0).getSwimlaneIn()); double x = 0; - for (Ftile tmp : getList()) { + for (Ftile tmp : list99) { final Dimension2D dim = tmp.calculateDimension(getStringBounder()); final Rainbow def; if (SkinParam.USE_STYLES()) { @@ -99,7 +99,7 @@ public class ParallelBuilderMerge extends AbstractParallelFtilesBuilder { } @Override - protected Ftile doStep2(Ftile result) { + protected Ftile doStep2(Ftile inner, Ftile result) { final HColor borderColor = getRose().getHtmlColor(skinParam(), ColorParam.activityDiamondBorder); final HColor backColor = getRose().getHtmlColor(skinParam(), ColorParam.activityDiamondBackground); final Ftile out = new FtileDiamond(skinParam(), backColor, borderColor, swimlaneOutForStep2()); @@ -108,7 +108,7 @@ public class ParallelBuilderMerge extends AbstractParallelFtilesBuilder { final UTranslate diamondTranslate = result.getTranslateFor(out, getStringBounder()); int i = 0; double x = 0; - for (Ftile tmp : getList()) { + for (Ftile tmp : list99) { final Dimension2D dim = tmp.calculateDimension(getStringBounder()); final UTranslate translate0 = new UTranslate(x, barHeight); final Rainbow def; diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/ParallelBuilderSplit.java b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/ParallelBuilderSplit.java index cbf0530b1..221b37bf5 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/ParallelBuilderSplit.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/ParallelBuilderSplit.java @@ -65,8 +65,8 @@ import net.sourceforge.plantuml.ugraphic.color.HColor; public class ParallelBuilderSplit extends AbstractParallelFtilesBuilder { - public ParallelBuilderSplit(ISkinParam skinParam, StringBounder stringBounder, final List list, Ftile inner) { - super(skinParam, stringBounder, list, inner); + public ParallelBuilderSplit(ISkinParam skinParam, StringBounder stringBounder, List all) { + super(skinParam, stringBounder, all); } @Override @@ -75,8 +75,8 @@ public class ParallelBuilderSplit extends AbstractParallelFtilesBuilder { } @Override - protected Ftile doStep1() { - Ftile result = getMiddle(); + protected Ftile doStep1(Ftile inner) { + Ftile result = inner; final List conns = new ArrayList(); final Rainbow thinColor; if (SkinParam.USE_STYLES()) { @@ -85,11 +85,11 @@ public class ParallelBuilderSplit extends AbstractParallelFtilesBuilder { } else { thinColor = result.getInLinkRendering().getRainbow(Rainbow.build(skinParam())); } - final Ftile thin = new FtileThinSplit(skinParam(), getThin1Color(thinColor), getList().get(0).getSwimlaneIn()); + final Ftile thin = new FtileThinSplit(skinParam(), getThin1Color(thinColor), list99.get(0).getSwimlaneIn()); double x = 0; double first = 0; double last = 0; - for (Ftile tmp : getList()) { + for (Ftile tmp : list99) { final FtileGeometry dim = tmp.calculateDimension(getStringBounder()); if (first == 0) { first = x + dim.getLeft(); @@ -123,7 +123,7 @@ public class ParallelBuilderSplit extends AbstractParallelFtilesBuilder { } private HColor getThin1Color(final Rainbow thinColor) { - for (Ftile tmp : getList()) { + for (Ftile tmp : list99) { final Rainbow rainbow; final LinkRendering inLinkRendering = tmp.getInLinkRendering(); if (SkinParam.USE_STYLES()) { @@ -140,7 +140,7 @@ public class ParallelBuilderSplit extends AbstractParallelFtilesBuilder { } private boolean hasOut() { - for (Ftile tmp : getList()) { + for (Ftile tmp : list99) { final boolean hasOutTmp = tmp.calculateDimension(getStringBounder()).hasPointOut(); if (hasOutTmp) { return true; @@ -150,7 +150,7 @@ public class ParallelBuilderSplit extends AbstractParallelFtilesBuilder { } @Override - protected Ftile doStep2(Ftile result) { + protected Ftile doStep2(Ftile inner, Ftile result) { final FtileGeometry geom = result.calculateDimension(getStringBounder()); if (hasOut() == false) { @@ -172,7 +172,7 @@ public class ParallelBuilderSplit extends AbstractParallelFtilesBuilder { double x = 0; double first = 0; double last = 0; - for (Ftile tmp : getList()) { + for (Ftile tmp : list99) { final UTranslate translate0 = UTranslate.dy(1.5); final FtileGeometry dim = tmp.calculateDimension(getStringBounder()); if (dim.hasPointOut()) { @@ -191,7 +191,7 @@ public class ParallelBuilderSplit extends AbstractParallelFtilesBuilder { rainbow = outLinkRendering.getRainbow(Rainbow.build(skinParam())); } - conns.add(new ConnectionOut(translate0, tmp, out, x, rainbow, getHeightOfMiddle())); + conns.add(new ConnectionOut(translate0, tmp, out, x, rainbow, getHeightOfMiddle(inner))); x += dim.getWidth(); } if (last < geom.getLeft()) { diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/cond/ConditionalBuilder.java b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/cond/ConditionalBuilder.java index e91e7c1db..7c3beb498 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/cond/ConditionalBuilder.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vcompact/cond/ConditionalBuilder.java @@ -46,7 +46,7 @@ import net.sourceforge.plantuml.activitydiagram3.ftile.Diamond; import net.sourceforge.plantuml.activitydiagram3.ftile.Ftile; import net.sourceforge.plantuml.activitydiagram3.ftile.FtileEmpty; import net.sourceforge.plantuml.activitydiagram3.ftile.FtileFactory; -import net.sourceforge.plantuml.activitydiagram3.ftile.FtileMinWidth; +import net.sourceforge.plantuml.activitydiagram3.ftile.FtileMinWidthCentered; import net.sourceforge.plantuml.activitydiagram3.ftile.FtileUtils; import net.sourceforge.plantuml.activitydiagram3.ftile.FtileWithUrl; import net.sourceforge.plantuml.activitydiagram3.ftile.Swimlane; @@ -132,8 +132,8 @@ public class ConditionalBuilder { this.stringBounder = stringBounder; this.url = url; - this.tile1 = new FtileMinWidth(branch1.getFtile(), 30); - this.tile2 = new FtileMinWidth(branch2.getFtile(), 30); + this.tile1 = new FtileMinWidthCentered(branch1.getFtile(), 30); + this.tile2 = new FtileMinWidthCentered(branch2.getFtile(), 30); } @@ -166,8 +166,8 @@ public class ConditionalBuilder { } private Ftile createDown(Branch branch1, Branch branch2) { - final Ftile tile1 = new FtileMinWidth(branch1.getFtile(), 30); - final Ftile tile2 = new FtileMinWidth(branch2.getFtile(), 30); + final Ftile tile1 = new FtileMinWidthCentered(branch1.getFtile(), 30); + final Ftile tile2 = new FtileMinWidthCentered(branch2.getFtile(), 30); final TextBlock tb1 = getLabelPositive(branch1); final TextBlock tb2 = getLabelPositive(branch2); final Ftile diamond1 = getDiamond1(false, tb1, tb2); diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vertical/FtileBox.java b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vertical/FtileBox.java index 4242a9658..ca00434b9 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/ftile/vertical/FtileBox.java +++ b/src/net/sourceforge/plantuml/activitydiagram3/ftile/vertical/FtileBox.java @@ -81,11 +81,10 @@ import net.sourceforge.plantuml.ugraphic.color.HColorNone; public class FtileBox extends AbstractFtile { - private double padding() { - return padding; - } - - private double padding = 10; + private double padding1 = 10; + private double padding2 = 10; + private double paddingTop = 10; + private double paddingBottom = 10; private final TextBlock tb; private double roundCorner = 25; private final double shadowing; @@ -130,12 +129,12 @@ public class FtileBox extends AbstractFtile { class MyStencil implements Stencil { public double getStartingX(StringBounder stringBounder, double y) { - return -padding(); + return -padding1; } public double getEndingX(StringBounder stringBounder, double y) { final Dimension2D dim = calculateDimension(stringBounder); - return dim.getWidth() - padding(); + return dim.getWidth() - padding2; } } @@ -199,7 +198,10 @@ public class FtileBox extends AbstractFtile { this.backColor = style.value(PName.BackGroundColor).asColor(getIHtmlColorSet()); fc = style.getFontConfiguration(getIHtmlColorSet()); horizontalAlignment = style.getHorizontalAlignment(); - this.padding = style.getPadding().asDouble(); + this.padding1 = style.getPadding().getLeft(); + this.padding2 = style.getPadding().getRight(); + this.paddingTop = style.getPadding().getTop(); + this.paddingBottom = style.getPadding().getBottom(); this.roundCorner = style.value(PName.RoundCorner).asDouble(); this.shadowing = style.value(PName.Shadowing).asDouble(); wrapWidth = style.wrapWidth(); @@ -251,20 +253,20 @@ public class FtileBox extends AbstractFtile { rect.drawU(ug); if (horizontalAlignment == HorizontalAlignment.LEFT) { - tb.drawU(ug.apply(new UTranslate(padding(), padding()))); + tb.drawU(ug.apply(new UTranslate(padding1, paddingTop))); } else if (horizontalAlignment == HorizontalAlignment.RIGHT) { final Dimension2D dimTb = tb.calculateDimension(ug.getStringBounder()); - tb.drawU(ug.apply(new UTranslate(dimTotal.getWidth() - dimTb.getWidth() - padding(), padding()))); + tb.drawU(ug.apply(new UTranslate(dimTotal.getWidth() - dimTb.getWidth() - padding2, paddingBottom))); } else if (horizontalAlignment == HorizontalAlignment.CENTER) { final Dimension2D dimTb = tb.calculateDimension(ug.getStringBounder()); - tb.drawU(ug.apply(new UTranslate((dimTotal.getWidth() - dimTb.getWidth()) / 2, padding()))); + tb.drawU(ug.apply(new UTranslate((dimTotal.getWidth() - dimTb.getWidth()) / 2, paddingBottom))); } } @Override protected FtileGeometry calculateDimensionFtile(StringBounder stringBounder) { Dimension2D dim = tb.calculateDimension(stringBounder); - dim = Dimension2DDouble.delta(dim, 2 * padding(), 2 * padding()); + dim = Dimension2DDouble.delta(dim, padding1 + padding2, paddingBottom + paddingTop); dim = Dimension2DDouble.atLeast(dim, minimumWidth, 0); return new FtileGeometry(dim, dim.getWidth() / 2, 0, dim.getHeight()); } diff --git a/src/net/sourceforge/plantuml/bpm/BpmDiagram.java b/src/net/sourceforge/plantuml/bpm/BpmDiagram.java index 69a727524..7ecf1d131 100644 --- a/src/net/sourceforge/plantuml/bpm/BpmDiagram.java +++ b/src/net/sourceforge/plantuml/bpm/BpmDiagram.java @@ -49,6 +49,7 @@ import net.sourceforge.plantuml.command.CommandExecutionResult; import net.sourceforge.plantuml.core.DiagramDescription; import net.sourceforge.plantuml.core.ImageData; import net.sourceforge.plantuml.graphic.UDrawable; +import net.sourceforge.plantuml.style.ClockwiseTopRightBottomLeft; import net.sourceforge.plantuml.ugraphic.ImageBuilder; public class BpmDiagram extends UmlDiagram { @@ -82,10 +83,17 @@ public class BpmDiagram extends UmlDiagram { protected ImageData exportDiagramInternal(OutputStream os, int index, FileFormatOption fileFormatOption) throws IOException { final double dpiFactor = 1; - final double margin = 10; - final ImageBuilder imageBuilder = new ImageBuilder(getSkinParam(), dpiFactor, - fileFormatOption.isWithMetadata() ? getMetadata() : null, getWarningOrError(), margin, margin, - getAnimation()); + final int margin1; + final int margin2; + if (SkinParam.USE_STYLES()) { + margin1 = SkinParam.zeroMargin(10); + margin2 = SkinParam.zeroMargin(10); + } else { + margin1 = 10; + margin2 = 10; + } + final ImageBuilder imageBuilder = ImageBuilder.buildD(getSkinParam(), ClockwiseTopRightBottomLeft.margin1margin2((double) margin1, (double) margin2), getAnimation(), fileFormatOption.isWithMetadata() ? getMetadata() : null, + getWarningOrError(), dpiFactor); imageBuilder.setUDrawable(getUDrawable()); return imageBuilder.writeImageTOBEMOVED(fileFormatOption, seed(), os); diff --git a/src/net/sourceforge/plantuml/braille/UGraphicBraille.java b/src/net/sourceforge/plantuml/braille/UGraphicBraille.java index d7d72db46..43521810b 100644 --- a/src/net/sourceforge/plantuml/braille/UGraphicBraille.java +++ b/src/net/sourceforge/plantuml/braille/UGraphicBraille.java @@ -128,8 +128,8 @@ public class UGraphicBraille extends AbstractUGraphic implements Cl } public void writeImageTOBEMOVED(OutputStream os, String metadata, int dpi) throws IOException { - final ImageBuilder imageBuilder = new ImageBuilder(new ColorMapperIdentity(), 1.0, HColorUtils.WHITE, - metadata, null, 0, 0, null, false); + final ImageBuilder imageBuilder = ImageBuilder.buildA(new ColorMapperIdentity(), + false, null, metadata, null, 1.0, HColorUtils.WHITE); imageBuilder.setUDrawable(new BrailleDrawer(getGraphicObject())); imageBuilder.writeImageTOBEMOVED(new FileFormatOption(FileFormat.PNG), 42, os); diff --git a/src/net/sourceforge/plantuml/classdiagram/ClassDiagram.java b/src/net/sourceforge/plantuml/classdiagram/ClassDiagram.java index 7577250f6..6270f9575 100644 --- a/src/net/sourceforge/plantuml/classdiagram/ClassDiagram.java +++ b/src/net/sourceforge/plantuml/classdiagram/ClassDiagram.java @@ -40,6 +40,7 @@ import java.io.OutputStream; import net.sourceforge.plantuml.FileFormatOption; import net.sourceforge.plantuml.ISkinSimple; +import net.sourceforge.plantuml.SkinParam; import net.sourceforge.plantuml.UmlDiagramType; import net.sourceforge.plantuml.core.ImageData; import net.sourceforge.plantuml.creole.CreoleMode; @@ -55,6 +56,7 @@ import net.sourceforge.plantuml.cucadiagram.Link; import net.sourceforge.plantuml.graphic.TextBlock; import net.sourceforge.plantuml.graphic.USymbol; import net.sourceforge.plantuml.objectdiagram.AbstractClassOrObjectDiagram; +import net.sourceforge.plantuml.style.ClockwiseTopRightBottomLeft; import net.sourceforge.plantuml.svek.image.EntityImageClass; import net.sourceforge.plantuml.ugraphic.ImageBuilder; @@ -129,7 +131,8 @@ public class ClassDiagram extends AbstractClassOrObjectDiagram { return createEntityWithNamespace1972(idNewLong, code, display, type, symbol); } - private ILeaf createEntityWithNamespace1972(Ident id, Code fullyCode, Display display, LeafType type, USymbol symbol) { + private ILeaf createEntityWithNamespace1972(Ident id, Code fullyCode, Display display, LeafType type, + USymbol symbol) { if (this.V1972()) throw new UnsupportedOperationException(); checkNotNull(id); @@ -200,7 +203,17 @@ public class ClassDiagram extends AbstractClassOrObjectDiagram { final RowLayout rawLayout = getRawLayout(i); fullLayout.addRowLayout(rawLayout); } - final ImageBuilder imageBuilder = new ImageBuilder(getSkinParam(), 1, null, null, 0, 10, null); + final int margin1; + final int margin2; + if (SkinParam.USE_STYLES()) { + margin1 = SkinParam.zeroMargin(0); + margin2 = SkinParam.zeroMargin(10); + } else { + margin1 = 0; + margin2 = 10; + } + final ImageBuilder imageBuilder = ImageBuilder.buildD(getSkinParam(), ClockwiseTopRightBottomLeft.margin1margin2((double) margin1, (double) margin2), null, null, + null, (double) 1); imageBuilder.setUDrawable(fullLayout); return imageBuilder.writeImageTOBEMOVED(fileFormatOption, seed(), os); } diff --git a/src/net/sourceforge/plantuml/classdiagram/command/CommandCreateClassMultilines.java b/src/net/sourceforge/plantuml/classdiagram/command/CommandCreateClassMultilines.java index 7115a90ad..f2dd9aca2 100644 --- a/src/net/sourceforge/plantuml/classdiagram/command/CommandCreateClassMultilines.java +++ b/src/net/sourceforge/plantuml/classdiagram/command/CommandCreateClassMultilines.java @@ -144,7 +144,7 @@ public class CommandCreateClassMultilines extends CommandMultilines2 if (symbol == null) { type = LeafType.DESCRIPTION; usymbol = diagram.getSkinParam().getActorStyle().getUSymbol(); + } else if (symbol.equalsIgnoreCase("port")) { + type = LeafType.PORT; + usymbol = null; } else if (symbol.equalsIgnoreCase("usecase")) { type = LeafType.USECASE; usymbol = null; diff --git a/src/net/sourceforge/plantuml/classdiagram/command/CommandLinkClass.java b/src/net/sourceforge/plantuml/classdiagram/command/CommandLinkClass.java index 6d630779c..0f8db89ad 100644 --- a/src/net/sourceforge/plantuml/classdiagram/command/CommandLinkClass.java +++ b/src/net/sourceforge/plantuml/classdiagram/command/CommandLinkClass.java @@ -30,6 +30,7 @@ * * * Original Author: Arnaud Roques + * Contribution : Hisashi Miyashita * * */ @@ -90,14 +91,16 @@ final public class CommandLinkClass extends SingleLineCommand2*+^\\{]|\\|[>\\]]|o\\{|\\|\\{|o\\||\\|\\|)?")), // + new RegexLeaf("ARROW_HEAD2", + "([ox][%s]+|:\\>\\>?|[(#\\]>*+^\\{]|[\\|\\:]\\|\\>|\\|[>\\]]|o\\{|\\|\\{|o\\||\\|\\|)?")), // RegexLeaf.spaceZeroOrMore(), new RegexOptional(new RegexLeaf("SECOND_LABEL", "[%g]([^%g]+)[%g]")), // RegexLeaf.spaceZeroOrMore(), // new RegexOr( // @@ -567,6 +570,12 @@ final public class CommandLinkClass extends SingleLineCommand2".equals(s)) { return LinkDecor.EXTENDS; } + if (":|>".equals(s)) { + return LinkDecor.DEFINEDBY; + } + if ("||>".equals(s)) { + return LinkDecor.REDEFINES; + } if (">".equals(s)) { return LinkDecor.ARROW; } diff --git a/src/net/sourceforge/plantuml/code/ArobaseStringCompressor.java b/src/net/sourceforge/plantuml/code/ArobaseStringCompressor.java index ee80186ed..63a689283 100644 --- a/src/net/sourceforge/plantuml/code/ArobaseStringCompressor.java +++ b/src/net/sourceforge/plantuml/code/ArobaseStringCompressor.java @@ -88,7 +88,7 @@ public class ArobaseStringCompressor implements StringCompressor { return ""; } - public String decompress(String s) throws IOException { + public String decompress(String s) { String result = clean(s); if (result.startsWith("@start")) { return result; diff --git a/src/net/sourceforge/plantuml/code/ArobaseStringCompressor2.java b/src/net/sourceforge/plantuml/code/ArobaseStringCompressor2.java index ba7fc5485..958fc7e2f 100644 --- a/src/net/sourceforge/plantuml/code/ArobaseStringCompressor2.java +++ b/src/net/sourceforge/plantuml/code/ArobaseStringCompressor2.java @@ -35,17 +35,15 @@ */ package net.sourceforge.plantuml.code; -import java.io.IOException; - import net.sourceforge.plantuml.StringUtils; public class ArobaseStringCompressor2 implements StringCompressor { - public String compress(String data) throws IOException { + public String compress(String data) { return clean2(data); } - public String decompress(String s) throws IOException { + public String decompress(String s) { return clean2(s); } diff --git a/src/net/sourceforge/plantuml/activitydiagram3/ftile/ISwimlanesA.java b/src/net/sourceforge/plantuml/code/ByteArray.java similarity index 60% rename from src/net/sourceforge/plantuml/activitydiagram3/ftile/ISwimlanesA.java rename to src/net/sourceforge/plantuml/code/ByteArray.java index eb58f1e82..e03c34c0e 100644 --- a/src/net/sourceforge/plantuml/activitydiagram3/ftile/ISwimlanesA.java +++ b/src/net/sourceforge/plantuml/code/ByteArray.java @@ -33,30 +33,39 @@ * * */ -package net.sourceforge.plantuml.activitydiagram3.ftile; +package net.sourceforge.plantuml.code; -import net.sourceforge.plantuml.activitydiagram3.Instruction; -import net.sourceforge.plantuml.activitydiagram3.LinkRendering; -import net.sourceforge.plantuml.cucadiagram.Display; -import net.sourceforge.plantuml.graphic.StringBounder; -import net.sourceforge.plantuml.graphic.TextBlock; -import net.sourceforge.plantuml.style.Styleable; -import net.sourceforge.plantuml.ugraphic.color.HColor; +import java.io.IOException; +import java.io.UnsupportedEncodingException; -public interface ISwimlanesA extends TextBlock, Styleable { +public class ByteArray { - public void computeSize(StringBounder stringBounder); + private final byte data[]; + private final int length; - public void swimlane(String name, HColor color, Display label); + private ByteArray(byte data[], int length) { + this.data = data; + this.length = length; + } - public void setCurrent(Instruction ins); + public static ByteArray from(byte[] input) { + return new ByteArray(input, input.length); + } - public Instruction getCurrent(); + public String toUFT8String() throws UnsupportedEncodingException { + return new String(data, 0, length, "UTF-8"); + } - public LinkRendering nextLinkRenderer(); + public String toUPF9String() throws IOException { + return Upf9.decodeString(data, length); + } - public Swimlane getCurrentSwimlane(); + public int getByteAt(int i) { + return data[i]; + } - public void setNextLinkRenderer(LinkRendering link); + public int length() { + return length; + } -} +} \ No newline at end of file diff --git a/src/net/sourceforge/plantuml/code/Compression.java b/src/net/sourceforge/plantuml/code/Compression.java index 2db22c433..818ed00df 100644 --- a/src/net/sourceforge/plantuml/code/Compression.java +++ b/src/net/sourceforge/plantuml/code/Compression.java @@ -35,8 +35,6 @@ */ package net.sourceforge.plantuml.code; -import java.io.IOException; - public interface Compression { /** @@ -47,11 +45,11 @@ public interface Compression { byte[] compress(final byte[] in); /** - * Grows the given in array with length len - * compressed with the shrink method. + * Grows the given in array with length len compressed + * with the shrink method. * * @return a newly created array with the expanded data. */ - byte[] decompress(byte[] in) throws IOException; + ByteArray decompress(byte[] in) throws NoPlantumlCompressionException; } \ No newline at end of file diff --git a/src/net/sourceforge/plantuml/code/CompressionBrotli.java b/src/net/sourceforge/plantuml/code/CompressionBrotli.java index f2e082b3b..c37708984 100644 --- a/src/net/sourceforge/plantuml/code/CompressionBrotli.java +++ b/src/net/sourceforge/plantuml/code/CompressionBrotli.java @@ -48,13 +48,18 @@ public class CompressionBrotli implements Compression { throw new UnsupportedOperationException(); } - public byte[] decompress(byte[] in) throws IOException { - final BrotliInputStream brotli = new BrotliInputStream(new ByteArrayInputStream(in)); - final ByteArrayOutputStream result = new ByteArrayOutputStream(); - FileUtils.copyToStream(brotli, result); - brotli.close(); - result.close(); - return result.toByteArray(); + public ByteArray decompress(byte[] in) throws NoPlantumlCompressionException { + try { + final BrotliInputStream brotli = new BrotliInputStream(new ByteArrayInputStream(in)); + final ByteArrayOutputStream result = new ByteArrayOutputStream(); + FileUtils.copyToStream(brotli, result); + brotli.close(); + result.close(); + return ByteArray.from(result.toByteArray()); + } catch (IOException e) { + e.printStackTrace(); + throw new NoPlantumlCompressionException(e); + } } } diff --git a/src/net/sourceforge/plantuml/code/CompressionHuffman.java b/src/net/sourceforge/plantuml/code/CompressionHuffman.java index c3156491a..4b17ae5a4 100644 --- a/src/net/sourceforge/plantuml/code/CompressionHuffman.java +++ b/src/net/sourceforge/plantuml/code/CompressionHuffman.java @@ -59,19 +59,24 @@ public class CompressionHuffman implements Compression { } } - public byte[] decompress(byte[] in) throws IOException { - final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + public ByteArray decompress(byte[] in) throws NoPlantumlCompressionException { + try { + final ByteArrayOutputStream baos = new ByteArrayOutputStream(); - final ByteArrayInputStream bais = new ByteArrayInputStream(in); - final InflaterInputStream gz = new InflaterInputStream(bais); - int read; - while ((read = gz.read()) != -1) { - baos.write(read); + final ByteArrayInputStream bais = new ByteArrayInputStream(in); + final InflaterInputStream gz = new InflaterInputStream(bais); + int read; + while ((read = gz.read()) != -1) { + baos.write(read); + } + gz.close(); + bais.close(); + baos.close(); + return ByteArray.from(baos.toByteArray()); + } catch (IOException e) { + System.err.println("Not Huffman"); + throw new NoPlantumlCompressionException(e); } - gz.close(); - bais.close(); - baos.close(); - return baos.toByteArray(); } } diff --git a/src/net/sourceforge/plantuml/code/CompressionNone.java b/src/net/sourceforge/plantuml/code/CompressionNone.java index 72db0c856..2691b40e8 100644 --- a/src/net/sourceforge/plantuml/code/CompressionNone.java +++ b/src/net/sourceforge/plantuml/code/CompressionNone.java @@ -41,8 +41,8 @@ public class CompressionNone implements Compression { return in; } - public byte[] decompress(byte[] in) { - return in; + public ByteArray decompress(byte[] in) { + return ByteArray.from(in); } } diff --git a/src/net/sourceforge/plantuml/code/CompressionZlib.java b/src/net/sourceforge/plantuml/code/CompressionZlib.java index f2f074f67..445d52be1 100644 --- a/src/net/sourceforge/plantuml/code/CompressionZlib.java +++ b/src/net/sourceforge/plantuml/code/CompressionZlib.java @@ -53,14 +53,14 @@ public class CompressionZlib implements Compression { return null; } int len = in.length * 2; - if (len < 100) { - len = 100; + if (len < 1000) { + len = 1000; } byte[] result = null; - while (result == null) { - result = tryCompress(in, len); - len *= 2; - } +// while (result == null) { + result = tryCompress(in, len); +// len *= 2; +// } return result; } @@ -79,20 +79,33 @@ public class CompressionZlib implements Compression { return result; } - public byte[] decompress(byte[] in) throws IOException { + public ByteArray decompress(byte[] in) throws NoPlantumlCompressionException { + try { + final byte in2[] = new byte[in.length + 256]; + System.arraycopy(in, 0, in2, 0, in.length); +// for (int i = 0; i < in.length; i++) { +// in2[i] = in[i]; +// } - final byte in2[] = new byte[in.length + 256]; - for (int i = 0; i < in.length; i++) { - in2[i] = in[i]; - } - - int len = in.length * 5; - byte[] result = null; - while (result == null) { + int len = 100000; + byte[] result = null; result = tryDecompress(in2, len); - len *= 2; + if (result == null) { + throw new NoPlantumlCompressionException("Too big?"); + + } +// int len = in.length * 5; +// byte[] result = null; +// while (result == null) { +// result = tryDecompress(in2, len); +// len *= 2; +// } + return ByteArray.from(result); + } catch (IOException e) { + e.printStackTrace(); + throw new NoPlantumlCompressionException(e); } - return result; + } private byte[] tryDecompress(byte[] in, final int len) throws IOException { @@ -120,9 +133,10 @@ public class CompressionZlib implements Compression { private byte[] copyArray(final byte[] data, final int len) { final byte[] result = new byte[len]; - for (int i = 0; i < result.length; i++) { - result[i] = data[i]; - } + System.arraycopy(data, 0, result, 0, len); +// for (int i = 0; i < result.length; i++) { +// result[i] = data[i]; +// } return result; } diff --git a/src/net/sourceforge/plantuml/code/CompressionZlibPure.java b/src/net/sourceforge/plantuml/code/CompressionZlibPure.java new file mode 100644 index 000000000..03fa66015 --- /dev/null +++ b/src/net/sourceforge/plantuml/code/CompressionZlibPure.java @@ -0,0 +1,88 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2020, Arnaud Roques + * + * Project Info: http://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * http://plantuml.com/patreon (only 1$ per month!) + * http://plantuml.com/paypal + * + * This file is part of PlantUML. + * + * PlantUML is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * PlantUML distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + * + */ +package net.sourceforge.plantuml.code; + +import java.io.ByteArrayInputStream; +import java.util.zip.Deflater; + +import net.sourceforge.plantuml.code.deflate.ByteBitInputStream; +import net.sourceforge.plantuml.code.deflate.Decompressor; + +public class CompressionZlibPure implements Compression { + + private static boolean USE_ZOPFLI = false; + private static final int COMPRESSION_LEVEL = 9; + + public byte[] compress(byte[] in) { + if (USE_ZOPFLI) { + return new CompressionZopfliZlib().compress(in); + } + if (in.length == 0) { + return null; + } + int len = in.length * 2; + if (len < 1000) { + len = 1000; + } + // Compress the bytes + final Deflater compresser = new Deflater(COMPRESSION_LEVEL, true); + compresser.setInput(in); + compresser.finish(); + + final byte[] output = new byte[len]; + final int compressedDataLength = compresser.deflate(output); + if (compresser.finished() == false) { + return null; + } + return copyArray(output, compressedDataLength); + } + + public ByteArray decompress(byte[] in) throws NoPlantumlCompressionException { + final ByteBitInputStream in2 = new ByteBitInputStream(new ByteArrayInputStream(in)); + try { + return ByteArray.from(Decompressor.decompress(in2)); + } catch (Exception e) { + throw new NoPlantumlCompressionException(e); + } + } + + private byte[] copyArray(final byte[] data, final int len) { + final byte[] result = new byte[len]; + System.arraycopy(data, 0, result, 0, len); + return result; + } + +} diff --git a/src/net/sourceforge/plantuml/code/CompressionZopfliZlib.java b/src/net/sourceforge/plantuml/code/CompressionZopfliZlib.java index ab6dc598d..b38647f14 100644 --- a/src/net/sourceforge/plantuml/code/CompressionZopfliZlib.java +++ b/src/net/sourceforge/plantuml/code/CompressionZopfliZlib.java @@ -35,8 +35,6 @@ */ package net.sourceforge.plantuml.code; -import java.io.IOException; - import net.sourceforge.plantuml.zopfli.Options; import net.sourceforge.plantuml.zopfli.Options.BlockSplitting; import net.sourceforge.plantuml.zopfli.Options.OutputFormat; @@ -58,7 +56,7 @@ public class CompressionZopfliZlib implements Compression { return compressor.compress(options, in).getResult(); } - public byte[] decompress(byte[] in) throws IOException { + public ByteArray decompress(byte[] in) throws NoPlantumlCompressionException { return new CompressionZlib().decompress(in); } diff --git a/src/net/sourceforge/plantuml/code/Keywords.java b/src/net/sourceforge/plantuml/code/Keywords.java new file mode 100644 index 000000000..8a585b8d3 --- /dev/null +++ b/src/net/sourceforge/plantuml/code/Keywords.java @@ -0,0 +1,183 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2020, Arnaud Roques + * + * Project Info: http://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * http://plantuml.com/patreon (only 1$ per month!) + * http://plantuml.com/paypal + * + * This file is part of PlantUML. + * + * PlantUML is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * PlantUML distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + * + */ +package net.sourceforge.plantuml.code; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; + +public class Keywords { + + private final List keywords = new ArrayList(); + + public static void main(String[] args) { + System.err.println("keywords=" + new Keywords().keywords.size()); + final Set sorted = new TreeSet(new Keywords().keywords); + for (String s : sorted) { + System.err.println(s); + } + } + + public String compress(String s) { + for (int i = 0; i < keywords.size(); i++) { + final char c = (char) ('\uE000' + i); + s = s.replace(keywords.get(i), "" + c); + } + return s; + + } + + public Keywords() { + add("actor"); + add("participant"); + add("usecase"); + add("class"); + add("interface"); + add("abstract"); + add("enum"); + add("component"); + add("state"); + add("object"); + add("artifact"); + add("folder"); + add("rectangle"); + add("node"); + add("frame"); + add("cloud"); + add("database"); + add("storage"); + add("agent"); + add("stack"); + add("boundary"); + add("control"); + add("entity"); + add("card"); + add("file"); + add("package"); + add("queue"); + add("archimate"); + add("diamond"); + add("detach"); + + add("@start"); + add("@end"); + add("also"); + add("autonumber"); + add("caption"); + add("title"); + add("newpage"); + add("loop"); + add("break"); + add("critical"); + add("note"); + add("legend"); + add("group"); + add("left"); + add("right"); + add("link"); + add("over"); + add("activate"); + add("deactivate"); + add("destroy"); + add("create"); + add("footbox"); + add("hide"); + add("show"); + add("skinparam"); + add("skin"); + add("bottom"); + add("namespace"); + add("page"); + add("down"); + add("else"); + add("endif"); + add("partition"); + add("footer"); + add("header"); + add("center"); + add("rotate"); + add("return"); + add("repeat"); + add("start"); + add("stop"); + add("while"); + add("endwhile"); + add("fork"); + add("again"); + add("kill"); + add("order"); + add("mainframe"); + add("across"); + add("stereotype"); + add("split"); + add("style"); + + add("!exit"); + add("!include"); + add("!pragma"); + add("!undef"); + add("!ifdef"); + add("!endif"); + add("!ifndef"); + add("!else"); + add("!function"); + add("!procedure"); + add("!endfunction"); + add("!endprocedure"); + add("!unquoted"); + add("!return"); + add("!startsub"); + add("!endsub"); + add("!assert"); + add("!local"); + + } + + private void add(String string) { + if (keywords.contains(string)) { + throw new IllegalArgumentException(string); + } + if (string.length() <= 3) { + throw new IllegalArgumentException(string); + } + keywords.add(string); + if (keywords.size() > 127) { + throw new IllegalArgumentException(); + } + } + +} diff --git a/src/net/sourceforge/plantuml/code/NoPlantumlCompressionException.java b/src/net/sourceforge/plantuml/code/NoPlantumlCompressionException.java new file mode 100644 index 000000000..2ec685e1e --- /dev/null +++ b/src/net/sourceforge/plantuml/code/NoPlantumlCompressionException.java @@ -0,0 +1,50 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2020, Arnaud Roques + * + * Project Info: http://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * http://plantuml.com/patreon (only 1$ per month!) + * http://plantuml.com/paypal + * + * This file is part of PlantUML. + * + * PlantUML is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * PlantUML distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + * + */ +package net.sourceforge.plantuml.code; + +import java.io.IOException; + +public class NoPlantumlCompressionException extends IOException { + + public NoPlantumlCompressionException(Exception cause) { + super(cause); + } + + public NoPlantumlCompressionException(String description) { + super(description); + } + +} diff --git a/src/net/sourceforge/plantuml/code/StringCompressor.java b/src/net/sourceforge/plantuml/code/StringCompressor.java index 18c1ab7a2..4d50035cd 100644 --- a/src/net/sourceforge/plantuml/code/StringCompressor.java +++ b/src/net/sourceforge/plantuml/code/StringCompressor.java @@ -41,6 +41,6 @@ public interface StringCompressor { String compress(String s) throws IOException; - String decompress(String compressed) throws IOException; + String decompress(String compressed) throws NoPlantumlCompressionException; } \ No newline at end of file diff --git a/src/net/sourceforge/plantuml/code/StringCompressorNone.java b/src/net/sourceforge/plantuml/code/StringCompressorNone.java index 25c59cfd6..0d6fb4b68 100644 --- a/src/net/sourceforge/plantuml/code/StringCompressorNone.java +++ b/src/net/sourceforge/plantuml/code/StringCompressorNone.java @@ -43,7 +43,7 @@ public class StringCompressorNone implements StringCompressor { return s; } - public String decompress(String stringAnnoted) throws IOException { + public String decompress(String stringAnnoted) { return stringAnnoted; } } \ No newline at end of file diff --git a/src/net/sourceforge/plantuml/code/Transcoder.java b/src/net/sourceforge/plantuml/code/Transcoder.java index e70749781..1bb0f1072 100644 --- a/src/net/sourceforge/plantuml/code/Transcoder.java +++ b/src/net/sourceforge/plantuml/code/Transcoder.java @@ -41,5 +41,5 @@ public interface Transcoder { public String encode(String text) throws IOException; - public String decode(String code) throws IOException; + public String decode(String code) throws NoPlantumlCompressionException; } diff --git a/src/net/sourceforge/plantuml/code/TranscoderImpl.java b/src/net/sourceforge/plantuml/code/TranscoderImpl.java index 9a94dc48f..38e7e156c 100644 --- a/src/net/sourceforge/plantuml/code/TranscoderImpl.java +++ b/src/net/sourceforge/plantuml/code/TranscoderImpl.java @@ -39,43 +39,54 @@ import java.io.IOException; public class TranscoderImpl implements Transcoder { + static enum Format { + UTF8, UPF9; + } + private final Compression compression; private final URLEncoder urlEncoder; private final StringCompressor stringCompressor; + private final Format format; -// private TranscoderImpl() { -// this(new AsciiEncoder(), new StringCompressorNone(), new CompressionHuffman()); -// } -// -// private TranscoderImpl(Compression compression) { -// this(new AsciiEncoder(), new StringCompressorNone(), compression); -// } -// -// private TranscoderImpl(URLEncoder urlEncoder, Compression compression) { -// this(urlEncoder, new ArobaseStringCompressor(), compression); -// } - - public TranscoderImpl(URLEncoder urlEncoder, StringCompressor stringCompressor, Compression compression) { + private TranscoderImpl(URLEncoder urlEncoder, StringCompressor stringCompressor, Compression compression, + Format format) { this.compression = compression; this.urlEncoder = urlEncoder; this.stringCompressor = stringCompressor; + this.format = format; + } + + public static Transcoder utf8(URLEncoder urlEncoder, StringCompressor stringCompressor, Compression compression) { + return new TranscoderImpl(urlEncoder, stringCompressor, compression, Format.UTF8); + } + + public static Transcoder upf9(URLEncoder urlEncoder, StringCompressor stringCompressor, Compression compression) { + return new TranscoderImpl(urlEncoder, stringCompressor, compression, Format.UPF9); } public String encode(String text) throws IOException { - final String stringAnnoted = stringCompressor.compress(text); + final byte[] data; + if (format == Format.UTF8) + data = stringAnnoted.getBytes("UTF-8"); + else + data = Upf9.getBytes(stringAnnoted); - final byte[] data = stringAnnoted.getBytes("UTF-8"); final byte[] compressedData = compression.compress(data); return urlEncoder.encode(compressedData); } - public String decode(String code) throws IOException { - final byte compressedData[] = urlEncoder.decode(code); - final byte data[] = compression.decompress(compressedData); - - return stringCompressor.decompress(new String(data, "UTF-8")); + public String decode(String code) throws NoPlantumlCompressionException { + try { + final byte compressedData[] = urlEncoder.decode(code); + final ByteArray data = compression.decompress(compressedData); + final String string = format == Format.UTF8 ? data.toUFT8String() : data.toUPF9String(); + return stringCompressor.decompress(string); + } catch (Exception e) { + System.err.println("Cannot decode string"); + throw new NoPlantumlCompressionException(e); + } } } diff --git a/src/net/sourceforge/plantuml/code/TranscoderSmart.java b/src/net/sourceforge/plantuml/code/TranscoderSmart.java index 7342d2ba4..9e81dea6c 100644 --- a/src/net/sourceforge/plantuml/code/TranscoderSmart.java +++ b/src/net/sourceforge/plantuml/code/TranscoderSmart.java @@ -40,59 +40,22 @@ import java.io.IOException; public class TranscoderSmart implements Transcoder { // Legacy encoder - private final Transcoder oldOne = new TranscoderImpl(new AsciiEncoder(), new ArobaseStringCompressor(), + private final Transcoder oldOne = TranscoderImpl.utf8(new AsciiEncoder(), new ArobaseStringCompressor(), new CompressionHuffman()); - private final Transcoder zlib = new TranscoderImpl(new AsciiEncoder(), new ArobaseStringCompressor(), + private final Transcoder zlib = TranscoderImpl.utf8(new AsciiEncoder(), new ArobaseStringCompressor(), new CompressionZlib()); - private final Transcoder brotli = new TranscoderImpl(new AsciiEncoder(), new ArobaseStringCompressor(), - new CompressionBrotli()); - - - private final Transcoder zlibBase64 = new TranscoderImpl(new AsciiEncoderBase64(), new ArobaseStringCompressor(), - new CompressionZlib()); - private final Transcoder brotliBase64 = new TranscoderImpl(new AsciiEncoderBase64(), new ArobaseStringCompressor(), - new CompressionBrotli()); - private final Transcoder base64only = new TranscoderImpl(new AsciiEncoderBase64(), new ArobaseStringCompressor(), - new CompressionNone()); - private final Transcoder hexOnly = new TranscoderImpl(new AsciiEncoderHex(), new ArobaseStringCompressor(), - new CompressionNone()); - public String decode(String code) throws IOException { + public String decode(String code) throws NoPlantumlCompressionException { // Work in progress // See https://github.com/plantuml/plantuml/issues/117 - // Two char headers - if (code.startsWith("0A")) { - return zlibBase64.decode(code.substring(2)); + if (code.startsWith("~0")) { + return zlib.decode(code.substring(2)); } - if (code.startsWith("0B")) { - return brotliBase64.decode(code.substring(2)); - } - if (code.startsWith("0C")) { - return base64only.decode(code.substring(2)); - } - if (code.startsWith("0D")) { - return hexOnly.decode(code.substring(2)); - } - // Text prefix - // Just a wild try: use them only for testing - if (code.startsWith("-deflate-")) { - return zlibBase64.decode(code.substring("-deflate-".length())); - } - if (code.startsWith("-brotli-")) { - return brotliBase64.decode(code.substring("-brotli-".length())); - } - if (code.startsWith("-base64-")) { - return base64only.decode(code.substring("-base64-".length())); - } - if (code.startsWith("-hex-")) { - return hexOnly.decode(code.substring("-hex-".length())); + if (code.startsWith("~1")) { + return oldOne.decode(code.substring(2)); } - // Legacy decoding : you should not use it any more. - if (code.startsWith("0")) { - return brotli.decode(code.substring(1)); - } try { return zlib.decode(code); } catch (Exception ex) { diff --git a/src/net/sourceforge/plantuml/code/TranscoderSmart2.java b/src/net/sourceforge/plantuml/code/TranscoderSmart2.java index 403ebd046..f36bd637c 100644 --- a/src/net/sourceforge/plantuml/code/TranscoderSmart2.java +++ b/src/net/sourceforge/plantuml/code/TranscoderSmart2.java @@ -40,24 +40,23 @@ import java.io.IOException; public class TranscoderSmart2 implements Transcoder { // Legacy encoder - private final Transcoder oldOne = new TranscoderImpl(new AsciiEncoder(), new ArobaseStringCompressor2(), + private final Transcoder oldOne = TranscoderImpl.utf8(new AsciiEncoder(), new ArobaseStringCompressor2(), new CompressionHuffman()); - private final Transcoder zlib = new TranscoderImpl(new AsciiEncoder(), new ArobaseStringCompressor2(), + private final Transcoder zlib = TranscoderImpl.utf8(new AsciiEncoder(), new ArobaseStringCompressor2(), new CompressionZlib()); - private final Transcoder brotli = new TranscoderImpl(new AsciiEncoder(), new ArobaseStringCompressor2(), + private final Transcoder brotli = TranscoderImpl.utf8(new AsciiEncoder(), new ArobaseStringCompressor2(), new CompressionBrotli()); - - - private final Transcoder zlibBase64 = new TranscoderImpl(new AsciiEncoderBase64(), new ArobaseStringCompressor2(), + + private final Transcoder zlibBase64 = TranscoderImpl.utf8(new AsciiEncoderBase64(), new ArobaseStringCompressor2(), new CompressionZlib()); - private final Transcoder brotliBase64 = new TranscoderImpl(new AsciiEncoderBase64(), new ArobaseStringCompressor2(), - new CompressionBrotli()); - private final Transcoder base64only = new TranscoderImpl(new AsciiEncoderBase64(), new ArobaseStringCompressor2(), + private final Transcoder brotliBase64 = TranscoderImpl.utf8(new AsciiEncoderBase64(), + new ArobaseStringCompressor2(), new CompressionBrotli()); + private final Transcoder base64only = TranscoderImpl.utf8(new AsciiEncoderBase64(), new ArobaseStringCompressor2(), new CompressionNone()); - private final Transcoder hexOnly = new TranscoderImpl(new AsciiEncoderHex(), new ArobaseStringCompressor2(), + private final Transcoder hexOnly = TranscoderImpl.utf8(new AsciiEncoderHex(), new ArobaseStringCompressor2(), new CompressionNone()); - public String decode(String code) throws IOException { + public String decode(String code) throws NoPlantumlCompressionException { // Work in progress // See https://github.com/plantuml/plantuml/issues/117 diff --git a/src/net/sourceforge/plantuml/code/TranscoderSmartAttic.java b/src/net/sourceforge/plantuml/code/TranscoderSmartAttic.java new file mode 100644 index 000000000..70aac69ad --- /dev/null +++ b/src/net/sourceforge/plantuml/code/TranscoderSmartAttic.java @@ -0,0 +1,108 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2020, Arnaud Roques + * + * Project Info: http://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * http://plantuml.com/patreon (only 1$ per month!) + * http://plantuml.com/paypal + * + * This file is part of PlantUML. + * + * PlantUML is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * PlantUML distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + * + */ +package net.sourceforge.plantuml.code; + +import java.io.IOException; + +public class TranscoderSmartAttic implements Transcoder { + + // Legacy encoder + private final Transcoder oldOne = TranscoderImpl.utf8(new AsciiEncoder(), new ArobaseStringCompressor(), + new CompressionHuffman()); + private final Transcoder zlib = TranscoderImpl.utf8(new AsciiEncoder(), new ArobaseStringCompressor(), + new CompressionZlib()); + private final Transcoder brotli = TranscoderImpl.utf8(new AsciiEncoder(), new ArobaseStringCompressor(), + new CompressionBrotli()); + + private final Transcoder zlibBase64 = TranscoderImpl.utf8(new AsciiEncoderBase64(), new ArobaseStringCompressor(), + new CompressionZlib()); + private final Transcoder brotliBase64 = TranscoderImpl.utf8(new AsciiEncoderBase64(), new ArobaseStringCompressor(), + new CompressionBrotli()); + private final Transcoder base64only = TranscoderImpl.utf8(new AsciiEncoderBase64(), new ArobaseStringCompressor(), + new CompressionNone()); + private final Transcoder hexOnly = TranscoderImpl.utf8(new AsciiEncoderHex(), new ArobaseStringCompressor(), + new CompressionNone()); + + public String decode(String code) throws NoPlantumlCompressionException { + // Work in progress + // See https://github.com/plantuml/plantuml/issues/117 + + // Two char headers + if (code.startsWith("0A")) { + return zlibBase64.decode(code.substring(2)); + } + if (code.startsWith("0B")) { + return brotliBase64.decode(code.substring(2)); + } + if (code.startsWith("0C")) { + return base64only.decode(code.substring(2)); + } + if (code.startsWith("0D")) { + return hexOnly.decode(code.substring(2)); + } + // Text prefix + // Just a wild try: use them only for testing + if (code.startsWith("-deflate-")) { + return zlibBase64.decode(code.substring("-deflate-".length())); + } + if (code.startsWith("-brotli-")) { + return brotliBase64.decode(code.substring("-brotli-".length())); + } + if (code.startsWith("-base64-")) { + return base64only.decode(code.substring("-base64-".length())); + } + if (code.startsWith("-hex-")) { + return hexOnly.decode(code.substring("-hex-".length())); + } + + // Legacy decoding : you should not use it any more. + if (code.startsWith("0")) { + return brotli.decode(code.substring(1)); + } + try { + return zlib.decode(code); + } catch (Exception ex) { + return oldOne.decode(code); + } + // return zlib.decode(code); + } + + public String encode(String text) throws IOException { + // Right now, we still use the legacy encoding. + // This will be changed in the incoming months + return zlib.encode(text); + } +} diff --git a/src/net/sourceforge/plantuml/code/TranscoderSmartProtected.java b/src/net/sourceforge/plantuml/code/TranscoderSmartProtected.java new file mode 100644 index 000000000..754998e8a --- /dev/null +++ b/src/net/sourceforge/plantuml/code/TranscoderSmartProtected.java @@ -0,0 +1,181 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2020, Arnaud Roques + * + * Project Info: http://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * http://plantuml.com/patreon (only 1$ per month!) + * http://plantuml.com/paypal + * + * This file is part of PlantUML. + * + * PlantUML is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * PlantUML distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + * + */ +package net.sourceforge.plantuml.code; + +import java.io.IOException; + +public class TranscoderSmartProtected implements Transcoder { + + // Legacy encoder + private final Transcoder oldOne = TranscoderImpl.utf8(new AsciiEncoder(), new ArobaseStringCompressor(), + new CompressionHuffman()); + private final Transcoder zlib = TranscoderImpl.utf8(new AsciiEncoder(), new ArobaseStringCompressor(), + new CompressionZlib()); + private final Transcoder hexOnly = TranscoderImpl.utf8(new AsciiEncoderHex(), new ArobaseStringCompressor(), + new CompressionNone()); + + public String decode(String code) throws NoPlantumlCompressionException { + // Work in progress + // See https://github.com/plantuml/plantuml/issues/117 + + if (code.startsWith("~0")) { + return decodeZlib(code.substring(2)); + } + if (code.startsWith("~1")) { + return decodeHuffman(code.substring(2)); + } + if (code.startsWith("~h")) { + return hexOnly.decode(code.substring(2)); + } + + return decodeZlib(code); + } + + private String decodeZlib(String code) { + try { + return zlib.decode(code); + } catch (Exception ex) { + try { + oldOne.decode(code); + return textProtectedDeflate2(code); + } catch (Exception ex2) { + return textProtectedDeflate(code); + } + } + } + + private String decodeHuffman(String code) { + try { + return oldOne.decode(code); + } catch (Exception ex) { + return textProtectedHuffman(code); + } + } + + private String textProtectedHuffman(String code) { + final StringBuilder result = new StringBuilder(); + appendLine(result, "@startuml"); + appendLine(result, "legend"); + appendLine(result, "The plugin you are using seems to generated a bad URL."); + appendLine(result, "This URL does not look like HUFFMAN data."); + appendLine(result, ""); + appendLine(result, "See https://plantuml.com/pte"); + appendLine(result, ""); + appendLine(result, "You may contact the PlantUML team at plantuml@gmail.com"); + appendLine(result, + "But you should also probably contact the plugin authors you are currently using and send them this image"); + appendLine(result, ""); + appendLine(result, "For the record, here is your data:"); + appendLine(result, ""); + appendURL(result, code); + appendLine(result, "endlegend"); + appendLine(result, "@enduml"); + + return result.toString(); + } + + private String textProtectedDeflate2(String code) { + final StringBuilder result = new StringBuilder(); + final String codeshort = code.length() > 30 ? code.substring(0, 30) + "..." : code; + appendLine(result, "@startuml"); + appendLine(result, "legend"); + appendLine(result, "The plugin you are using seems to generated a bad URL."); + appendLine(result, "This URL does not look like DEFLATE data."); + appendLine(result, "It looks like your plugin is using HUFFMAN encoding."); + appendLine(result, ""); + appendLine(result, + "This means you have now to add an header ~1 to your data. For example, you have to change:"); + appendLine(result, "http://www.plantuml.com/plantuml/png/" + codeshort); + appendLine(result, "to"); + appendLine(result, "http://www.plantuml.com/plantuml/png/~1" + codeshort); + appendLine(result, ""); + appendLine(result, "It will work this way"); + appendLine(result, "You may contact the PlantUML team at plantuml@gmail.com"); + appendLine(result, + "But you should also probably contact the plugin authors you are currently using and send them this image"); + appendLine(result, ""); + appendLine(result, "For the record, here is your data:"); + appendLine(result, ""); + appendURL(result, code); + appendLine(result, "endlegend"); + appendLine(result, "@enduml"); + + return result.toString(); + } + + private String textProtectedDeflate(String code) { + final StringBuilder result = new StringBuilder(); + appendLine(result, "@startuml"); + appendLine(result, "legend"); + appendLine(result, "The plugin you are using seems to generated a bad URL."); + appendLine(result, "This URL does not look like DEFLATE data."); + appendLine(result, ""); + appendLine(result, "See https://plantuml.com/pte"); + appendLine(result, ""); + appendLine(result, "You may contact the PlantUML team at plantuml@gmail.com"); + appendLine(result, + "But you should also probably contact the plugin authors you are currently using and send them this image"); + appendLine(result, ""); + appendLine(result, "For the record, here is your data:"); + appendLine(result, ""); + appendURL(result, code); + appendLine(result, "endlegend"); + appendLine(result, "@enduml"); + + return result.toString(); + } + + private void appendURL(StringBuilder result, String url) { + while (url.length() > 80) { + appendLine(result, url.substring(0, 80)); + url = url.substring(80); + } + if (url.length() > 0) { + appendLine(result, url); + } + } + + private void appendLine(StringBuilder sb, String s) { + sb.append(s); + sb.append("\n"); + } + + public String encode(String text) throws IOException { + // Right now, we still use the legacy encoding. + // This will be changed in the incoming months + return zlib.encode(text); + } +} diff --git a/src/net/sourceforge/plantuml/code/TranscoderSmartProtectedPure.java b/src/net/sourceforge/plantuml/code/TranscoderSmartProtectedPure.java new file mode 100644 index 000000000..07d913bd5 --- /dev/null +++ b/src/net/sourceforge/plantuml/code/TranscoderSmartProtectedPure.java @@ -0,0 +1,181 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2020, Arnaud Roques + * + * Project Info: http://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * http://plantuml.com/patreon (only 1$ per month!) + * http://plantuml.com/paypal + * + * This file is part of PlantUML. + * + * PlantUML is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * PlantUML distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + * + */ +package net.sourceforge.plantuml.code; + +import java.io.IOException; + +public class TranscoderSmartProtectedPure implements Transcoder { + + // Legacy encoder + private final Transcoder oldOne = TranscoderImpl.utf8(new AsciiEncoder(), new ArobaseStringCompressor(), + new CompressionHuffman()); + private final Transcoder zlib = TranscoderImpl.utf8(new AsciiEncoder(), new ArobaseStringCompressor(), + new CompressionZlibPure()); + private final Transcoder hexOnly = TranscoderImpl.utf8(new AsciiEncoderHex(), new ArobaseStringCompressor(), + new CompressionNone()); + + public String decode(String code) throws NoPlantumlCompressionException { + // Work in progress + // See https://github.com/plantuml/plantuml/issues/117 + + if (code.startsWith("~0")) { + return decodeZlib(code.substring(2)); + } + if (code.startsWith("~1")) { + return decodeHuffman(code.substring(2)); + } + if (code.startsWith("~h")) { + return hexOnly.decode(code.substring(2)); + } + + return decodeZlib(code); + } + + private String decodeZlib(String code) { + try { + return zlib.decode(code); + } catch (Exception ex) { + try { + oldOne.decode(code); + return textProtectedDeflate2(code); + } catch (Exception ex2) { + return textProtectedDeflate(code); + } + } + } + + private String decodeHuffman(String code) { + try { + return oldOne.decode(code); + } catch (Exception ex) { + return textProtectedHuffman(code); + } + } + + private String textProtectedHuffman(String code) { + final StringBuilder result = new StringBuilder(); + appendLine(result, "@startuml"); + appendLine(result, "legend"); + appendLine(result, "The plugin you are using seems to generated a bad URL."); + appendLine(result, "This URL does not look like HUFFMAN data."); + appendLine(result, ""); + appendLine(result, "See https://plantuml.com/pte"); + appendLine(result, ""); + appendLine(result, "You may contact the PlantUML team at plantuml@gmail.com"); + appendLine(result, + "But you should also probably contact the plugin authors you are currently using and send them this image"); + appendLine(result, ""); + appendLine(result, "For the record, here is your data:"); + appendLine(result, ""); + appendURL(result, code); + appendLine(result, "endlegend"); + appendLine(result, "@enduml"); + + return result.toString(); + } + + private String textProtectedDeflate2(String code) { + final StringBuilder result = new StringBuilder(); + final String codeshort = code.length() > 30 ? code.substring(0, 30) + "..." : code; + appendLine(result, "@startuml"); + appendLine(result, "legend"); + appendLine(result, "The plugin you are using seems to generated a bad URL."); + appendLine(result, "This URL does not look like DEFLATE data."); + appendLine(result, "It looks like your plugin is using HUFFMAN encoding."); + appendLine(result, ""); + appendLine(result, + "This means you have now to add an header ~1 to your data. For example, you have to change:"); + appendLine(result, "http://www.plantuml.com/plantuml/png/" + codeshort); + appendLine(result, "to"); + appendLine(result, "http://www.plantuml.com/plantuml/png/~1" + codeshort); + appendLine(result, ""); + appendLine(result, "It will work this way"); + appendLine(result, "You may contact the PlantUML team at plantuml@gmail.com"); + appendLine(result, + "But you should also probably contact the plugin authors you are currently using and send them this image"); + appendLine(result, ""); + appendLine(result, "For the record, here is your data:"); + appendLine(result, ""); + appendURL(result, code); + appendLine(result, "endlegend"); + appendLine(result, "@enduml"); + + return result.toString(); + } + + private String textProtectedDeflate(String code) { + final StringBuilder result = new StringBuilder(); + appendLine(result, "@startuml"); + appendLine(result, "legend"); + appendLine(result, "The plugin you are using seems to generated a bad URL."); + appendLine(result, "This URL does not look like DEFLATE data."); + appendLine(result, ""); + appendLine(result, "See https://plantuml.com/pte"); + appendLine(result, ""); + appendLine(result, "You may contact the PlantUML team at plantuml@gmail.com"); + appendLine(result, + "But you should also probably contact the plugin authors you are currently using and send them this image"); + appendLine(result, ""); + appendLine(result, "For the record, here is your data:"); + appendLine(result, ""); + appendURL(result, code); + appendLine(result, "endlegend"); + appendLine(result, "@enduml"); + + return result.toString(); + } + + private void appendURL(StringBuilder result, String url) { + while (url.length() > 80) { + appendLine(result, url.substring(0, 80)); + url = url.substring(80); + } + if (url.length() > 0) { + appendLine(result, url); + } + } + + private void appendLine(StringBuilder sb, String s) { + sb.append(s); + sb.append("\n"); + } + + public String encode(String text) throws IOException { + // Right now, we still use the legacy encoding. + // This will be changed in the incoming months + return zlib.encode(text); + } +} diff --git a/src/net/sourceforge/plantuml/code/TranscoderUtil.java b/src/net/sourceforge/plantuml/code/TranscoderUtil.java index 4148cd06f..518e41898 100644 --- a/src/net/sourceforge/plantuml/code/TranscoderUtil.java +++ b/src/net/sourceforge/plantuml/code/TranscoderUtil.java @@ -41,8 +41,12 @@ public class TranscoderUtil { return new TranscoderSmart(); } - public static Transcoder getDefaultTranscoder2() { - return new TranscoderSmart2(); + public static Transcoder getDefaultTranscoderProtected() { + return new TranscoderSmartProtected(); + } + + public static Transcoder getDefaultTranscoderProtectedPure() { + return new TranscoderSmartProtectedPure(); } } diff --git a/src/net/sourceforge/plantuml/code/Upf9.java b/src/net/sourceforge/plantuml/code/Upf9.java new file mode 100644 index 000000000..6cb5e5bf6 --- /dev/null +++ b/src/net/sourceforge/plantuml/code/Upf9.java @@ -0,0 +1,156 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2020, Arnaud Roques + * + * Project Info: http://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * http://plantuml.com/patreon (only 1$ per month!) + * http://plantuml.com/paypal + * + * This file is part of PlantUML. + * + * PlantUML is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * PlantUML distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + * + */ +package net.sourceforge.plantuml.code; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; + +public class Upf9 { + + private Upf9() { + + } + + public static byte[] encodeChar(char c) { + final byte[] result = encodeCharInternal(c); + assert checkBack(c, result); + return result; + } + + private static boolean checkBack(char c, byte[] result) { + try { + if (c == decodeChar(new ByteArrayInputStream(result))) + return true; + } catch (IOException e) { + e.printStackTrace(); + } + return false; + } + + private static byte[] encodeCharInternal(char c) { + if (c == '\n' || c == '\r' || c == '\t') { + return new byte[] { (byte) c }; + } + if (c >= '\u0020' && c <= '\u007E') { + return new byte[] { (byte) c }; + } + if (c >= '\u0080' && c <= '\u00FF') { + return new byte[] { 0x0B, (byte) c }; + } + if (c >= '\u0100' && c <= '\u08FF') { + return new byte[] { highByte(c), lowByte(c) }; + } + if (c >= '\u0900' && c <= '\u10FF') { + return new byte[] { (byte) (5 + highByte(c)), lowByte(c) }; + } + if (c >= '\u1900' && c <= '\u1FFF') { + return new byte[] { (byte) (-3 + highByte(c)), lowByte(c) }; + } + if (c >= '\u2000' && c <= '\u9FFF') { + return new byte[] { (byte) (96 + highByte(c)), lowByte(c) }; + } + if (c >= '\uE000' && c <= '\uE07F') { + return new byte[] { 0x0B, lowByte(c) }; + } + return new byte[] { 0x0C, highByte(c), lowByte(c) }; + } + + static int decodeChar(InputStream is) throws IOException { + final int read0 = is.read(); + if (read0 == -1) { + return -1; + } + if (read0 == 0x0B) { + final int read1 = is.read(); + if (read1 >= 0x80) + return (char) read1; + return (char) ((0xE0 << 8) + read1); + } + if (read0 == 0x0C) { + final int read1 = is.read(); + final int read2 = is.read(); + return (char) ((read1 << 8) + read2); + } + if (read0 >= 0x01 && read0 <= 0x08) { + final int read1 = is.read(); + return (char) ((read0 << 8) + read1); + } + if (read0 >= 0x0E && read0 <= 0x15) { + final int read1 = is.read(); + return (char) (((read0 - 5) << 8) + read1); + } + if (read0 >= 0x16 && read0 <= 0x1C) { + final int read1 = is.read(); + return (char) (((read0 + 3) << 8) + read1); + } + if (read0 >= 0x80 && read0 <= 0xFF) { + final int read1 = is.read(); + return (char) (((read0 - 96) << 8) + read1); + } + return (char) read0; + } + + private static byte lowByte(char c) { + return (byte) (c & 0x00FF); + } + + private static byte highByte(char c) { + return (byte) ((c & 0xFF00) >> 8); + } + + public static byte[] getBytes(String s) throws IOException { + final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + for (int i = 0; i < s.length(); i++) { + baos.write(encodeChar(s.charAt(i))); + } + baos.close(); + return baos.toByteArray(); + } + + public static String decodeString(byte[] data, int length) throws IOException { + final ByteArrayInputStream bais = new ByteArrayInputStream(data, 0, length); + final StringBuilder result = new StringBuilder(); + int read; + while ((read = decodeChar(bais)) != -1) { + result.append((char) read); + } + bais.close(); + return result.toString(); + } + +} diff --git a/src/net/sourceforge/plantuml/code/deflate/BitInputStream.java b/src/net/sourceforge/plantuml/code/deflate/BitInputStream.java new file mode 100644 index 000000000..9db9aa86b --- /dev/null +++ b/src/net/sourceforge/plantuml/code/deflate/BitInputStream.java @@ -0,0 +1,62 @@ +package net.sourceforge.plantuml.code.deflate; + +/* + * Simple DEFLATE decompressor + * Copyright (c) Project Nayuki + * + * https://www.nayuki.io/page/simple-deflate-decompressor + * https://github.com/nayuki/Simple-DEFLATE-decompressor + */ + +import java.io.Closeable; +import java.io.EOFException; +import java.io.IOException; + + +/** + * A stream of bits that can be read. Bits are packed in little endian within a byte. + * For example, the byte 0x87 reads as the sequence of bits [1,1,1,0,0,0,0,1]. + */ +public interface BitInputStream extends Closeable { + + /** + * Returns the current bit position, which ascends from 0 to 7 as bits are read. + * @return the current bit position, which is between 0 and 7 + */ + public int getBitPosition(); + + + /** + * Discards the remainder of the current byte (if any) and reads the next + * whole byte from the stream. Returns -1 if the end of stream is reached. + * @return the next byte from the stream, or -1 if the end of stream is reached + */ + public int readByte() throws IOException; + + + /** + * Reads a bit from this stream. Returns 0 or 1 if a bit is available, or -1 if + * the end of stream is reached. The end of stream always occurs on a byte boundary. + * @return the next bit of 0 or 1, or -1 for the end of stream + * @throws IOException if an I/O exception occurred + */ + public int read() throws IOException; + + + /** + * Reads a bit from this stream. Returns 0 or 1 if a bit is available, or throws an {@code EOFException} + * if the end of stream is reached. The end of stream always occurs on a byte boundary. + * @return the next bit of 0 or 1 + * @throws IOException if an I/O exception occurred + * @throws EOFException if the end of stream is reached + */ + public int readNoEof() throws IOException; + + + /** + * Closes this stream and the underlying input stream. + * @throws IOException if an I/O exception occurred + */ + public void close() throws IOException; + +} diff --git a/src/net/sourceforge/plantuml/code/deflate/ByteBitInputStream.java b/src/net/sourceforge/plantuml/code/deflate/ByteBitInputStream.java new file mode 100644 index 000000000..2ec18f60f --- /dev/null +++ b/src/net/sourceforge/plantuml/code/deflate/ByteBitInputStream.java @@ -0,0 +1,98 @@ +package net.sourceforge.plantuml.code.deflate; + +/* + * Simple DEFLATE decompressor + * Copyright (c) Project Nayuki + * + * https://www.nayuki.io/page/simple-deflate-decompressor + * https://github.com/nayuki/Simple-DEFLATE-decompressor + */ + +import java.io.EOFException; +import java.io.IOException; +import java.io.InputStream; +import java.util.Objects; + + +/** + * A stream of bits that can be read. Because they come from an underlying byte stream, + * the total number of bits is always a multiple of 8. The bits are read in little endian. + * Mutable and not thread-safe. + */ +public final class ByteBitInputStream implements BitInputStream { + + /*---- Fields ----*/ + + // The underlying byte stream to read from (not null). + private InputStream input; + + // Either in the range [0x00, 0xFF] if bits are available, or -1 if end of stream is reached. + private int currentByte; + + // Number of remaining bits in the current byte, always between 0 and 7 (inclusive). + private int numBitsRemaining; + + + + /*---- Constructor ----*/ + + /** + * Constructs a bit input stream based on the specified byte input stream. + * @param in the byte input stream (not {@code null}) + * @throws NullPointerException if the input stream is {@code null} + */ + public ByteBitInputStream(InputStream in) { + input = Objects.requireNonNull(in); + currentByte = 0; + numBitsRemaining = 0; + } + + + + /*---- Methods ----*/ + + public int getBitPosition() { + if (numBitsRemaining < 0 || numBitsRemaining > 7) + throw new IllegalStateException(); + return (8 - numBitsRemaining) % 8; + } + + + public int readByte() throws IOException { + currentByte = 0; + numBitsRemaining = 0; + return input.read(); + } + + + public int read() throws IOException { + if (currentByte == -1) + return -1; + if (numBitsRemaining == 0) { + currentByte = input.read(); + if (currentByte == -1) + return -1; + numBitsRemaining = 8; + } + if (numBitsRemaining <= 0) + throw new IllegalStateException(); + numBitsRemaining--; + return (currentByte >>> (7 - numBitsRemaining)) & 1; + } + + + public int readNoEof() throws IOException { + int result = read(); + if (result == -1) + throw new EOFException(); + return result; + } + + + public void close() throws IOException { + input.close(); + currentByte = -1; + numBitsRemaining = 0; + } + +} diff --git a/src/net/sourceforge/plantuml/code/deflate/ByteHistory.java b/src/net/sourceforge/plantuml/code/deflate/ByteHistory.java new file mode 100644 index 000000000..8321448a6 --- /dev/null +++ b/src/net/sourceforge/plantuml/code/deflate/ByteHistory.java @@ -0,0 +1,92 @@ +package net.sourceforge.plantuml.code.deflate; + +/* + * Simple DEFLATE decompressor + * Copyright (c) Project Nayuki + * + * https://www.nayuki.io/page/simple-deflate-decompressor + * https://github.com/nayuki/Simple-DEFLATE-decompressor + */ + +import java.io.IOException; +import java.util.Objects; + + +/** + * Stores a finite recent history of a byte stream. Useful as an implicit + * dictionary for Lempel-Ziv schemes. Mutable and not thread-safe. + */ +final class ByteHistory { + + /*---- Fields ----*/ + + // Circular buffer of byte data. + private byte[] data; + + // Index of next byte to write to, always in the range [0, data.length). + private int index; + + + + /*---- Constructor ----*/ + + /** + * Constructs a byte history of the specified size, initialized to zeros. + * @param size the size, which must be positive + * @throws IllegalArgumentException if size is zero or negative + */ + public ByteHistory(int size) { + if (size < 1) + throw new IllegalArgumentException("Size must be positive"); + data = new byte[size]; + index = 0; + } + + + + /*---- Methods ----*/ + + /** + * Appends the specified byte to this history. + * This overwrites the byte value at {@code size} positions ago. + * @param b the byte value to append + */ + public void append(int b) { + if (index < 0 || index >= data.length) + throw new IllegalStateException(); + data[index] = (byte)b; + index = (index + 1) % data.length; + } + + + /** + * Copies {@code len} bytes starting at {@code dist} bytes ago to + * the specified output stream and also back into this buffer itself. + *

Note that if the length exceeds the distance, then some of the output + * data will be a copy of data that was copied earlier in the process.

+ * @param dist the distance to go back, in the range [1, size] + * @param len the length to copy, which must be at least 0 + * @param out the output stream to write to (not {@code null}) + * @throws NullPointerException if the output stream is {@code null} + * @throws IllegalArgumentException if the length is negative, + * distance is not positive, or distance is greater than the buffer size + * @throws IOException if an I/O exception occurs + */ + public void copy(int dist, int len, OutputStreamProtected out) throws IOException { + Objects.requireNonNull(out); + if (len < 0 || dist < 1 || dist > data.length) + throw new IllegalArgumentException(); + + int readIndex = (index - dist + data.length) % data.length; + if (readIndex < 0 || readIndex >= data.length) + throw new IllegalStateException(); + + for (int i = 0; i < len; i++) { + byte b = data[readIndex]; + readIndex = (readIndex + 1) % data.length; + out.write(b); + append(b); + } + } + +} diff --git a/src/net/sourceforge/plantuml/code/deflate/CanonicalCode.java b/src/net/sourceforge/plantuml/code/deflate/CanonicalCode.java new file mode 100644 index 000000000..bfe21cf70 --- /dev/null +++ b/src/net/sourceforge/plantuml/code/deflate/CanonicalCode.java @@ -0,0 +1,174 @@ +package net.sourceforge.plantuml.code.deflate; + +/* + * Simple DEFLATE decompressor + * Copyright (c) Project Nayuki + * + * https://www.nayuki.io/page/simple-deflate-decompressor + * https://github.com/nayuki/Simple-DEFLATE-decompressor + */ + +import java.io.IOException; +import java.util.Arrays; +import java.util.Objects; + + +/** + * A canonical Huffman code, where the code values for each symbol is derived + * from a given sequence of code lengths. This data structure is immutable. + * This could be transformed into an explicit Huffman code tree. + *

Example:

+ *
  Code lengths (canonical code):
+ *    Symbol A: 1
+ *    Symbol B: 0 (no code)
+ *    Symbol C: 3
+ *    Symbol D: 2
+ *    Symbol E: 3
+ *  
+ *  Generated Huffman codes:
+ *    Symbol A: 0
+ *    Symbol B: (Absent)
+ *    Symbol C: 110
+ *    Symbol D: 10
+ *    Symbol E: 111
+ *  
+ *  Huffman code tree:
+ *      .
+ *     / \
+ *    A   .
+ *       / \
+ *      D   .
+ *         / \
+ *        C   E
+ */ +final class CanonicalCode { + + /* + * These arrays store the Huffman codes and values necessary for decoding. + * symbolCodeBits contains Huffman codes, each padded with a 1 bit at the + * beginning to disambiguate codes of different lengths (e.g. otherwise we + * can't distinguish 0b01 from 0b0001). Each symbolCodeBits[i] decodes to its + * corresponding symbolValues[i]. Values in symbolCodeBits are strictly increasing. + * + * For the example of codeLengths=[1,0,3,2,3], we would have: + * i | symbolCodeBits[i] | symbolValues[i] + * --+-------------------+---------------- + * 0 | 0b1_0 | 0 + * 1 | 0b1_10 | 3 + * 2 | 0b1_110 | 2 + * 3 | 0b1_111 | 4 + */ + private int[] symbolCodeBits; + private int[] symbolValues; + + + + /** + * Constructs a canonical Huffman code from the specified array of symbol code lengths. + * Each code length must be non-negative. Code length 0 means no code for the symbol. + * The collection of code lengths must represent a proper full Huffman code tree. + *

Examples of code lengths that result in correct full Huffman code trees:

+ *
    + *
  • [1, 1] (result: A=0, B=1)
  • + *
  • [2, 2, 1, 0, 0, 0] (result: A=10, B=11, C=0)
  • + *
  • [3, 3, 3, 3, 3, 3, 3, 3] (result: A=000, B=001, C=010, ..., H=111)
  • + *
+ *

Examples of code lengths that result in under-full Huffman code trees:

+ *
    + *
  • [0, 2, 0] (result: B=00, unused=01, unused=1)
  • + *
  • [0, 1, 0, 2] (result: B=0, D=10, unused=11)
  • + *
+ *

Examples of code lengths that result in over-full Huffman code trees:

+ *
    + *
  • [1, 1, 1] (result: A=0, B=1, C=overflow)
  • + *
  • [1, 1, 2, 2, 3, 3, 3, 3] (result: A=0, B=1, C=overflow, ...)
  • + *
+ * @param canonicalCodeLengths array of symbol code lengths (not {@code null}) + * @throws NullPointerException if the array is {@code null} + * @throws IllegalArgumentException if any element is negative, any value exceeds MAX_CODE_LENGTH, + * or the collection of code lengths would yield an under-full or over-full Huffman code tree + */ + public CanonicalCode(int[] codeLengths) { + // Check argument values + Objects.requireNonNull(codeLengths); + for (int x : codeLengths) { + if (x < 0) + throw new IllegalArgumentException("Negative code length"); + if (x > MAX_CODE_LENGTH) + throw new IllegalArgumentException("Maximum code length exceeded"); + } + + // Allocate code values to symbols. Symbols are processed in the order + // of shortest code length first, breaking ties by lowest symbol value. + symbolCodeBits = new int[codeLengths.length]; + symbolValues = new int[codeLengths.length]; + int numSymbolsAllocated = 0; + int nextCode = 0; + for (int codeLength = 1; codeLength <= MAX_CODE_LENGTH; codeLength++) { + nextCode <<= 1; + int startBit = 1 << codeLength; + for (int symbol = 0; symbol < codeLengths.length; symbol++) { + if (codeLengths[symbol] != codeLength) + continue; + if (nextCode >= startBit) + throw new IllegalArgumentException("This canonical code produces an over-full Huffman code tree"); + + symbolCodeBits[numSymbolsAllocated] = startBit | nextCode; + symbolValues [numSymbolsAllocated] = symbol; + numSymbolsAllocated++; + nextCode++; + } + } + if (nextCode != 1 << MAX_CODE_LENGTH) + throw new IllegalArgumentException("This canonical code produces an under-full Huffman code tree"); + + // Trim unused trailing elements + symbolCodeBits = Arrays.copyOf(symbolCodeBits, numSymbolsAllocated); + symbolValues = Arrays.copyOf(symbolValues , numSymbolsAllocated); + } + + + + /** + * Decodes the next symbol from the specified bit input stream based on this + * canonical code. The returned symbol value is in the range [0, codeLengths.length). + * @param in the bit input stream to read from + * @return the next decoded symbol + * @throws IOException if an I/O exception occurred + */ + public int decodeNextSymbol(BitInputStream in) throws IOException { + Objects.requireNonNull(in); + int codeBits = 1; // The start bit + while (true) { + // Accumulate one bit at a time on the right side until a match is + // found in the symbolCodeBits array. Because the Huffman code tree is + // full, this loop must terminate after at most MAX_CODE_LENGTH iterations. + codeBits = codeBits << 1 | in.readNoEof(); + int index = Arrays.binarySearch(symbolCodeBits, codeBits); + if (index >= 0) + return symbolValues[index]; + } + } + + + /** + * Returns a string representation of this canonical code, + * useful for debugging only, and the format is subject to change. + * @return a string representation of this canonical code + */ + public String toString() { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < symbolCodeBits.length; i++) { + sb.append(String.format("Code %s: Symbol %d%n", + Integer.toBinaryString(symbolCodeBits[i]).substring(1), + symbolValues[i])); + } + return sb.toString(); + } + + + + // The maximum Huffman code length allowed in the DEFLATE standard. + private static final int MAX_CODE_LENGTH = 15; + +} diff --git a/src/net/sourceforge/plantuml/code/deflate/Decompressor.java b/src/net/sourceforge/plantuml/code/deflate/Decompressor.java new file mode 100644 index 000000000..ccafd96f5 --- /dev/null +++ b/src/net/sourceforge/plantuml/code/deflate/Decompressor.java @@ -0,0 +1,300 @@ +package net.sourceforge.plantuml.code.deflate; + +import java.io.EOFException; +import java.io.IOException; +import java.util.Arrays; +import java.util.Objects; +import java.util.zip.DataFormatException; + + +/** + * Decompresses raw DEFLATE data (without zlib or gzip container) into bytes. + */ +public final class Decompressor { + + /*---- Public functions ----*/ + + /** + * Reads from the specified input stream, decompress the data, and returns a new byte array. + * @param in the bit input stream to read from (not {@code null}) + * @throws NullPointerException if the input stream is {@code null} + * @throws DataFormatException if the DEFLATE data is malformed + */ + public static byte[] decompress(BitInputStream in) throws IOException, DataFormatException { + OutputStreamProtected out = new OutputStreamProtected(); + decompress(in, out); + return out.toByteArray(); + } + + + /** + * Reads from the specified input stream, decompress the data, and writes to the specified output stream. + * @param in the bit input stream to read from (not {@code null}) + * @param out the byte output stream to write to (not {@code null}) + * @throws NullPointerException if the input or output stream is {@code null} + * @throws DataFormatException if the DEFLATE data is malformed + */ + public static void decompress(BitInputStream in, OutputStreamProtected out) throws IOException, DataFormatException { + new Decompressor(in, out); + } + + + + /*---- Private implementation ----*/ + + private BitInputStream input; + + private OutputStreamProtected output; + + private ByteHistory dictionary; + + + + // Constructor, which immediately performs decompression + private Decompressor(BitInputStream in, OutputStreamProtected out) throws IOException, DataFormatException { + // Initialize fields + input = Objects.requireNonNull(in); + output = Objects.requireNonNull(out); + dictionary = new ByteHistory(32 * 1024); + + // Process the stream of blocks + boolean isFinal; + do { + // Read the block header + isFinal = in.readNoEof() == 1; // bfinal + int type = readInt(2); // btype + + // Decompress rest of block based on the type + if (type == 0) + decompressUncompressedBlock(); + else if (type == 1) + decompressHuffmanBlock(FIXED_LITERAL_LENGTH_CODE, FIXED_DISTANCE_CODE); + else if (type == 2) { + CanonicalCode[] litLenAndDist = decodeHuffmanCodes(); + decompressHuffmanBlock(litLenAndDist[0], litLenAndDist[1]); + } else if (type == 3) + throw new DataFormatException("Reserved block type"); + else + throw new IllegalStateException("Impossible value"); + } while (!isFinal); + } + + + /*-- The constant code trees for static Huffman codes (btype = 1) --*/ + + private static final CanonicalCode FIXED_LITERAL_LENGTH_CODE; + private static final CanonicalCode FIXED_DISTANCE_CODE; + + static { // Make temporary tables of canonical code lengths + int[] llcodelens = new int[288]; + Arrays.fill(llcodelens, 0, 144, 8); + Arrays.fill(llcodelens, 144, 256, 9); + Arrays.fill(llcodelens, 256, 280, 7); + Arrays.fill(llcodelens, 280, 288, 8); + FIXED_LITERAL_LENGTH_CODE = new CanonicalCode(llcodelens); + + int[] distcodelens = new int[32]; + Arrays.fill(distcodelens, 5); + FIXED_DISTANCE_CODE = new CanonicalCode(distcodelens); + } + + + /*-- Method for reading and decoding dynamic Huffman codes (btype = 2) --*/ + + // Reads from the bit input stream, decodes the Huffman code + // specifications into code trees, and returns the trees. + private CanonicalCode[] decodeHuffmanCodes() throws IOException, DataFormatException { + int numLitLenCodes = readInt(5) + 257; // hlit + 257 + int numDistCodes = readInt(5) + 1; // hdist + 1 + + // Read the code length code lengths + int numCodeLenCodes = readInt(4) + 4; // hclen + 4 + int[] codeLenCodeLen = new int[19]; // This array is filled in a strange order + codeLenCodeLen[16] = readInt(3); + codeLenCodeLen[17] = readInt(3); + codeLenCodeLen[18] = readInt(3); + codeLenCodeLen[ 0] = readInt(3); + for (int i = 0; i < numCodeLenCodes - 4; i++) { + int j = (i % 2 == 0) ? (8 + i / 2) : (7 - i / 2); + codeLenCodeLen[j] = readInt(3); + } + + // Create the code length code + CanonicalCode codeLenCode; + try { + codeLenCode = new CanonicalCode(codeLenCodeLen); + } catch (IllegalArgumentException e) { + throw new DataFormatException(e.getMessage()); + } + + // Read the main code lengths and handle runs + int[] codeLens = new int[numLitLenCodes + numDistCodes]; + for (int codeLensIndex = 0; codeLensIndex < codeLens.length; ) { + int sym = codeLenCode.decodeNextSymbol(input); + if (0 <= sym && sym <= 15) { + codeLens[codeLensIndex] = sym; + codeLensIndex++; + } else { + int runLen; + int runVal = 0; + if (sym == 16) { + if (codeLensIndex == 0) + throw new DataFormatException("No code length value to copy"); + runLen = readInt(2) + 3; + runVal = codeLens[codeLensIndex - 1]; + } else if (sym == 17) + runLen = readInt(3) + 3; + else if (sym == 18) + runLen = readInt(7) + 11; + else + throw new IllegalStateException("Symbol out of range"); + int end = codeLensIndex + runLen; + if (end > codeLens.length) + throw new DataFormatException("Run exceeds number of codes"); + Arrays.fill(codeLens, codeLensIndex, end, runVal); + codeLensIndex = end; + } + } + + // Create literal-length code tree + int[] litLenCodeLen = Arrays.copyOf(codeLens, numLitLenCodes); + CanonicalCode litLenCode; + try { + litLenCode = new CanonicalCode(litLenCodeLen); + } catch (IllegalArgumentException e) { + throw new DataFormatException(e.getMessage()); + } + + // Create distance code tree with some extra processing + int[] distCodeLen = Arrays.copyOfRange(codeLens, numLitLenCodes, codeLens.length); + CanonicalCode distCode; + if (distCodeLen.length == 1 && distCodeLen[0] == 0) + distCode = null; // Empty distance code; the block shall be all literal symbols + else { + // Get statistics for upcoming logic + int oneCount = 0; + int otherPositiveCount = 0; + for (int x : distCodeLen) { + if (x == 1) + oneCount++; + else if (x > 1) + otherPositiveCount++; + } + + // Handle the case where only one distance code is defined + if (oneCount == 1 && otherPositiveCount == 0) { + // Add a dummy invalid code to make the Huffman tree complete + distCodeLen = Arrays.copyOf(distCodeLen, 32); + distCodeLen[31] = 1; + } + try { + distCode = new CanonicalCode(distCodeLen); + } catch (IllegalArgumentException e) { + throw new DataFormatException(e.getMessage()); + } + } + + return new CanonicalCode[]{litLenCode, distCode}; + } + + + /*-- Block decompression methods --*/ + + // Handles and copies an uncompressed block from the bit input stream. + private void decompressUncompressedBlock() throws IOException, DataFormatException { + // Discard bits to align to byte boundary + while (input.getBitPosition() != 0) + input.readNoEof(); + + // Read length + int len = readInt(16); + int nlen = readInt(16); + if ((len ^ 0xFFFF) != nlen) + throw new DataFormatException("Invalid length in uncompressed block"); + + // Copy bytes + for (int i = 0; i < len; i++) { + int b = input.readByte(); + if (b == -1) + throw new EOFException(); + output.write(b); + dictionary.append(b); + } + } + + + // Decompresses a Huffman-coded block from the bit input stream based on the given Huffman codes. + private void decompressHuffmanBlock(CanonicalCode litLenCode, CanonicalCode distCode) + throws IOException, DataFormatException { + Objects.requireNonNull(litLenCode); + // distCode is allowed to be null + + while (true) { + int sym = litLenCode.decodeNextSymbol(input); + if (sym == 256) // End of block + break; + + if (sym < 256) { // Literal byte + output.write(sym); + dictionary.append(sym); + } else { // Length and distance for copying + int run = decodeRunLength(sym); + if (run < 3 || run > 258) + throw new IllegalStateException("Invalid run length"); + if (distCode == null) + throw new DataFormatException("Length symbol encountered with empty distance code"); + int distSym = distCode.decodeNextSymbol(input); + int dist = decodeDistance(distSym); + if (dist < 1 || dist > 32768) + throw new IllegalStateException("Invalid distance"); + dictionary.copy(dist, run, output); + } + } + } + + + /*-- Symbol decoding methods --*/ + + // Returns the run length based on the given symbol and possibly reading more bits. + private int decodeRunLength(int sym) throws IOException, DataFormatException { + if (sym < 257 || sym > 287) // Cannot occur in the bit stream; indicates the decompressor is buggy + throw new IllegalStateException("Invalid run length symbol: " + sym); + else if (sym <= 264) + return sym - 254; + else if (sym <= 284) { + int numExtraBits = (sym - 261) / 4; + return (((sym - 265) % 4 + 4) << numExtraBits) + 3 + readInt(numExtraBits); + } else if (sym == 285) + return 258; + else // sym is 286 or 287 + throw new DataFormatException("Reserved length symbol: " + sym); + } + + + // Returns the distance based on the given symbol and possibly reading more bits. + private int decodeDistance(int sym) throws IOException, DataFormatException { + if (sym < 0 || sym > 31) // Cannot occur in the bit stream; indicates the decompressor is buggy + throw new IllegalStateException("Invalid distance symbol: " + sym); + if (sym <= 3) + return sym + 1; + else if (sym <= 29) { + int numExtraBits = sym / 2 - 1; + return ((sym % 2 + 2) << numExtraBits) + 1 + readInt(numExtraBits); + } else // sym is 30 or 31 + throw new DataFormatException("Reserved distance symbol: " + sym); + } + + + /*-- Utility method --*/ + + // Reads the given number of bits from the bit input stream as a single integer, packed in little endian. + private int readInt(int numBits) throws IOException { + if (numBits < 0 || numBits > 31) + throw new IllegalArgumentException(); + int result = 0; + for (int i = 0; i < numBits; i++) + result |= input.readNoEof() << i; + return result; + } + +} diff --git a/src/net/sourceforge/plantuml/code/deflate/OutputStreamProtected.java b/src/net/sourceforge/plantuml/code/deflate/OutputStreamProtected.java new file mode 100644 index 000000000..f00ab5bae --- /dev/null +++ b/src/net/sourceforge/plantuml/code/deflate/OutputStreamProtected.java @@ -0,0 +1,38 @@ +package net.sourceforge.plantuml.code.deflate; + +import java.io.ByteArrayOutputStream; + +/* + * Simple DEFLATE decompressor + * Copyright (c) Project Nayuki + * + * https://www.nayuki.io/page/simple-deflate-decompressor + * https://github.com/nayuki/Simple-DEFLATE-decompressor + */ + +import java.io.Closeable; +import java.io.IOException; + +public class OutputStreamProtected implements Closeable { + + private final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + private int counter = 0; + + public void close() throws IOException { + baos.close(); + } + + public byte[] toByteArray() { + return baos.toByteArray(); + } + + public void write(int b) throws IOException { + this.counter++; + baos.write(b); + if (counter > 128000) { + throw new IOException("Too big"); + } + + } + +} diff --git a/src/net/sourceforge/plantuml/command/BlocLines.java b/src/net/sourceforge/plantuml/command/BlocLines.java index 1e8cea047..6fd471099 100644 --- a/src/net/sourceforge/plantuml/command/BlocLines.java +++ b/src/net/sourceforge/plantuml/command/BlocLines.java @@ -57,7 +57,13 @@ public class BlocLines implements Iterable { @Override public String toString() { - return lines.toString(); + final StringBuilder sb = new StringBuilder(); + for (StringLocated line : lines) { + sb.append("<<<"); + sb.append(line); + sb.append(">>>"); + } + return sb.toString(); } public static BlocLines load(File f, LineLocation location) throws IOException { @@ -88,7 +94,7 @@ public class BlocLines implements Iterable { return Display.createFoo(lines); } - public static BlocLines single2(StringLocated single) { + public static BlocLines single(StringLocated single) { final List result = new ArrayList(); result.add(single); return new BlocLines(result); @@ -120,7 +126,7 @@ public class BlocLines implements Iterable { this(new ArrayList()); } - public BlocLines add2(StringLocated s) { + public BlocLines add(StringLocated s) { final List copy = new ArrayList(lines); copy.add(s); return new BlocLines(copy); @@ -132,10 +138,6 @@ public class BlocLines implements Iterable { return new BlocLines(copy); } - // public List getLines() { - // return lines2; - // } - public List getLinesAsStringForSprite() { final List result = new ArrayList(); for (StringLocated s : lines) { @@ -148,43 +150,55 @@ public class BlocLines implements Iterable { return lines.size(); } - public StringLocated get499(int i) { + public StringLocated getAt(int i) { return lines.get(i); } - public StringLocated getFirst499() { + public StringLocated getFirst() { if (lines.size() == 0) { return null; } return lines.get(0); } - public StringLocated getLast499() { + public StringLocated getLast() { return lines.get(lines.size() - 1); } - public BlocLines cleanList2(MultilinesStrategy strategy) { + public BlocLines cleanList(MultilinesStrategy strategy) { final List copy = new ArrayList(lines); strategy.cleanList(copy); return new BlocLines(copy); } - public BlocLines trim(boolean removeEmptyLines) { + public BlocLines trim() { final List copy = new ArrayList(lines); for (int i = 0; i < copy.size(); i++) { final StringLocated s = copy.get(i); - copy.set(i, new StringLocated(s.getTrimmed().getString(), s.getLocation())); + copy.set(i, s.getTrimmed()); } - if (removeEmptyLines) { - for (final Iterator it = copy.iterator(); it.hasNext();) { - if (it.next().getString().length() == 0) { - it.remove(); - } + return new BlocLines(copy); + } + + public BlocLines removeEmptyLines() { + final List copy = new ArrayList(lines); + for (final Iterator it = copy.iterator(); it.hasNext();) { + if (it.next().getString().length() == 0) { + it.remove(); } } return new BlocLines(copy); } +// public BlocLines trimRight() { +// final List copy = new ArrayList(lines); +// for (int i = 0; i < copy.size(); i++) { +// final StringLocated s = copy.get(i); +// copy.set(i, s.getTrimmedRight()); +// } +// return new BlocLines(copy); +// } + public BlocLines removeEmptyColumns() { if (firstColumnRemovable(lines) == false) { return this; @@ -221,7 +235,7 @@ public class BlocLines implements Iterable { return s.getString().charAt(s.getString().length() - 1); } - public BlocLines removeStartingAndEnding2(String data) { + public BlocLines removeStartingAndEnding(String data, int removeAtEnd) { if (lines.size() == 0) { return this; } @@ -229,7 +243,18 @@ public class BlocLines implements Iterable { copy.set(0, new StringLocated(data, null)); final int n = copy.size() - 1; final StringLocated s = copy.get(n); - copy.set(n, s.substring(0, s.getString().length() - 1)); + copy.set(n, s.substring(0, s.getString().length() - removeAtEnd)); + return new BlocLines(copy); + } + + public BlocLines overrideLastLine(String last) { + if (lines.size() == 0) { + return this; + } + final List copy = new ArrayList(lines); + final int n = copy.size() - 1; + final StringLocated currentLast = copy.get(n); + copy.set(n, new StringLocated(last, currentLast.getLocation())); return new BlocLines(copy); } @@ -299,10 +324,10 @@ public class BlocLines implements Iterable { if (size() < 2) { return this; } - final String first = getFirst499().getTrimmed().getString(); - final String second = get499(1).getTrimmed().getString(); + final String first = getFirst().getTrimmed().getString(); + final String second = getAt(1).getTrimmed().getString(); if (first.endsWith("{") == false && second.equals("{")) { - final StringLocated vline = getFirst499().append(" {"); + final StringLocated vline = getFirst().append(" {"); final List result = new ArrayList(); result.add(vline); result.addAll(this.lines.subList(2, this.lines.size())); diff --git a/src/net/sourceforge/plantuml/command/CommandDecoratorMultine.java b/src/net/sourceforge/plantuml/command/CommandDecoratorMultine.java index 5571dedb6..be6f0198b 100644 --- a/src/net/sourceforge/plantuml/command/CommandDecoratorMultine.java +++ b/src/net/sourceforge/plantuml/command/CommandDecoratorMultine.java @@ -66,7 +66,7 @@ public class CommandDecoratorMultine implements Command { return CommandControl.NOT_OK; } lines = lines.toSingleLineWithHiddenNewLine(); - if (cmd.isForbidden(lines.getFirst499().getString())) { + if (cmd.isForbidden(lines.getFirst().getString())) { return CommandControl.NOT_OK; } final CommandControl tmp = cmd.isValid(lines); diff --git a/src/net/sourceforge/plantuml/command/CommandFactorySprite.java b/src/net/sourceforge/plantuml/command/CommandFactorySprite.java index 5033e9c03..b01eb3a05 100644 --- a/src/net/sourceforge/plantuml/command/CommandFactorySprite.java +++ b/src/net/sourceforge/plantuml/command/CommandFactorySprite.java @@ -82,7 +82,8 @@ public final class CommandFactorySprite implements SingleMultiFactoryCommand(getRegexConcatSingleLine()) { @Override - protected CommandExecutionResult executeArg(final WithSprite system, LineLocation location, RegexResult arg) { + protected CommandExecutionResult executeArg(final WithSprite system, LineLocation location, + RegexResult arg) { return executeInternal(system, arg, Arrays.asList((String) arg.get("DATA", 0))); } @@ -98,8 +99,8 @@ public final class CommandFactorySprite implements SingleMultiFactoryCommand strings) { - try { - final Sprite sprite; - if (line0.get("DIM", 0) == null) { - sprite = SpriteGrayLevel.GRAY_16.buildSprite(-1, -1, strings); - } else { - final int width = Integer.parseInt(line0.get("DIM", 0)); - final int height = Integer.parseInt(line0.get("DIM", 1)); - if (line0.get("DIM", 4) == null) { - final int nbLevel = Integer.parseInt(line0.get("DIM", 2)); - if (nbLevel != 4 && nbLevel != 8 && nbLevel != 16) { - return CommandExecutionResult.error("Only 4, 8 or 16 graylevel are allowed."); - } - final SpriteGrayLevel level = SpriteGrayLevel.get(nbLevel); - if (line0.get("DIM", 3) == null) { - sprite = level.buildSprite(width, height, strings); - } else { - sprite = level.buildSpriteZ(width, height, concat(strings)); - } - } else { - sprite = SpriteColorBuilder4096.buildSprite(strings); + final Sprite sprite; + if (line0.get("DIM", 0) == null) { + sprite = SpriteGrayLevel.GRAY_16.buildSprite(-1, -1, strings); + } else { + final int width = Integer.parseInt(line0.get("DIM", 0)); + final int height = Integer.parseInt(line0.get("DIM", 1)); + if (line0.get("DIM", 4) == null) { + final int nbLevel = Integer.parseInt(line0.get("DIM", 2)); + if (nbLevel != 4 && nbLevel != 8 && nbLevel != 16) { + return CommandExecutionResult.error("Only 4, 8 or 16 graylevel are allowed."); } + final SpriteGrayLevel level = SpriteGrayLevel.get(nbLevel); + if (line0.get("DIM", 3) == null) { + sprite = level.buildSprite(width, height, strings); + } else { + sprite = level.buildSpriteZ(width, height, concat(strings)); + if (sprite == null) { + return CommandExecutionResult.error("Cannot decode sprite."); + } + } + } else { + sprite = SpriteColorBuilder4096.buildSprite(strings); } - system.addSprite(line0.get("NAME", 0), sprite); - return CommandExecutionResult.ok(); - } catch (IOException e) { - return CommandExecutionResult.error("Cannot decode sprite."); } + system.addSprite(line0.get("NAME", 0), sprite); + return CommandExecutionResult.ok(); } private String concat(final List strings) { diff --git a/src/net/sourceforge/plantuml/command/CommandMultilines.java b/src/net/sourceforge/plantuml/command/CommandMultilines.java index 6f4f8eec7..a4360a451 100644 --- a/src/net/sourceforge/plantuml/command/CommandMultilines.java +++ b/src/net/sourceforge/plantuml/command/CommandMultilines.java @@ -61,7 +61,7 @@ public abstract class CommandMultilines implements Command if (isCommandForbidden()) { return CommandControl.NOT_OK; } - Matcher2 m1 = starting.matcher(lines.getFirst499().getTrimmed().getString()); + Matcher2 m1 = starting.matcher(lines.getFirst().getTrimmed().getString()); if (m1.matches() == false) { return CommandControl.NOT_OK; } @@ -69,7 +69,7 @@ public abstract class CommandMultilines implements Command return CommandControl.OK_PARTIAL; } - m1 = MyPattern.cmpile(getPatternEnd()).matcher(lines.getLast499().getTrimmed().getString()); + m1 = MyPattern.cmpile(getPatternEnd()).matcher(lines.getLast().getTrimmed().getString()); if (m1.matches() == false) { return CommandControl.OK_PARTIAL; } diff --git a/src/net/sourceforge/plantuml/command/CommandMultilines2.java b/src/net/sourceforge/plantuml/command/CommandMultilines2.java index cad3ae205..1d1af037d 100644 --- a/src/net/sourceforge/plantuml/command/CommandMultilines2.java +++ b/src/net/sourceforge/plantuml/command/CommandMultilines2.java @@ -66,13 +66,13 @@ public abstract class CommandMultilines2 implements Command implements Command implements Command implements Command implements Command implements Command implements Command implements Com if (isCommandForbidden()) { return CommandControl.NOT_OK; } - final Matcher2 m1 = starting.matcher(lines.getFirst499().getTrimmed().getString()); + final Matcher2 m1 = starting.matcher(lines.getFirst().getTrimmed().getString()); if (m1.matches() == false) { return CommandControl.NOT_OK; } diff --git a/src/net/sourceforge/plantuml/command/CommandMultilinesCaption.java b/src/net/sourceforge/plantuml/command/CommandMultilinesCaption.java new file mode 100644 index 000000000..f09c92b8b --- /dev/null +++ b/src/net/sourceforge/plantuml/command/CommandMultilinesCaption.java @@ -0,0 +1,66 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * (C) Copyright 2009-2020, Arnaud Roques + * + * Project Info: http://plantuml.com + * + * If you like this project or if you find it useful, you can support us at: + * + * http://plantuml.com/patreon (only 1$ per month!) + * http://plantuml.com/paypal + * + * This file is part of PlantUML. + * + * PlantUML is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * PlantUML distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * + * Original Author: Arnaud Roques + * + * + */ +package net.sourceforge.plantuml.command; + +import net.sourceforge.plantuml.TitledDiagram; +import net.sourceforge.plantuml.cucadiagram.Display; +import net.sourceforge.plantuml.cucadiagram.DisplayPositionned; +import net.sourceforge.plantuml.graphic.HorizontalAlignment; +import net.sourceforge.plantuml.graphic.VerticalAlignment; + +public class CommandMultilinesCaption extends CommandMultilines { + + public CommandMultilinesCaption() { + super("(?i)^caption$"); + } + + @Override + public String getPatternEnd() { + return "(?i)^end[%s]?caption$"; + } + + public CommandExecutionResult execute(final TitledDiagram diagram, BlocLines lines) { + lines = lines.subExtract(1, 1); + lines = lines.removeEmptyColumns(); + final Display strings = lines.toDisplay(); + if (strings.size() > 0) { + diagram.setCaption(DisplayPositionned.single(strings.replaceBackslashT(), HorizontalAlignment.CENTER, VerticalAlignment.BOTTOM)); + return CommandExecutionResult.ok(); + } + return CommandExecutionResult.error("No caption defined"); + } + +} diff --git a/src/net/sourceforge/plantuml/command/CommandMultilinesFooter.java b/src/net/sourceforge/plantuml/command/CommandMultilinesFooter.java index 71a4c1dcf..34d3429b6 100644 --- a/src/net/sourceforge/plantuml/command/CommandMultilinesFooter.java +++ b/src/net/sourceforge/plantuml/command/CommandMultilinesFooter.java @@ -55,8 +55,8 @@ public class CommandMultilinesFooter extends CommandMultilines { } public CommandExecutionResult execute(final TitledDiagram diagram, BlocLines lines) { - lines = lines.trim(false); - final Matcher2 m = getStartingPattern().matcher(lines.getFirst499().getTrimmed().getString()); + lines = lines.trim(); + final Matcher2 m = getStartingPattern().matcher(lines.getFirst().getTrimmed().getString()); if (m.find() == false) { throw new IllegalStateException(); } diff --git a/src/net/sourceforge/plantuml/command/CommandMultilinesHeader.java b/src/net/sourceforge/plantuml/command/CommandMultilinesHeader.java index b87374f25..be75bb43f 100644 --- a/src/net/sourceforge/plantuml/command/CommandMultilinesHeader.java +++ b/src/net/sourceforge/plantuml/command/CommandMultilinesHeader.java @@ -55,8 +55,8 @@ public class CommandMultilinesHeader extends CommandMultilines { } public CommandExecutionResult execute(final TitledDiagram diagram, BlocLines lines) { - lines = lines.trim(false); - final Matcher2 m = getStartingPattern().matcher(lines.getFirst499().getTrimmed().getString()); + lines = lines.trim(); + final Matcher2 m = getStartingPattern().matcher(lines.getFirst().getTrimmed().getString()); if (m.find() == false) { throw new IllegalStateException(); } diff --git a/src/net/sourceforge/plantuml/command/CommandMultilinesLegend.java b/src/net/sourceforge/plantuml/command/CommandMultilinesLegend.java index 86510af03..ea73cc711 100644 --- a/src/net/sourceforge/plantuml/command/CommandMultilinesLegend.java +++ b/src/net/sourceforge/plantuml/command/CommandMultilinesLegend.java @@ -75,7 +75,7 @@ public class CommandMultilinesLegend extends CommandMultilines2 { @Override protected CommandExecutionResult executeNow(TitledDiagram diagram, BlocLines lines) { lines = lines.trimSmart(1); - final RegexResult line0 = getStartingPattern().matcher(lines.getFirst499().getTrimmed().getString()); + final RegexResult line0 = getStartingPattern().matcher(lines.getFirst().getTrimmed().getString()); final String align = line0.get("ALIGN", 0); final String valign = line0.get("VALIGN", 0); lines = lines.subExtract(1, 1); diff --git a/src/net/sourceforge/plantuml/command/CommandSkinParamMultilines.java b/src/net/sourceforge/plantuml/command/CommandSkinParamMultilines.java index 4f57e90c8..53746101d 100644 --- a/src/net/sourceforge/plantuml/command/CommandSkinParamMultilines.java +++ b/src/net/sourceforge/plantuml/command/CommandSkinParamMultilines.java @@ -63,7 +63,7 @@ public class CommandSkinParamMultilines extends CommandMultilinesBracket implements Command implements Command implements Command 0; diff --git a/src/net/sourceforge/plantuml/command/UmlDiagramFactory.java b/src/net/sourceforge/plantuml/command/UmlDiagramFactory.java index ca71732b6..6d52f7cfd 100644 --- a/src/net/sourceforge/plantuml/command/UmlDiagramFactory.java +++ b/src/net/sourceforge/plantuml/command/UmlDiagramFactory.java @@ -128,7 +128,7 @@ public abstract class UmlDiagramFactory extends PSystemAbstractFactory { final CommandExecutionResult result = sys.executeCommand(step.command, step.blocLines); if (result.isOk() == false) { final ErrorUml err = new ErrorUml(ErrorUmlType.EXECUTION_ERROR, result.getError(), - ((StringLocated) step.blocLines.getFirst499()).getLocation()); + ((StringLocated) step.blocLines.getFirst()).getLocation()); sys = PSystemErrorUtils.buildV2(source, err, result.getDebugLines(), it.getTrace()); } if (result.getNewDiagram() != null) { @@ -150,7 +150,7 @@ public abstract class UmlDiagramFactory extends PSystemAbstractFactory { } private Step getCandidate(final IteratorCounter2 it) { - final BlocLines single = BlocLines.single2(it.peek()); + final BlocLines single = BlocLines.single(it.peek()); if (cmds == null) { cmds = createCommands(); } @@ -196,11 +196,11 @@ public abstract class UmlDiagramFactory extends PSystemAbstractFactory { private BlocLines addOneSingleLineManageEmbedded2(IteratorCounter2 it, BlocLines lines) { final StringLocated linetoBeAdded = it.next(); - lines = lines.add2(linetoBeAdded); + lines = lines.add(linetoBeAdded); if (linetoBeAdded.getTrimmed().getString().equals("{{")) { while (it.hasNext()) { final StringLocated s = it.next(); - lines = lines.add2(s); + lines = lines.add(s); if (s.getTrimmed().getString().equals("}}")) { return lines; } @@ -258,6 +258,7 @@ public abstract class UmlDiagramFactory extends PSystemAbstractFactory { cmds.add(new CommandTitle()); cmds.add(new CommandMainframe()); cmds.add(new CommandCaption()); + cmds.add(new CommandMultilinesCaption()); cmds.add(new CommandMultilinesTitle()); cmds.add(new CommandMultilinesLegend()); diff --git a/src/net/sourceforge/plantuml/command/note/CommandFactoryNote.java b/src/net/sourceforge/plantuml/command/note/CommandFactoryNote.java index 8dea9a73f..7b025b85f 100644 --- a/src/net/sourceforge/plantuml/command/note/CommandFactoryNote.java +++ b/src/net/sourceforge/plantuml/command/note/CommandFactoryNote.java @@ -117,7 +117,7 @@ public final class CommandFactoryNote implements SingleMultiFactoryCommand{2})?"), // + RegexLeaf.spaceZeroOrMore(), // new RegexLeaf("TAGS", Stereotag.pattern() + "?"), // RegexLeaf.spaceZeroOrMore(), // color().getRegex(), // @@ -99,7 +104,7 @@ public final class CommandFactoryNoteOnEntity implements SingleMultiFactoryComma RegexLeaf.spaceZeroOrMore(), // new RegexLeaf("NOTE", "(.*)"), // RegexLeaf.end() // - ); + ); } private static ColorParser color() { @@ -120,6 +125,8 @@ public final class CommandFactoryNoteOnEntity implements SingleMultiFactoryComma partialPattern), // new RegexLeaf("")), // RegexLeaf.spaceZeroOrMore(), // + new RegexLeaf("STEREO", "(\\<{2}.*\\>{2})?"), // + RegexLeaf.spaceZeroOrMore(), // new RegexLeaf("TAGS", Stereotag.pattern() + "?"), // RegexLeaf.spaceZeroOrMore(), // color().getRegex(), // @@ -128,7 +135,7 @@ public final class CommandFactoryNoteOnEntity implements SingleMultiFactoryComma RegexLeaf.spaceZeroOrMore(), // new RegexLeaf("\\{"), // RegexLeaf.end() // - ); + ); } return RegexConcat.build(CommandFactoryNoteOnEntity.class.getName() + key + "multi" + withBracket, RegexLeaf.start(), // @@ -142,13 +149,15 @@ public final class CommandFactoryNoteOnEntity implements SingleMultiFactoryComma partialPattern), // new RegexLeaf("")), // RegexLeaf.spaceZeroOrMore(), // + new RegexLeaf("STEREO", "(\\<{2}.*\\>{2})?"), // + RegexLeaf.spaceZeroOrMore(), // new RegexLeaf("TAGS", Stereotag.pattern() + "?"), // RegexLeaf.spaceZeroOrMore(), // color().getRegex(), // RegexLeaf.spaceZeroOrMore(), // new RegexLeaf("URL", "(" + UrlBuilder.getRegexp() + ")?"), // RegexLeaf.end() // - ); + ); } public Command createSingleLine() { @@ -177,7 +186,7 @@ public final class CommandFactoryNoteOnEntity implements SingleMultiFactoryComma protected CommandExecutionResult executeNow(final AbstractEntityDiagram system, BlocLines lines) { // StringUtils.trim(lines, false); - final RegexResult line0 = getStartingPattern().matcher(lines.getFirst499().getTrimmed().getString()); + final RegexResult line0 = getStartingPattern().matcher(lines.getFirst().getTrimmed().getString()); lines = lines.subExtract(1, 1); lines = lines.removeEmptyColumns(); @@ -226,15 +235,24 @@ public final class CommandFactoryNoteOnEntity implements SingleMultiFactoryComma else note = diagram.createLeaf(idNewLong, diagram.buildCode(tmp), strings.toDisplay(), LeafType.NOTE, null); - final Colors colors = color().getColor(line0, diagram.getSkinParam().getIHtmlColorSet()); + Colors colors = color().getColor(line0, diagram.getSkinParam().getIHtmlColorSet()); + + final String stereotypeString = line0.get("STEREO", 0); + if (stereotypeString != null) { + final Stereotype stereotype = new Stereotype(stereotypeString); + colors = colors.applyStereotypeForNote(stereotype, diagram.getSkinParam(), FontParam.NOTE, + ColorParam.noteBackground, ColorParam.noteBorder); + note.setStereotype(stereotype); + } + note.setColors(colors); if (url != null) { note.addUrl(url); } CommandCreateClassMultilines.addTags(note, line0.get("TAGS", 0)); - final Position position = Position.valueOf(StringUtils.goUpperCase(pos)).withRankdir( - diagram.getSkinParam().getRankdir()); + final Position position = Position.valueOf(StringUtils.goUpperCase(pos)) + .withRankdir(diagram.getSkinParam().getRankdir()); final Link link; final LinkType type = new LinkType(LinkDecor.NONE, LinkDecor.NONE).goDashed(); diff --git a/src/net/sourceforge/plantuml/command/note/CommandFactoryNoteOnLink.java b/src/net/sourceforge/plantuml/command/note/CommandFactoryNoteOnLink.java index 43e1462bf..fb7bd7ffa 100644 --- a/src/net/sourceforge/plantuml/command/note/CommandFactoryNoteOnLink.java +++ b/src/net/sourceforge/plantuml/command/note/CommandFactoryNoteOnLink.java @@ -102,7 +102,7 @@ public final class CommandFactoryNoteOnLink implements SingleMultiFactoryCommand } protected CommandExecutionResult executeNow(final CucaDiagram system, BlocLines lines) { - final String line0 = lines.getFirst499().getTrimmed().getString(); + final String line0 = lines.getFirst().getTrimmed().getString(); lines = lines.subExtract(1, 1); lines = lines.removeEmptyColumns(); if (lines.size() > 0) { diff --git a/src/net/sourceforge/plantuml/command/note/CommandFactoryTipOnEntity.java b/src/net/sourceforge/plantuml/command/note/CommandFactoryTipOnEntity.java index 7c8e9ba28..3f0ba0b31 100644 --- a/src/net/sourceforge/plantuml/command/note/CommandFactoryTipOnEntity.java +++ b/src/net/sourceforge/plantuml/command/note/CommandFactoryTipOnEntity.java @@ -123,7 +123,7 @@ public final class CommandFactoryTipOnEntity implements SingleMultiFactoryComman protected CommandExecutionResult executeNow(final AbstractEntityDiagram system, BlocLines lines) { // StringUtils.trim(lines, false); - final RegexResult line0 = getStartingPattern().matcher(lines.getFirst499().getTrimmed().getString()); + final RegexResult line0 = getStartingPattern().matcher(lines.getFirst().getTrimmed().getString()); lines = lines.subExtract(1, 1); lines = lines.removeEmptyColumns(); diff --git a/src/net/sourceforge/plantuml/command/note/sequence/FactorySequenceNoteAcrossCommand.java b/src/net/sourceforge/plantuml/command/note/sequence/FactorySequenceNoteAcrossCommand.java index 3d678ffcd..692c400f9 100644 --- a/src/net/sourceforge/plantuml/command/note/sequence/FactorySequenceNoteAcrossCommand.java +++ b/src/net/sourceforge/plantuml/command/note/sequence/FactorySequenceNoteAcrossCommand.java @@ -127,7 +127,7 @@ public final class FactorySequenceNoteAcrossCommand implements SingleMultiFactor } protected CommandExecutionResult executeNow(final SequenceDiagram system, BlocLines lines) { - final RegexResult line0 = getStartingPattern().matcher(lines.getFirst499().getTrimmed().getString()); + final RegexResult line0 = getStartingPattern().matcher(lines.getFirst().getTrimmed().getString()); lines = lines.subExtract(1, 1); lines = lines.removeEmptyColumns(); return executeInternal(system, line0, lines); diff --git a/src/net/sourceforge/plantuml/command/note/sequence/FactorySequenceNoteCommand.java b/src/net/sourceforge/plantuml/command/note/sequence/FactorySequenceNoteCommand.java index 85456cf2d..e3f83aac5 100644 --- a/src/net/sourceforge/plantuml/command/note/sequence/FactorySequenceNoteCommand.java +++ b/src/net/sourceforge/plantuml/command/note/sequence/FactorySequenceNoteCommand.java @@ -120,7 +120,7 @@ public final class FactorySequenceNoteCommand implements SingleMultiFactoryComma } protected CommandExecutionResult executeNow(final SequenceDiagram system, BlocLines lines) { - final RegexResult line0 = getStartingPattern().matcher(lines.getFirst499().getTrimmed().getString()); + final RegexResult line0 = getStartingPattern().matcher(lines.getFirst().getTrimmed().getString()); lines = lines.subExtract(1, 1); lines = lines.removeEmptyColumns(); return executeInternal(system, line0, lines); diff --git a/src/net/sourceforge/plantuml/command/note/sequence/FactorySequenceNoteOnArrowCommand.java b/src/net/sourceforge/plantuml/command/note/sequence/FactorySequenceNoteOnArrowCommand.java index c00f6fcce..019a72eb1 100644 --- a/src/net/sourceforge/plantuml/command/note/sequence/FactorySequenceNoteOnArrowCommand.java +++ b/src/net/sourceforge/plantuml/command/note/sequence/FactorySequenceNoteOnArrowCommand.java @@ -123,7 +123,7 @@ public final class FactorySequenceNoteOnArrowCommand implements SingleMultiFacto } protected CommandExecutionResult executeNow(final SequenceDiagram diagram, BlocLines lines) { - final RegexResult line0 = getStartingPattern().matcher(lines.getFirst499().getTrimmed().getString()); + final RegexResult line0 = getStartingPattern().matcher(lines.getFirst().getTrimmed().getString()); lines = lines.subExtract(1, 1); lines = lines.removeEmptyColumns(); return executeInternal(diagram, line0, lines); diff --git a/src/net/sourceforge/plantuml/command/note/sequence/FactorySequenceNoteOverSeveralCommand.java b/src/net/sourceforge/plantuml/command/note/sequence/FactorySequenceNoteOverSeveralCommand.java index 32cd5c2f7..d7b0f3e46 100644 --- a/src/net/sourceforge/plantuml/command/note/sequence/FactorySequenceNoteOverSeveralCommand.java +++ b/src/net/sourceforge/plantuml/command/note/sequence/FactorySequenceNoteOverSeveralCommand.java @@ -142,7 +142,7 @@ public final class FactorySequenceNoteOverSeveralCommand implements SingleMultiF } protected CommandExecutionResult executeNow(final SequenceDiagram system, BlocLines lines) { - final RegexResult line0 = getStartingPattern().matcher(lines.getFirst499().getTrimmed().getString()); + final RegexResult line0 = getStartingPattern().matcher(lines.getFirst().getTrimmed().getString()); lines = lines.subExtract(1, 1); lines = lines.removeEmptyColumns(); return executeInternal(system, line0, lines); diff --git a/src/net/sourceforge/plantuml/creole/PSystemCreole.java b/src/net/sourceforge/plantuml/creole/PSystemCreole.java index fbc3aaef8..887bfc512 100644 --- a/src/net/sourceforge/plantuml/creole/PSystemCreole.java +++ b/src/net/sourceforge/plantuml/creole/PSystemCreole.java @@ -79,8 +79,8 @@ public class PSystemCreole extends AbstractPSystem { .createSheet(display); final SheetBlock1 sheetBlock = new SheetBlock1(sheet, LineBreakStrategy.NONE, 0); - final ImageBuilder builder = new ImageBuilder(new ColorMapperIdentity(), 1.0, null, null, null, 0, 0, null, - false); + final ImageBuilder builder = ImageBuilder.buildA(new ColorMapperIdentity(), false, null, null, null, 1.0, + null); builder.setUDrawable(sheetBlock); return builder.writeImageTOBEMOVED(fileFormat, seed, os); diff --git a/src/net/sourceforge/plantuml/creole/SheetBlock2.java b/src/net/sourceforge/plantuml/creole/SheetBlock2.java index 779519a69..a14c0d577 100644 --- a/src/net/sourceforge/plantuml/creole/SheetBlock2.java +++ b/src/net/sourceforge/plantuml/creole/SheetBlock2.java @@ -58,15 +58,15 @@ public class SheetBlock2 extends AbstractTextBlock implements TextBlock, Atom { private final UStroke defaultStroke; private final Stencil stencil; - public SheetBlock2 enlargeMe(final double delta) { + public SheetBlock2 enlargeMe(final double delta1, final double delta2) { final Stencil newStencil = new Stencil() { public double getStartingX(StringBounder stringBounder, double y) { - return stencil.getStartingX(stringBounder, y) - delta; + return stencil.getStartingX(stringBounder, y) - delta1; } public double getEndingX(StringBounder stringBounder, double y) { - return stencil.getEndingX(stringBounder, y) + delta; + return stencil.getEndingX(stringBounder, y) + delta2; } }; return new SheetBlock2(block, newStencil, defaultStroke); diff --git a/src/net/sourceforge/plantuml/cucadiagram/EntityPosition.java b/src/net/sourceforge/plantuml/cucadiagram/EntityPosition.java index 01ebf4c9a..e2efb8665 100644 --- a/src/net/sourceforge/plantuml/cucadiagram/EntityPosition.java +++ b/src/net/sourceforge/plantuml/cucadiagram/EntityPosition.java @@ -30,6 +30,7 @@ * * * Original Author: Arnaud Roques + * Contribution : Hisashi Miyashita * * */ @@ -50,7 +51,7 @@ import net.sourceforge.plantuml.ugraphic.UTranslate; public enum EntityPosition { - NORMAL, ENTRY_POINT, EXIT_POINT, INPUT_PIN, OUTPUT_PIN, EXPANSION_INPUT, EXPANSION_OUTPUT; + NORMAL, ENTRY_POINT, EXIT_POINT, INPUT_PIN, OUTPUT_PIN, EXPANSION_INPUT, EXPANSION_OUTPUT, PORT, PORTIN, PORTOUT; public static final double RADIUS = 6; @@ -69,7 +70,7 @@ public enum EntityPosition { drawLine(ug, getPointOnCircle(xc, yc, -Math.PI / 4, radius), getPointOnCircle(xc, yc, Math.PI - Math.PI / 4, radius)); } - } else if (this == INPUT_PIN || this == OUTPUT_PIN) { + } else if (this == INPUT_PIN || this == OUTPUT_PIN || this == PORT) { final Shadowable rectangle = new URectangle(RADIUS * 2, RADIUS * 2); ug.draw(rectangle); } else if (this == EXPANSION_INPUT || this == EXPANSION_OUTPUT) { @@ -126,6 +127,9 @@ public enum EntityPosition { } public static EntityPosition fromStereotype(String label) { + if ("<>".equalsIgnoreCase(label)) { + return PORT; + } if ("<>".equalsIgnoreCase(label)) { return ENTRY_POINT; } @@ -148,11 +152,19 @@ public enum EntityPosition { } public static EnumSet getInputs() { - return EnumSet.of(ENTRY_POINT, INPUT_PIN, EXPANSION_INPUT); + return EnumSet.of(ENTRY_POINT, INPUT_PIN, EXPANSION_INPUT, PORTIN); } public static EnumSet getOutputs() { - return EnumSet.of(EXIT_POINT, OUTPUT_PIN, EXPANSION_OUTPUT); + return EnumSet.of(EXIT_POINT, OUTPUT_PIN, EXPANSION_OUTPUT, PORTOUT); + } + + public static EnumSet getSame() { + return EnumSet.of(PORT); + } + + public boolean isPort() { + return this == PORT || this == PORTIN || this == PORTOUT; } } diff --git a/src/net/sourceforge/plantuml/cucadiagram/LeafType.java b/src/net/sourceforge/plantuml/cucadiagram/LeafType.java index f37e10ff4..b5c9848f5 100644 --- a/src/net/sourceforge/plantuml/cucadiagram/LeafType.java +++ b/src/net/sourceforge/plantuml/cucadiagram/LeafType.java @@ -30,7 +30,7 @@ * * * Original Author: Arnaud Roques - * + * Contribution : Hisashi Miyashita * */ package net.sourceforge.plantuml.cucadiagram; @@ -56,6 +56,8 @@ public enum LeafType { BLOCK, ENTITY, DOMAIN, REQUIREMENT, + + PORT, PORTIN, PORTOUT, STILL_UNKNOWN; diff --git a/src/net/sourceforge/plantuml/cucadiagram/LinkDecor.java b/src/net/sourceforge/plantuml/cucadiagram/LinkDecor.java index 65ff0ab60..d6fa7b5a5 100644 --- a/src/net/sourceforge/plantuml/cucadiagram/LinkDecor.java +++ b/src/net/sourceforge/plantuml/cucadiagram/LinkDecor.java @@ -30,6 +30,7 @@ * * * Original Author: Arnaud Roques + * Contribution : Hisashi Miyashita * * */ @@ -47,6 +48,7 @@ import net.sourceforge.plantuml.svek.extremity.ExtremityFactoryCircleLine; import net.sourceforge.plantuml.svek.extremity.ExtremityFactoryCrowfoot; import net.sourceforge.plantuml.svek.extremity.ExtremityFactoryDiamond; import net.sourceforge.plantuml.svek.extremity.ExtremityFactoryDoubleLine; +import net.sourceforge.plantuml.svek.extremity.ExtremityFactoryExtendsLike; import net.sourceforge.plantuml.svek.extremity.ExtremityFactoryHalfArrow; import net.sourceforge.plantuml.svek.extremity.ExtremityFactoryLineCrowfoot; import net.sourceforge.plantuml.svek.extremity.ExtremityFactoryNotNavigable; @@ -61,6 +63,8 @@ public enum LinkDecor { NONE(2, false, 0), EXTENDS(30, false, 2), COMPOSITION(15, true, 1.3), AGREGATION(15, false, 1.3), NOT_NAVIGABLE(1, false, 0.5), + REDEFINES(30, false, 2), DEFINEDBY(30, false, 2), + CROWFOOT(10, true, 0.8), CIRCLE_CROWFOOT(14, false, 0.8), CIRCLE_LINE(10, false, 0.8), DOUBLE_LINE(7, false, 0.7), LINE_CROWFOOT(10, false, 0.8), @@ -93,48 +97,56 @@ public enum LinkDecor { return arrowSize; } - public ExtremityFactory getExtremityFactory(HColor backgroundColor) { - if (this == LinkDecor.PLUS) { - return new ExtremityFactoryPlus(); - } else if (this == LinkDecor.HALF_ARROW) { - return new ExtremityFactoryHalfArrow(); - } else if (this == LinkDecor.ARROW_TRIANGLE) { - return new ExtremityFactoryTriangle(); - } else if (this == LinkDecor.CROWFOOT) { - return new ExtremityFactoryCrowfoot(); - } else if (this == LinkDecor.CIRCLE_CROWFOOT) { - return new ExtremityFactoryCircleCrowfoot(); - } else if (this == LinkDecor.LINE_CROWFOOT) { - return new ExtremityFactoryLineCrowfoot(); - } else if (this == LinkDecor.CIRCLE_LINE) { - return new ExtremityFactoryCircleLine(); - } else if (this == LinkDecor.DOUBLE_LINE) { - return new ExtremityFactoryDoubleLine(); - } else if (this == LinkDecor.CIRCLE_CROSS) { - return new ExtremityFactoryCircleCross(); - } else if (this == LinkDecor.ARROW) { - return new ExtremityFactoryArrow(); - } else if (this == LinkDecor.ARROW_AND_CIRCLE) { - return new ExtremityFactoryArrowAndCircle(); - } else if (this == LinkDecor.NOT_NAVIGABLE) { - return new ExtremityFactoryNotNavigable(); - } else if (this == LinkDecor.AGREGATION) { - return new ExtremityFactoryDiamond(false, backgroundColor); - } else if (this == LinkDecor.COMPOSITION) { - return new ExtremityFactoryDiamond(true, backgroundColor); - } else if (this == LinkDecor.CIRCLE) { - return new ExtremityFactoryCircle(false); - } else if (this == LinkDecor.CIRCLE_FILL) { - return new ExtremityFactoryCircle(true); - } else if (this == LinkDecor.SQUARE) { - return new ExtremityFactorySquarre(); - } else if (this == LinkDecor.PARENTHESIS) { - return new ExtremityFactoryParenthesis(); - } else if (this == LinkDecor.CIRCLE_CONNECT) { - return new ExtremityFactoryCircleConnect(); - } - - return null; + public boolean isExtendsLike() { + return this == EXTENDS || this == REDEFINES || this == DEFINEDBY; } + public ExtremityFactory getExtremityFactory(HColor backgroundColor) { + switch (this) { + case PLUS: + return new ExtremityFactoryPlus(); + case REDEFINES: + return new ExtremityFactoryExtendsLike(backgroundColor, false); + case DEFINEDBY: + return new ExtremityFactoryExtendsLike(backgroundColor, true); + case HALF_ARROW: + return new ExtremityFactoryHalfArrow(); + case ARROW_TRIANGLE: + return new ExtremityFactoryTriangle(); + case CROWFOOT: + return new ExtremityFactoryCrowfoot(); + case CIRCLE_CROWFOOT: + return new ExtremityFactoryCircleCrowfoot(); + case LINE_CROWFOOT: + return new ExtremityFactoryLineCrowfoot(); + case CIRCLE_LINE: + return new ExtremityFactoryCircleLine(); + case DOUBLE_LINE: + return new ExtremityFactoryDoubleLine(); + case CIRCLE_CROSS: + return new ExtremityFactoryCircleCross(); + case ARROW: + return new ExtremityFactoryArrow(); + case ARROW_AND_CIRCLE: + return new ExtremityFactoryArrowAndCircle(); + case NOT_NAVIGABLE: + return new ExtremityFactoryNotNavigable(); + case AGREGATION: + return new ExtremityFactoryDiamond(false, backgroundColor); + case COMPOSITION: + return new ExtremityFactoryDiamond(true, backgroundColor); + case CIRCLE: + return new ExtremityFactoryCircle(false); + case CIRCLE_FILL: + return new ExtremityFactoryCircle(true); + case SQUARE: + return new ExtremityFactorySquarre(); + case PARENTHESIS: + return new ExtremityFactoryParenthesis(); + case CIRCLE_CONNECT: + return new ExtremityFactoryCircleConnect(); + default: + return null; + } + } } diff --git a/src/net/sourceforge/plantuml/cucadiagram/LinkType.java b/src/net/sourceforge/plantuml/cucadiagram/LinkType.java index 2351f1459..57c038623 100644 --- a/src/net/sourceforge/plantuml/cucadiagram/LinkType.java +++ b/src/net/sourceforge/plantuml/cucadiagram/LinkType.java @@ -30,6 +30,7 @@ * * * Original Author: Arnaud Roques + * Contribution : Hisashi Miyashita * * */ @@ -204,8 +205,13 @@ public class LinkType { return decor2; } - public boolean isExtendsOrAggregationOrCompositionOrPlus() { - return isExtends() || isAggregationOrComposition() || isPlus(); + private boolean isExtendsOrAggregationOrCompositionOrPlus() { + return isExtends() || isAggregationOrComposition() || isPlus() || isOf(LinkDecor.DEFINEDBY) + || isOf(LinkDecor.REDEFINES); + } + + private boolean isOf(LinkDecor ld) { + return decor1 == ld || decor2 == ld; } private boolean isExtends() { diff --git a/src/net/sourceforge/plantuml/cucadiagram/MethodsOrFieldsArea.java b/src/net/sourceforge/plantuml/cucadiagram/MethodsOrFieldsArea.java index 3a1a21978..565a71200 100644 --- a/src/net/sourceforge/plantuml/cucadiagram/MethodsOrFieldsArea.java +++ b/src/net/sourceforge/plantuml/cucadiagram/MethodsOrFieldsArea.java @@ -44,6 +44,7 @@ import java.util.Map; import net.sourceforge.plantuml.Dimension2DDouble; import net.sourceforge.plantuml.FontParam; import net.sourceforge.plantuml.ISkinParam; +import net.sourceforge.plantuml.SkinParam; import net.sourceforge.plantuml.Url; import net.sourceforge.plantuml.creole.CreoleMode; import net.sourceforge.plantuml.graphic.AbstractTextBlock; @@ -58,6 +59,9 @@ import net.sourceforge.plantuml.graphic.TextBlockWidth; import net.sourceforge.plantuml.graphic.TextBlockWithUrl; import net.sourceforge.plantuml.skin.VisibilityModifier; import net.sourceforge.plantuml.skin.rose.Rose; +import net.sourceforge.plantuml.style.SName; +import net.sourceforge.plantuml.style.Style; +import net.sourceforge.plantuml.style.StyleSignature; import net.sourceforge.plantuml.svek.Ports; import net.sourceforge.plantuml.svek.WithPorts; import net.sourceforge.plantuml.ugraphic.PlacementStrategy; @@ -77,9 +81,9 @@ public class MethodsOrFieldsArea extends AbstractTextBlock implements TextBlockW private final FontParam fontParam; private final ISkinParam skinParam; - private final HColor color; - private final HColor hyperlinkColor; - private final boolean useUnderlineForHyperlink; +// private final HColor color; +// private final HColor hyperlinkColor; +// private final boolean useUnderlineForHyperlink; private final Rose rose = new Rose(); private final List members = new ArrayList(); private final HorizontalAlignment align; @@ -98,9 +102,9 @@ public class MethodsOrFieldsArea extends AbstractTextBlock implements TextBlockW this.align = align; this.skinParam = skinParam; this.fontParam = fontParam; - this.color = rose.getFontColor(skinParam, fontParam); - this.hyperlinkColor = skinParam.getHyperlinkColor(); - this.useUnderlineForHyperlink = skinParam.useUnderlineForHyperlink(); +// this.color = rose.getFontColor(skinParam, fontParam); +// this.hyperlinkColor = skinParam.getHyperlinkColor(); +// this.useUnderlineForHyperlink = skinParam.useUnderlineForHyperlink(); this.members.addAll(members); } @@ -159,13 +163,21 @@ public class MethodsOrFieldsArea extends AbstractTextBlock implements TextBlockW if (withVisibilityChar && s.startsWith("#")) { s = CharHidder.addTileAtBegin(s); } - FontConfiguration config = new FontConfiguration(skinParam, fontParam, stereotype); + FontConfiguration config; + if (SkinParam.USE_STYLES()) { + final Style style = StyleSignature.of(SName.root, SName.element, SName.componentDiagram, SName.component) + .getMergedStyle(skinParam.getCurrentStyleBuilder()); + config = new FontConfiguration(style, skinParam, stereotype, fontParam); + } else { + config = new FontConfiguration(skinParam, fontParam, stereotype); + } if (m.isAbstract()) { config = config.italic(); } if (m.isStatic()) { config = config.underline(); } + TextBlock bloc = Display.getWithNewlines(s).create8(config, align, skinParam, CreoleMode.SIMPLE_LINE, skinParam.wrapWidth()); bloc = TextBlockUtils.fullInnerPosition(bloc, m.getDisplay(false)); @@ -210,9 +222,10 @@ public class MethodsOrFieldsArea extends AbstractTextBlock implements TextBlockW public void drawU(UGraphic ug) { } - + @Override - public Rectangle2D getInnerPosition(String member, StringBounder stringBounder, InnerStrategy strategy) { + public Rectangle2D getInnerPosition(String member, StringBounder stringBounder, + InnerStrategy strategy) { return null; } @@ -221,8 +234,8 @@ public class MethodsOrFieldsArea extends AbstractTextBlock implements TextBlockW } }; } - final HColor back = modifier.getBackground() == null ? null : rose.getHtmlColor(skinParam, - modifier.getBackground()); + final HColor back = modifier.getBackground() == null ? null + : rose.getHtmlColor(skinParam, modifier.getBackground()); final HColor fore = rose.getHtmlColor(skinParam, modifier.getForeground()); final TextBlock uBlock = modifier.getUBlock(skinParam.classAttributeIconSize(), fore, back, url != null); @@ -252,8 +265,8 @@ public class MethodsOrFieldsArea extends AbstractTextBlock implements TextBlockW private ULayoutGroup getLayout(final StringBounder stringBounder) { final ULayoutGroup group; if (hasSmallIcon()) { - group = new ULayoutGroup(new PlacementStrategyVisibility(stringBounder, - skinParam.getCircledCharacterRadius() + 3)); + group = new ULayoutGroup( + new PlacementStrategyVisibility(stringBounder, skinParam.getCircledCharacterRadius() + 3)); for (Member att : members) { final TextBlock bloc = createTextBlock(att); final VisibilityModifier modifier = att.getVisibilityModifier(); diff --git a/src/net/sourceforge/plantuml/cucadiagram/dot/DotData.java b/src/net/sourceforge/plantuml/cucadiagram/dot/DotData.java index 261dce13d..07f786774 100644 --- a/src/net/sourceforge/plantuml/cucadiagram/dot/DotData.java +++ b/src/net/sourceforge/plantuml/cucadiagram/dot/DotData.java @@ -175,7 +175,7 @@ final public class DotData implements PortionShower { public void removeIrrelevantSametail() { final Map sametails = new HashMap(); for (Link link : links) { - if (link.getType().getDecor2() == LinkDecor.EXTENDS) { + if (link.getType().getDecor2().isExtendsLike()) { link.setSametail(link.getEntity1().getUid()); } final String sametail = link.getSametail(); diff --git a/src/net/sourceforge/plantuml/cucadiagram/entity/EntityImpl.java b/src/net/sourceforge/plantuml/cucadiagram/entity/EntityImpl.java index d79d57ffa..f65174869 100644 --- a/src/net/sourceforge/plantuml/cucadiagram/entity/EntityImpl.java +++ b/src/net/sourceforge/plantuml/cucadiagram/entity/EntityImpl.java @@ -30,7 +30,7 @@ * * * Original Author: Arnaud Roques - * + * Contribution : Hisashi Miyashita * * */ package net.sourceforge.plantuml.cucadiagram.entity; @@ -335,6 +335,15 @@ final public class EntityImpl implements ILeaf, IGroup { public EntityPosition getEntityPosition() { checkNotGroup(); + if (leafType == LeafType.PORT) { + return EntityPosition.PORT; + } + if (leafType == LeafType.PORTIN) { + return EntityPosition.PORTIN; + } + if (leafType == LeafType.PORTOUT) { + return EntityPosition.PORTOUT; + } if (leafType != LeafType.STATE) { return EntityPosition.NORMAL; } diff --git a/src/net/sourceforge/plantuml/cute/PSystemCute.java b/src/net/sourceforge/plantuml/cute/PSystemCute.java index a8d04fddb..6a737491c 100644 --- a/src/net/sourceforge/plantuml/cute/PSystemCute.java +++ b/src/net/sourceforge/plantuml/cute/PSystemCute.java @@ -41,9 +41,11 @@ import java.util.StringTokenizer; import net.sourceforge.plantuml.AbstractPSystem; import net.sourceforge.plantuml.FileFormatOption; +import net.sourceforge.plantuml.SkinParam; import net.sourceforge.plantuml.StringUtils; import net.sourceforge.plantuml.core.DiagramDescription; import net.sourceforge.plantuml.core.ImageData; +import net.sourceforge.plantuml.style.ClockwiseTopRightBottomLeft; import net.sourceforge.plantuml.ugraphic.ImageBuilder; import net.sourceforge.plantuml.ugraphic.color.ColorMapperIdentity; @@ -86,8 +88,17 @@ public class PSystemCute extends AbstractPSystem { @Override final protected ImageData exportDiagramNow(OutputStream os, int num, FileFormatOption fileFormat, long seed) throws IOException { - final ImageBuilder builder = new ImageBuilder(new ColorMapperIdentity(), 1.0, null, null, null, 10, 10, null, - false); + final int margin1; + final int margin2; + if (SkinParam.USE_STYLES()) { + margin1 = SkinParam.zeroMargin(10); + margin2 = SkinParam.zeroMargin(10); + } else { + margin1 = 10; + margin2 = 10; + } + final ImageBuilder builder = ImageBuilder.buildB(new ColorMapperIdentity(), false, ClockwiseTopRightBottomLeft.margin1margin2((double) margin1, (double) margin2), + null, null, null, 1.0, null); builder.setUDrawable(root); return builder.writeImageTOBEMOVED(fileFormat, seed, os); } diff --git a/src/net/sourceforge/plantuml/dedication/PSystemDedication.java b/src/net/sourceforge/plantuml/dedication/PSystemDedication.java index bc9cd7301..40d9f8f7d 100644 --- a/src/net/sourceforge/plantuml/dedication/PSystemDedication.java +++ b/src/net/sourceforge/plantuml/dedication/PSystemDedication.java @@ -63,8 +63,8 @@ public class PSystemDedication extends AbstractPSystem { @Override final protected ImageData exportDiagramNow(OutputStream os, int num, FileFormatOption fileFormat, long seed) throws IOException { - final ImageBuilder imageBuilder = new ImageBuilder(new ColorMapperIdentity(), 1.0, HColorUtils.WHITE, - getMetadata(), null, 0, 0, null, false); + final ImageBuilder imageBuilder = ImageBuilder.buildA(new ColorMapperIdentity(), + false, null, getMetadata(), null, 1.0, HColorUtils.WHITE); imageBuilder.setUDrawable(new UDrawable() { public void drawU(UGraphic ug) { final BufferedImage bufferedImage = dedication.getBufferedImage(keepLetter); diff --git a/src/net/sourceforge/plantuml/definition/PSystemDefinition.java b/src/net/sourceforge/plantuml/definition/PSystemDefinition.java index 6562f4fb9..16fc0e27d 100644 --- a/src/net/sourceforge/plantuml/definition/PSystemDefinition.java +++ b/src/net/sourceforge/plantuml/definition/PSystemDefinition.java @@ -71,8 +71,8 @@ public class PSystemDefinition extends AbstractPSystem implements UDrawable { @Override final protected ImageData exportDiagramNow(OutputStream os, int num, FileFormatOption fileFormatOption, long seed) throws IOException { - final ImageBuilder imageBuilder = new ImageBuilder(new ColorMapperIdentity(), 1, null, "", "", 0, 0, null, - false); + final ImageBuilder imageBuilder = ImageBuilder.buildA(new ColorMapperIdentity(), false, null, "", "", 1, + null); imageBuilder.setUDrawable(this); return imageBuilder.writeImageTOBEMOVED(fileFormatOption, seed, os); diff --git a/src/net/sourceforge/plantuml/descdiagram/command/CommandArchimateMultilines.java b/src/net/sourceforge/plantuml/descdiagram/command/CommandArchimateMultilines.java index 32c4db2a3..06adaf7aa 100644 --- a/src/net/sourceforge/plantuml/descdiagram/command/CommandArchimateMultilines.java +++ b/src/net/sourceforge/plantuml/descdiagram/command/CommandArchimateMultilines.java @@ -99,8 +99,8 @@ public class CommandArchimateMultilines extends CommandMultilines2 { - public static final String ALL_TYPES = "artifact|actor|folder|card|file|package|rectangle|label|node|frame|cloud|database|queue|stack|storage|agent|usecase|component|boundary|control|entity|interface|circle|collections"; + public static final String ALL_TYPES = "artifact|actor|folder|card|file|package|rectangle|label|node|frame|cloud|database|queue|stack|storage|agent|usecase|component|boundary|control|entity|interface|circle|collections|port|portin|portout"; public CommandCreateElementFull() { super(getRegexConcat()); @@ -178,6 +179,15 @@ public class CommandCreateElementFull extends SingleLineCommand2 2 ? codeRaw.charAt(0) : 0; } } + \ No newline at end of file diff --git a/src/net/sourceforge/plantuml/descdiagram/command/CommandCreateElementMultilines.java b/src/net/sourceforge/plantuml/descdiagram/command/CommandCreateElementMultilines.java index 6d55cff19..308896a58 100644 --- a/src/net/sourceforge/plantuml/descdiagram/command/CommandCreateElementMultilines.java +++ b/src/net/sourceforge/plantuml/descdiagram/command/CommandCreateElementMultilines.java @@ -123,8 +123,8 @@ public class CommandCreateElementMultilines extends CommandMultilines2 lineLast = StringUtils.getSplit(MyPattern.cmpile(getPatternEnd()), lines.getLast499() - .getString()); + final List lineLast = StringUtils.getSplit(MyPattern.cmpile(getPatternEnd()), + lines.getLast().getTrimmed().getString()); lines = lines.subExtract(1, 1); Display display = lines.toDisplay(); final String descStart = line0.get("DESC", 0); @@ -167,9 +167,9 @@ public class CommandCreateElementMultilines extends CommandMultilines2 { RegexLeaf.spaceZeroOrMore(), // new RegexOptional(new RegexLeaf("LABEL1", "[%g]([^%g]+)[%g]")), // RegexLeaf.spaceZeroOrMore(), // - new RegexLeaf("HEAD2", "(0\\)|<<|[<^*+#0@)]|<\\||[%s]+o)?"), // + new RegexLeaf("HEAD2", "(0\\)|<<|[<^*+#0@)]|<\\|[\\|\\:]?|[%s]+o)?"), // new RegexLeaf("BODY1", "([-=.~]+)"), // new RegexLeaf("ARROW_STYLE1", "(?:\\[(" + LINE_STYLE_MUTILPLES + ")\\])?"), // new RegexOptional(new RegexLeaf("DIRECTION", "(left|right|up|down|le?|ri?|up?|do?)(?=[-=.~0()])")), // new RegexOptional(new RegexLeaf("INSIDE", "(0|\\(0\\)|\\(0|0\\))(?=[-=.~])")), // new RegexLeaf("ARROW_STYLE2", "(?:\\[(" + LINE_STYLE + ")\\])?"), // new RegexLeaf("BODY2", "([-=.~]*)"), // - new RegexLeaf("HEAD1", "(\\(0|>>|[>^*+#0@(]|\\|>|\\\\\\\\|o[%s]+)?"), // + new RegexLeaf("HEAD1", "(\\(0|>>|[>^*+#0@(]|[\\:\\|]?\\|>|\\\\\\\\|o[%s]+)?"), // RegexLeaf.spaceZeroOrMore(), // new RegexOptional(new RegexLeaf("LABEL2", "[%g]([^%g]+)[%g]")), // RegexLeaf.spaceZeroOrMore(), // @@ -136,6 +137,10 @@ public class CommandLinkElement extends SingleLineCommand2 { d1 = LinkDecor.ARROW_TRIANGLE; } else if (head1.equals("^")) { d1 = LinkDecor.EXTENDS; + } else if (head1.equals(":|>")) { + d1 = LinkDecor.DEFINEDBY; + } else if (head1.equals("||>")) { + d1 = LinkDecor.REDEFINES; } else if (head1.equals("|>")) { d1 = LinkDecor.EXTENDS; } @@ -162,6 +167,10 @@ public class CommandLinkElement extends SingleLineCommand2 { d2 = LinkDecor.ARROW_TRIANGLE; } else if (head2.equals("^")) { d2 = LinkDecor.EXTENDS; + } else if (head2.equals("<|:")) { + d2 = LinkDecor.DEFINEDBY; + } else if (head2.equals("<||")) { + d2 = LinkDecor.REDEFINES; } else if (head2.equals("<|")) { d2 = LinkDecor.EXTENDS; } @@ -210,8 +219,7 @@ public class CommandLinkElement extends SingleLineCommand2 { } private static RegexLeaf getGroup(String name) { - return new RegexLeaf( - name, + return new RegexLeaf(name, "([\\p{L}0-9_.]+|\\(\\)[%s]*[\\p{L}0-9_.]+|\\(\\)[%s]*[%g][^%g]+[%g]|:[^:]+:|(?!\\[\\*\\])\\[[^\\[\\]]+\\]|\\((?!\\*\\))[^)]+\\))"); } @@ -261,8 +269,8 @@ public class CommandLinkElement extends SingleLineCommand2 { final Matcher2 m1 = p1.matcher(labelLink); if (m1.matches()) { firstLabel = m1.group(1); - labelLink = StringUtils.trin(StringUtils.eventuallyRemoveStartingAndEndingDoubleQuote(StringUtils - .trin(m1.group(2)))); + labelLink = StringUtils + .trin(StringUtils.eventuallyRemoveStartingAndEndingDoubleQuote(StringUtils.trin(m1.group(2)))); secondLabel = m1.group(3); return; } @@ -270,8 +278,8 @@ public class CommandLinkElement extends SingleLineCommand2 { final Matcher2 m2 = p2.matcher(labelLink); if (m2.matches()) { firstLabel = m2.group(1); - labelLink = StringUtils.trin(StringUtils.eventuallyRemoveStartingAndEndingDoubleQuote(StringUtils - .trin(m2.group(2)))); + labelLink = StringUtils + .trin(StringUtils.eventuallyRemoveStartingAndEndingDoubleQuote(StringUtils.trin(m2.group(2)))); secondLabel = null; return; } @@ -279,8 +287,8 @@ public class CommandLinkElement extends SingleLineCommand2 { final Matcher2 m3 = p3.matcher(labelLink); if (m3.matches()) { firstLabel = null; - labelLink = StringUtils.trin(StringUtils.eventuallyRemoveStartingAndEndingDoubleQuote(StringUtils - .trin(m3.group(1)))); + labelLink = StringUtils + .trin(StringUtils.eventuallyRemoveStartingAndEndingDoubleQuote(StringUtils.trin(m3.group(1)))); secondLabel = m3.group(2); } } @@ -311,17 +319,17 @@ public class CommandLinkElement extends SingleLineCommand2 { final IEntity cl1; final IEntity cl2; if (diagram.isGroup(code1) && diagram.isGroup(code2)) { - cl1 = diagram.V1972() ? diagram.getGroupStrict(diagram.buildLeafIdent(ent1String)) : diagram - .getGroup(diagram.buildCode(ent1String)); - cl2 = diagram.V1972() ? diagram.getGroupStrict(diagram.buildLeafIdent(ent2String)) : diagram - .getGroup(diagram.buildCode(ent2String)); + cl1 = diagram.V1972() ? diagram.getGroupStrict(diagram.buildLeafIdent(ent1String)) + : diagram.getGroup(diagram.buildCode(ent1String)); + cl2 = diagram.V1972() ? diagram.getGroupStrict(diagram.buildLeafIdent(ent2String)) + : diagram.getGroup(diagram.buildCode(ent2String)); } else { cl1 = getFoo1(diagram, code1, ident1, ident1pure); cl2 = getFoo1(diagram, code2, ident2, ident2pure); } Link link = new Link(cl1, cl2, linkType, Display.getWithNewlines(labels.labelLink), queue.length(), - labels.firstLabel, labels.secondLabel, diagram.getLabeldistance(), diagram.getLabelangle(), diagram - .getSkinParam().getCurrentStyleBuilder()); + labels.firstLabel, labels.secondLabel, diagram.getLabeldistance(), diagram.getLabelangle(), + diagram.getSkinParam().getCurrentStyleBuilder()); link.setLinkArrow(labels.linkArrow); if (dir == Direction.LEFT || dir == Direction.UP) { link = link.getInv(); @@ -356,8 +364,8 @@ public class CommandLinkElement extends SingleLineCommand2 { if (codeChar == '(') { return getOrCreateLeaf1972(diagram, ident3, code3, LeafType.USECASE, USymbol.USECASE, pure); } else if (codeChar == ':') { - return getOrCreateLeaf1972(diagram, ident3, code3, LeafType.DESCRIPTION, diagram.getSkinParam() - .getActorStyle().getUSymbol(), pure); + return getOrCreateLeaf1972(diagram, ident3, code3, LeafType.DESCRIPTION, + diagram.getSkinParam().getActorStyle().getUSymbol(), pure); } else if (codeChar == '[') { final USymbol sym = diagram.getSkinParam().useUml2ForComponent() ? USymbol.COMPONENT2 : USymbol.COMPONENT1; return getOrCreateLeaf1972(diagram, ident3, code3, LeafType.DESCRIPTION, sym, pure); @@ -366,8 +374,8 @@ public class CommandLinkElement extends SingleLineCommand2 { return getOrCreateLeaf1972(diagram, ident, code, null, null, pure); } - private ILeaf getOrCreateLeaf1972(DescriptionDiagram diagram, Ident ident, Code code, LeafType type, - USymbol symbol, Ident pure) { + private ILeaf getOrCreateLeaf1972(DescriptionDiagram diagram, Ident ident, Code code, LeafType type, USymbol symbol, + Ident pure) { if (diagram.V1972()) { final ILeaf result = pure.size() == 1 ? diagram.getLeafVerySmart(ident) : diagram.getLeafStrict(ident); // final ILeaf result = diagram.getLeafSmart(ident); diff --git a/src/net/sourceforge/plantuml/donors/PSystemDonors.java b/src/net/sourceforge/plantuml/donors/PSystemDonors.java index 61308f145..9746892df 100644 --- a/src/net/sourceforge/plantuml/donors/PSystemDonors.java +++ b/src/net/sourceforge/plantuml/donors/PSystemDonors.java @@ -48,6 +48,7 @@ import net.sourceforge.plantuml.BackSlash; import net.sourceforge.plantuml.FileFormatOption; import net.sourceforge.plantuml.code.AsciiEncoder; import net.sourceforge.plantuml.code.CompressionBrotli; +import net.sourceforge.plantuml.code.NoPlantumlCompressionException; import net.sourceforge.plantuml.code.StringCompressorNone; import net.sourceforge.plantuml.code.Transcoder; import net.sourceforge.plantuml.code.TranscoderImpl; @@ -71,25 +72,25 @@ public class PSystemDonors extends AbstractPSystem { private static final int COLS = 6; private static final int FREE_LINES = 6; - public static final String DONORS = "6nmB0AmFkBcp0hHmgCOwx9qzUsNuYPYXIV3upfH_WeHti04o13LNIRGeSf_iNWC41T0rTFIOstTwt6-a" - + "luYkTE-RPaHR_fhZvnb3CH3qUFww6hRvtnuyvfxff-Ixcz4JPiBaVmA4fYcNj0L8bI6ba87tDyDvlcaC" - + "lVGCM1vLFqNtjV-xT9LrzwfEcBReReNpfn6gCqUZc6Ew_wF0XIZO2QfeKCWndSgv3eUg3dAs4trL54X2" - + "nJk_dTzsJLR5P2wH4gkDRSICpe3kdFH-IGvajFwZVe0F7TCr9RWd59TU8kZyizhXPG73hv7uDHGEiU38" - + "m1nAEoesA6Lk91J22L3eNCLiRFt1aITUM5H12_lmZqPou9wIh65eKOXu00Knp-02IM_KhKdEJXq6LEUP" - + "BOOrITUjyH3fcuU95AsBXll18iA2Ma0DGzw4RlXqd_MIeNk_A1huos-JNBlbG1so9K3RhEXRU3H9LF-d" - + "csUUkCkKpLEQZdhj_J5sXzmrPURqFteVXLp0SsuMKcJnyWBvCUYvcgWbFvVpO24DuJfANqZtkUtYCOjm" - + "oOOCDUlopIoZHb_iIdGsBSPsif0Vy-TM4n9iuQkKHw0djUfeqVb28JKrhX_oUcg_3d9DdGNUCLeV5NEL" - + "_r-4LPYXE46douoYhb-e6BDvDLGiKGHdZ2uFkGaa5-1SJMx7QlKXVkqJH6yb8n3Bng07ulMlbIwNGbWT" - + "wxezpGfW-R1IDuMeBGAQj1jw4bVoaR88lHqcZMKpnj9pqWOVfut6A4xejCOcShCGfCkmJbNDT8dsEQrX" - + "U3M_b_dql1_9UHNNwIRlUH_IwoSPg3Cjw9XK6l5ObhANHBe6gipYB7NL4DyLjlFmq7t1UHQBDZ1pjhaE" - + "MHOQ5vBKr3yn-Q59npj9sQnzjHLx1_4lWtc8P4OHND-UF5AJonJ2bZET09j0LAh59_PRqhWpg8VbP7Eu" - + "3c7beTMBa2I_Ipv1hAfOE5rO6-v-UOOW2lR9UI_CsXgNBYNN0chE7eAyj51LJocEj3b91kQQzAot3hRV" - + "rRd0jtwhZcr0yPqGdTRSO7CAZ3HHVb6WHDAGbV9BJn8J-5y_Jxb7vZha-2ul6na7oIb93Ac2TCSlN3sD" - + "rSlG2jPR_FsprZOhvy__lIOhEVN4irvD41qWed-J0hYSqnZ1sy1VjuyaRqxCi57GsEJAWrel0ea8zk6T" - + "NTIJoupy8aQMMvIBLd5zgBgluXwvM0snOUiYd-BeFiMLrZODKILZt_T5kCZ1EFyjginAuQgMriA8JR7T" - + "ipYviLilnTFMRY23whX3uEoft-wckKgVwmjBJSFJH7uwa4EskaiBQthQD3O3syJOtrlR3acw_oOT_v9U" - + "q_sk7ePsTlucJuF6RtSO_OQHO41axPXWjymvYS2JRoJaZNauoUrYwPEBxYcxKB32VjClayM4LrQqoaIq" - + "vkRMS-vj8Svk6tFO5hPFLwFu5qKr4O5CBZRhdiH2AU21L9A2EMVBL86qdIPDymc9Inq0"; + public static final String DONORS = "6qmB02mFUBXRGOc9nbfsvvsjZ8ybZ2OHBCyJYiF08fxk1iGVuDxfSR-H_YAwqhrlcX5jsPhYF6E8M13q" + + "U9fSCsnpRmyyvfxff-Ixcz4JPiBaVmA4fYcNj0L8bI4b-FUTh_mIz0xls23HNANHuiWzilk5zpV3UUuq" + + "Fdhf6V08LJz5zxN_Dvr8N1uAOPPcAup1g6Y4sXSuHUTOxlzJgKkZsdrNHNMhAiTqwk8OhWeRqDK9ZmMh" + + "cLguQvnNXoQZOhARI8cqHWaHepD3JqvgNo47CaZyKJz0XyqLbehS4uhBA4bqVJrtPDj0ymiIBuLWY0MR" + + "1-PGok7TeCIv4ICH5453rofwOnkEB7dYWY4EBUpX7utaY4SgiwQZHIBa4IY8U1e79BrGZoOnExqOK7ra" + + "j1Yn95LNnqsuVnuMKhGs6ku1Yn0BpW9g2F8cTCEdnwgF9lTnDTJmLvucUQjMXpfaou2s6T6t-6YIA9-p" + + "JJD7N3NA5gdEKPzZlEOHaBkbLixuCkeevnBSv-vT3UiVBP0VWPwhYKhoPyw5XIJ4TPHzaAvp-vL7By8b" + + "6p9DhCitiOKQVR4hMTcCB3l8GfxEhwjDo60BNRay33sfLPzcdI-qfANr-qMFfetx9DRKc-4Tf_THDXVv" + + "_ztkPMOeJj2P4hEewm65CPjMmyM68ZWjT6t8JK2kG7bptOgRrqN-gW-8ta96878R9RqGxu-Kkov2JCUg" + + "xaWn0fW_fPoRHDY62CtQ1JsDAgL8MU_sE5qzovUDkUUa3wvdZSOeZkcanYPyyowuks6zgZVJpThdM5Fm" + + "7A_BlEfUK_qgjhFDlHTyIAs_O23EzCw8IDKHZMqh_oZShQD45cl9rRfyL_U3WuVkNt06YpOneyrsoF9G" + + "k9oCC_KhmqzB1jufokRztjxa5IJk2XiX71dDuFhHv96QN28Hj9pb-DW445MBL-nA2QSBLREiL8wmAIPF" + + "Nxq8cU1toIUmLDw5fnjhpJqepX14GPsOzyAgRVqwrBmje9OS9YX92wL6gYdIro8PcAlJiz4wsFwqu8An" + + "ZKTLh06ARvlehCO6ZLDWkeZmYmQUI0go4hta9370V_tyIZtIry77TqNvZ3X8JfV442f8TSQ5KzFuUHbM" + + "ndgBlbzlRVSA_lnx7UtWr1lt-XH1z00Y_k-a08vo4YDu6lXxv2F1MmUhHeysYiJAGqfl1X8MxCSxiwYd" + + "XXcDEp6Zt99Sz8hjGzN_TdAVM2o6sB3yefIc6B7afBVTkbEbRD__nk8W1yFVHPKvcLpbqXeOqIYsjnUd" + + "E7ORPRZBQWLuK1sN2QpzwhTcbZUDkUvOgXkU8VBJ4JbLz70jhAbfyzWCR1TZVczfFvNfyP-Cw9VIcXvx" + + "zJ1yK7vFdGADt_PG-WqZmO18tJ5WD_SvcO4xtd382rDpKjF5CYiNtTVj0i4A-ysyH1OJNjdMAfUmrXvU" + + "S_7jNPxTTkQmBMIVgKRJ2qKLCGEPN6pHtOc5Ki03gI05S_QMYIBI3dg3Opq3y105n_jx1k5eiNczPftZ" + "6Gq0"; /* * Special thanks to our sponsors and donors: @@ -101,8 +102,8 @@ public class PSystemDonors extends AbstractPSystem { final protected ImageData exportDiagramNow(OutputStream os, int num, FileFormatOption fileFormat, long seed) throws IOException { final UDrawable result = getGraphicStrings(); - final ImageBuilder imageBuilder = new ImageBuilder(new ColorMapperIdentity(), 1.0, HColorUtils.WHITE, - getMetadata(), null, 0, 0, null, false); + final ImageBuilder imageBuilder = ImageBuilder.buildA(new ColorMapperIdentity(), false, null, getMetadata(), + null, 1.0, HColorUtils.WHITE); imageBuilder.setUDrawable(result); return imageBuilder.writeImageTOBEMOVED(fileFormat, seed, os); } @@ -144,12 +145,16 @@ public class PSystemDonors extends AbstractPSystem { private List getDonors() throws IOException { final List lines = new ArrayList(); - final Transcoder t = new TranscoderImpl(new AsciiEncoder(), new StringCompressorNone(), + final Transcoder t = TranscoderImpl.utf8(new AsciiEncoder(), new StringCompressorNone(), new CompressionBrotli()); - final String s = t.decode(DONORS).replace('*', '.'); - final StringTokenizer st = new StringTokenizer(s, BackSlash.NEWLINE); - while (st.hasMoreTokens()) { - lines.add(st.nextToken()); + try { + final String s = t.decode(DONORS).replace('*', '.'); + final StringTokenizer st = new StringTokenizer(s, BackSlash.NEWLINE); + while (st.hasMoreTokens()) { + lines.add(st.nextToken()); + } + } catch (NoPlantumlCompressionException e) { + e.printStackTrace(); } return lines; } diff --git a/src/net/sourceforge/plantuml/donors/PSystemSkinparameterList.java b/src/net/sourceforge/plantuml/donors/PSystemSkinparameterList.java index 9b33d2ed5..a4cb554fd 100644 --- a/src/net/sourceforge/plantuml/donors/PSystemSkinparameterList.java +++ b/src/net/sourceforge/plantuml/donors/PSystemSkinparameterList.java @@ -62,8 +62,8 @@ public class PSystemSkinparameterList extends AbstractPSystem { final protected ImageData exportDiagramNow(OutputStream os, int num, FileFormatOption fileFormat, long seed) throws IOException { final UDrawable result = getGraphicStrings(); - final ImageBuilder imageBuilder = new ImageBuilder(new ColorMapperIdentity(), 1.0, HColorUtils.WHITE, - getMetadata(), null, 0, 0, null, false); + final ImageBuilder imageBuilder = ImageBuilder.buildA(new ColorMapperIdentity(), + false, null, getMetadata(), null, 1.0, HColorUtils.WHITE); imageBuilder.setUDrawable(result); return imageBuilder.writeImageTOBEMOVED(fileFormat, seed, os); } diff --git a/src/net/sourceforge/plantuml/eggs/PSystemAppleTwo.java b/src/net/sourceforge/plantuml/eggs/PSystemAppleTwo.java index 1a28f81a4..49f14399a 100644 --- a/src/net/sourceforge/plantuml/eggs/PSystemAppleTwo.java +++ b/src/net/sourceforge/plantuml/eggs/PSystemAppleTwo.java @@ -68,8 +68,8 @@ public class PSystemAppleTwo extends AbstractPSystem { final protected ImageData exportDiagramNow(OutputStream os, int num, FileFormatOption fileFormat, long seed) throws IOException { final TextBlockBackcolored result = getGraphicStrings(); - final ImageBuilder imageBuilder = new ImageBuilder(new ColorMapperIdentity(), 1.0, result.getBackcolor(), - getMetadata(), null, 0, 0, null, false); + final ImageBuilder imageBuilder = ImageBuilder.buildA(new ColorMapperIdentity(), + false, null, getMetadata(), null, 1.0, result.getBackcolor()); imageBuilder.setUDrawable(result); return imageBuilder.writeImageTOBEMOVED(fileFormat, seed, os); } diff --git a/src/net/sourceforge/plantuml/eggs/PSystemCharlie.java b/src/net/sourceforge/plantuml/eggs/PSystemCharlie.java index e10926004..48f3dbf4f 100644 --- a/src/net/sourceforge/plantuml/eggs/PSystemCharlie.java +++ b/src/net/sourceforge/plantuml/eggs/PSystemCharlie.java @@ -61,8 +61,8 @@ public class PSystemCharlie extends AbstractPSystem { @Override final protected ImageData exportDiagramNow(OutputStream os, int num, FileFormatOption fileFormat, long seed) throws IOException { - final ImageBuilder imageBuilder = new ImageBuilder(new ColorMapperIdentity(), 1.0, HColorUtils.BLACK, - getMetadata(), null, 0, 0, null, false); + final ImageBuilder imageBuilder = ImageBuilder.buildA(new ColorMapperIdentity(), + false, null, getMetadata(), null, 1.0, HColorUtils.BLACK); imageBuilder.setUDrawable(new UDrawable() { public void drawU(UGraphic ug) { diff --git a/src/net/sourceforge/plantuml/eggs/PSystemColors.java b/src/net/sourceforge/plantuml/eggs/PSystemColors.java index c693f9e7a..908f747bc 100644 --- a/src/net/sourceforge/plantuml/eggs/PSystemColors.java +++ b/src/net/sourceforge/plantuml/eggs/PSystemColors.java @@ -90,8 +90,8 @@ public class PSystemColors extends AbstractPSystem implements UDrawable { @Override final protected ImageData exportDiagramNow(OutputStream os, int num, FileFormatOption fileFormat, long seed) throws IOException { - final ImageBuilder imageBuilder = new ImageBuilder(new ColorMapperIdentity(), 1.0, HColorUtils.WHITE, - getMetadata(), null, 0, 0, null, false); + final ImageBuilder imageBuilder = ImageBuilder.buildA(new ColorMapperIdentity(), + false, null, getMetadata(), null, 1.0, HColorUtils.WHITE); imageBuilder.setUDrawable(this); return imageBuilder.writeImageTOBEMOVED(fileFormat, seed, os); } diff --git a/src/net/sourceforge/plantuml/eggs/PSystemEgg.java b/src/net/sourceforge/plantuml/eggs/PSystemEgg.java index d79f7f0f1..7e44264c7 100644 --- a/src/net/sourceforge/plantuml/eggs/PSystemEgg.java +++ b/src/net/sourceforge/plantuml/eggs/PSystemEgg.java @@ -65,8 +65,8 @@ public class PSystemEgg extends AbstractPSystem { final protected ImageData exportDiagramNow(OutputStream os, int num, FileFormatOption fileFormat, long seed) throws IOException { final TextBlockBackcolored result = getGraphicStrings(); - final ImageBuilder imageBuilder = new ImageBuilder(new ColorMapperIdentity(), 1.0, result.getBackcolor(), - getMetadata(), null, 0, 0, null, false); + final ImageBuilder imageBuilder = ImageBuilder.buildA(new ColorMapperIdentity(), + false, null, getMetadata(), null, 1.0, result.getBackcolor()); imageBuilder.setUDrawable(result); return imageBuilder.writeImageTOBEMOVED(fileFormat, seed, os); } diff --git a/src/net/sourceforge/plantuml/eggs/PSystemLost.java b/src/net/sourceforge/plantuml/eggs/PSystemLost.java index 9a43722b8..68f278f03 100644 --- a/src/net/sourceforge/plantuml/eggs/PSystemLost.java +++ b/src/net/sourceforge/plantuml/eggs/PSystemLost.java @@ -61,8 +61,8 @@ public class PSystemLost extends AbstractPSystem { final protected ImageData exportDiagramNow(OutputStream os, int num, FileFormatOption fileFormat, long seed) throws IOException { final TextBlockBackcolored result = getGraphicStrings(); - final ImageBuilder imageBuilder = new ImageBuilder(new ColorMapperIdentity(), 1.0, result.getBackcolor(), - getMetadata(), null, 0, 0, null, false); + final ImageBuilder imageBuilder = ImageBuilder.buildA(new ColorMapperIdentity(), + false, null, getMetadata(), null, 1.0, result.getBackcolor()); imageBuilder.setUDrawable(result); return imageBuilder.writeImageTOBEMOVED(fileFormat, seed, os); } diff --git a/src/net/sourceforge/plantuml/eggs/PSystemRIP.java b/src/net/sourceforge/plantuml/eggs/PSystemRIP.java index 758313bf5..48256feb6 100644 --- a/src/net/sourceforge/plantuml/eggs/PSystemRIP.java +++ b/src/net/sourceforge/plantuml/eggs/PSystemRIP.java @@ -81,8 +81,8 @@ public class PSystemRIP extends AbstractPSystem { final protected ImageData exportDiagramNow(OutputStream os, int num, FileFormatOption fileFormat, long seed) throws IOException { final TextBlockBackcolored result = getGraphicStrings(); - final ImageBuilder imageBuilder = new ImageBuilder(new ColorMapperIdentity(), 1.0, result.getBackcolor(), - getMetadata(), null, 0, 0, null, false); + final ImageBuilder imageBuilder = ImageBuilder.buildA(new ColorMapperIdentity(), + false, null, getMetadata(), null, 1.0, result.getBackcolor()); imageBuilder.setUDrawable(result); return imageBuilder.writeImageTOBEMOVED(fileFormat, seed, os); } diff --git a/src/net/sourceforge/plantuml/eggs/PSystemWelcome.java b/src/net/sourceforge/plantuml/eggs/PSystemWelcome.java index 9798f6d83..546badc96 100644 --- a/src/net/sourceforge/plantuml/eggs/PSystemWelcome.java +++ b/src/net/sourceforge/plantuml/eggs/PSystemWelcome.java @@ -84,8 +84,8 @@ public class PSystemWelcome extends AbstractPSystem { final protected ImageData exportDiagramNow(OutputStream os, int num, FileFormatOption fileFormat, long seed) throws IOException { final TextBlockBackcolored result = getGraphicStrings(); - final ImageBuilder imageBuilder = new ImageBuilder(new ColorMapperIdentity(), 1.0, result.getBackcolor(), - getMetadata(), null, 0, 0, null, false); + final ImageBuilder imageBuilder = ImageBuilder.buildA(new ColorMapperIdentity(), + false, null, getMetadata(), null, 1.0, result.getBackcolor()); imageBuilder.setUDrawable(result); // imageBuilder.setUDrawable(TextBlockUtils.withMargin(result, 4, 4)); return imageBuilder.writeImageTOBEMOVED(fileFormat, seed, os); diff --git a/src/net/sourceforge/plantuml/error/PSystemError.java b/src/net/sourceforge/plantuml/error/PSystemError.java index 526ce8412..1bc8543c6 100644 --- a/src/net/sourceforge/plantuml/error/PSystemError.java +++ b/src/net/sourceforge/plantuml/error/PSystemError.java @@ -210,8 +210,8 @@ public abstract class PSystemError extends AbstractPSystem { final TextBlockBackcolored result = getGraphicalFormatted(); TextBlock udrawable; - final ImageBuilder imageBuilder = new ImageBuilder(new ColorMapperIdentity(), 1.0, result.getBackcolor(), - getMetadata(), null, 0, 0, null, false); + final ImageBuilder imageBuilder = ImageBuilder.buildA(new ColorMapperIdentity(), + false, null, getMetadata(), null, 1.0, result.getBackcolor()); imageBuilder.setRandomPixel(true); if (getSource().getTotalLineCount() < 5) { udrawable = addWelcome(result); diff --git a/src/net/sourceforge/plantuml/font/PSystemListFonts.java b/src/net/sourceforge/plantuml/font/PSystemListFonts.java index 0bec5b189..12d897434 100644 --- a/src/net/sourceforge/plantuml/font/PSystemListFonts.java +++ b/src/net/sourceforge/plantuml/font/PSystemListFonts.java @@ -73,8 +73,8 @@ public class PSystemListFonts extends AbstractPSystem { final protected ImageData exportDiagramNow(OutputStream os, int num, FileFormatOption fileFormat, long seed) throws IOException { final TextBlockBackcolored result = getGraphicStrings(); - final ImageBuilder imageBuilder = new ImageBuilder(new ColorMapperIdentity(), 1.0, result.getBackcolor(), - getMetadata(), null, 0, 0, null, false); + final ImageBuilder imageBuilder = ImageBuilder.buildA(new ColorMapperIdentity(), + false, null, getMetadata(), null, 1.0, result.getBackcolor()); imageBuilder.setUDrawable(result); return imageBuilder.writeImageTOBEMOVED(fileFormat, seed, os); } diff --git a/src/net/sourceforge/plantuml/graphic/FontConfiguration.java b/src/net/sourceforge/plantuml/graphic/FontConfiguration.java index 62a384183..e5e5cc84a 100644 --- a/src/net/sourceforge/plantuml/graphic/FontConfiguration.java +++ b/src/net/sourceforge/plantuml/graphic/FontConfiguration.java @@ -44,6 +44,8 @@ import net.sourceforge.plantuml.SkinParamUtils; import net.sourceforge.plantuml.cucadiagram.Stereotype; import net.sourceforge.plantuml.graphic.color.ColorType; import net.sourceforge.plantuml.graphic.color.Colors; +import net.sourceforge.plantuml.style.PName; +import net.sourceforge.plantuml.style.Style; import net.sourceforge.plantuml.ugraphic.UFont; import net.sourceforge.plantuml.ugraphic.color.HColor; import net.sourceforge.plantuml.ugraphic.color.HColorUtils; @@ -78,8 +80,14 @@ public class FontConfiguration { } public FontConfiguration(ISkinParam skinParam, FontParam fontParam, Stereotype stereo) { - this(SkinParamUtils.getFont(skinParam, fontParam, stereo), SkinParamUtils.getFontColor(skinParam, fontParam, - stereo), skinParam.getHyperlinkColor(), skinParam.useUnderlineForHyperlink(), skinParam.getTabSize()); + this(SkinParamUtils.getFont(skinParam, fontParam, stereo), + SkinParamUtils.getFontColor(skinParam, fontParam, stereo), skinParam.getHyperlinkColor(), + skinParam.useUnderlineForHyperlink(), skinParam.getTabSize()); + } + + public FontConfiguration(Style style, ISkinParam skinParam, Stereotype stereo, FontParam fontParam) { + this(style.getUFont(), style.value(PName.FontColor).asColor(skinParam.getIHtmlColorSet()), + skinParam.getHyperlinkColor(), skinParam.useUnderlineForHyperlink(), skinParam.getTabSize()); } // --- @@ -192,9 +200,9 @@ public class FontConfiguration { } public FontConfiguration changeFamily(String family) { - return new FontConfiguration(styles, motherFont, motherColor, new UFont(family, currentFont.getStyle(), - currentFont.getSize()), currentColor, extendedColor, fontPosition, svgAttributes, hyperlink, - hyperlinkColor, useUnderlineForHyperlink, tabSize); + return new FontConfiguration(styles, motherFont, motherColor, + new UFont(family, currentFont.getStyle(), currentFont.getSize()), currentColor, extendedColor, + fontPosition, svgAttributes, hyperlink, hyperlinkColor, useUnderlineForHyperlink, tabSize); } public FontConfiguration resetFont() { @@ -208,8 +216,8 @@ public class FontConfiguration { r.clear(); } r.add(style); - return new FontConfiguration(r, motherFont, motherColor, currentFont, currentColor, extendedColor, - fontPosition, svgAttributes, hyperlink, hyperlinkColor, useUnderlineForHyperlink, tabSize); + return new FontConfiguration(r, motherFont, motherColor, currentFont, currentColor, extendedColor, fontPosition, + svgAttributes, hyperlink, hyperlinkColor, useUnderlineForHyperlink, tabSize); } public FontConfiguration italic() { @@ -238,8 +246,8 @@ public class FontConfiguration { FontConfiguration remove(FontStyle style) { final EnumSet r = styles.clone(); r.remove(style); - return new FontConfiguration(r, motherFont, motherColor, currentFont, currentColor, extendedColor, - fontPosition, svgAttributes, hyperlink, hyperlinkColor, useUnderlineForHyperlink, tabSize); + return new FontConfiguration(r, motherFont, motherColor, currentFont, currentColor, extendedColor, fontPosition, + svgAttributes, hyperlink, hyperlinkColor, useUnderlineForHyperlink, tabSize); } public UFont getFont() { diff --git a/src/net/sourceforge/plantuml/graphic/HtmlColorAndStyle.java b/src/net/sourceforge/plantuml/graphic/HtmlColorAndStyle.java index ddb1d32e5..f53449538 100644 --- a/src/net/sourceforge/plantuml/graphic/HtmlColorAndStyle.java +++ b/src/net/sourceforge/plantuml/graphic/HtmlColorAndStyle.java @@ -64,8 +64,8 @@ public class HtmlColorAndStyle { if (arrowColor == null) { throw new IllegalArgumentException(); } - this.arrowHeadColor = arrowHeadColor; this.arrowColor = arrowColor; + this.arrowHeadColor = arrowHeadColor == null ? arrowColor : arrowHeadColor; this.style = style; } diff --git a/src/net/sourceforge/plantuml/graphic/QuoteUtils.java b/src/net/sourceforge/plantuml/graphic/QuoteUtils.java index f1f1ebaff..6601be055 100644 --- a/src/net/sourceforge/plantuml/graphic/QuoteUtils.java +++ b/src/net/sourceforge/plantuml/graphic/QuoteUtils.java @@ -261,7 +261,13 @@ public class QuoteUtils { "Guvf rkcynvaf abg whfg Ubyyljbbq, ohg nyzbfg gur ragvergl bs Sbk Arjf", "Gur terngrfg rarzl bs xabjyrqtr vf abg vtabenapr; vg vf gur vyyhfvba bs xabjyrqtr", "N fghql sbhaq gung vtabenag crbcyr ner zber yvxryl gb oryvrir gurl'er oevyyvnag", - "Dh'rfg-pr dh'ba n qbap n fbaare pbzzr pn, pr zngva ?"); + "Dh'rfg-pr dh'ba n qbap n fbaare pbzzr pn, pr zngva ?", "Ernyvgl vf gur bayl guvat gung'f erny", + "V jbhyq tvir zlfrys na N+", "Lbh rire unir frpbaq gubhtugf nobhg fbzrguvat ?", + "V oryvrir vg'f n ebhtu fvghngvba bire gurer", "Whfg fb lbh xabj, V tbg zl yvprafr fhfcraqrq", + "Gunax lbh sbe pubbfvat Bprnavp Nveyvarf", "4-8-15-16-23-42", + "...naq gnk phgf. Gung'yy fubj gurz znegvnaf.", + "Jurarire V srry gur arrq gb rkrepvfr, V yvr qbja hagvy vg tbrf njnl", "Ernyvgl pbagvahrf gb ehva zl yvsr", + "Vs lbh gvpxyr hf, qb jr abg ynhtu?", "V xabj n HQC wbxr, ohg lbh zvtug abg trg vg"); private QuoteUtils() { } diff --git a/src/net/sourceforge/plantuml/graphic/SkinParameter.java b/src/net/sourceforge/plantuml/graphic/SkinParameter.java index c4b54835e..7b5e657c1 100644 --- a/src/net/sourceforge/plantuml/graphic/SkinParameter.java +++ b/src/net/sourceforge/plantuml/graphic/SkinParameter.java @@ -41,89 +41,96 @@ import net.sourceforge.plantuml.FontParam; import net.sourceforge.plantuml.ISkinParam; import net.sourceforge.plantuml.LineParam; import net.sourceforge.plantuml.cucadiagram.Stereotype; +import net.sourceforge.plantuml.style.SName; import net.sourceforge.plantuml.ugraphic.UStroke; public class SkinParameter { - public static final SkinParameter DATABASE = new SkinParameter("DATABASE", ColorParam.databaseBackground, - ColorParam.databaseBorder, FontParam.DATABASE, FontParam.DATABASE_STEREOTYPE); + public static final SkinParameter DATABASE = new SkinParameter(SName.databse, "DATABASE", + ColorParam.databaseBackground, ColorParam.databaseBorder, FontParam.DATABASE, + FontParam.DATABASE_STEREOTYPE); - public static final SkinParameter ARTIFACT = new SkinParameter("ARTIFACT", ColorParam.artifactBackground, - ColorParam.artifactBorder, FontParam.ARTIFACT, FontParam.ARTIFACT_STEREOTYPE); + public static final SkinParameter ARTIFACT = new SkinParameter(SName.artifact, "ARTIFACT", + ColorParam.artifactBackground, ColorParam.artifactBorder, FontParam.ARTIFACT, + FontParam.ARTIFACT_STEREOTYPE); - public static final SkinParameter COMPONENT1 = new SkinParameter("COMPONENT1", ColorParam.componentBackground, - ColorParam.componentBorder, FontParam.COMPONENT, FontParam.COMPONENT_STEREOTYPE, LineParam.componentBorder, - CornerParam.component); + public static final SkinParameter COMPONENT1 = new SkinParameter(SName.component, "COMPONENT1", + ColorParam.componentBackground, ColorParam.componentBorder, FontParam.COMPONENT, + FontParam.COMPONENT_STEREOTYPE, LineParam.componentBorder, CornerParam.component); - public static final SkinParameter NODE = new SkinParameter("NODE", ColorParam.nodeBackground, + public static final SkinParameter NODE = new SkinParameter(SName.node, "NODE", ColorParam.nodeBackground, ColorParam.nodeBorder, FontParam.NODE, FontParam.NODE_STEREOTYPE); - public static final SkinParameter STORAGE = new SkinParameter("STORAGE", ColorParam.storageBackground, - ColorParam.storageBorder, FontParam.STORAGE, FontParam.STORAGE_STEREOTYPE); + public static final SkinParameter STORAGE = new SkinParameter(SName.storage, "STORAGE", + ColorParam.storageBackground, ColorParam.storageBorder, FontParam.STORAGE, FontParam.STORAGE_STEREOTYPE); - public static final SkinParameter QUEUE = new SkinParameter("QUEUE", ColorParam.queueBackground, + public static final SkinParameter QUEUE = new SkinParameter(SName.queue, "QUEUE", ColorParam.queueBackground, ColorParam.queueBorder, FontParam.QUEUE, FontParam.QUEUE_STEREOTYPE); - public static final SkinParameter STACK = new SkinParameter("STACK", ColorParam.stackBackground, + public static final SkinParameter STACK = new SkinParameter(SName.stack, "STACK", ColorParam.stackBackground, ColorParam.stackBorder, FontParam.STACK, FontParam.STACK_STEREOTYPE); - public static final SkinParameter CLOUD = new SkinParameter("CLOUD", ColorParam.cloudBackground, + public static final SkinParameter CLOUD = new SkinParameter(SName.cloud, "CLOUD", ColorParam.cloudBackground, ColorParam.cloudBorder, FontParam.CLOUD, FontParam.CLOUD_STEREOTYPE); - public static final SkinParameter FRAME = new SkinParameter("FRAME", ColorParam.frameBackground, + public static final SkinParameter FRAME = new SkinParameter(SName.frame, "FRAME", ColorParam.frameBackground, ColorParam.frameBorder, FontParam.FRAME, FontParam.FRAME_STEREOTYPE); - public static final SkinParameter COMPONENT2 = new SkinParameter("COMPONENT2", ColorParam.componentBackground, - ColorParam.componentBorder, FontParam.COMPONENT, FontParam.COMPONENT_STEREOTYPE, LineParam.componentBorder, - CornerParam.component); + public static final SkinParameter COMPONENT2 = new SkinParameter(SName.component, "COMPONENT2", + ColorParam.componentBackground, ColorParam.componentBorder, FontParam.COMPONENT, + FontParam.COMPONENT_STEREOTYPE, LineParam.componentBorder, CornerParam.component); - public static final SkinParameter AGENT = new SkinParameter("AGENT", ColorParam.agentBackground, - ColorParam.agentBorder, FontParam.AGENT, FontParam.AGENT_STEREOTYPE, LineParam.agentBorder, CornerParam.agent); + public static final SkinParameter AGENT = new SkinParameter(SName.agent, "AGENT", ColorParam.agentBackground, + ColorParam.agentBorder, FontParam.AGENT, FontParam.AGENT_STEREOTYPE, LineParam.agentBorder, + CornerParam.agent); - public static final SkinParameter FOLDER = new SkinParameter("FOLDER", ColorParam.folderBackground, + public static final SkinParameter FOLDER = new SkinParameter(SName.folder, "FOLDER", ColorParam.folderBackground, ColorParam.folderBorder, FontParam.FOLDER, FontParam.FOLDER_STEREOTYPE); - public static final SkinParameter FILE = new SkinParameter("FILE", ColorParam.fileBackground, + public static final SkinParameter FILE = new SkinParameter(SName.file, "FILE", ColorParam.fileBackground, ColorParam.fileBorder, FontParam.FILE, FontParam.FILE_STEREOTYPE); - public static final SkinParameter PACKAGE = new SkinParameter("PACKAGE", ColorParam.packageBackground, - ColorParam.packageBorder, FontParam.PACKAGE, FontParam.PACKAGE_STEREOTYPE); + public static final SkinParameter PACKAGE = new SkinParameter(SName.package_, "PACKAGE", + ColorParam.packageBackground, ColorParam.packageBorder, FontParam.PACKAGE, FontParam.PACKAGE_STEREOTYPE); - public static final SkinParameter CARD = new SkinParameter("CARD", ColorParam.cardBackground, - ColorParam.cardBorder, FontParam.CARD, FontParam.CARD_STEREOTYPE, LineParam.cardBorder, - CornerParam.card); + public static final SkinParameter CARD = new SkinParameter(SName.card, "CARD", ColorParam.cardBackground, + ColorParam.cardBorder, FontParam.CARD, FontParam.CARD_STEREOTYPE, LineParam.cardBorder, CornerParam.card); - public static final SkinParameter RECTANGLE = new SkinParameter("RECTANGLE", ColorParam.rectangleBackground, - ColorParam.rectangleBorder, FontParam.RECTANGLE, FontParam.RECTANGLE_STEREOTYPE, LineParam.rectangleBorder, - CornerParam.rectangle); + public static final SkinParameter RECTANGLE = new SkinParameter(SName.rectangle, "RECTANGLE", + ColorParam.rectangleBackground, ColorParam.rectangleBorder, FontParam.RECTANGLE, + FontParam.RECTANGLE_STEREOTYPE, LineParam.rectangleBorder, CornerParam.rectangle); - public static final SkinParameter ARCHIMATE = new SkinParameter("ARCHIMATE", ColorParam.archimateBackground, - ColorParam.archimateBorder, FontParam.ARCHIMATE, FontParam.ARCHIMATE_STEREOTYPE, LineParam.archimateBorder, - CornerParam.archimate); + public static final SkinParameter ARCHIMATE = new SkinParameter(SName.archimate, "ARCHIMATE", + ColorParam.archimateBackground, ColorParam.archimateBorder, FontParam.ARCHIMATE, + FontParam.ARCHIMATE_STEREOTYPE, LineParam.archimateBorder, CornerParam.archimate); - public static final SkinParameter COLLECTIONS = new SkinParameter("COLLECTIONS", ColorParam.collectionsBackground, - ColorParam.collectionsBorder, FontParam.RECTANGLE, FontParam.RECTANGLE_STEREOTYPE); + public static final SkinParameter COLLECTIONS = new SkinParameter(SName.collection, "COLLECTIONS", + ColorParam.collectionsBackground, ColorParam.collectionsBorder, FontParam.RECTANGLE, + FontParam.RECTANGLE_STEREOTYPE); - public static final SkinParameter ACTOR = new SkinParameter("ACTOR", ColorParam.actorBackground, + public static final SkinParameter ACTOR = new SkinParameter(SName.actor, "ACTOR", ColorParam.actorBackground, ColorParam.actorBorder, FontParam.ACTOR, FontParam.ACTOR_STEREOTYPE); - public static final SkinParameter USECASE = new SkinParameter("USECASE", ColorParam.usecaseBackground, - ColorParam.usecaseBorder, FontParam.USECASE, FontParam.USECASE_STEREOTYPE); + public static final SkinParameter USECASE = new SkinParameter(SName.usecase, "USECASE", + ColorParam.usecaseBackground, ColorParam.usecaseBorder, FontParam.USECASE, FontParam.USECASE_STEREOTYPE); - public static final SkinParameter BOUNDARY = new SkinParameter("BOUNDARY", ColorParam.boundaryBackground, - ColorParam.boundaryBorder, FontParam.BOUNDARY, FontParam.BOUNDARY_STEREOTYPE); + public static final SkinParameter BOUNDARY = new SkinParameter(SName.boundary, "BOUNDARY", + ColorParam.boundaryBackground, ColorParam.boundaryBorder, FontParam.BOUNDARY, + FontParam.BOUNDARY_STEREOTYPE); - public static final SkinParameter CONTROL = new SkinParameter("CONTROL", ColorParam.controlBackground, - ColorParam.controlBorder, FontParam.CONTROL, FontParam.CONTROL_STEREOTYPE); + public static final SkinParameter CONTROL = new SkinParameter(SName.control, "CONTROL", + ColorParam.controlBackground, ColorParam.controlBorder, FontParam.CONTROL, FontParam.CONTROL_STEREOTYPE); - public static final SkinParameter ENTITY = new SkinParameter("ENTITY", ColorParam.entityBackground, + public static final SkinParameter ENTITY = new SkinParameter(SName.entity, "ENTITY", ColorParam.entityBackground, ColorParam.entityBorder, FontParam.ENTITY, FontParam.ENTITY_STEREOTYPE); - public static final SkinParameter INTERFACE = new SkinParameter("INTERFACE", ColorParam.interfaceBackground, - ColorParam.interfaceBorder, FontParam.INTERFACE, FontParam.INTERFACE_STEREOTYPE); + public static final SkinParameter INTERFACE = new SkinParameter(SName.interface_, "INTERFACE", + ColorParam.interfaceBackground, ColorParam.interfaceBorder, FontParam.INTERFACE, + FontParam.INTERFACE_STEREOTYPE); - public static final SkinParameter PARTICIPANT = new SkinParameter("PARTICIPANT", ColorParam.participantBackground, - ColorParam.participantBorder, FontParam.PARTICIPANT, FontParam.PARTICIPANT_STEREOTYPE); + public static final SkinParameter PARTICIPANT = new SkinParameter(SName.participant, "PARTICIPANT", + ColorParam.participantBackground, ColorParam.participantBorder, FontParam.PARTICIPANT, + FontParam.PARTICIPANT_STEREOTYPE); private final ColorParam colorParamBorder; private final ColorParam colorParamBack; @@ -132,10 +139,16 @@ public class SkinParameter { private final String name; private final LineParam lineParam; private final CornerParam roundParam; + private final SName styleName; - private SkinParameter(String name, ColorParam colorParamBack, ColorParam colorParamBorder, FontParam fontParam, - FontParam fontParamStereotype, LineParam lineParam, CornerParam roundParam) { + public SName getStyleName() { + return styleName; + } + + private SkinParameter(SName styleName, String name, ColorParam colorParamBack, ColorParam colorParamBorder, + FontParam fontParam, FontParam fontParamStereotype, LineParam lineParam, CornerParam roundParam) { this.name = name; + this.styleName = styleName; this.colorParamBack = colorParamBack; this.colorParamBorder = colorParamBorder; this.fontParam = fontParam; @@ -144,9 +157,10 @@ public class SkinParameter { this.roundParam = roundParam; } - private SkinParameter(String name, ColorParam colorParamBack, ColorParam colorParamBorder, FontParam fontParam, - FontParam fontParamStereotype) { - this(name, colorParamBack, colorParamBorder, fontParam, fontParamStereotype, null, CornerParam.DEFAULT); + private SkinParameter(SName styleName, String name, ColorParam colorParamBack, ColorParam colorParamBorder, + FontParam fontParam, FontParam fontParamStereotype) { + this(styleName, name, colorParamBack, colorParamBorder, fontParam, fontParamStereotype, null, + CornerParam.DEFAULT); } public String getUpperCaseName() { diff --git a/src/net/sourceforge/plantuml/graphic/TextBlockBordered.java b/src/net/sourceforge/plantuml/graphic/TextBlockBordered.java index 4aae90c5d..91466f025 100644 --- a/src/net/sourceforge/plantuml/graphic/TextBlockBordered.java +++ b/src/net/sourceforge/plantuml/graphic/TextBlockBordered.java @@ -39,6 +39,7 @@ import java.awt.geom.Dimension2D; import net.sourceforge.plantuml.Dimension2DDouble; import net.sourceforge.plantuml.creole.SheetBlock2; +import net.sourceforge.plantuml.style.ClockwiseTopRightBottomLeft; import net.sourceforge.plantuml.ugraphic.Shadowable; import net.sourceforge.plantuml.ugraphic.UGraphic; import net.sourceforge.plantuml.ugraphic.URectangle; @@ -52,8 +53,10 @@ public class TextBlockBordered extends AbstractTextBlock implements TextBlock { private final double cornersize; private final HColor backgroundColor; private final HColor borderColor; - private final double marginX; - private final double marginY; + private final double top; + private final double right; + private final double bottom; + private final double left; private final UStroke stroke; private final boolean withShadow; @@ -61,8 +64,24 @@ public class TextBlockBordered extends AbstractTextBlock implements TextBlock { TextBlockBordered(TextBlock textBlock, UStroke stroke, HColor borderColor, HColor backgroundColor, double cornersize, double marginX, double marginY) { - this.marginX = marginX; - this.marginY = marginY; + this.top = marginY; + this.right = marginX; + this.bottom = marginY; + this.left = marginX; + this.cornersize = cornersize; + this.textBlock = textBlock; + this.withShadow = false; + this.stroke = stroke; + this.borderColor = borderColor; + this.backgroundColor = backgroundColor; + } + + TextBlockBordered(TextBlock textBlock, UStroke stroke, HColor borderColor, HColor backgroundColor, + double cornersize, ClockwiseTopRightBottomLeft margins) { + this.top = margins.getTop(); + this.right = margins.getRight(); + this.bottom = margins.getBottom(); + this.left = margins.getLeft(); this.cornersize = cornersize; this.textBlock = textBlock; this.withShadow = false; @@ -78,7 +97,7 @@ public class TextBlockBordered extends AbstractTextBlock implements TextBlock { private double getTextHeight(StringBounder stringBounder) { final Dimension2D size = textBlock.calculateDimension(stringBounder); - return size.getHeight() + 2 * marginY; + return size.getHeight() + top + bottom; } private double getPureTextWidth(StringBounder stringBounder) { @@ -87,7 +106,7 @@ public class TextBlockBordered extends AbstractTextBlock implements TextBlock { } private double getTextWidth(StringBounder stringBounder) { - return getPureTextWidth(stringBounder) + 2 * marginX; + return getPureTextWidth(stringBounder) + left + right; } public Dimension2D calculateDimension(StringBounder stringBounder) { @@ -131,9 +150,9 @@ public class TextBlockBordered extends AbstractTextBlock implements TextBlock { ug.draw(polygon); TextBlock toDraw = textBlock; if (textBlock instanceof SheetBlock2) { - toDraw = ((SheetBlock2) textBlock).enlargeMe(marginX); + toDraw = ((SheetBlock2) textBlock).enlargeMe(left, right); } - toDraw.drawU(ugOriginal.apply(color).apply(new UTranslate(marginX, marginY))); + toDraw.drawU(ugOriginal.apply(color).apply(new UTranslate(left, top))); } private Shadowable getPolygonNormal(final StringBounder stringBounder) { diff --git a/src/net/sourceforge/plantuml/graphic/TextBlockMarged.java b/src/net/sourceforge/plantuml/graphic/TextBlockMarged.java index 32f683e0a..ad154e8bd 100644 --- a/src/net/sourceforge/plantuml/graphic/TextBlockMarged.java +++ b/src/net/sourceforge/plantuml/graphic/TextBlockMarged.java @@ -39,6 +39,7 @@ import java.awt.geom.Dimension2D; import java.awt.geom.Rectangle2D; import net.sourceforge.plantuml.Dimension2DDouble; +import net.sourceforge.plantuml.style.ClockwiseTopRightBottomLeft; import net.sourceforge.plantuml.svek.Ports; import net.sourceforge.plantuml.svek.WithPorts; import net.sourceforge.plantuml.ugraphic.UGraphic; @@ -47,26 +48,34 @@ import net.sourceforge.plantuml.ugraphic.UTranslate; class TextBlockMarged extends AbstractTextBlock implements TextBlock, WithPorts { private final TextBlock textBlock; - private final double x1; - private final double x2; - private final double y1; - private final double y2; + private final double top; + private final double right; + private final double bottom; + private final double left; - TextBlockMarged(TextBlock textBlock, double x1, double x2, double y1, double y2) { + TextBlockMarged(TextBlock textBlock, double top, double right, double bottom, double left) { this.textBlock = textBlock; - this.x1 = x1; - this.x2 = x2; - this.y1 = y1; - this.y2 = y2; + this.top = top; + this.right = right; + this.bottom = bottom; + this.left = left; + } + + TextBlockMarged(TextBlock textBlock, ClockwiseTopRightBottomLeft margins) { + this.textBlock = textBlock; + this.top = margins.getTop(); + this.right = margins.getRight(); + this.bottom = margins.getBottom(); + this.left = margins.getLeft(); } public Dimension2D calculateDimension(StringBounder stringBounder) { final Dimension2D dim = textBlock.calculateDimension(stringBounder); - return Dimension2DDouble.delta(dim, x1 + x2, y1 + y2); + return Dimension2DDouble.delta(dim, left + right, top + bottom); } public void drawU(UGraphic ug) { - final UTranslate translate = new UTranslate(x1, y1); + final UTranslate translate = new UTranslate(left, top); textBlock.drawU(ug.apply(translate)); } @@ -76,12 +85,12 @@ class TextBlockMarged extends AbstractTextBlock implements TextBlock, WithPorts if (parent == null) { return null; } - final UTranslate translate = new UTranslate(x1, y1); + final UTranslate translate = new UTranslate(left, top); return translate.apply(parent); } public Ports getPorts(StringBounder stringBounder) { - return ((WithPorts) textBlock).getPorts(stringBounder).translateY(y1); + return ((WithPorts) textBlock).getPorts(stringBounder).translateY(top); } } \ No newline at end of file diff --git a/src/net/sourceforge/plantuml/graphic/TextBlockUtils.java b/src/net/sourceforge/plantuml/graphic/TextBlockUtils.java index f32935dca..94e4a959d 100644 --- a/src/net/sourceforge/plantuml/graphic/TextBlockUtils.java +++ b/src/net/sourceforge/plantuml/graphic/TextBlockUtils.java @@ -55,6 +55,7 @@ import net.sourceforge.plantuml.cucadiagram.Display; import net.sourceforge.plantuml.posimo.Positionable; import net.sourceforge.plantuml.posimo.PositionableImpl; import net.sourceforge.plantuml.skin.rose.Rose; +import net.sourceforge.plantuml.style.ClockwiseTopRightBottomLeft; import net.sourceforge.plantuml.svek.TextBlockBackcolored; import net.sourceforge.plantuml.ugraphic.LimitFinder; import net.sourceforge.plantuml.ugraphic.MinMax; @@ -77,6 +78,11 @@ public class TextBlockUtils { return new TextBlockBordered(textBlock, stroke, borderColor, backgroundColor, cornersize, marginX, marginY); } + public static TextBlock bordered(TextBlock textBlock, UStroke stroke, HColor borderColor, HColor backgroundColor, + double cornersize, ClockwiseTopRightBottomLeft margins) { + return new TextBlockBordered(textBlock, stroke, borderColor, backgroundColor, cornersize, margins); + } + public static TextBlock title(FontConfiguration font, Display stringsToDisplay, ISkinParam skinParam) { if (SkinParam.USE_STYLES()) { throw new UnsupportedOperationException(); @@ -100,12 +106,16 @@ public class TextBlockUtils { } public static TextBlock withMargin(TextBlock textBlock, double marginX, double marginY) { - return new TextBlockMarged(textBlock, marginX, marginX, marginY, marginY); + return new TextBlockMarged(textBlock, marginY, marginX, marginY, marginX); + } + + public static TextBlock withMargin(TextBlock textBlock, ClockwiseTopRightBottomLeft margins) { + return new TextBlockMarged(textBlock, margins); } public static TextBlock withMargin(TextBlock textBlock, double marginX1, double marginX2, double marginY1, double marginY2) { - return new TextBlockMarged(textBlock, marginX1, marginX2, marginY1, marginY2); + return new TextBlockMarged(textBlock, marginY1, marginX2, marginY2, marginX1); } public static TextBlock withMinWidth(TextBlock textBlock, double minWidth, diff --git a/src/net/sourceforge/plantuml/help/Help.java b/src/net/sourceforge/plantuml/help/Help.java index 4a9571420..1a3d3e5e9 100644 --- a/src/net/sourceforge/plantuml/help/Help.java +++ b/src/net/sourceforge/plantuml/help/Help.java @@ -79,8 +79,8 @@ public class Help extends UmlDiagram { CreoleMode.FULL).createSheet(display); final SheetBlock1 sheetBlock = new SheetBlock1(sheet, LineBreakStrategy.NONE, 0); - final ImageBuilder builder = new ImageBuilder(new ColorMapperIdentity(), 1.0, null, null, null, 0, 0, null, - false); + final ImageBuilder builder = ImageBuilder.buildA(new ColorMapperIdentity(), false, null, null, null, 1.0, + null); builder.setUDrawable(sheetBlock); return builder.writeImageTOBEMOVED(fileFormat, 0, os); } diff --git a/src/net/sourceforge/plantuml/jdot/CucaDiagramFileMakerJDot.java b/src/net/sourceforge/plantuml/jdot/CucaDiagramFileMakerJDot.java index 58ba9b9e1..76dc522f3 100644 --- a/src/net/sourceforge/plantuml/jdot/CucaDiagramFileMakerJDot.java +++ b/src/net/sourceforge/plantuml/jdot/CucaDiagramFileMakerJDot.java @@ -65,6 +65,7 @@ import h.ST_boxf; import net.sourceforge.plantuml.FileFormatOption; import net.sourceforge.plantuml.FontParam; import net.sourceforge.plantuml.ISkinParam; +import net.sourceforge.plantuml.SkinParam; import net.sourceforge.plantuml.StringUtils; import net.sourceforge.plantuml.UmlDiagram; import net.sourceforge.plantuml.api.ImageDataSimple; @@ -91,6 +92,7 @@ import net.sourceforge.plantuml.graphic.TextBlockUtils; import net.sourceforge.plantuml.graphic.TextBlockWidth; import net.sourceforge.plantuml.graphic.UDrawable; import net.sourceforge.plantuml.graphic.USymbol; +import net.sourceforge.plantuml.style.ClockwiseTopRightBottomLeft; import net.sourceforge.plantuml.svek.Bibliotekon; import net.sourceforge.plantuml.svek.Cluster; import net.sourceforge.plantuml.svek.CucaDiagramFileMaker; @@ -416,9 +418,17 @@ public class CucaDiagramFileMakerJDot implements CucaDiagramFileMaker { final double scale = 1; - final ImageBuilder imageBuilder = new ImageBuilder(diagram.getSkinParam(), scale, - fileFormatOption.isWithMetadata() ? diagram.getMetadata() : null, null, 0, 10, - diagram.getAnimation()); + final int margin1; + final int margin2; + if (SkinParam.USE_STYLES()) { + margin1 = SkinParam.zeroMargin(0); + margin2 = SkinParam.zeroMargin(10); + } else { + margin1 = 0; + margin2 = 10; + } + final ImageBuilder imageBuilder = ImageBuilder.buildD(diagram.getSkinParam(), ClockwiseTopRightBottomLeft.margin1margin2((double) margin1, (double) margin2), diagram.getAnimation(), fileFormatOption.isWithMetadata() ? diagram.getMetadata() : null, + null, scale); imageBuilder.setUDrawable(new Drawing(null)); final Dimension2D dim = imageBuilder.getFinalDimension(stringBounder); diff --git a/src/net/sourceforge/plantuml/jungle/PSystemTree.java b/src/net/sourceforge/plantuml/jungle/PSystemTree.java index aca8e052e..78589201c 100644 --- a/src/net/sourceforge/plantuml/jungle/PSystemTree.java +++ b/src/net/sourceforge/plantuml/jungle/PSystemTree.java @@ -41,12 +41,14 @@ import java.util.List; import net.sourceforge.plantuml.AbstractPSystem; import net.sourceforge.plantuml.FileFormatOption; +import net.sourceforge.plantuml.SkinParam; import net.sourceforge.plantuml.command.CommandExecutionResult; import net.sourceforge.plantuml.core.DiagramDescription; import net.sourceforge.plantuml.core.ImageData; import net.sourceforge.plantuml.cucadiagram.Display; import net.sourceforge.plantuml.graphic.UDrawable; import net.sourceforge.plantuml.graphic.UDrawableUtils; +import net.sourceforge.plantuml.style.ClockwiseTopRightBottomLeft; import net.sourceforge.plantuml.ugraphic.ImageBuilder; import net.sourceforge.plantuml.ugraphic.LimitFinder; import net.sourceforge.plantuml.ugraphic.color.ColorMapperIdentity; @@ -65,8 +67,17 @@ public class PSystemTree extends AbstractPSystem { @Override final protected ImageData exportDiagramNow(OutputStream os, int num, FileFormatOption fileFormat, long seed) throws IOException { - final ImageBuilder builder = new ImageBuilder(new ColorMapperIdentity(), 1.0, HColorUtils.WHITE, null, null, - 5, 5, null, false); + final int margin1; + final int margin2; + if (SkinParam.USE_STYLES()) { + margin1 = SkinParam.zeroMargin(5); + margin2 = SkinParam.zeroMargin(5); + } else { + margin1 = 5; + margin2 = 5; + } + final ImageBuilder builder = ImageBuilder.buildB(new ColorMapperIdentity(), false, ClockwiseTopRightBottomLeft.margin1margin2((double) margin1, (double) margin2), + null, null, null, 1.0, HColorUtils.WHITE); if (rendering == Rendering.NEEDLE) { final UDrawable tmp = Needle.getNeedle(root, 200, 0, 60); final LimitFinder limitFinder = new LimitFinder(fileFormat.getDefaultStringBounder(), true); diff --git a/src/net/sourceforge/plantuml/math/ScientificEquationSafe.java b/src/net/sourceforge/plantuml/math/ScientificEquationSafe.java index 8078528df..f3fdfd505 100644 --- a/src/net/sourceforge/plantuml/math/ScientificEquationSafe.java +++ b/src/net/sourceforge/plantuml/math/ScientificEquationSafe.java @@ -134,8 +134,8 @@ public class ScientificEquationSafe { private ImageBuilder getRollback() { final TextBlock block = GraphicStrings.createBlackOnWhiteMonospaced(Arrays.asList(formula)); - final ImageBuilder imageBuilder = new ImageBuilder(new ColorMapperIdentity(), 1.0, null, null, null, 0, 0, - null, false); + final ImageBuilder imageBuilder = ImageBuilder.buildA(new ColorMapperIdentity(), false, null, null, null, + 1.0, null); imageBuilder.setUDrawable(block); return imageBuilder; } diff --git a/src/net/sourceforge/plantuml/mindmap/CommandMindMapOrgmodeMultiline.java b/src/net/sourceforge/plantuml/mindmap/CommandMindMapOrgmodeMultiline.java index 9abd4309d..2d14d64ef 100644 --- a/src/net/sourceforge/plantuml/mindmap/CommandMindMapOrgmodeMultiline.java +++ b/src/net/sourceforge/plantuml/mindmap/CommandMindMapOrgmodeMultiline.java @@ -35,11 +35,15 @@ */ package net.sourceforge.plantuml.mindmap; +import java.util.List; + +import net.sourceforge.plantuml.StringUtils; import net.sourceforge.plantuml.command.BlocLines; import net.sourceforge.plantuml.command.CommandExecutionResult; import net.sourceforge.plantuml.command.CommandMultilines2; import net.sourceforge.plantuml.command.MultilinesStrategy; import net.sourceforge.plantuml.command.regex.IRegex; +import net.sourceforge.plantuml.command.regex.MyPattern; import net.sourceforge.plantuml.command.regex.RegexConcat; import net.sourceforge.plantuml.command.regex.RegexLeaf; import net.sourceforge.plantuml.command.regex.RegexOptional; @@ -64,21 +68,34 @@ public class CommandMindMapOrgmodeMultiline extends CommandMultilines2\\>)?$"; } @Override protected CommandExecutionResult executeNow(MindMapDiagram diagram, BlocLines lines) { - final RegexResult line0 = getStartingPattern().matcher(lines.getFirst499().getTrimmed().getString()); + final RegexResult line0 = getStartingPattern().matcher(lines.getFirst().getTrimmed().getString()); + + final List lineLast = StringUtils.getSplit(MyPattern.cmpile(getPatternEnd()), + lines.getLast().getString()); + lines = lines.removeStartingAndEnding(line0.get("DATA", 0), 1); + + final String stereotype = lineLast.get(1); + if (stereotype != null) { + lines = lines.overrideLastLine(lineLast.get(0)); + } + final String type = line0.get("TYPE", 0); final String stringColor = line0.get("BACKCOLOR", 0); HColor backColor = null; if (stringColor != null) { backColor = diagram.getSkinParam().getIHtmlColorSet().getColorIfValid(stringColor); } - lines = lines.removeStartingAndEnding2(line0.get("DATA", 0)); - return diagram.addIdea(backColor, type.length() - 1, lines.toDisplay(), + if (stereotype == null) { + return diagram.addIdea(backColor, type.length() - 1, lines.toDisplay(), + IdeaShape.fromDesc(line0.get("SHAPE", 0))); + } + return diagram.addIdea(stereotype, backColor, type.length() - 1, lines.toDisplay(), IdeaShape.fromDesc(line0.get("SHAPE", 0))); } diff --git a/src/net/sourceforge/plantuml/mindmap/FingerImpl.java b/src/net/sourceforge/plantuml/mindmap/FingerImpl.java index 08039f2aa..b510364e7 100644 --- a/src/net/sourceforge/plantuml/mindmap/FingerImpl.java +++ b/src/net/sourceforge/plantuml/mindmap/FingerImpl.java @@ -79,7 +79,10 @@ public class FingerImpl implements Finger, UDrawable { private final Direction direction; private final int level; private boolean drawPhalanx = true; - private double margin = 10; + private double marginLeft = 10; + private double marginRight = 10; + private double marginTop = 10; + private double marginBottom = 10; private final List nail = new ArrayList(); private Tetris tetris = null; @@ -129,7 +132,10 @@ public class FingerImpl implements Finger, UDrawable { this.styleBuilder = styleBuilder; this.direction = direction; final Style styleNode = getDefaultStyleDefinitionNode().getMergedStyle(styleBuilder); - this.margin = styleNode.getMargin().asDouble(); + this.marginLeft = styleNode.getMargin().getLeft(); + this.marginRight = styleNode.getMargin().getRight(); + this.marginTop = styleNode.getMargin().getTop(); + this.marginBottom = styleNode.getMargin().getBottom(); } public void drawU(final UGraphic ug) { @@ -141,14 +147,14 @@ public class FingerImpl implements Finger, UDrawable { final double posX = direction == Direction.RIGHT ? 0 : -dimPhalanx.getWidth(); phalanx.drawU(ug.apply(new UTranslate(posX, posY))); } - final Point2D p1 = new Point2D.Double(direction == Direction.RIGHT ? dimPhalanx.getWidth() - : -dimPhalanx.getWidth(), 0); + final Point2D p1 = new Point2D.Double( + direction == Direction.RIGHT ? dimPhalanx.getWidth() : -dimPhalanx.getWidth(), 0); for (int i = 0; i < nail.size(); i++) { final FingerImpl child = nail.get(i); final SymetricalTeePositioned stp = tetris(stringBounder).getElements().get(i); - final double x = direction == Direction.RIGHT ? dimPhalanx.getWidth() + getX12() : -dimPhalanx.getWidth() - - getX12(); + final double x = direction == Direction.RIGHT ? dimPhalanx.getWidth() + getX12() + : -dimPhalanx.getWidth() - getX12(); final Point2D p2 = new Point2D.Double(x, stp.getY()); child.drawU(ug.apply(new UTranslate(p2))); drawLine(ug.apply(getLinkColor()).apply(getUStroke()), p1, p2); @@ -210,11 +216,11 @@ public class FingerImpl implements Finger, UDrawable { } private double getX1() { - return margin(); + return marginLeft; } private double getX2() { - return margin() + 30; + return marginRight + 30; } public double getX12() { @@ -241,10 +247,11 @@ public class FingerImpl implements Finger, UDrawable { font = skinParam.getFont(null, false, FontParam.ACTIVITY); } if (shape == IdeaShape.BOX) { - // final ISkinParam foo = new SkinParamBackcolored(Colors.empty().mute(skinParam), backColor); + // final ISkinParam foo = new + // SkinParamBackcolored(Colors.empty().mute(skinParam), backColor); final ISkinParam foo = new SkinParamColors(skinParam, Colors.empty().add(ColorType.BACK, backColor)); final FtileBox box = FtileBox.createMindMap(styleBuilder, foo, label, getDefaultStyleDefinitionNode()); - return TextBlockUtils.withMargin(box, 0, 0, margin(), margin()); + return TextBlockUtils.withMargin(box, 0, 0, marginTop, marginBottom); } final TextBlock text = label.create(FontConfiguration.blackBlueTrue(font), HorizontalAlignment.LEFT, skinParam); @@ -254,10 +261,6 @@ public class FingerImpl implements Finger, UDrawable { return TextBlockUtils.withMargin(text, 0, 3, 1, 1); } - private double margin() { - return margin; - } - public double getNailThickness(StringBounder stringBounder) { return tetris(stringBounder).getHeight(); } diff --git a/src/net/sourceforge/plantuml/mindmap/Idea.java b/src/net/sourceforge/plantuml/mindmap/Idea.java index 22479420a..dde8d43e2 100644 --- a/src/net/sourceforge/plantuml/mindmap/Idea.java +++ b/src/net/sourceforge/plantuml/mindmap/Idea.java @@ -66,8 +66,8 @@ class Idea { return result; } - private Idea(StyleBuilder styleBuilder, HColor backColor, int level, Idea parent, Display label, - IdeaShape shape, String stereotype) { + private Idea(StyleBuilder styleBuilder, HColor backColor, int level, Idea parent, Display label, IdeaShape shape, + String stereotype) { this.backColor = backColor; this.styleBuilder = styleBuilder; this.label = label; diff --git a/src/net/sourceforge/plantuml/mindmap/MindMapDiagram.java b/src/net/sourceforge/plantuml/mindmap/MindMapDiagram.java index 850fa4d24..051cdffbc 100644 --- a/src/net/sourceforge/plantuml/mindmap/MindMapDiagram.java +++ b/src/net/sourceforge/plantuml/mindmap/MindMapDiagram.java @@ -46,6 +46,7 @@ import net.sourceforge.plantuml.Direction; import net.sourceforge.plantuml.FileFormatOption; import net.sourceforge.plantuml.ISkinParam; import net.sourceforge.plantuml.Scale; +import net.sourceforge.plantuml.SkinParam; import net.sourceforge.plantuml.UmlDiagram; import net.sourceforge.plantuml.UmlDiagramType; import net.sourceforge.plantuml.command.CommandExecutionResult; @@ -55,6 +56,7 @@ import net.sourceforge.plantuml.cucadiagram.Display; import net.sourceforge.plantuml.graphic.InnerStrategy; import net.sourceforge.plantuml.graphic.StringBounder; import net.sourceforge.plantuml.graphic.TextBlock; +import net.sourceforge.plantuml.style.ClockwiseTopRightBottomLeft; import net.sourceforge.plantuml.style.StyleBuilder; import net.sourceforge.plantuml.svek.TextBlockBackcolored; import net.sourceforge.plantuml.ugraphic.ImageBuilder; @@ -90,9 +92,17 @@ public class MindMapDiagram extends UmlDiagram { final double dpiFactor = scale == null ? getScaleCoef(fileFormatOption) : scale.getScale(100, 100); final ISkinParam skinParam = getSkinParam(); - final ImageBuilder imageBuilder = new ImageBuilder(skinParam.getColorMapper(), dpiFactor, - skinParam.getBackgroundColor(false), fileFormatOption.isWithMetadata() ? getMetadata() : null, "", 10, 10, - null, skinParam.handwritten()); + final int margin1; + final int margin2; + if (SkinParam.USE_STYLES()) { + margin1 = SkinParam.zeroMargin(10); + margin2 = SkinParam.zeroMargin(10); + } else { + margin1 = 10; + margin2 = 10; + } + final ImageBuilder imageBuilder = ImageBuilder.buildB(skinParam.getColorMapper(), skinParam.handwritten(), ClockwiseTopRightBottomLeft.margin1margin2((double) margin1, (double) margin2), + null, fileFormatOption.isWithMetadata() ? getMetadata() : null, "", dpiFactor, skinParam.getBackgroundColor(false)); TextBlock result = getTextBlock(); result = new AnnotatedWorker(this, skinParam, fileFormatOption.getDefaultStringBounder()).addAdd(result); @@ -149,8 +159,8 @@ public class MindMapDiagram extends UmlDiagram { final double y2 = left.finger == null ? 0 : left.finger.getFullThickness(stringBounder) / 2; final double y = Math.max(y1, y2); - final double x = left.finger == null ? 0 : left.finger.getFullElongation(stringBounder) - + ((FingerImpl) left.finger).getX12(); + final double x = left.finger == null ? 0 + : left.finger.getFullElongation(stringBounder) + ((FingerImpl) left.finger).getX12(); if (right.finger != null) { right.finger.drawU(ug.apply(new UTranslate(x, y))); } @@ -183,10 +193,20 @@ public class MindMapDiagram extends UmlDiagram { if (stereotype != null) { label = label.removeEndingStereotype(); } + return addIdeaInternal(stereotype, backColor, level, label, shape, direction); + } + + public CommandExecutionResult addIdea(String stereotype, HColor backColor, int level, Display label, + IdeaShape shape) { + return addIdeaInternal(stereotype, backColor, level, label, shape, defaultDirection); + } + + private CommandExecutionResult addIdeaInternal(String stereotype, HColor backColor, int level, Display label, + IdeaShape shape, Direction direction) { if (level == 0) { if (this.right.root != null) { - return CommandExecutionResult - .error("I don't know how to draw multi-root diagram. You should suggest an image so that the PlantUML team implements it :-)"); + return CommandExecutionResult.error( + "I don't know how to draw multi-root diagram. You should suggest an image so that the PlantUML team implements it :-)"); } right.initRoot(getSkinParam().getCurrentStyleBuilder(), backColor, label, shape, stereotype); left.initRoot(getSkinParam().getCurrentStyleBuilder(), backColor, label, shape, stereotype); @@ -203,7 +223,8 @@ public class MindMapDiagram extends UmlDiagram { private Idea last; private Finger finger; - private void initRoot(StyleBuilder styleBuilder, HColor backColor, Display label, IdeaShape shape, String stereotype) { + private void initRoot(StyleBuilder styleBuilder, HColor backColor, Display label, IdeaShape shape, + String stereotype) { root = new Idea(styleBuilder, backColor, label, shape, stereotype); last = root; } diff --git a/src/net/sourceforge/plantuml/nwdiag/NwDiagram.java b/src/net/sourceforge/plantuml/nwdiag/NwDiagram.java index 7dfa9b66a..198833715 100644 --- a/src/net/sourceforge/plantuml/nwdiag/NwDiagram.java +++ b/src/net/sourceforge/plantuml/nwdiag/NwDiagram.java @@ -52,6 +52,7 @@ import net.sourceforge.plantuml.Dimension2DDouble; import net.sourceforge.plantuml.FileFormatOption; import net.sourceforge.plantuml.ISkinParam; import net.sourceforge.plantuml.Scale; +import net.sourceforge.plantuml.SkinParam; import net.sourceforge.plantuml.SpriteContainerEmpty; import net.sourceforge.plantuml.UmlDiagram; import net.sourceforge.plantuml.UmlDiagramType; @@ -66,6 +67,7 @@ import net.sourceforge.plantuml.graphic.StringBounder; import net.sourceforge.plantuml.graphic.TextBlock; import net.sourceforge.plantuml.graphic.TextBlockUtils; import net.sourceforge.plantuml.graphic.UDrawable; +import net.sourceforge.plantuml.style.ClockwiseTopRightBottomLeft; import net.sourceforge.plantuml.svek.TextBlockBackcolored; import net.sourceforge.plantuml.ugraphic.ImageBuilder; import net.sourceforge.plantuml.ugraphic.MinMax; @@ -185,8 +187,17 @@ public class NwDiagram extends UmlDiagram { final double dpiFactor = scale == null ? 1 : scale.getScale(100, 100); final ISkinParam skinParam = getSkinParam(); - final ImageBuilder imageBuilder = new ImageBuilder(new ColorMapperIdentity(), dpiFactor, null, "", "", 0, 0, - null, false); + final int margin1; + final int margin2; + if (SkinParam.USE_STYLES()) { + margin1 = SkinParam.zeroMargin(0); + margin2 = SkinParam.zeroMargin(0); + } else { + margin1 = 0; + margin2 = 0; + } + final ImageBuilder imageBuilder = ImageBuilder.buildB(new ColorMapperIdentity(), false, ClockwiseTopRightBottomLeft.margin1margin2((double) margin1, (double) margin2), + null, "", "", dpiFactor, null); TextBlock result = getTextBlock(); result = new AnnotatedWorker(this, skinParam, fileFormatOption.getDefaultStringBounder()).addAdd(result); imageBuilder.setUDrawable(result); diff --git a/src/net/sourceforge/plantuml/objectdiagram/command/CommandCreateEntityObjectMultilines.java b/src/net/sourceforge/plantuml/objectdiagram/command/CommandCreateEntityObjectMultilines.java index 7941695d4..4fd7637be 100644 --- a/src/net/sourceforge/plantuml/objectdiagram/command/CommandCreateEntityObjectMultilines.java +++ b/src/net/sourceforge/plantuml/objectdiagram/command/CommandCreateEntityObjectMultilines.java @@ -86,8 +86,8 @@ public class CommandCreateEntityObjectMultilines extends CommandMultilines2 line0 = StringUtils.getSplit(getStartingPattern(), lines.getFirst499().getTrimmed() + final List line0 = StringUtils.getSplit(getStartingPattern(), lines.getFirst().getTrimmed() .getString()); final HColor backColorElement = diagram.getSkinParam().getIHtmlColorSet().getColorIfValid(line0.get(0)); // final HtmlColor backColorGeneral = HtmlColorSetSimple.instance().getColorIfValid(line0.get(1)); diff --git a/src/net/sourceforge/plantuml/sequencediagram/graphic/SequenceDiagramFileMakerPuma2.java b/src/net/sourceforge/plantuml/sequencediagram/graphic/SequenceDiagramFileMakerPuma2.java index 952d846ed..32a44cc2e 100644 --- a/src/net/sourceforge/plantuml/sequencediagram/graphic/SequenceDiagramFileMakerPuma2.java +++ b/src/net/sourceforge/plantuml/sequencediagram/graphic/SequenceDiagramFileMakerPuma2.java @@ -66,6 +66,7 @@ import net.sourceforge.plantuml.sequencediagram.Newpage; import net.sourceforge.plantuml.sequencediagram.Participant; import net.sourceforge.plantuml.sequencediagram.SequenceDiagram; import net.sourceforge.plantuml.skin.rose.Rose; +import net.sourceforge.plantuml.style.ClockwiseTopRightBottomLeft; import net.sourceforge.plantuml.style.SName; import net.sourceforge.plantuml.style.Style; import net.sourceforge.plantuml.style.StyleSignature; @@ -85,7 +86,8 @@ public class SequenceDiagramFileMakerPuma2 implements FileMaker { private double scale; - public SequenceDiagramFileMakerPuma2(SequenceDiagram sequenceDiagram, Rose skin, FileFormatOption fileFormatOption) { + public SequenceDiagramFileMakerPuma2(SequenceDiagram sequenceDiagram, Rose skin, + FileFormatOption fileFormatOption) { this.diagram = sequenceDiagram; this.stringBounder = fileFormatOption.getDefaultStringBounder(); this.fileFormatOption = fileFormatOption; @@ -158,14 +160,15 @@ public class SequenceDiagramFileMakerPuma2 implements FileMaker { compTitle = null; } else { if (SkinParam.USE_STYLES()) { - final Style style = StyleSignature.of(SName.root, SName.title).getMergedStyle( - diagram.getSkinParam().getCurrentStyleBuilder()); + final Style style = StyleSignature.of(SName.root, SName.title) + .getMergedStyle(diagram.getSkinParam().getCurrentStyleBuilder()); compTitle = style.createTextBlockBordered(page.getTitle(), diagram.getSkinParam().getIHtmlColorSet(), diagram.getSkinParam()); } else { - compTitle = TextBlockUtils.withMargin(TextBlockUtils.title( - new FontConfiguration(drawableSet.getSkinParam(), FontParam.TITLE, null), - page.getTitle(), drawableSet.getSkinParam()), 7, 7); + compTitle = TextBlockUtils.withMargin( + TextBlockUtils.title(new FontConfiguration(drawableSet.getSkinParam(), FontParam.TITLE, null), + page.getTitle(), drawableSet.getSkinParam()), + 7, 7); } final Dimension2D dimTitle = compTitle.calculateDimension(stringBounder); area.setTitleArea(dimTitle.getWidth(), dimTitle.getHeight()); @@ -179,10 +182,10 @@ public class SequenceDiagramFileMakerPuma2 implements FileMaker { legendBlock = TextBlockUtils.empty(0, 0); } else { if (SkinParam.USE_STYLES()) { - final Style style = StyleSignature.of(SName.root, SName.legend).getMergedStyle( - diagram.getSkinParam().getCurrentStyleBuilder()); - legendBlock = style.createTextBlockBordered(legend.getDisplay(), diagram.getSkinParam() - .getIHtmlColorSet(), diagram.getSkinParam()); + final Style style = StyleSignature.of(SName.root, SName.legend) + .getMergedStyle(diagram.getSkinParam().getCurrentStyleBuilder()); + legendBlock = style.createTextBlockBordered(legend.getDisplay(), + diagram.getSkinParam().getIHtmlColorSet(), diagram.getSkinParam()); } else { legendBlock = EntityImageLegend.create(legend.getDisplay(), diagram.getSkinParam()); } @@ -197,8 +200,17 @@ public class SequenceDiagramFileMakerPuma2 implements FileMaker { final String metadata = fileFormatOption.isWithMetadata() ? diagram.getMetadata() : null; - final ImageBuilder imageBuilder = new ImageBuilder(diagram.getSkinParam(), oneOf(scale, dpiFactor), metadata, - null, 3, 10, diagram.getAnimation()); + final int margin1; + final int margin2; + if (SkinParam.USE_STYLES()) { + margin1 = SkinParam.zeroMargin(3); + margin2 = SkinParam.zeroMargin(10); + } else { + margin1 = 3; + margin2 = 10; + } + final ImageBuilder imageBuilder = ImageBuilder.buildD(diagram.getSkinParam(), ClockwiseTopRightBottomLeft.margin1margin2((double) margin1, (double) margin2), diagram.getAnimation(), metadata, + null, oneOf(scale, dpiFactor)); imageBuilder.setUDrawable(new UDrawable() { public void drawU(UGraphic ug) { @@ -231,7 +243,8 @@ public class SequenceDiagramFileMakerPuma2 implements FileMaker { sequenceAreaY += legendBlock.calculateDimension(ug.getStringBounder()).getHeight(); } final UTranslate forCore = new UTranslate(area.getSequenceAreaX() + delta1 / 2, sequenceAreaY); - TextBlock core = drawableSet.asTextBlock(delta, fullDimension.getWidth(), page, diagram.isShowFootbox()); + TextBlock core = drawableSet.asTextBlock(delta, fullDimension.getWidth(), page, + diagram.isShowFootbox()); core = annotatedWorker.addFrame(core); core.drawU(ug.apply(forCore)); // drawableSet.drawU22(ug.apply(forCore), delta, fullDimension.getWidth(), page, @@ -263,8 +276,8 @@ public class SequenceDiagramFileMakerPuma2 implements FileMaker { if (text == null) { return; } - text.drawU(ug.apply(new UTranslate(area.getFooterX(diagram.getFooter().getHorizontalAlignment()), area - .getFooterY() + legendHeight))); + text.drawU(ug.apply(new UTranslate(area.getFooterX(diagram.getFooter().getHorizontalAlignment()), + area.getFooterY() + legendHeight))); } private void drawHeader(SequenceDiagramArea area, UGraphic ug, int page) { @@ -273,8 +286,8 @@ public class SequenceDiagramFileMakerPuma2 implements FileMaker { if (text == null) { return; } - text.drawU(ug.apply(new UTranslate(area.getHeaderX(diagram.getHeader().getHorizontalAlignment()), area - .getHeaderY()))); + text.drawU(ug.apply( + new UTranslate(area.getHeaderX(diagram.getHeader().getHorizontalAlignment()), area.getHeaderY()))); } private double oneOf(double a, double b) { diff --git a/src/net/sourceforge/plantuml/sequencediagram/teoz/SequenceDiagramFileMakerTeoz.java b/src/net/sourceforge/plantuml/sequencediagram/teoz/SequenceDiagramFileMakerTeoz.java index 31c5d0b4a..3d8d0972e 100644 --- a/src/net/sourceforge/plantuml/sequencediagram/teoz/SequenceDiagramFileMakerTeoz.java +++ b/src/net/sourceforge/plantuml/sequencediagram/teoz/SequenceDiagramFileMakerTeoz.java @@ -65,6 +65,7 @@ import net.sourceforge.plantuml.sequencediagram.SequenceDiagram; import net.sourceforge.plantuml.sequencediagram.graphic.FileMaker; import net.sourceforge.plantuml.skin.SimpleContext2D; import net.sourceforge.plantuml.skin.rose.Rose; +import net.sourceforge.plantuml.style.ClockwiseTopRightBottomLeft; import net.sourceforge.plantuml.style.SName; import net.sourceforge.plantuml.style.Style; import net.sourceforge.plantuml.style.StyleSignature; @@ -149,8 +150,17 @@ public class SequenceDiagramFileMakerTeoz implements FileMaker { final double scale = 1; final String metadata = fileFormatOption.isWithMetadata() ? diagram.getMetadata() : null; - final ImageBuilder imageBuilder = new ImageBuilder(diagram.getSkinParam(), oneOf(scale, dpiFactor), metadata, - null, 3, 10, diagram.getAnimation()); + final int margin1; + final int margin2; + if (SkinParam.USE_STYLES()) { + margin1 = SkinParam.zeroMargin(3); + margin2 = SkinParam.zeroMargin(10); + } else { + margin1 = 3; + margin2 = 10; + } + final ImageBuilder imageBuilder = ImageBuilder.buildD(diagram.getSkinParam(), ClockwiseTopRightBottomLeft.margin1margin2((double) margin1, (double) margin2), diagram.getAnimation(), metadata, + null, oneOf(scale, dpiFactor)); imageBuilder.setUDrawable(new Foo(index)); return imageBuilder.writeImageTOBEMOVED(fileFormatOption, diagram.seed(), os); diff --git a/src/net/sourceforge/plantuml/sprite/ListSpriteDiagram.java b/src/net/sourceforge/plantuml/sprite/ListSpriteDiagram.java index f2308849b..70211eb15 100644 --- a/src/net/sourceforge/plantuml/sprite/ListSpriteDiagram.java +++ b/src/net/sourceforge/plantuml/sprite/ListSpriteDiagram.java @@ -42,6 +42,7 @@ import java.io.OutputStream; import net.sourceforge.plantuml.Dimension2DDouble; import net.sourceforge.plantuml.FileFormatOption; import net.sourceforge.plantuml.ISkinSimple; +import net.sourceforge.plantuml.SkinParam; import net.sourceforge.plantuml.UmlDiagram; import net.sourceforge.plantuml.UmlDiagramType; import net.sourceforge.plantuml.core.DiagramDescription; @@ -53,6 +54,7 @@ import net.sourceforge.plantuml.graphic.HorizontalAlignment; import net.sourceforge.plantuml.graphic.StringBounder; import net.sourceforge.plantuml.graphic.TextBlock; import net.sourceforge.plantuml.graphic.TextBlockUtils; +import net.sourceforge.plantuml.style.ClockwiseTopRightBottomLeft; import net.sourceforge.plantuml.ugraphic.ImageBuilder; import net.sourceforge.plantuml.ugraphic.UFont; import net.sourceforge.plantuml.ugraphic.UGraphic; @@ -79,12 +81,19 @@ public class ListSpriteDiagram extends UmlDiagram { throws IOException { final TextBlock result = getTable(); - final double margin = 10; final double dpiFactor = 1; - final ImageBuilder imageBuilder = new ImageBuilder(getSkinParam(), dpiFactor, - fileFormatOption.isWithMetadata() ? getMetadata() : null, getWarningOrError(), margin, margin, - getAnimation()); + final int margin1; + final int margin2; + if (SkinParam.USE_STYLES()) { + margin1 = SkinParam.zeroMargin(10); + margin2 = SkinParam.zeroMargin(10); + } else { + margin1 = 10; + margin2 = 10; + } + final ImageBuilder imageBuilder = ImageBuilder.buildD(getSkinParam(), ClockwiseTopRightBottomLeft.margin1margin2((double) margin1, (double) margin2), getAnimation(), fileFormatOption.isWithMetadata() ? getMetadata() : null, + getWarningOrError(), dpiFactor); imageBuilder.setUDrawable(result); return imageBuilder.writeImageTOBEMOVED(fileFormatOption, seed(), os); @@ -99,9 +108,8 @@ public class ListSpriteDiagram extends UmlDiagram { double rawHeight = 0; for (String n : getSkinParam().getAllSpriteNames()) { final Sprite sprite = getSkinParam().getSprite(n); - TextBlock blockName = Display.create(n).create( - FontConfiguration.blackBlueTrue(UFont.sansSerif(14)), HorizontalAlignment.LEFT, - getSkinParam()); + TextBlock blockName = Display.create(n).create(FontConfiguration.blackBlueTrue(UFont.sansSerif(14)), + HorizontalAlignment.LEFT, getSkinParam()); TextBlock tb = sprite.asTextBlock(HColorUtils.BLACK, 1.0); tb = TextBlockUtils.mergeTB(tb, blockName, HorizontalAlignment.CENTER); tb.drawU(ug.apply(new UTranslate(x, y))); diff --git a/src/net/sourceforge/plantuml/sprite/PSystemListInternalSprites.java b/src/net/sourceforge/plantuml/sprite/PSystemListInternalSprites.java index 89be13037..49e003dc1 100644 --- a/src/net/sourceforge/plantuml/sprite/PSystemListInternalSprites.java +++ b/src/net/sourceforge/plantuml/sprite/PSystemListInternalSprites.java @@ -59,8 +59,8 @@ public class PSystemListInternalSprites extends AbstractPSystem { final protected ImageData exportDiagramNow(OutputStream os, int num, FileFormatOption fileFormat, long seed) throws IOException { final UDrawable result = getGraphicStrings(); - final ImageBuilder imageBuilder = new ImageBuilder(new ColorMapperIdentity(), 1.0, HColorUtils.WHITE, - getMetadata(), null, 0, 0, null, false); + final ImageBuilder imageBuilder = ImageBuilder.buildA(new ColorMapperIdentity(), + false, null, getMetadata(), null, 1.0, HColorUtils.WHITE); imageBuilder.setUDrawable(result); return imageBuilder.writeImageTOBEMOVED(fileFormat, seed, os); } diff --git a/src/net/sourceforge/plantuml/sprite/SpriteGrayLevel.java b/src/net/sourceforge/plantuml/sprite/SpriteGrayLevel.java index e3237dd4a..d6d8fd741 100644 --- a/src/net/sourceforge/plantuml/sprite/SpriteGrayLevel.java +++ b/src/net/sourceforge/plantuml/sprite/SpriteGrayLevel.java @@ -45,8 +45,10 @@ import java.util.List; import net.sourceforge.plantuml.StringUtils; import net.sourceforge.plantuml.code.AsciiEncoder; import net.sourceforge.plantuml.code.AsciiEncoderFinalZeros; +import net.sourceforge.plantuml.code.ByteArray; import net.sourceforge.plantuml.code.CompressionZlib; import net.sourceforge.plantuml.code.CompressionZopfliZlib; +import net.sourceforge.plantuml.code.NoPlantumlCompressionException; import net.sourceforge.plantuml.code.PairInt; import net.sourceforge.plantuml.code.SpiralOnRectangle; import net.sourceforge.plantuml.ugraphic.color.ColorChangerMonochrome; @@ -281,18 +283,23 @@ public enum SpriteGrayLevel { return Collections.unmodifiableList(result); } - public Sprite buildSpriteZ(int width, int height, String compressed) throws IOException { + public Sprite buildSpriteZ(int width, int height, String compressed) { final byte comp[] = new AsciiEncoder().decode(compressed); - final byte img[] = new CompressionZlib().decompress(comp); - final SpriteMonochrome result = new SpriteMonochrome(width, height, nbColor); - int cpt = 0; - for (int line = 0; line < result.getHeight(); line++) { - for (int col = 0; col < result.getWidth(); col++) { - result.setGrey(col, line, img[cpt++]); + try { + final ByteArray img = new CompressionZlib().decompress(comp); + final SpriteMonochrome result = new SpriteMonochrome(width, height, nbColor); + int cpt = 0; + for (int line = 0; line < result.getHeight(); line++) { + for (int col = 0; col < result.getWidth(); col++) { + result.setGrey(col, line, img.getByteAt(cpt++)); + } } + return result; + } catch (NoPlantumlCompressionException e) { + e.printStackTrace(); + return null; } - return result; } } diff --git a/src/net/sourceforge/plantuml/sprite/StdlibDiagram.java b/src/net/sourceforge/plantuml/sprite/StdlibDiagram.java index 1fd688688..9ae7cd145 100644 --- a/src/net/sourceforge/plantuml/sprite/StdlibDiagram.java +++ b/src/net/sourceforge/plantuml/sprite/StdlibDiagram.java @@ -43,6 +43,7 @@ import java.util.List; import net.sourceforge.plantuml.Dimension2DDouble; import net.sourceforge.plantuml.FileFormatOption; import net.sourceforge.plantuml.ISkinSimple; +import net.sourceforge.plantuml.SkinParam; import net.sourceforge.plantuml.UmlDiagram; import net.sourceforge.plantuml.UmlDiagramType; import net.sourceforge.plantuml.WithSprite; @@ -59,6 +60,7 @@ import net.sourceforge.plantuml.graphic.StringBounder; import net.sourceforge.plantuml.graphic.TextBlock; import net.sourceforge.plantuml.graphic.TextBlockUtils; import net.sourceforge.plantuml.preproc.Stdlib; +import net.sourceforge.plantuml.style.ClockwiseTopRightBottomLeft; import net.sourceforge.plantuml.ugraphic.ImageBuilder; import net.sourceforge.plantuml.ugraphic.UFont; import net.sourceforge.plantuml.ugraphic.UGraphic; @@ -88,12 +90,19 @@ public class StdlibDiagram extends UmlDiagram { throws IOException { final TextBlock result = getTable(); - final double margin = 10; - final double dpiFactor = 1; - final ImageBuilder imageBuilder = new ImageBuilder(getSkinParam(), dpiFactor, - fileFormatOption.isWithMetadata() ? getMetadata() : null, getWarningOrError(), margin, margin, - getAnimation()); + final double dpiFactor = 1; + final int margin1; + final int margin2; + if (SkinParam.USE_STYLES()) { + margin1 = SkinParam.zeroMargin(10); + margin2 = SkinParam.zeroMargin(10); + } else { + margin1 = 10; + margin2 = 10; + } + final ImageBuilder imageBuilder = ImageBuilder.buildD(getSkinParam(), ClockwiseTopRightBottomLeft.margin1margin2((double) margin1, (double) margin2), getAnimation(), fileFormatOption.isWithMetadata() ? getMetadata() : null, + getWarningOrError(), dpiFactor); imageBuilder.setUDrawable(result); return imageBuilder.writeImageTOBEMOVED(fileFormatOption, seed(), os); diff --git a/src/net/sourceforge/plantuml/stats/PSystemStats.java b/src/net/sourceforge/plantuml/stats/PSystemStats.java index 1719c87a6..37ca53203 100644 --- a/src/net/sourceforge/plantuml/stats/PSystemStats.java +++ b/src/net/sourceforge/plantuml/stats/PSystemStats.java @@ -61,8 +61,8 @@ public class PSystemStats extends AbstractPSystem { final protected ImageData exportDiagramNow(OutputStream os, int num, FileFormatOption fileFormat, long seed) throws IOException { final TextBlockBackcolored result = getGraphicStrings(); - final ImageBuilder imageBuilder = new ImageBuilder(new ColorMapperIdentity(), 1.0, result.getBackcolor(), - getMetadata(), null, 0, 0, null, false); + final ImageBuilder imageBuilder = ImageBuilder.buildA(new ColorMapperIdentity(), + false, null, getMetadata(), null, 1.0, result.getBackcolor()); imageBuilder.setUDrawable(result); return imageBuilder.writeImageTOBEMOVED(fileFormat, seed, os); } diff --git a/src/net/sourceforge/plantuml/style/ClockwiseTopRightBottomLeft.java b/src/net/sourceforge/plantuml/style/ClockwiseTopRightBottomLeft.java index 56cbe1677..ba02f6ac3 100644 --- a/src/net/sourceforge/plantuml/style/ClockwiseTopRightBottomLeft.java +++ b/src/net/sourceforge/plantuml/style/ClockwiseTopRightBottomLeft.java @@ -37,14 +37,83 @@ package net.sourceforge.plantuml.style; public class ClockwiseTopRightBottomLeft { - private final double value; + private final double top; + private final double right; + private final double bottom; + private final double left; - public ClockwiseTopRightBottomLeft(double value) { - this.value = value; + public static ClockwiseTopRightBottomLeft same(double value) { + return new ClockwiseTopRightBottomLeft(value, value, value, value); } - public double asDouble() { - return value; + public static ClockwiseTopRightBottomLeft none() { + return new ClockwiseTopRightBottomLeft(0, 0, 0, 0); + } + + public static ClockwiseTopRightBottomLeft read(String value) { + if (value.matches("[0-9 ]+")) { + final String split[] = value.split(" +"); + if (split.length == 1) { + final double first = Integer.parseInt(split[0]); + return new ClockwiseTopRightBottomLeft(first, first, first, first); + } + if (split.length == 2) { + final double first = Integer.parseInt(split[0]); + final double second = Integer.parseInt(split[1]); + return new ClockwiseTopRightBottomLeft(first, second, first, second); + } + if (split.length == 3) { + final double first = Integer.parseInt(split[0]); + final double second = Integer.parseInt(split[1]); + final double third = Integer.parseInt(split[2]); + return new ClockwiseTopRightBottomLeft(first, second, third, second); + } + if (split.length == 4) { + final double first = Integer.parseInt(split[0]); + final double second = Integer.parseInt(split[1]); + final double third = Integer.parseInt(split[2]); + final double forth = Integer.parseInt(split[3]); + return new ClockwiseTopRightBottomLeft(first, second, third, forth); + } + } + return none(); + } + + public static ClockwiseTopRightBottomLeft margin1margin2(double margin1, double margin2) { + return new ClockwiseTopRightBottomLeft(margin1, margin2, margin2, margin1); + } + + private ClockwiseTopRightBottomLeft(double top, double right, double bottom, double left) { + this.top = top; + this.right = right; + this.bottom = bottom; + this.left = left; + } + + @Override + public String toString() { + return "" + top + ":" + right + ":" + bottom + ":" + left; + } + + public final double getTop() { + return top; + } + + public final double getRight() { + return right; + } + + public final double getBottom() { + return bottom; + } + + public final double getLeft() { + return left; + } + + public static ClockwiseTopRightBottomLeft marginForDocument(StyleBuilder styleBuilder) { + final Style style = StyleSignature.of(SName.root, SName.document).getMergedStyle(styleBuilder); + return style.getMargin(); } } \ No newline at end of file diff --git a/src/net/sourceforge/plantuml/style/CommandStyleMultilinesCSS.java b/src/net/sourceforge/plantuml/style/CommandStyleMultilinesCSS.java index 1a4f06baf..f7c5ccb8b 100644 --- a/src/net/sourceforge/plantuml/style/CommandStyleMultilinesCSS.java +++ b/src/net/sourceforge/plantuml/style/CommandStyleMultilinesCSS.java @@ -64,6 +64,7 @@ public class CommandStyleMultilinesCSS extends CommandMultilines2 { } protected CommandExecutionResult executeNow(UmlDiagram diagram, BlocLines lines) { + SkinParam.setBetaStyle(true); if (SkinParam.USE_STYLES() == false) { return CommandExecutionResult.ok(); } diff --git a/src/net/sourceforge/plantuml/style/SName.java b/src/net/sourceforge/plantuml/style/SName.java index 22adc542c..e83370178 100644 --- a/src/net/sourceforge/plantuml/style/SName.java +++ b/src/net/sourceforge/plantuml/style/SName.java @@ -36,55 +36,72 @@ package net.sourceforge.plantuml.style; public enum SName { - root, - title, - header, - footer, - legend, - caption, - element, - clickable, - sequenceDiagram, - destroy, - lifeLine, - group, - groupHeader, - reference, - referenceHeader, - box, - separator, - delay, - arrow, - participant, - actor, - boundary, - control, - entity, - queue, - database, - collections, - class_, - classDiagram, - activityDiagram, - activity, - activityBar, - note, - stereotype, - swimlane, - diamond, - partition, - circle, - mindmapDiagram, - node, - rootNode, - leafNode, - wbsDiagram, - objectDiagram, - componentDiagram, - stateDiagram; - - public static String depth(int level) { - return "depth(" + level + ")"; - } + activity, // + activityBar, // + activityDiagram, // + actor, // + agent, // + archimate, // + arrow, // + artifact, // + boundary, // + box, // + caption, // + card, // + circle, // + classDiagram, // + class_, // + clickable, // + cloud, // + collection, // + collections, // + component, // + componentDiagram, // + control, // + database, // + databse, // + delay, // + destroy, // + diamond, // + document, // + element, // + entity, // + file, // + folder, // + footer, // + frame, // + group, // + groupHeader, // + header, // + interface_, // + leafNode, // + legend, // + lifeLine, // + mindmapDiagram, // + node, // + note, // + objectDiagram, // + package_, // + participant, // + partition, // + queue, // + rectangle, // + reference, // + referenceHeader, // + root, // + rootNode, // + separator, // + sequenceDiagram, // + stack, // + stateDiagram, // + stereotype, // + storage, // + swimlane, // + title, // + usecase, // + wbsDiagram; // + public static String depth(int level) { + return "depth(" + level + ")"; + } } \ No newline at end of file diff --git a/src/net/sourceforge/plantuml/style/Style.java b/src/net/sourceforge/plantuml/style/Style.java index 2ad5381c5..b77b787ef 100644 --- a/src/net/sourceforge/plantuml/style/Style.java +++ b/src/net/sourceforge/plantuml/style/Style.java @@ -186,13 +186,13 @@ public class Style { } public ClockwiseTopRightBottomLeft getPadding() { - final double padding = value(PName.Padding).asDouble(); - return new ClockwiseTopRightBottomLeft(padding); + final String padding = value(PName.Padding).asString(); + return ClockwiseTopRightBottomLeft.read(padding); } public ClockwiseTopRightBottomLeft getMargin() { - final double padding = value(PName.Margin).asDouble(); - return new ClockwiseTopRightBottomLeft(padding); + final String margin = value(PName.Margin).asString(); + return ClockwiseTopRightBottomLeft.read(margin); } public HorizontalAlignment getHorizontalAlignment() { @@ -214,12 +214,11 @@ public class Style { final HColor legendColor = this.value(PName.LineColor).asColor(set); final UStroke stroke = this.getStroke(); final int cornersize = this.value(PName.RoundCorner).asInt(); - final double margin = this.value(PName.Margin).asDouble(); - final double padding = this.value(PName.Padding).asDouble(); - + final ClockwiseTopRightBottomLeft margin = this.getMargin(); + final ClockwiseTopRightBottomLeft padding = this.getPadding(); final TextBlock result = TextBlockUtils.bordered(textBlock, stroke, legendColor, legendBackgroundColor, - cornersize, padding, padding); - return TextBlockUtils.withMargin(result, margin, margin); + cornersize, padding); + return TextBlockUtils.withMargin(result, margin); } public UGraphic applyStrokeAndLineColor(UGraphic ug, HColorSet colorSet) { diff --git a/src/net/sourceforge/plantuml/style/StyleBuilder.java b/src/net/sourceforge/plantuml/style/StyleBuilder.java index e44be3055..2eeb80c0a 100644 --- a/src/net/sourceforge/plantuml/style/StyleBuilder.java +++ b/src/net/sourceforge/plantuml/style/StyleBuilder.java @@ -108,9 +108,6 @@ public class StyleBuilder implements AutomaticCounter { if (added) { Log.info("Using style " + signature); } - // if (signature.isStarred()) { - // throw new IllegalArgumentException(); - // } Style result = null; for (Entry ent : styles.entrySet()) { final StyleSignature key = ent.getKey(); diff --git a/src/net/sourceforge/plantuml/style/StyleSignature.java b/src/net/sourceforge/plantuml/style/StyleSignature.java index 12d3d5f21..7e572fb59 100644 --- a/src/net/sourceforge/plantuml/style/StyleSignature.java +++ b/src/net/sourceforge/plantuml/style/StyleSignature.java @@ -54,7 +54,7 @@ public class StyleSignature { if (s.contains("*") || s.contains("&") || s.contains("-")) { throw new IllegalArgumentException(); } - this.names.add(s.toLowerCase()); + this.names.add(clean(s)); } public static StyleSignature empty() { @@ -86,7 +86,7 @@ public class StyleSignature { throw new IllegalArgumentException(); } final Set result = new HashSet(names); - result.add(s.toLowerCase()); + result.add(clean(s)); return new StyleSignature(result); } @@ -145,7 +145,7 @@ public class StyleSignature { public static StyleSignature of(SName... names) { final List result = new ArrayList(); for (SName name : names) { - result.add(name.name().toLowerCase()); + result.add(name.name().toLowerCase().replace("_", "")); } return new StyleSignature(result); } @@ -154,10 +154,10 @@ public class StyleSignature { final List result = new ArrayList(names); if (stereotype != null) { for (String name : stereotype.getStyleNames()) { - result.add(name.toLowerCase()); + result.add(clean(name)); } } - result.add(SName.stereotype.name().toLowerCase()); + result.add(SName.stereotype.name().toLowerCase().replace("_", "")); return new StyleSignature(result); } @@ -165,12 +165,16 @@ public class StyleSignature { final List result = new ArrayList(names); if (stereotype != null) { for (String name : stereotype.getStyleNames()) { - result.add(name.toLowerCase()); + result.add(clean(name)); } } return new StyleSignature(result); } + private String clean(String name) { + return name.toLowerCase().replace("_", ""); + } + public StyleSignature mergeWith(List