1
0
mirror of https://github.com/octoleo/plantuml.git synced 2024-11-26 14:56:28 +00:00

Merge pull request #679 from matthew16550/png-split

Update PNG splitting to support more diagram types
This commit is contained in:
arnaudroques 2021-09-21 14:43:38 +02:00 committed by GitHub
commit 08cba946b3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 176 additions and 187 deletions

View File

@ -63,6 +63,8 @@ public abstract class AbstractPSystem implements Diagram {
private final UmlSource source;
private Scale scale;
private int splitPagesHorizontal = 1;
private int splitPagesVertical = 1;
public AbstractPSystem(UmlSource source) {
this.source = Objects.requireNonNull(source);
@ -108,6 +110,24 @@ public abstract class AbstractPSystem implements Diagram {
return 1;
}
@Override
public int getSplitPagesHorizontal() {
return splitPagesHorizontal;
}
public void setSplitPagesHorizontal(int splitPagesHorizontal) {
this.splitPagesHorizontal = splitPagesHorizontal;
}
@Override
public int getSplitPagesVertical() {
return splitPagesVertical;
}
public void setSplitPagesVertical(int splitPagesVertical) {
this.splitPagesVertical = splitPagesVertical;
}
public DisplayPositionned getTitle() {
if (source == null) {
return DisplayPositionned.single(Display.empty(), HorizontalAlignment.CENTER, VerticalAlignment.TOP);

View File

@ -35,11 +35,13 @@
*/
package net.sourceforge.plantuml;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import net.sourceforge.plantuml.activitydiagram3.ActivityDiagram3;
@ -85,16 +87,34 @@ public class PSystemUtils {
if (system instanceof SequenceDiagram) {
return exportDiagramsSequence((SequenceDiagram) system, suggestedFile, fileFormatOption);
}
if (system instanceof CucaDiagram && fileFormatOption.getFileFormat() == FileFormat.HTML) {
return createFilesHtml((CucaDiagram) system, suggestedFile);
}
final FileImageData fileImageData;
if (system instanceof CucaDiagram) {
return exportDiagramsCuca((CucaDiagram) system, suggestedFile, fileFormatOption);
fileImageData = exportDiagramsCuca((CucaDiagram) system, suggestedFile, fileFormatOption);
}
if (system instanceof GanttDiagram) {
return exportDiagramsGantt2((GanttDiagram) system, suggestedFile, fileFormatOption);
else if (system instanceof GanttDiagram) {
fileImageData = exportDiagramsGantt2((GanttDiagram) system, suggestedFile, fileFormatOption);
}
if (system instanceof ActivityDiagram3) {
return exportDiagramsActivityDiagram3((ActivityDiagram3) system, suggestedFile, fileFormatOption);
else if (system instanceof ActivityDiagram3) {
fileImageData = exportDiagramsActivityDiagram3((ActivityDiagram3) system, suggestedFile, fileFormatOption);
}
return exportDiagramsDefault(system, suggestedFile, fileFormatOption);
else {
fileImageData = exportDiagramsDefault(system, suggestedFile, fileFormatOption);
}
if (fileImageData == null) {
return emptyList();
}
if (system instanceof TitledDiagram && fileFormatOption.getFileFormat() == FileFormat.PNG) {
return splitPng((TitledDiagram) system, suggestedFile, fileImageData, fileFormatOption);
}
return singletonList(fileImageData);
}
private static List<FileImageData> exportDiagramsNewpaged(NewpagedDiagram system, SuggestedFile suggestedFile,
@ -138,7 +158,7 @@ public class PSystemUtils {
return true;
}
static private List<FileImageData> exportDiagramsDefault(Diagram system, SuggestedFile suggestedFile,
static private FileImageData exportDiagramsDefault(Diagram system, SuggestedFile suggestedFile,
FileFormatOption fileFormat) throws IOException {
if (suggestedFile.getFile(0).exists() && suggestedFile.getFile(0).isDirectory()) {
throw new IllegalArgumentException("File is a directory " + suggestedFile);
@ -147,7 +167,7 @@ public class PSystemUtils {
ImageData imageData = null;
try {
if (PSystemUtils.canFileBeWritten(suggestedFile.getFile(0)) == false) {
return Collections.emptyList();
return null;
}
os = suggestedFile.getFile(0).createBufferedOutputStream();
// system.exportDiagram(os, null, 0, fileFormat);
@ -157,10 +177,10 @@ public class PSystemUtils {
os.close();
}
}
return Arrays.asList(new FileImageData(suggestedFile.getFile(0), imageData));
return new FileImageData(suggestedFile.getFile(0), imageData);
}
static private List<FileImageData> exportDiagramsActivityDiagram3(ActivityDiagram3 system,
static private FileImageData exportDiagramsActivityDiagram3(ActivityDiagram3 system,
SuggestedFile suggestedFile, FileFormatOption fileFormat) throws IOException {
if (suggestedFile.getFile(0).exists() && suggestedFile.getFile(0).isDirectory()) {
throw new IllegalArgumentException("File is a directory " + suggestedFile);
@ -170,7 +190,7 @@ public class PSystemUtils {
ImageData imageData = null;
try {
if (PSystemUtils.canFileBeWritten(suggestedFile.getFile(0)) == false) {
return Collections.emptyList();
return null;
}
os = suggestedFile.getFile(0).createBufferedOutputStream();
imageData = cmap = system.exportDiagram(os, 0, fileFormat);
@ -182,7 +202,7 @@ public class PSystemUtils {
if (cmap != null && cmap.containsCMapData()) {
system.exportCmap(suggestedFile, 0, cmap);
}
return Arrays.asList(new FileImageData(suggestedFile.getFile(0), imageData));
return new FileImageData(suggestedFile.getFile(0), imageData);
}
private static List<FileImageData> exportDiagramsSequence(SequenceDiagram system, SuggestedFile suggestedFile,
@ -211,21 +231,17 @@ public class PSystemUtils {
return result;
}
static private List<FileImageData> exportDiagramsCuca(CucaDiagram system, SuggestedFile suggestedFile,
static private FileImageData exportDiagramsCuca(CucaDiagram system, SuggestedFile suggestedFile,
FileFormatOption fileFormat) throws IOException {
if (suggestedFile.getFile(0).exists() && suggestedFile.getFile(0).isDirectory()) {
throw new IllegalArgumentException("File is a directory " + suggestedFile);
}
if (fileFormat.getFileFormat() == FileFormat.HTML) {
return createFilesHtml(system, suggestedFile);
}
ImageData cmap = null;
OutputStream os = null;
try {
if (PSystemUtils.canFileBeWritten(suggestedFile.getFile(0)) == false) {
return Collections.emptyList();
return null;
}
// System.err.println("FOO11=" + suggestedFile);
// os = SecurityUtils.BufferedOutputStream(suggestedFile));
@ -236,27 +252,14 @@ public class PSystemUtils {
os.close();
}
}
List<SFile> result = Arrays.asList(suggestedFile.getFile(0));
if (cmap != null && cmap.containsCMapData()) {
system.exportCmap(suggestedFile, 0, cmap);
}
if (fileFormat.getFileFormat() == FileFormat.PNG) {
final int dpi = system.getSkinParam().getDpi();
result = new PngSplitter(suggestedFile, system.getHorizontalPages(), system.getVerticalPages(),
system.getMetadata(), dpi, fileFormat.isWithMetadata(), system.getSkinParam().getSplitParam())
.getFiles();
}
final List<FileImageData> result2 = new ArrayList<>();
for (SFile f : result) {
result2.add(new FileImageData(f, cmap));
}
return result2;
return new FileImageData(suggestedFile.getFile(0), cmap);
}
static private List<FileImageData> exportDiagramsGantt2(GanttDiagram system, SuggestedFile suggestedFile,
static private FileImageData exportDiagramsGantt2(GanttDiagram system, SuggestedFile suggestedFile,
FileFormatOption fileFormat) throws IOException {
if (suggestedFile.getFile(0).exists() && suggestedFile.getFile(0).isDirectory()) {
throw new IllegalArgumentException("File is a directory " + suggestedFile);
@ -266,7 +269,7 @@ public class PSystemUtils {
OutputStream os = null;
try {
if (PSystemUtils.canFileBeWritten(suggestedFile.getFile(0)) == false) {
return Collections.emptyList();
return null;
}
os = new NamedOutputStream(suggestedFile.getFile(0));
cmap = system.exportDiagram(os, 0, fileFormat);
@ -275,20 +278,7 @@ public class PSystemUtils {
os.close();
}
}
List<SFile> result = Arrays.asList(suggestedFile.getFile(0));
if (fileFormat.getFileFormat() == FileFormat.PNG) {
final SplitParam splitParam = new SplitParam(HColorUtils.BLACK, null, 5);
result = new PngSplitter(suggestedFile, system.getHorizontalPages(), system.getVerticalPages(),
system.getMetadata(), system.getDpi(fileFormat), fileFormat.isWithMetadata(), splitParam)
.getFiles();
}
final List<FileImageData> result2 = new ArrayList<>();
for (SFile f : result) {
result2.add(new FileImageData(f, cmap));
}
return result2;
return new FileImageData(suggestedFile.getFile(0), cmap);
}
private static List<FileImageData> createFilesHtml(CucaDiagram system, SuggestedFile suggestedFile)
@ -300,4 +290,25 @@ public class PSystemUtils {
return maker.create();
}
private static List<FileImageData> splitPng(TitledDiagram diagram, SuggestedFile pngFile, FileImageData fileImageData, FileFormatOption fileFormatOption)
throws IOException {
final List<SFile> files = new PngSplitter(
pngFile,
diagram.getSplitPagesHorizontal(),
diagram.getSplitPagesVertical(),
fileFormatOption.isWithMetadata() ? diagram.getMetadata() : null,
diagram.getSkinParam().getDpi(),
diagram instanceof GanttDiagram
? new SplitParam(HColorUtils.BLACK, null, 5) // for backwards compatibility
: diagram.getSkinParam().getSplitParam()
).getFiles();
final List<FileImageData> result = new ArrayList<>();
for (SFile f : files) {
result.add(new FileImageData(f, fileImageData.getImageData()));
}
return result;
}
}

View File

@ -63,7 +63,6 @@ import net.sourceforge.plantuml.command.CommandNamespace2;
import net.sourceforge.plantuml.command.CommandNamespaceEmpty;
import net.sourceforge.plantuml.command.CommandPackage;
import net.sourceforge.plantuml.command.CommandPackageEmpty;
import net.sourceforge.plantuml.command.CommandPage;
import net.sourceforge.plantuml.command.CommandRankDir;
import net.sourceforge.plantuml.command.PSystemCommandFactory;
import net.sourceforge.plantuml.command.note.CommandConstraintOnLinks;
@ -96,7 +95,6 @@ public class ClassDiagramFactory extends PSystemCommandFactory {
cmds.add(new CommandRankDir());
cmds.add(new CommandNewpage(this));
cmds.add(new CommandPage());
cmds.add(new CommandAddMethod());
addCommonHides(cmds);

View File

@ -35,14 +35,14 @@
*/
package net.sourceforge.plantuml.command;
import net.sourceforge.plantuml.AbstractPSystem;
import net.sourceforge.plantuml.LineLocation;
import net.sourceforge.plantuml.classdiagram.AbstractEntityDiagram;
import net.sourceforge.plantuml.command.regex.IRegex;
import net.sourceforge.plantuml.command.regex.RegexConcat;
import net.sourceforge.plantuml.command.regex.RegexLeaf;
import net.sourceforge.plantuml.command.regex.RegexResult;
public class CommandPage extends SingleLineCommand2<AbstractEntityDiagram> {
public class CommandPage extends SingleLineCommand2<AbstractPSystem> {
public CommandPage() {
super(getRegexConcat());
@ -60,7 +60,7 @@ public class CommandPage extends SingleLineCommand2<AbstractEntityDiagram> {
}
@Override
protected CommandExecutionResult executeArg(AbstractEntityDiagram classDiagram, LineLocation location,
protected CommandExecutionResult executeArg(AbstractPSystem system, LineLocation location,
RegexResult arg) {
final int horizontal = Integer.parseInt(arg.get("NB1", 0));
@ -68,8 +68,8 @@ public class CommandPage extends SingleLineCommand2<AbstractEntityDiagram> {
if (horizontal <= 0 || vertical <= 0) {
return CommandExecutionResult.error("Argument must be positive");
}
classDiagram.setHorizontalPages(horizontal);
classDiagram.setVerticalPages(vertical);
system.setSplitPagesHorizontal(horizontal);
system.setSplitPagesVertical(vertical);
return CommandExecutionResult.ok();
}

View File

@ -231,6 +231,7 @@ public abstract class PSystemCommandFactory extends PSystemAbstractFactory {
cmds.add(new CommandSkinParamMultilines());
cmds.add(new CommandSkin());
cmds.add(new CommandMinwidth());
cmds.add(new CommandPage());
cmds.add(new CommandRotate());
cmds.add(new CommandScale());
cmds.add(new CommandScaleWidthAndHeight());

View File

@ -71,6 +71,10 @@ public interface Diagram {
*/
int getNbImages();
int getSplitPagesHorizontal();
int getSplitPagesVertical();
DiagramDescription getDescription();
String getMetadata();

View File

@ -104,9 +104,6 @@ public abstract class CucaDiagram extends UmlDiagram implements GroupHierarchy,
return entityFactory.getAllSuperGroups();
}
private int horizontalPages = 1;
private int verticalPages = 1;
private final List<HideOrShow2> hides2 = new ArrayList<>();
private final List<HideOrShow2> removed = new ArrayList<>();
protected final EntityFactory entityFactory = new EntityFactory(hides2, removed, this);
@ -546,27 +543,6 @@ public abstract class CucaDiagram extends UmlDiagram implements GroupHierarchy,
return entityFactory.getLinks();
}
final public int getHorizontalPages() {
return horizontalPages;
}
final public void setHorizontalPages(int horizontalPages) {
this.horizontalPages = horizontalPages;
}
final public int getVerticalPages() {
return verticalPages;
}
final public void setVerticalPages(int verticalPages) {
this.verticalPages = verticalPages;
}
@Override
public int getNbImages() {
return this.horizontalPages * this.verticalPages;
}
abstract protected List<String> getDotStrings();
final public String[] getDotStringSkek() {

View File

@ -80,7 +80,6 @@ public class DescriptionDiagramFactory extends PSystemCommandFactory {
cmds.add(new CommandNewpage(this));
addCommonCommands1(cmds);
cmds.add(new CommandPage());
cmds.add(new CommandLinkElement());
cmds.add(new CommandHideShow2());
cmds.add(new CommandRemoveRestore());

View File

@ -52,8 +52,8 @@ public class PngSplitter {
private final List<SFile> files = new ArrayList<>();
public PngSplitter(SuggestedFile pngFile, int horizontalPages, int verticalPages, String source, int dpi,
boolean isWithMetadata, SplitParam splitParam) throws IOException {
public PngSplitter(SuggestedFile pngFile, int horizontalPages, int verticalPages, String metadata, int dpi,
SplitParam splitParam) throws IOException {
if (horizontalPages == 1 && verticalPages == 1) {
this.files.add(pngFile.getFile(0));
return;
@ -106,7 +106,7 @@ public class PngSplitter {
g2d.dispose();
}
// Thread.yield();
PngIO.write(piece, f, isWithMetadata ? source : null, dpi);
PngIO.write(piece, f, metadata, dpi);
// Thread.yield();
}
}

View File

@ -162,30 +162,6 @@ public class GanttDiagram extends TitledDiagram implements ToTaskDraw, WithSprit
super(source, UmlDiagramType.GANTT);
}
private int horizontalPages = 1;
private int verticalPages = 1;
final public int getHorizontalPages() {
return horizontalPages;
}
final public void setHorizontalPages(int horizontalPages) {
this.horizontalPages = horizontalPages;
}
final public int getVerticalPages() {
return verticalPages;
}
final public void setVerticalPages(int verticalPages) {
this.verticalPages = verticalPages;
}
@Override
public int getNbImages() {
return this.horizontalPages * this.verticalPages;
}
public final int getDpi(FileFormatOption fileFormatOption) {
return 96;
}

View File

@ -53,7 +53,6 @@ import net.sourceforge.plantuml.project.command.CommandGanttArrow2;
import net.sourceforge.plantuml.project.command.CommandLabelOnColumn;
import net.sourceforge.plantuml.project.command.CommandLanguage;
import net.sourceforge.plantuml.project.command.CommandNoteBottom;
import net.sourceforge.plantuml.project.command.CommandPage;
import net.sourceforge.plantuml.project.command.CommandPrintBetween;
import net.sourceforge.plantuml.project.command.CommandPrintScale;
import net.sourceforge.plantuml.project.command.CommandSeparator;
@ -107,7 +106,6 @@ public class GanttDiagramFactory extends PSystemCommandFactory {
cmds.add(new CommandLanguage());
cmds.add(new CommandPrintScale());
cmds.add(new CommandPrintBetween());
cmds.add(new CommandPage());
cmds.add(new CommandNoteBottom());
cmds.add(new CommandFootbox());
cmds.add(new CommandLabelOnColumn());

View File

@ -1,77 +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.project.command;
import net.sourceforge.plantuml.LineLocation;
import net.sourceforge.plantuml.command.CommandExecutionResult;
import net.sourceforge.plantuml.command.SingleLineCommand2;
import net.sourceforge.plantuml.command.regex.IRegex;
import net.sourceforge.plantuml.command.regex.RegexConcat;
import net.sourceforge.plantuml.command.regex.RegexLeaf;
import net.sourceforge.plantuml.command.regex.RegexResult;
import net.sourceforge.plantuml.project.GanttDiagram;
public class CommandPage extends SingleLineCommand2<GanttDiagram> {
public CommandPage() {
super(getRegexConcat());
}
static IRegex getRegexConcat() {
return RegexConcat.build(CommandPage.class.getName(), RegexLeaf.start(), //
new RegexLeaf("page"), //
RegexLeaf.spaceOneOrMore(), //
new RegexLeaf("NB1", "(\\d+)"), //
RegexLeaf.spaceZeroOrMore(), //
new RegexLeaf("x"), //
RegexLeaf.spaceZeroOrMore(), //
new RegexLeaf("NB2", "(\\d+)"), RegexLeaf.end()); //
}
@Override
protected CommandExecutionResult executeArg(GanttDiagram diagram, LineLocation location, RegexResult arg) {
final int horizontal = Integer.parseInt(arg.get("NB1", 0));
final int vertical = Integer.parseInt(arg.get("NB2", 0));
if (horizontal <= 0 || vertical <= 0) {
return CommandExecutionResult.error("Argument must be positive");
}
diagram.setHorizontalPages(horizontal);
diagram.setVerticalPages(vertical);
return CommandExecutionResult.ok();
}
}

View File

@ -0,0 +1,83 @@
package net.sourceforge.plantuml;
import static java.nio.charset.StandardCharsets.UTF_8;
import static net.sourceforge.plantuml.FileFormat.PNG;
import static org.assertj.core.api.Assertions.assertThat;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Collections;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import net.sourceforge.plantuml.core.Diagram;
import net.sourceforge.plantuml.preproc.Defines;
class PSystemUtilsTest {
//
// Test Cases
//
@Test
void test_splitPng(@TempDir Path tempDir) throws Exception {
final String source = "" +
"@startuml\n" +
"page 3x2\n" +
"class foo\n" +
"@enduml\n";
final List<FileImageData> fileImageData = render(source, tempDir);
assertThat(tempDir.resolve("output.png"))
.isNotEmptyFile();
assertThat(tempDir.resolve("output_001.png"))
.isNotEmptyFile();
assertThat(tempDir.resolve("output_002.png"))
.isNotEmptyFile();
assertThat(tempDir.resolve("output_003.png"))
.isNotEmptyFile();
assertThat(tempDir.resolve("output_004.png"))
.isNotEmptyFile();
assertThat(tempDir.resolve("output_005.png"))
.isNotEmptyFile();
assertThat(fileImageData)
.hasSize(6);
assertThat(tempDir.toFile().listFiles())
.hasSize(6);
}
@Test
void test_splitPng_no_split(@TempDir Path tempDir) throws Exception {
final String source = "" +
"@startuml\n" +
"class foo\n" +
"@enduml\n";
final List<FileImageData> fileImageData = render(source, tempDir);
assertThat(tempDir.resolve("output.png"))
.isNotEmptyFile();
assertThat(fileImageData)
.hasSize(1);
assertThat(tempDir.toFile().listFiles())
.hasSize(1);
}
//
// Test DSL
//
private static List<FileImageData> render(String source, Path tempDir) throws IOException {
final SourceStringReader reader = new SourceStringReader(Defines.createEmpty(), source, UTF_8.name(), Collections.<String>emptyList());
final Diagram diagram = reader.getBlocks().get(0).getDiagram();
final SuggestedFile suggestedFile = SuggestedFile.fromOutputFile(tempDir.resolve("output").toFile(), PNG, 0);
return PSystemUtils.exportDiagrams(diagram, suggestedFile, new FileFormatOption(PNG), false);
}
}