working on padding and cell linespacing

This commit is contained in:
Jörg Prante 2022-01-17 16:39:59 +01:00
parent e7ff6e59ff
commit d7066d586e
21 changed files with 122 additions and 65 deletions

View file

@ -21,6 +21,8 @@ public class HorizontalRuler implements Drawable, Element, WidthRespecting {
private float maxWidth = -1f; private float maxWidth = -1f;
private Position absolutePosition;
public HorizontalRuler(Stroke stroke, Color color) { public HorizontalRuler(Stroke stroke, Color color) {
super(); super();
this.stroke = stroke; this.stroke = stroke;
@ -66,7 +68,16 @@ public class HorizontalRuler implements Drawable, Element, WidthRespecting {
@Override @Override
public Position getAbsolutePosition() { public Position getAbsolutePosition() {
return null; return absolutePosition;
}
/**
* Sets the absolute position to render at.
*
* @param absolutePosition the absolute position.
*/
public void setAbsolutePosition(Position absolutePosition) {
this.absolutePosition = absolutePosition;
} }
@Override @Override

View file

@ -84,7 +84,7 @@ public class Paragraph extends TextFlow implements Drawable, Element, WidthRespe
public Element add(Element element) { public Element add(Element element) {
if (element instanceof TextElement) { if (element instanceof TextElement) {
TextElement textElement = (TextElement) element; TextElement textElement = (TextElement) element;
addMarkup(textElement.getValue(), textElement.getSize(), textElement.getFont()); addMarkup(textElement.getValue(), textElement.getFontSize(), textElement.getFont());
} else { } else {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }

View file

@ -42,8 +42,8 @@ public class TableElement implements Element, Drawable, Dividable {
table.addColumnOfWidth(width); table.addColumnOfWidth(width);
} }
public void padding(float padding) { public void padding(float paddingLeft, float paddingRight, float paddingTop, float paddingBottom) {
table.padding(padding); table.padding(paddingLeft, paddingRight, paddingTop, paddingBottom);
} }
public void textColor(Color color) { public void textColor(Color color) {

View file

@ -8,12 +8,12 @@ public class TextElement implements Element {
private final Font font; private final Font font;
private final float size; private final float fontsize;
public TextElement(String value, Font font, float size) { public TextElement(String value, Font font, float fontsize) {
this.value = value; this.value = value;
this.font = font; this.font = font;
this.size = size; this.fontsize = fontsize;
} }
public String getValue() { public String getValue() {
@ -24,8 +24,7 @@ public class TextElement implements Element {
return font; return font;
} }
public float getSize() { public float getFontSize() {
return size; return fontsize;
} }
} }

View file

@ -29,7 +29,8 @@ public class Engine implements Closeable {
public void executeElements(Settings settings) throws IOException { public void executeElements(Settings settings) throws IOException {
execute(settings.getAsSettings("elements")); execute(settings.getAsSettings("elements"));
for (int i = 0; i < 256; i++) { // limit to 1000 elements, abort if no element is present
for (int i = 0; i < 1000; i++) {
if (!executeElement(i, settings)) { if (!executeElement(i, settings)) {
break; break;
} }

View file

@ -30,7 +30,15 @@ public class CellCommand implements Command {
public void execute(Engine engine, State state, Settings settings) throws IOException { public void execute(Engine engine, State state, Settings settings) throws IOException {
if (settings.containsSetting("value")) { if (settings.containsSetting("value")) {
TextCell.Builder cell = TextCell.builder(); TextCell.Builder cell = TextCell.builder();
cell.padding(settings.getAsFloat("padding", 0f)); if (settings.containsSetting("padding")) {
String padding = settings.get("padding", "0 0 0 0");
String[] paddings = padding.split(" ");
float paddingLeft = Float.parseFloat(paddings[0]);
float paddingRight = Float.parseFloat(paddings[1]);
float paddingTop = Float.parseFloat(paddings[2]);
float paddingBottom = Float.parseFloat(paddings[3]);
cell.padding(paddingLeft, paddingRight, paddingTop, paddingBottom);
}
cell.text(settings.get("value")); cell.text(settings.get("value"));
cell.fontSize(settings.getAsFloat("fontsize", 11.0f)); cell.fontSize(settings.getAsFloat("fontsize", 11.0f));
Document document = state.getDocument(); Document document = state.getDocument();
@ -75,9 +83,13 @@ public class CellCommand implements Command {
cell.paragraph(paragraph); cell.paragraph(paragraph);
String value = settings.get("markup"); String value = settings.get("markup");
float size = settings.getAsFloat("fontsize", 11.0f); float size = settings.getAsFloat("fontsize", 11.0f);
Float lineSpacing = settings.getAsFloat("linespacing", -1f);
Document document = state.getDocument(); Document document = state.getDocument();
Font font = Fonts.valueOf(settings.get("font", "helvetica").toUpperCase(Locale.ROOT)).getFont(document); Font font = Fonts.valueOf(settings.get("font", "helvetica").toUpperCase(Locale.ROOT)).getFont(document);
cell.add(new Markup().setValue(value).setFont(font).setFontSize(size)); cell.add(new Markup().setValue(value).setFont(font).setFontSize(size));
if (lineSpacing != null && lineSpacing >= 0f) {
cell.lineSpacing(lineSpacing);
}
state.elements.peek().add(cell.build()); state.elements.peek().add(cell.build());
} }
} }

View file

@ -5,13 +5,16 @@ import org.xbib.graphics.pdfbox.layout.element.HorizontalRuler;
import org.xbib.graphics.pdfbox.layout.element.scripting.Engine; import org.xbib.graphics.pdfbox.layout.element.scripting.Engine;
import org.xbib.graphics.pdfbox.layout.element.scripting.State; import org.xbib.graphics.pdfbox.layout.element.scripting.State;
import org.xbib.graphics.pdfbox.layout.shape.Stroke; import org.xbib.graphics.pdfbox.layout.shape.Stroke;
import org.xbib.graphics.pdfbox.layout.text.Position;
import org.xbib.settings.Settings; import org.xbib.settings.Settings;
import java.awt.Color; import java.awt.Color;
import java.io.IOException; import java.io.IOException;
import java.util.Locale; import java.util.Locale;
import static org.xbib.graphics.pdfbox.layout.util.PdfUtil.mmToPt;
public class HorizontalrulerCommand implements Command { public class HorizontalrulerCommand 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 {
Stroke.StrokeBuilder strokeBuilder = Stroke.builder() Stroke.StrokeBuilder strokeBuilder = Stroke.builder()
@ -23,6 +26,12 @@ public class HorizontalrulerCommand implements Command {
} }
Color color = ColorFactory.web(settings.get("color", "black")); Color color = ColorFactory.web(settings.get("color", "black"));
HorizontalRuler horizontalRuler = new HorizontalRuler(strokeBuilder.build(), color); HorizontalRuler horizontalRuler = new HorizontalRuler(strokeBuilder.build(), color);
if (settings.containsSetting("x") && settings.containsSetting("y")) {
horizontalRuler.setAbsolutePosition(new Position(mmToPt(settings.getAsFloat("x", 0f)), mmToPt(settings.getAsFloat("y", 0f))));
}
if (settings.containsSetting("width")) {
horizontalRuler.setMaxWidth(mmToPt(settings.getAsFloat("width", -1f)));
}
state.elements.peek().add(horizontalRuler); state.elements.peek().add(horizontalRuler);
} }
} }

View file

@ -27,6 +27,9 @@ public class ParagraphCommand implements Command {
if (settings.containsSetting("alignment")) { if (settings.containsSetting("alignment")) {
paragraph.setAlignment(Alignment.valueOf(settings.get("alignment", "left").toUpperCase(Locale.ROOT))); paragraph.setAlignment(Alignment.valueOf(settings.get("alignment", "left").toUpperCase(Locale.ROOT)));
} }
if (settings.containsSetting("linespacing")) {
paragraph.setLineSpacing(settings.getAsFloat("linespacing", -1f));
}
state.elements.push(paragraph); state.elements.push(paragraph);
engine.executeElements(settings); engine.executeElements(settings);
state.elements.pop(); state.elements.pop();

View file

@ -21,7 +21,15 @@ public class RowCommand 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 {
Row.Builder row = Row.builder(); Row.Builder row = Row.builder();
row.padding(settings.getAsFloat("padding", 0f)); if (settings.containsSetting("padding")) {
String padding = settings.get("padding", "0 0 0 0");
String[] paddings = padding.split(" ");
float paddingLeft = Float.parseFloat(paddings[0]);
float paddingRight = Float.parseFloat(paddings[1]);
float paddingTop = Float.parseFloat(paddings[2]);
float paddingBottom = Float.parseFloat(paddings[3]);
row.padding(paddingLeft, paddingRight, paddingTop, paddingBottom);
}
row.fontSize(settings.getAsFloat("fontsize", 11.0f)); row.fontSize(settings.getAsFloat("fontsize", 11.0f));
Document document = state.getDocument(); Document document = state.getDocument();
row.font(Fonts.valueOf(settings.get("font", "helvetica").toUpperCase(Locale.ROOT)).getFont(document)); row.font(Fonts.valueOf(settings.get("font", "helvetica").toUpperCase(Locale.ROOT)).getFont(document));

View file

@ -22,10 +22,18 @@ public class TableCommand implements Command {
tableElement.addColumnOfWidth(mmToPt(Float.parseFloat(width))); tableElement.addColumnOfWidth(mmToPt(Float.parseFloat(width)));
} }
} }
if (settings.containsSetting("x") && settings.containsSetting("y")) { if (settings.containsSetting("x") && settings.containsSetting("y")) {
tableElement.setAbsolutePosition(new Position(mmToPt(settings.getAsFloat("x", 0f)), mmToPt(settings.getAsFloat("y", 0f)))); tableElement.setAbsolutePosition(new Position(mmToPt(settings.getAsFloat("x", 0f)), mmToPt(settings.getAsFloat("y", 0f))));
} }
if (settings.containsSetting("padding")) {
String padding = settings.get("padding", "0 0 0 0");
String[] paddings = padding.split(" ");
float paddingLeft = Float.parseFloat(paddings[0]);
float paddingRight = Float.parseFloat(paddings[1]);
float paddingTop = Float.parseFloat(paddings[2]);
float paddingBottom = Float.parseFloat(paddings[3]);
tableElement.padding(paddingLeft, paddingRight, paddingTop, paddingBottom);
}
state.elements.push(tableElement); state.elements.push(tableElement);
engine.executeElements(settings); engine.executeElements(settings);
state.elements.pop(); state.elements.pop();

View file

@ -43,5 +43,4 @@ public class Markup implements ParagraphProcessor {
float fontSize = getFontSize() != null ? getFontSize() : parameters.getFontSize(); float fontSize = getFontSize() != null ? getFontSize() : parameters.getFontSize();
paragraph.addMarkup(getValue(), fontSize, font); paragraph.addMarkup(getValue(), fontSize, font);
} }
} }

View file

@ -34,8 +34,6 @@ public class ParagraphCell extends AbstractCell {
@Override @Override
public void setWidth(float width) { public void setWidth(float width) {
super.setWidth(width); super.setWidth(width);
//while (getCellParagraph().getParagraph().removeLast() != null) {
//}
for (ParagraphProcessor p : getCellParagraph().getParagraphProcessors()) { for (ParagraphProcessor p : getCellParagraph().getParagraphProcessors()) {
try { try {
p.process(getCellParagraph().getParagraph(), getParameters()); p.process(getCellParagraph().getParagraph(), getParameters());
@ -94,6 +92,8 @@ public class ParagraphCell extends AbstractCell {
private Paragraph paragraph; private Paragraph paragraph;
private float lineSpacing = 1f;
private final List<ParagraphProcessor> processors; private final List<ParagraphProcessor> processors;
private Builder() { private Builder() {
@ -116,6 +116,11 @@ public class ParagraphCell extends AbstractCell {
return this; return this;
} }
public Builder lineSpacing(float lineSpacing) {
this.lineSpacing = lineSpacing;
return this;
}
public Builder add(ParagraphProcessor processor) { public Builder add(ParagraphProcessor processor) {
this.processors.add(processor); this.processors.add(processor);
return this; return this;
@ -126,6 +131,7 @@ public class ParagraphCell extends AbstractCell {
cell.setParameters(parameters); cell.setParameters(parameters);
cell.setColSpan(colSpan); cell.setColSpan(colSpan);
cell.setRowSpan(rowSpan); cell.setRowSpan(rowSpan);
cell.setLineSpacing(lineSpacing);
cell.setCellParagraph(new CellParagraph(paragraph, processors)); cell.setCellParagraph(new CellParagraph(paragraph, processors));
return cell; return cell;
} }

View file

@ -134,11 +134,11 @@ public class Row {
return this; return this;
} }
public Builder padding(final float padding) { public Builder padding(float paddingLeft, float paddingRight, float paddingTop, float paddingBottom) {
parameters.setPaddingTop(padding); parameters.setPaddingLeft(paddingLeft);
parameters.setPaddingBottom(padding); parameters.setPaddingRight(paddingRight);
parameters.setPaddingLeft(padding); parameters.setPaddingTop(paddingTop);
parameters.setPaddingRight(padding); parameters.setPaddingBottom(paddingBottom);
return this; return this;
} }

View file

@ -252,11 +252,11 @@ public class Table {
return this; return this;
} }
public Builder padding(final float padding) { public Builder padding(float paddingLeft, float paddingRight, float paddingTop, float paddingBottom) {
parameters.setPaddingTop(padding); parameters.setPaddingLeft(paddingLeft);
parameters.setPaddingBottom(padding); parameters.setPaddingRight(paddingRight);
parameters.setPaddingLeft(padding); parameters.setPaddingTop(paddingTop);
parameters.setPaddingRight(padding); parameters.setPaddingBottom(paddingBottom);
return this; return this;
} }

View file

@ -116,11 +116,11 @@ public class TextCell extends AbstractTextCell {
.borderStyleTop(style); .borderStyleTop(style);
} }
public Builder padding(final float padding) { public Builder padding(float paddingLeft, float paddingRight, float paddingTop, float paddingBottom) {
return this.paddingTop(padding) return this.paddingTop(paddingTop)
.paddingBottom(padding) .paddingBottom(paddingBottom)
.paddingLeft(padding) .paddingLeft(paddingLeft)
.paddingRight(padding); .paddingRight(paddingRight);
} }
public Builder paddingTop(final float padding) { public Builder paddingTop(final float padding) {

View file

@ -71,15 +71,15 @@ public class TextFlow implements TextSequence, WidthRespecting {
} }
public void addText(String text, float fontSize, Font font) { public void addText(String text, float fontSize, Font font) {
add(TextFlowUtil.createTextFlow(text, new FontDescriptor(font, fontSize))); add(TextFlowUtil.createTextFlow(text, new FontDescriptor(font, fontSize), lineSpacing));
} }
public void addMarkup(String markup, FontDescriptor fontDescriptor) { public void addMarkup(String markup, FontDescriptor fontDescriptor) {
add(TextFlowUtil.createTextFlowFromMarkup(markup, fontDescriptor)); add(TextFlowUtil.createTextFlowFromMarkup(markup, fontDescriptor, lineSpacing));
} }
public void addMarkup(String markup, float fontSize, Font font) { public void addMarkup(String markup, float fontSize, Font font) {
add(TextFlowUtil.createTextFlowFromMarkup(markup, new FontDescriptor(font, fontSize))); add(TextFlowUtil.createTextFlowFromMarkup(markup, new FontDescriptor(font, fontSize), lineSpacing));
} }
public void addIndent(String label, float indentWidth, SpaceUnit indentUnit, float fontsize, Font font) { public void addIndent(String label, float indentWidth, SpaceUnit indentUnit, float fontsize, Font font) {
@ -262,5 +262,4 @@ public class TextFlow implements TextSequence, WidthRespecting {
public String toString() { public String toString() {
return "TextFlow [text=" + text + "]"; return "TextFlow [text=" + text + "]";
} }
} }

View file

@ -15,9 +15,8 @@ import java.util.regex.Matcher;
public class TextFlowUtil { public class TextFlowUtil {
public static TextFlow createTextFlow(String text, FontDescriptor descriptor) { public static TextFlow createTextFlow(String text, FontDescriptor descriptor, float linespacing) {
final Iterable<CharSequence> parts = fromPlainText(text); return createTextFlow(fromPlainText(text), descriptor, linespacing);
return createTextFlow(parts, descriptor);
} }
/** /**
@ -49,11 +48,11 @@ public class TextFlowUtil {
* *
* @param markup the markup text. * @param markup the markup text.
* @param descriptor the font size to use, and the font. * @param descriptor the font size to use, and the font.
* @param linespacing the line spacing
* @return the created text flow. * @return the created text flow.
*/ */
public static TextFlow createTextFlowFromMarkup(String markup, FontDescriptor descriptor) { public static TextFlow createTextFlowFromMarkup(String markup, FontDescriptor descriptor, float linespacing) {
final Iterable<CharSequence> parts = fromMarkup(markup); return createTextFlow(fromMarkup(markup), descriptor, linespacing);
return createTextFlow(parts, descriptor);
} }
/** /**
@ -61,10 +60,12 @@ public class TextFlowUtil {
* *
* @param parts the parts to create the text flow from. * @param parts the parts to create the text flow from.
* @param descriptor the font size to use. * @param descriptor the font size to use.
* @param linespacing the line spacing
* @return the created text flow. * @return the created text flow.
*/ */
protected static TextFlow createTextFlow(Iterable<CharSequence> parts, FontDescriptor descriptor) { protected static TextFlow createTextFlow(Iterable<CharSequence> parts, FontDescriptor descriptor, float linespacing) {
final TextFlow result = new TextFlow(); final TextFlow textFlow = new TextFlow();
textFlow.setLineSpacing(linespacing);
boolean bold = false; boolean bold = false;
boolean italic = false; boolean italic = false;
Color color = Color.black; Color color = Color.black;
@ -74,7 +75,7 @@ public class TextFlowUtil {
for (final CharSequence fragment : parts) { for (final CharSequence fragment : parts) {
if (fragment instanceof ControlCharacter) { if (fragment instanceof ControlCharacter) {
if (fragment instanceof ControlCharacters.NewLineControlCharacter) { if (fragment instanceof ControlCharacters.NewLineControlCharacter) {
result.add(new NewLine(descriptor)); textFlow.add(new NewLine(descriptor));
} }
if (fragment instanceof ControlCharacters.BoldControlCharacter) { if (fragment instanceof ControlCharacters.BoldControlCharacter) {
bold = !bold; bold = !bold;
@ -105,7 +106,7 @@ public class TextFlowUtil {
IndentCharacters.IndentCharacter currentIndent = (IndentCharacters.IndentCharacter) fragment; IndentCharacters.IndentCharacter currentIndent = (IndentCharacters.IndentCharacter) fragment;
if (currentIndent.getLevel() == 0) { if (currentIndent.getLevel() == 0) {
indentStack.clear(); indentStack.clear();
result.add(Indent.UNINDENT); textFlow.add(Indent.UNINDENT);
} else { } else {
IndentCharacters.IndentCharacter last = null; IndentCharacters.IndentCharacter last = null;
while (!indentStack.isEmpty() while (!indentStack.isEmpty()
@ -120,7 +121,7 @@ public class TextFlowUtil {
indentStack.push(currentIndent); indentStack.push(currentIndent);
FontDescriptor fontDescriptor = FontDescriptor fontDescriptor =
new FontDescriptor(descriptor.getFont(), descriptor.getSize(), bold, italic); new FontDescriptor(descriptor.getFont(), descriptor.getSize(), bold, italic);
result.add(currentIndent.createNewIndent(fontDescriptor, color)); textFlow.add(currentIndent.createNewIndent(fontDescriptor, color));
} }
} }
} else { } else {
@ -134,16 +135,16 @@ public class TextFlowUtil {
if (annotationMap.isEmpty()) { if (annotationMap.isEmpty()) {
StyledText styledText = new StyledText(fragment.toString(), fontDescriptor, StyledText styledText = new StyledText(fragment.toString(), fontDescriptor,
color, baselineOffset, 0, 0); color, baselineOffset, 0, 0);
result.add(styledText); textFlow.add(styledText);
} else { } else {
AnnotatedStyledText styledText = AnnotatedStyledText styledText =
new AnnotatedStyledText(fragment.toString(), fontDescriptor, new AnnotatedStyledText(fragment.toString(), fontDescriptor,
color, baselineOffset, 0, 0, annotationMap.values()); color, baselineOffset, 0, 0, annotationMap.values());
result.add(styledText); textFlow.add(styledText);
} }
} }
} }
return result; return textFlow;
} }
/** /**

View file

@ -98,7 +98,7 @@ public class CustomRendererTest {
public void afterPage(RenderContext renderContext) { public void afterPage(RenderContext renderContext) {
String content = String.format("Section %s, Page %s", sectionNumber, renderContext.getPageIndex() + 1); String content = String.format("Section %s, Page %s", sectionNumber, renderContext.getPageIndex() + 1);
FontDescriptor fontDescriptor = new FontDescriptor(BaseFont.TIMES, 11); FontDescriptor fontDescriptor = new FontDescriptor(BaseFont.TIMES, 11);
TextFlow text = TextFlowUtil.createTextFlow(content, fontDescriptor); TextFlow text = TextFlowUtil.createTextFlow(content, fontDescriptor, 1.2f);
float offset = renderContext.getPageFormat().getMarginLeft() + float offset = renderContext.getPageFormat().getMarginLeft() +
TextSequenceUtil.getOffset(text, renderContext.getWidth(), Alignment.RIGHT); TextSequenceUtil.getOffset(text, renderContext.getWidth(), Alignment.RIGHT);
text.drawText(renderContext.getContentStream(), new Position( text.drawText(renderContext.getContentStream(), new Position(

View file

@ -48,7 +48,7 @@ public class ListenerTest {
public void afterPage(RenderContext renderContext) { public void afterPage(RenderContext renderContext) {
String content = String.format("Page %s", renderContext.getPageIndex() + 1); String content = String.format("Page %s", renderContext.getPageIndex() + 1);
FontDescriptor fontDescriptor = new FontDescriptor(BaseFont.HELVETICA, 11); FontDescriptor fontDescriptor = new FontDescriptor(BaseFont.HELVETICA, 11);
TextFlow text = TextFlowUtil.createTextFlow(content, fontDescriptor); TextFlow text = TextFlowUtil.createTextFlow(content, fontDescriptor, 1.2f);
float offset = renderContext.getPageFormat().getMarginLeft() float offset = renderContext.getPageFormat().getMarginLeft()
+ TextSequenceUtil.getOffset(text, + TextSequenceUtil.getOffset(text,
renderContext.getWidth(), Alignment.RIGHT); renderContext.getWidth(), Alignment.RIGHT);

View file

@ -54,7 +54,7 @@ public class LowLevelText {
TextFlow text = TextFlowUtil.createTextFlowFromMarkup( TextFlow text = TextFlowUtil.createTextFlowFromMarkup(
"Hello *bold _italic bold-end* italic-end_. Eirmod\ntempor invidunt ut \\*labore", "Hello *bold _italic bold-end* italic-end_. Eirmod\ntempor invidunt ut \\*labore",
new FontDescriptor(BaseFont.TIMES, 11)); new FontDescriptor(BaseFont.TIMES, 11), 1.2f);
text.addText("Spongebob", 11, BaseFont.COURIER); text.addText("Spongebob", 11, BaseFont.COURIER);
text.addText(" is ", 20, BaseFont.HELVETICA); text.addText(" is ", 20, BaseFont.HELVETICA);
text.addText("cool", 7, BaseFont.HELVETICA); text.addText("cool", 7, BaseFont.HELVETICA);

View file

@ -5,7 +5,8 @@
"elements": [ "elements": [
{ {
"type": "image", "type": "image",
"scale": 0.25, "scalex": 0.2,
"scaley": 0.2,
"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==" "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=="
}, },
{ {
@ -25,7 +26,7 @@
"elements": [ "elements": [
{ {
"type": "text", "type": "text",
"value": "Hello World", "value": "Hello World 1",
"size": 24, "size": 24,
"font": "helvetica" "font": "helvetica"
} }
@ -36,7 +37,7 @@
"elements": [ "elements": [
{ {
"type": "text", "type": "text",
"value": "Hello World", "value": "Hello World 2",
"size": 24, "size": 24,
"font": "helvetica" "font": "helvetica"
} }
@ -47,7 +48,7 @@
"elements": [ "elements": [
{ {
"type": "text", "type": "text",
"value": "Hello World", "value": "Hello World 3",
"size": 24, "size": 24,
"font": "helvetica" "font": "helvetica"
} }
@ -61,7 +62,7 @@
"elements": [ "elements": [
{ {
"type": "text", "type": "text",
"value": "Hello World", "value": "Hello World 4",
"size": 16, "size": 16,
"font": "notosans" "font": "notosans"
} }
@ -72,7 +73,7 @@
"elements": [ "elements": [
{ {
"type": "text", "type": "text",
"value": "Hello World", "value": "Hello World 5",
"size": 20, "size": 20,
"font": "notosans" "font": "notosans"
} }
@ -80,7 +81,7 @@
}, },
{ {
"type": "table", "type": "table",
"padding": 10, "padding": "10 10 10 10",
"columnwidths": "50 50 50", "columnwidths": "50 50 50",
"elements": [ "elements": [
{ {
@ -121,7 +122,7 @@
}, },
{ {
"type": "table", "type": "table",
"columnwidths": "80 80 80", "columnwidths": "60 40 20",
"elements": [ "elements": [
{ {
"type": "row", "type": "row",
@ -146,19 +147,19 @@
{ {
"type": "cell", "type": "cell",
"value": "Cell 4", "value": "Cell 4",
"padding": 5, "padding": "5 5 5 5",
"borderwidth": 0.5 "borderwidth": 0.5
}, },
{ {
"type": "cell", "type": "cell",
"value": "Cell 5", "value": "Cell 5",
"padding": 5, "padding": "5 5 5 5",
"borderwidth": 0.5 "borderwidth": 0.5
}, },
{ {
"type": "cell", "type": "cell",
"value": "Cell 6", "value": "Cell 6",
"padding": 5, "padding": "5 5 5 5",
"borderwidth": 0.5 "borderwidth": 0.5
} }
] ]
@ -170,7 +171,7 @@
"elements": [ "elements": [
{ {
"type": "text", "type": "text",
"value": "Hello World", "value": "Hello World 6",
"size": 20, "size": 20,
"font": "notosans" "font": "notosans"
} }