mirror of
https://github.com/octoleo/plantuml.git
synced 2024-11-25 06:17:33 +00:00
Import version 1.2021.5
This commit is contained in:
parent
b56e0af316
commit
fcf10ee0a9
@ -91,7 +91,7 @@
|
|||||||
<manifest>
|
<manifest>
|
||||||
<attribute name="Automatic-Module-Name" value="net.sourceforge.plantuml" />
|
<attribute name="Automatic-Module-Name" value="net.sourceforge.plantuml" />
|
||||||
<attribute name="Main-Class" value="net.sourceforge.plantuml.Run" />
|
<attribute name="Main-Class" value="net.sourceforge.plantuml.Run" />
|
||||||
<attribute name="Class-Path" value="avalon-framework-4.2.0.jar batik-all-1.7.jar commons-io-1.3.1.jar commons-logging-1.0.4.jar fop.jar xml-apis-ext-1.3.04.jar xmlgraphics-commons-1.4.jar jlatexmath-minimal-1.0.3.jar jlm_cyrillic.jar jlm_greek.jar vizjs.jar j2v8_win32_x86_64-3.1.6.jar j2v8_linux_x86_64-3.1.6.jar j2v8_macosx_x86_64-3.1.6.jar ditaa0_9.jar" />
|
<attribute name="Class-Path" value="elk-full.jar avalon-framework-4.2.0.jar batik-all-1.7.jar commons-io-1.3.1.jar commons-logging-1.0.4.jar fop.jar xml-apis-ext-1.3.04.jar xmlgraphics-commons-1.4.jar jlatexmath-minimal-1.0.3.jar jlm_cyrillic.jar jlm_greek.jar vizjs.jar j2v8_win32_x86_64-3.1.6.jar j2v8_linux_x86_64-3.1.6.jar j2v8_macosx_x86_64-3.1.6.jar ditaa0_9.jar" />
|
||||||
</manifest>
|
</manifest>
|
||||||
</jar>
|
</jar>
|
||||||
<delete dir="build" />
|
<delete dir="build" />
|
||||||
|
17
pom.xml
17
pom.xml
@ -35,7 +35,7 @@
|
|||||||
|
|
||||||
<groupId>net.sourceforge.plantuml</groupId>
|
<groupId>net.sourceforge.plantuml</groupId>
|
||||||
<artifactId>plantuml</artifactId>
|
<artifactId>plantuml</artifactId>
|
||||||
<version>1.2021.5-SNAPSHOT</version>
|
<version>1.2021.6-SNAPSHOT</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<name>PlantUML</name>
|
<name>PlantUML</name>
|
||||||
@ -94,21 +94,6 @@
|
|||||||
<version>1.0.7</version>
|
<version>1.0.7</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.eclipse.elk</groupId>
|
|
||||||
<artifactId>org.eclipse.elk.core</artifactId>
|
|
||||||
<version>0.7.1</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.eclipse.elk</groupId>
|
|
||||||
<artifactId>org.eclipse.elk.alg.layered</artifactId>
|
|
||||||
<version>0.7.1</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.eclipse.elk</groupId>
|
|
||||||
<artifactId>org.eclipse.elk.alg.mrtree</artifactId>
|
|
||||||
<version>0.7.1</version>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<licenses>
|
<licenses>
|
||||||
|
@ -290,6 +290,10 @@ ganttDiagram {
|
|||||||
timeline {
|
timeline {
|
||||||
BackgroundColor transparent
|
BackgroundColor transparent
|
||||||
}
|
}
|
||||||
|
closed {
|
||||||
|
BackGroundColor #E0E8E8
|
||||||
|
FontColor #909898
|
||||||
|
}
|
||||||
task {
|
task {
|
||||||
RoundCorner 0
|
RoundCorner 0
|
||||||
Margin 2 2 2 2
|
Margin 2 2 2 2
|
||||||
|
271
src/ext/plantuml/com/at/gadermaier/argon2/Argon2.java
Normal file
271
src/ext/plantuml/com/at/gadermaier/argon2/Argon2.java
Normal file
@ -0,0 +1,271 @@
|
|||||||
|
/* This file is taken from
|
||||||
|
https://github.com/andreas1327250/argon2-java
|
||||||
|
|
||||||
|
Original Author: Andreas Gadermaier <up.gadermaier@gmail.com>
|
||||||
|
*/
|
||||||
|
package ext.plantuml.com.at.gadermaier.argon2;
|
||||||
|
|
||||||
|
import static ext.plantuml.com.at.gadermaier.argon2.Constants.Defaults.LANES_DEF;
|
||||||
|
import static ext.plantuml.com.at.gadermaier.argon2.Constants.Defaults.LOG_M_COST_DEF;
|
||||||
|
import static ext.plantuml.com.at.gadermaier.argon2.Constants.Defaults.OUTLEN_DEF;
|
||||||
|
import static ext.plantuml.com.at.gadermaier.argon2.Constants.Defaults.TYPE_DEF;
|
||||||
|
import static ext.plantuml.com.at.gadermaier.argon2.Constants.Defaults.T_COST_DEF;
|
||||||
|
import static ext.plantuml.com.at.gadermaier.argon2.Constants.Defaults.VERSION_DEF;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.CharBuffer;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import ext.plantuml.com.at.gadermaier.argon2.algorithm.FillMemory;
|
||||||
|
import ext.plantuml.com.at.gadermaier.argon2.algorithm.Finalize;
|
||||||
|
import ext.plantuml.com.at.gadermaier.argon2.algorithm.Initialize;
|
||||||
|
import ext.plantuml.com.at.gadermaier.argon2.model.Argon2Type;
|
||||||
|
import ext.plantuml.com.at.gadermaier.argon2.model.Instance;
|
||||||
|
|
||||||
|
public class Argon2 {
|
||||||
|
|
||||||
|
private byte[] output;
|
||||||
|
private int outputLength; // -l N
|
||||||
|
private double duration;
|
||||||
|
|
||||||
|
private byte[] password;
|
||||||
|
private byte[] salt;
|
||||||
|
private byte[] secret;
|
||||||
|
private byte[] additional;
|
||||||
|
|
||||||
|
private int iterations; // -t N
|
||||||
|
private int memory; // -m N
|
||||||
|
private int lanes; // -p N
|
||||||
|
|
||||||
|
private int version; // -v (10/13)
|
||||||
|
private Argon2Type type;
|
||||||
|
|
||||||
|
private boolean clearMemory = true;
|
||||||
|
private Charset charset = Charset.forName("UTF-8");
|
||||||
|
|
||||||
|
private boolean encodedOnly = false;
|
||||||
|
private boolean rawOnly = false;
|
||||||
|
|
||||||
|
Argon2() {
|
||||||
|
this.lanes = LANES_DEF;
|
||||||
|
this.outputLength = OUTLEN_DEF;
|
||||||
|
this.memory = 1 << LOG_M_COST_DEF;
|
||||||
|
this.iterations = T_COST_DEF;
|
||||||
|
this.version = VERSION_DEF;
|
||||||
|
this.type = TYPE_DEF;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] toByteArray(char[] chars, Charset charset) {
|
||||||
|
assert chars != null;
|
||||||
|
|
||||||
|
CharBuffer charBuffer = CharBuffer.wrap(chars);
|
||||||
|
ByteBuffer byteBuffer = charset.encode(charBuffer);
|
||||||
|
byte[] bytes = Arrays.copyOfRange(byteBuffer.array(), byteBuffer.position(), byteBuffer.limit());
|
||||||
|
Arrays.fill(byteBuffer.array(), (byte) 0);
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void hashNow() {
|
||||||
|
try {
|
||||||
|
Validation.validateInput(this);
|
||||||
|
|
||||||
|
long start = System.nanoTime();
|
||||||
|
|
||||||
|
Instance instance = new Instance(this);
|
||||||
|
|
||||||
|
Initialize.initialize(instance, this);
|
||||||
|
FillMemory.fillMemoryBlocks(instance);
|
||||||
|
Finalize.finalize(instance, this);
|
||||||
|
|
||||||
|
duration = (System.nanoTime() - start) / 1000000000.0;
|
||||||
|
} finally {
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
if (password != null)
|
||||||
|
Arrays.fill(password, 0, password.length - 1, (byte) 0);
|
||||||
|
|
||||||
|
if (salt != null)
|
||||||
|
Arrays.fill(salt, 0, salt.length - 1, (byte) 0);
|
||||||
|
|
||||||
|
if (secret != null)
|
||||||
|
Arrays.fill(secret, 0, secret.length - 1, (byte) 0);
|
||||||
|
|
||||||
|
if (additional != null)
|
||||||
|
Arrays.fill(additional, 0, additional.length - 1, (byte) 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void printSummary() {
|
||||||
|
if (encodedOnly)
|
||||||
|
System.out.println(getEncoded());
|
||||||
|
else if (rawOnly)
|
||||||
|
System.out.println(getOutputString());
|
||||||
|
else {
|
||||||
|
System.out.println("Type:\t\t" + type);
|
||||||
|
System.out.println("Iterations:\t" + iterations);
|
||||||
|
System.out.println("Memory:\t\t" + memory + " KiB");
|
||||||
|
System.out.println("Parallelism:\t" + lanes);
|
||||||
|
System.out.println("Hash:\t\t" + getOutputString());
|
||||||
|
System.out.println("Encoded:\t " + getEncoded());
|
||||||
|
System.out.println(duration + " seconds");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Argon2 setMemoryInKiB(int memory) {
|
||||||
|
this.memory = memory;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Argon2 setParallelism(int parallelism) {
|
||||||
|
this.lanes = parallelism;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Argon2 setPassword(char[] password) {
|
||||||
|
return setPassword(toByteArray(password, charset));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Argon2 setSalt(String salt) {
|
||||||
|
return setSalt(salt.getBytes(charset));
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getOutput() {
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOutput(byte[] finalResult) {
|
||||||
|
this.output = finalResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOutputString() {
|
||||||
|
return Util.bytesToHexString(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getOutputLength() {
|
||||||
|
return outputLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Argon2 setOutputLength(int outputLength) {
|
||||||
|
this.outputLength = outputLength;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getPassword() {
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Argon2 setPassword(byte[] password) {
|
||||||
|
this.password = password;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPasswordLength() {
|
||||||
|
return password.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getSalt() {
|
||||||
|
return salt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Argon2 setSalt(byte[] salt) {
|
||||||
|
this.salt = salt;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSaltLength() {
|
||||||
|
return salt.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getSecret() {
|
||||||
|
return secret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Argon2 setSecret(byte[] secret) {
|
||||||
|
this.secret = secret;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSecretLength() {
|
||||||
|
return secret != null ? secret.length : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getAdditional() {
|
||||||
|
return additional;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Argon2 setAdditional(byte[] additional) {
|
||||||
|
this.additional = additional;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAdditionalLength() {
|
||||||
|
return additional != null ? additional.length : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getIterations() {
|
||||||
|
return iterations;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Argon2 setIterations(int iterations) {
|
||||||
|
this.iterations = iterations;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMemory() {
|
||||||
|
return memory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Argon2 setMemory(int memory) {
|
||||||
|
this.memory = 1 << memory;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLanes() {
|
||||||
|
return lanes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getVersion() {
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Argon2 setVersion(int version) {
|
||||||
|
this.version = version;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Argon2Type getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Argon2 setType(Argon2Type type) {
|
||||||
|
this.type = type;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isClearMemory() {
|
||||||
|
return clearMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClearMemory(boolean clearMemory) {
|
||||||
|
this.clearMemory = clearMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Charset getCharset() {
|
||||||
|
return charset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEncodedOnly(boolean encodedOnly) {
|
||||||
|
this.encodedOnly = encodedOnly;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRawOnly(boolean rawOnly) {
|
||||||
|
this.rawOnly = rawOnly;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEncoded() {
|
||||||
|
return ""; // TODO
|
||||||
|
}
|
||||||
|
}
|
12
src/ext/plantuml/com/at/gadermaier/argon2/Argon2Factory.java
Normal file
12
src/ext/plantuml/com/at/gadermaier/argon2/Argon2Factory.java
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
/* This file is taken from
|
||||||
|
https://github.com/andreas1327250/argon2-java
|
||||||
|
|
||||||
|
Original Author: Andreas Gadermaier <up.gadermaier@gmail.com>
|
||||||
|
*/
|
||||||
|
package ext.plantuml.com.at.gadermaier.argon2;
|
||||||
|
|
||||||
|
public class Argon2Factory {
|
||||||
|
public static Argon2 create(){
|
||||||
|
return new Argon2();
|
||||||
|
}
|
||||||
|
}
|
102
src/ext/plantuml/com/at/gadermaier/argon2/Constants.java
Normal file
102
src/ext/plantuml/com/at/gadermaier/argon2/Constants.java
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
/* This file is taken from
|
||||||
|
https://github.com/andreas1327250/argon2-java
|
||||||
|
|
||||||
|
Original Author: Andreas Gadermaier <up.gadermaier@gmail.com>
|
||||||
|
*/
|
||||||
|
package ext.plantuml.com.at.gadermaier.argon2;
|
||||||
|
|
||||||
|
import ext.plantuml.com.at.gadermaier.argon2.model.Argon2Type;
|
||||||
|
|
||||||
|
public class Constants {
|
||||||
|
|
||||||
|
/* Memory block size in bytes */
|
||||||
|
public static final int ARGON2_BLOCK_SIZE = 1024;
|
||||||
|
public static final int ARGON2_QWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 8;
|
||||||
|
/* Number of pseudo-random values generated by one call to Blake in Argon2i
|
||||||
|
to
|
||||||
|
generate reference block positions
|
||||||
|
*/
|
||||||
|
public static final int ARGON2_ADDRESSES_IN_BLOCK = 128;
|
||||||
|
/* Pre-hashing digest length and its extension*/
|
||||||
|
public static final int ARGON2_PREHASH_DIGEST_LENGTH = 64;
|
||||||
|
public static final int ARGON2_PREHASH_SEED_LENGTH = 72;
|
||||||
|
/* Number of synchronization points between lanes per pass */
|
||||||
|
public static final int ARGON2_SYNC_POINTS = 4;
|
||||||
|
/* Flags to determine which fields are securely wiped (default = no wipe). */
|
||||||
|
public static final int ARGON2_DEFAULT_FLAGS = 0;
|
||||||
|
public static final int ARGON2_VERSION_10 = 0x10;
|
||||||
|
public static final int ARGON2_VERSION_13 = 0x13;
|
||||||
|
|
||||||
|
public static class Defaults {
|
||||||
|
|
||||||
|
public static final int OUTLEN_DEF = 32;
|
||||||
|
public static final int T_COST_DEF = 3;
|
||||||
|
public static final int LOG_M_COST_DEF = 12;
|
||||||
|
public static final int LANES_DEF = 1;
|
||||||
|
public static final Argon2Type TYPE_DEF = Argon2Type.Argon2i;
|
||||||
|
public static final int VERSION_DEF = ARGON2_VERSION_13;
|
||||||
|
public static final int ARGON2_VERSION_NUMBER = ARGON2_VERSION_13;
|
||||||
|
public static final boolean ENCODED_ONLY = false;
|
||||||
|
public static final boolean RAW_ONLY = false;
|
||||||
|
}
|
||||||
|
//public static int ARGON2_FLAG_CLEAR_PASSWORD (UINT32_C(1) << 0)
|
||||||
|
//public static int ARGON2_FLAG_CLEAR_SECRET (UINT32_C(1) << 1)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Argon2 input parameter restrictions
|
||||||
|
*/
|
||||||
|
public static class Constraints {
|
||||||
|
|
||||||
|
public static final int MAX_PASSWORD_LEN = 128;
|
||||||
|
|
||||||
|
/* Minimum and maximum number of lanes (degree of parallelism) */
|
||||||
|
public static final int MIN_PARALLELISM = 1;
|
||||||
|
public static final int MAX_PARALLELISM = 16777216;
|
||||||
|
|
||||||
|
/* Minimum and maximum digest size in bytes */
|
||||||
|
public static final int MIN_OUTLEN = 4;
|
||||||
|
public static final int MAX_OUTLEN = Integer.MAX_VALUE;
|
||||||
|
|
||||||
|
/* Minimum and maximum number of memory blocks (each of BLOCK_SIZE bytes) */
|
||||||
|
public static final int MIN_MEMORY = (2 * ARGON2_SYNC_POINTS); /* 2 blocks per slice */
|
||||||
|
|
||||||
|
/* Minimum and maximum number of passes */
|
||||||
|
public static final int MIN_ITERATIONS = 1;
|
||||||
|
public static final int MAX_ITERATIONS = Integer.MAX_VALUE;
|
||||||
|
|
||||||
|
/* Minimum and maximum password length in bytes */
|
||||||
|
public static final int MIN_PWD_LENGTH = 0;
|
||||||
|
public static final int MAX_PWD_LENGTH = Integer.MAX_VALUE;
|
||||||
|
|
||||||
|
/* Minimum and maximum salt length in bytes */
|
||||||
|
public static final int MIN_SALT_LENGTH = 0;
|
||||||
|
public static final int MAX_SALT_LENGTH = Integer.MAX_VALUE;
|
||||||
|
|
||||||
|
/* Minimum and maximum key length in bytes */
|
||||||
|
public static final int MAX_SECRET_LENGTH = Integer.MAX_VALUE;
|
||||||
|
|
||||||
|
/* Minimum and maximum associated model length in bytes */
|
||||||
|
public static final int MAX_AD_LENGTH = Integer.MAX_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Messages {
|
||||||
|
public static final String P_MIN_MSG = "degree of parallelism cannot be smaller than one";
|
||||||
|
public static final String P_MAX_MSG = "parallelism cannot be greater than 16777216";
|
||||||
|
|
||||||
|
public static final String M_MIN_MSG = "memory too small";
|
||||||
|
|
||||||
|
public static final String T_MIN_MSG = "number of iterations cannot be less than one";
|
||||||
|
public static final String T_MAX_MSG = "number of iterations too high";
|
||||||
|
|
||||||
|
public static final String PWD_MIN_MSG = "password too short";
|
||||||
|
public static final String PWD_MAX_MSG = "password too long";
|
||||||
|
|
||||||
|
public static final String SALT_MIN_MSG = "salt too short";
|
||||||
|
public static final String SALT_MAX_MSG = "salt too long";
|
||||||
|
|
||||||
|
public static final String SECRET_MAX_MSG = "secret too long";
|
||||||
|
public static final String ADDITIONAL_MAX_MSG = "additional data too long";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
67
src/ext/plantuml/com/at/gadermaier/argon2/Util.java
Normal file
67
src/ext/plantuml/com/at/gadermaier/argon2/Util.java
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/* This file is taken from
|
||||||
|
https://github.com/andreas1327250/argon2-java
|
||||||
|
|
||||||
|
Original Author: Andreas Gadermaier <up.gadermaier@gmail.com>
|
||||||
|
*/
|
||||||
|
package ext.plantuml.com.at.gadermaier.argon2;
|
||||||
|
|
||||||
|
public class Util {
|
||||||
|
|
||||||
|
public static String bytesToHexString(byte[] bytes) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (byte b : bytes) {
|
||||||
|
sb.append(String.format("%02x", b & 0xff));
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] hexStringToByteArray(String s) {
|
||||||
|
int len = s.length();
|
||||||
|
byte[] data = new byte[len / 2];
|
||||||
|
for (int i = 0; i < len; i += 2) {
|
||||||
|
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
|
||||||
|
+ Character.digit(s.charAt(i+1), 16));
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long littleEndianBytesToLong(byte[] b) {
|
||||||
|
long result = 0;
|
||||||
|
for (int i = 7; i >= 0; i--) {
|
||||||
|
result <<= 8;
|
||||||
|
result |= (b[i] & 0xFF);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] intToLittleEndianBytes(int a) {
|
||||||
|
byte[] result = new byte[4];
|
||||||
|
result[0] = (byte) (a & 0xFF);
|
||||||
|
result[1] = (byte) ((a >> 8) & 0xFF);
|
||||||
|
result[2] = (byte) ((a >> 16) & 0xFF);
|
||||||
|
result[3] = (byte) ((a >> 24) & 0xFF);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] longToLittleEndianBytes(long a) {
|
||||||
|
byte[] result = new byte[8];
|
||||||
|
result[0] = (byte) (a & 0xFF);
|
||||||
|
result[1] = (byte) ((a >> 8) & 0xFF);
|
||||||
|
result[2] = (byte) ((a >> 16) & 0xFF);
|
||||||
|
result[3] = (byte) ((a >> 24) & 0xFF);
|
||||||
|
result[4] = (byte) ((a >> 32) & 0xFF);
|
||||||
|
result[5] = (byte) ((a >> 40) & 0xFF);
|
||||||
|
result[6] = (byte) ((a >> 48) & 0xFF);
|
||||||
|
result[7] = (byte) ((a >> 56) & 0xFF);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long intToLong(int x){
|
||||||
|
byte[] intBytes = intToLittleEndianBytes(x);
|
||||||
|
byte[] bytes = new byte[8];
|
||||||
|
System.arraycopy(intBytes, 0, bytes, 0, 4);
|
||||||
|
return littleEndianBytesToLong(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
63
src/ext/plantuml/com/at/gadermaier/argon2/Validation.java
Normal file
63
src/ext/plantuml/com/at/gadermaier/argon2/Validation.java
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/* This file is taken from
|
||||||
|
https://github.com/andreas1327250/argon2-java
|
||||||
|
|
||||||
|
Original Author: Andreas Gadermaier <up.gadermaier@gmail.com>
|
||||||
|
*/
|
||||||
|
package ext.plantuml.com.at.gadermaier.argon2;
|
||||||
|
|
||||||
|
import static ext.plantuml.com.at.gadermaier.argon2.Constants.Constraints.MAX_AD_LENGTH;
|
||||||
|
import static ext.plantuml.com.at.gadermaier.argon2.Constants.Constraints.MAX_ITERATIONS;
|
||||||
|
import static ext.plantuml.com.at.gadermaier.argon2.Constants.Constraints.MAX_PARALLELISM;
|
||||||
|
import static ext.plantuml.com.at.gadermaier.argon2.Constants.Constraints.MAX_PWD_LENGTH;
|
||||||
|
import static ext.plantuml.com.at.gadermaier.argon2.Constants.Constraints.MAX_SALT_LENGTH;
|
||||||
|
import static ext.plantuml.com.at.gadermaier.argon2.Constants.Constraints.MAX_SECRET_LENGTH;
|
||||||
|
import static ext.plantuml.com.at.gadermaier.argon2.Constants.Constraints.MIN_ITERATIONS;
|
||||||
|
import static ext.plantuml.com.at.gadermaier.argon2.Constants.Constraints.MIN_PARALLELISM;
|
||||||
|
import static ext.plantuml.com.at.gadermaier.argon2.Constants.Constraints.MIN_PWD_LENGTH;
|
||||||
|
import static ext.plantuml.com.at.gadermaier.argon2.Constants.Constraints.MIN_SALT_LENGTH;
|
||||||
|
import static ext.plantuml.com.at.gadermaier.argon2.Constants.Messages.ADDITIONAL_MAX_MSG;
|
||||||
|
import static ext.plantuml.com.at.gadermaier.argon2.Constants.Messages.M_MIN_MSG;
|
||||||
|
import static ext.plantuml.com.at.gadermaier.argon2.Constants.Messages.PWD_MAX_MSG;
|
||||||
|
import static ext.plantuml.com.at.gadermaier.argon2.Constants.Messages.PWD_MIN_MSG;
|
||||||
|
import static ext.plantuml.com.at.gadermaier.argon2.Constants.Messages.P_MAX_MSG;
|
||||||
|
import static ext.plantuml.com.at.gadermaier.argon2.Constants.Messages.P_MIN_MSG;
|
||||||
|
import static ext.plantuml.com.at.gadermaier.argon2.Constants.Messages.SALT_MAX_MSG;
|
||||||
|
import static ext.plantuml.com.at.gadermaier.argon2.Constants.Messages.SALT_MIN_MSG;
|
||||||
|
import static ext.plantuml.com.at.gadermaier.argon2.Constants.Messages.SECRET_MAX_MSG;
|
||||||
|
import static ext.plantuml.com.at.gadermaier.argon2.Constants.Messages.T_MAX_MSG;
|
||||||
|
import static ext.plantuml.com.at.gadermaier.argon2.Constants.Messages.T_MIN_MSG;
|
||||||
|
|
||||||
|
import ext.plantuml.com.at.gadermaier.argon2.exception.Argon2InvalidParameterException;
|
||||||
|
|
||||||
|
class Validation {
|
||||||
|
|
||||||
|
static void validateInput(Argon2 argon2){
|
||||||
|
String message = null;
|
||||||
|
|
||||||
|
if (argon2.getLanes() < MIN_PARALLELISM)
|
||||||
|
message = P_MIN_MSG;
|
||||||
|
else if (argon2.getLanes() > MAX_PARALLELISM)
|
||||||
|
message = P_MAX_MSG;
|
||||||
|
else if(argon2.getMemory() < 2 * argon2.getLanes())
|
||||||
|
message = M_MIN_MSG;
|
||||||
|
else if(argon2.getIterations() < MIN_ITERATIONS)
|
||||||
|
message = T_MIN_MSG;
|
||||||
|
else if(argon2.getIterations() > MAX_ITERATIONS)
|
||||||
|
message = T_MAX_MSG;
|
||||||
|
else if(argon2.getPasswordLength() < MIN_PWD_LENGTH)
|
||||||
|
message = PWD_MIN_MSG;
|
||||||
|
else if(argon2.getPasswordLength() > MAX_PWD_LENGTH)
|
||||||
|
message = PWD_MAX_MSG;
|
||||||
|
else if(argon2.getSaltLength() < MIN_SALT_LENGTH)
|
||||||
|
message = SALT_MIN_MSG;
|
||||||
|
else if(argon2.getSaltLength() > MAX_SALT_LENGTH)
|
||||||
|
message = SALT_MAX_MSG;
|
||||||
|
else if(argon2.getSecretLength() > MAX_SECRET_LENGTH)
|
||||||
|
message = SECRET_MAX_MSG;
|
||||||
|
else if(argon2.getAdditionalLength() > MAX_AD_LENGTH)
|
||||||
|
message = ADDITIONAL_MAX_MSG;
|
||||||
|
|
||||||
|
if(message != null)
|
||||||
|
throw new Argon2InvalidParameterException(message);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
/* This file is taken from
|
||||||
|
https://github.com/andreas1327250/argon2-java
|
||||||
|
|
||||||
|
Original Author: Andreas Gadermaier <up.gadermaier@gmail.com>
|
||||||
|
*/
|
||||||
|
package ext.plantuml.com.at.gadermaier.argon2.algorithm;
|
||||||
|
|
||||||
|
import ext.plantuml.com.at.gadermaier.argon2.model.Block;
|
||||||
|
|
||||||
|
class FillBlock {
|
||||||
|
|
||||||
|
static void fillBlock(Block X, Block Y, Block currentBlock, boolean withXor) {
|
||||||
|
|
||||||
|
Block R = new Block();
|
||||||
|
Block Z = new Block();
|
||||||
|
|
||||||
|
R.xor(X, Y);
|
||||||
|
Z.copyBlock(R);
|
||||||
|
|
||||||
|
/* Apply Blake2 on columns of 64-bit words: (0,1,...,15) , then
|
||||||
|
(16,17,..31)... finally (112,113,...127) */
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
|
||||||
|
Functions.roundFunction(Z,
|
||||||
|
16 * i, 16 * i + 1, 16 * i + 2,
|
||||||
|
16 * i + 3, 16 * i + 4, 16 * i + 5,
|
||||||
|
16 * i + 6, 16 * i + 7, 16 * i + 8,
|
||||||
|
16 * i + 9, 16 * i + 10, 16 * i + 11,
|
||||||
|
16 * i + 12, 16 * i + 13, 16 * i + 14,
|
||||||
|
16 * i + 15
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Apply Blake2 on rows of 64-bit words: (0,1,16,17,...112,113), then
|
||||||
|
(2,3,18,19,...,114,115).. finally (14,15,30,31,...,126,127) */
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
|
||||||
|
Functions.roundFunction(Z,
|
||||||
|
2 * i, 2 * i + 1, 2 * i + 16,
|
||||||
|
2 * i + 17, 2 * i + 32, 2 * i + 33,
|
||||||
|
2 * i + 48, 2 * i + 49, 2 * i + 64,
|
||||||
|
2 * i + 65, 2 * i + 80, 2 * i + 81,
|
||||||
|
2 * i + 96, 2 * i + 97, 2 * i + 112,
|
||||||
|
2 * i + 113
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (withXor) {
|
||||||
|
currentBlock.xor(R, Z, currentBlock);
|
||||||
|
} else {
|
||||||
|
currentBlock.xor(R, Z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,80 @@
|
|||||||
|
/* This file is taken from
|
||||||
|
https://github.com/andreas1327250/argon2-java
|
||||||
|
|
||||||
|
Original Author: Andreas Gadermaier <up.gadermaier@gmail.com>
|
||||||
|
*/
|
||||||
|
package ext.plantuml.com.at.gadermaier.argon2.algorithm;
|
||||||
|
|
||||||
|
import static ext.plantuml.com.at.gadermaier.argon2.Constants.ARGON2_SYNC_POINTS;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
|
import ext.plantuml.com.at.gadermaier.argon2.model.Instance;
|
||||||
|
import ext.plantuml.com.at.gadermaier.argon2.model.Position;
|
||||||
|
|
||||||
|
public class FillMemory {
|
||||||
|
|
||||||
|
public static void fillMemoryBlocks(Instance instance) {
|
||||||
|
if (instance.getLanes() == 1) {
|
||||||
|
fillMemoryBlockSingleThreaded(instance);
|
||||||
|
} else {
|
||||||
|
fillMemoryBlockMultiThreaded(instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void fillMemoryBlockSingleThreaded(Instance instance) {
|
||||||
|
for (int i = 0; i < instance.getIterations(); i++) {
|
||||||
|
for (int j = 0; j < ARGON2_SYNC_POINTS; j++) {
|
||||||
|
Position position = new Position(i, 0, j, 0);
|
||||||
|
FillSegment.fillSegment(instance, position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void fillMemoryBlockMultiThreaded(final Instance instance) {
|
||||||
|
|
||||||
|
ExecutorService service = Executors.newFixedThreadPool(instance.getLanes());
|
||||||
|
List<Future<?>> futures = new ArrayList<Future<?>>();
|
||||||
|
|
||||||
|
for (int i = 0; i < instance.getIterations(); i++) {
|
||||||
|
for (int j = 0; j < ARGON2_SYNC_POINTS; j++) {
|
||||||
|
for (int k = 0; k < instance.getLanes(); k++) {
|
||||||
|
|
||||||
|
final Position position = new Position(i, k, j, 0);
|
||||||
|
|
||||||
|
Future future = service.submit(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
FillSegment.fillSegment(instance, position);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
futures.add(future);
|
||||||
|
}
|
||||||
|
|
||||||
|
joinThreads(instance, futures);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
service.shutdownNow();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void joinThreads(Instance instance, List<Future<?>> futures) {
|
||||||
|
try {
|
||||||
|
for (Future<?> f : futures) {
|
||||||
|
f.get();
|
||||||
|
}
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
instance.clear();
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} catch (ExecutionException e) {
|
||||||
|
instance.clear();
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,170 @@
|
|||||||
|
/* This file is taken from
|
||||||
|
https://github.com/andreas1327250/argon2-java
|
||||||
|
|
||||||
|
Original Author: Andreas Gadermaier <up.gadermaier@gmail.com>
|
||||||
|
*/
|
||||||
|
package ext.plantuml.com.at.gadermaier.argon2.algorithm;
|
||||||
|
|
||||||
|
import static ext.plantuml.com.at.gadermaier.argon2.Constants.ARGON2_ADDRESSES_IN_BLOCK;
|
||||||
|
import static ext.plantuml.com.at.gadermaier.argon2.Constants.ARGON2_VERSION_10;
|
||||||
|
|
||||||
|
import ext.plantuml.com.at.gadermaier.argon2.Constants;
|
||||||
|
import ext.plantuml.com.at.gadermaier.argon2.Util;
|
||||||
|
import ext.plantuml.com.at.gadermaier.argon2.model.Argon2Type;
|
||||||
|
import ext.plantuml.com.at.gadermaier.argon2.model.Block;
|
||||||
|
import ext.plantuml.com.at.gadermaier.argon2.model.Instance;
|
||||||
|
import ext.plantuml.com.at.gadermaier.argon2.model.Position;
|
||||||
|
|
||||||
|
|
||||||
|
class FillSegment {
|
||||||
|
|
||||||
|
static void fillSegment(Instance instance, Position position) {
|
||||||
|
|
||||||
|
Block addressBlock = null, inputBlock = null, zeroBlock = null;
|
||||||
|
|
||||||
|
boolean dataIndependentAddressing = isDataIndependentAddressing(instance, position);
|
||||||
|
int startingIndex = getStartingIndex(position);
|
||||||
|
int currentOffset = position.lane * instance.getLaneLength() + position.slice * instance.getSegmentLength() + startingIndex;
|
||||||
|
int prevOffset = getPrevOffset(instance, currentOffset);
|
||||||
|
|
||||||
|
if (dataIndependentAddressing) {
|
||||||
|
addressBlock = new Block();
|
||||||
|
zeroBlock = new Block();
|
||||||
|
inputBlock = new Block();
|
||||||
|
|
||||||
|
initAddressBlocks(instance, position, zeroBlock, inputBlock, addressBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (position.index = startingIndex; position.index < instance.getSegmentLength(); position.index++, currentOffset++, prevOffset++) {
|
||||||
|
prevOffset = rotatePrevOffset(instance, currentOffset, prevOffset);
|
||||||
|
|
||||||
|
long pseudoRandom = getPseudoRandom(instance, position, addressBlock, inputBlock, zeroBlock, prevOffset, dataIndependentAddressing);
|
||||||
|
int refLane = getRefLane(instance, position, pseudoRandom);
|
||||||
|
int refColumn = getRefColumn(instance, position, pseudoRandom, refLane == position.lane);
|
||||||
|
|
||||||
|
/* 2 Creating a new block */
|
||||||
|
Block prevBlock = instance.memory[prevOffset];
|
||||||
|
Block refBlock = instance.memory[((instance.getLaneLength()) * refLane + refColumn)];
|
||||||
|
Block currentBlock = instance.memory[currentOffset];
|
||||||
|
|
||||||
|
boolean withXor = isWithXor(instance, position);
|
||||||
|
FillBlock.fillBlock(prevBlock, refBlock, currentBlock, withXor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isDataIndependentAddressing(Instance instance, Position position) {
|
||||||
|
return (instance.getType() == Argon2Type.Argon2i) ||
|
||||||
|
(instance.getType() == Argon2Type.Argon2id
|
||||||
|
&& (position.pass == 0)
|
||||||
|
&& (position.slice < Constants.ARGON2_SYNC_POINTS / 2)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void initAddressBlocks(Instance instance, Position position, Block zeroBlock, Block inputBlock, Block addressBlock) {
|
||||||
|
inputBlock.v[0] = Util.intToLong(position.pass);
|
||||||
|
inputBlock.v[1] = Util.intToLong(position.lane);
|
||||||
|
inputBlock.v[2] = Util.intToLong(position.slice);
|
||||||
|
inputBlock.v[3] = Util.intToLong(instance.memory.length);
|
||||||
|
inputBlock.v[4] = Util.intToLong(instance.getIterations());
|
||||||
|
inputBlock.v[5] = Util.intToLong(instance.getType().ordinal());
|
||||||
|
|
||||||
|
if ((position.pass == 0) && (position.slice == 0)) {
|
||||||
|
/* Don't forget to generate the first block of addresses: */
|
||||||
|
nextAddresses(zeroBlock, inputBlock, addressBlock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isWithXor(Instance instance, Position position) {
|
||||||
|
return !(position.pass == 0 || instance.getVersion() == ARGON2_VERSION_10);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int getPrevOffset(Instance instance, int currentOffset) {
|
||||||
|
if (currentOffset % instance.getLaneLength() == 0) {
|
||||||
|
/* Last block in this lane */
|
||||||
|
return currentOffset + instance.getLaneLength() - 1;
|
||||||
|
} else {
|
||||||
|
/* Previous block */
|
||||||
|
return currentOffset - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int rotatePrevOffset(Instance instance, int currentOffset, int prevOffset) {
|
||||||
|
if (currentOffset % instance.getLaneLength() == 1) {
|
||||||
|
prevOffset = currentOffset - 1;
|
||||||
|
}
|
||||||
|
return prevOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int getStartingIndex(Position position) {
|
||||||
|
if ((position.pass == 0) && (position.slice == 0)) {
|
||||||
|
return 2; /* we have already generated the first two blocks */
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void nextAddresses(Block zeroBlock, Block inputBlock, Block addressBlock) {
|
||||||
|
inputBlock.v[6]++;
|
||||||
|
FillBlock.fillBlock(zeroBlock, inputBlock, addressBlock, false);
|
||||||
|
FillBlock.fillBlock(zeroBlock, addressBlock, addressBlock, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 1.2 Computing the index of the reference block */
|
||||||
|
/* 1.2.1 Taking pseudo-random value from the previous block */
|
||||||
|
private static long getPseudoRandom(Instance instance, Position position, Block addressBlock, Block inputBlock, Block zeroBlock, int prevOffset, boolean dataIndependentAddressing) {
|
||||||
|
if (dataIndependentAddressing) {
|
||||||
|
if (position.index % ARGON2_ADDRESSES_IN_BLOCK == 0) {
|
||||||
|
nextAddresses(zeroBlock, inputBlock, addressBlock);
|
||||||
|
}
|
||||||
|
return addressBlock.v[position.index % ARGON2_ADDRESSES_IN_BLOCK];
|
||||||
|
} else {
|
||||||
|
return instance.memory[prevOffset].v[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int getRefLane(Instance instance, Position position, long pseudoRandom) {
|
||||||
|
int refLane = (int) (((pseudoRandom >>> 32)) % instance.getLanes());
|
||||||
|
|
||||||
|
if ((position.pass == 0) && (position.slice == 0)) {
|
||||||
|
/* Can not reference other lanes yet */
|
||||||
|
refLane = position.lane;
|
||||||
|
}
|
||||||
|
return refLane;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int getRefColumn(Instance instance, Position position, long pseudoRandom,
|
||||||
|
boolean sameLane) {
|
||||||
|
|
||||||
|
int referenceAreaSize;
|
||||||
|
int startPosition;
|
||||||
|
|
||||||
|
if (position.pass == 0) {
|
||||||
|
startPosition = 0;
|
||||||
|
|
||||||
|
if (sameLane) {
|
||||||
|
/* The same lane => add current segment */
|
||||||
|
referenceAreaSize = position.slice * instance.getSegmentLength() + position.index - 1;
|
||||||
|
} else {
|
||||||
|
/* pass == 0 && !sameLane => position.slice > 0*/
|
||||||
|
referenceAreaSize = position.slice * instance.getSegmentLength() + ((position.index == 0) ? (-1) : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
startPosition = ((position.slice + 1) * instance.getSegmentLength()) % instance.getLaneLength();
|
||||||
|
|
||||||
|
if (sameLane) {
|
||||||
|
referenceAreaSize = instance.getLaneLength() - instance.getSegmentLength() + position.index - 1;
|
||||||
|
} else {
|
||||||
|
referenceAreaSize = instance.getLaneLength() - instance.getSegmentLength() + ((position.index == 0) ? (-1) : 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
long relativePosition = pseudoRandom & 0xFFFFFFFFL;
|
||||||
|
// long relativePosition = pseudoRandom << 32 >>> 32;
|
||||||
|
relativePosition = (relativePosition * relativePosition) >>> 32;
|
||||||
|
relativePosition = referenceAreaSize - 1 - (referenceAreaSize * relativePosition >>> 32);
|
||||||
|
|
||||||
|
return (int) (startPosition + relativePosition) % instance.getLaneLength();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
/* This file is taken from
|
||||||
|
https://github.com/andreas1327250/argon2-java
|
||||||
|
|
||||||
|
Original Author: Andreas Gadermaier <up.gadermaier@gmail.com>
|
||||||
|
*/
|
||||||
|
package ext.plantuml.com.at.gadermaier.argon2.algorithm;
|
||||||
|
|
||||||
|
import ext.plantuml.com.at.gadermaier.argon2.Argon2;
|
||||||
|
import ext.plantuml.com.at.gadermaier.argon2.model.Block;
|
||||||
|
import ext.plantuml.com.at.gadermaier.argon2.model.Instance;
|
||||||
|
|
||||||
|
public class Finalize {
|
||||||
|
|
||||||
|
public static void finalize(Instance instance, Argon2 argon2) {
|
||||||
|
|
||||||
|
Block finalBlock = instance.memory[instance.getLaneLength() - 1];
|
||||||
|
|
||||||
|
/* XOR the last blocks */
|
||||||
|
for (int i = 1; i < instance.getLanes(); i++) {
|
||||||
|
int lastBlockInLane = i * instance.getLaneLength() + (instance.getLaneLength() - 1);
|
||||||
|
finalBlock.xorWith(instance.memory[lastBlockInLane]);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] finalBlockBytes = finalBlock.toBytes();
|
||||||
|
byte[] finalResult = Functions.blake2bLong(finalBlockBytes, argon2.getOutputLength());
|
||||||
|
|
||||||
|
argon2.setOutput(finalResult);
|
||||||
|
|
||||||
|
if (argon2.isClearMemory()) {
|
||||||
|
instance.clear();
|
||||||
|
argon2.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,172 @@
|
|||||||
|
/* This file is taken from
|
||||||
|
https://github.com/andreas1327250/argon2-java
|
||||||
|
|
||||||
|
Original Author: Andreas Gadermaier <up.gadermaier@gmail.com>
|
||||||
|
*/
|
||||||
|
package ext.plantuml.com.at.gadermaier.argon2.algorithm;
|
||||||
|
|
||||||
|
import static ext.plantuml.com.at.gadermaier.argon2.Constants.ARGON2_BLOCK_SIZE;
|
||||||
|
import static ext.plantuml.com.at.gadermaier.argon2.Constants.ARGON2_PREHASH_DIGEST_LENGTH;
|
||||||
|
import static ext.plantuml.com.at.gadermaier.argon2.Constants.ARGON2_PREHASH_SEED_LENGTH;
|
||||||
|
|
||||||
|
import ext.plantuml.com.at.gadermaier.argon2.Util;
|
||||||
|
import ext.plantuml.com.at.gadermaier.argon2.blake2.Blake2b;
|
||||||
|
import ext.plantuml.com.at.gadermaier.argon2.model.Block;
|
||||||
|
|
||||||
|
class Functions {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* H0 = H64(p, τ, m, t, v, y, |P|, P, |S|, S, |L|, K, |X|, X)
|
||||||
|
* -> 64 byte (ARGON2_PREHASH_DIGEST_LENGTH)
|
||||||
|
*/
|
||||||
|
static byte[] initialHash(byte[] lanes, byte[] outputLength,
|
||||||
|
byte[] memory, byte[] iterations,
|
||||||
|
byte[] version, byte[] type,
|
||||||
|
byte[] passwordLength, byte[] password,
|
||||||
|
byte[] saltLength, byte[] salt,
|
||||||
|
byte[] secretLength, byte[] secret,
|
||||||
|
byte[] additionalLength, byte[] additional) {
|
||||||
|
|
||||||
|
|
||||||
|
Blake2b.Param params = new Blake2b.Param()
|
||||||
|
.setDigestLength(ARGON2_PREHASH_DIGEST_LENGTH);
|
||||||
|
|
||||||
|
final Blake2b blake2b = Blake2b.Digest.newInstance(params);
|
||||||
|
|
||||||
|
blake2b.update(lanes);
|
||||||
|
blake2b.update(outputLength);
|
||||||
|
blake2b.update(memory);
|
||||||
|
blake2b.update(iterations);
|
||||||
|
blake2b.update(version);
|
||||||
|
blake2b.update(type);
|
||||||
|
|
||||||
|
blake2b.update(passwordLength);
|
||||||
|
if (password != null) {
|
||||||
|
blake2b.update(password);
|
||||||
|
}
|
||||||
|
|
||||||
|
blake2b.update(saltLength);
|
||||||
|
if (salt != null) {
|
||||||
|
blake2b.update(salt);
|
||||||
|
}
|
||||||
|
|
||||||
|
blake2b.update(secretLength);
|
||||||
|
if (secret != null) {
|
||||||
|
blake2b.update(secret);
|
||||||
|
}
|
||||||
|
|
||||||
|
blake2b.update(additionalLength);
|
||||||
|
if (additional != null) {
|
||||||
|
blake2b.update(additional);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] blake2hash = blake2b.digest();
|
||||||
|
assert (blake2hash.length == 64);
|
||||||
|
|
||||||
|
return blake2hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* H' - blake2bLong - variable length hash function
|
||||||
|
*/
|
||||||
|
static byte[] blake2bLong(byte[] input, int outputLength) {
|
||||||
|
|
||||||
|
assert (input.length == ARGON2_PREHASH_SEED_LENGTH || input.length == ARGON2_BLOCK_SIZE);
|
||||||
|
|
||||||
|
byte[] result = new byte[outputLength];
|
||||||
|
byte[] outlenBytes = Util.intToLittleEndianBytes(outputLength);
|
||||||
|
|
||||||
|
int blake2bLength = 64;
|
||||||
|
|
||||||
|
if (outputLength <= blake2bLength) {
|
||||||
|
result = blake2b(input, outlenBytes, outputLength);
|
||||||
|
} else {
|
||||||
|
byte[] outBuffer;
|
||||||
|
|
||||||
|
/* V1 */
|
||||||
|
outBuffer = blake2b(input, outlenBytes, blake2bLength);
|
||||||
|
System.arraycopy(outBuffer, 0, result, 0, blake2bLength / 2);
|
||||||
|
|
||||||
|
int r = (outputLength / 32) + (outputLength % 32 == 0 ? 0 : 1) - 2;
|
||||||
|
|
||||||
|
int position = blake2bLength / 2;
|
||||||
|
for (int i = 2; i <= r; i++, position += blake2bLength / 2) {
|
||||||
|
/* V2 to Vr */
|
||||||
|
outBuffer = blake2b(outBuffer, null, blake2bLength);
|
||||||
|
System.arraycopy(outBuffer, 0, result, position, blake2bLength / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
int lastLength = outputLength - 32 * r;
|
||||||
|
|
||||||
|
/* Vr+1 */
|
||||||
|
outBuffer = blake2b(outBuffer, null, lastLength);
|
||||||
|
System.arraycopy(outBuffer, 0, result, position, lastLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert (result.length == outputLength);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] blake2b(byte[] input, byte[] outlenBytes, int outputLength) {
|
||||||
|
Blake2b.Param params = new Blake2b.Param()
|
||||||
|
.setDigestLength(outputLength);
|
||||||
|
|
||||||
|
final Blake2b blake2b = Blake2b.Digest.newInstance(params);
|
||||||
|
|
||||||
|
if (outlenBytes != null)
|
||||||
|
blake2b.update(outlenBytes);
|
||||||
|
|
||||||
|
blake2b.update(input);
|
||||||
|
|
||||||
|
return blake2b.digest();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void roundFunction(Block block,
|
||||||
|
int v0, int v1, int v2, int v3,
|
||||||
|
int v4, int v5, int v6, int v7,
|
||||||
|
int v8, int v9, int v10, int v11,
|
||||||
|
int v12, int v13, int v14, int v15) {
|
||||||
|
|
||||||
|
F(block, v0, v4, v8, v12);
|
||||||
|
F(block, v1, v5, v9, v13);
|
||||||
|
F(block, v2, v6, v10, v14);
|
||||||
|
F(block, v3, v7, v11, v15);
|
||||||
|
|
||||||
|
F(block, v0, v5, v10, v15);
|
||||||
|
F(block, v1, v6, v11, v12);
|
||||||
|
F(block, v2, v7, v8, v13);
|
||||||
|
F(block, v3, v4, v9, v14);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void F(Block block, int a, int b, int c, int d) {
|
||||||
|
fBlaMka(block, a, b);
|
||||||
|
rotr64(block, d, a, 32);
|
||||||
|
|
||||||
|
fBlaMka(block, c, d);
|
||||||
|
rotr64(block, b, c, 24);
|
||||||
|
|
||||||
|
fBlaMka(block, a, b);
|
||||||
|
rotr64(block, d, a, 16);
|
||||||
|
|
||||||
|
fBlaMka(block, c, d);
|
||||||
|
rotr64(block, b, c, 63);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*designed by the Lyra PHC team */
|
||||||
|
/* a <- a + b + 2*aL*bL
|
||||||
|
* + == addition modulo 2^64
|
||||||
|
* aL = least 32 bit */
|
||||||
|
private static void fBlaMka(Block block, int x, int y) {
|
||||||
|
final long m = 0xFFFFFFFFL;
|
||||||
|
final long xy = (block.v[x] & m) * (block.v[y] & m);
|
||||||
|
|
||||||
|
block.v[x] = block.v[x] + block.v[y] + 2 * xy;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void rotr64(Block block, int v, int w, long c) {
|
||||||
|
final long temp = block.v[v] ^ block.v[w];
|
||||||
|
block.v[v] = (temp >>> c) | (temp << (64 - c));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,75 @@
|
|||||||
|
/* This file is taken from
|
||||||
|
https://github.com/andreas1327250/argon2-java
|
||||||
|
|
||||||
|
Original Author: Andreas Gadermaier <up.gadermaier@gmail.com>
|
||||||
|
*/
|
||||||
|
package ext.plantuml.com.at.gadermaier.argon2.algorithm;
|
||||||
|
|
||||||
|
import static ext.plantuml.com.at.gadermaier.argon2.Constants.ARGON2_BLOCK_SIZE;
|
||||||
|
import static ext.plantuml.com.at.gadermaier.argon2.Constants.ARGON2_PREHASH_DIGEST_LENGTH;
|
||||||
|
import static ext.plantuml.com.at.gadermaier.argon2.Constants.ARGON2_PREHASH_SEED_LENGTH;
|
||||||
|
|
||||||
|
import ext.plantuml.com.at.gadermaier.argon2.Argon2;
|
||||||
|
import ext.plantuml.com.at.gadermaier.argon2.Util;
|
||||||
|
import ext.plantuml.com.at.gadermaier.argon2.model.Instance;
|
||||||
|
|
||||||
|
public class Initialize {
|
||||||
|
|
||||||
|
|
||||||
|
public static void initialize(Instance instance, Argon2 argon2) {
|
||||||
|
byte[] initialHash = Functions.initialHash(
|
||||||
|
Util.intToLittleEndianBytes(argon2.getLanes()),
|
||||||
|
Util.intToLittleEndianBytes(argon2.getOutputLength()),
|
||||||
|
Util.intToLittleEndianBytes(argon2.getMemory()),
|
||||||
|
Util.intToLittleEndianBytes(argon2.getIterations()),
|
||||||
|
Util.intToLittleEndianBytes(argon2.getVersion()),
|
||||||
|
Util.intToLittleEndianBytes(argon2.getType().ordinal()),
|
||||||
|
Util.intToLittleEndianBytes(argon2.getPasswordLength()),
|
||||||
|
argon2.getPassword(),
|
||||||
|
Util.intToLittleEndianBytes(argon2.getSaltLength()),
|
||||||
|
argon2.getSalt(),
|
||||||
|
Util.intToLittleEndianBytes(argon2.getSecretLength()),
|
||||||
|
argon2.getSecret(),
|
||||||
|
Util.intToLittleEndianBytes(argon2.getAdditionalLength()),
|
||||||
|
argon2.getAdditional()
|
||||||
|
);
|
||||||
|
fillFirstBlocks(instance, initialHash);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (H0 || 0 || i) 72 byte -> 1024 byte
|
||||||
|
* (H0 || 1 || i) 72 byte -> 1024 byte
|
||||||
|
*/
|
||||||
|
private static void fillFirstBlocks(Instance instance, byte[] initialHash) {
|
||||||
|
|
||||||
|
final byte[] zeroBytes = {0, 0, 0, 0};
|
||||||
|
final byte[] oneBytes = {1, 0, 0, 0};
|
||||||
|
|
||||||
|
byte[] initialHashWithZeros = getInitialHashLong(initialHash, zeroBytes);
|
||||||
|
byte[] initialHashWithOnes = getInitialHashLong(initialHash, oneBytes);
|
||||||
|
|
||||||
|
for (int i = 0; i < instance.getLanes(); i++) {
|
||||||
|
|
||||||
|
byte[] iBytes = Util.intToLittleEndianBytes(i);
|
||||||
|
|
||||||
|
System.arraycopy(iBytes, 0, initialHashWithZeros, ARGON2_PREHASH_DIGEST_LENGTH + 4, 4);
|
||||||
|
System.arraycopy(iBytes, 0, initialHashWithOnes, ARGON2_PREHASH_DIGEST_LENGTH + 4, 4);
|
||||||
|
|
||||||
|
byte[] blockhashBytes = Functions.blake2bLong(initialHashWithZeros, ARGON2_BLOCK_SIZE);
|
||||||
|
instance.memory[i * instance.getLaneLength() + 0].fromBytes(blockhashBytes);
|
||||||
|
|
||||||
|
blockhashBytes = Functions.blake2bLong(initialHashWithOnes, ARGON2_BLOCK_SIZE);
|
||||||
|
instance.memory[i * instance.getLaneLength() + 1].fromBytes(blockhashBytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] getInitialHashLong(byte[] initialHash, byte[] appendix) {
|
||||||
|
byte[] initialHashLong = new byte[ARGON2_PREHASH_SEED_LENGTH];
|
||||||
|
|
||||||
|
System.arraycopy(initialHash, 0, initialHashLong, 0, ARGON2_PREHASH_DIGEST_LENGTH);
|
||||||
|
System.arraycopy(appendix, 0, initialHashLong, ARGON2_PREHASH_DIGEST_LENGTH, 4);
|
||||||
|
|
||||||
|
return initialHashLong;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
1288
src/ext/plantuml/com/at/gadermaier/argon2/blake2/Blake2b.java
Normal file
1288
src/ext/plantuml/com/at/gadermaier/argon2/blake2/Blake2b.java
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,13 @@
|
|||||||
|
/* This file is taken from
|
||||||
|
https://github.com/andreas1327250/argon2-java
|
||||||
|
|
||||||
|
Original Author: Andreas Gadermaier <up.gadermaier@gmail.com>
|
||||||
|
*/
|
||||||
|
package ext.plantuml.com.at.gadermaier.argon2.exception;
|
||||||
|
|
||||||
|
/* dislike checked exceptions */
|
||||||
|
class Argon2Exception extends RuntimeException {
|
||||||
|
Argon2Exception(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
/* This file is taken from
|
||||||
|
https://github.com/andreas1327250/argon2-java
|
||||||
|
|
||||||
|
Original Author: Andreas Gadermaier <up.gadermaier@gmail.com>
|
||||||
|
*/
|
||||||
|
package ext.plantuml.com.at.gadermaier.argon2.exception;
|
||||||
|
|
||||||
|
public class Argon2InvalidParameterException extends Argon2Exception{
|
||||||
|
public Argon2InvalidParameterException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
/* This file is taken from
|
||||||
|
https://github.com/andreas1327250/argon2-java
|
||||||
|
|
||||||
|
Original Author: Andreas Gadermaier <up.gadermaier@gmail.com>
|
||||||
|
*/
|
||||||
|
package ext.plantuml.com.at.gadermaier.argon2.model;
|
||||||
|
|
||||||
|
public enum Argon2Type {
|
||||||
|
Argon2d, Argon2i, Argon2id;
|
||||||
|
}
|
81
src/ext/plantuml/com/at/gadermaier/argon2/model/Block.java
Normal file
81
src/ext/plantuml/com/at/gadermaier/argon2/model/Block.java
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
/* This file is taken from
|
||||||
|
https://github.com/andreas1327250/argon2-java
|
||||||
|
|
||||||
|
Original Author: Andreas Gadermaier <up.gadermaier@gmail.com>
|
||||||
|
*/
|
||||||
|
package ext.plantuml.com.at.gadermaier.argon2.model;
|
||||||
|
|
||||||
|
|
||||||
|
import static ext.plantuml.com.at.gadermaier.argon2.Constants.ARGON2_BLOCK_SIZE;
|
||||||
|
import static ext.plantuml.com.at.gadermaier.argon2.Constants.ARGON2_QWORDS_IN_BLOCK;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import ext.plantuml.com.at.gadermaier.argon2.Util;
|
||||||
|
|
||||||
|
public class Block {
|
||||||
|
|
||||||
|
/* 128 * 8 Byte QWords */
|
||||||
|
public long[] v;
|
||||||
|
|
||||||
|
public Block() {
|
||||||
|
v = new long[ARGON2_QWORDS_IN_BLOCK];
|
||||||
|
}
|
||||||
|
|
||||||
|
public void fromBytes(byte[] input) {
|
||||||
|
assert (input.length == ARGON2_BLOCK_SIZE);
|
||||||
|
|
||||||
|
for (int i = 0; i < v.length; i++) {
|
||||||
|
byte[] slice = Arrays.copyOfRange(input, i * 8, (i + 1) * 8);
|
||||||
|
v[i] = Util.littleEndianBytesToLong(slice);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] toBytes() {
|
||||||
|
byte[] result = new byte[ARGON2_BLOCK_SIZE];
|
||||||
|
|
||||||
|
for (int i = 0; i < v.length; i++) {
|
||||||
|
byte[] bytes = Util.longToLittleEndianBytes(v[i]);
|
||||||
|
System.arraycopy(bytes, 0, result, i * bytes.length, bytes.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void copyBlock(Block other) {
|
||||||
|
System.arraycopy(other.v, 0, v, 0, v.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void xor(Block b1, Block b2) {
|
||||||
|
for (int i = 0; i < v.length; i++) {
|
||||||
|
v[i] = b1.v[i] ^ b2.v[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void xor(Block b1, Block b2, Block b3) {
|
||||||
|
for (int i = 0; i < v.length; i++) {
|
||||||
|
v[i] = b1.v[i] ^ b2.v[i] ^ b3.v[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void xorWith(Block other) {
|
||||||
|
for (int i = 0; i < v.length; i++) {
|
||||||
|
v[i] = v[i] ^ other.v[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder result = new StringBuilder();
|
||||||
|
for (long value : v) {
|
||||||
|
result.append(Util.bytesToHexString(Util.longToLittleEndianBytes(value)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear() {
|
||||||
|
Arrays.fill(v, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,88 @@
|
|||||||
|
/* This file is taken from
|
||||||
|
https://github.com/andreas1327250/argon2-java
|
||||||
|
|
||||||
|
Original Author: Andreas Gadermaier <up.gadermaier@gmail.com>
|
||||||
|
*/
|
||||||
|
package ext.plantuml.com.at.gadermaier.argon2.model;
|
||||||
|
|
||||||
|
import static ext.plantuml.com.at.gadermaier.argon2.Constants.ARGON2_SYNC_POINTS;
|
||||||
|
|
||||||
|
import ext.plantuml.com.at.gadermaier.argon2.Argon2;
|
||||||
|
|
||||||
|
public class Instance {
|
||||||
|
|
||||||
|
public Block[] memory;
|
||||||
|
private int version;
|
||||||
|
private int iterations;
|
||||||
|
private int segmentLength;
|
||||||
|
private int laneLength;
|
||||||
|
private int lanes;
|
||||||
|
|
||||||
|
private Argon2Type type;
|
||||||
|
|
||||||
|
public Instance(Argon2 argon2) {
|
||||||
|
this.version = argon2.getVersion();
|
||||||
|
this.iterations = argon2.getIterations();
|
||||||
|
this.lanes = argon2.getLanes();
|
||||||
|
this.type = argon2.getType();
|
||||||
|
|
||||||
|
/* 2. Align memory size */
|
||||||
|
/* Minimum memoryBlocks = 8L blocks, where L is the number of lanes */
|
||||||
|
int memoryBlocks = argon2.getMemory();
|
||||||
|
|
||||||
|
if (memoryBlocks < 2 * ARGON2_SYNC_POINTS * argon2.getLanes()) {
|
||||||
|
memoryBlocks = 2 * ARGON2_SYNC_POINTS * argon2.getLanes();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.segmentLength = memoryBlocks / (argon2.getLanes() * ARGON2_SYNC_POINTS);
|
||||||
|
this.laneLength = segmentLength * ARGON2_SYNC_POINTS;
|
||||||
|
/* Ensure that all segments have equal length */
|
||||||
|
memoryBlocks = segmentLength * (argon2.getLanes() * ARGON2_SYNC_POINTS);
|
||||||
|
|
||||||
|
initMemory(memoryBlocks);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initMemory(int memoryBlocks) {
|
||||||
|
this.memory = new Block[memoryBlocks];
|
||||||
|
|
||||||
|
for (int i = 0; i < memory.length; i++) {
|
||||||
|
memory[i] = new Block();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
for (Block b : memory) {
|
||||||
|
b.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
memory = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Block[] getMemory() {
|
||||||
|
return memory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getVersion() {
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getIterations() {
|
||||||
|
return iterations;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSegmentLength() {
|
||||||
|
return segmentLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLaneLength() {
|
||||||
|
return laneLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLanes() {
|
||||||
|
return lanes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Argon2Type getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
/* This file is taken from
|
||||||
|
https://github.com/andreas1327250/argon2-java
|
||||||
|
|
||||||
|
Original Author: Andreas Gadermaier <up.gadermaier@gmail.com>
|
||||||
|
*/
|
||||||
|
package ext.plantuml.com.at.gadermaier.argon2.model;
|
||||||
|
|
||||||
|
public class Position {
|
||||||
|
|
||||||
|
public int pass;
|
||||||
|
public int lane;
|
||||||
|
public int slice;
|
||||||
|
public int index;
|
||||||
|
|
||||||
|
public Position(int pass, int lane, int slice, int index) {
|
||||||
|
this.pass = pass;
|
||||||
|
this.lane = lane;
|
||||||
|
this.slice = slice;
|
||||||
|
this.index = index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,104 +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.dedication;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.security.MessageDigest;
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
public class DecoderInputStream extends InputStream {
|
|
||||||
|
|
||||||
private final TurningBytes message;
|
|
||||||
private final TurningBytes sha;
|
|
||||||
private final Random rnd;
|
|
||||||
private final InputStream source;
|
|
||||||
|
|
||||||
public DecoderInputStream(InputStream source, String s) {
|
|
||||||
this.source = source;
|
|
||||||
try {
|
|
||||||
final byte[] text = s.getBytes("UTF-8");
|
|
||||||
final byte[] key = getSignatureSha512(text);
|
|
||||||
this.rnd = new Random(getSeed(key));
|
|
||||||
this.message = new TurningBytes(text);
|
|
||||||
this.sha = new TurningBytes(key);
|
|
||||||
} catch (UnsupportedEncodingException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
throw new UnsupportedOperationException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static byte[] getSignatureSha512(byte[] bytes) {
|
|
||||||
try {
|
|
||||||
final MessageDigest msgDigest = MessageDigest.getInstance("SHA-512");
|
|
||||||
msgDigest.update(bytes);
|
|
||||||
return msgDigest.digest();
|
|
||||||
} catch (NoSuchAlgorithmException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
throw new UnsupportedOperationException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private long getSeed(byte[] bytes) {
|
|
||||||
long result = 17;
|
|
||||||
for (byte b : bytes) {
|
|
||||||
result = result * 37 + b;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private byte getNextByte() {
|
|
||||||
return (byte) (rnd.nextInt() ^ message.nextByte() ^ sha.nextByte());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() throws IOException {
|
|
||||||
source.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int read() throws IOException {
|
|
||||||
int b = source.read();
|
|
||||||
if (b == -1) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
b = (b ^ getNextByte()) & 0xFF;
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -36,69 +36,16 @@
|
|||||||
package net.sourceforge.plantuml.dedication;
|
package net.sourceforge.plantuml.dedication;
|
||||||
|
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
|
||||||
import javax.imageio.stream.ImageInputStream;
|
public interface Dedication {
|
||||||
|
|
||||||
import net.sourceforge.plantuml.security.ImageIO;
|
|
||||||
|
|
||||||
public class Dedication {
|
|
||||||
|
|
||||||
private final String name;
|
|
||||||
public static final int SIZE = 512;
|
public static final int SIZE = 512;
|
||||||
|
|
||||||
public Dedication(String name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
static public final BigInteger E = new BigInteger("47");
|
static public final BigInteger E = new BigInteger("47");
|
||||||
static public final BigInteger N = new BigInteger(
|
static public final BigInteger N = new BigInteger(
|
||||||
"64194259632025692228025828504368542164501926620236990850309916606915924860847417702229807236946186163298479808527077315212362810246237044147835839820235668271044023359607622658694578433933680627840319408427732468918341837133798296090069295727323673222224923200718714534955390633175683720810506099934813509605263799234445827953809462431871169282281822048299576307847441008670575692934434087522877910989584374673170522742162366773143807761599862833698229067475807108264396251702152180676841544743258182370105404479387062985271422237607462447989728490398294623785717593446941673706569352249533885603771123718557406286501161336667835919957553680522213067630956498293529840163155604109185561515875171125161872265975088797712442352939352686113608345330266855433849127812528823634773975825170679786399199082599910532761710473383280738663105826045325480095451410448217715495894688594898541182351588505292424154550388343455540760277051977859647543838445735549451966254020972172982014944475678385523833120793348365125754234511467512831686599126674298367512469557219326026525667529348508876650236597163509336304607610284488623800062157659286940214435134423619711736992281071131245654755167288438258292694799131521268600284444731890784171372171309");
|
"64194259632025692228025828504368542164501926620236990850309916606915924860847417702229807236946186163298479808527077315212362810246237044147835839820235668271044023359607622658694578433933680627840319408427732468918341837133798296090069295727323673222224923200718714534955390633175683720810506099934813509605263799234445827953809462431871169282281822048299576307847441008670575692934434087522877910989584374673170522742162366773143807761599862833698229067475807108264396251702152180676841544743258182370105404479387062985271422237607462447989728490398294623785717593446941673706569352249533885603771123718557406286501161336667835919957553680522213067630956498293529840163155604109185561515875171125161872265975088797712442352939352686113608345330266855433849127812528823634773975825170679786399199082599910532761710473383280738663105826045325480095451410448217715495894688594898541182351588505292424154550388343455540760277051977859647543838445735549451966254020972172982014944475678385523833120793348365125754234511467512831686599126674298367512469557219326026525667529348508876650236597163509336304607610284488623800062157659286940214435134423619711736992281071131245654755167288438258292694799131521268600284444731890784171372171309");
|
||||||
|
|
||||||
public InputStream getInputStream(String keepLetter) throws IOException {
|
public BufferedImage getImage(String sentence);
|
||||||
final InputStream tmp = PSystemDedication.class.getResourceAsStream(name + ".png");
|
|
||||||
final InputStream step1 = new DecoderInputStream(tmp, keepLetter);
|
|
||||||
final QBlocks rsa = QBlocks.readFrom(step1, SIZE + 1);
|
|
||||||
final QBlocks decrypted = rsa.change(E, N);
|
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
|
||||||
decrypted.writeTo(baos, SIZE);
|
|
||||||
baos.close();
|
|
||||||
return new ByteArrayInputStream(baos.toByteArray());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static BufferedImage getBufferedImage(InputStream is) {
|
|
||||||
try {
|
|
||||||
final Class<?> clVP8Decoder = Class.forName("net.sourceforge.plantuml.webp.VP8Decoder");
|
|
||||||
final Object vp8Decoder = clVP8Decoder.newInstance();
|
|
||||||
// final VP8Decoder vp8Decoder = new VP8Decoder();
|
|
||||||
final Method decodeFrame = clVP8Decoder.getMethod("decodeFrame", ImageInputStream.class);
|
|
||||||
final ImageInputStream iis = ImageIO.createImageInputStream(is);
|
|
||||||
decodeFrame.invoke(vp8Decoder, iis);
|
|
||||||
// vp8Decoder.decodeFrame(iis);
|
|
||||||
iis.close();
|
|
||||||
final Object frame = clVP8Decoder.getMethod("getFrame").invoke(vp8Decoder);
|
|
||||||
return (BufferedImage) frame.getClass().getMethod("getBufferedImage").invoke(frame);
|
|
||||||
// final VP8Frame frame = vp8Decoder.getFrame();
|
|
||||||
// return frame.getBufferedImage();
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public BufferedImage getBufferedImage(String keepLetter) {
|
|
||||||
try {
|
|
||||||
final InputStream is = getInputStream(keepLetter);
|
|
||||||
return getBufferedImage(is);
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
119
src/net/sourceforge/plantuml/dedication/DedicationCrypted.java
Normal file
119
src/net/sourceforge/plantuml/dedication/DedicationCrypted.java
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
/* ========================================================================
|
||||||
|
* 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.dedication;
|
||||||
|
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
import net.sourceforge.plantuml.utils.MTRandom;
|
||||||
|
|
||||||
|
public class DedicationCrypted implements Dedication {
|
||||||
|
|
||||||
|
private final String argon2;
|
||||||
|
private final BigInteger pq;
|
||||||
|
private final byte crypted[];
|
||||||
|
private final int tinyHash;
|
||||||
|
private String solution;
|
||||||
|
|
||||||
|
private long next = 0L;
|
||||||
|
|
||||||
|
public DedicationCrypted(byte crypted[], int tinyHash, String argon2, BigInteger pq) {
|
||||||
|
this.crypted = crypted;
|
||||||
|
this.pq = pq;
|
||||||
|
this.argon2 = argon2;
|
||||||
|
this.tinyHash = tinyHash;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized BufferedImage getImage(final String sentence) {
|
||||||
|
if (sentence.length() < 40) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (solution == null || sentence.equals(this.solution) == false) {
|
||||||
|
if (System.currentTimeMillis() < next) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
final int tinyHash = Noise.shortHash(sentence.getBytes("UTF-8"), N.toByteArray());
|
||||||
|
if (this.tinyHash != tinyHash) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
this.next = System.currentTimeMillis() + 5000L;
|
||||||
|
}
|
||||||
|
|
||||||
|
final byte[] hash1 = Noise.computeArgon2bytes(sentence.getBytes("UTF-8"),
|
||||||
|
(pq.toString(35) + sentence).getBytes("UTF-8"));
|
||||||
|
final byte[] hash2 = Noise.computeArgon2bytes(sentence.getBytes("UTF-8"),
|
||||||
|
(pq.toString(36) + sentence).getBytes("UTF-8"));
|
||||||
|
|
||||||
|
final BlumBlumShub rndBBS = new BlumBlumShub(pq, hash1);
|
||||||
|
final MTRandom rndMT = new MTRandom(hash2);
|
||||||
|
|
||||||
|
byte[] current = crypted.clone();
|
||||||
|
Noise.shuffle(current, rndMT);
|
||||||
|
Noise.xor(current, rndBBS);
|
||||||
|
Noise.xor(current, sentence.getBytes("UTF-8"));
|
||||||
|
|
||||||
|
Noise.shuffle(current, rndMT);
|
||||||
|
|
||||||
|
final RBlocks init = RBlocks.readFrom(current, 513);
|
||||||
|
final RBlocks decoded = init.change(E, N);
|
||||||
|
|
||||||
|
current = decoded.toByteArray(512);
|
||||||
|
|
||||||
|
Noise.shuffle(current, rndMT);
|
||||||
|
Noise.xor(current, rndBBS);
|
||||||
|
|
||||||
|
final String argon = Noise.computeArgon2String(current, (pq.toString(34) + sentence).getBytes("UTF-8"));
|
||||||
|
|
||||||
|
if (this.argon2.equals(argon) == false) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Noise.shuffle(current, rndMT);
|
||||||
|
current = Noise.reverse(current, rndMT.nextInt());
|
||||||
|
|
||||||
|
final BufferedImage img = PSystemDedication.getBufferedImage(new ByteArrayInputStream(current));
|
||||||
|
this.solution = sentence;
|
||||||
|
return img;
|
||||||
|
} catch (Throwable t) {
|
||||||
|
t.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -35,38 +35,41 @@
|
|||||||
*/
|
*/
|
||||||
package net.sourceforge.plantuml.dedication;
|
package net.sourceforge.plantuml.dedication;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.InputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
|
|
||||||
import net.sourceforge.plantuml.utils.MTRandom;
|
public class DedicationSimple implements Dedication {
|
||||||
|
|
||||||
public class NoisyInputStream extends InputStream {
|
private final byte crypted[];
|
||||||
|
private final String sentence;
|
||||||
|
|
||||||
private final MTRandom rnd;
|
public DedicationSimple(byte crypted[], String sentence) {
|
||||||
private final InputStream source;
|
this.crypted = crypted;
|
||||||
|
this.sentence = sentence;
|
||||||
public NoisyInputStream(InputStream source, byte[] pass) {
|
|
||||||
this.source = source;
|
|
||||||
this.rnd = new MTRandom(pass);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte getNextByte() {
|
public synchronized BufferedImage getImage(String sentence) {
|
||||||
return (byte) rnd.nextInt();
|
if (same(this.sentence, sentence) == false) {
|
||||||
}
|
return null;
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() throws IOException {
|
|
||||||
source.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int read() throws IOException {
|
|
||||||
int b = source.read();
|
|
||||||
if (b == -1) {
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
b = (b ^ getNextByte()) & 0xFF;
|
|
||||||
return b;
|
try {
|
||||||
|
byte[] current = crypted.clone();
|
||||||
|
|
||||||
|
final RBlocks init = RBlocks.readFrom(current, 513);
|
||||||
|
final RBlocks decoded = init.change(E, N);
|
||||||
|
current = decoded.toByteArray(512);
|
||||||
|
return PSystemDedication.getBufferedImage(new ByteArrayInputStream(current));
|
||||||
|
} catch (Throwable t) {
|
||||||
|
t.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean same(String s1, String s2) {
|
||||||
|
s1 = s1.replaceAll("[^\\p{L}0-9]+", "");
|
||||||
|
s2 = s2.replaceAll("[^\\p{L}0-9]+", "");
|
||||||
|
return s1.equalsIgnoreCase(s2);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -35,79 +35,60 @@
|
|||||||
*/
|
*/
|
||||||
package net.sourceforge.plantuml.dedication;
|
package net.sourceforge.plantuml.dedication;
|
||||||
|
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.HashMap;
|
import java.math.BigInteger;
|
||||||
import java.util.Map;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import net.sourceforge.plantuml.SignatureUtils;
|
import net.sourceforge.plantuml.FileUtils;
|
||||||
|
|
||||||
public class Dedications {
|
public class Dedications {
|
||||||
|
|
||||||
private static final Map<String, Dedication> normal = new HashMap<String, Dedication>();
|
private static final List<Dedication> all = new ArrayList<Dedication>();
|
||||||
private static final Map<String, Dedication> crypted = new HashMap<String, Dedication>();
|
|
||||||
|
|
||||||
static {
|
static {
|
||||||
addNormal("Write your own dedication!", "dedication");
|
|
||||||
addNormal("linux_china", "linux_china");
|
try {
|
||||||
addNormal("ARKBAN", "arkban");
|
all.add(new DedicationSimple(load("dedication"), "Write your own dedication!"));
|
||||||
addNormal("Boundaries allow discipline to create true strength", "boundaries");
|
all.add(new DedicationSimple(load("linux_china"), "linux_china"));
|
||||||
addNormal("Thank you, Dr. Chet. I wouldn't be where I am without you", "dr_chet");
|
all.add(new DedicationSimple(load("arkban"), "arkban"));
|
||||||
addNormal("Ben and Jen 2020", "ben");
|
all.add(new DedicationSimple(load("boundaries"), "Boundaries allow discipline to create true strength"));
|
||||||
addCrypted("0", "pOhci6rKgPXw32AeYXhOpSY0suoauHq5VUSwFqHLHsLYgSO6WaJ7BW5vtHBAoU6ePbcW7d8Flx99MWjPSKQTDm00");
|
all.add(new DedicationSimple(load("dr_chet"), "Thank you, Dr. Chet. I wouldn't be where I am without you"));
|
||||||
addCrypted("1", "LTxN3hdnhSJ515qcA7IQ841axt4GXfUd3n2wgNirYCdLnyX2360Gv1OEOnJ1-gwFzRW5B3HAqLBkR6Ge0WW_Z000");
|
all.add(new DedicationSimple(load("ben"), "Ben and Jen 2020"));
|
||||||
addCrypted("2", "lZqLduj4j1yRqSfAvkhbqVpqK8diklatiFeenDUXSdna9bKYQTzdS264YfUBScUVDYCp2Vcq04updoN98RwxE000");
|
all.add(secret(5, "835ff5d643b58cd35a20db6480071d05751aa6a0e01da78662ceafd0161f3f5e", new BigInteger(
|
||||||
|
"1182423723677118831606503500858825217076578422970565964857326298418401529955036896808663335300684244453386039908536275400945824932191521017102701344437753036730900076162922741167523337650578479960119614237031234925702200473053235777")));
|
||||||
|
all.add(secret(3, "514816d583044efbd336882227deb822194ff63e3bdc3cf707a01f17770d5a6a", new BigInteger(
|
||||||
|
"538955952645999836068094511687012232127213955837942782605199622268460518023083462090291844640318324475656060087513198129259364840841077651829017347845508167869708224054456044836844382437974410757740941102771969965334031780041648873")));
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void addNormal(String sentence, String name) {
|
private static DedicationCrypted secret(int tiny, String sig, BigInteger pq) throws IOException {
|
||||||
normal.put(keepLetter(sentence), new Dedication(name));
|
return new DedicationCrypted(load(sig), tiny, sig, pq);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void addCrypted(String name, String contentKey) {
|
private static byte[] load(String name) throws IOException {
|
||||||
crypted.put(contentKey, new Dedication(name));
|
final InputStream tmp = PSystemDedication.class.getResourceAsStream(name + ".png");
|
||||||
|
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
FileUtils.copyInternal(tmp, baos, true);
|
||||||
|
return baos.toByteArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Dedications() {
|
private Dedications() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Dedication get(String line) {
|
public synchronized static BufferedImage get(String line) {
|
||||||
final String keepLetter = keepLetter(line);
|
for (Dedication dedication : all) {
|
||||||
final Dedication result = normal.get(keepLetter);
|
final BufferedImage image = dedication.getImage(line);
|
||||||
if (result != null) {
|
if (image != null) {
|
||||||
return result;
|
return image;
|
||||||
}
|
|
||||||
for (Map.Entry<String, Dedication> ent : crypted.entrySet()) {
|
|
||||||
final Dedication dedication = ent.getValue();
|
|
||||||
InputStream is = null;
|
|
||||||
try {
|
|
||||||
is = dedication.getInputStream(keepLetter);
|
|
||||||
final String signature = SignatureUtils.getSignatureSha512(is);
|
|
||||||
if (signature.equals(ent.getKey())) {
|
|
||||||
return dedication;
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} finally {
|
|
||||||
try {
|
|
||||||
if (is != null)
|
|
||||||
is.close();
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String keepLetter(String s) {
|
|
||||||
final StringBuilder sb = new StringBuilder();
|
|
||||||
for (int i = 0; i < s.length(); i++) {
|
|
||||||
final char c = s.charAt(i);
|
|
||||||
if (Character.isLetterOrDigit(c)) {
|
|
||||||
sb.append(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,80 @@
|
|||||||
*/
|
*/
|
||||||
package net.sourceforge.plantuml.dedication;
|
package net.sourceforge.plantuml.dedication;
|
||||||
|
|
||||||
|
import ext.plantuml.com.at.gadermaier.argon2.Argon2;
|
||||||
|
import ext.plantuml.com.at.gadermaier.argon2.Argon2Factory;
|
||||||
|
import ext.plantuml.com.at.gadermaier.argon2.model.Argon2Type;
|
||||||
|
import net.sourceforge.plantuml.utils.MTRandom;
|
||||||
|
|
||||||
public class Noise {
|
public class Noise {
|
||||||
|
|
||||||
|
private static Argon2 argon2(byte[] buffer, byte[] salt) {
|
||||||
|
final Argon2 argon = Argon2Factory.create() //
|
||||||
|
.setType(Argon2Type.Argon2id) //
|
||||||
|
.setMemory(8) //
|
||||||
|
.setSalt(salt.clone()) //
|
||||||
|
.setIterations(50) //
|
||||||
|
.setPassword(buffer.clone());
|
||||||
|
argon.hashNow();
|
||||||
|
return argon;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String computeArgon2String(byte[] buffer, byte[] salt) {
|
||||||
|
return argon2(buffer, salt).getOutputString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] computeArgon2bytes(byte[] buffer, byte[] salt) {
|
||||||
|
return argon2(buffer, salt).getOutput();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int shortHash(byte[] buffer, byte[] salt) {
|
||||||
|
final byte hash[] = argon2(buffer, salt).getOutput();
|
||||||
|
int result = 0;
|
||||||
|
for (byte b : hash) {
|
||||||
|
final int b1 = b & 0x0F;
|
||||||
|
final int b2 = (b & 0xF0) >> 4;
|
||||||
|
result ^= b1 ^ b2;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void shuffle(byte[] buffer, MTRandom rnd) {
|
||||||
|
for (int i = 0; i < buffer.length; i++) {
|
||||||
|
final int r1 = rnd.nextInt();
|
||||||
|
final int r2 = rnd.nextInt();
|
||||||
|
final int a = Math.abs(r1) % buffer.length;
|
||||||
|
final int b = Math.abs(r2) % buffer.length;
|
||||||
|
final byte tmp = buffer[a];
|
||||||
|
buffer[a] = buffer[b];
|
||||||
|
buffer[b] = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void xor(byte[] buffer, byte[] xor) {
|
||||||
|
for (int i = 0; i < buffer.length; i++) {
|
||||||
|
buffer[i] ^= xor[i % xor.length];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void xor(byte[] buffer, BlumBlumShub rnd) {
|
||||||
|
for (int i = 0; i < buffer.length; i++) {
|
||||||
|
final byte mask = (byte) (rnd.nextRnd(8) & 0xFF);
|
||||||
|
buffer[i] = (byte) (buffer[i] ^ mask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] reverse(byte[] buffer, int delta) {
|
||||||
|
delta = Math.abs(delta) % buffer.length;
|
||||||
|
final byte result[] = new byte[buffer.length];
|
||||||
|
for (int i = 0; i < buffer.length; i++)
|
||||||
|
result[i] = buffer[(buffer.length - 1 - i + delta) % buffer.length];
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -53,22 +53,20 @@ import net.sourceforge.plantuml.ugraphic.UImage;
|
|||||||
|
|
||||||
public class PSystemDedication extends PlainDiagram {
|
public class PSystemDedication extends PlainDiagram {
|
||||||
|
|
||||||
private final Dedication dedication;
|
private final BufferedImage img;
|
||||||
private final String keepLetter;
|
|
||||||
|
|
||||||
public PSystemDedication(Dedication dedication, String keepLetter) {
|
public PSystemDedication(BufferedImage img) {
|
||||||
this.dedication = dedication;
|
this.img = img;
|
||||||
this.keepLetter = keepLetter;
|
if (img == null) {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected UDrawable getRootDrawable(FileFormatOption fileFormatOption) {
|
protected UDrawable getRootDrawable(FileFormatOption fileFormatOption) {
|
||||||
return new UDrawable() {
|
return new UDrawable() {
|
||||||
public void drawU(UGraphic ug) {
|
public void drawU(UGraphic ug) {
|
||||||
final BufferedImage bufferedImage = dedication.getBufferedImage(keepLetter);
|
ug.draw(new UImage(new PixelImage(img, AffineTransformType.TYPE_BILINEAR)));
|
||||||
if (bufferedImage != null) {
|
|
||||||
ug.draw(new UImage(new PixelImage(bufferedImage, AffineTransformType.TYPE_BILINEAR)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,8 @@
|
|||||||
*/
|
*/
|
||||||
package net.sourceforge.plantuml.dedication;
|
package net.sourceforge.plantuml.dedication;
|
||||||
|
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
|
||||||
import net.sourceforge.plantuml.AbstractPSystem;
|
import net.sourceforge.plantuml.AbstractPSystem;
|
||||||
import net.sourceforge.plantuml.command.PSystemSingleLineFactory;
|
import net.sourceforge.plantuml.command.PSystemSingleLineFactory;
|
||||||
|
|
||||||
@ -42,9 +44,9 @@ public class PSystemDedicationFactory extends PSystemSingleLineFactory {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected AbstractPSystem executeLine(String line) {
|
protected AbstractPSystem executeLine(String line) {
|
||||||
final Dedication dedication = Dedications.get(line);
|
final BufferedImage dedication = Dedications.get(line);
|
||||||
if (dedication != null) {
|
if (dedication != null) {
|
||||||
return new PSystemDedication(dedication, Dedications.keepLetter(line));
|
return new PSystemDedication(dedication);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -271,25 +271,30 @@ public class GanttDiagram extends TitledDiagram implements ToTaskDraw, WithSprit
|
|||||||
|
|
||||||
private TimeHeader getTimeHeader() {
|
private TimeHeader getTimeHeader() {
|
||||||
if (openClose.getCalendar() == null) {
|
if (openClose.getCalendar() == null) {
|
||||||
return new TimeHeaderSimple(min, max);
|
return new TimeHeaderSimple(min, max, getClosedStyle(), getIHtmlColorSet());
|
||||||
} else if (printScale == PrintScale.WEEKLY) {
|
} else if (printScale == PrintScale.WEEKLY) {
|
||||||
return new TimeHeaderWeekly(getFactorScale(), openClose.getCalendar(), min, max, openClose, colorDays,
|
return new TimeHeaderWeekly(getFactorScale(), openClose.getCalendar(), min, max, openClose, colorDays,
|
||||||
colorDaysOfWeek, weekNumberStrategy);
|
colorDaysOfWeek, weekNumberStrategy, getClosedStyle(), getIHtmlColorSet());
|
||||||
} else if (printScale == PrintScale.MONTHLY) {
|
} else if (printScale == PrintScale.MONTHLY) {
|
||||||
return new TimeHeaderMonthly(getFactorScale(), openClose.getCalendar(), min, max, openClose, colorDays,
|
return new TimeHeaderMonthly(getFactorScale(), openClose.getCalendar(), min, max, openClose, colorDays,
|
||||||
colorDaysOfWeek);
|
colorDaysOfWeek, getClosedStyle(), getIHtmlColorSet());
|
||||||
} else if (printScale == PrintScale.QUARTERLY) {
|
} else if (printScale == PrintScale.QUARTERLY) {
|
||||||
return new TimeHeaderQuarterly(getFactorScale(), openClose.getCalendar(), min, max, openClose, colorDays,
|
return new TimeHeaderQuarterly(getFactorScale(), openClose.getCalendar(), min, max, openClose, colorDays,
|
||||||
colorDaysOfWeek);
|
colorDaysOfWeek, getClosedStyle(), getIHtmlColorSet());
|
||||||
} else if (printScale == PrintScale.YEARLY) {
|
} else if (printScale == PrintScale.YEARLY) {
|
||||||
return new TimeHeaderYearly(getFactorScale(), openClose.getCalendar(), min, max, openClose, colorDays,
|
return new TimeHeaderYearly(getFactorScale(), openClose.getCalendar(), min, max, openClose, colorDays,
|
||||||
colorDaysOfWeek);
|
colorDaysOfWeek, getClosedStyle(), getIHtmlColorSet());
|
||||||
} else {
|
} else {
|
||||||
return new TimeHeaderDaily(openClose.getCalendar(), min, max, openClose, colorDays, colorDaysOfWeek,
|
return new TimeHeaderDaily(openClose.getCalendar(), min, max, openClose, colorDays, colorDaysOfWeek,
|
||||||
nameDays, printStart, printEnd);
|
nameDays, printStart, printEnd, getClosedStyle(), getIHtmlColorSet());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Style getClosedStyle() {
|
||||||
|
return StyleSignature.of(SName.root, SName.element, SName.ganttDiagram, SName.closed)
|
||||||
|
.getMergedStyle(getCurrentStyleBuilder());
|
||||||
|
}
|
||||||
|
|
||||||
private double getTotalHeight(TimeHeader timeHeader) {
|
private double getTotalHeight(TimeHeader timeHeader) {
|
||||||
if (showFootbox) {
|
if (showFootbox) {
|
||||||
return totalHeightWithoutFooter + timeHeader.getTimeFooterHeight();
|
return totalHeightWithoutFooter + timeHeader.getTimeFooterHeight();
|
||||||
|
@ -42,6 +42,8 @@ import net.sourceforge.plantuml.graphic.HorizontalAlignment;
|
|||||||
import net.sourceforge.plantuml.graphic.TextBlock;
|
import net.sourceforge.plantuml.graphic.TextBlock;
|
||||||
import net.sourceforge.plantuml.project.time.Day;
|
import net.sourceforge.plantuml.project.time.Day;
|
||||||
import net.sourceforge.plantuml.project.timescale.TimeScale;
|
import net.sourceforge.plantuml.project.timescale.TimeScale;
|
||||||
|
import net.sourceforge.plantuml.style.PName;
|
||||||
|
import net.sourceforge.plantuml.style.Style;
|
||||||
import net.sourceforge.plantuml.ugraphic.UFont;
|
import net.sourceforge.plantuml.ugraphic.UFont;
|
||||||
import net.sourceforge.plantuml.ugraphic.UGraphic;
|
import net.sourceforge.plantuml.ugraphic.UGraphic;
|
||||||
import net.sourceforge.plantuml.ugraphic.ULine;
|
import net.sourceforge.plantuml.ugraphic.ULine;
|
||||||
@ -62,17 +64,30 @@ public abstract class TimeHeader {
|
|||||||
return 28;
|
return 28;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final HColor veryLightGray = HColorSet.instance().getColorOrWhite("#E0E8E8");
|
|
||||||
protected final HColor lightGray = HColorSet.instance().getColorOrWhite("#909898");
|
|
||||||
|
|
||||||
private final TimeScale timeScale;
|
private final TimeScale timeScale;
|
||||||
|
private final Style style;
|
||||||
|
private final HColorSet colorSet;
|
||||||
|
|
||||||
protected final Day min;
|
protected final Day min;
|
||||||
protected final Day max;
|
protected final Day max;
|
||||||
|
|
||||||
public TimeHeader(Day min, Day max, TimeScale timeScale) {
|
public TimeHeader(Day min, Day max, TimeScale timeScale, Style style, HColorSet colorSet) {
|
||||||
|
if (style == null) {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
this.timeScale = timeScale;
|
this.timeScale = timeScale;
|
||||||
this.min = min;
|
this.min = min;
|
||||||
this.max = max;
|
this.max = max;
|
||||||
|
this.style = style;
|
||||||
|
this.colorSet = colorSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final HColor closedBackgroundColor() {
|
||||||
|
return style.value(PName.BackGroundColor).asColor(colorSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final HColor closedFontColor() {
|
||||||
|
return style.value(PName.FontColor).asColor(colorSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract double getTimeHeaderHeight();
|
public abstract double getTimeHeaderHeight();
|
||||||
|
@ -41,8 +41,10 @@ import net.sourceforge.plantuml.project.LoadPlanable;
|
|||||||
import net.sourceforge.plantuml.project.time.Day;
|
import net.sourceforge.plantuml.project.time.Day;
|
||||||
import net.sourceforge.plantuml.project.time.DayOfWeek;
|
import net.sourceforge.plantuml.project.time.DayOfWeek;
|
||||||
import net.sourceforge.plantuml.project.timescale.TimeScale;
|
import net.sourceforge.plantuml.project.timescale.TimeScale;
|
||||||
|
import net.sourceforge.plantuml.style.Style;
|
||||||
import net.sourceforge.plantuml.ugraphic.UGraphic;
|
import net.sourceforge.plantuml.ugraphic.UGraphic;
|
||||||
import net.sourceforge.plantuml.ugraphic.color.HColor;
|
import net.sourceforge.plantuml.ugraphic.color.HColor;
|
||||||
|
import net.sourceforge.plantuml.ugraphic.color.HColorSet;
|
||||||
|
|
||||||
public abstract class TimeHeaderCalendar extends TimeHeader {
|
public abstract class TimeHeaderCalendar extends TimeHeader {
|
||||||
|
|
||||||
@ -51,8 +53,8 @@ public abstract class TimeHeaderCalendar extends TimeHeader {
|
|||||||
protected final Map<DayOfWeek, HColor> colorDaysOfWeek;
|
protected final Map<DayOfWeek, HColor> colorDaysOfWeek;
|
||||||
|
|
||||||
public TimeHeaderCalendar(Day calendar, Day min, Day max, LoadPlanable defaultPlan, Map<Day, HColor> colorDays,
|
public TimeHeaderCalendar(Day calendar, Day min, Day max, LoadPlanable defaultPlan, Map<Day, HColor> colorDays,
|
||||||
Map<DayOfWeek, HColor> colorDaysOfWeek, TimeScale timeScale) {
|
Map<DayOfWeek, HColor> colorDaysOfWeek, TimeScale timeScale, Style style, HColorSet colorSet) {
|
||||||
super(min, max, timeScale);
|
super(min, max, timeScale, style, colorSet);
|
||||||
this.defaultPlan = defaultPlan;
|
this.defaultPlan = defaultPlan;
|
||||||
this.colorDays = colorDays;
|
this.colorDays = colorDays;
|
||||||
this.colorDaysOfWeek = colorDaysOfWeek;
|
this.colorDaysOfWeek = colorDaysOfWeek;
|
||||||
@ -89,7 +91,7 @@ public abstract class TimeHeaderCalendar extends TimeHeader {
|
|||||||
back = backDoW;
|
back = backDoW;
|
||||||
}
|
}
|
||||||
if (back == null && defaultPlan.getLoadAt(wink) == 0) {
|
if (back == null && defaultPlan.getLoadAt(wink) == 0) {
|
||||||
back = veryLightGray;
|
back = closedBackgroundColor();
|
||||||
}
|
}
|
||||||
if (back == null) {
|
if (back == null) {
|
||||||
if (pending != null)
|
if (pending != null)
|
||||||
|
@ -43,10 +43,12 @@ import net.sourceforge.plantuml.project.time.Day;
|
|||||||
import net.sourceforge.plantuml.project.time.DayOfWeek;
|
import net.sourceforge.plantuml.project.time.DayOfWeek;
|
||||||
import net.sourceforge.plantuml.project.time.MonthYear;
|
import net.sourceforge.plantuml.project.time.MonthYear;
|
||||||
import net.sourceforge.plantuml.project.timescale.TimeScaleDaily;
|
import net.sourceforge.plantuml.project.timescale.TimeScaleDaily;
|
||||||
|
import net.sourceforge.plantuml.style.Style;
|
||||||
import net.sourceforge.plantuml.ugraphic.UGraphic;
|
import net.sourceforge.plantuml.ugraphic.UGraphic;
|
||||||
import net.sourceforge.plantuml.ugraphic.ULine;
|
import net.sourceforge.plantuml.ugraphic.ULine;
|
||||||
import net.sourceforge.plantuml.ugraphic.UTranslate;
|
import net.sourceforge.plantuml.ugraphic.UTranslate;
|
||||||
import net.sourceforge.plantuml.ugraphic.color.HColor;
|
import net.sourceforge.plantuml.ugraphic.color.HColor;
|
||||||
|
import net.sourceforge.plantuml.ugraphic.color.HColorSet;
|
||||||
import net.sourceforge.plantuml.ugraphic.color.HColorUtils;
|
import net.sourceforge.plantuml.ugraphic.color.HColorUtils;
|
||||||
|
|
||||||
public class TimeHeaderDaily extends TimeHeaderCalendar {
|
public class TimeHeaderDaily extends TimeHeaderCalendar {
|
||||||
@ -63,8 +65,10 @@ public class TimeHeaderDaily extends TimeHeaderCalendar {
|
|||||||
private final Map<Day, String> nameDays;
|
private final Map<Day, String> nameDays;
|
||||||
|
|
||||||
public TimeHeaderDaily(Day calendar, Day min, Day max, LoadPlanable defaultPlan, Map<Day, HColor> colorDays,
|
public TimeHeaderDaily(Day calendar, Day min, Day max, LoadPlanable defaultPlan, Map<Day, HColor> colorDays,
|
||||||
Map<DayOfWeek, HColor> colorDaysOfWeek, Map<Day, String> nameDays, Day printStart, Day printEnd) {
|
Map<DayOfWeek, HColor> colorDaysOfWeek, Map<Day, String> nameDays, Day printStart, Day printEnd,
|
||||||
super(calendar, min, max, defaultPlan, colorDays, colorDaysOfWeek, new TimeScaleDaily(calendar, printStart));
|
Style style, HColorSet colorSet) {
|
||||||
|
super(calendar, min, max, defaultPlan, colorDays, colorDaysOfWeek, new TimeScaleDaily(calendar, printStart),
|
||||||
|
style, colorSet);
|
||||||
this.nameDays = nameDays;
|
this.nameDays = nameDays;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,7 +115,7 @@ public class TimeHeaderDaily extends TimeHeaderCalendar {
|
|||||||
|
|
||||||
private HColor getTextBackColor(Day wink) {
|
private HColor getTextBackColor(Day wink) {
|
||||||
if (defaultPlan.getLoadAt(wink) <= 0) {
|
if (defaultPlan.getLoadAt(wink) <= 0) {
|
||||||
return lightGray;
|
return closedFontColor();
|
||||||
}
|
}
|
||||||
return HColorUtils.BLACK;
|
return HColorUtils.BLACK;
|
||||||
}
|
}
|
||||||
|
@ -43,10 +43,12 @@ import net.sourceforge.plantuml.project.time.Day;
|
|||||||
import net.sourceforge.plantuml.project.time.DayOfWeek;
|
import net.sourceforge.plantuml.project.time.DayOfWeek;
|
||||||
import net.sourceforge.plantuml.project.time.MonthYear;
|
import net.sourceforge.plantuml.project.time.MonthYear;
|
||||||
import net.sourceforge.plantuml.project.timescale.TimeScaleCompressed;
|
import net.sourceforge.plantuml.project.timescale.TimeScaleCompressed;
|
||||||
|
import net.sourceforge.plantuml.style.Style;
|
||||||
import net.sourceforge.plantuml.ugraphic.UGraphic;
|
import net.sourceforge.plantuml.ugraphic.UGraphic;
|
||||||
import net.sourceforge.plantuml.ugraphic.ULine;
|
import net.sourceforge.plantuml.ugraphic.ULine;
|
||||||
import net.sourceforge.plantuml.ugraphic.UTranslate;
|
import net.sourceforge.plantuml.ugraphic.UTranslate;
|
||||||
import net.sourceforge.plantuml.ugraphic.color.HColor;
|
import net.sourceforge.plantuml.ugraphic.color.HColor;
|
||||||
|
import net.sourceforge.plantuml.ugraphic.color.HColorSet;
|
||||||
import net.sourceforge.plantuml.ugraphic.color.HColorUtils;
|
import net.sourceforge.plantuml.ugraphic.color.HColorUtils;
|
||||||
|
|
||||||
public class TimeHeaderMonthly extends TimeHeaderCalendar {
|
public class TimeHeaderMonthly extends TimeHeaderCalendar {
|
||||||
@ -60,9 +62,9 @@ public class TimeHeaderMonthly extends TimeHeaderCalendar {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public TimeHeaderMonthly(double scale, Day calendar, Day min, Day max, LoadPlanable defaultPlan, Map<Day, HColor> colorDays,
|
public TimeHeaderMonthly(double scale, Day calendar, Day min, Day max, LoadPlanable defaultPlan, Map<Day, HColor> colorDays,
|
||||||
Map<DayOfWeek, HColor> colorDaysOfWeek) {
|
Map<DayOfWeek, HColor> colorDaysOfWeek, Style style, HColorSet colorSet) {
|
||||||
super(calendar, min, max, defaultPlan, colorDays, colorDaysOfWeek,
|
super(calendar, min, max, defaultPlan, colorDays, colorDaysOfWeek,
|
||||||
new TimeScaleCompressed(calendar, scale));
|
new TimeScaleCompressed(calendar, scale), style, colorSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -43,10 +43,12 @@ import net.sourceforge.plantuml.project.time.Day;
|
|||||||
import net.sourceforge.plantuml.project.time.DayOfWeek;
|
import net.sourceforge.plantuml.project.time.DayOfWeek;
|
||||||
import net.sourceforge.plantuml.project.time.MonthYear;
|
import net.sourceforge.plantuml.project.time.MonthYear;
|
||||||
import net.sourceforge.plantuml.project.timescale.TimeScaleCompressed;
|
import net.sourceforge.plantuml.project.timescale.TimeScaleCompressed;
|
||||||
|
import net.sourceforge.plantuml.style.Style;
|
||||||
import net.sourceforge.plantuml.ugraphic.UGraphic;
|
import net.sourceforge.plantuml.ugraphic.UGraphic;
|
||||||
import net.sourceforge.plantuml.ugraphic.ULine;
|
import net.sourceforge.plantuml.ugraphic.ULine;
|
||||||
import net.sourceforge.plantuml.ugraphic.UTranslate;
|
import net.sourceforge.plantuml.ugraphic.UTranslate;
|
||||||
import net.sourceforge.plantuml.ugraphic.color.HColor;
|
import net.sourceforge.plantuml.ugraphic.color.HColor;
|
||||||
|
import net.sourceforge.plantuml.ugraphic.color.HColorSet;
|
||||||
import net.sourceforge.plantuml.ugraphic.color.HColorUtils;
|
import net.sourceforge.plantuml.ugraphic.color.HColorUtils;
|
||||||
|
|
||||||
public class TimeHeaderQuarterly extends TimeHeaderCalendar {
|
public class TimeHeaderQuarterly extends TimeHeaderCalendar {
|
||||||
@ -59,10 +61,10 @@ public class TimeHeaderQuarterly extends TimeHeaderCalendar {
|
|||||||
return 16 + 13 - 1;
|
return 16 + 13 - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TimeHeaderQuarterly(double scale, Day calendar, Day min, Day max, LoadPlanable defaultPlan, Map<Day, HColor> colorDays,
|
public TimeHeaderQuarterly(double scale, Day calendar, Day min, Day max, LoadPlanable defaultPlan,
|
||||||
Map<DayOfWeek, HColor> colorDaysOfWeek) {
|
Map<Day, HColor> colorDays, Map<DayOfWeek, HColor> colorDaysOfWeek, Style style, HColorSet colorSet) {
|
||||||
super(calendar, min, max, defaultPlan, colorDays, colorDaysOfWeek,
|
super(calendar, min, max, defaultPlan, colorDays, colorDaysOfWeek, new TimeScaleCompressed(calendar, scale),
|
||||||
new TimeScaleCompressed(calendar, scale));
|
style, colorSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -126,9 +128,9 @@ public class TimeHeaderQuarterly extends TimeHeaderCalendar {
|
|||||||
}
|
}
|
||||||
drawVbar(ug, getTimeScale().getEndingPosition(max), 0, 12);
|
drawVbar(ug, getTimeScale().getEndingPosition(max), 0, 12);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String quarter(Day day) {
|
private String quarter(Day day) {
|
||||||
return "Q" + (( day.month().ordinal() + 3 ) / 3);
|
return "Q" + ((day.month().ordinal() + 3) / 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void printYear(UGraphic ug, MonthYear monthYear, double start, double end) {
|
private void printYear(UGraphic ug, MonthYear monthYear, double start, double end) {
|
||||||
|
@ -42,9 +42,11 @@ import net.sourceforge.plantuml.graphic.TextBlock;
|
|||||||
import net.sourceforge.plantuml.project.time.Day;
|
import net.sourceforge.plantuml.project.time.Day;
|
||||||
import net.sourceforge.plantuml.project.timescale.TimeScale;
|
import net.sourceforge.plantuml.project.timescale.TimeScale;
|
||||||
import net.sourceforge.plantuml.project.timescale.TimeScaleWink;
|
import net.sourceforge.plantuml.project.timescale.TimeScaleWink;
|
||||||
|
import net.sourceforge.plantuml.style.Style;
|
||||||
import net.sourceforge.plantuml.ugraphic.UGraphic;
|
import net.sourceforge.plantuml.ugraphic.UGraphic;
|
||||||
import net.sourceforge.plantuml.ugraphic.ULine;
|
import net.sourceforge.plantuml.ugraphic.ULine;
|
||||||
import net.sourceforge.plantuml.ugraphic.UTranslate;
|
import net.sourceforge.plantuml.ugraphic.UTranslate;
|
||||||
|
import net.sourceforge.plantuml.ugraphic.color.HColorSet;
|
||||||
import net.sourceforge.plantuml.ugraphic.color.HColorUtils;
|
import net.sourceforge.plantuml.ugraphic.color.HColorUtils;
|
||||||
|
|
||||||
public class TimeHeaderSimple extends TimeHeader {
|
public class TimeHeaderSimple extends TimeHeader {
|
||||||
@ -66,8 +68,8 @@ public class TimeHeaderSimple extends TimeHeader {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TimeHeaderSimple(Day min, Day max) {
|
public TimeHeaderSimple(Day min, Day max, Style style, HColorSet colorSet) {
|
||||||
super(min, max, new TimeScaleWink());
|
super(min, max, new TimeScaleWink(), style, colorSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void drawSmallVlinesDay(UGraphic ug, TimeScale timeScale, double totalHeightWithoutFooter) {
|
private void drawSmallVlinesDay(UGraphic ug, TimeScale timeScale, double totalHeightWithoutFooter) {
|
||||||
|
@ -44,10 +44,12 @@ import net.sourceforge.plantuml.project.time.DayOfWeek;
|
|||||||
import net.sourceforge.plantuml.project.time.MonthYear;
|
import net.sourceforge.plantuml.project.time.MonthYear;
|
||||||
import net.sourceforge.plantuml.project.time.WeekNumberStrategy;
|
import net.sourceforge.plantuml.project.time.WeekNumberStrategy;
|
||||||
import net.sourceforge.plantuml.project.timescale.TimeScaleCompressed;
|
import net.sourceforge.plantuml.project.timescale.TimeScaleCompressed;
|
||||||
|
import net.sourceforge.plantuml.style.Style;
|
||||||
import net.sourceforge.plantuml.ugraphic.UGraphic;
|
import net.sourceforge.plantuml.ugraphic.UGraphic;
|
||||||
import net.sourceforge.plantuml.ugraphic.ULine;
|
import net.sourceforge.plantuml.ugraphic.ULine;
|
||||||
import net.sourceforge.plantuml.ugraphic.UTranslate;
|
import net.sourceforge.plantuml.ugraphic.UTranslate;
|
||||||
import net.sourceforge.plantuml.ugraphic.color.HColor;
|
import net.sourceforge.plantuml.ugraphic.color.HColor;
|
||||||
|
import net.sourceforge.plantuml.ugraphic.color.HColorSet;
|
||||||
import net.sourceforge.plantuml.ugraphic.color.HColorUtils;
|
import net.sourceforge.plantuml.ugraphic.color.HColorUtils;
|
||||||
|
|
||||||
public class TimeHeaderWeekly extends TimeHeaderCalendar {
|
public class TimeHeaderWeekly extends TimeHeaderCalendar {
|
||||||
@ -63,8 +65,10 @@ public class TimeHeaderWeekly extends TimeHeaderCalendar {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public TimeHeaderWeekly(double scale, Day calendar, Day min, Day max, LoadPlanable defaultPlan,
|
public TimeHeaderWeekly(double scale, Day calendar, Day min, Day max, LoadPlanable defaultPlan,
|
||||||
Map<Day, HColor> colorDays, Map<DayOfWeek, HColor> colorDaysOfWeek, WeekNumberStrategy weekNumberStrategy) {
|
Map<Day, HColor> colorDays, Map<DayOfWeek, HColor> colorDaysOfWeek, WeekNumberStrategy weekNumberStrategy,
|
||||||
super(calendar, min, max, defaultPlan, colorDays, colorDaysOfWeek, new TimeScaleCompressed(calendar, scale));
|
Style style, HColorSet colorSet) {
|
||||||
|
super(calendar, min, max, defaultPlan, colorDays, colorDaysOfWeek, new TimeScaleCompressed(calendar, scale),
|
||||||
|
style, colorSet);
|
||||||
this.weekNumberStrategy = weekNumberStrategy;
|
this.weekNumberStrategy = weekNumberStrategy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,10 +43,12 @@ import net.sourceforge.plantuml.project.time.Day;
|
|||||||
import net.sourceforge.plantuml.project.time.DayOfWeek;
|
import net.sourceforge.plantuml.project.time.DayOfWeek;
|
||||||
import net.sourceforge.plantuml.project.time.MonthYear;
|
import net.sourceforge.plantuml.project.time.MonthYear;
|
||||||
import net.sourceforge.plantuml.project.timescale.TimeScaleCompressed;
|
import net.sourceforge.plantuml.project.timescale.TimeScaleCompressed;
|
||||||
|
import net.sourceforge.plantuml.style.Style;
|
||||||
import net.sourceforge.plantuml.ugraphic.UGraphic;
|
import net.sourceforge.plantuml.ugraphic.UGraphic;
|
||||||
import net.sourceforge.plantuml.ugraphic.ULine;
|
import net.sourceforge.plantuml.ugraphic.ULine;
|
||||||
import net.sourceforge.plantuml.ugraphic.UTranslate;
|
import net.sourceforge.plantuml.ugraphic.UTranslate;
|
||||||
import net.sourceforge.plantuml.ugraphic.color.HColor;
|
import net.sourceforge.plantuml.ugraphic.color.HColor;
|
||||||
|
import net.sourceforge.plantuml.ugraphic.color.HColorSet;
|
||||||
import net.sourceforge.plantuml.ugraphic.color.HColorUtils;
|
import net.sourceforge.plantuml.ugraphic.color.HColorUtils;
|
||||||
|
|
||||||
public class TimeHeaderYearly extends TimeHeaderCalendar {
|
public class TimeHeaderYearly extends TimeHeaderCalendar {
|
||||||
@ -60,8 +62,9 @@ public class TimeHeaderYearly extends TimeHeaderCalendar {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public TimeHeaderYearly(double scale, Day calendar, Day min, Day max, LoadPlanable defaultPlan,
|
public TimeHeaderYearly(double scale, Day calendar, Day min, Day max, LoadPlanable defaultPlan,
|
||||||
Map<Day, HColor> colorDays, Map<DayOfWeek, HColor> colorDaysOfWeek) {
|
Map<Day, HColor> colorDays, Map<DayOfWeek, HColor> colorDaysOfWeek, Style style, HColorSet colorSet) {
|
||||||
super(calendar, min, max, defaultPlan, colorDays, colorDaysOfWeek, new TimeScaleCompressed(calendar, scale));
|
super(calendar, min, max, defaultPlan, colorDays, colorDaysOfWeek, new TimeScaleCompressed(calendar, scale),
|
||||||
|
style, colorSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -54,6 +54,7 @@ public enum SName {
|
|||||||
class_, //
|
class_, //
|
||||||
clickable, //
|
clickable, //
|
||||||
cloud, //
|
cloud, //
|
||||||
|
closed, //
|
||||||
collection, //
|
collection, //
|
||||||
collections, //
|
collections, //
|
||||||
component, //
|
component, //
|
||||||
|
@ -53,8 +53,8 @@ import net.sourceforge.plantuml.graphic.StringBounder;
|
|||||||
import net.sourceforge.plantuml.graphic.TextBlock;
|
import net.sourceforge.plantuml.graphic.TextBlock;
|
||||||
import net.sourceforge.plantuml.svek.AbstractEntityImage;
|
import net.sourceforge.plantuml.svek.AbstractEntityImage;
|
||||||
import net.sourceforge.plantuml.svek.Bibliotekon;
|
import net.sourceforge.plantuml.svek.Bibliotekon;
|
||||||
import net.sourceforge.plantuml.svek.SvekLine;
|
|
||||||
import net.sourceforge.plantuml.svek.ShapeType;
|
import net.sourceforge.plantuml.svek.ShapeType;
|
||||||
|
import net.sourceforge.plantuml.svek.SvekLine;
|
||||||
import net.sourceforge.plantuml.ugraphic.UEllipse;
|
import net.sourceforge.plantuml.ugraphic.UEllipse;
|
||||||
import net.sourceforge.plantuml.ugraphic.UGraphic;
|
import net.sourceforge.plantuml.ugraphic.UGraphic;
|
||||||
import net.sourceforge.plantuml.ugraphic.UStroke;
|
import net.sourceforge.plantuml.ugraphic.UStroke;
|
||||||
|
@ -71,8 +71,8 @@ import net.sourceforge.plantuml.style.SName;
|
|||||||
import net.sourceforge.plantuml.style.Style;
|
import net.sourceforge.plantuml.style.Style;
|
||||||
import net.sourceforge.plantuml.style.StyleSignature;
|
import net.sourceforge.plantuml.style.StyleSignature;
|
||||||
import net.sourceforge.plantuml.svek.AbstractEntityImage;
|
import net.sourceforge.plantuml.svek.AbstractEntityImage;
|
||||||
import net.sourceforge.plantuml.svek.SvekLine;
|
|
||||||
import net.sourceforge.plantuml.svek.ShapeType;
|
import net.sourceforge.plantuml.svek.ShapeType;
|
||||||
|
import net.sourceforge.plantuml.svek.SvekLine;
|
||||||
import net.sourceforge.plantuml.svek.SvekNode;
|
import net.sourceforge.plantuml.svek.SvekNode;
|
||||||
import net.sourceforge.plantuml.ugraphic.UGraphic;
|
import net.sourceforge.plantuml.ugraphic.UGraphic;
|
||||||
import net.sourceforge.plantuml.ugraphic.UGraphicStencil;
|
import net.sourceforge.plantuml.ugraphic.UGraphicStencil;
|
||||||
|
@ -37,13 +37,9 @@ package net.sourceforge.plantuml.svek.image;
|
|||||||
|
|
||||||
import java.awt.geom.Dimension2D;
|
import java.awt.geom.Dimension2D;
|
||||||
|
|
||||||
import net.sourceforge.plantuml.ColorParam;
|
|
||||||
import net.sourceforge.plantuml.Dimension2DDouble;
|
import net.sourceforge.plantuml.Dimension2DDouble;
|
||||||
import net.sourceforge.plantuml.FontParam;
|
import net.sourceforge.plantuml.FontParam;
|
||||||
import net.sourceforge.plantuml.ISkinParam;
|
import net.sourceforge.plantuml.ISkinParam;
|
||||||
import net.sourceforge.plantuml.LineConfigurable;
|
|
||||||
import net.sourceforge.plantuml.SkinParamUtils;
|
|
||||||
import net.sourceforge.plantuml.Url;
|
|
||||||
import net.sourceforge.plantuml.creole.CreoleMode;
|
import net.sourceforge.plantuml.creole.CreoleMode;
|
||||||
import net.sourceforge.plantuml.cucadiagram.Display;
|
import net.sourceforge.plantuml.cucadiagram.Display;
|
||||||
import net.sourceforge.plantuml.cucadiagram.IEntity;
|
import net.sourceforge.plantuml.cucadiagram.IEntity;
|
||||||
@ -52,24 +48,16 @@ import net.sourceforge.plantuml.graphic.FontConfiguration;
|
|||||||
import net.sourceforge.plantuml.graphic.HorizontalAlignment;
|
import net.sourceforge.plantuml.graphic.HorizontalAlignment;
|
||||||
import net.sourceforge.plantuml.graphic.StringBounder;
|
import net.sourceforge.plantuml.graphic.StringBounder;
|
||||||
import net.sourceforge.plantuml.graphic.TextBlock;
|
import net.sourceforge.plantuml.graphic.TextBlock;
|
||||||
import net.sourceforge.plantuml.graphic.color.ColorType;
|
|
||||||
import net.sourceforge.plantuml.svek.AbstractEntityImage;
|
|
||||||
import net.sourceforge.plantuml.svek.ShapeType;
|
|
||||||
import net.sourceforge.plantuml.ugraphic.Shadowable;
|
|
||||||
import net.sourceforge.plantuml.ugraphic.UEllipse;
|
import net.sourceforge.plantuml.ugraphic.UEllipse;
|
||||||
import net.sourceforge.plantuml.ugraphic.UGraphic;
|
import net.sourceforge.plantuml.ugraphic.UGraphic;
|
||||||
import net.sourceforge.plantuml.ugraphic.UGroupType;
|
import net.sourceforge.plantuml.ugraphic.UGroupType;
|
||||||
import net.sourceforge.plantuml.ugraphic.ULine;
|
import net.sourceforge.plantuml.ugraphic.ULine;
|
||||||
import net.sourceforge.plantuml.ugraphic.URectangle;
|
|
||||||
import net.sourceforge.plantuml.ugraphic.UStroke;
|
import net.sourceforge.plantuml.ugraphic.UStroke;
|
||||||
import net.sourceforge.plantuml.ugraphic.UTranslate;
|
import net.sourceforge.plantuml.ugraphic.UTranslate;
|
||||||
import net.sourceforge.plantuml.ugraphic.color.HColor;
|
|
||||||
|
|
||||||
public class EntityImageState extends AbstractEntityImage {
|
public class EntityImageState extends EntityImageStateCommon {
|
||||||
|
|
||||||
final private TextBlock desc;
|
|
||||||
final private TextBlock fields;
|
final private TextBlock fields;
|
||||||
final private Url url;
|
|
||||||
|
|
||||||
final private static int MIN_WIDTH = 50;
|
final private static int MIN_WIDTH = 50;
|
||||||
final private static int MIN_HEIGHT = 50;
|
final private static int MIN_HEIGHT = 50;
|
||||||
@ -81,25 +69,13 @@ public class EntityImageState extends AbstractEntityImage {
|
|||||||
final static private double smallMarginX = 7;
|
final static private double smallMarginX = 7;
|
||||||
final static private double smallMarginY = 4;
|
final static private double smallMarginY = 4;
|
||||||
|
|
||||||
final private LineConfigurable lineConfig;
|
|
||||||
|
|
||||||
public EntityImageState(IEntity entity, ISkinParam skinParam) {
|
public EntityImageState(IEntity entity, ISkinParam skinParam) {
|
||||||
super(entity, skinParam);
|
super(entity, skinParam);
|
||||||
this.lineConfig = entity;
|
|
||||||
final Stereotype stereotype = entity.getStereotype();
|
final Stereotype stereotype = entity.getStereotype();
|
||||||
|
|
||||||
this.withSymbol = stereotype != null && stereotype.isWithOOSymbol();
|
this.withSymbol = stereotype != null && stereotype.isWithOOSymbol();
|
||||||
|
|
||||||
this.desc = entity.getDisplay().create8(new FontConfiguration(getSkinParam(), FontParam.STATE, stereotype),
|
|
||||||
HorizontalAlignment.CENTER, skinParam, CreoleMode.FULL, skinParam.wrapWidth());
|
|
||||||
|
|
||||||
// Display list = Display.empty();
|
|
||||||
// for (Member att : entity.getBodier().getFieldsToDisplay()) {
|
|
||||||
// list = list.addAll(Display.getWithNewlines(att.getDisplay(true)));
|
|
||||||
// }
|
|
||||||
final Display list = Display.create(entity.getBodier().getRawBody());
|
final Display list = Display.create(entity.getBodier().getRawBody());
|
||||||
|
|
||||||
this.url = entity.getUrl99();
|
|
||||||
|
|
||||||
this.fields = list.create8(new FontConfiguration(getSkinParam(), FontParam.STATE_ATTRIBUTE, stereotype),
|
this.fields = list.create8(new FontConfiguration(getSkinParam(), FontParam.STATE_ATTRIBUTE, stereotype),
|
||||||
HorizontalAlignment.LEFT, skinParam, CreoleMode.FULL, skinParam.wrapWidth());
|
HorizontalAlignment.LEFT, skinParam, CreoleMode.FULL, skinParam.wrapWidth());
|
||||||
|
|
||||||
@ -125,28 +101,11 @@ public class EntityImageState extends AbstractEntityImage {
|
|||||||
final Dimension2D dimTotal = calculateDimension(stringBounder);
|
final Dimension2D dimTotal = calculateDimension(stringBounder);
|
||||||
final Dimension2D dimDesc = desc.calculateDimension(stringBounder);
|
final Dimension2D dimDesc = desc.calculateDimension(stringBounder);
|
||||||
|
|
||||||
final double widthTotal = dimTotal.getWidth();
|
ug = applyColor(ug);
|
||||||
final double heightTotal = dimTotal.getHeight();
|
ug.draw(getShape(dimTotal));
|
||||||
final Shadowable rect = new URectangle(widthTotal, heightTotal).rounded(CORNER);
|
|
||||||
if (getSkinParam().shadowing(getEntity().getStereotype())) {
|
|
||||||
rect.setDeltaShadow(4);
|
|
||||||
}
|
|
||||||
|
|
||||||
HColor classBorder = lineConfig.getColors(getSkinParam()).getColor(ColorType.LINE);
|
|
||||||
if (classBorder == null) {
|
|
||||||
classBorder = SkinParamUtils.getColor(getSkinParam(), getStereo(), ColorParam.stateBorder);
|
|
||||||
}
|
|
||||||
ug = ug.apply(getStroke()).apply(classBorder);
|
|
||||||
HColor backcolor = getEntity().getColors(getSkinParam()).getColor(ColorType.BACK);
|
|
||||||
if (backcolor == null) {
|
|
||||||
backcolor = SkinParamUtils.getColor(getSkinParam(), getStereo(), ColorParam.stateBackground);
|
|
||||||
}
|
|
||||||
ug = ug.apply(backcolor.bg());
|
|
||||||
|
|
||||||
ug.draw(rect);
|
|
||||||
|
|
||||||
final double yLine = MARGIN + dimDesc.getHeight() + MARGIN_LINE;
|
final double yLine = MARGIN + dimDesc.getHeight() + MARGIN_LINE;
|
||||||
ug.apply(UTranslate.dy(yLine)).draw(ULine.hline(widthTotal));
|
ug.apply(UTranslate.dy(yLine)).draw(ULine.hline(dimTotal.getWidth()));
|
||||||
|
|
||||||
ug = ug.apply(new UStroke());
|
ug = ug.apply(new UStroke());
|
||||||
|
|
||||||
@ -156,7 +115,7 @@ public class EntityImageState extends AbstractEntityImage {
|
|||||||
drawSymbol(ug, xSymbol, ySymbol);
|
drawSymbol(ug, xSymbol, ySymbol);
|
||||||
}
|
}
|
||||||
|
|
||||||
final double xDesc = (widthTotal - dimDesc.getWidth()) / 2;
|
final double xDesc = (dimTotal.getWidth() - dimDesc.getWidth()) / 2;
|
||||||
final double yDesc = MARGIN;
|
final double yDesc = MARGIN;
|
||||||
desc.drawU(ug.apply(new UTranslate(xDesc, yDesc)));
|
desc.drawU(ug.apply(new UTranslate(xDesc, yDesc)));
|
||||||
|
|
||||||
@ -170,14 +129,6 @@ public class EntityImageState extends AbstractEntityImage {
|
|||||||
ug.closeGroup();
|
ug.closeGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
private UStroke getStroke() {
|
|
||||||
UStroke stroke = lineConfig.getColors(getSkinParam()).getSpecificLineStroke();
|
|
||||||
if (stroke == null) {
|
|
||||||
stroke = new UStroke(1.5);
|
|
||||||
}
|
|
||||||
return stroke;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void drawSymbol(UGraphic ug, double xSymbol, double ySymbol) {
|
public static void drawSymbol(UGraphic ug, double xSymbol, double ySymbol) {
|
||||||
xSymbol -= 4 * smallRadius + smallLine + smallMarginX;
|
xSymbol -= 4 * smallRadius + smallLine + smallMarginX;
|
||||||
ySymbol -= 2 * smallRadius + smallMarginY;
|
ySymbol -= 2 * smallRadius + smallMarginY;
|
||||||
@ -187,8 +138,4 @@ public class EntityImageState extends AbstractEntityImage {
|
|||||||
ug.apply(new UTranslate(xSymbol + 2 * smallRadius, ySymbol + smallLine)).draw(ULine.hline(smallLine));
|
ug.apply(new UTranslate(xSymbol + 2 * smallRadius, ySymbol + smallLine)).draw(ULine.hline(smallLine));
|
||||||
}
|
}
|
||||||
|
|
||||||
public ShapeType getShapeType() {
|
|
||||||
return ShapeType.ROUND_RECTANGLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -63,22 +63,15 @@ import net.sourceforge.plantuml.ugraphic.color.HColor;
|
|||||||
public class EntityImageState2 extends AbstractEntityImage {
|
public class EntityImageState2 extends AbstractEntityImage {
|
||||||
|
|
||||||
final private Url url;
|
final private Url url;
|
||||||
|
// final private LineConfigurable lineConfig;
|
||||||
final private LineConfigurable lineConfig;
|
|
||||||
|
|
||||||
private final TextBlock asSmall;
|
private final TextBlock asSmall;
|
||||||
|
|
||||||
public EntityImageState2(ILeaf entity, ISkinParam skinParam) {
|
public EntityImageState2(ILeaf entity, ISkinParam skinParam) {
|
||||||
super(entity, skinParam);
|
super(entity, skinParam);
|
||||||
this.lineConfig = entity;
|
// this.lineConfig = entity;
|
||||||
final Stereotype stereotype = entity.getStereotype();
|
final Stereotype stereotype = entity.getStereotype();
|
||||||
|
|
||||||
// Display list = Display.empty();
|
|
||||||
// for (Member att : entity.getBodier().getFieldsToDisplay()) {
|
|
||||||
// list = list.addAll(Display.getWithNewlines(att.getDisplay(true)));
|
|
||||||
// }
|
|
||||||
// final Display list = Display.create(entity.getBodier().getRawBody());
|
|
||||||
|
|
||||||
final USymbol symbol = USymbol.FRAME;
|
final USymbol symbol = USymbol.FRAME;
|
||||||
|
|
||||||
HColor backcolor = getEntity().getColors(getSkinParam()).getColor(ColorType.BACK);
|
HColor backcolor = getEntity().getColors(getSkinParam()).getColor(ColorType.BACK);
|
||||||
|
@ -0,0 +1,115 @@
|
|||||||
|
/* ========================================================================
|
||||||
|
* 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.svek.image;
|
||||||
|
|
||||||
|
import java.awt.geom.Dimension2D;
|
||||||
|
|
||||||
|
import net.sourceforge.plantuml.ColorParam;
|
||||||
|
import net.sourceforge.plantuml.FontParam;
|
||||||
|
import net.sourceforge.plantuml.ISkinParam;
|
||||||
|
import net.sourceforge.plantuml.LineConfigurable;
|
||||||
|
import net.sourceforge.plantuml.SkinParamUtils;
|
||||||
|
import net.sourceforge.plantuml.Url;
|
||||||
|
import net.sourceforge.plantuml.creole.CreoleMode;
|
||||||
|
import net.sourceforge.plantuml.cucadiagram.IEntity;
|
||||||
|
import net.sourceforge.plantuml.cucadiagram.Stereotype;
|
||||||
|
import net.sourceforge.plantuml.graphic.FontConfiguration;
|
||||||
|
import net.sourceforge.plantuml.graphic.HorizontalAlignment;
|
||||||
|
import net.sourceforge.plantuml.graphic.TextBlock;
|
||||||
|
import net.sourceforge.plantuml.graphic.color.ColorType;
|
||||||
|
import net.sourceforge.plantuml.svek.AbstractEntityImage;
|
||||||
|
import net.sourceforge.plantuml.svek.ShapeType;
|
||||||
|
import net.sourceforge.plantuml.ugraphic.UGraphic;
|
||||||
|
import net.sourceforge.plantuml.ugraphic.URectangle;
|
||||||
|
import net.sourceforge.plantuml.ugraphic.UStroke;
|
||||||
|
import net.sourceforge.plantuml.ugraphic.color.HColor;
|
||||||
|
|
||||||
|
public abstract class EntityImageStateCommon extends AbstractEntityImage {
|
||||||
|
|
||||||
|
final protected TextBlock desc;
|
||||||
|
final protected Url url;
|
||||||
|
|
||||||
|
final protected LineConfigurable lineConfig;
|
||||||
|
|
||||||
|
public EntityImageStateCommon(IEntity entity, ISkinParam skinParam) {
|
||||||
|
super(entity, skinParam);
|
||||||
|
|
||||||
|
this.lineConfig = entity;
|
||||||
|
final Stereotype stereotype = entity.getStereotype();
|
||||||
|
|
||||||
|
this.desc = entity.getDisplay().create8(new FontConfiguration(getSkinParam(), FontParam.STATE, stereotype),
|
||||||
|
HorizontalAlignment.CENTER, skinParam, CreoleMode.FULL, skinParam.wrapWidth());
|
||||||
|
this.url = entity.getUrl99();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
final protected UStroke getStroke() {
|
||||||
|
UStroke stroke = lineConfig.getColors(getSkinParam()).getSpecificLineStroke();
|
||||||
|
if (stroke == null) {
|
||||||
|
stroke = new UStroke(1.5);
|
||||||
|
}
|
||||||
|
return stroke;
|
||||||
|
}
|
||||||
|
|
||||||
|
final public ShapeType getShapeType() {
|
||||||
|
return ShapeType.ROUND_RECTANGLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
final protected URectangle getShape(final Dimension2D dimTotal) {
|
||||||
|
final URectangle rect = new URectangle(dimTotal).rounded(CORNER);
|
||||||
|
if (getSkinParam().shadowing(getEntity().getStereotype())) {
|
||||||
|
rect.setDeltaShadow(4);
|
||||||
|
}
|
||||||
|
return rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
final protected UGraphic applyColor(UGraphic ug) {
|
||||||
|
|
||||||
|
HColor classBorder = lineConfig.getColors(getSkinParam()).getColor(ColorType.LINE);
|
||||||
|
if (classBorder == null) {
|
||||||
|
classBorder = SkinParamUtils.getColor(getSkinParam(), getStereo(), ColorParam.stateBorder);
|
||||||
|
}
|
||||||
|
ug = ug.apply(getStroke()).apply(classBorder);
|
||||||
|
HColor backcolor = getEntity().getColors(getSkinParam()).getColor(ColorType.BACK);
|
||||||
|
if (backcolor == null) {
|
||||||
|
backcolor = SkinParamUtils.getColor(getSkinParam(), getStereo(), ColorParam.stateBackground);
|
||||||
|
}
|
||||||
|
ug = ug.apply(backcolor.bg());
|
||||||
|
|
||||||
|
return ug;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -37,51 +37,20 @@ package net.sourceforge.plantuml.svek.image;
|
|||||||
|
|
||||||
import java.awt.geom.Dimension2D;
|
import java.awt.geom.Dimension2D;
|
||||||
|
|
||||||
import net.sourceforge.plantuml.ColorParam;
|
|
||||||
import net.sourceforge.plantuml.Dimension2DDouble;
|
import net.sourceforge.plantuml.Dimension2DDouble;
|
||||||
import net.sourceforge.plantuml.FontParam;
|
|
||||||
import net.sourceforge.plantuml.ISkinParam;
|
import net.sourceforge.plantuml.ISkinParam;
|
||||||
import net.sourceforge.plantuml.SkinParamUtils;
|
|
||||||
import net.sourceforge.plantuml.Url;
|
|
||||||
import net.sourceforge.plantuml.creole.CreoleMode;
|
|
||||||
import net.sourceforge.plantuml.cucadiagram.IEntity;
|
import net.sourceforge.plantuml.cucadiagram.IEntity;
|
||||||
import net.sourceforge.plantuml.cucadiagram.Stereotype;
|
|
||||||
import net.sourceforge.plantuml.graphic.FontConfiguration;
|
|
||||||
import net.sourceforge.plantuml.graphic.HorizontalAlignment;
|
|
||||||
import net.sourceforge.plantuml.graphic.StringBounder;
|
import net.sourceforge.plantuml.graphic.StringBounder;
|
||||||
import net.sourceforge.plantuml.graphic.TextBlock;
|
|
||||||
import net.sourceforge.plantuml.graphic.color.ColorType;
|
|
||||||
import net.sourceforge.plantuml.svek.AbstractEntityImage;
|
|
||||||
import net.sourceforge.plantuml.svek.ShapeType;
|
|
||||||
import net.sourceforge.plantuml.ugraphic.Shadowable;
|
|
||||||
import net.sourceforge.plantuml.ugraphic.UGraphic;
|
import net.sourceforge.plantuml.ugraphic.UGraphic;
|
||||||
import net.sourceforge.plantuml.ugraphic.URectangle;
|
|
||||||
import net.sourceforge.plantuml.ugraphic.UStroke;
|
|
||||||
import net.sourceforge.plantuml.ugraphic.UTranslate;
|
import net.sourceforge.plantuml.ugraphic.UTranslate;
|
||||||
import net.sourceforge.plantuml.ugraphic.color.HColor;
|
|
||||||
|
|
||||||
public class EntityImageStateEmptyDescription extends AbstractEntityImage {
|
public class EntityImageStateEmptyDescription extends EntityImageStateCommon {
|
||||||
|
|
||||||
final private TextBlock desc;
|
|
||||||
final private Url url;
|
|
||||||
|
|
||||||
final private static int MIN_WIDTH = 50;
|
final private static int MIN_WIDTH = 50;
|
||||||
final private static int MIN_HEIGHT = 40;
|
final private static int MIN_HEIGHT = 40;
|
||||||
|
|
||||||
public EntityImageStateEmptyDescription(IEntity entity, ISkinParam skinParam) {
|
public EntityImageStateEmptyDescription(IEntity entity, ISkinParam skinParam) {
|
||||||
super(entity, skinParam);
|
super(entity, skinParam);
|
||||||
final Stereotype stereotype = entity.getStereotype();
|
|
||||||
|
|
||||||
this.desc = entity.getDisplay().create8(new FontConfiguration(getSkinParam(), FontParam.STATE, stereotype),
|
|
||||||
HorizontalAlignment.CENTER, skinParam, CreoleMode.FULL, skinParam.wrapWidth());
|
|
||||||
|
|
||||||
// Display list = Display.empty();
|
|
||||||
// for (Member att : entity.getBodier().getFieldsToDisplay()) {
|
|
||||||
// list = list.addAll(Display.getWithNewlines(att.getDisplay(true)));
|
|
||||||
// }
|
|
||||||
// final Display list = Display.create(entity.getBodier().getRawBody());
|
|
||||||
|
|
||||||
this.url = entity.getUrl99();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,23 +68,11 @@ public class EntityImageStateEmptyDescription extends AbstractEntityImage {
|
|||||||
final Dimension2D dimTotal = calculateDimension(stringBounder);
|
final Dimension2D dimTotal = calculateDimension(stringBounder);
|
||||||
final Dimension2D dimDesc = desc.calculateDimension(stringBounder);
|
final Dimension2D dimDesc = desc.calculateDimension(stringBounder);
|
||||||
|
|
||||||
final double widthTotal = dimTotal.getWidth();
|
ug = applyColor(ug);
|
||||||
final double heightTotal = dimTotal.getHeight();
|
ug.draw(getShape(dimTotal));
|
||||||
final Shadowable rect = new URectangle(widthTotal, heightTotal).rounded(CORNER);
|
|
||||||
if (getSkinParam().shadowing(getEntity().getStereotype())) {
|
|
||||||
rect.setDeltaShadow(4);
|
|
||||||
}
|
|
||||||
|
|
||||||
ug = ug.apply(new UStroke(1.5))
|
final double xDesc = (dimTotal.getWidth() - dimDesc.getWidth()) / 2;
|
||||||
.apply(SkinParamUtils.getColor(getSkinParam(), getStereo(), ColorParam.stateBorder));
|
final double yDesc = (dimTotal.getHeight() - dimDesc.getHeight()) / 2;
|
||||||
HColor backcolor = getEntity().getColors(getSkinParam()).getColor(ColorType.BACK);
|
|
||||||
if (backcolor == null) {
|
|
||||||
backcolor = SkinParamUtils.getColor(getSkinParam(), getStereo(), ColorParam.stateBackground);
|
|
||||||
}
|
|
||||||
ug = ug.apply(backcolor.bg());
|
|
||||||
ug.draw(rect);
|
|
||||||
final double xDesc = (widthTotal - dimDesc.getWidth()) / 2;
|
|
||||||
final double yDesc = (heightTotal - dimDesc.getHeight()) / 2;
|
|
||||||
desc.drawU(ug.apply(new UTranslate(xDesc, yDesc)));
|
desc.drawU(ug.apply(new UTranslate(xDesc, yDesc)));
|
||||||
|
|
||||||
if (url != null) {
|
if (url != null) {
|
||||||
@ -123,8 +80,4 @@ public class EntityImageStateEmptyDescription extends AbstractEntityImage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ShapeType getShapeType() {
|
|
||||||
return ShapeType.ROUND_RECTANGLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,8 @@
|
|||||||
*/
|
*/
|
||||||
package net.sourceforge.plantuml.version;
|
package net.sourceforge.plantuml.version;
|
||||||
|
|
||||||
|
import static net.sourceforge.plantuml.graphic.GraphicPosition.BACKGROUND_CORNER_BOTTOM_RIGHT;
|
||||||
|
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
@ -47,7 +49,7 @@ import net.sourceforge.plantuml.PlainStringsDiagram;
|
|||||||
import net.sourceforge.plantuml.Run;
|
import net.sourceforge.plantuml.Run;
|
||||||
import net.sourceforge.plantuml.core.DiagramDescription;
|
import net.sourceforge.plantuml.core.DiagramDescription;
|
||||||
import net.sourceforge.plantuml.cucadiagram.dot.GraphvizUtils;
|
import net.sourceforge.plantuml.cucadiagram.dot.GraphvizUtils;
|
||||||
import net.sourceforge.plantuml.dedication.Dedication;
|
import net.sourceforge.plantuml.dedication.PSystemDedication;
|
||||||
import net.sourceforge.plantuml.preproc.ImportedFiles;
|
import net.sourceforge.plantuml.preproc.ImportedFiles;
|
||||||
import net.sourceforge.plantuml.preproc.Stdlib;
|
import net.sourceforge.plantuml.preproc.Stdlib;
|
||||||
import net.sourceforge.plantuml.preproc2.PreprocessorUtils;
|
import net.sourceforge.plantuml.preproc2.PreprocessorUtils;
|
||||||
@ -57,8 +59,6 @@ import net.sourceforge.plantuml.security.SecurityProfile;
|
|||||||
import net.sourceforge.plantuml.security.SecurityUtils;
|
import net.sourceforge.plantuml.security.SecurityUtils;
|
||||||
import net.sourceforge.plantuml.svek.GraphvizCrash;
|
import net.sourceforge.plantuml.svek.GraphvizCrash;
|
||||||
|
|
||||||
import static net.sourceforge.plantuml.graphic.GraphicPosition.BACKGROUND_CORNER_BOTTOM_RIGHT;
|
|
||||||
|
|
||||||
public class PSystemVersion extends PlainStringsDiagram {
|
public class PSystemVersion extends PlainStringsDiagram {
|
||||||
|
|
||||||
PSystemVersion(boolean withImage, List<String> args) {
|
PSystemVersion(boolean withImage, List<String> args) {
|
||||||
@ -126,7 +126,7 @@ public class PSystemVersion extends PlainStringsDiagram {
|
|||||||
private static BufferedImage getImageWebp(final String name) {
|
private static BufferedImage getImageWebp(final String name) {
|
||||||
try {
|
try {
|
||||||
final InputStream is = PSystemVersion.class.getResourceAsStream(name);
|
final InputStream is = PSystemVersion.class.getResourceAsStream(name);
|
||||||
final BufferedImage image = Dedication.getBufferedImage(is);
|
final BufferedImage image = PSystemDedication.getBufferedImage(is);
|
||||||
is.close();
|
is.close();
|
||||||
return image;
|
return image;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
@ -44,7 +44,7 @@ public class Version {
|
|||||||
private static final int MAJOR_SEPARATOR = 1000000;
|
private static final int MAJOR_SEPARATOR = 1000000;
|
||||||
|
|
||||||
public static int version() {
|
public static int version() {
|
||||||
return 1202104;
|
return 1202105;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int versionPatched() {
|
public static int versionPatched() {
|
||||||
@ -80,7 +80,7 @@ public class Version {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static int beta() {
|
public static int beta() {
|
||||||
final int beta = 5;
|
final int beta = 0;
|
||||||
return beta;
|
return beta;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,7 +93,7 @@ public class Version {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static long compileTime() {
|
public static long compileTime() {
|
||||||
return 1617526179012L;
|
return 1619349628741L;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String compileTimeString() {
|
public static String compileTimeString() {
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
.elem {cursor: pointer;}
|
|
||||||
.elem, .link {opacity: 0.3;}
|
|
||||||
.elem.selected, .link.selected {opacity: 1;}
|
|
110
svg/default.js
110
svg/default.js
@ -1,110 +0,0 @@
|
|||||||
function addItemToMapOfLists(mapOfLists, name, item) {
|
|
||||||
// mapOfLists = {
|
|
||||||
// 'key1': [item1, item2, ...],
|
|
||||||
// 'key2': [item3, item4, ...],
|
|
||||||
// }
|
|
||||||
if (mapOfLists[name].length > 0) {
|
|
||||||
if (!mapOfLists[name].includes(item)) {
|
|
||||||
mapOfLists[name].push(item);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
mapOfLists[name] = [item];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function main() {
|
|
||||||
let elems = Array.from(document.getElementsByClassName('elem'));
|
|
||||||
let links = Array.from(document.getElementsByClassName('link'));
|
|
||||||
|
|
||||||
let elemsMap = {};
|
|
||||||
let linkedElems = {};
|
|
||||||
let linkedLinks = {};
|
|
||||||
|
|
||||||
elems.forEach(elem => {
|
|
||||||
let name = elem.classList[1];
|
|
||||||
elemsMap[name] = elem;
|
|
||||||
linkedElems[name] = [];
|
|
||||||
linkedLinks[name] = [];
|
|
||||||
});
|
|
||||||
|
|
||||||
links.forEach(link => {
|
|
||||||
let name1 = link.classList[1];
|
|
||||||
let name2 = link.classList[2];
|
|
||||||
|
|
||||||
if (elemsMap[name1]) {
|
|
||||||
if (elemsMap[name2]) {
|
|
||||||
let elem1 = elemsMap[name1];
|
|
||||||
let elem2 = elemsMap[name2];
|
|
||||||
|
|
||||||
addItemToMapOfLists(linkedElems, name1, elem2);
|
|
||||||
addItemToMapOfLists(linkedElems, name2, elem1);
|
|
||||||
|
|
||||||
addItemToMapOfLists(linkedLinks, name1, link);
|
|
||||||
addItemToMapOfLists(linkedLinks, name2, link);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let selectedElems = [];
|
|
||||||
let selectedLinks = [];
|
|
||||||
let selectedElemName = null;
|
|
||||||
|
|
||||||
function clearSelected() {
|
|
||||||
selectedElems.forEach(item => {
|
|
||||||
item.classList.remove('selected');
|
|
||||||
});
|
|
||||||
selectedElems = [];
|
|
||||||
|
|
||||||
selectedLinks.forEach(item => {
|
|
||||||
item.classList.remove('selected');
|
|
||||||
});
|
|
||||||
selectedLinks = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
function selectAll() {
|
|
||||||
selectedElemName = null;
|
|
||||||
|
|
||||||
selectedElems = Array.from(elems);
|
|
||||||
selectedElems.forEach(item => {
|
|
||||||
item.classList.add('selected');
|
|
||||||
});
|
|
||||||
|
|
||||||
selectedLinks = Array.from(links);
|
|
||||||
selectedLinks.forEach(item => {
|
|
||||||
item.classList.add('selected');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function selectElem(elemName) {
|
|
||||||
if (elemName === selectedElemName) {
|
|
||||||
selectAll();
|
|
||||||
|
|
||||||
} else {
|
|
||||||
clearSelected();
|
|
||||||
selectedElemName = elemName;
|
|
||||||
|
|
||||||
elemsMap[elemName].classList.add('selected');
|
|
||||||
selectedElems.push(elemsMap[elemName]);
|
|
||||||
|
|
||||||
linkedElems[elemName].forEach(linkedElem => {
|
|
||||||
selectedElems.push(linkedElem);
|
|
||||||
linkedElem.classList.add('selected');
|
|
||||||
});
|
|
||||||
|
|
||||||
linkedLinks[elemName].forEach(linkedLink => {
|
|
||||||
selectedLinks.push(linkedLink);
|
|
||||||
linkedLink.classList.add('selected');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Object.keys(elemsMap).forEach(name => {
|
|
||||||
elemsMap[name].onclick = () => { selectElem(name); };
|
|
||||||
});
|
|
||||||
|
|
||||||
selectAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', (event) => {
|
|
||||||
main();
|
|
||||||
});
|
|
Loading…
Reference in New Issue
Block a user