version 1.2020.13

This commit is contained in:
Arnaud Roques 2020-06-14 22:35:42 +02:00
parent 301fd18b2f
commit 37a6f82e35
41 changed files with 418 additions and 623 deletions

View File

@ -35,7 +35,7 @@
<groupId>net.sourceforge.plantuml</groupId>
<artifactId>plantuml</artifactId>
<version>1.2020.13-SNAPSHOT</version>
<version>1.2020.14-SNAPSHOT</version>
<packaging>jar</packaging>
<name>PlantUML</name>

View File

@ -0,0 +1,56 @@
/* ========================================================================
* 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;
import net.sourceforge.plantuml.graphic.USymbol;
public enum ComponentStyle {
UML1, UML2, RECTANGLE;
public USymbol toSymbol() {
switch (this) {
case UML1:
return USymbol.COMPONENT1;
case UML2:
return USymbol.COMPONENT2;
case RECTANGLE:
return USymbol.RECTANGLE;
}
throw new AssertionError();
}
}

View File

@ -98,7 +98,7 @@ public interface ISkinParam extends ISkinSimple {
public PackageStyle getPackageStyle();
public boolean useUml2ForComponent();
public ComponentStyle componentStyle();
public boolean stereotypePositionTop();

View File

@ -807,12 +807,16 @@ public class SkinParam implements ISkinParam {
return result;
}
public boolean useUml2ForComponent() {
public ComponentStyle componentStyle() {
if (strictUmlStyle()) {
return true;
return ComponentStyle.UML2;
}
final String value = getValue("componentstyle");
return "uml2".equalsIgnoreCase(value);
if ("uml2".equalsIgnoreCase(value))
return ComponentStyle.UML2;
if ("rectangle".equalsIgnoreCase(value))
return ComponentStyle.RECTANGLE;
return ComponentStyle.UML1;
}
public boolean stereotypePositionTop() {

View File

@ -132,8 +132,8 @@ public class SkinParamDelegator implements ISkinParam {
return skinParam.getSprite(name);
}
public boolean useUml2ForComponent() {
return skinParam.useUml2ForComponent();
public ComponentStyle componentStyle() {
return skinParam.componentStyle();
}
public boolean stereotypePositionTop() {

View File

@ -144,6 +144,7 @@ public class ClassDiagram extends AbstractClassOrObjectDiagram {
final Code namespace = buildCode(namespaceString);
final Display tmp = Display.getWithNewlines(namespaceString);
final Ident newIdLong = buildLeafIdentSpecial(namespaceString);
// final Ident newIdLong = buildLeafIdentSpecial2(namespaceString);
gotoGroupExternal(newIdLong, namespace, tmp, namespace, GroupType.PACKAGE, getRootGroup());
}
final Display tmpDisplay;
@ -212,8 +213,8 @@ public class ClassDiagram extends AbstractClassOrObjectDiagram {
margin1 = 0;
margin2 = 10;
}
final ImageBuilder imageBuilder = ImageBuilder.buildD(getSkinParam(), ClockwiseTopRightBottomLeft.margin1margin2((double) margin1, (double) margin2), null, null,
null, (double) 1);
final ImageBuilder imageBuilder = ImageBuilder.buildD(getSkinParam(),
ClockwiseTopRightBottomLeft.margin1margin2(margin1, margin2), null, null, null, 1);
imageBuilder.setUDrawable(fullLayout);
return imageBuilder.writeImageTOBEMOVED(fileFormatOption, seed(), os);
}

View File

@ -39,10 +39,7 @@ import java.awt.Color;
import java.awt.geom.Dimension2D;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLConnection;
import net.sourceforge.plantuml.Dimension2DDouble;
import net.sourceforge.plantuml.FileSystem;
@ -88,8 +85,9 @@ public class AtomImg extends AbstractAtom implements Atom {
if (im == null) {
im = new BufferedImage(10, 10, BufferedImage.TYPE_INT_RGB);
}
return new AtomImg(new UImage(new PixelImage(im, AffineTransformType.TYPE_NEAREST_NEIGHBOR))
.scale(scale).getImage(1), 1, null, null);
return new AtomImg(
new UImage(new PixelImage(im, AffineTransformType.TYPE_NEAREST_NEIGHBOR)).scale(scale).getImage(1), 1,
null, null);
}
public static Atom create(String src, ImgValign valign, int vspace, double scale, Url url) {
@ -171,42 +169,13 @@ public class AtomImg extends AbstractAtom implements Atom {
if (source == null) {
return AtomText.create("(Cannot decode SVG: " + text + ")", fc);
}
final byte[] read = getFile(source);
final byte[] read = source.getBytes();
if (read == null) {
return AtomText.create("(Cannot decode SVG: " + text + ")", fc);
}
return new AtomImgSvg(new TileImageSvg(new String(read, "UTF-8")));
}
// Added by Alain Corbiere
private static byte[] getFile(SURL url) {
try {
InputStream input = null;
try {
final URLConnection connection = url.openConnection();
if (connection == null) {
return null;
}
input = connection.getInputStream();
final ByteArrayOutputStream image = new ByteArrayOutputStream();
final byte[] buffer = new byte[1024];
int read;
while ((read = input.read(buffer)) > 0) {
image.write(buffer, 0, read);
}
image.close();
return image.toByteArray();
} finally {
if (input != null) {
input.close();
}
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
// End
public Dimension2D calculateDimension(StringBounder stringBounder) {
@ -221,8 +190,8 @@ public class AtomImg extends AbstractAtom implements Atom {
if (url != null) {
ug.startUrl(url);
}
ug.draw(new UImage(new PixelImage(image, AffineTransformType.TYPE_BILINEAR))
.withRawFileName(rawFileName).scale(scale));
ug.draw(new UImage(new PixelImage(image, AffineTransformType.TYPE_BILINEAR)).withRawFileName(rawFileName)
.scale(scale));
if (url != null) {
ug.closeUrl();
}

View File

@ -220,12 +220,15 @@ public abstract class CucaDiagram extends UmlDiagram implements GroupHierarchy,
final public Ident buildLeafIdentSpecial(String id) {
return buildFullyQualified(id);
// if (namespaceSeparator != null) {
// if (id.contains(namespaceSeparator)) {
// return Ident.empty().add(id, namespaceSeparator);
// }
// }
// return getLastID().add(id, namespaceSeparator);
}
private Ident buildLeafIdentSpecialUnused(String id) {
// if (namespaceSeparator != null) {
// if (id.contains(namespaceSeparator)) {
return Ident.empty().add(id, ".");
// }
// }
// return getLastID().add(id, namespaceSeparator);
}
final public Ident buildFullyQualified(String id) {

View File

@ -75,6 +75,11 @@ public class GroupRoot implements IGroup {
return Collections.unmodifiableCollection(result);
}
@Override
public String toString() {
return "ROOT";
}
public boolean isGroup() {
return true;

View File

@ -237,6 +237,11 @@ public final class EntityFactory {
if (groupType == null) {
throw new IllegalArgumentException();
}
for (Entry<Ident, IGroup> ent : groups2.entrySet()) {
if (ent.getKey().equals(ident)) {
return ent.getValue();
}
}
final Bodier bodier = new BodierImpl(null, hides);
final EntityImpl result = new EntityImpl(ident, code, this, bodier, parentContainer, groupType, namespace,
namespaceSeparator, rawLayout);

View File

@ -268,7 +268,7 @@ final public class EntityImpl implements ILeaf, IGroup {
// + getUid();
if (entityFactory.namespaceSeparator.V1972())
return getUid() + " " + ident + " " + display + "(" + leafType + ")[" + groupType + "]";
return super.toString() + code + ident + " " + display + "(" + leafType + ")[" + groupType + "] " + getUid();
return "EntityImpl " + code + ident + " " + display + "(" + leafType + ")[" + groupType + "] " + getUid();
}
public final Url getUrl99() {
@ -802,7 +802,7 @@ final public class EntityImpl implements ILeaf, IGroup {
public IGroup getOriginalGroup() {
return originalGroup;
}
private boolean together;
public void setThisIsTogether() {

View File

@ -35,6 +35,7 @@
*/
package net.sourceforge.plantuml.descdiagram;
import net.sourceforge.plantuml.ComponentStyle;
import net.sourceforge.plantuml.ISkinSimple;
import net.sourceforge.plantuml.StringUtils;
import net.sourceforge.plantuml.UmlDiagramType;
@ -74,14 +75,14 @@ public class DescriptionDiagram extends AbstractEntityDiagram {
if (type == null) {
String codeString = code.getName();
if (codeString.startsWith("[") && codeString.endsWith("]")) {
final USymbol sym = getSkinParam().useUml2ForComponent() ? USymbol.COMPONENT2 : USymbol.COMPONENT1;
final USymbol sym = getSkinParam().componentStyle().toSymbol() ;
final Ident idNewLong = ident.eventuallyRemoveStartingAndEndingDoubleQuote("\"([:");
return getOrCreateLeafDefault(idNewLong, idNewLong.toCode(this), LeafType.DESCRIPTION, sym);
}
if (codeString.startsWith(":") && codeString.endsWith(":")) {
final Ident idNewLong = ident.eventuallyRemoveStartingAndEndingDoubleQuote("\"([:");
return getOrCreateLeafDefault(idNewLong, idNewLong.toCode(this), LeafType.DESCRIPTION, getSkinParam()
.getActorStyle().getUSymbol());
return getOrCreateLeafDefault(idNewLong, idNewLong.toCode(this), LeafType.DESCRIPTION,
getSkinParam().getActorStyle().getUSymbol());
}
if (codeString.startsWith("()")) {
codeString = StringUtils.trin(codeString.substring(2));

View File

@ -291,7 +291,7 @@ public class CommandLinkElement extends SingleLineCommand2<DescriptionDiagram> {
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;
final USymbol sym = diagram.getSkinParam().componentStyle().toSymbol();
return getOrCreateLeaf1972(diagram, ident3, code3, LeafType.DESCRIPTION, sym, pure);
}

View File

@ -74,26 +74,26 @@ public class PSystemDonors extends AbstractPSystem {
private static final int COLS = 6;
private static final int FREE_LINES = 6;
public static final String DONORS = "6vaB02mFUBXRGOc9nbfsvvsjZ9-86KqYM9ud58U1HJpT3OW_mBtJutuZ_KLqfNlVD2FQiZN5USOGiI3e"
+ "yJIvPjZctXu8Sw9y2FxT21uW0qH9r4QrBFUas6sRAaDAyEyxN_abw1tUiK6YkKgZnP5xPFSBxs-6ytpJ"
+ "-EYbPy0IgdwAxcl_Tqqhw_AcAWpfifenC-hqX2hcrgWHaIB-_rJhRgSsJgOw3IG1dSgvWflgLC2h4nu3"
+ "YpI3MyPvDMaoAYQ-YPHWQvGGD3epjEMazZco8OF4B_K3jDbSOQd8cL0SeoJHzVNSlcq3pI-NU15y8HPi"
+ "7fX3AOThWHBdHeo4JmGDBRFeZQqwikI97OPIQ64V_j18ZdYaCdCwMYJy7e62eATnGD8BjMd2sT75W2eZ"
+ "sQBFabHT6G_XpkkmFCLge-5EiF2pu2oWXY3_Woxuz5ZrqUGSLqCjgQT9tggjH_rAl9Us6T4t_MYIA9_j"
+ "JREYk0kKBLAThJx7UCqZ87TBhRpYowWZcoEuzzsx6jO_MY0_0jrM4vNapx8lB2GXhgtiWtIT6wyyUX6E"
+ "sP1fOXs_YosliHUwmfMDoR82BFHf-xhIX0osq9NBmz0JMfLfrlb4IrfQlr_qwB9ndt1DfTczW_G-okOY"
+ "_x_RlSmCnG4wLc8MT9sWQ5nDgzvY0n6S5hemv2OWLw2ykMx5pUiYl-e3WhUG4OZ2XgGTulMHSjT5YEbO"
+ "rKqfHW3pfvHpaGXO4A5Mkw1RKIKJAUlT7gUhP_goCNUVzC5rky4OnJ6Tr5Y4xzu5zp2iL8rcjbaxXJa5"
+ "B-Drd5VTQwHVnRAzXVUK3wdvHmRYJE-CY9GVqTYsye_2tJeAivXBRjRbkxeV73nqvu8pMBIC6MssGvQ0"
+ "mjbadAbV6NvQClmTWMp2xurDNa7eJbWFOMOqWjjRasjgSec4ptIMusONW6ArUCMkY719eMgMcSeMDiNa"
+ "6Qj78KD-ntm2I-LQUDgmrjoLUKRrAAZ3UNUiMjQlGytR0ghBOOACj51gf9eYVIsGWMjrUfPQ1zkV5bZG"
+ "j_6eYbM7ujicsgxSe68AJ1SHVj4W4cb1hKGlEKaCy3z_VgKUxUlWupkZV38EaZqaCL05hKu_SMeQF8zX"
+ "PQpNwFlrrdQluC-_rz4cf_PuvgS8ekSW6lys2k0e9p62fu6_BXybxoHODJgrKPGhroYz4KXOi1FlpA8U"
+ "6MRKxyHakHcvw1NRXwhyxUGAN2o6sB3Y8fEc6B7afBVTUb15RD_vnk8WXuQ_YoeJChdAPJKmGY6sGYzE"
+ "Ukmsod2NLGlme3ek4vZxrM-dMTuqvhnZgMvu3CWtH-HKqIEqiAQcjMCXi56C-Rsb_LIcntyoebz4QtRi"
+ "rKFlGVaziWiqV5k3z3D6Wk4YPST0kxdFoGZSVCCXRqpDYKmNYwrSTCMmymOhx3Vs4bb8U65Rgrp2N7ju"
+ "pUcNTtbMsv6ZRI7xM3MQNYYgY178XSKwNPrOAELu84LIC6TlcIWYxQ0tkAHd04vHSBo_sn2E5PeVqQnz"
+ "FADHp6MTUt4FOYgSt4zxKhQRdfK7";
public static final String DONORS = "6ySB02mFUBXRGOc9nbfsvvsjZ8zbDKqYM9ud58U1HJpT3OW_mBtJutuZ_KLqfNlVD2FQiZN5USOGiI3e"
+ "yJIvPjZctXvupCdFe-IxmsY4GPYio__BbYQxT2r0gWmfmRDSR_uPnVYUEsbeodQv4793qY-yxupDizFu"
+ "ujMZ2Te8_1ZOL_zlwf1nUQWAmz1iXJ4O5OrGdJ_q56ijjVR_KOqBfs3VeOeUIuxfrCLrE5JHYCwA5uhL"
+ "E0UtZFFHfCMecD0cKefgeuGYEPYXhIRLvyWL6TpyKZz0cwxjcX8v4efzbaXqV-rftt60ziibFtJoGopO"
+ "8h20Ye_i9oXvRSIuoHT1GyjSzCPM7Ldo90E6KkZ2tloXB8wufsJcChIuAN062ehSne78I6hJ0hC3Ym5L"
+ "Ug95doOfkZ5kmftFOLcArKR3iy2YW2Nd06ioyZ_e4pxTTtraSioRefQKfqdUozQZSTMzbsipec_wqIHH"
+ "lhPtoTBZIb4rJ-bizUdpjRf3xfgowl4leqOyUt2tqq8Q5XyfY1-6RXiJbUJFj8M558HhA_qWNUR6AsSl"
+ "mZ4RifIjus-nPJNsyYvViJ6nB7SMUFTytMXAXbhAAkGqTBjMPIxjVAAbD3N-B_BeqVc_m9fAita7wJrB"
+ "vpB_lnjMQiOI3Zesn2pNpGB5ucbIzIusBaBJJAU6t0J83QZk9hVYRdKHVzG7vDvICX65pRO4YVPKSfUB"
+ "4APZfPjAZ02MJ2dd-XjR4FcgrS7eLaI9HSeYz35CUgRjgx1D-k1ckxanYQCwfNmIVbi8tCEmKYsQsQ5j"
+ "6tCnNiR7SLvrh_v-bRJjBRodV4ZDAnZ8AoqOOIaveZoEie-4kmOAihXBNXhYUuHr3XwwSy4PB5h6Z3RR"
+ "8Gj3SZmPP-bN31-Q37lxNJPihurDNi3xghCJmiZ8WzTBacjgSOcRV3DOJWxR08gDnIjs-PcB25LRRYgR"
+ "wnAcHgmUXGhu7VC9p9LjuSfZlTsru0nO5DN1l3lMM1gtAStR0ghBgOAOTA6CcT8KQNix6NfMfsUf3R3z"
+ "gUuBpZOVLTWqABsjeks63QPFeUaKwHSD8X4IhGgvrAGmm7Tz_4eywEiGupkzR24EaHQI5A02oZaVE9K6"
+ "ppsrbFKQ_N-jjTFA-VFlTMI3KtlSyvD2w1a8ujz3WHpX539v6lXwymVW7G6hOfPs2h1oZTppG5A3dNXd"
+ "5dN_CADp9nRApQX5hzW-LELltww0nNA83IikOccAwLkSidPg19LVzvrlB0voMFYxg38Xawkdh3P6mcVG"
+ "YnCT-vgbk7FD116CZai5xdxrMJFDkumvNx6iRZWuyiqH6L9q3osg9MbjFZsmKPpvlPLjIARxNp8Ydrzg"
+ "rlVgeRTJ_Xnf0is_jTJx6LbWcCWuCB2-tEV40pVU2AWBKpl-wMB1bOkk67PvmHRs6_iHMPxmmhPMcGXp"
+ "dswLeoyByQnsUewr9UzZez7qGQ9IU23R5-lqsOd5iWoFP84KhjbR9ej8w_I6Ixg3S8Z2-VxU1dEilFaH"
+ "cTNcqnk5NDhSYtiG-N1ycgIcNJOxSfCRwuxSRIC1-ge0";
/*
* Special thanks to our sponsors and donors:

View File

@ -269,9 +269,10 @@ public class QuoteUtils {
"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",
"Chvfdhr prf zlfgrerf abhf qrcnffrag, srvtabaf q'ra rger y'betnavfngrhe.",
"V qba'g gnxr nal erfcbafvovyvgl ng nyy",
"V qba'g gnxr erfcbafvovyvgl ng nyy",
"Gurer'f n jbeq sbe crbcyr jub guvax rirelbar vf pbafcvevat ntnvafg gurz: creprcgvir",
"V'yy yrg gung cnff orpnhfr guvf vf tbbqolr");
"V'yy yrg gung cnff orpnhfr guvf vf tbbqolr", "V ybir vg jura n cyna pbzrf gbtrgure",
"Znxr hf nyy fnsr. Tb onpx gb lbhe ohaxre");
private QuoteUtils() {
}

View File

@ -58,24 +58,24 @@ public abstract class USymbol {
public final static USymbol FRAME = record("FRAME", SkinParameter.FRAME, new USymbolFrame());
public final static USymbol NODE = record("NODE", SkinParameter.NODE, new USymbolNode());
public final static USymbol ARTIFACT = record("ARTIFACT", SkinParameter.ARTIFACT, new USymbolArtifact());
public final static USymbol PACKAGE = record("PACKAGE", SkinParameter.PACKAGE, new USymbolFolder(
SkinParameter.PACKAGE, true));
public final static USymbol FOLDER = record("FOLDER", SkinParameter.FOLDER, new USymbolFolder(SkinParameter.FOLDER,
false));
public final static USymbol PACKAGE = record("PACKAGE", SkinParameter.PACKAGE,
new USymbolFolder(SkinParameter.PACKAGE, true));
public final static USymbol FOLDER = record("FOLDER", SkinParameter.FOLDER,
new USymbolFolder(SkinParameter.FOLDER, false));
public final static USymbol FILE = record("FILE", SkinParameter.FILE, new USymbolFile());
public final static USymbol RECTANGLE = record("RECTANGLE", SkinParameter.RECTANGLE, new USymbolRect(
SkinParameter.RECTANGLE));
public final static USymbol LABEL = record("LABEL", SkinParameter.RECTANGLE, new USymbolLabel(
SkinParameter.RECTANGLE));
public final static USymbol ARCHIMATE = record("ARCHIMATE", SkinParameter.ARCHIMATE, new USymbolRect(
SkinParameter.ARCHIMATE));
public final static USymbol COLLECTIONS = record("COLLECTIONS", SkinParameter.COLLECTIONS, new USymbolCollections(
SkinParameter.RECTANGLE));
public final static USymbol RECTANGLE = record("RECTANGLE", SkinParameter.RECTANGLE,
new USymbolRect(SkinParameter.RECTANGLE));
public final static USymbol LABEL = record("LABEL", SkinParameter.RECTANGLE,
new USymbolLabel(SkinParameter.RECTANGLE));
public final static USymbol ARCHIMATE = record("ARCHIMATE", SkinParameter.ARCHIMATE,
new USymbolRect(SkinParameter.ARCHIMATE));
public final static USymbol COLLECTIONS = record("COLLECTIONS", SkinParameter.COLLECTIONS,
new USymbolCollections(SkinParameter.RECTANGLE));
public final static USymbol AGENT = record("AGENT", SkinParameter.AGENT, new USymbolRect(SkinParameter.AGENT));
public final static USymbol ACTOR_STICKMAN = record("ACTOR_STICKMAN", SkinParameter.ACTOR, new USymbolActor(
ActorStyle.STICKMAN));
public final static USymbol ACTOR_AWESOME = record("ACTOR_AWESOME", SkinParameter.ACTOR, new USymbolActor(
ActorStyle.AWESOME));
public final static USymbol ACTOR_STICKMAN = record("ACTOR_STICKMAN", SkinParameter.ACTOR,
new USymbolActor(ActorStyle.STICKMAN));
public final static USymbol ACTOR_AWESOME = record("ACTOR_AWESOME", SkinParameter.ACTOR,
new USymbolActor(ActorStyle.AWESOME));
public final static USymbol USECASE = null;
public final static USymbol COMPONENT1 = record("COMPONENT1", SkinParameter.COMPONENT1, new USymbolComponent1());
public final static USymbol COMPONENT2 = record("COMPONENT2", SkinParameter.COMPONENT2, new USymbolComponent2());
@ -235,7 +235,7 @@ public abstract class USymbol {
} else if (symbol.equalsIgnoreCase("actor")) {
usymbol = skinParam.getActorStyle().getUSymbol();
} else if (symbol.equalsIgnoreCase("component")) {
usymbol = skinParam.useUml2ForComponent() ? USymbol.COMPONENT2 : USymbol.COMPONENT1;
usymbol = skinParam.componentStyle().toSymbol();
} else if (symbol.equalsIgnoreCase("boundary")) {
usymbol = USymbol.BOUNDARY;
} else if (symbol.equalsIgnoreCase("control")) {

View File

@ -119,11 +119,11 @@ public class LatexBuilder implements ScientificEquation {
}
public MutableImage muteColor(Color newColor) {
throw new UnsupportedOperationException();
return this;
}
public MutableImage muteTransparentColor(Color newColor) {
throw new UnsupportedOperationException();
return this;
}
}

View File

@ -46,27 +46,50 @@ import net.sourceforge.plantuml.project.core.TaskInstant;
public class ComplementBeforeOrAfterOrAtTaskStartOrEnd implements ComplementPattern {
public IRegex toRegex(String suffix) {
return new RegexLeaf("COMPLEMENT" + suffix,
"(?:at|with|after|(\\d+)[%s]+days?[%s]+(before|after))[%s]+\\[([^\\[\\]]+?)\\].?s[%s]+(start|end)");
private static final int POS_NB1 = 0;
private static final int POS_DAY_OR_WEEK1 = 1;
private static final int POS_NB2 = 2;
private static final int POS_DAY_OR_WEEK2 = 3;
private static final int POS_BEFORE_OR_AFTER = 4;
private static final int POS_CODE_OTHER = 5;
private static final int POS_START_OR_END = 6;
public IRegex toRegex(String suffix) { // "+"
return new RegexLeaf("COMPLEMENT" + suffix, "(?:at|with|after|" + //
"(\\d+)[%s]+(day|week)s?" + //
"(?:[%s]+and[%s]+(\\d+)[%s]+(day|week)s?)?" + //
"[%s]+(before|after))[%s]+\\[([^\\[\\]]+?)\\].?s[%s]+(start|end)");
}
public Failable<Complement> getComplement(GanttDiagram system, RegexResult arg, String suffix) {
final String code = arg.get("COMPLEMENT" + suffix, 2);
final String position = arg.get("COMPLEMENT" + suffix, 3);
final String code = arg.get("COMPLEMENT" + suffix, POS_CODE_OTHER);
final String startOrEnd = arg.get("COMPLEMENT" + suffix, POS_START_OR_END);
final Moment task = system.getExistingMoment(code);
if (task == null) {
return Failable.<Complement> error("No such task " + code);
return Failable.<Complement>error("No such task " + code);
}
final String days = arg.get("COMPLEMENT" + suffix, 0);
TaskInstant result = new TaskInstant(task, TaskAttribute.fromString(position));
if (days != null) {
int delta = Integer.parseInt(days);
if ("before".equalsIgnoreCase(arg.get("COMPLEMENT" + suffix, 1))) {
TaskInstant result = new TaskInstant(task, TaskAttribute.fromString(startOrEnd));
final String nb1 = arg.get("COMPLEMENT" + suffix, POS_NB1);
if (nb1 != null) {
final int factor1 = arg.get("COMPLEMENT" + suffix, POS_DAY_OR_WEEK1).startsWith("w") ? system.daysInWeek()
: 1;
final int days1 = Integer.parseInt(nb1) * factor1;
final String nb2 = arg.get("COMPLEMENT" + suffix, POS_NB2);
int days2 = 0;
if (nb2 != null) {
final int factor2 = arg.get("COMPLEMENT" + suffix, POS_DAY_OR_WEEK2).startsWith("w")
? system.daysInWeek()
: 1;
days2 = Integer.parseInt(nb2) * factor2;
}
int delta = days1 + days2;
if ("before".equalsIgnoreCase(arg.get("COMPLEMENT" + suffix, POS_BEFORE_OR_AFTER))) {
delta = -delta;
}
result = result.withDelta(delta);
}
return Failable.<Complement> ok(result);
return Failable.<Complement>ok(result);
}
}

View File

@ -47,15 +47,24 @@ public class ComplementSeveralDays implements ComplementPattern {
public IRegex toRegex(String suffix) {
return new RegexConcat( //
new RegexLeaf("COMPLEMENT" + suffix, "(\\d+)[%s]+(days?|weeks?)")); //
new RegexLeaf("COMPLEMENT" + suffix, "(\\d+)[%s]+(day|week)s?" + //
"(?:[%s]+and[%s]+(\\d+)[%s]+(day|week)s?)?" //
)); //
}
public Failable<Complement> getComplement(GanttDiagram system, RegexResult arg, String suffix) {
final String number = arg.get("COMPLEMENT" + suffix, 0);
final boolean inWeeks = arg.get("COMPLEMENT" + suffix, 1).startsWith("w");
final int factor = inWeeks ? system.daysInWeek() : 1;
final int days = Integer.parseInt(number) * factor;
return Failable.<Complement> ok(Load.inWinks(days));
final String nb1 = arg.get("COMPLEMENT" + suffix, 0);
final int factor1 = arg.get("COMPLEMENT" + suffix, 1).startsWith("w") ? system.daysInWeek() : 1;
final int days1 = Integer.parseInt(nb1) * factor1;
final String nb2 = arg.get("COMPLEMENT" + suffix, 2);
int days2 = 0;
if (nb2 != null) {
final int factor2 = arg.get("COMPLEMENT" + suffix, 3).startsWith("w") ? system.daysInWeek() : 1;
days2 = Integer.parseInt(nb2) * factor2;
}
return Failable.<Complement>ok(Load.inWinks(days1 + days2));
}
}

View File

@ -245,17 +245,17 @@ public class SFile implements Comparable<SFile> {
// In SANDBOX, we cannot read any files
return false;
}
// Files in "plantuml.include.path" and "plantuml.whitelist.path" are ok.
if (isIn(SecurityUtils.getPath("plantuml.include.path"))) {
// Files in "plantuml.include.path" and "plantuml.allowlist.path" are ok.
if (isInAllowList(SecurityUtils.getPath("plantuml.include.path"))) {
return true;
}
if (isIn(SecurityUtils.getPath("plantuml.whitelist.path"))) {
if (isInAllowList(SecurityUtils.getPath("plantuml.allowlist.path"))) {
return true;
}
if (SecurityUtils.getSecurityProfile() == SecurityProfile.INTERNET) {
return false;
}
if (SecurityUtils.getSecurityProfile() == SecurityProfile.WHITELIST) {
if (SecurityUtils.getSecurityProfile() == SecurityProfile.ALLOWLIST) {
return false;
}
if (SecurityUtils.getSecurityProfile() != SecurityProfile.UNSECURE) {
@ -272,11 +272,11 @@ public class SFile implements Comparable<SFile> {
return true;
}
private boolean isIn(List<SFile> whiteList) {
private boolean isInAllowList(List<SFile> allowlist) {
final String path = getCleanPathSecure();
for (SFile white : whiteList) {
if (path.startsWith(white.getCleanPathSecure())) {
// File directory is in the whiteList
for (SFile allow : allowlist) {
if (path.startsWith(allow.getCleanPathSecure())) {
// File directory is in the allowlist
return true;
}
}

View File

@ -36,7 +36,8 @@
package net.sourceforge.plantuml.security;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
@ -110,10 +111,13 @@ public class SURL {
// We are UNSECURE anyway
return true;
}
if (isInWhiteList()) {
if (isInAllowList()) {
return true;
}
if (SecurityUtils.getSecurityProfile() == SecurityProfile.INTERNET) {
if (pureIP(cleanPath(internal.toString()))) {
return false;
}
final int port = internal.getPort();
// Using INTERNET profile, port 80 and 443 are ok
if (port == 80 || port == 443) {
@ -123,10 +127,17 @@ public class SURL {
return false;
}
private boolean isInWhiteList() {
private boolean pureIP(String full) {
if (full.matches("^https?://\\d+\\.\\d+\\.\\d+\\.\\d+\\/")) {
return false;
}
return true;
}
private boolean isInAllowList() {
final String full = cleanPath(internal.toString());
for (String white : getWhiteList()) {
if (full.startsWith(cleanPath(white))) {
for (String allow : getAllowList()) {
if (full.startsWith(cleanPath(allow))) {
return true;
}
}
@ -141,31 +152,51 @@ public class SURL {
return path;
}
private List<String> getWhiteList() {
final String env = SecurityUtils.getenv("plantuml.whitelist.url");
private List<String> getAllowList() {
final String env = SecurityUtils.getenv("plantuml.allowlist.url");
if (env == null) {
return Collections.emptyList();
}
return Arrays.asList(StringUtils.eventuallyRemoveStartingAndEndingDoubleQuote(env).split(";"));
}
public URLConnection openConnection() {
// Added by Alain Corbiere
public byte[] getBytes() {
if (isUrlOk())
try {
return internal.openConnection();
} catch (IOException e) {
InputStream input = null;
try {
final URLConnection connection = internal.openConnection();
if (connection == null) {
return null;
}
input = connection.getInputStream();
final ByteArrayOutputStream image = new ByteArrayOutputStream();
final byte[] buffer = new byte[1024];
int read;
while ((read = input.read(buffer)) > 0) {
image.write(buffer, 0, read);
}
image.close();
return image.toByteArray();
} finally {
if (input != null) {
input.close();
}
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public InputStream openStream() {
if (isUrlOk())
try {
return internal.openStream();
} catch (IOException e) {
e.printStackTrace();
if (isUrlOk()) {
final byte data[] = getBytes();
if (data != null) {
return new ByteArrayInputStream(data);
}
}
return null;
}

View File

@ -69,7 +69,7 @@ public enum SecurityProfile {
/**
*
*/
WHITELIST,
ALLOWLIST,
/**
* This mode is designed for PlantUML running in a web server.
@ -108,8 +108,8 @@ public enum SecurityProfile {
final String env = SecurityUtils.getenv("PLANTUML_SECURITY_PROFILE");
if ("SANDBOX".equalsIgnoreCase(env)) {
return SANDBOX;
} else if ("WHITELIST".equalsIgnoreCase(env)) {
return WHITELIST;
} else if ("ALLOWLIST".equalsIgnoreCase(env)) {
return ALLOWLIST;
} else if ("INTERNET".equalsIgnoreCase(env)) {
return INTERNET;
} else if ("UNSECURE".equalsIgnoreCase(env)) {
@ -125,7 +125,7 @@ public enum SecurityProfile {
switch (this) {
case SANDBOX:
return "This is completely safe: no access to local files or to distant URL.";
case WHITELIST:
case ALLOWLIST:
return "Some local ressource may be accessible.";
case INTERNET:
return "<i>Mode designed for server connected to Internet.";

View File

@ -66,7 +66,7 @@ import net.sourceforge.plantuml.ugraphic.color.HColorSet;
public class CommandArrow extends SingleLineCommand2<SequenceDiagram> {
private static final String ANCHOR = "(\\{([\\p{L}0-9_]+)\\}[%s]+)?";
static final String ANCHOR = "(\\{([\\p{L}0-9_]+)\\}[%s]+)?";
public CommandArrow() {
super(getRegexConcat());
@ -77,44 +77,42 @@ public class CommandArrow extends SingleLineCommand2<SequenceDiagram> {
}
static IRegex getRegexConcat() {
return RegexConcat
.build(CommandArrow.class.getName(),
RegexLeaf.start(), //
new RegexLeaf("PARALLEL", "(&[%s]*)?"), //
new RegexLeaf("ANCHOR", ANCHOR), //
new RegexOr("PART1", //
new RegexLeaf("PART1CODE", "([\\p{L}0-9_.@]+)"), //
new RegexLeaf("PART1LONG", "[%g]([^%g]+)[%g]"), //
new RegexLeaf("PART1LONGCODE", "[%g]([^%g]+)[%g][%s]*as[%s]+([\\p{L}0-9_.@]+)"), //
new RegexLeaf("PART1CODELONG", "([\\p{L}0-9_.@]+)[%s]+as[%s]*[%g]([^%g]+)[%g]")), //
new RegexLeaf("PART1ANCHOR", ANCHOR), //
RegexLeaf.spaceZeroOrMore(), //
new RegexLeaf("ARROW_DRESSING1",
"([%s][ox]|(?:[%s][ox])?<<?|(?:[%s][ox])?//?|(?:[%s][ox])?\\\\\\\\?)?"), //
new RegexOr(new RegexConcat( //
new RegexLeaf("ARROW_BODYA1", "(-+)"), //
new RegexLeaf("ARROW_STYLE1", getColorOrStylePattern()), //
new RegexLeaf("ARROW_BODYB1", "(-*)")), //
new RegexConcat( //
new RegexLeaf("ARROW_BODYA2", "(-*)"), //
new RegexLeaf("ARROW_STYLE2", getColorOrStylePattern()), //
new RegexLeaf("ARROW_BODYB2", "(-+)"))), //
new RegexLeaf("ARROW_DRESSING2",
"(>>?(?:[ox][%s])?|//?(?:[ox][%s])?|\\\\\\\\?(?:[ox][%s])?|[ox][%s])?"), //
RegexLeaf.spaceZeroOrMore(), //
new RegexOr("PART2", //
new RegexLeaf("PART2CODE", "([\\p{L}0-9_.@]+)"), //
new RegexLeaf("PART2LONG", "[%g]([^%g]+)[%g]"), //
new RegexLeaf("PART2LONGCODE", "[%g]([^%g]+)[%g][%s]*as[%s]+([\\p{L}0-9_.@]+)"), //
new RegexLeaf("PART2CODELONG", "([\\p{L}0-9_.@]+)[%s]+as[%s]*[%g]([^%g]+)[%g]")), //
new RegexLeaf("PART2ANCHOR", ANCHOR), //
RegexLeaf.spaceZeroOrMore(), //
new RegexLeaf("ACTIVATION", "(?:([+*!-]+)?)"), //
RegexLeaf.spaceZeroOrMore(), //
new RegexLeaf("LIFECOLOR", "(?:(#\\w+)?)"), //
RegexLeaf.spaceZeroOrMore(), //
new RegexLeaf("URL", "(" + UrlBuilder.getRegexp() + ")?"), //
RegexLeaf.spaceZeroOrMore(), new RegexLeaf("MESSAGE", "(?::[%s]*(.*))?"), RegexLeaf.end());
return RegexConcat.build(CommandArrow.class.getName(), RegexLeaf.start(), //
new RegexLeaf("PARALLEL", "(&[%s]*)?"), //
new RegexLeaf("ANCHOR", ANCHOR), //
new RegexOr("PART1", //
new RegexLeaf("PART1CODE", "([\\p{L}0-9_.@]+)"), //
new RegexLeaf("PART1LONG", "[%g]([^%g]+)[%g]"), //
new RegexLeaf("PART1LONGCODE", "[%g]([^%g]+)[%g][%s]*as[%s]+([\\p{L}0-9_.@]+)"), //
new RegexLeaf("PART1CODELONG", "([\\p{L}0-9_.@]+)[%s]+as[%s]*[%g]([^%g]+)[%g]")), //
new RegexLeaf("PART1ANCHOR", ANCHOR), //
RegexLeaf.spaceZeroOrMore(), //
new RegexLeaf("ARROW_DRESSING1",
"([%s][ox]|(?:[%s][ox])?<<?|(?:[%s][ox])?//?|(?:[%s][ox])?\\\\\\\\?)?"), //
new RegexOr(new RegexConcat( //
new RegexLeaf("ARROW_BODYA1", "(-+)"), //
new RegexLeaf("ARROW_STYLE1", getColorOrStylePattern()), //
new RegexLeaf("ARROW_BODYB1", "(-*)")), //
new RegexConcat( //
new RegexLeaf("ARROW_BODYA2", "(-*)"), //
new RegexLeaf("ARROW_STYLE2", getColorOrStylePattern()), //
new RegexLeaf("ARROW_BODYB2", "(-+)"))), //
new RegexLeaf("ARROW_DRESSING2",
"(>>?(?:[ox][%s])?|//?(?:[ox][%s])?|\\\\\\\\?(?:[ox][%s])?|[ox][%s])?"), //
RegexLeaf.spaceZeroOrMore(), //
new RegexOr("PART2", //
new RegexLeaf("PART2CODE", "([\\p{L}0-9_.@]+)"), //
new RegexLeaf("PART2LONG", "[%g]([^%g]+)[%g]"), //
new RegexLeaf("PART2LONGCODE", "[%g]([^%g]+)[%g][%s]*as[%s]+([\\p{L}0-9_.@]+)"), //
new RegexLeaf("PART2CODELONG", "([\\p{L}0-9_.@]+)[%s]+as[%s]*[%g]([^%g]+)[%g]")), //
new RegexLeaf("PART2ANCHOR", ANCHOR), //
RegexLeaf.spaceZeroOrMore(), //
new RegexLeaf("ACTIVATION", "(?:([+*!-]+)?)"), //
RegexLeaf.spaceZeroOrMore(), //
new RegexLeaf("LIFECOLOR", "(?:(#\\w+)?)"), //
RegexLeaf.spaceZeroOrMore(), //
new RegexLeaf("URL", "(" + UrlBuilder.getRegexp() + ")?"), //
RegexLeaf.spaceZeroOrMore(), new RegexLeaf("MESSAGE", "(?::[%s]*(.*))?"), RegexLeaf.end());
}
private Participant getOrCreateParticipant(SequenceDiagram system, RegexResult arg2, String n) {

View File

@ -142,6 +142,9 @@ abstract class CommandExoArrowAny extends SingleLineCommand2<SequenceDiagram> {
if (parallel) {
msg.goParallel();
}
msg.setAnchor(arg.get("ANCHOR", 1));
msg.setPart1Anchor(arg.get("PART1ANCHOR", 1));
msg.setPart2Anchor(arg.get("PART2ANCHOR", 1));
final String error = diagram.addMessage(msg);
if (error != null) {

View File

@ -53,6 +53,7 @@ public class CommandExoArrowLeft extends CommandExoArrowAny {
static IRegex getRegexConcat() {
return RegexConcat.build(CommandExoArrowLeft.class.getName(), RegexLeaf.start(), //
new RegexLeaf("PARALLEL", "(&[%s]*)?"), //
new RegexLeaf("ANCHOR", CommandArrow.ANCHOR), //
new RegexLeaf("SHORT", "([?\\[\\]][ox]?)?"), //
new RegexOr( //
new RegexConcat( //

View File

@ -53,6 +53,7 @@ public class CommandExoArrowRight extends CommandExoArrowAny {
static IRegex getRegexConcat() {
return RegexConcat.build(CommandExoArrowRight.class.getName(), RegexLeaf.start(), //
new RegexLeaf("PARALLEL", "(&[%s]*)?"), //
new RegexLeaf("ANCHOR", CommandArrow.ANCHOR), //
new RegexLeaf("PARTICIPANT", "([\\p{L}0-9_.@]+|[%g][^%g]+[%g])"), //
RegexLeaf.spaceZeroOrMore(), //
new RegexLeaf("ARROW_SUPPCIRCLE", "([%s]+[ox])?"), //

View File

@ -144,7 +144,7 @@ public class StyleLoader {
if (mPropertyAndValue.find()) {
final PName key = PName.getFromName(mPropertyAndValue.group(1));
final String value = mPropertyAndValue.group(2);
if (key != null) {
if (key != null && maps.size() > 0) {
maps.get(maps.size() - 1).put(key, new ValueImpl(value, counter));
}
continue;

View File

@ -54,7 +54,6 @@ import net.sourceforge.plantuml.ColorParam;
import net.sourceforge.plantuml.Dimension2DDouble;
import net.sourceforge.plantuml.FontParam;
import net.sourceforge.plantuml.ISkinParam;
import net.sourceforge.plantuml.LineParam;
import net.sourceforge.plantuml.SkinParam;
import net.sourceforge.plantuml.SkinParamUtils;
import net.sourceforge.plantuml.UmlDiagramType;
@ -305,7 +304,7 @@ public class Cluster implements Moveable {
return StyleSignature.of(SName.root, SName.element, styleName, SName.group);
}
public void drawU(UGraphic ug, UStroke stroke, UmlDiagramType umlDiagramType, ISkinParam skinParam2) {
public void drawU(UGraphic ug, UStroke strokeForState, UmlDiagramType umlDiagramType, ISkinParam skinParam2) {
if (group.isHidden()) {
return;
}
@ -345,12 +344,12 @@ public class Cluster implements Moveable {
final boolean isState = umlDiagramType == UmlDiagramType.STATE;
if (isState) {
if (group.getColors(skinParam).getSpecificLineStroke() != null) {
stroke = group.getColors(skinParam).getSpecificLineStroke();
strokeForState = group.getColors(skinParam).getSpecificLineStroke();
}
if (group.getColors(skinParam).getColor(ColorType.LINE) != null) {
borderColor = group.getColors(skinParam).getColor(ColorType.LINE);
}
drawUState(ug, borderColor, skinParam2, stroke, umlDiagramType);
drawUState(ug, borderColor, skinParam2, strokeForState, umlDiagramType);
return;
}
PackageStyle packageStyle = group.getPackageStyle();
@ -365,10 +364,12 @@ public class Cluster implements Moveable {
}
final double shadowing;
final UStroke stroke;
if (SkinParam.USE_STYLES()) {
final Style style = getDefaultStyleDefinition(umlDiagramType.getStyleName())
.getMergedStyle(skinParam.getCurrentStyleBuilder());
shadowing = style.value(PName.Shadowing).asDouble();
stroke = style.getStroke();
} else {
if (group.getUSymbol() == null) {
shadowing = skinParam2.shadowing2(group.getStereotype(), USymbol.PACKAGE.getSkinParameter()) ? 3
@ -377,6 +378,7 @@ public class Cluster implements Moveable {
shadowing = skinParam2.shadowing2(group.getStereotype(), group.getUSymbol().getSkinParameter()) ? 3
: 0;
}
stroke = getStrokeInternal(skinParam2);
}
HColor backColor = getBackColor(umlDiagramType);
backColor = getBackColor(backColor, skinParam2, group.getStereotype(), umlDiagramType.getStyleName());
@ -384,9 +386,8 @@ public class Cluster implements Moveable {
final double roundCorner = group.getUSymbol() == null ? 0
: group.getUSymbol().getSkinParameter().getRoundCorner(skinParam, stereotype);
final UStroke stroke2 = getStrokeInternal(skinParam2);
final ClusterDecoration decoration = new ClusterDecoration(packageStyle, group.getUSymbol(), ztitle,
zstereo, minX, minY, maxX, maxY, stroke2);
zstereo, minX, minY, maxX, maxY, stroke);
decoration.drawU(ug, backColor, borderColor, shadowing, roundCorner,
skinParam2.getHorizontalAlignment(AlignmentParam.packageTitleAlignment, null, false),
skinParam2.getStereotypeAlignment());
@ -410,14 +411,15 @@ public class Cluster implements Moveable {
if (colors.getSpecificLineStroke() != null) {
return colors.getSpecificLineStroke();
}
if (group.getUSymbol() != null) {
if (group.getUSymbol() != null && group.getUSymbol() != USymbol.PACKAGE) {
return group.getUSymbol().getSkinParameter().getStroke(skinParam, group.getStereotype());
}
UStroke stroke = skinParam.getThickness(LineParam.packageBorder, group.getStereotype());
if (stroke == null) {
stroke = new UStroke(1.5);
}
return stroke;
return GeneralImageBuilder.getForcedStroke(group.getStereotype(), skinParam);
// UStroke stroke = skinParam.getThickness(LineParam.packageBorder, group.getStereotype());
// if (stroke == null) {
// stroke = new UStroke(1.5);
// }
// return stroke;
}
public void manageEntryExitPoint(StringBounder stringBounder) {

View File

@ -54,6 +54,7 @@ import net.sourceforge.plantuml.Dimension2DDouble;
import net.sourceforge.plantuml.FontParam;
import net.sourceforge.plantuml.Guillemet;
import net.sourceforge.plantuml.ISkinParam;
import net.sourceforge.plantuml.LineParam;
import net.sourceforge.plantuml.Log;
import net.sourceforge.plantuml.OptionFlags;
import net.sourceforge.plantuml.Pragma;
@ -134,6 +135,7 @@ import net.sourceforge.plantuml.svek.image.EntityImageTips;
import net.sourceforge.plantuml.svek.image.EntityImageUseCase;
import net.sourceforge.plantuml.ugraphic.MinMax;
import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.UStroke;
import net.sourceforge.plantuml.ugraphic.color.HColor;
public final class GeneralImageBuilder {
@ -200,7 +202,8 @@ public final class GeneralImageBuilder {
return new EntityImageLollipopInterface(leaf, skinParam);
}
if (leaf.getLeafType() == LeafType.CIRCLE) {
return new EntityImageDescription(leaf, skinParam, portionShower, links, umlDiagramType.getStyleName());
return new EntityImageDescription(leaf, skinParam, portionShower, links, umlDiagramType.getStyleName(),
null);
}
if (leaf.getLeafType() == LeafType.DESCRIPTION) {
@ -209,7 +212,11 @@ public final class GeneralImageBuilder {
} else if (OptionFlags.USE_INTERFACE_EYE2 && leaf.getUSymbol() instanceof USymbolInterface) {
return new EntityImageLollipopInterfaceEye2(leaf, skinParam, portionShower);
} else {
return new EntityImageDescription(leaf, skinParam, portionShower, links, umlDiagramType.getStyleName());
final UStroke forced = leaf.getUSymbol() == USymbol.PACKAGE
? getForcedStroke(leaf.getStereotype(), skinParam)
: null;
return new EntityImageDescription(leaf, skinParam, portionShower, links, umlDiagramType.getStyleName(),
forced);
}
}
if (leaf.getLeafType() == LeafType.USECASE) {
@ -242,7 +249,7 @@ public final class GeneralImageBuilder {
final HColor black = SkinParamUtils.getColor(skinParam, leaf.getStereotype(),
leaf.getUSymbol().getColorParamBorder());
return new EntityImageDescription(leaf, new SkinParamForecolored(skinParam, black), portionShower,
links, umlDiagramType.getStyleName());
links, umlDiagramType.getStyleName(), getForcedStroke(leaf.getStereotype(), skinParam));
}
return new EntityImageEmptyPackage(leaf, skinParam, portionShower, umlDiagramType.getStyleName());
}
@ -283,6 +290,14 @@ public final class GeneralImageBuilder {
throw new UnsupportedOperationException(leaf.getLeafType().toString());
}
public static UStroke getForcedStroke(Stereotype stereotype, ISkinParam skinParam) {
UStroke stroke = skinParam.getThickness(LineParam.packageBorder, stereotype);
if (stroke == null) {
stroke = new UStroke(1.5);
}
return stroke;
}
private final DotData dotData;
private final EntityFactory entityFactory;
private final UmlSource source;
@ -371,7 +386,7 @@ public final class GeneralImageBuilder {
}
return dotData.getSkinParam().getBackgroundColor(false);
}
public IEntityImage buildImage(BaseFile basefile, String dotStrings[]) {
if (dotData.isDegeneratedWithFewEntities(0)) {
return new EntityImageSimpleEmpty(dotData.getSkinParam().getBackgroundColor(false));

View File

@ -98,7 +98,7 @@ public class EntityImageDescription extends AbstractEntityImage {
private final boolean fixCircleLabelOverlapping;
public EntityImageDescription(ILeaf entity, ISkinParam skinParam, PortionShower portionShower,
Collection<Link> links, SName styleName) {
Collection<Link> links, SName styleName, UStroke forceStroke) {
super(entity, entity.getColors(skinParam).mute(skinParam));
this.useRankSame = skinParam.useRankSame();
this.fixCircleLabelOverlapping = skinParam.fixCircleLabelOverlapping();
@ -133,6 +133,8 @@ public class EntityImageDescription extends AbstractEntityImage {
final HColor forecolor;
final double roundCorner;
final double diagonalCorner;
final double deltaShadow;
final UStroke stroke;
if (SkinParam.USE_STYLES()) {
final Style style = StyleSignature
.of(SName.root, SName.element, styleName, symbol.getSkinParameter().getStyleName())
@ -143,6 +145,8 @@ public class EntityImageDescription extends AbstractEntityImage {
}
roundCorner = style.value(PName.RoundCorner).asDouble();
diagonalCorner = style.value(PName.DiagonalCorner).asDouble();
deltaShadow = style.value(PName.Shadowing).asDouble();
stroke = style.getStroke();
} else {
forecolor = SkinParamUtils.getColor(getSkinParam(), stereotype, symbol.getColorParamBorder());
if (backcolor == null) {
@ -150,13 +154,17 @@ public class EntityImageDescription extends AbstractEntityImage {
}
roundCorner = symbol.getSkinParameter().getRoundCorner(getSkinParam(), stereotype);
diagonalCorner = symbol.getSkinParameter().getDiagonalCorner(getSkinParam(), stereotype);
deltaShadow = getSkinParam().shadowing2(getEntity().getStereotype(), symbol.getSkinParameter()) ? 3 : 0;
if (forceStroke == null) {
stroke = colors.muteStroke(symbol.getSkinParameter().getStroke(getSkinParam(), stereotype));
} else {
stroke = forceStroke;
}
}
assert getStereo() == stereotype;
final UStroke stroke = colors.muteStroke(symbol.getSkinParameter().getStroke(getSkinParam(), stereotype));
final SymbolContext ctx = new SymbolContext(backcolor, forecolor).withStroke(stroke)
.withShadow(getSkinParam().shadowing2(getEntity().getStereotype(), symbol.getSkinParameter()) ? 3 : 0)
final SymbolContext ctx = new SymbolContext(backcolor, forecolor).withStroke(stroke).withShadow(deltaShadow)
.withCorner(roundCorner, diagonalCorner);
stereo = TextBlockUtils.empty(0, 0);
@ -183,8 +191,7 @@ public class EntityImageDescription extends AbstractEntityImage {
}
private USymbol getUSymbol(ILeaf entity) {
final USymbol result = entity.getUSymbol() == null
? (getSkinParam().useUml2ForComponent() ? USymbol.COMPONENT2 : USymbol.COMPONENT1)
final USymbol result = entity.getUSymbol() == null ? getSkinParam().componentStyle().toSymbol()
: entity.getUSymbol();
if (result == null) {
throw new IllegalArgumentException();

View File

@ -43,7 +43,6 @@ import net.sourceforge.plantuml.Dimension2DDouble;
import net.sourceforge.plantuml.FontParam;
import net.sourceforge.plantuml.Guillemet;
import net.sourceforge.plantuml.ISkinParam;
import net.sourceforge.plantuml.LineParam;
import net.sourceforge.plantuml.SkinParamUtils;
import net.sourceforge.plantuml.Url;
import net.sourceforge.plantuml.cucadiagram.Display;
@ -61,6 +60,7 @@ import net.sourceforge.plantuml.style.SName;
import net.sourceforge.plantuml.svek.AbstractEntityImage;
import net.sourceforge.plantuml.svek.Cluster;
import net.sourceforge.plantuml.svek.ClusterDecoration;
import net.sourceforge.plantuml.svek.GeneralImageBuilder;
import net.sourceforge.plantuml.svek.ShapeType;
import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.UStroke;
@ -106,14 +106,6 @@ public class EntityImageEmptyPackage extends AbstractEntityImage {
return Dimension2DDouble.delta(dim, MARGIN * 2, MARGIN * 2);
}
private UStroke getStroke() {
UStroke stroke = getSkinParam().getThickness(LineParam.packageBorder, getStereo());
if (stroke == null) {
stroke = new UStroke(1.5);
}
return stroke;
}
final public void drawU(UGraphic ug) {
if (url != null) {
ug.startUrl(url);
@ -128,8 +120,9 @@ public class EntityImageEmptyPackage extends AbstractEntityImage {
final HColor back = Cluster.getBackColor(specificBackColor, skinParam, stereotype, styleName);
final double roundCorner = 0;
final UStroke stroke = GeneralImageBuilder.getForcedStroke(getEntity().getStereotype(), getSkinParam());
final ClusterDecoration decoration = new ClusterDecoration(getSkinParam().getPackageStyle(), null, desc,
stereoBlock, 0, 0, widthTotal, heightTotal, getStroke());
stereoBlock, 0, 0, widthTotal, heightTotal, stroke);
final double shadowing = getSkinParam().shadowing(getEntity().getStereotype()) ? 3 : 0;
decoration.drawU(ug, back, SkinParamUtils.getColor(getSkinParam(), getStereo(), ColorParam.packageBorder),

View File

@ -76,8 +76,8 @@ public class EntityImageLollipopInterfaceEye2 extends AbstractEntityImage {
super(entity, skinParam);
final Stereotype stereotype = entity.getStereotype();
final USymbol symbol = entity.getUSymbol() == null ? (skinParam.useUml2ForComponent() ? USymbol.COMPONENT2
: USymbol.COMPONENT1) : entity.getUSymbol();
final USymbol symbol = entity.getUSymbol() == null ? skinParam.componentStyle().toSymbol()
: entity.getUSymbol();
if (symbol == null) {
throw new IllegalArgumentException();
}
@ -93,8 +93,8 @@ public class EntityImageLollipopInterfaceEye2 extends AbstractEntityImage {
}
// backcolor = HtmlColorUtils.BLUE;
final HColor forecolor = SkinParamUtils.getColor(getSkinParam(), getStereo(), symbol.getColorParamBorder());
this.ctx = new SymbolContext(backcolor, forecolor).withStroke(new UStroke(1.5)).withShadow(
getSkinParam().shadowing(getEntity().getStereotype()) ? 3 : 0);
this.ctx = new SymbolContext(backcolor, forecolor).withStroke(new UStroke(1.5))
.withShadow(getSkinParam().shadowing(getEntity().getStereotype()) ? 3 : 0);
if (stereotype != null && stereotype.getLabel(Guillemet.DOUBLE_COMPARATOR) != null
&& portionShower.showPortion(EntityPortion.STEREOTYPE, entity)) {

View File

@ -180,8 +180,9 @@ public class LimitFinder extends UGraphicNo implements UGraphic {
}
private void drawRectangle(double x, double y, URectangle shape) {
addPoint(x, y);
addPoint(x + shape.getWidth() - 1, y + shape.getHeight() - 1);
addPoint(x - 1, y - 1);
addPoint(x + shape.getWidth() - 1 + shape.getDeltaShadow() * 2,
y + shape.getHeight() - 1 + shape.getDeltaShadow() * 2);
}
private void drawDotPath(double x, double y, DotPath shape) {
@ -202,7 +203,8 @@ public class LimitFinder extends UGraphicNo implements UGraphic {
private void drawEllipse(double x, double y, UEllipse shape) {
addPoint(x, y);
addPoint(x + shape.getWidth() - 1, y + shape.getHeight() - 1);
addPoint(x + shape.getWidth() - 1 + shape.getDeltaShadow() * 2,
y + shape.getHeight() - 1 + shape.getDeltaShadow() * 2);
}
private void drawText(double x, double y, UText text) {

View File

@ -37,10 +37,8 @@ package net.sourceforge.plantuml.ugraphic.g2d;
import java.awt.GradientPaint;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.Line2D;
import net.sourceforge.plantuml.golem.MinMaxDouble;
import net.sourceforge.plantuml.ugraphic.MinMax;
import net.sourceforge.plantuml.ugraphic.UDriver;
import net.sourceforge.plantuml.ugraphic.UParam;
import net.sourceforge.plantuml.ugraphic.UPath;
@ -65,23 +63,23 @@ public class DriverPathG2d extends DriverShadowedG2d implements UDriver<Graphics
final UPath shape = (UPath) ushape;
DriverLineG2d.manageStroke(param, g2d);
final HColor back = param.getBackcolor();
final ExtendedGeneralPath p = new ExtendedGeneralPath();
final MinMaxDouble minMax = new MinMaxDouble();
minMax.manage(x, y);
boolean slowShadow = false;
MinMax minMax = MinMax.getEmpty(false);
minMax = minMax.addPoint(x, y);
for (USegment seg : shape) {
final USegmentType type = seg.getSegmentType();
final double coord[] = seg.getCoord();
if (type == USegmentType.SEG_MOVETO) {
p.moveTo(x + coord[0], y + coord[1]);
minMax.manage(x + coord[0], y + coord[1]);
minMax = minMax.addPoint(x + coord[0], y + coord[1]);
} else if (type == USegmentType.SEG_LINETO) {
p.lineTo(x + coord[0], y + coord[1]);
minMax.manage(x + coord[0], y + coord[1]);
minMax = minMax.addPoint(x + coord[0], y + coord[1]);
} else if (type == USegmentType.SEG_CUBICTO) {
p.curveTo(x + coord[0], y + coord[1], x + coord[2], y + coord[3], x + coord[4], y + coord[5]);
minMax.manage(x + coord[4], y + coord[5]);
slowShadow = true;
minMax = minMax.addPoint(x + coord[4], y + coord[5]);
} else if (type == USegmentType.SEG_ARCTO) {
p.arcTo(coord[0], coord[1], coord[2], coord[3] != 0, coord[4] != 0, x + coord[5], y + coord[6]);
} else {
@ -97,32 +95,11 @@ public class DriverPathG2d extends DriverShadowedG2d implements UDriver<Graphics
}
// Shadow
final HColor back = param.getBackcolor();
if (back != null) {
slowShadow = true;
}
if (shape.getDeltaShadow() != 0 && HColorUtils.isTransparent(back) == false) {
if (slowShadow) {
drawShadow(g2d, p, shape.getDeltaShadow(), dpiFactor);
if (shape.getDeltaShadow() != 0) {
if (back == null || HColorUtils.isTransparent(back)) {
drawOnlyLineShadowSpecial(g2d, p, shape.getDeltaShadow(), dpiFactor);
} else {
double lastX = 0;
double lastY = 0;
for (USegment seg : shape) {
final USegmentType type = seg.getSegmentType();
final double coord[] = seg.getCoord();
// Cast float for Java 1.5
if (type == USegmentType.SEG_MOVETO) {
lastX = x + coord[0];
lastY = y + coord[1];
} else if (type == USegmentType.SEG_LINETO) {
final Shape line = new Line2D.Double(lastX, lastY, x + coord[0], y + coord[1]);
drawShadow(g2d, line, shape.getDeltaShadow(), dpiFactor);
lastX = x + coord[0];
lastY = y + coord[1];
} else {
throw new UnsupportedOperationException();
}
}
drawShadow(g2d, p, shape.getDeltaShadow(), dpiFactor);
}
}

View File

@ -1,157 +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.ugraphic.g2d;
import java.awt.GradientPaint;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.Line2D;
import java.awt.geom.Path2D;
import net.sourceforge.plantuml.golem.MinMaxDouble;
import net.sourceforge.plantuml.ugraphic.UDriver;
import net.sourceforge.plantuml.ugraphic.UParam;
import net.sourceforge.plantuml.ugraphic.UPath;
import net.sourceforge.plantuml.ugraphic.USegment;
import net.sourceforge.plantuml.ugraphic.USegmentType;
import net.sourceforge.plantuml.ugraphic.UShape;
import net.sourceforge.plantuml.ugraphic.color.ColorMapper;
import net.sourceforge.plantuml.ugraphic.color.HColor;
import net.sourceforge.plantuml.ugraphic.color.HColorGradient;
public class DriverPathG2dLegacy extends DriverShadowedG2d implements UDriver<Graphics2D> {
private final double dpiFactor;
public DriverPathG2dLegacy(double dpiFactor) {
this.dpiFactor = dpiFactor;
}
public void draw(UShape ushape, final double x, final double y, ColorMapper mapper, UParam param, Graphics2D g2d) {
final UPath shape = (UPath) ushape;
DriverLineG2d.manageStroke(param, g2d);
final Path2D.Double p = new Path2D.Double();
boolean hasBezier = false;
final MinMaxDouble minMax = new MinMaxDouble();
minMax.manage(x, y);
for (USegment seg : shape) {
final USegmentType type = seg.getSegmentType();
final double coord[] = seg.getCoord();
if (type == USegmentType.SEG_MOVETO) {
p.moveTo(x + coord[0], y + coord[1]);
minMax.manage(x + coord[0], y + coord[1]);
} else if (type == USegmentType.SEG_LINETO) {
p.lineTo(x + coord[0], y + coord[1]);
minMax.manage(x + coord[0], y + coord[1]);
} else if (type == USegmentType.SEG_CUBICTO) {
p.curveTo(x + coord[0], y + coord[1], x + coord[2], y + coord[3], x + coord[4], y + coord[5]);
minMax.manage(x + coord[4], y + coord[5]);
hasBezier = true;
} else {
throw new UnsupportedOperationException();
}
}
if (shape.isOpenIconic()) {
p.closePath();
g2d.setColor(mapper.toColor(param.getColor()));
g2d.fill(p);
return;
}
// Shadow
if (shape.getDeltaShadow() != 0) {
if (hasBezier) {
drawShadow(g2d, p, shape.getDeltaShadow(), dpiFactor);
} else {
double lastX = 0;
double lastY = 0;
for (USegment seg : shape) {
final USegmentType type = seg.getSegmentType();
final double coord[] = seg.getCoord();
// Cast float for Java 1.5
if (type == USegmentType.SEG_MOVETO) {
lastX = x + coord[0];
lastY = y + coord[1];
} else if (type == USegmentType.SEG_LINETO) {
final Shape line = new Line2D.Double(lastX, lastY, x + coord[0], y + coord[1]);
drawShadow(g2d, line, shape.getDeltaShadow(), dpiFactor);
lastX = x + coord[0];
lastY = y + coord[1];
} else {
throw new UnsupportedOperationException();
}
}
}
}
final HColor back = param.getBackcolor();
if (back instanceof HColorGradient) {
final HColorGradient gr = (HColorGradient) back;
final char policy = gr.getPolicy();
final GradientPaint paint;
if (policy == '|') {
paint = new GradientPaint((float) minMax.getMinX(), (float) minMax.getMaxY() / 2,
mapper.toColor(gr.getColor1()), (float) minMax.getMaxX(), (float) minMax.getMaxY() / 2,
mapper.toColor(gr.getColor2()));
} else if (policy == '\\') {
paint = new GradientPaint((float) minMax.getMinX(), (float) minMax.getMaxY(), mapper.toColor(gr
.getColor1()), (float) minMax.getMaxX(), (float) minMax.getMinY(), mapper.toColor(gr
.getColor2()));
} else if (policy == '-') {
paint = new GradientPaint((float) minMax.getMaxX() / 2, (float) minMax.getMinY(),
mapper.toColor(gr.getColor1()), (float) minMax.getMaxX() / 2, (float) minMax.getMaxY(),
mapper.toColor(gr.getColor2()));
} else {
// for /
paint = new GradientPaint((float) x, (float) y, mapper.toColor(gr.getColor1()),
(float) minMax.getMaxX(), (float) minMax.getMaxY(), mapper.toColor(gr.getColor2()));
}
g2d.setPaint(paint);
g2d.fill(p);
} else if (back != null) {
g2d.setColor(mapper.toColor(back));
g2d.fill(p);
}
if (param.getColor() != null) {
g2d.setColor(mapper.toColor(param.getColor()));
g2d.draw(p);
}
}
}

View File

@ -1,157 +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.ugraphic.g2d;
import java.awt.GradientPaint;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.GeneralPath;
import java.awt.geom.Line2D;
import net.sourceforge.plantuml.golem.MinMaxDouble;
import net.sourceforge.plantuml.ugraphic.UDriver;
import net.sourceforge.plantuml.ugraphic.UParam;
import net.sourceforge.plantuml.ugraphic.UPath;
import net.sourceforge.plantuml.ugraphic.USegment;
import net.sourceforge.plantuml.ugraphic.USegmentType;
import net.sourceforge.plantuml.ugraphic.UShape;
import net.sourceforge.plantuml.ugraphic.color.ColorMapper;
import net.sourceforge.plantuml.ugraphic.color.HColor;
import net.sourceforge.plantuml.ugraphic.color.HColorGradient;
public class DriverPathOldG2d extends DriverShadowedG2d implements UDriver<Graphics2D> {
private final double dpiFactor;
public DriverPathOldG2d(double dpiFactor) {
this.dpiFactor = dpiFactor;
}
public void draw(UShape ushape, final double x, final double y, ColorMapper mapper, UParam param, Graphics2D g2d) {
final UPath shape = (UPath) ushape;
DriverLineG2d.manageStroke(param, g2d);
final GeneralPath p = new GeneralPath();
boolean hasBezier = false;
final MinMaxDouble minMax = new MinMaxDouble();
minMax.manage(x, y);
for (USegment seg : shape) {
final USegmentType type = seg.getSegmentType();
final double coord[] = seg.getCoord();
// Cast float for Java 1.5
if (type == USegmentType.SEG_MOVETO) {
p.moveTo((float) (x + coord[0]), (float) (y + coord[1]));
minMax.manage(x + coord[0], y + coord[1]);
} else if (type == USegmentType.SEG_LINETO) {
p.lineTo((float) (x + coord[0]), (float) (y + coord[1]));
minMax.manage(x + coord[0], y + coord[1]);
} else if (type == USegmentType.SEG_CUBICTO) {
p.curveTo((float) (x + coord[0]), (float) (y + coord[1]), (float) (x + coord[2]),
(float) (y + coord[3]), (float) (x + coord[4]), (float) (y + coord[5]));
minMax.manage(x + coord[4], y + coord[5]);
hasBezier = true;
} else {
throw new UnsupportedOperationException();
}
// bez = new CubicCurve2D.Double(x + bez.x1, y + bez.y1, x +
// bez.ctrlx1, y + bez.ctrly1, x + bez.ctrlx2, y
// + bez.ctrly2, x + bez.x2, y + bez.y2);
// p.append(bez, true);
}
// p.closePath();
// Shadow
if (shape.getDeltaShadow() != 0) {
if (hasBezier) {
drawShadow(g2d, p, shape.getDeltaShadow(), dpiFactor);
} else {
double lastX = 0;
double lastY = 0;
for (USegment seg : shape) {
final USegmentType type = seg.getSegmentType();
final double coord[] = seg.getCoord();
// Cast float for Java 1.5
if (type == USegmentType.SEG_MOVETO) {
lastX = x + coord[0];
lastY = y + coord[1];
} else if (type == USegmentType.SEG_LINETO) {
final Shape line = new Line2D.Double(lastX, lastY, x + coord[0], y + coord[1]);
drawShadow(g2d, line, shape.getDeltaShadow(), dpiFactor);
lastX = x + coord[0];
lastY = y + coord[1];
} else {
throw new UnsupportedOperationException();
}
}
}
}
final HColor back = param.getBackcolor();
if (back instanceof HColorGradient) {
final HColorGradient gr = (HColorGradient) back;
final char policy = gr.getPolicy();
final GradientPaint paint;
if (policy == '|') {
paint = new GradientPaint((float) minMax.getMinX(), (float) minMax.getMaxY() / 2,
mapper.toColor(gr.getColor1()), (float) minMax.getMaxX(), (float) minMax.getMaxY() / 2,
mapper.toColor(gr.getColor2()));
} else if (policy == '\\') {
paint = new GradientPaint((float) minMax.getMinX(), (float) minMax.getMaxY(), mapper.toColor(gr
.getColor1()), (float) minMax.getMaxX(), (float) minMax.getMinY(), mapper.toColor(gr
.getColor2()));
} else if (policy == '-') {
paint = new GradientPaint((float) minMax.getMaxX() / 2, (float) minMax.getMinY(),
mapper.toColor(gr.getColor1()), (float) minMax.getMaxX() / 2, (float) minMax.getMaxY(),
mapper.toColor(gr.getColor2()));
} else {
// for /
paint = new GradientPaint((float) x, (float) y, mapper.toColor(gr.getColor1()),
(float) minMax.getMaxX(), (float) minMax.getMaxY(), mapper.toColor(gr.getColor2()));
}
g2d.setPaint(paint);
g2d.fill(p);
} else if (back != null) {
g2d.setColor(mapper.toColor(back));
g2d.fill(p);
}
if (param.getColor() != null) {
g2d.setColor(mapper.toColor(param.getColor()));
g2d.draw(p);
}
}
}

View File

@ -39,13 +39,9 @@ import java.awt.BasicStroke;
import java.awt.GradientPaint;
import java.awt.Graphics2D;
import java.awt.geom.GeneralPath;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.List;
import net.sourceforge.plantuml.EnsureVisible;
import net.sourceforge.plantuml.ugraphic.MinMax;
import net.sourceforge.plantuml.ugraphic.UDriver;
import net.sourceforge.plantuml.ugraphic.UParam;
import net.sourceforge.plantuml.ugraphic.UPolygon;
@ -73,9 +69,6 @@ public class DriverPolygonG2d extends DriverShadowedG2d implements UDriver<Graph
final GeneralPath path = new GeneralPath();
final HColor back = param.getBackcolor();
final List<Line2D.Double> shadows = shape.getDeltaShadow() != 0 && HColorUtils.isTransparent(back)
? new ArrayList<Line2D.Double>()
: null;
Point2D.Double last = null;
for (Point2D pt : shape.getPoints()) {
@ -85,9 +78,6 @@ public class DriverPolygonG2d extends DriverShadowedG2d implements UDriver<Graph
if (last == null) {
path.moveTo((float) xp, (float) yp);
} else {
if (shadows != null) {
shadows.add(new Line2D.Double(last.x, last.y, xp, yp));
}
path.lineTo((float) xp, (float) yp);
}
last = new Point2D.Double(xp, yp);
@ -97,12 +87,12 @@ public class DriverPolygonG2d extends DriverShadowedG2d implements UDriver<Graph
path.closePath();
}
if (shadows != null) {
for (Line2D.Double line : keepSome(shadows)) {
drawOnlyLineShadow(g2d, line, shape.getDeltaShadow(), dpiFactor);
if (shape.getDeltaShadow() != 0) {
if (HColorUtils.isTransparent(back)) {
drawOnlyLineShadowSpecial(g2d, path, shape.getDeltaShadow(), dpiFactor);
} else {
drawShadow(g2d, path, shape.getDeltaShadow(), dpiFactor);
}
} else if (shape.getDeltaShadow() != 0) {
drawShadow(g2d, path, shape.getDeltaShadow(), dpiFactor);
}
if (back instanceof HColorGradient) {
@ -141,32 +131,4 @@ public class DriverPolygonG2d extends DriverShadowedG2d implements UDriver<Graph
}
}
private List<Line2D.Double> keepSome(List<Line2D.Double> shadows) {
final List<Line2D.Double> result = new ArrayList<Line2D.Double>();
MinMax minMax = MinMax.getEmpty(true);
for (Line2D.Double line : shadows) {
minMax = minMax.addPoint(line.x1, line.y1);
minMax = minMax.addPoint(line.y2, line.y2);
}
for (Line2D.Double line : shadows) {
if (keepMe(line, minMax.getMaxX(), minMax.getMaxY()))
result.add(line);
}
return result;
}
private boolean keepMe(Line2D.Double line, double maxX, double maxY) {
if (line.x1 >= maxX && line.x2 >= maxX) {
return true;
}
if (line.y1 >= maxY && line.y2 >= maxY) {
return true;
}
final double margin = 10;
if (line.x1 >= maxX - margin && line.x2 >= maxX - margin && line.y1 >= maxY - margin
&& line.y2 >= maxY - margin) {
return true;
}
return false;
}
}

View File

@ -41,7 +41,6 @@ import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.TexturePaint;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
@ -89,10 +88,7 @@ public class DriverRectangleG2d extends DriverShadowedG2d implements UDriver<Gra
// Shadow
if (rect.getDeltaShadow() != 0) {
if (HColorUtils.isTransparent(back)) {
drawOnlyLineShadow(g2d, new Line2D.Double(x, y + rect.getHeight(), x + rect.getWidth(), y + rect.getHeight()),
rect.getDeltaShadow(), dpiFactor);
drawOnlyLineShadow(g2d, new Line2D.Double(x + rect.getWidth(), y, x + rect.getWidth(), y + rect.getHeight()),
rect.getDeltaShadow(), dpiFactor);
drawOnlyLineShadowSpecial(g2d, shape, rect.getDeltaShadow(), dpiFactor);
} else {
drawShadow(g2d, shape, rect.getDeltaShadow(), dpiFactor);
}

View File

@ -39,6 +39,7 @@ import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.Area;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
@ -111,7 +112,7 @@ public class DriverShadowedG2d {
}
}
protected void drawOnlyLineShadow(Graphics2D g2d, Line2D.Double shape, double deltaShadow, double dpiFactor) {
protected void drawOnlyLineShadow(Graphics2D g2d, Shape shape, double deltaShadow, double dpiFactor) {
if (dpiFactor < 1) {
dpiFactor = 1;
}
@ -145,4 +146,47 @@ public class DriverShadowedG2d {
g2d.setTransform(at);
}
}
protected void drawOnlyLineShadowSpecial(Graphics2D g2d, Shape shape, double deltaShadow, double dpiFactor) {
if (dpiFactor < 1) {
dpiFactor = 1;
}
final Rectangle2D bounds = shape.getBounds2D();
final double ww = bounds.getMaxX() - bounds.getMinX();
final double hh = bounds.getMaxY() - bounds.getMinY();
final double w = (ww + deltaShadow * 2 + 6) * dpiFactor;
final double h = (hh + deltaShadow * 2 + 6) * dpiFactor;
BufferedImage destination = null;
try {
destination = new BufferedImage((int) w, (int) h, BufferedImage.TYPE_INT_ARGB);
final Graphics2D gg = destination.createGraphics();
gg.scale(dpiFactor, dpiFactor);
gg.translate(deltaShadow - bounds.getMinX(), deltaShadow - bounds.getMinY());
gg.draw(shape);
gg.dispose();
final ConvolveOp simpleBlur = getConvolveOp(6, dpiFactor);
destination = simpleBlur.filter(destination, null);
} catch (OutOfMemoryError error) {
Log.info("Warning: Cannot draw shadow, image too big.");
} catch (Exception e) {
Log.info("Warning: Cannot draw shadow: " + e);
}
if (destination != null) {
final AffineTransform at = g2d.getTransform();
g2d.scale(1 / dpiFactor, 1 / dpiFactor);
final Shape sav = g2d.getClip();
Area full = new Area(new Rectangle2D.Double(0, 0, bounds.getMaxX() + deltaShadow * 2 + 6,
bounds.getMaxY() + deltaShadow * 2 + 6));
full.subtract(new Area(shape));
g2d.setClip(full);
g2d.drawImage(destination, (int) (bounds.getMinX() * dpiFactor), (int) (bounds.getMinY() * dpiFactor),
null);
g2d.setClip(sav);
g2d.setTransform(at);
}
}
}

View File

@ -44,7 +44,7 @@ public class Version {
private static final int MAJOR_SEPARATOR = 1000000;
public static int version() {
return 1202012;
return 1202013;
}
public static int versionPatched() {
@ -93,7 +93,7 @@ public class Version {
}
public static long compileTime() {
return 1591440855351L;
return 1592051198896L;
}
public static String compileTimeString() {

Binary file not shown.