add script engine
This commit is contained in:
parent
813cba2acb
commit
0e30fc69df
41 changed files with 2117 additions and 140 deletions
|
@ -0,0 +1,51 @@
|
||||||
|
package org.xbib.graphics.barcode;
|
||||||
|
|
||||||
|
public enum Symbols {
|
||||||
|
AustraliaPost,
|
||||||
|
AztecCode,
|
||||||
|
ChannelCode,
|
||||||
|
Codabar,
|
||||||
|
CodablockF,
|
||||||
|
Code2Of5,
|
||||||
|
Code3Of9,
|
||||||
|
Code3Of9Extended,
|
||||||
|
Code11,
|
||||||
|
Code16k,
|
||||||
|
Code32,
|
||||||
|
Code49,
|
||||||
|
Code93,
|
||||||
|
Code128,
|
||||||
|
CodeOne,
|
||||||
|
Composite,
|
||||||
|
DataBar14,
|
||||||
|
DataBarExpanded,
|
||||||
|
DataBarLimited,
|
||||||
|
DataMatrix,
|
||||||
|
Ean,
|
||||||
|
GridMatrix,
|
||||||
|
JapanPost,
|
||||||
|
KixCode,
|
||||||
|
KoreaPost,
|
||||||
|
Logmars,
|
||||||
|
MaxiCode,
|
||||||
|
MicroQrCode,
|
||||||
|
MsiPlessey,
|
||||||
|
Nve18,
|
||||||
|
Pdf417,
|
||||||
|
Pharmacode,
|
||||||
|
Pharmacode2Track,
|
||||||
|
Pharmazentralnummer,
|
||||||
|
Postnet,
|
||||||
|
QrCode,
|
||||||
|
RoyalMail4State,
|
||||||
|
Telepen,
|
||||||
|
Upc,
|
||||||
|
UspsOneCode,
|
||||||
|
UspsPackage;
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public Symbol getSymbol() throws Exception {
|
||||||
|
Class<? extends AbstractSymbol> cl = (Class<? extends AbstractSymbol>) getClass().getClassLoader().loadClass(getClass().getPackageName() + "." + name());
|
||||||
|
return cl.getDeclaredConstructor().newInstance();
|
||||||
|
}
|
||||||
|
}
|
|
@ -122,8 +122,8 @@ public class SymbolTest {
|
||||||
}
|
}
|
||||||
String backend = "org.xbib.graphics.barcode";
|
String backend = "org.xbib.graphics.barcode";
|
||||||
Reflections reflections = new Reflections(backend);
|
Reflections reflections = new Reflections(backend);
|
||||||
Set< Class< ? extends AbstractSymbol>> symbols = reflections.getSubTypesOf(AbstractSymbol.class);
|
Set<Class<? extends AbstractSymbol>> symbols = reflections.getSubTypesOf(AbstractSymbol.class);
|
||||||
List< Object[] > data = new ArrayList<>();
|
List<Object[]> data = new ArrayList<>();
|
||||||
for (Class< ? extends AbstractSymbol> symbol : symbols) {
|
for (Class< ? extends AbstractSymbol> symbol : symbols) {
|
||||||
String symbolName = symbol.getSimpleName().toLowerCase();
|
String symbolName = symbol.getSimpleName().toLowerCase();
|
||||||
String dir = "src/test/resources/" + backend.replace('.', '/') + "/" + symbolName;
|
String dir = "src/test/resources/" + backend.replace('.', '/') + "/" + symbolName;
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
module org.xbib.graphics.layout.pdfbox {
|
module org.xbib.graphics.layout.pdfbox {
|
||||||
exports org.xbib.graphics.pdfbox.layout.boxable;
|
exports org.xbib.graphics.pdfbox.layout.boxable;
|
||||||
|
exports org.xbib.graphics.pdfbox.layout.color;
|
||||||
exports org.xbib.graphics.pdfbox.layout.elements;
|
exports org.xbib.graphics.pdfbox.layout.elements;
|
||||||
exports org.xbib.graphics.pdfbox.layout.elements.render;
|
exports org.xbib.graphics.pdfbox.layout.elements.render;
|
||||||
exports org.xbib.graphics.pdfbox.layout.font;
|
exports org.xbib.graphics.pdfbox.layout.font;
|
||||||
|
exports org.xbib.graphics.pdfbox.layout.script;
|
||||||
|
exports org.xbib.graphics.pdfbox.layout.script.command;
|
||||||
exports org.xbib.graphics.pdfbox.layout.shape;
|
exports org.xbib.graphics.pdfbox.layout.shape;
|
||||||
exports org.xbib.graphics.pdfbox.layout.table;
|
exports org.xbib.graphics.pdfbox.layout.table;
|
||||||
exports org.xbib.graphics.pdfbox.layout.table.render;
|
exports org.xbib.graphics.pdfbox.layout.table.render;
|
||||||
|
@ -11,6 +14,7 @@ module org.xbib.graphics.layout.pdfbox {
|
||||||
exports org.xbib.graphics.pdfbox.layout.util;
|
exports org.xbib.graphics.pdfbox.layout.util;
|
||||||
requires transitive org.xbib.graphics.barcode;
|
requires transitive org.xbib.graphics.barcode;
|
||||||
requires transitive org.xbib.graphics.pdfbox;
|
requires transitive org.xbib.graphics.pdfbox;
|
||||||
|
requires transitive org.xbib.settings.api;
|
||||||
requires org.xbib.settings.datastructures;
|
requires org.xbib.settings.datastructures;
|
||||||
requires transitive java.desktop;
|
requires transitive java.desktop;
|
||||||
requires java.logging;
|
requires java.logging;
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -21,24 +21,27 @@ public class BarcodeElement implements Element, Drawable, Dividable, WidthRespec
|
||||||
|
|
||||||
private float height;
|
private float height;
|
||||||
|
|
||||||
|
private float scale;
|
||||||
|
|
||||||
private float maxWidth = -1;
|
private float maxWidth = -1;
|
||||||
|
|
||||||
private Position absolutePosition;
|
private Position absolutePosition;
|
||||||
|
|
||||||
public BarcodeElement(Symbol symbol) {
|
public BarcodeElement(Symbol symbol) {
|
||||||
this.symbol = symbol;
|
this.symbol = symbol;
|
||||||
this.width = symbol.getWidth();
|
setWidth(symbol.getWidth());
|
||||||
this.height = symbol.getHeight();
|
setHeight(symbol.getHeight());
|
||||||
|
setScale(1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setScale(float scale) {
|
public void setScale(float scale) {
|
||||||
|
this.scale = scale;
|
||||||
setWidth(width * scale);
|
setWidth(width * scale);
|
||||||
setHeight(height * scale);
|
setHeight(height * scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public float getScale() {
|
||||||
public float getWidth() throws IOException {
|
return scale;
|
||||||
return width;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setWidth(float width) {
|
public void setWidth(float width) {
|
||||||
|
@ -46,14 +49,19 @@ public class BarcodeElement implements Element, Drawable, Dividable, WidthRespec
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float getHeight() throws IOException {
|
public float getWidth() throws IOException {
|
||||||
return height;
|
return width;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHeight(float height) {
|
public void setHeight(float height) {
|
||||||
this.height = height;
|
this.height = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getHeight() throws IOException {
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Divided divide(float remainingHeight, float nextPageHeight)
|
public Divided divide(float remainingHeight, float nextPageHeight)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
|
|
@ -11,6 +11,11 @@ public class ControlElement implements Element {
|
||||||
*/
|
*/
|
||||||
public final static ControlElement NEWPAGE = new ControlElement("NEWPAGE");
|
public final static ControlElement NEWPAGE = new ControlElement("NEWPAGE");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggers flip to the next column.
|
||||||
|
*/
|
||||||
|
public final static ControlElement NEWCOLUMN = new ControlElement("NEWCOLUMN");
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
|
|
||||||
public ControlElement(final String name) {
|
public ControlElement(final String name) {
|
||||||
|
|
|
@ -98,7 +98,7 @@ public class Frame implements Element, Drawable, WidthRespecting, Dividable {
|
||||||
/**
|
/**
|
||||||
* Adds a drawable to the frame.
|
* Adds a drawable to the frame.
|
||||||
*
|
*
|
||||||
* @param drawable
|
* @param drawable the drawable
|
||||||
*/
|
*/
|
||||||
public void add(final Drawable drawable) {
|
public void add(final Drawable drawable) {
|
||||||
innerList.add(drawable);
|
innerList.add(drawable);
|
||||||
|
@ -154,8 +154,7 @@ public class Frame implements Element, Drawable, WidthRespecting, Dividable {
|
||||||
* stroke} and {@link #getBorderColor() color} is set.
|
* stroke} and {@link #getBorderColor() color} is set.
|
||||||
*/
|
*/
|
||||||
protected boolean hasBorder() {
|
protected boolean hasBorder() {
|
||||||
return getShape() != null && getBorderStroke() != null
|
return getShape() != null && getBorderStroke() != null && getBorderColor() != null;
|
||||||
&& getBorderColor() != null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -490,11 +489,9 @@ public class Frame implements Element, Drawable, WidthRespecting, Dividable {
|
||||||
private void setMaxWidth(final Drawable inner, float maxWidth) {
|
private void setMaxWidth(final Drawable inner, float maxWidth) {
|
||||||
if (inner instanceof WidthRespecting) {
|
if (inner instanceof WidthRespecting) {
|
||||||
if (getGivenWidth() != null) {
|
if (getGivenWidth() != null) {
|
||||||
((WidthRespecting) inner).setMaxWidth(getGivenWidth()
|
((WidthRespecting) inner).setMaxWidth(getGivenWidth() - getHorizontalShapeSpacing());
|
||||||
- getHorizontalShapeSpacing());
|
|
||||||
} else if (maxWidth >= 0) {
|
} else if (maxWidth >= 0) {
|
||||||
((WidthRespecting) inner).setMaxWidth(maxWidth
|
((WidthRespecting) inner).setMaxWidth(maxWidth - getHorizontalSpacing());
|
||||||
- getHorizontalSpacing());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -514,22 +511,15 @@ public class Frame implements Element, Drawable, WidthRespecting, Dividable {
|
||||||
@Override
|
@Override
|
||||||
public void draw(PDDocument pdDocument, PDPageContentStream contentStream,
|
public void draw(PDDocument pdDocument, PDPageContentStream contentStream,
|
||||||
Position upperLeft, DrawListener drawListener) throws IOException {
|
Position upperLeft, DrawListener drawListener) throws IOException {
|
||||||
|
|
||||||
setInnerMaxWidthIfNecessary();
|
setInnerMaxWidthIfNecessary();
|
||||||
|
|
||||||
float halfBorderWidth = 0;
|
float halfBorderWidth = 0;
|
||||||
if (getBorderWidth() > 0) {
|
if (getBorderWidth() > 0) {
|
||||||
halfBorderWidth = getBorderWidth() / 2f;
|
halfBorderWidth = getBorderWidth() / 2f;
|
||||||
}
|
}
|
||||||
upperLeft = upperLeft.add(getMarginLeft() + halfBorderWidth,
|
upperLeft = upperLeft.add(getMarginLeft() + halfBorderWidth, -getMarginTop() - halfBorderWidth);
|
||||||
-getMarginTop() - halfBorderWidth);
|
|
||||||
|
|
||||||
if (getShape() != null) {
|
if (getShape() != null) {
|
||||||
float shapeWidth = getWidth() - getMarginLeft() - getMarginRight()
|
float shapeWidth = getWidth() - getMarginLeft() - getMarginRight() - getBorderWidth();
|
||||||
- getBorderWidth();
|
float shapeHeight = getHeight() - getMarginTop() - getMarginBottom() - getBorderWidth();
|
||||||
float shapeHeight = getHeight() - getMarginTop()
|
|
||||||
- getMarginBottom() - getBorderWidth();
|
|
||||||
|
|
||||||
if (getBackgroundColor() != null) {
|
if (getBackgroundColor() != null) {
|
||||||
getShape().fill(pdDocument, contentStream, upperLeft,
|
getShape().fill(pdDocument, contentStream, upperLeft,
|
||||||
shapeWidth, shapeHeight, getBackgroundColor(),
|
shapeWidth, shapeHeight, getBackgroundColor(),
|
||||||
|
@ -541,10 +531,7 @@ public class Frame implements Element, Drawable, WidthRespecting, Dividable {
|
||||||
getBorderStroke(), drawListener);
|
getBorderStroke(), drawListener);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Position innerUpperLeft = upperLeft.add(getPaddingLeft() + halfBorderWidth, -getPaddingTop() - halfBorderWidth);
|
||||||
Position innerUpperLeft = upperLeft.add(getPaddingLeft()
|
|
||||||
+ halfBorderWidth, -getPaddingTop() - halfBorderWidth);
|
|
||||||
|
|
||||||
for (Drawable inner : innerList) {
|
for (Drawable inner : innerList) {
|
||||||
inner.draw(pdDocument, contentStream, innerUpperLeft, drawListener);
|
inner.draw(pdDocument, contentStream, innerUpperLeft, drawListener);
|
||||||
innerUpperLeft = innerUpperLeft.add(0, -inner.getHeight());
|
innerUpperLeft = innerUpperLeft.add(0, -inner.getHeight());
|
||||||
|
@ -562,23 +549,16 @@ public class Frame implements Element, Drawable, WidthRespecting, Dividable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Divided divide(float remainingHeight, float nextPageHeight)
|
public Divided divide(float remainingHeight, float nextPageHeight) throws IOException {
|
||||||
throws IOException {
|
|
||||||
setInnerMaxWidthIfNecessary();
|
setInnerMaxWidthIfNecessary();
|
||||||
|
|
||||||
if (remainingHeight - getVerticalSpacing() <= 0) {
|
if (remainingHeight - getVerticalSpacing() <= 0) {
|
||||||
return new Divided(new VerticalSpacer(remainingHeight), this);
|
return new Divided(new VerticalSpacer(remainingHeight), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// find first inner that does not fit on page
|
// find first inner that does not fit on page
|
||||||
float spaceLeft = remainingHeight - getVerticalSpacing();
|
float spaceLeft = remainingHeight - getVerticalSpacing();
|
||||||
|
|
||||||
DividedList dividedList = divideList(innerList, spaceLeft);
|
DividedList dividedList = divideList(innerList, spaceLeft);
|
||||||
|
float spaceLeftForDivided = spaceLeft - getHeight(dividedList.getHead());
|
||||||
float spaceLeftForDivided = spaceLeft
|
|
||||||
- getHeight(dividedList.getHead());
|
|
||||||
Divided divided = null;
|
Divided divided = null;
|
||||||
|
|
||||||
if (dividedList.getDrawableToDivide() != null) {
|
if (dividedList.getDrawableToDivide() != null) {
|
||||||
Dividable innerDividable = null;
|
Dividable innerDividable = null;
|
||||||
if (dividedList.getDrawableToDivide() instanceof Dividable) {
|
if (dividedList.getDrawableToDivide() instanceof Dividable) {
|
||||||
|
@ -590,11 +570,9 @@ public class Frame implements Element, Drawable, WidthRespecting, Dividable {
|
||||||
divided = innerDividable.divide(spaceLeftForDivided, nextPageHeight
|
divided = innerDividable.divide(spaceLeftForDivided, nextPageHeight
|
||||||
- getVerticalSpacing());
|
- getVerticalSpacing());
|
||||||
}
|
}
|
||||||
|
|
||||||
Float firstHeight = getGivenHeight() == null ? null : remainingHeight;
|
Float firstHeight = getGivenHeight() == null ? null : remainingHeight;
|
||||||
Float tailHeight = getGivenHeight() == null ? null : getGivenHeight()
|
Float tailHeight = getGivenHeight() == null ? null : getGivenHeight()
|
||||||
- spaceLeft;
|
- spaceLeft;
|
||||||
|
|
||||||
// create head sub frame
|
// create head sub frame
|
||||||
Frame first = new Frame(getGivenWidth(), firstHeight);
|
Frame first = new Frame(getGivenWidth(), firstHeight);
|
||||||
copyAllButInnerAndSizeTo(first);
|
copyAllButInnerAndSizeTo(first);
|
||||||
|
@ -604,7 +582,6 @@ public class Frame implements Element, Drawable, WidthRespecting, Dividable {
|
||||||
if (divided != null) {
|
if (divided != null) {
|
||||||
first.add(divided.getFirst());
|
first.add(divided.getFirst());
|
||||||
}
|
}
|
||||||
|
|
||||||
// create tail sub frame
|
// create tail sub frame
|
||||||
Frame tail = new Frame(getGivenWidth(), tailHeight);
|
Frame tail = new Frame(getGivenWidth(), tailHeight);
|
||||||
copyAllButInnerAndSizeTo(tail);
|
copyAllButInnerAndSizeTo(tail);
|
||||||
|
@ -614,21 +591,17 @@ public class Frame implements Element, Drawable, WidthRespecting, Dividable {
|
||||||
if (dividedList.getTail() != null) {
|
if (dividedList.getTail() != null) {
|
||||||
tail.addAll(dividedList.getTail());
|
tail.addAll(dividedList.getTail());
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Divided(first, tail);
|
return new Divided(first, tail);
|
||||||
}
|
}
|
||||||
|
|
||||||
private DividedList divideList(List<Drawable> items, float spaceLeft)
|
private DividedList divideList(List<Drawable> items, float spaceLeft) throws IOException {
|
||||||
throws IOException {
|
|
||||||
List<Drawable> head = null;
|
List<Drawable> head = null;
|
||||||
List<Drawable> tail = null;
|
List<Drawable> tail = null;
|
||||||
Drawable toDivide = null;
|
Drawable toDivide = null;
|
||||||
|
|
||||||
float tmpHeight = 0;
|
float tmpHeight = 0;
|
||||||
int index = 0;
|
int index = 0;
|
||||||
while (tmpHeight < spaceLeft) {
|
while (tmpHeight < spaceLeft) {
|
||||||
tmpHeight += items.get(index).getHeight();
|
tmpHeight += items.get(index).getHeight();
|
||||||
|
|
||||||
if (tmpHeight == spaceLeft) {
|
if (tmpHeight == spaceLeft) {
|
||||||
// we can split between two drawables
|
// we can split between two drawables
|
||||||
head = items.subList(0, index + 1);
|
head = items.subList(0, index + 1);
|
||||||
|
@ -636,7 +609,6 @@ public class Frame implements Element, Drawable, WidthRespecting, Dividable {
|
||||||
tail = items.subList(index + 1, items.size());
|
tail = items.subList(index + 1, items.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tmpHeight > spaceLeft) {
|
if (tmpHeight > spaceLeft) {
|
||||||
head = items.subList(0, index);
|
head = items.subList(0, index);
|
||||||
toDivide = items.get(index);
|
toDivide = items.get(index);
|
||||||
|
@ -644,10 +616,8 @@ public class Frame implements Element, Drawable, WidthRespecting, Dividable {
|
||||||
tail = items.subList(index + 1, items.size());
|
tail = items.subList(index + 1, items.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
++index;
|
++index;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new DividedList(head, toDivide, tail);
|
return new DividedList(head, toDivide, tail);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -674,7 +644,5 @@ public class Frame implements Element, Drawable, WidthRespecting, Dividable {
|
||||||
public List<Drawable> getTail() {
|
public List<Drawable> getTail() {
|
||||||
return tail;
|
return tail;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,8 +7,12 @@ import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
|
||||||
import org.xbib.graphics.pdfbox.layout.text.DrawListener;
|
import org.xbib.graphics.pdfbox.layout.text.DrawListener;
|
||||||
import org.xbib.graphics.pdfbox.layout.text.Position;
|
import org.xbib.graphics.pdfbox.layout.text.Position;
|
||||||
import org.xbib.graphics.pdfbox.layout.text.WidthRespecting;
|
import org.xbib.graphics.pdfbox.layout.text.WidthRespecting;
|
||||||
|
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Base64;
|
||||||
|
|
||||||
public class ImageElement implements Element, Drawable, Dividable, WidthRespecting {
|
public class ImageElement implements Element, Drawable, Dividable, WidthRespecting {
|
||||||
|
|
||||||
|
@ -24,10 +28,16 @@ public class ImageElement implements Element, Drawable, Dividable, WidthRespecti
|
||||||
|
|
||||||
private float height;
|
private float height;
|
||||||
|
|
||||||
|
private float scale;
|
||||||
|
|
||||||
private float maxWidth = -1;
|
private float maxWidth = -1;
|
||||||
|
|
||||||
private Position absolutePosition;
|
private Position absolutePosition;
|
||||||
|
|
||||||
|
public ImageElement(String base64) throws IOException {
|
||||||
|
this(ImageIO.read(new ByteArrayInputStream(Base64.getDecoder().decode(base64))));
|
||||||
|
}
|
||||||
|
|
||||||
public ImageElement(BufferedImage image) {
|
public ImageElement(BufferedImage image) {
|
||||||
this.image = image;
|
this.image = image;
|
||||||
this.width = image.getWidth();
|
this.width = image.getWidth();
|
||||||
|
@ -35,19 +45,13 @@ public class ImageElement implements Element, Drawable, Dividable, WidthRespecti
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setScale(float scale) {
|
public void setScale(float scale) {
|
||||||
|
this.scale = scale;
|
||||||
setWidth(width * scale);
|
setWidth(width * scale);
|
||||||
setHeight(height * scale);
|
setHeight(height * scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public float getScale() {
|
||||||
public float getWidth() throws IOException {
|
return scale;
|
||||||
if (width == SCALE_TO_RESPECT_WIDTH) {
|
|
||||||
if (getMaxWidth() > 0 && image.getWidth() > getMaxWidth()) {
|
|
||||||
return getMaxWidth();
|
|
||||||
}
|
|
||||||
return image.getWidth();
|
|
||||||
}
|
|
||||||
return width;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -62,15 +66,14 @@ public class ImageElement implements Element, Drawable, Dividable, WidthRespecti
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float getHeight() throws IOException {
|
public float getWidth() throws IOException {
|
||||||
if (height == SCALE_TO_RESPECT_WIDTH) {
|
if (width == SCALE_TO_RESPECT_WIDTH) {
|
||||||
if (getMaxWidth() > 0 && image.getWidth() > getMaxWidth()) {
|
if (getMaxWidth() > 0 && image.getWidth() > getMaxWidth()) {
|
||||||
return getMaxWidth() / (float) image.getWidth()
|
return getMaxWidth();
|
||||||
* (float) image.getHeight();
|
|
||||||
}
|
}
|
||||||
return image.getHeight();
|
return image.getWidth();
|
||||||
}
|
}
|
||||||
return height;
|
return width;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -86,8 +89,18 @@ public class ImageElement implements Element, Drawable, Dividable, WidthRespecti
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Divided divide(float remainingHeight, float nextPageHeight)
|
public float getHeight() throws IOException {
|
||||||
throws IOException {
|
if (height == SCALE_TO_RESPECT_WIDTH) {
|
||||||
|
if (getMaxWidth() > 0 && image.getWidth() > getMaxWidth()) {
|
||||||
|
return getMaxWidth() / (float) image.getWidth() * (float) image.getHeight();
|
||||||
|
}
|
||||||
|
return image.getHeight();
|
||||||
|
}
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Divided divide(float remainingHeight, float nextPageHeight) throws IOException {
|
||||||
if (getHeight() <= nextPageHeight) {
|
if (getHeight() <= nextPageHeight) {
|
||||||
return new Divided(new VerticalSpacer(remainingHeight), this);
|
return new Divided(new VerticalSpacer(remainingHeight), this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
package org.xbib.graphics.pdfbox.layout.elements;
|
||||||
|
|
||||||
|
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||||
|
import org.apache.pdfbox.pdmodel.PDPageContentStream;
|
||||||
|
import org.xbib.graphics.pdfbox.layout.shape.Path;
|
||||||
|
import org.xbib.graphics.pdfbox.layout.shape.Stroke;
|
||||||
|
import org.xbib.graphics.pdfbox.layout.text.DrawListener;
|
||||||
|
import org.xbib.graphics.pdfbox.layout.text.Position;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class PathElement implements Drawable, Element {
|
||||||
|
|
||||||
|
private final Path path;
|
||||||
|
|
||||||
|
private final Stroke stroke;
|
||||||
|
|
||||||
|
private final Color color;
|
||||||
|
|
||||||
|
private final Position position;
|
||||||
|
|
||||||
|
private float width;
|
||||||
|
|
||||||
|
private float height;
|
||||||
|
|
||||||
|
public PathElement(Path path, Stroke stroke, Color color, Position position) {
|
||||||
|
this.path = path;
|
||||||
|
this.stroke = stroke;
|
||||||
|
this.color = color;
|
||||||
|
this.position = position;
|
||||||
|
setWidth(0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Stroke getStroke() {
|
||||||
|
return stroke;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color getColor() {
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWidth(float width) {
|
||||||
|
this.width = width;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getWidth() throws IOException {
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHeight(float height) {
|
||||||
|
this.height = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getHeight() throws IOException {
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Position getAbsolutePosition() {
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void draw(PDDocument pdDocument, PDPageContentStream contentStream,
|
||||||
|
Position upperLeft, DrawListener drawListener) throws IOException {
|
||||||
|
path.draw(pdDocument, contentStream, upperLeft, getWidth(), getHeight(), color, stroke, drawListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Drawable removeLeadingEmptyVerticalSpace() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
|
@ -24,8 +24,7 @@ public class Rectangle extends Dimension {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Rectangle [x=" + x + ", y=" + y + ", width=" + getWidth()
|
return "Rectangle [x=" + x + ", y=" + y + ", width=" + getWidth() + ", height=" + getHeight() + "]";
|
||||||
+ ", height=" + getHeight() + "]";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -54,5 +53,4 @@ public class Rectangle extends Dimension {
|
||||||
}
|
}
|
||||||
return Float.floatToIntBits(y) == Float.floatToIntBits(other.y);
|
return Float.floatToIntBits(y) == Float.floatToIntBits(other.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,18 +13,13 @@ import java.io.IOException;
|
||||||
*/
|
*/
|
||||||
public class ColumnLayout extends VerticalLayout {
|
public class ColumnLayout extends VerticalLayout {
|
||||||
|
|
||||||
/**
|
|
||||||
* Triggers flip to the next column.
|
|
||||||
*/
|
|
||||||
public final static ControlElement NEWCOLUMN = new ControlElement("NEWCOLUMN");
|
|
||||||
|
|
||||||
|
|
||||||
private final int columnCount;
|
private final int columnCount;
|
||||||
|
|
||||||
private final float columnSpacing;
|
private final float columnSpacing;
|
||||||
|
|
||||||
private int columnIndex = 0;
|
private int columnIndex = 0;
|
||||||
private Float offsetY = null;
|
private Float offsetY = null;
|
||||||
|
|
||||||
|
|
||||||
public ColumnLayout(int columnCount) {
|
public ColumnLayout(int columnCount) {
|
||||||
this(columnCount, 0);
|
this(columnCount, 0);
|
||||||
}
|
}
|
||||||
|
@ -65,7 +60,7 @@ public class ColumnLayout extends VerticalLayout {
|
||||||
renderContext.newPage();
|
renderContext.newPage();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (element == NEWCOLUMN) {
|
if (element == ControlElement.NEWCOLUMN) {
|
||||||
turnPage(renderContext);
|
turnPage(renderContext);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
package org.xbib.graphics.pdfbox.layout.font;
|
||||||
|
|
||||||
|
import org.xbib.graphics.pdfbox.layout.elements.Document;
|
||||||
|
|
||||||
|
public enum Fonts {
|
||||||
|
HELVETICA,
|
||||||
|
TIMES,
|
||||||
|
COURIER,
|
||||||
|
NOTOSANS;
|
||||||
|
|
||||||
|
public Font getFont(Document document) {
|
||||||
|
if ("notosans".equalsIgnoreCase(name())) {
|
||||||
|
return new NotoSansFont(document);
|
||||||
|
}
|
||||||
|
return BaseFont.valueOf(name());
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,26 +4,39 @@ import org.xbib.graphics.pdfbox.layout.script.command.Command;
|
||||||
import org.xbib.settings.Settings;
|
import org.xbib.settings.Settings;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Map;
|
import java.util.Set;
|
||||||
|
|
||||||
public class Engine {
|
public class Engine {
|
||||||
|
private final String packageName;
|
||||||
|
|
||||||
|
private final ClassLoader classLoader;
|
||||||
|
|
||||||
private final State state;
|
private final State state;
|
||||||
|
|
||||||
public Engine() {
|
public Engine() {
|
||||||
|
packageName = getClass().getPackageName();
|
||||||
|
classLoader = getClass().getClassLoader();
|
||||||
this.state = new State();
|
this.state = new State();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void execute(String key, Settings settings) throws IOException {
|
public void execute(Settings settings) throws IOException {
|
||||||
State state = new State();
|
execute("document", state, settings);
|
||||||
String packageName = getClass().getPackageName();
|
}
|
||||||
ClassLoader classLoader = getClass().getClassLoader();
|
|
||||||
for (Map.Entry<String, Settings> entry : settings.getGroups(key).entrySet()) {
|
public void execute(String prefix, State state, Settings settings) throws IOException {
|
||||||
|
Settings subSettings = settings.getByPrefix(prefix);
|
||||||
|
Set<String> set = subSettings.getAsStructuredMap().keySet();
|
||||||
|
for (String string : set) {
|
||||||
try {
|
try {
|
||||||
String string = entry.getKey();
|
Settings thisSettings = settings.getAsSettings(prefix + string);
|
||||||
Class<?> cl = classLoader.loadClass(packageName + ".command." + string.substring(0, 1).toUpperCase() + string.substring(1) + "Command");
|
String type = thisSettings.get("type");
|
||||||
|
if (type == null) {
|
||||||
|
type = prefix;
|
||||||
|
}
|
||||||
|
String className = packageName + ".command." + type.substring(0, 1).toUpperCase() + type.substring(1) + "Command";
|
||||||
|
Class<?> cl = classLoader.loadClass(className);
|
||||||
Command command = (Command) cl.getConstructor().newInstance();
|
Command command = (Command) cl.getConstructor().newInstance();
|
||||||
command.execute(this, state, entry.getValue());
|
command.execute(this, state, thisSettings);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new IOException(e);
|
throw new IOException(e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,15 @@
|
||||||
package org.xbib.graphics.pdfbox.layout.script;
|
package org.xbib.graphics.pdfbox.layout.script;
|
||||||
|
|
||||||
import org.xbib.graphics.pdfbox.layout.elements.Document;
|
import org.xbib.graphics.pdfbox.layout.elements.Document;
|
||||||
|
import org.xbib.graphics.pdfbox.layout.elements.Paragraph;
|
||||||
|
import org.xbib.graphics.pdfbox.layout.elements.PathElement;
|
||||||
|
|
||||||
public class State {
|
public class State {
|
||||||
|
|
||||||
public Document document;
|
public Document document;
|
||||||
|
|
||||||
|
public Paragraph paragraph;
|
||||||
|
|
||||||
|
public PathElement pathElement;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
package org.xbib.graphics.pdfbox.layout.script.command;
|
||||||
|
|
||||||
|
import org.xbib.graphics.barcode.HumanReadableLocation;
|
||||||
|
import org.xbib.graphics.barcode.Symbol;
|
||||||
|
import org.xbib.graphics.barcode.Symbols;
|
||||||
|
import org.xbib.graphics.pdfbox.layout.elements.BarcodeElement;
|
||||||
|
import org.xbib.graphics.pdfbox.layout.script.Engine;
|
||||||
|
import org.xbib.graphics.pdfbox.layout.script.State;
|
||||||
|
import org.xbib.graphics.pdfbox.layout.text.Position;
|
||||||
|
import org.xbib.settings.Settings;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class BarcodeCommand implements Command {
|
||||||
|
@Override
|
||||||
|
public void execute(Engine engine, State state, Settings settings) throws IOException {
|
||||||
|
BarcodeElement element;
|
||||||
|
try {
|
||||||
|
Symbol symbol = Symbols.valueOf(settings.get("symbol")).getSymbol();
|
||||||
|
symbol.setContent(settings.get("value"));
|
||||||
|
symbol.setBarHeight(settings.getAsInt("barheight", 150));
|
||||||
|
symbol.setHumanReadableLocation(HumanReadableLocation.valueOf(settings.get("readablelocation", "BOTTOM")));
|
||||||
|
element = new BarcodeElement(symbol);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new IOException(e);
|
||||||
|
}
|
||||||
|
if (settings.containsSetting("x") && settings.containsSetting("y")) {
|
||||||
|
element.setAbsolutePosition(new Position(settings.getAsFloat("x", 0f), settings.getAsFloat("y", 0f)));
|
||||||
|
}
|
||||||
|
if (settings.containsSetting("width")) {
|
||||||
|
element.setWidth(settings.getAsFloat("width", element.getWidth()));
|
||||||
|
}
|
||||||
|
if (settings.containsSetting("height")) {
|
||||||
|
element.setWidth(settings.getAsFloat("height", element.getHeight()));
|
||||||
|
}
|
||||||
|
if (settings.containsSetting("scale")) {
|
||||||
|
element.setScale(settings.getAsFloat("scale", element.getScale()));
|
||||||
|
}
|
||||||
|
state.document.add(element);
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,11 +12,20 @@ public class DocumentCommand implements Command {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(Engine engine, State state, Settings settings) throws IOException {
|
public void execute(Engine engine, State state, Settings settings) throws IOException {
|
||||||
|
String margin = settings.get("margin", "0 0 0 0");
|
||||||
|
String[] margins = margin.split(" ");
|
||||||
PageFormat pageFormat = PageFormat.builder()
|
PageFormat pageFormat = PageFormat.builder()
|
||||||
|
.marginLeft(Float.parseFloat(margins[0]))
|
||||||
|
.marginRight(Float.parseFloat(margins[1]))
|
||||||
|
.marginTop(Float.parseFloat(margins[2]))
|
||||||
|
.marginBottom(Float.parseFloat(margins[3]))
|
||||||
.pageFormat(settings.get("format", "A4"))
|
.pageFormat(settings.get("format", "A4"))
|
||||||
.orientation(settings.get("orientiation", "PORTRAIT"))
|
.orientation(settings.get("orientiation", "PORTRAIT"))
|
||||||
.build();
|
.build();
|
||||||
state.document = new Document(pageFormat);
|
state.document = new Document(pageFormat);
|
||||||
engine.execute("paragraoh", settings);
|
engine.execute("image", state, settings);
|
||||||
|
engine.execute("barcode", state, settings);
|
||||||
|
engine.execute("path", state, settings);
|
||||||
|
engine.execute("paragraph", state, settings);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
package org.xbib.graphics.pdfbox.layout.script.command;
|
||||||
|
|
||||||
|
import org.xbib.graphics.pdfbox.layout.elements.ImageElement;
|
||||||
|
import org.xbib.graphics.pdfbox.layout.elements.render.VerticalLayoutHint;
|
||||||
|
import org.xbib.graphics.pdfbox.layout.script.Engine;
|
||||||
|
import org.xbib.graphics.pdfbox.layout.script.State;
|
||||||
|
import org.xbib.graphics.pdfbox.layout.text.Alignment;
|
||||||
|
import org.xbib.graphics.pdfbox.layout.text.Position;
|
||||||
|
import org.xbib.settings.Settings;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class ImageCommand implements Command {
|
||||||
|
@Override
|
||||||
|
public void execute(Engine engine, State state, Settings settings) throws IOException {
|
||||||
|
ImageElement element = new ImageElement(settings.get("value"));
|
||||||
|
if (settings.containsSetting("x") && settings.containsSetting("y")) {
|
||||||
|
element.setAbsolutePosition(new Position(settings.getAsFloat("x", 0f), settings.getAsFloat("y", 0f)));
|
||||||
|
}
|
||||||
|
if (settings.containsSetting("width")) {
|
||||||
|
element.setWidth(settings.getAsFloat("width", element.getWidth()));
|
||||||
|
}
|
||||||
|
if (settings.containsSetting("height")) {
|
||||||
|
element.setWidth(settings.getAsFloat("height", element.getHeight()));
|
||||||
|
}
|
||||||
|
if (settings.containsSetting("scale")) {
|
||||||
|
element.setScale(settings.getAsFloat("scale", element.getScale()));
|
||||||
|
}
|
||||||
|
state.document.add(element, new VerticalLayoutHint(Alignment.LEFT, 10, 10, 10, 10, true));
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,9 @@
|
||||||
package org.xbib.graphics.pdfbox.layout.script.command;
|
package org.xbib.graphics.pdfbox.layout.script.command;
|
||||||
|
|
||||||
|
import org.xbib.graphics.pdfbox.layout.elements.Paragraph;
|
||||||
import org.xbib.graphics.pdfbox.layout.script.Engine;
|
import org.xbib.graphics.pdfbox.layout.script.Engine;
|
||||||
import org.xbib.graphics.pdfbox.layout.script.State;
|
import org.xbib.graphics.pdfbox.layout.script.State;
|
||||||
|
import org.xbib.graphics.pdfbox.layout.text.Position;
|
||||||
import org.xbib.settings.Settings;
|
import org.xbib.settings.Settings;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -10,5 +12,14 @@ public class ParagraphCommand implements Command {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(Engine engine, State state, Settings settings) throws IOException {
|
public void execute(Engine engine, State state, Settings settings) throws IOException {
|
||||||
|
state.paragraph = new Paragraph();
|
||||||
|
if (settings.containsSetting("x") && settings.containsSetting("y")) {
|
||||||
|
state.paragraph.setAbsolutePosition(new Position(settings.getAsFloat("x", 0f), settings.getAsFloat("y", 0f)));
|
||||||
|
}
|
||||||
|
if (settings.containsSetting("width")) {
|
||||||
|
state.paragraph.setMaxWidth(settings.getAsFloat("width", state.document.getPageWidth()));
|
||||||
|
}
|
||||||
|
state.document.add(state.paragraph);
|
||||||
|
engine.execute("text", state, settings);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
package org.xbib.graphics.pdfbox.layout.script.command;
|
||||||
|
|
||||||
|
import org.xbib.graphics.pdfbox.layout.color.ColorFactory;
|
||||||
|
import org.xbib.graphics.pdfbox.layout.elements.PathElement;
|
||||||
|
import org.xbib.graphics.pdfbox.layout.script.Engine;
|
||||||
|
import org.xbib.graphics.pdfbox.layout.script.State;
|
||||||
|
import org.xbib.graphics.pdfbox.layout.shape.Path;
|
||||||
|
import org.xbib.graphics.pdfbox.layout.shape.Stroke;
|
||||||
|
import org.xbib.graphics.pdfbox.layout.text.Position;
|
||||||
|
import org.xbib.settings.Settings;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class PathCommand implements Command {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(Engine engine, State state, Settings settings) {
|
||||||
|
String value = settings.get("value");
|
||||||
|
if (value == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
List<Position> list = new ArrayList<>();
|
||||||
|
String[] s = value.split(" ");
|
||||||
|
Position position = null;
|
||||||
|
if (s.length > 0) {
|
||||||
|
if (settings.getAsBoolean("absolute", false)) {
|
||||||
|
position = new Position(Float.parseFloat(s[0]), Float.parseFloat(s[1]));
|
||||||
|
list.add(position);
|
||||||
|
} else {
|
||||||
|
Position p = new Position(Float.parseFloat(s[0]), Float.parseFloat(s[1]));
|
||||||
|
list.add(p);
|
||||||
|
}
|
||||||
|
for (int i = 2; i < s.length; i += 2) {
|
||||||
|
Position p = new Position(Float.parseFloat(s[i]), Float.parseFloat(s[i + 1]));
|
||||||
|
list.add(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Path path = new Path(list);
|
||||||
|
Stroke.StrokeBuilder strokeBuilder = Stroke.builder()
|
||||||
|
.capStyle(Stroke.CapStyle.valueOf(settings.get("capstyie", "Cap")))
|
||||||
|
.joinStyle(Stroke.JoinStyle.valueOf(settings.get("joinstyle", "Miter")))
|
||||||
|
.lineWidth(settings.getAsFloat("linewidth", 1f));
|
||||||
|
if (settings.containsSetting("dash")) {
|
||||||
|
strokeBuilder.dashPattern(new Stroke.DashPattern(settings.getAsFloat("dash", 1f)));
|
||||||
|
}
|
||||||
|
Color color = ColorFactory.web(settings.get("color", "black"));
|
||||||
|
state.document.add(new PathElement(path, strokeBuilder.build(), color, position));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
package org.xbib.graphics.pdfbox.layout.script.command;
|
||||||
|
|
||||||
|
import org.xbib.graphics.pdfbox.layout.font.Font;
|
||||||
|
import org.xbib.graphics.pdfbox.layout.font.Fonts;
|
||||||
|
import org.xbib.graphics.pdfbox.layout.script.Engine;
|
||||||
|
import org.xbib.graphics.pdfbox.layout.script.State;
|
||||||
|
import org.xbib.settings.Settings;
|
||||||
|
|
||||||
|
public class TextCommand implements Command {
|
||||||
|
@Override
|
||||||
|
public void execute(Engine engine, State state, Settings settings) {
|
||||||
|
String value = settings.get("value");
|
||||||
|
float size = settings.getAsFloat("size", 12.0f);
|
||||||
|
Font font = Fonts.valueOf(settings.get("font", "HELVETICA")).getFont(state.document);
|
||||||
|
state.paragraph.addMarkup(value, size, font);
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,7 +20,6 @@ public class Ellipse extends RoundRect {
|
||||||
protected void addRoundRect(PDPageContentStream contentStream,
|
protected void addRoundRect(PDPageContentStream contentStream,
|
||||||
Position upperLeft, float width, float height, float cornerRadiusX,
|
Position upperLeft, float width, float height, float cornerRadiusX,
|
||||||
float cornerRadiusY) throws IOException {
|
float cornerRadiusY) throws IOException {
|
||||||
super.addRoundRect(contentStream, upperLeft, width, height, width / 2f,
|
super.addRoundRect(contentStream, upperLeft, width, height, width / 2f, height / 2);
|
||||||
height / 2);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,33 +7,45 @@ import org.xbib.graphics.pdfbox.layout.text.Position;
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class Path implements Shape {
|
public class Path implements Shape {
|
||||||
|
|
||||||
private final List<Position> list;
|
private final List<Position> list;
|
||||||
|
|
||||||
public Path() {
|
public Path(List<Position> list) {
|
||||||
this.list = new ArrayList<>();
|
this.list = list;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void draw(PDDocument pdDocument, PDPageContentStream contentStream, Position upperLeft,
|
public void draw(PDDocument pdDocument,
|
||||||
float width, float height, Color color, Stroke stroke, DrawListener drawListener) throws IOException {
|
PDPageContentStream contentStream,
|
||||||
|
Position upperLeft,
|
||||||
|
float width,
|
||||||
|
float height,
|
||||||
|
Color color,
|
||||||
|
Stroke stroke,
|
||||||
|
DrawListener drawListener) throws IOException {
|
||||||
contentStream.saveGraphicsState();
|
contentStream.saveGraphicsState();
|
||||||
contentStream.moveTo(upperLeft.getX(), upperLeft.getY());
|
float x = upperLeft.getX();
|
||||||
|
float y = upperLeft.getY() - stroke.getLineWidth() / 2;
|
||||||
contentStream.setStrokingColor(color);
|
contentStream.setStrokingColor(color);
|
||||||
contentStream.setLineCapStyle(stroke.getCapStyle().value());
|
stroke.applyTo(contentStream);
|
||||||
contentStream.setLineDashPattern(stroke.getDashPattern().getPattern(), stroke.getDashPattern().getPhase());
|
boolean move = true;
|
||||||
contentStream.setLineJoinStyle(stroke.getJoinStyle().value());
|
|
||||||
contentStream.setLineWidth(stroke.getLineWidth());
|
|
||||||
for (Position p : list) {
|
for (Position p : list) {
|
||||||
contentStream.lineTo(p.getX(), p.getY());
|
if (move) {
|
||||||
|
contentStream.moveTo(x + p.getX(), y + p.getY());
|
||||||
|
move = false;
|
||||||
|
} else {
|
||||||
|
contentStream.lineTo(x + p.getX(), y + p.getY());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
contentStream.stroke();
|
||||||
contentStream.restoreGraphicsState();
|
contentStream.restoreGraphicsState();
|
||||||
|
if (drawListener != null) {
|
||||||
drawListener.drawn(this, upperLeft, width, height);
|
drawListener.drawn(this, upperLeft, width, height);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void fill(PDDocument pdDocument, PDPageContentStream contentStream, Position upperLeft,
|
public void fill(PDDocument pdDocument, PDPageContentStream contentStream, Position upperLeft,
|
||||||
|
@ -44,6 +56,5 @@ public class Path implements Shape {
|
||||||
@Override
|
@Override
|
||||||
public void add(PDDocument pdDocument, PDPageContentStream contentStream, Position upperLeft,
|
public void add(PDDocument pdDocument, PDPageContentStream contentStream, Position upperLeft,
|
||||||
float width, float height) throws IOException {
|
float width, float height) throws IOException {
|
||||||
list.add(new Position(width, height));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,8 +13,6 @@ public class Rect extends AbstractShape {
|
||||||
@Override
|
@Override
|
||||||
public void add(PDDocument pdDocument, PDPageContentStream contentStream,
|
public void add(PDDocument pdDocument, PDPageContentStream contentStream,
|
||||||
Position upperLeft, float width, float height) throws IOException {
|
Position upperLeft, float width, float height) throws IOException {
|
||||||
contentStream.addRect(upperLeft.getX(), upperLeft.getY() - height,
|
contentStream.addRect(upperLeft.getX(), upperLeft.getY() - height, width, height);
|
||||||
width, height);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,9 +37,11 @@ public class RoundRect extends AbstractShape {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void add(PDDocument pdDocument, PDPageContentStream contentStream,
|
public void add(PDDocument pdDocument,
|
||||||
Position upperLeft, float width, float height) throws IOException {
|
PDPageContentStream contentStream,
|
||||||
|
Position upperLeft,
|
||||||
|
float width,
|
||||||
|
float height) throws IOException {
|
||||||
addRoundRect(contentStream, upperLeft, width, height, cornerRadiusX, cornerRadiusY);
|
addRoundRect(contentStream, upperLeft, width, height, cornerRadiusX, cornerRadiusY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,6 @@ package org.xbib.graphics.pdfbox.layout.shape;
|
||||||
|
|
||||||
import org.apache.pdfbox.pdmodel.PDPageContentStream;
|
import org.apache.pdfbox.pdmodel.PDPageContentStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a container for all information needed to perform a stroke.
|
* This is a container for all information needed to perform a stroke.
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package org.xbib.graphics.pdfbox.layout.table;
|
package org.xbib.graphics.pdfbox.layout.table;
|
||||||
|
|
||||||
import org.xbib.graphics.pdfbox.layout.font.Font;
|
import org.xbib.graphics.pdfbox.layout.font.Font;
|
||||||
|
import org.xbib.graphics.pdfbox.layout.util.PdfUtil;
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
|
|
@ -3,6 +3,7 @@ package org.xbib.graphics.pdfbox.layout.table;
|
||||||
import org.xbib.graphics.pdfbox.layout.elements.Paragraph;
|
import org.xbib.graphics.pdfbox.layout.elements.Paragraph;
|
||||||
import org.xbib.graphics.pdfbox.layout.font.Font;
|
import org.xbib.graphics.pdfbox.layout.font.Font;
|
||||||
import org.xbib.graphics.pdfbox.layout.font.FontDescriptor;
|
import org.xbib.graphics.pdfbox.layout.font.FontDescriptor;
|
||||||
|
import org.xbib.graphics.pdfbox.layout.util.PdfUtil;
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ import static org.xbib.graphics.pdfbox.layout.table.HorizontalAlignment.JUSTIFY;
|
||||||
import static org.xbib.graphics.pdfbox.layout.table.HorizontalAlignment.RIGHT;
|
import static org.xbib.graphics.pdfbox.layout.table.HorizontalAlignment.RIGHT;
|
||||||
import org.xbib.graphics.pdfbox.layout.font.Font;
|
import org.xbib.graphics.pdfbox.layout.font.Font;
|
||||||
import org.xbib.graphics.pdfbox.layout.table.AbstractTextCell;
|
import org.xbib.graphics.pdfbox.layout.table.AbstractTextCell;
|
||||||
import org.xbib.graphics.pdfbox.layout.table.PdfUtil;
|
import org.xbib.graphics.pdfbox.layout.util.PdfUtil;
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
|
@ -3,7 +3,7 @@ package org.xbib.graphics.pdfbox.layout.table.render;
|
||||||
import org.apache.pdfbox.pdmodel.PDPageContentStream;
|
import org.apache.pdfbox.pdmodel.PDPageContentStream;
|
||||||
import org.apache.pdfbox.util.Matrix;
|
import org.apache.pdfbox.util.Matrix;
|
||||||
import org.xbib.graphics.pdfbox.layout.font.Font;
|
import org.xbib.graphics.pdfbox.layout.font.Font;
|
||||||
import org.xbib.graphics.pdfbox.layout.table.PdfUtil;
|
import org.xbib.graphics.pdfbox.layout.util.PdfUtil;
|
||||||
import org.xbib.graphics.pdfbox.layout.table.VerticalTextCell;
|
import org.xbib.graphics.pdfbox.layout.table.VerticalTextCell;
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
|
|
|
@ -200,7 +200,7 @@ public class IndentCharacters {
|
||||||
}
|
}
|
||||||
enumerator = EnumeratorFactory.createEnumerator(enumerationType);
|
enumerator = EnumeratorFactory.createEnumerator(enumerationType);
|
||||||
this.separator = separator != null ? separator : enumerator
|
this.separator = separator != null ? separator : enumerator
|
||||||
.getDefaultSeperator();
|
.getDefaultSeparator();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -13,5 +13,5 @@ public interface Enumerator {
|
||||||
/**
|
/**
|
||||||
* @return the default separator.
|
* @return the default separator.
|
||||||
*/
|
*/
|
||||||
String getDefaultSeperator();
|
String getDefaultSeparator();
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ public class Enumerators {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getDefaultSeperator() {
|
public String getDefaultSeparator() {
|
||||||
return ".";
|
return ".";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,8 +49,7 @@ public class Enumerators {
|
||||||
* c) Stet clita ...
|
* c) Stet clita ...
|
||||||
* </pre>
|
* </pre>
|
||||||
*/
|
*/
|
||||||
public static class LowerCaseAlphabeticEnumerator extends
|
public static class LowerCaseAlphabeticEnumerator extends AlphabeticEnumerator {
|
||||||
AlphabeticEnumerator {
|
|
||||||
|
|
||||||
public LowerCaseAlphabeticEnumerator() {
|
public LowerCaseAlphabeticEnumerator() {
|
||||||
super();
|
super();
|
||||||
|
@ -98,7 +97,7 @@ public class Enumerators {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getDefaultSeperator() {
|
public String getDefaultSeparator() {
|
||||||
return ")";
|
return ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,7 +172,7 @@ public class Enumerators {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getDefaultSeperator() {
|
public String getDefaultSeparator() {
|
||||||
return ".";
|
return ".";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,60 +180,60 @@ public class Enumerators {
|
||||||
if (input < 1 || input > 3999) {
|
if (input < 1 || input > 3999) {
|
||||||
return "Invalid Roman Number Value";
|
return "Invalid Roman Number Value";
|
||||||
}
|
}
|
||||||
String s = "";
|
StringBuilder s = new StringBuilder();
|
||||||
while (input >= 1000) {
|
while (input >= 1000) {
|
||||||
s += "M";
|
s.append("M");
|
||||||
input -= 1000;
|
input -= 1000;
|
||||||
}
|
}
|
||||||
while (input >= 900) {
|
while (input >= 900) {
|
||||||
s += "CM";
|
s.append("CM");
|
||||||
input -= 900;
|
input -= 900;
|
||||||
}
|
}
|
||||||
while (input >= 500) {
|
while (input >= 500) {
|
||||||
s += "D";
|
s.append("D");
|
||||||
input -= 500;
|
input -= 500;
|
||||||
}
|
}
|
||||||
while (input >= 400) {
|
while (input >= 400) {
|
||||||
s += "CD";
|
s.append("CD");
|
||||||
input -= 400;
|
input -= 400;
|
||||||
}
|
}
|
||||||
while (input >= 100) {
|
while (input >= 100) {
|
||||||
s += "C";
|
s.append("C");
|
||||||
input -= 100;
|
input -= 100;
|
||||||
}
|
}
|
||||||
while (input >= 90) {
|
while (input >= 90) {
|
||||||
s += "XC";
|
s.append("XC");
|
||||||
input -= 90;
|
input -= 90;
|
||||||
}
|
}
|
||||||
while (input >= 50) {
|
while (input >= 50) {
|
||||||
s += "L";
|
s.append("L");
|
||||||
input -= 50;
|
input -= 50;
|
||||||
}
|
}
|
||||||
while (input >= 40) {
|
while (input >= 40) {
|
||||||
s += "XL";
|
s.append("XL");
|
||||||
input -= 40;
|
input -= 40;
|
||||||
}
|
}
|
||||||
while (input >= 10) {
|
while (input >= 10) {
|
||||||
s += "X";
|
s.append("X");
|
||||||
input -= 10;
|
input -= 10;
|
||||||
}
|
}
|
||||||
while (input >= 9) {
|
while (input >= 9) {
|
||||||
s += "IX";
|
s.append("IX");
|
||||||
input -= 9;
|
input -= 9;
|
||||||
}
|
}
|
||||||
while (input >= 5) {
|
while (input >= 5) {
|
||||||
s += "V";
|
s.append("V");
|
||||||
input -= 5;
|
input -= 5;
|
||||||
}
|
}
|
||||||
while (input >= 4) {
|
while (input >= 4) {
|
||||||
s += "IV";
|
s.append("IV");
|
||||||
input -= 4;
|
input -= 4;
|
||||||
}
|
}
|
||||||
while (input >= 1) {
|
while (input >= 1) {
|
||||||
s += "I";
|
s.append("I");
|
||||||
input -= 1;
|
input -= 1;
|
||||||
}
|
}
|
||||||
return s;
|
return s.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package org.xbib.graphics.pdfbox.layout.table;
|
package org.xbib.graphics.pdfbox.layout.util;
|
||||||
|
|
||||||
import org.xbib.graphics.pdfbox.layout.font.Font;
|
import org.xbib.graphics.pdfbox.layout.font.Font;
|
||||||
|
import org.xbib.graphics.pdfbox.layout.table.CouldNotDetermineStringWidthException;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
|
@ -0,0 +1,2 @@
|
||||||
|
org.xbib.settings.datastructures.PropertiesSettingsLoader
|
||||||
|
org.xbib.settings.datastructures.json.JsonSettingsLoader
|
|
@ -1,6 +1,7 @@
|
||||||
package org.xbib.graphics.pdfbox.layout.test;
|
package org.xbib.graphics.pdfbox.layout.test;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.xbib.graphics.pdfbox.layout.elements.ControlElement;
|
||||||
import org.xbib.graphics.pdfbox.layout.elements.Document;
|
import org.xbib.graphics.pdfbox.layout.elements.Document;
|
||||||
import org.xbib.graphics.pdfbox.layout.elements.Paragraph;
|
import org.xbib.graphics.pdfbox.layout.elements.Paragraph;
|
||||||
import org.xbib.graphics.pdfbox.layout.elements.render.ColumnLayout;
|
import org.xbib.graphics.pdfbox.layout.elements.render.ColumnLayout;
|
||||||
|
@ -34,7 +35,7 @@ public class LineSpacingTest {
|
||||||
document.add(left);
|
document.add(left);
|
||||||
document.add(left);
|
document.add(left);
|
||||||
document.add(left);
|
document.add(left);
|
||||||
document.add(ColumnLayout.NEWCOLUMN);
|
document.add(ControlElement.NEWCOLUMN);
|
||||||
Paragraph right = new Paragraph();
|
Paragraph right = new Paragraph();
|
||||||
right.setLineSpacing(1.5f);
|
right.setLineSpacing(1.5f);
|
||||||
right.setMaxWidth(document.getPageWidth() / 2);
|
right.setMaxWidth(document.getPageWidth() / 2);
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
package org.xbib.graphics.pdfbox.layout.test.script;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.xbib.graphics.pdfbox.layout.elements.Document;
|
||||||
|
import org.xbib.graphics.pdfbox.layout.script.Engine;
|
||||||
|
import org.xbib.settings.Settings;
|
||||||
|
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
|
||||||
|
public class ScriptTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void script() throws Exception {
|
||||||
|
Settings settings = Settings.settingsBuilder().loadFromResource("json", getClass().getResourceAsStream("script.json"))
|
||||||
|
.build();
|
||||||
|
Engine engine = new Engine();
|
||||||
|
engine.execute(settings);
|
||||||
|
Document document = engine.getState().document;
|
||||||
|
document.render().save(new FileOutputStream("build/script.pdf"));
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,7 +17,7 @@ import org.xbib.graphics.pdfbox.layout.table.BorderStyle;
|
||||||
import org.xbib.graphics.pdfbox.layout.table.Column;
|
import org.xbib.graphics.pdfbox.layout.table.Column;
|
||||||
import org.xbib.graphics.pdfbox.layout.table.HorizontalAlignment;
|
import org.xbib.graphics.pdfbox.layout.table.HorizontalAlignment;
|
||||||
import org.xbib.graphics.pdfbox.layout.table.ImageCell;
|
import org.xbib.graphics.pdfbox.layout.table.ImageCell;
|
||||||
import org.xbib.graphics.pdfbox.layout.table.PdfUtil;
|
import org.xbib.graphics.pdfbox.layout.util.PdfUtil;
|
||||||
import org.xbib.graphics.pdfbox.layout.table.Row;
|
import org.xbib.graphics.pdfbox.layout.table.Row;
|
||||||
import org.xbib.graphics.pdfbox.layout.table.Table;
|
import org.xbib.graphics.pdfbox.layout.table.Table;
|
||||||
import org.xbib.graphics.pdfbox.layout.table.TableRenderer;
|
import org.xbib.graphics.pdfbox.layout.table.TableRenderer;
|
||||||
|
|
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 673 B |
|
@ -0,0 +1 @@
|
||||||
|
iVBORw0KGgoAAAANSUhEUgAAAfQAAAC0AQMAAABYN0wRAAAABlBMVEUAAAD///+l2Z/dAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH1gsEDjEFTKgt4wAAAi5JREFUaN7t2s1ygyAQAOClHLiVHnvojI/io+mj+Sg+Qo4eGKmwgPkfdjfTNC05ZEblm+BmxQUFL/ocoPnmhX6Fy0/zzf+kN8L8fXl/Fr8Z9O/wACq1nQAs1S9Q/Mabb/6v+qOd0+O82/3C8eFYvn6X++evrno/lwNr88033/zr+Vlnv8BA99vIOSQ/nvahzs+x58G7OBynglnX+jGO78EfIHSF6FfIv2rDoZ7qHRb0wY/xJkT0odPYawvxVkX0M+RevyMj+rANXWj2BTEURD8W/4lzG6KPjWPUPjhen/uB5t/gJOpbKGkeHu07jteP85bsp+K/ON644uMsas0hqfT9mrPWhG2TvK31g8/ebgJrxYXg/TYCoe+CMzjybRt1Xu2+9zEUuL+v9DrsEniz+zgK6dRoqPR29774Ma5x0L2n+654tXvcYHnly2lU+b547fGvlHuHaVTlhys+TWaI3hz7rtb7K/4g9BgWkR8kfhJ6TF+qt0deiTzUe3XF56tY4I3EO6HPc3muT+nL81rkY+RT+rN9St+n+ZT+PG/2VdWf92sqxfRtn8rOOz6nL8O78C31ZSmL7pdUBHUXfj5dAbztO4mPNKc/w0ea05fhJ6EfA40zIhxHiH5N5SjXu1hEcT2Enpf5H8MjcyKvhd482Vuh74R+EHov80rotdBboe+F3nM9TqU133vMnguPzylVzdPO81Y0f+/9i6d7/vP35ptvvvnmX9i/8PuHzf9f/w3g1VrR1Tf4UwAAAABJRU5ErkJggg==
|
|
@ -0,0 +1,33 @@
|
||||||
|
{
|
||||||
|
"document1": {
|
||||||
|
"margin": "10 10 10 10",
|
||||||
|
"image1": {
|
||||||
|
"scale": 0.25,
|
||||||
|
"value": "iVBORw0KGgoAAAANSUhEUgAAAfQAAAC0AQMAAABYN0wRAAAABlBMVEUAAAD///+l2Z/dAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH1gsEDjEFTKgt4wAAAi5JREFUaN7t2s1ygyAQAOClHLiVHnvojI/io+mj+Sg+Qo4eGKmwgPkfdjfTNC05ZEblm+BmxQUFL/ocoPnmhX6Fy0/zzf+kN8L8fXl/Fr8Z9O/wACq1nQAs1S9Q/Mabb/6v+qOd0+O82/3C8eFYvn6X++evrno/lwNr88033/zr+Vlnv8BA99vIOSQ/nvahzs+x58G7OBynglnX+jGO78EfIHSF6FfIv2rDoZ7qHRb0wY/xJkT0odPYawvxVkX0M+RevyMj+rANXWj2BTEURD8W/4lzG6KPjWPUPjhen/uB5t/gJOpbKGkeHu07jteP85bsp+K/ON644uMsas0hqfT9mrPWhG2TvK31g8/ebgJrxYXg/TYCoe+CMzjybRt1Xu2+9zEUuL+v9DrsEniz+zgK6dRoqPR29774Ma5x0L2n+654tXvcYHnly2lU+b547fGvlHuHaVTlhys+TWaI3hz7rtb7K/4g9BgWkR8kfhJ6TF+qt0deiTzUe3XF56tY4I3EO6HPc3muT+nL81rkY+RT+rN9St+n+ZT+PG/2VdWf92sqxfRtn8rOOz6nL8O78C31ZSmL7pdUBHUXfj5dAbztO4mPNKc/w0ea05fhJ6EfA40zIhxHiH5N5SjXu1hEcT2Enpf5H8MjcyKvhd482Vuh74R+EHov80rotdBboe+F3nM9TqU133vMnguPzylVzdPO81Y0f+/9i6d7/vP35ptvvvnmX9i/8PuHzf9f/w3g1VrR1Tf4UwAAAABJRU5ErkJggg=="
|
||||||
|
},
|
||||||
|
"barcode1": {
|
||||||
|
"symbol": "Code3Of9",
|
||||||
|
"value": "12345678"
|
||||||
|
},
|
||||||
|
"path1": {
|
||||||
|
"absolute": false,
|
||||||
|
"value": "10 10 100 10 100 20 10 20 10 10",
|
||||||
|
"color": "red",
|
||||||
|
"dash": 1
|
||||||
|
},
|
||||||
|
"paragraph1": {
|
||||||
|
"text1": {
|
||||||
|
"value": "Hello World",
|
||||||
|
"size": 24,
|
||||||
|
"font": "HELVETICA"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"paragraph2": {
|
||||||
|
"text1": {
|
||||||
|
"value": "*Hello World*",
|
||||||
|
"size": 16,
|
||||||
|
"font": "NOTOSANS"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue