2015-04-07 18:26:58 +00:00
|
|
|
/* ========================================================================
|
|
|
|
* PlantUML : a free UML diagram generator
|
|
|
|
* ========================================================================
|
|
|
|
*
|
2019-01-16 18:34:41 +00:00
|
|
|
* (C) Copyright 2009-2020, Arnaud Roques
|
2015-04-07 18:26:58 +00:00
|
|
|
*
|
2016-03-06 16:47:34 +00:00
|
|
|
* Project Info: http://plantuml.com
|
2015-04-07 18:26:58 +00:00
|
|
|
*
|
2017-03-15 19:13:31 +00:00
|
|
|
* 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
|
|
|
|
*
|
2015-04-07 18:26:58 +00:00
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
*
|
2021-03-23 22:10:34 +00:00
|
|
|
* Original Author: Matthew Leather
|
2015-04-07 18:26:58 +00:00
|
|
|
*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
package net.sourceforge.plantuml.ugraphic;
|
|
|
|
|
|
|
|
import java.awt.Color;
|
|
|
|
import java.awt.Graphics2D;
|
|
|
|
import java.awt.Image;
|
|
|
|
import java.awt.geom.AffineTransform;
|
|
|
|
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.OutputStream;
|
2019-09-14 18:12:04 +00:00
|
|
|
import java.util.Random;
|
2015-04-07 18:26:58 +00:00
|
|
|
import java.util.Set;
|
|
|
|
|
|
|
|
import javax.swing.ImageIcon;
|
|
|
|
|
|
|
|
import net.sourceforge.plantuml.AnimatedGifEncoder;
|
2021-03-23 09:40:50 +00:00
|
|
|
import net.sourceforge.plantuml.AnnotatedWorker;
|
2015-04-07 18:26:58 +00:00
|
|
|
import net.sourceforge.plantuml.CMapData;
|
2021-03-23 14:11:20 +00:00
|
|
|
import net.sourceforge.plantuml.ColorParam;
|
|
|
|
import net.sourceforge.plantuml.CornerParam;
|
2015-04-07 18:26:58 +00:00
|
|
|
import net.sourceforge.plantuml.Dimension2DDouble;
|
|
|
|
import net.sourceforge.plantuml.EmptyImageBuilder;
|
|
|
|
import net.sourceforge.plantuml.FileFormat;
|
2015-05-31 18:56:03 +00:00
|
|
|
import net.sourceforge.plantuml.FileFormatOption;
|
2015-04-07 18:26:58 +00:00
|
|
|
import net.sourceforge.plantuml.FileUtils;
|
2021-03-23 09:40:50 +00:00
|
|
|
import net.sourceforge.plantuml.ISkinParam;
|
2021-03-23 14:11:20 +00:00
|
|
|
import net.sourceforge.plantuml.LineParam;
|
|
|
|
import net.sourceforge.plantuml.Scale;
|
|
|
|
import net.sourceforge.plantuml.SvgCharSizeHack;
|
2021-03-23 09:40:50 +00:00
|
|
|
import net.sourceforge.plantuml.TitledDiagram;
|
2015-04-07 18:26:58 +00:00
|
|
|
import net.sourceforge.plantuml.Url;
|
2021-03-23 14:11:20 +00:00
|
|
|
import net.sourceforge.plantuml.UseStyle;
|
2015-04-07 18:26:58 +00:00
|
|
|
import net.sourceforge.plantuml.anim.AffineTransformation;
|
|
|
|
import net.sourceforge.plantuml.anim.Animation;
|
|
|
|
import net.sourceforge.plantuml.api.ImageDataComplex;
|
|
|
|
import net.sourceforge.plantuml.api.ImageDataSimple;
|
2016-07-25 19:25:28 +00:00
|
|
|
import net.sourceforge.plantuml.braille.UGraphicBraille;
|
2015-04-07 18:26:58 +00:00
|
|
|
import net.sourceforge.plantuml.core.ImageData;
|
|
|
|
import net.sourceforge.plantuml.eps.EpsStrategy;
|
2016-08-25 20:45:37 +00:00
|
|
|
import net.sourceforge.plantuml.graphic.StringBounder;
|
2021-03-23 09:40:50 +00:00
|
|
|
import net.sourceforge.plantuml.graphic.TextBlock;
|
2015-04-07 18:26:58 +00:00
|
|
|
import net.sourceforge.plantuml.graphic.UDrawable;
|
|
|
|
import net.sourceforge.plantuml.mjpeg.MJPEGGenerator;
|
2020-05-30 15:20:23 +00:00
|
|
|
import net.sourceforge.plantuml.security.ImageIO;
|
|
|
|
import net.sourceforge.plantuml.security.SFile;
|
2021-03-23 14:11:20 +00:00
|
|
|
import net.sourceforge.plantuml.skin.rose.Rose;
|
2021-03-23 09:40:50 +00:00
|
|
|
import net.sourceforge.plantuml.style.ClockwiseTopRightBottomLeft;
|
2021-03-23 14:11:20 +00:00
|
|
|
import net.sourceforge.plantuml.style.PName;
|
|
|
|
import net.sourceforge.plantuml.style.SName;
|
|
|
|
import net.sourceforge.plantuml.style.Style;
|
|
|
|
import net.sourceforge.plantuml.style.StyleSignature;
|
2021-03-23 09:40:50 +00:00
|
|
|
import net.sourceforge.plantuml.svek.TextBlockBackcolored;
|
2021-01-10 20:52:19 +00:00
|
|
|
import net.sourceforge.plantuml.svg.LengthAdjust;
|
2020-03-18 10:50:02 +00:00
|
|
|
import net.sourceforge.plantuml.ugraphic.color.ColorMapper;
|
2021-03-23 14:11:20 +00:00
|
|
|
import net.sourceforge.plantuml.ugraphic.color.ColorMapperIdentity;
|
2020-03-18 10:50:02 +00:00
|
|
|
import net.sourceforge.plantuml.ugraphic.color.HColor;
|
|
|
|
import net.sourceforge.plantuml.ugraphic.color.HColorBackground;
|
|
|
|
import net.sourceforge.plantuml.ugraphic.color.HColorGradient;
|
|
|
|
import net.sourceforge.plantuml.ugraphic.color.HColorSimple;
|
|
|
|
import net.sourceforge.plantuml.ugraphic.color.HColorUtils;
|
2021-03-21 12:52:20 +00:00
|
|
|
import net.sourceforge.plantuml.ugraphic.debug.UGraphicDebug;
|
2015-04-07 18:26:58 +00:00
|
|
|
import net.sourceforge.plantuml.ugraphic.eps.UGraphicEps;
|
|
|
|
import net.sourceforge.plantuml.ugraphic.g2d.UGraphicG2d;
|
|
|
|
import net.sourceforge.plantuml.ugraphic.hand.UGraphicHandwritten;
|
|
|
|
import net.sourceforge.plantuml.ugraphic.html5.UGraphicHtml5;
|
|
|
|
import net.sourceforge.plantuml.ugraphic.svg.UGraphicSvg;
|
|
|
|
import net.sourceforge.plantuml.ugraphic.tikz.UGraphicTikz;
|
2018-06-25 19:05:58 +00:00
|
|
|
import net.sourceforge.plantuml.ugraphic.txt.UGraphicTxt;
|
2015-04-07 18:26:58 +00:00
|
|
|
import net.sourceforge.plantuml.ugraphic.visio.UGraphicVdx;
|
|
|
|
|
2021-04-02 06:09:04 +00:00
|
|
|
import static net.sourceforge.plantuml.SkinParam.DEFAULT_PRESERVE_ASPECT_RATIO;
|
|
|
|
|
2015-04-07 18:26:58 +00:00
|
|
|
public class ImageBuilder {
|
|
|
|
|
2021-03-23 14:11:20 +00:00
|
|
|
private Animation animation;
|
2021-03-23 09:40:50 +00:00
|
|
|
private boolean annotations;
|
|
|
|
private HColor backcolor = HColorUtils.WHITE;
|
2021-03-23 14:11:20 +00:00
|
|
|
private ColorMapper colorMapper = new ColorMapperIdentity();
|
2021-03-25 10:49:53 +00:00
|
|
|
private Dimension2D dimension;
|
2021-03-24 03:53:58 +00:00
|
|
|
private final FileFormatOption fileFormatOption;
|
2021-03-28 01:05:48 +00:00
|
|
|
private String hoverPathColorRGB;
|
2021-03-24 03:53:58 +00:00
|
|
|
private LengthAdjust lengthAdjust = LengthAdjust.defaultValue();
|
2015-04-07 18:26:58 +00:00
|
|
|
private UDrawable udrawable;
|
2021-03-24 03:53:58 +00:00
|
|
|
private ClockwiseTopRightBottomLeft margin = ClockwiseTopRightBottomLeft.none();
|
|
|
|
private String metadata;
|
2021-03-28 14:33:48 +00:00
|
|
|
private String preserveAspectRatio;
|
2021-03-23 14:11:20 +00:00
|
|
|
private Scale scale;
|
2021-03-23 13:06:33 +00:00
|
|
|
private long seed = 42;
|
2021-04-07 03:01:15 +00:00
|
|
|
private ISkinParam skinParam;
|
2021-03-23 09:40:50 +00:00
|
|
|
private int status = 0;
|
2021-03-23 14:11:20 +00:00
|
|
|
private boolean svgDimensionStyle = true;
|
2021-03-28 14:33:48 +00:00
|
|
|
private String svgLinkTarget;
|
2021-03-24 03:53:58 +00:00
|
|
|
private TitledDiagram titledDiagram;
|
2019-09-14 18:12:04 +00:00
|
|
|
private boolean randomPixel;
|
2021-03-23 09:40:50 +00:00
|
|
|
private String warningOrError;
|
|
|
|
|
2021-04-03 00:49:34 +00:00
|
|
|
public static ImageBuilder imageBuilder(FileFormatOption fileFormatOption) {
|
|
|
|
return new ImageBuilder(fileFormatOption);
|
|
|
|
}
|
|
|
|
|
2021-03-23 13:06:33 +00:00
|
|
|
public static ImageBuilder plainImageBuilder(UDrawable drawable, FileFormatOption fileFormatOption) {
|
2021-04-03 00:49:34 +00:00
|
|
|
return imageBuilder(fileFormatOption)
|
|
|
|
.drawable(drawable);
|
2021-03-23 09:40:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public static ImageBuilder plainPngBuilder(UDrawable drawable) {
|
2021-04-03 00:49:34 +00:00
|
|
|
return imageBuilder(new FileFormatOption(FileFormat.PNG))
|
|
|
|
.drawable(drawable);
|
2021-03-23 09:40:50 +00:00
|
|
|
}
|
|
|
|
|
2021-04-03 00:49:34 +00:00
|
|
|
private ImageBuilder(FileFormatOption fileFormatOption) {
|
2021-03-23 09:40:50 +00:00
|
|
|
this.fileFormatOption = fileFormatOption;
|
2021-04-02 06:09:04 +00:00
|
|
|
this.preserveAspectRatio = calculatePreserveAspectRatio(fileFormatOption, null);
|
2021-03-23 09:40:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public ImageBuilder annotations(boolean annotations) {
|
|
|
|
this.annotations = annotations;
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public ImageBuilder backcolor(HColor backcolor) {
|
|
|
|
this.backcolor = backcolor;
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public ImageBuilder blackBackcolor() {
|
|
|
|
return backcolor(HColorUtils.BLACK);
|
|
|
|
}
|
|
|
|
|
2021-03-25 10:49:53 +00:00
|
|
|
public ImageBuilder dimension(Dimension2D dimension) {
|
|
|
|
this.dimension = dimension;
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2021-04-07 08:46:12 +00:00
|
|
|
private int getDpi() {
|
|
|
|
return skinParam == null ? 96 : skinParam.getDpi();
|
|
|
|
}
|
|
|
|
|
2021-04-03 00:49:34 +00:00
|
|
|
public ImageBuilder drawable(UDrawable drawable) {
|
|
|
|
this.udrawable = drawable;
|
|
|
|
if (backcolor == null && drawable instanceof TextBlockBackcolored) {
|
|
|
|
backcolor = ((TextBlockBackcolored) drawable).getBackcolor();
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2021-03-23 09:40:50 +00:00
|
|
|
public ImageBuilder margin(ClockwiseTopRightBottomLeft margin) {
|
2021-03-24 03:53:58 +00:00
|
|
|
this.margin = margin;
|
2021-03-23 09:40:50 +00:00
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public ImageBuilder metadata(String metadata) {
|
|
|
|
this.metadata = metadata;
|
|
|
|
return this;
|
|
|
|
}
|
2016-11-04 21:39:29 +00:00
|
|
|
|
2021-04-02 06:09:04 +00:00
|
|
|
public String getPreserveAspectRatio() {
|
|
|
|
return preserveAspectRatio;
|
|
|
|
}
|
|
|
|
|
2021-03-23 09:40:50 +00:00
|
|
|
public ImageBuilder randomPixel() {
|
|
|
|
this.randomPixel = true;
|
|
|
|
return this;
|
2020-05-07 14:12:08 +00:00
|
|
|
}
|
|
|
|
|
2021-03-23 13:06:33 +00:00
|
|
|
public ImageBuilder seed(long seed) {
|
|
|
|
this.seed = seed;
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2021-03-23 09:40:50 +00:00
|
|
|
public ImageBuilder status(int status) {
|
|
|
|
this.status = status;
|
|
|
|
return this;
|
|
|
|
}
|
2020-05-07 14:12:08 +00:00
|
|
|
|
2021-04-07 08:27:57 +00:00
|
|
|
private SvgCharSizeHack getSvgCharSizeHack() {
|
|
|
|
return skinParam == null ? SvgCharSizeHack.NO_HACK : skinParam;
|
|
|
|
}
|
|
|
|
|
2021-03-23 09:40:50 +00:00
|
|
|
public ImageBuilder warningOrError(String warningOrError) {
|
|
|
|
this.warningOrError = warningOrError;
|
|
|
|
return this;
|
|
|
|
}
|
2020-05-07 14:12:08 +00:00
|
|
|
|
2021-04-03 00:49:34 +00:00
|
|
|
public ImageBuilder styled(TitledDiagram diagram) {
|
2021-04-07 03:01:15 +00:00
|
|
|
skinParam = diagram.getSkinParam();
|
2021-03-23 14:11:20 +00:00
|
|
|
animation = diagram.getAnimation();
|
|
|
|
annotations = true;
|
|
|
|
backcolor = calculateBackColor(diagram);
|
|
|
|
colorMapper = skinParam.getColorMapper();
|
2021-03-28 01:05:48 +00:00
|
|
|
hoverPathColorRGB = calculateHoverPathColor(skinParam);
|
2021-03-23 14:11:20 +00:00
|
|
|
lengthAdjust = skinParam.getlengthAdjust();
|
2021-03-24 03:53:58 +00:00
|
|
|
margin = calculateMargin(diagram);
|
2021-03-23 14:11:20 +00:00
|
|
|
metadata = fileFormatOption.isWithMetadata() ? diagram.getMetadata() : null;
|
2021-04-02 06:09:04 +00:00
|
|
|
preserveAspectRatio = calculatePreserveAspectRatio(fileFormatOption, skinParam);
|
2021-03-23 14:11:20 +00:00
|
|
|
scale = diagram.getScale();
|
|
|
|
seed = diagram.seed();
|
|
|
|
svgDimensionStyle = skinParam.svgDimensionStyle();
|
2021-03-28 14:33:48 +00:00
|
|
|
svgLinkTarget = (fileFormatOption.getSvgLinkTarget() != null)
|
|
|
|
? fileFormatOption.getSvgLinkTarget() : skinParam.getSvgLinkTarget();
|
2021-03-23 14:11:20 +00:00
|
|
|
titledDiagram = diagram;
|
|
|
|
warningOrError = diagram.getWarningOrError();
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2021-03-23 09:40:50 +00:00
|
|
|
public ImageData write(OutputStream os) throws IOException {
|
|
|
|
if (annotations && titledDiagram != null) {
|
|
|
|
if (!(udrawable instanceof TextBlock)) throw new IllegalStateException("udrawable is not a TextBlock");
|
|
|
|
final ISkinParam skinParam = titledDiagram.getSkinParam();
|
|
|
|
final StringBounder stringBounder = fileFormatOption.getDefaultStringBounder(skinParam);
|
|
|
|
final AnnotatedWorker annotatedWorker = new AnnotatedWorker(titledDiagram, skinParam, stringBounder);
|
|
|
|
udrawable = annotatedWorker.addAdd((TextBlock) udrawable);
|
|
|
|
}
|
2021-03-24 03:53:58 +00:00
|
|
|
|
|
|
|
switch (fileFormatOption.getFileFormat()) {
|
|
|
|
case MJPEG:
|
|
|
|
return writeImageMjpeg(os);
|
|
|
|
case ANIMATED_GIF:
|
|
|
|
return writeImageAnimatedGif(os);
|
|
|
|
default:
|
|
|
|
return writeImageInternal(fileFormatOption, os, animation);
|
|
|
|
}
|
2015-04-07 18:26:58 +00:00
|
|
|
}
|
|
|
|
|
2021-03-23 09:40:50 +00:00
|
|
|
public byte[] writeByteArray() throws IOException {
|
|
|
|
try (final ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
|
|
|
|
write(baos);
|
|
|
|
return baos.toByteArray();
|
|
|
|
}
|
2015-04-07 18:26:58 +00:00
|
|
|
}
|
|
|
|
|
2021-03-23 13:06:33 +00:00
|
|
|
private ImageData writeImageInternal(FileFormatOption fileFormatOption, OutputStream os,
|
2017-04-19 18:30:16 +00:00
|
|
|
Animation animationArg) throws IOException {
|
2021-03-25 10:49:53 +00:00
|
|
|
Dimension2D dim = (dimension == null)
|
2021-04-07 08:27:57 +00:00
|
|
|
? getFinalDimension(fileFormatOption.getDefaultStringBounder(getSvgCharSizeHack())) : dimension;
|
2015-04-07 18:26:58 +00:00
|
|
|
double dx = 0;
|
|
|
|
double dy = 0;
|
2016-03-06 16:47:34 +00:00
|
|
|
if (animationArg != null) {
|
2021-03-23 14:11:20 +00:00
|
|
|
final MinMax minmax = animationArg.getMinMax(dim);
|
2016-03-06 16:47:34 +00:00
|
|
|
animationArg.setDimension(dim);
|
2015-04-07 18:26:58 +00:00
|
|
|
dim = minmax.getDimension();
|
|
|
|
dx = -minmax.getMinX();
|
|
|
|
dy = -minmax.getMinY();
|
|
|
|
}
|
2021-04-07 08:46:12 +00:00
|
|
|
final double scaleFactor = (scale == null ? 1 : scale.getScale(dim.getWidth(), dim.getHeight())) * getDpi() / 96.0;
|
2021-04-07 08:38:29 +00:00
|
|
|
final UGraphic2 ug = createUGraphic(fileFormatOption, dim, animationArg, dx, dy, scaleFactor);
|
2020-09-30 20:57:58 +00:00
|
|
|
UGraphic ug2 = ug;
|
2021-04-07 03:01:15 +00:00
|
|
|
maybeDrawBorder(ug, dim);
|
2020-09-30 20:57:58 +00:00
|
|
|
if (randomPixel) {
|
|
|
|
drawRandomPoint(ug2);
|
|
|
|
}
|
2021-03-24 03:53:58 +00:00
|
|
|
ug2 = handwritten(ug2.apply(new UTranslate(margin.getLeft(), margin.getTop())));
|
|
|
|
udrawable.drawU(ug2);
|
|
|
|
ug2.flushUg();
|
2021-03-23 09:40:50 +00:00
|
|
|
ug.writeImageTOBEMOVED(os, metadata, 96);
|
2020-09-30 20:57:58 +00:00
|
|
|
os.flush();
|
|
|
|
|
|
|
|
if (ug instanceof UGraphicG2d) {
|
|
|
|
final Set<Url> urls = ((UGraphicG2d) ug).getAllUrlsEncountered();
|
|
|
|
if (urls.size() > 0) {
|
2021-04-05 20:57:59 +00:00
|
|
|
final CMapData cmap = CMapData.cmapString(urls, scaleFactor);
|
2021-03-24 03:53:58 +00:00
|
|
|
return new ImageDataComplex(dim, cmap, warningOrError, status);
|
2015-04-07 18:26:58 +00:00
|
|
|
}
|
|
|
|
}
|
2021-03-24 03:53:58 +00:00
|
|
|
return createImageData(dim);
|
2015-04-07 18:26:58 +00:00
|
|
|
}
|
|
|
|
|
2021-04-07 03:01:15 +00:00
|
|
|
private void maybeDrawBorder(UGraphic ug, Dimension2D dim) {
|
|
|
|
if (skinParam == null) return;
|
|
|
|
|
|
|
|
final HColor color = new Rose().getHtmlColor(skinParam, ColorParam.diagramBorder);
|
|
|
|
|
|
|
|
UStroke stroke = skinParam.getThickness(LineParam.diagramBorder, null);
|
|
|
|
if (stroke == null && color != null) stroke = new UStroke();
|
|
|
|
if (stroke == null) return;
|
|
|
|
|
|
|
|
final URectangle rectangle = new URectangle(dim.getWidth() - stroke.getThickness(), dim.getHeight() - stroke.getThickness())
|
|
|
|
.rounded(skinParam.getRoundCorner(CornerParam.diagramBorder, null));
|
|
|
|
|
|
|
|
ug.apply(color == null ? HColorUtils.BLACK : color).apply(stroke).draw(rectangle);
|
|
|
|
}
|
|
|
|
|
2019-09-14 18:12:04 +00:00
|
|
|
private void drawRandomPoint(UGraphic ug2) {
|
|
|
|
final Random rnd = new Random();
|
|
|
|
final int red = rnd.nextInt(40);
|
|
|
|
final int green = rnd.nextInt(40);
|
|
|
|
final int blue = rnd.nextInt(40);
|
|
|
|
final Color c = new Color(red, green, blue);
|
2020-03-18 10:50:02 +00:00
|
|
|
final HColor color = new HColorSimple(c, false);
|
2020-04-19 16:04:39 +00:00
|
|
|
ug2.apply(color).apply(color.bg()).draw(new URectangle(1, 1));
|
2019-09-14 18:12:04 +00:00
|
|
|
}
|
|
|
|
|
2021-03-24 03:53:58 +00:00
|
|
|
private Dimension2D getFinalDimension(StringBounder stringBounder) {
|
2019-09-14 18:12:04 +00:00
|
|
|
final LimitFinder limitFinder = new LimitFinder(stringBounder, true);
|
|
|
|
udrawable.drawU(limitFinder);
|
2021-03-24 03:53:58 +00:00
|
|
|
return new Dimension2DDouble(limitFinder.getMaxX() + 1 + margin.getLeft() + margin.getRight(),
|
|
|
|
limitFinder.getMaxY() + 1 + margin.getTop() + margin.getBottom());
|
|
|
|
}
|
2020-05-07 14:12:08 +00:00
|
|
|
|
2021-03-24 03:53:58 +00:00
|
|
|
private Dimension2D getFinalDimension() {
|
2021-04-07 08:27:57 +00:00
|
|
|
return getFinalDimension(fileFormatOption.getDefaultStringBounder(getSvgCharSizeHack()));
|
2016-03-06 16:47:34 +00:00
|
|
|
}
|
|
|
|
|
2015-04-07 18:26:58 +00:00
|
|
|
private UGraphic handwritten(UGraphic ug) {
|
2021-04-07 08:50:19 +00:00
|
|
|
if (skinParam != null && skinParam.handwritten()) {
|
2015-04-07 18:26:58 +00:00
|
|
|
return new UGraphicHandwritten(ug);
|
|
|
|
}
|
2021-03-22 18:00:32 +00:00
|
|
|
// if (OptionFlags.OMEGA_CROSSING) {
|
|
|
|
// return new UGraphicCrossing(ug);
|
|
|
|
// } else {
|
|
|
|
return ug;
|
|
|
|
// }
|
2015-04-07 18:26:58 +00:00
|
|
|
}
|
|
|
|
|
2021-03-24 03:53:58 +00:00
|
|
|
private ImageData writeImageMjpeg(OutputStream os) throws IOException {
|
2015-04-07 18:26:58 +00:00
|
|
|
|
2021-03-24 03:53:58 +00:00
|
|
|
final Dimension2D dim = getFinalDimension();
|
2015-04-07 18:26:58 +00:00
|
|
|
|
2020-05-30 15:20:23 +00:00
|
|
|
final SFile f = new SFile("c:/tmp.avi");
|
2015-04-07 18:26:58 +00:00
|
|
|
|
|
|
|
final int nbframe = 100;
|
|
|
|
|
2020-03-18 10:50:02 +00:00
|
|
|
final MJPEGGenerator m = new MJPEGGenerator(f, getAviImage(null).getWidth(null),
|
|
|
|
getAviImage(null).getHeight(null), 12.0, nbframe);
|
2015-04-07 18:26:58 +00:00
|
|
|
for (int i = 0; i < nbframe; i++) {
|
|
|
|
// AffineTransform at = AffineTransform.getRotateInstance(1.0);
|
|
|
|
AffineTransform at = AffineTransform.getTranslateInstance(dim.getWidth() / 2, dim.getHeight() / 2);
|
|
|
|
at.rotate(90.0 * Math.PI / 180.0 * i / 100);
|
|
|
|
at.translate(-dim.getWidth() / 2, -dim.getHeight() / 2);
|
|
|
|
// final AffineTransform at = AffineTransform.getTranslateInstance(i, 0);
|
|
|
|
// final ImageIcon ii = new ImageIcon(getAviImage(at));
|
|
|
|
// m.addImage(ii.getImage());
|
|
|
|
throw new UnsupportedOperationException();
|
|
|
|
}
|
|
|
|
m.finishAVI();
|
|
|
|
|
|
|
|
FileUtils.copyToStream(f, os);
|
|
|
|
|
2021-03-24 03:53:58 +00:00
|
|
|
return createImageData(dim);
|
2015-04-07 18:26:58 +00:00
|
|
|
}
|
|
|
|
|
2021-03-24 03:53:58 +00:00
|
|
|
private ImageData writeImageAnimatedGif(OutputStream os) throws IOException {
|
2015-04-07 18:26:58 +00:00
|
|
|
|
2021-03-24 03:53:58 +00:00
|
|
|
final Dimension2D dim = getFinalDimension();
|
2015-04-07 18:26:58 +00:00
|
|
|
|
2021-03-23 14:11:20 +00:00
|
|
|
final MinMax minmax = animation.getMinMax(dim);
|
2015-04-07 18:26:58 +00:00
|
|
|
|
|
|
|
final AnimatedGifEncoder e = new AnimatedGifEncoder();
|
|
|
|
// e.setQuality(1);
|
|
|
|
e.setRepeat(0);
|
|
|
|
e.start(os);
|
|
|
|
// e.setDelay(1000); // 1 frame per sec
|
|
|
|
// e.setDelay(100); // 10 frame per sec
|
|
|
|
e.setDelay(60); // 16 frame per sec
|
|
|
|
// e.setDelay(50); // 20 frame per sec
|
|
|
|
|
2021-03-23 14:11:20 +00:00
|
|
|
for (AffineTransformation at : animation.getAll()) {
|
2015-04-07 18:26:58 +00:00
|
|
|
final ImageIcon ii = new ImageIcon(getAviImage(at));
|
|
|
|
e.addFrame((BufferedImage) ii.getImage());
|
|
|
|
}
|
|
|
|
e.finish();
|
2021-03-24 03:53:58 +00:00
|
|
|
return createImageData(dim);
|
2015-04-07 18:26:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private Image getAviImage(AffineTransformation affineTransform) throws IOException {
|
|
|
|
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
2021-03-23 13:06:33 +00:00
|
|
|
writeImageInternal(new FileFormatOption(FileFormat.PNG), baos, Animation.singleton(affineTransform));
|
2015-04-07 18:26:58 +00:00
|
|
|
baos.close();
|
|
|
|
|
|
|
|
final ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
|
|
|
|
final Image im = ImageIO.read(bais);
|
|
|
|
bais.close();
|
|
|
|
return im;
|
|
|
|
}
|
|
|
|
|
2021-03-23 13:06:33 +00:00
|
|
|
private UGraphic2 createUGraphic(FileFormatOption option, final Dimension2D dim, Animation animationArg,
|
2021-04-07 08:38:29 +00:00
|
|
|
double dx, double dy, double scaleFactor) {
|
2021-03-24 03:53:58 +00:00
|
|
|
switch (option.getFileFormat()) {
|
2015-04-07 18:26:58 +00:00
|
|
|
case PNG:
|
2021-03-25 02:26:11 +00:00
|
|
|
return createUGraphicPNG(scaleFactor, dim, animationArg, dx, dy,
|
2020-12-06 21:43:09 +00:00
|
|
|
option.getWatermark());
|
2015-04-07 18:26:58 +00:00
|
|
|
case SVG:
|
2021-03-28 14:33:48 +00:00
|
|
|
return createUGraphicSVG(scaleFactor, dim);
|
2015-04-07 18:26:58 +00:00
|
|
|
case EPS:
|
|
|
|
return new UGraphicEps(colorMapper, EpsStrategy.getDefault2());
|
|
|
|
case EPS_TEXT:
|
|
|
|
return new UGraphicEps(colorMapper, EpsStrategy.WITH_MACRO_AND_TEXT);
|
|
|
|
case HTML5:
|
|
|
|
return new UGraphicHtml5(colorMapper);
|
|
|
|
case VDX:
|
|
|
|
return new UGraphicVdx(colorMapper);
|
|
|
|
case LATEX:
|
2021-03-18 18:14:42 +00:00
|
|
|
return new UGraphicTikz(colorMapper, scaleFactor, true, option.getTikzFontDistortion());
|
2016-03-06 16:47:34 +00:00
|
|
|
case LATEX_NO_PREAMBLE:
|
2021-03-18 18:14:42 +00:00
|
|
|
return new UGraphicTikz(colorMapper, scaleFactor, false, option.getTikzFontDistortion());
|
2016-07-25 19:25:28 +00:00
|
|
|
case BRAILLE_PNG:
|
2021-03-24 03:53:58 +00:00
|
|
|
return new UGraphicBraille(colorMapper);
|
2019-04-21 20:40:01 +00:00
|
|
|
case UTXT:
|
2018-06-25 19:05:58 +00:00
|
|
|
case ATXT:
|
|
|
|
return new UGraphicTxt();
|
2021-03-21 12:52:20 +00:00
|
|
|
case DEBUG:
|
2021-03-30 21:19:28 +00:00
|
|
|
return new UGraphicDebug(scaleFactor, dim, svgLinkTarget, hoverPathColorRGB, seed, preserveAspectRatio);
|
2015-04-07 18:26:58 +00:00
|
|
|
default:
|
2021-03-24 03:53:58 +00:00
|
|
|
throw new UnsupportedOperationException(option.getFileFormat().toString());
|
2015-04-07 18:26:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-28 14:33:48 +00:00
|
|
|
private UGraphic2 createUGraphicSVG(double scaleFactor, Dimension2D dim) {
|
2021-04-07 08:27:57 +00:00
|
|
|
final SvgCharSizeHack svgCharSizeHack = getSvgCharSizeHack();
|
2021-03-25 02:26:11 +00:00
|
|
|
HColor backColor = HColorUtils.WHITE; // TODO simplify backcolor some more in a future PR
|
|
|
|
if (this.backcolor instanceof HColorSimple) {
|
|
|
|
backColor = this.backcolor;
|
2015-04-07 18:26:58 +00:00
|
|
|
}
|
|
|
|
final UGraphicSvg ug;
|
2021-03-25 02:26:11 +00:00
|
|
|
if (this.backcolor instanceof HColorGradient) {
|
|
|
|
ug = new UGraphicSvg(svgDimensionStyle, dim, colorMapper, (HColorGradient) this.backcolor, false, scaleFactor,
|
2021-03-28 01:05:48 +00:00
|
|
|
svgLinkTarget, hoverPathColorRGB, seed, preserveAspectRatio, svgCharSizeHack, lengthAdjust);
|
2020-04-26 18:31:41 +00:00
|
|
|
} else if (backColor == null || colorMapper.toColor(backColor).equals(Color.WHITE)) {
|
2021-03-28 01:05:48 +00:00
|
|
|
ug = new UGraphicSvg(svgDimensionStyle, dim, colorMapper, false, scaleFactor, svgLinkTarget, hoverPathColorRGB, seed,
|
2021-03-23 14:11:20 +00:00
|
|
|
preserveAspectRatio, svgCharSizeHack, lengthAdjust);
|
2015-04-07 18:26:58 +00:00
|
|
|
} else {
|
2020-06-07 10:03:18 +00:00
|
|
|
final String tmp = colorMapper.toSvg(backColor);
|
2021-03-28 01:05:48 +00:00
|
|
|
ug = new UGraphicSvg(svgDimensionStyle, dim, colorMapper, tmp, false, scaleFactor, svgLinkTarget, hoverPathColorRGB, seed,
|
2021-03-23 14:11:20 +00:00
|
|
|
preserveAspectRatio, svgCharSizeHack, lengthAdjust);
|
2015-04-07 18:26:58 +00:00
|
|
|
}
|
|
|
|
return ug;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2021-03-25 02:26:11 +00:00
|
|
|
private UGraphic2 createUGraphicPNG(double scaleFactor, final Dimension2D dim,
|
|
|
|
Animation affineTransforms, double dx, double dy, String watermark) {
|
|
|
|
Color backColor = Color.WHITE; // TODO simplify backcolor some more in a future PR
|
|
|
|
if (this.backcolor instanceof HColorSimple) {
|
|
|
|
backColor = colorMapper.toColor(this.backcolor);
|
|
|
|
} else if (this.backcolor instanceof HColorBackground) {
|
2015-04-07 18:26:58 +00:00
|
|
|
backColor = null;
|
|
|
|
}
|
|
|
|
|
2021-03-18 18:14:42 +00:00
|
|
|
final EmptyImageBuilder builder = new EmptyImageBuilder(watermark, (int) (dim.getWidth() * scaleFactor),
|
|
|
|
(int) (dim.getHeight() * scaleFactor), backColor);
|
2015-04-07 18:26:58 +00:00
|
|
|
final Graphics2D graphics2D = builder.getGraphics2D();
|
|
|
|
|
2021-03-18 18:14:42 +00:00
|
|
|
final UGraphicG2d ug = new UGraphicG2d(colorMapper, graphics2D, scaleFactor,
|
2020-03-18 10:50:02 +00:00
|
|
|
affineTransforms == null ? null : affineTransforms.getFirst(), dx, dy);
|
2015-04-07 18:26:58 +00:00
|
|
|
ug.setBufferedImage(builder.getBufferedImage());
|
2021-03-25 02:26:11 +00:00
|
|
|
final BufferedImage im = ug.getBufferedImage();
|
|
|
|
if (this.backcolor instanceof HColorGradient) {
|
|
|
|
ug.apply(this.backcolor.bg()).draw(new URectangle(im.getWidth() / scaleFactor, im.getHeight() / scaleFactor));
|
2015-04-07 18:26:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return ug;
|
|
|
|
}
|
|
|
|
|
2021-03-23 14:11:20 +00:00
|
|
|
private static HColor calculateBackColor(TitledDiagram diagram) {
|
|
|
|
if (UseStyle.useBetaStyle()) {
|
|
|
|
final Style style = StyleSignature
|
|
|
|
.of(SName.root, SName.document, diagram.getUmlDiagramType().getStyleName())
|
|
|
|
.getMergedStyle(diagram.getSkinParam().getCurrentStyleBuilder());
|
|
|
|
|
|
|
|
HColor backgroundColor = style.value(PName.BackGroundColor)
|
|
|
|
.asColor(diagram.getSkinParam().getIHtmlColorSet());
|
|
|
|
if (backgroundColor == null) {
|
|
|
|
backgroundColor = HColorUtils.transparent();
|
|
|
|
}
|
|
|
|
return backgroundColor;
|
|
|
|
|
|
|
|
}
|
|
|
|
return diagram.getSkinParam().getBackgroundColor(false);
|
|
|
|
}
|
|
|
|
|
2021-03-28 01:05:48 +00:00
|
|
|
private String calculateHoverPathColor(ISkinParam skinParam) {
|
|
|
|
if (fileFormatOption.getHoverColor() != null) {
|
|
|
|
return fileFormatOption.getHoverColor();
|
|
|
|
}
|
|
|
|
final HColor color = skinParam.hoverPathColor();
|
|
|
|
return color == null ? null : colorMapper.toRGB(color);
|
|
|
|
}
|
|
|
|
|
2021-03-24 03:53:58 +00:00
|
|
|
private static ClockwiseTopRightBottomLeft calculateMargin(TitledDiagram diagram) {
|
2021-03-23 14:11:20 +00:00
|
|
|
if (UseStyle.useBetaStyle()) {
|
|
|
|
final Style style = StyleSignature.of(SName.root, SName.document)
|
|
|
|
.getMergedStyle(diagram.getSkinParam().getCurrentStyleBuilder());
|
|
|
|
if (style.hasValue(PName.Margin)) {
|
|
|
|
return style.getMargin();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return diagram.getDefaultMargins();
|
|
|
|
}
|
2021-03-24 03:53:58 +00:00
|
|
|
|
2021-04-02 06:09:04 +00:00
|
|
|
private static String calculatePreserveAspectRatio(FileFormatOption fileFormatOption, ISkinParam skinParam) {
|
|
|
|
if (fileFormatOption.getPreserveAspectRatio() != null) {
|
|
|
|
return fileFormatOption.getPreserveAspectRatio();
|
|
|
|
} else if (skinParam != null) {
|
|
|
|
return skinParam.getPreserveAspectRatio();
|
|
|
|
} else {
|
|
|
|
return DEFAULT_PRESERVE_ASPECT_RATIO;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-24 03:53:58 +00:00
|
|
|
private ImageDataSimple createImageData(Dimension2D dim) {
|
|
|
|
return new ImageDataSimple(dim, status);
|
|
|
|
}
|
|
|
|
|
2015-04-07 18:26:58 +00:00
|
|
|
}
|