x/y scaling of barcodes, add paragraph and drawable cells

This commit is contained in:
Jörg Prante 2021-12-09 18:20:57 +01:00
parent 6711aa9cec
commit 10a401731f
62 changed files with 1028 additions and 479 deletions

View file

@ -643,7 +643,6 @@ public abstract class AbstractSymbol implements Symbol {
encodeInfo.append("Encoding in Shift-JIS character set\n"); encodeInfo.append("Encoding in Shift-JIS character set\n");
return; return;
} }
/* default */ /* default */
qmarksAfter = eciEncode("UTF8"); qmarksAfter = eciEncode("UTF8");
eciMode = 26; eciMode = 26;
@ -902,8 +901,7 @@ public abstract class AbstractSymbol implements Symbol {
errorLatch = 2; errorLatch = 2;
break; break;
} }
if ( if (((aiValue[i] >= 100) && (aiValue[i] <= 179))
((aiValue[i] >= 100) && (aiValue[i] <= 179))
|| ((aiValue[i] >= 1000) && (aiValue[i] <= 1799)) || ((aiValue[i] >= 1000) && (aiValue[i] <= 1799))
|| ((aiValue[i] >= 200) && (aiValue[i] <= 229)) || ((aiValue[i] >= 200) && (aiValue[i] <= 229))
|| ((aiValue[i] >= 2000) && (aiValue[i] <= 2299)) || ((aiValue[i] >= 2000) && (aiValue[i] <= 2299))
@ -916,8 +914,7 @@ public abstract class AbstractSymbol implements Symbol {
if ((aiValue[i] >= 3100) && (aiValue[i] <= 3699) && dataLength[i] != 6) { if ((aiValue[i] >= 3100) && (aiValue[i] <= 3699) && dataLength[i] != 6) {
errorLatch = 1; errorLatch = 1;
} }
if ( if (((aiValue[i] >= 370) && (aiValue[i] <= 379))
((aiValue[i] >= 370) && (aiValue[i] <= 379))
|| ((aiValue[i] >= 3700) && (aiValue[i] <= 3799))) { || ((aiValue[i] >= 3700) && (aiValue[i] <= 3799))) {
errorLatch = 2; errorLatch = 2;
} }
@ -926,8 +923,7 @@ public abstract class AbstractSymbol implements Symbol {
errorLatch = 1; errorLatch = 1;
} }
} }
if ( if (((aiValue[i] >= 4100) && (aiValue[i] <= 4199))
((aiValue[i] >= 4100) && (aiValue[i] <= 4199))
|| ((aiValue[i] >= 700) && (aiValue[i] <= 703)) || ((aiValue[i] >= 700) && (aiValue[i] <= 703))
|| ((aiValue[i] >= 800) && (aiValue[i] <= 810)) || ((aiValue[i] >= 800) && (aiValue[i] <= 810))
|| ((aiValue[i] >= 900) && (aiValue[i] <= 999)) || ((aiValue[i] >= 900) && (aiValue[i] <= 999))
@ -945,7 +941,6 @@ public abstract class AbstractSymbol implements Symbol {
return ""; return "";
} }
} }
aiLatch = false;
for (i = 0; i < srcLen; i++) { for (i = 0; i < srcLen; i++) {
if ((source.charAt(i) != '[') && (source.charAt(i) != ']')) { if ((source.charAt(i) != '[') && (source.charAt(i) != ']')) {
reduced.append(source.charAt(i)); reduced.append(source.charAt(i));

View file

@ -130,7 +130,7 @@ public class Code3Of9 extends AbstractSymbol {
} }
pattern = new String[]{dest.toString()}; pattern = new String[]{dest.toString()};
rowCount = 1; rowCount = 1;
rowHeight = new int[]{-1}; rowHeight = new int[]{defaultHeight};
plotSymbol(); plotSymbol();
return true; return true;
} }

View file

@ -42,21 +42,17 @@ public class Code3Of9Extended extends AbstractSymbol {
int l = content.length(); int l = content.length();
int asciicode; int asciicode;
Code3Of9 c = new Code3Of9(); Code3Of9 c = new Code3Of9();
if (checkOption == CheckDigit.MOD43) { if (checkOption == CheckDigit.MOD43) {
c.setCheckDigit(Code3Of9.CheckDigit.MOD43); c.setCheckDigit(Code3Of9.CheckDigit.MOD43);
} }
if (!content.matches("[\u0000-\u007F]+")) { if (!content.matches("[\u0000-\u007F]+")) {
errorMsg.append("Invalid characters in input data"); errorMsg.append("Invalid characters in input data");
return false; return false;
} }
for (int i = 0; i < l; i++) { for (int i = 0; i < l; i++) {
asciicode = content.charAt(i); asciicode = content.charAt(i);
buffer.append(ECode39[asciicode]); buffer.append(ECode39[asciicode]);
} }
try { try {
c.setContent(buffer.toString()); c.setContent(buffer.toString());
} catch (Exception e) { } catch (Exception e) {
@ -68,7 +64,7 @@ public class Code3Of9Extended extends AbstractSymbol {
pattern[0] = c.pattern[0]; pattern[0] = c.pattern[0];
rowCount = 1; rowCount = 1;
rowHeight = new int[1]; rowHeight = new int[1];
rowHeight[0] = -1; rowHeight[0] = defaultHeight;
plotSymbol(); plotSymbol();
return true; return true;
} }

View file

@ -457,7 +457,7 @@ public class Pdf417 extends AbstractSymbol {
* Creates a new PDF417 symbol instance. * Creates a new PDF417 symbol instance.
*/ */
public Pdf417() { public Pdf417() {
setBarHeight(3); defaultHeight = 3;
} }
private static EncodingMode chooseMode(int codeascii) { private static EncodingMode chooseMode(int codeascii) {
@ -589,16 +589,6 @@ public class Pdf417 extends AbstractSymbol {
} }
} }
/**
* Sets the default bar height (height of a single row) for this symbol (default value is <code>3</code>).
*
* @param barHeight the default bar height for this symbol
*/
@Override
public void setBarHeight(int barHeight) {
super.setBarHeight(barHeight);
}
/** /**
* Returns the number of data columns used by this symbol, or {@code null} * Returns the number of data columns used by this symbol, or {@code null}
* if the number of data columns has not been set. * if the number of data columns has not been set.

View file

@ -31,9 +31,14 @@ public class BarcodeGraphicsRenderer {
private final Rectangle rectangle; private final Rectangle rectangle;
/** /**
* The scaling factor. * The scaling factor for X dimension.
*/ */
private final double scalingFactor; private final double scalingFactorX;
/**
* The scaling factor for Y dimension.
*/
private final double scalingFactorY;
/** /**
* The paper (background) color. * The paper (background) color.
@ -54,7 +59,8 @@ public class BarcodeGraphicsRenderer {
* *
* @param g2d the graphics to render to * @param g2d the graphics to render to
* @param rectangle the visible rectangle * @param rectangle the visible rectangle
* @param scalingFactor the scaling factor to apply * @param scalingFactorX the scaling factor to apply for x dimension
* @param scalingFactorY the scaling factor to apply for y dimension
* @param background the paper (background) color * @param background the paper (background) color
* @param foreground the ink (foreground) color * @param foreground the ink (foreground) color
* @param antialias if true give anti alias hint * @param antialias if true give anti alias hint
@ -62,14 +68,16 @@ public class BarcodeGraphicsRenderer {
*/ */
public BarcodeGraphicsRenderer(Graphics2D g2d, public BarcodeGraphicsRenderer(Graphics2D g2d,
Rectangle rectangle, Rectangle rectangle,
double scalingFactor, double scalingFactorX,
double scalingFactorY,
Color background, Color background,
Color foreground, Color foreground,
boolean antialias, boolean antialias,
boolean transparentBackground) { boolean transparentBackground) {
this.g2d = g2d; this.g2d = g2d;
this.rectangle = rectangle; this.rectangle = rectangle;
this.scalingFactor = scalingFactor; this.scalingFactorX = scalingFactorX;
this.scalingFactorY = scalingFactorY;
this.background = background; this.background = background;
this.foreground = foreground; this.foreground = foreground;
this.antialias = antialias; this.antialias = antialias;
@ -85,8 +93,8 @@ public class BarcodeGraphicsRenderer {
} else { } else {
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
} }
double marginX = symbol.getQuietZoneHorizontal() * scalingFactor; double marginX = symbol.getQuietZoneHorizontal() * scalingFactorX;
double marginY = symbol.getQuietZoneVertical() * scalingFactor; double marginY = symbol.getQuietZoneVertical() * scalingFactorY;
g2d.setBackground(background); g2d.setBackground(background);
if (!transparentBackground) { if (!transparentBackground) {
g2d.setColor(background); g2d.setColor(background);
@ -96,10 +104,10 @@ public class BarcodeGraphicsRenderer {
g2d.setColor(foreground); g2d.setColor(foreground);
} }
for (Rectangle2D.Double rect : symbol.getRectangles()) { for (Rectangle2D.Double rect : symbol.getRectangles()) {
double x = rect.x * scalingFactor + marginX; double x = rect.x * scalingFactorX + marginX;
double y = rect.y * scalingFactor + marginY; double y = rect.y * scalingFactorY + marginY;
double w = rect.width * scalingFactor; double w = rect.width * scalingFactorX;
double h = rect.height * scalingFactor; double h = rect.height * scalingFactorY;
Path2D path = new Path2D.Double(); Path2D path = new Path2D.Double();
path.moveTo(x, y); path.moveTo(x, y);
path.lineTo(x + w, y); path.lineTo(x + w, y);
@ -111,24 +119,24 @@ public class BarcodeGraphicsRenderer {
if (symbol.getHumanReadableLocation() != HumanReadableLocation.NONE) { if (symbol.getHumanReadableLocation() != HumanReadableLocation.NONE) {
Map<TextAttribute, Object> attributes = new HashMap<>(); Map<TextAttribute, Object> attributes = new HashMap<>();
attributes.put(TextAttribute.TRACKING, 0); attributes.put(TextAttribute.TRACKING, 0);
Font f = new Font(symbol.getFontName(), Font.PLAIN, (int) (symbol.getFontSize() * scalingFactor)).deriveFont(attributes); Font f = new Font(symbol.getFontName(), Font.PLAIN, (int) (symbol.getFontSize() * Math.min(scalingFactorX, scalingFactorY))).deriveFont(attributes);
Font oldFont = g2d.getFont(); Font oldFont = g2d.getFont();
g2d.setFont(f); g2d.setFont(f);
FontMetrics fm = g2d.getFontMetrics(); FontMetrics fm = g2d.getFontMetrics();
for (TextBox text : symbol.getTexts()) { for (TextBox text : symbol.getTexts()) {
Rectangle2D bounds = fm.getStringBounds(text.text, g2d); Rectangle2D bounds = fm.getStringBounds(text.text, g2d);
double x = (text.x * scalingFactor) - (bounds.getWidth() / 2) + marginX; double x = (text.x * scalingFactorX) - (bounds.getWidth() / 2) + marginX;
double y = (text.y * scalingFactor) + marginY; double y = (text.y * scalingFactorY) + marginY;
g2d.drawString(text.text, (float) x, (float) y); g2d.drawString(text.text, (float) x, (float) y);
} }
g2d.setFont(oldFont); g2d.setFont(oldFont);
} }
for (Hexagon hexagon : symbol.getHexagons()) { for (Hexagon hexagon : symbol.getHexagons()) {
Path2D path = new Path2D.Double(); Path2D path = new Path2D.Double();
path.moveTo(hexagon.pointX[0] * scalingFactor + marginX, hexagon.pointY[0] * scalingFactor + marginY); path.moveTo(hexagon.pointX[0] * scalingFactorX + marginX, hexagon.pointY[0] * scalingFactorY + marginY);
for(int i = 1; i < 6; ++i) { for(int i = 1; i < 6; ++i) {
double x = hexagon.pointX[i] * scalingFactor + marginX; double x = hexagon.pointX[i] * scalingFactorX + marginX;
double y = hexagon.pointY[i] * scalingFactor + marginY; double y = hexagon.pointY[i] * scalingFactorY + marginY;
path.lineTo(x, y); path.lineTo(x, y);
} }
path.closePath(); path.closePath();
@ -137,10 +145,10 @@ public class BarcodeGraphicsRenderer {
List<Ellipse2D.Double> targets = symbol.getTarget(); List<Ellipse2D.Double> targets = symbol.getTarget();
for (int i = 0; i < targets.size(); i++) { for (int i = 0; i < targets.size(); i++) {
Ellipse2D.Double ellipse = targets.get(i); Ellipse2D.Double ellipse = targets.get(i);
double x = ellipse.x * scalingFactor + marginX; double x = ellipse.x * scalingFactorX + marginX;
double y = ellipse.y * scalingFactor + marginY; double y = ellipse.y * scalingFactorY + marginY;
double w = ellipse.width * scalingFactor; double w = ellipse.width * scalingFactorX;
double h = ellipse.height * scalingFactor; double h = ellipse.height * scalingFactorY;
if ((i & 1) == 0) { if ((i & 1) == 0) {
g2d.setColor(foreground); g2d.setColor(foreground);
} else { } else {

View file

@ -219,7 +219,7 @@ public class SymbolTest {
// make sure the barcode images match // make sure the barcode images match
if (pngFile.exists()) { if (pngFile.exists()) {
BufferedImage expected = ImageIO.read(pngFile); BufferedImage expected = ImageIO.read(pngFile);
BufferedImage actual = draw(symbol, 10.0d); BufferedImage actual = draw(symbol, 10.0d, 10.0d);
if (expected != null && actual != null) { if (expected != null && actual != null) {
assertEqualImage(pngFile.getName(), expected, actual); assertEqualImage(pngFile.getName(), expected, actual);
} }
@ -358,20 +358,18 @@ public class SymbolTest {
* @throws IOException if there is any I/O error * @throws IOException if there is any I/O error
*/ */
private void generateCodewordsExpectationFile(AbstractSymbol symbol) throws IOException { private void generateCodewordsExpectationFile(AbstractSymbol symbol) throws IOException {
//if (!codewordsFile.exists()) { PrintWriter writer = new PrintWriter(codewordsFile);
PrintWriter writer = new PrintWriter(codewordsFile); try {
try { int[] codewords = symbol.getCodewords();
int[] codewords = symbol.getCodewords(); for (int codeword : codewords) {
for (int codeword : codewords) { writer.println(codeword);
writer.println(codeword);
}
} catch (UnsupportedOperationException e) {
for (String pattern : symbol.pattern) {
writer.println(pattern);
}
} }
writer.close(); } catch (UnsupportedOperationException e) {
//} for (String pattern : symbol.pattern) {
writer.println(pattern);
}
}
writer.close();
} }
/** /**
@ -381,7 +379,7 @@ public class SymbolTest {
* @throws IOException if there is any I/O error * @throws IOException if there is any I/O error
*/ */
private void generatePngExpectationFile(AbstractSymbol symbol) throws IOException { private void generatePngExpectationFile(AbstractSymbol symbol) throws IOException {
BufferedImage img = draw(symbol, 10.0d); BufferedImage img = draw(symbol, 10.0d, 10.0d);
if (img != null) { if (img != null) {
ImageIO.write(img, "png", pngFile); ImageIO.write(img, "png", pngFile);
} }
@ -408,15 +406,15 @@ public class SymbolTest {
* @param symbol the symbol to draw * @param symbol the symbol to draw
* @return the resultant image * @return the resultant image
*/ */
private static BufferedImage draw(AbstractSymbol symbol, double scalingFactor) { private static BufferedImage draw(AbstractSymbol symbol, double scalingFactorX, double scalingFactorY) {
int width = (int) (symbol.getWidth() * scalingFactor); int width = (int) (symbol.getWidth() * scalingFactorX);
int height = (int) (symbol.getHeight() * scalingFactor); int height = (int) (symbol.getHeight() * scalingFactorY);
if (width > 0 && height > 0) { if (width > 0 && height > 0) {
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY); BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
Rectangle rectangle = new Rectangle(0, 0, img.getWidth(), img.getHeight()); Rectangle rectangle = new Rectangle(0, 0, img.getWidth(), img.getHeight());
Graphics2D g2d = img.createGraphics(); Graphics2D g2d = img.createGraphics();
BarcodeGraphicsRenderer renderer = new BarcodeGraphicsRenderer(g2d, rectangle, BarcodeGraphicsRenderer renderer = new BarcodeGraphicsRenderer(g2d, rectangle,
scalingFactor, Color.WHITE, Color.BLACK, true, false); scalingFactorX, scalingFactorY, Color.WHITE, Color.BLACK, true, false);
renderer.render(symbol); renderer.render(symbol);
g2d.dispose(); g2d.dispose();
return img; return img;

View file

@ -21,12 +21,11 @@ public class Code39Test {
Code3Of9 code3Of9 = new Code3Of9(); Code3Of9 code3Of9 = new Code3Of9();
code3Of9.setContent("20180123456"); code3Of9.setContent("20180123456");
code3Of9.setHumanReadableLocation(HumanReadableLocation.BOTTOM); code3Of9.setHumanReadableLocation(HumanReadableLocation.BOTTOM);
// pixels = (mm * dpi) / 25.4 double scalingFactor = 3.0d;
double scalingFactor = (1.0d * 72.0d) / 25.4;
int width = (int) (code3Of9.getWidth() * scalingFactor); int width = (int) (code3Of9.getWidth() * scalingFactor);
int height = (int) (code3Of9.getHeight() * scalingFactor); int height = (int) (code3Of9.getHeight() * scalingFactor);
BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY); BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
BarcodeGraphicsRenderer renderer = createRenderer(bufferedImage, scalingFactor); BarcodeGraphicsRenderer renderer = createRenderer(bufferedImage, scalingFactor, scalingFactor);
renderer.render(code3Of9); renderer.render(code3Of9);
renderer.close(); renderer.close();
OutputStream outputStream = Files.newOutputStream(Paths.get("build/barcode1.png")); OutputStream outputStream = Files.newOutputStream(Paths.get("build/barcode1.png"));
@ -36,13 +35,15 @@ public class Code39Test {
@Test @Test
public void createBarcode2() throws IOException { public void createBarcode2() throws IOException {
int width = 512;
int height = 150;
Code3Of9 code3Of9 = new Code3Of9(); Code3Of9 code3Of9 = new Code3Of9();
//code3Of9.setContent("20180123456"); code3Of9.setContent("20180123456");
code3Of9.setContent("11111111111"); code3Of9.setHumanReadableLocation(HumanReadableLocation.BOTTOM);
double scalingFactorX = 6.0d;
double scalingFactorY = 3.0d;
int width = (int) (code3Of9.getWidth() * scalingFactorX);
int height = (int) (code3Of9.getHeight() * scalingFactorY);
BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY); BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
BarcodeGraphicsRenderer renderer = createRenderer(bufferedImage, 3.0d); BarcodeGraphicsRenderer renderer = createRenderer(bufferedImage, scalingFactorX, scalingFactorY);
renderer.render(code3Of9); renderer.render(code3Of9);
renderer.close(); renderer.close();
OutputStream outputStream = Files.newOutputStream(Paths.get("build/barcode2.png")); OutputStream outputStream = Files.newOutputStream(Paths.get("build/barcode2.png"));
@ -50,9 +51,26 @@ public class Code39Test {
outputStream.close(); outputStream.close();
} }
private BarcodeGraphicsRenderer createRenderer(BufferedImage bufferedImage, double scalingFactor) { @Test
public void createBarcode3() throws IOException {
int width = 512;
int height = 150;
Code3Of9 code3Of9 = new Code3Of9();
code3Of9.setContent("11111111111");
double scalingFactor = 3.0d;
BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
BarcodeGraphicsRenderer renderer = createRenderer(bufferedImage, scalingFactor, scalingFactor);
renderer.render(code3Of9);
renderer.close();
OutputStream outputStream = Files.newOutputStream(Paths.get("build/barcode3.png"));
ImageIO.write(bufferedImage, "png", outputStream);
outputStream.close();
}
private BarcodeGraphicsRenderer createRenderer(BufferedImage bufferedImage, double scalingFactorX, double scalingFactorY) {
Graphics2D g2d = bufferedImage.createGraphics(); Graphics2D g2d = bufferedImage.createGraphics();
Rectangle rectangle = new Rectangle(0, 0, bufferedImage.getWidth(), bufferedImage.getHeight()); Rectangle rectangle = new Rectangle(0, 0, bufferedImage.getWidth(), bufferedImage.getHeight());
return new BarcodeGraphicsRenderer(g2d, rectangle, scalingFactor, Color.WHITE, Color.BLACK, false, false); return new BarcodeGraphicsRenderer(g2d, rectangle, scalingFactorX, scalingFactorY,
Color.WHITE, Color.BLACK, false, false);
} }
} }

View file

@ -87,20 +87,20 @@ public class EPSRendererTest {
} }
private void test(AbstractSymbol symbol, private void test(AbstractSymbol symbol,
double magnification, double scale,
Color paper, Color paper,
Color ink, Color ink,
int margin, int margin,
String expectationFile) throws IOException { String expectationFile) throws IOException {
symbol.setQuietZoneHorizontal(margin); symbol.setQuietZoneHorizontal(margin);
symbol.setQuietZoneVertical(margin); symbol.setQuietZoneVertical(margin);
int width = (int) (symbol.getWidth() * magnification); int width = (int) (symbol.getWidth() * scale);
int height = (int) (symbol.getHeight() * magnification); int height = (int) (symbol.getHeight() * scale);
Rectangle rectangle = new Rectangle(0, 0, width, height); Rectangle rectangle = new Rectangle(0, 0, width, height);
EPSGraphics2D epsGraphics2D = new EPSGraphics2D(rectangle); EPSGraphics2D epsGraphics2D = new EPSGraphics2D(rectangle);
epsGraphics2D.setFont(Font.decode("Dialog")); epsGraphics2D.setFont(Font.decode("Dialog"));
BarcodeGraphicsRenderer barcodeGraphicsRenderer = new BarcodeGraphicsRenderer(epsGraphics2D, rectangle, BarcodeGraphicsRenderer barcodeGraphicsRenderer = new BarcodeGraphicsRenderer(epsGraphics2D, rectangle,
magnification, paper, ink, false, false); scale, scale, paper, ink, false, false);
barcodeGraphicsRenderer.render(symbol); barcodeGraphicsRenderer.render(symbol);
barcodeGraphicsRenderer.close(); barcodeGraphicsRenderer.close();
byte[] actualBytes = epsGraphics2D.getBytes(); byte[] actualBytes = epsGraphics2D.getBytes();

View file

@ -87,20 +87,20 @@ public class PDFRendererTest {
} }
private void test(AbstractSymbol symbol, private void test(AbstractSymbol symbol,
double magnification, double scale,
Color paper, Color paper,
Color ink, Color ink,
int margin, int margin,
String expectationFile) throws IOException { String expectationFile) throws IOException {
symbol.setQuietZoneHorizontal(margin); symbol.setQuietZoneHorizontal(margin);
symbol.setQuietZoneVertical(margin); symbol.setQuietZoneVertical(margin);
int width = (int) (symbol.getWidth() * magnification); int width = (int) (symbol.getWidth() * scale);
int height = (int) (symbol.getHeight() * magnification); int height = (int) (symbol.getHeight() * scale);
Rectangle rectangle = new Rectangle(0, 0, width, height); Rectangle rectangle = new Rectangle(0, 0, width, height);
PDFGraphics2D pdfGraphics2D = new PDFGraphics2D(rectangle); PDFGraphics2D pdfGraphics2D = new PDFGraphics2D(rectangle);
pdfGraphics2D.setFont(Font.decode("Dialog")); // Helvetica pdfGraphics2D.setFont(Font.decode("Dialog")); // Helvetica
BarcodeGraphicsRenderer barcodeGraphicsRenderer = new BarcodeGraphicsRenderer(pdfGraphics2D, BarcodeGraphicsRenderer barcodeGraphicsRenderer = new BarcodeGraphicsRenderer(pdfGraphics2D,
rectangle, magnification, paper, ink, false, false); rectangle, scale, scale, paper, ink, false, false);
barcodeGraphicsRenderer.render(symbol); barcodeGraphicsRenderer.render(symbol);
barcodeGraphicsRenderer.close(); barcodeGraphicsRenderer.close();
byte[] actualBytes = pdfGraphics2D.getBytes(); byte[] actualBytes = pdfGraphics2D.getBytes();

View file

@ -87,20 +87,20 @@ public class SVGRendererTest {
} }
private void test(AbstractSymbol symbol, private void test(AbstractSymbol symbol,
double magnification, double scale,
Color paper, Color paper,
Color ink, Color ink,
int margin, int margin,
String expectationFile) throws IOException { String expectationFile) throws IOException {
symbol.setQuietZoneHorizontal(margin); symbol.setQuietZoneHorizontal(margin);
symbol.setQuietZoneVertical(margin); symbol.setQuietZoneVertical(margin);
int width = (int) (symbol.getWidth() * magnification); int width = (int) (symbol.getWidth() * scale);
int height = (int) (symbol.getHeight() * magnification); int height = (int) (symbol.getHeight() * scale);
Rectangle rectangle = new Rectangle(0, 0, width, height); Rectangle rectangle = new Rectangle(0, 0, width, height);
SVGGraphics2D svgGraphics2D = new SVGGraphics2D(rectangle); SVGGraphics2D svgGraphics2D = new SVGGraphics2D(rectangle);
svgGraphics2D.setFont(Font.decode("Dialog")); svgGraphics2D.setFont(Font.decode("Dialog"));
BarcodeGraphicsRenderer barcodeGraphicsRenderer = new BarcodeGraphicsRenderer(svgGraphics2D, BarcodeGraphicsRenderer barcodeGraphicsRenderer = new BarcodeGraphicsRenderer(svgGraphics2D,
rectangle, magnification, paper, ink, false, false); rectangle, scale, scale, paper, ink, false, false);
barcodeGraphicsRenderer.render(symbol); barcodeGraphicsRenderer.render(symbol);
barcodeGraphicsRenderer.close(); barcodeGraphicsRenderer.close();
byte[] actualBytes = svgGraphics2D.getBytes(); byte[] actualBytes = svgGraphics2D.getBytes();

View file

@ -17,31 +17,40 @@ public class BarcodeElement implements Element, Drawable, Dividable, WidthRespec
private final Symbol symbol; private final Symbol symbol;
private float width; private Float width;
private float height; private Float height;
private float scale; private float scaleX = 1.0f;
private float scaleY = 1.0f;
private float maxWidth = -1; private float maxWidth = -1;
private Position absolutePosition; private Position absolutePosition;
private Color color = Color.BLACK;
private Color backgroundColor = Color.WHITE;
public BarcodeElement(Symbol symbol) { public BarcodeElement(Symbol symbol) {
this.symbol = symbol; this.symbol = symbol;
setWidth(symbol.getWidth());
setHeight(symbol.getHeight());
setScale(1.0f);
} }
public void setScale(float scale) { public void setScaleX(float scaleX) {
this.scale = scale; this.scaleX = scaleX;
setWidth(width * scale);
setHeight(height * scale);
} }
public float getScale() { public float getScaleX() {
return scale; return scaleX;
}
public void setScaleY(float scaleY) {
this.scaleY = scaleY;
}
public float getScaleY() {
return scaleY;
} }
public void setWidth(float width) { public void setWidth(float width) {
@ -50,7 +59,7 @@ public class BarcodeElement implements Element, Drawable, Dividable, WidthRespec
@Override @Override
public float getWidth() throws IOException { public float getWidth() throws IOException {
return width; return width != null ? width * scaleX : symbol.getWidth() * scaleX;
} }
public void setHeight(float height) { public void setHeight(float height) {
@ -59,7 +68,7 @@ public class BarcodeElement implements Element, Drawable, Dividable, WidthRespec
@Override @Override
public float getHeight() throws IOException { public float getHeight() throws IOException {
return height; return height != null ? height * scaleY : symbol.getHeight() * scaleY;
} }
@Override @Override
@ -95,14 +104,22 @@ public class BarcodeElement implements Element, Drawable, Dividable, WidthRespec
this.absolutePosition = absolutePosition; this.absolutePosition = absolutePosition;
} }
public void setColor(Color color) {
this.color = color;
}
public void setBackgroundColor(Color backgroundColor) {
this.backgroundColor = backgroundColor;
}
@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 {
float x = upperLeft.getX(); float x = upperLeft.getX();
float y = upperLeft.getY() - height; float y = upperLeft.getY() - getHeight();
PdfBoxGraphics2D pdfBoxGraphics2D = new PdfBoxGraphics2D(pdDocument, width, height); PdfBoxGraphics2D pdfBoxGraphics2D = new PdfBoxGraphics2D(pdDocument, getWidth(), getHeight());
BarcodeGraphicsRenderer renderer = new BarcodeGraphicsRenderer(pdfBoxGraphics2D, null, 1.0d, BarcodeGraphicsRenderer renderer = new BarcodeGraphicsRenderer(pdfBoxGraphics2D, null, scaleX, scaleY,
Color.WHITE, Color.BLACK, false, false); backgroundColor, color, false, false);
renderer.render(symbol); renderer.render(symbol);
renderer.close(); renderer.close();
PDFormXObject xFormObject = pdfBoxGraphics2D.getXFormObject(); PDFormXObject xFormObject = pdfBoxGraphics2D.getXFormObject();

View file

@ -35,7 +35,7 @@ public class Document implements Element, Closeable, RenderListener {
private final List<RenderListener> renderListener = new ArrayList<>(); private final List<RenderListener> renderListener = new ArrayList<>();
private final PageFormat pageFormat; private PageFormat pageFormat;
private final PDDocument pdDocument; private final PDDocument pdDocument;
@ -58,13 +58,6 @@ public class Document implements Element, Closeable, RenderListener {
this(pageFormat, true); this(pageFormat, true);
} }
public Document(PageFormat pageFormat, boolean memory) {
this.pageFormat = pageFormat;
this.pdDocument = new PDDocument(memory ?
MemoryUsageSetting.setupMainMemoryOnly() : MemoryUsageSetting.setupTempFileOnly());
this.pdDocumentInformation = new PDDocumentInformation();
}
/** /**
* Creates a Document in A4 with orientation portrait and the given margins. * Creates a Document in A4 with orientation portrait and the given margins.
* By default, a {@link VerticalLayout} is used. * By default, a {@link VerticalLayout} is used.
@ -88,6 +81,16 @@ public class Document implements Element, Closeable, RenderListener {
this(PageFormat.builder().margins(marginLeft, marginRight, marginTop, marginBottom).build(), memory); this(PageFormat.builder().margins(marginLeft, marginRight, marginTop, marginBottom).build(), memory);
} }
public Document(PageFormat pageFormat, boolean memory) {
this.pdDocument = new PDDocument(memory ? MemoryUsageSetting.setupMainMemoryOnly() : MemoryUsageSetting.setupTempFileOnly());
this.pdDocumentInformation = new PDDocumentInformation();
setPageFormat(pageFormat);
}
public void setPageFormat(PageFormat pageFormat) {
this.pageFormat = pageFormat;
}
public PDDocument getPdDocument() { public PDDocument getPdDocument() {
return pdDocument; return pdDocument;
} }
@ -153,8 +156,9 @@ public class Document implements Element, Closeable, RenderListener {
* @param element the element to add * @param element the element to add
* @param layoutHint the hint for the {@link Layout}. * @param layoutHint the hint for the {@link Layout}.
*/ */
public void add(Element element, LayoutHint layoutHint) { public Element add(Element element, LayoutHint layoutHint) {
elements.add(Map.entry(element, layoutHint)); elements.add(Map.entry(element, layoutHint));
return this;
} }
/** /**

View file

@ -1,5 +1,7 @@
package org.xbib.graphics.pdfbox.layout.elements; package org.xbib.graphics.pdfbox.layout.elements;
import org.xbib.graphics.pdfbox.layout.elements.render.LayoutHint;
/** /**
* Base (tagging) interface for elements in a {@link Document}. * Base (tagging) interface for elements in a {@link Document}.
*/ */
@ -8,4 +10,8 @@ public interface Element {
default Element add(Element element) { default Element add(Element element) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
default Element add(Element element, LayoutHint layoutHint) {
throw new UnsupportedOperationException();
}
} }

View file

@ -6,13 +6,13 @@ import org.xbib.graphics.pdfbox.layout.elements.render.VerticalLayout;
import java.util.Locale; import java.util.Locale;
import java.util.Objects; import java.util.Objects;
import static org.xbib.graphics.pdfbox.layout.util.PdfUtil.MM_TO_UNITS;
/** /**
* Defines the size and orientation of a page. The default is A4 portrait without margins. * Defines the size and orientation of a page. The default is A4 portrait without margins.
*/ */
public class PageFormat implements Element { public class PageFormat implements Element {
public static final float MM_TO_UNITS = 1.0f / 25.4f * 72.0f;
public static final PDRectangle A0 = new PDRectangle(Math.round(841f * MM_TO_UNITS), Math.round(1189f * MM_TO_UNITS)); public static final PDRectangle A0 = new PDRectangle(Math.round(841f * MM_TO_UNITS), Math.round(1189f * MM_TO_UNITS));
public static final PDRectangle A1 = new PDRectangle(Math.round(594f * MM_TO_UNITS), Math.round(841f * MM_TO_UNITS)); public static final PDRectangle A1 = new PDRectangle(Math.round(594f * MM_TO_UNITS), Math.round(841f * MM_TO_UNITS));

View file

@ -6,7 +6,7 @@ import org.xbib.graphics.pdfbox.layout.text.Alignment;
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.TextFlow; import org.xbib.graphics.pdfbox.layout.text.TextFlow;
import org.xbib.graphics.pdfbox.layout.text.TextSequenceUtil; import org.xbib.graphics.pdfbox.layout.util.TextSequenceUtil;
import org.xbib.graphics.pdfbox.layout.text.WidthRespecting; import org.xbib.graphics.pdfbox.layout.text.WidthRespecting;
/** /**

View file

@ -29,6 +29,9 @@ public class TableElement implements Element, Drawable, Dividable {
if (element instanceof Row.Builder) { if (element instanceof Row.Builder) {
Row row = ((Row.Builder) element).build(); Row row = ((Row.Builder) element).build();
table.addRow(row); table.addRow(row);
} else if (element instanceof HorizontalRuler) {
Row row = Row.builder().add(element).build();
table.addRow(row);
} else { } else {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }

View file

@ -13,20 +13,22 @@ import java.io.IOException;
*/ */
public class ColumnLayout extends VerticalLayout { public class ColumnLayout extends VerticalLayout {
private final int columnCount; private int columnCount = 1;
private final float columnSpacing; private float columnSpacing = 0f;
private int columnIndex = 0; private int columnIndex = 0;
private Float offsetY = null; private Float offsetY = null;
public ColumnLayout(int columnCount) { public ColumnLayout setColumnCount(int columnCount) {
this(columnCount, 0); this.columnCount = columnCount;
return this;
} }
public ColumnLayout(int columnCount, float columnSpacing) { public ColumnLayout setColumnSpacing(float columnSpacing) {
this.columnCount = columnCount;
this.columnSpacing = columnSpacing; this.columnSpacing = columnSpacing;
return this;
} }
@Override @Override
@ -36,26 +38,24 @@ public class ColumnLayout extends VerticalLayout {
} }
/** /**
* Flips to the next column * Flips to the next column.
* @param renderContext render context
*/ */
@Override @Override
protected void turnPage(final RenderContext renderContext) protected void turnPage(RenderContext renderContext) throws IOException {
throws IOException {
if (++columnIndex >= columnCount) { if (++columnIndex >= columnCount) {
renderContext.newPage(); renderContext.newPage();
columnIndex = 0; columnIndex = 0;
offsetY = 0f; offsetY = 0f;
} else { } else {
float nextColumnX = (getTargetWidth(renderContext) + columnSpacing) float nextColumnX = (getTargetWidth(renderContext) + columnSpacing) * columnIndex;
* columnIndex;
renderContext.resetPositionToUpperLeft(); renderContext.resetPositionToUpperLeft();
renderContext.movePositionBy(nextColumnX, -offsetY); renderContext.movePositionBy(nextColumnX, -offsetY);
} }
} }
@Override @Override
public boolean render(RenderContext renderContext, Element element, public boolean render(RenderContext renderContext, Element element, LayoutHint layoutHint) throws IOException {
LayoutHint layoutHint) throws IOException {
if (element == ControlElement.NEWPAGE) { if (element == ControlElement.NEWPAGE) {
renderContext.newPage(); renderContext.newPage();
return true; return true;
@ -68,8 +68,7 @@ public class ColumnLayout extends VerticalLayout {
} }
@Override @Override
public void render(RenderContext renderContext, Drawable drawable, public void render(RenderContext renderContext, Drawable drawable, LayoutHint layoutHint) throws IOException {
LayoutHint layoutHint) throws IOException {
if (offsetY == null) { if (offsetY == null) {
offsetY = renderContext.getUpperLeft().getY() - renderContext.getCurrentPosition().getY(); offsetY = renderContext.getUpperLeft().getY() - renderContext.getCurrentPosition().getY();
} }
@ -84,5 +83,4 @@ public class ColumnLayout extends VerticalLayout {
} }
return renderContext.getCurrentPosition().getY() == topPosition; return renderContext.getCurrentPosition().getY() == topPosition;
} }
} }

View file

@ -8,18 +8,17 @@ import org.xbib.graphics.pdfbox.layout.text.Alignment;
*/ */
public class ColumnLayoutHint extends VerticalLayoutHint { public class ColumnLayoutHint extends VerticalLayoutHint {
public final static ColumnLayoutHint LEFT = new ColumnLayoutHint( public final static ColumnLayoutHint LEFT = new ColumnLayoutHint(Alignment.LEFT);
Alignment.LEFT);
public final static ColumnLayoutHint CENTER = new ColumnLayoutHint( public final static ColumnLayoutHint CENTER = new ColumnLayoutHint(Alignment.CENTER);
Alignment.CENTER);
public final static ColumnLayoutHint RIGHT = new ColumnLayoutHint( public final static ColumnLayoutHint RIGHT = new ColumnLayoutHint(Alignment.RIGHT);
Alignment.RIGHT);
/** /**
* Creates a layout hint with {@link Alignment#LEFT left alignment}. * Creates a layout hint with {@link Alignment#LEFT left alignment}.
*/ */
public ColumnLayoutHint() { public ColumnLayoutHint() {
super(); super(Alignment.LEFT);
} }
/** /**
@ -40,8 +39,7 @@ public class ColumnLayoutHint extends VerticalLayoutHint {
* @param marginTop the top alignment. * @param marginTop the top alignment.
* @param marginBottom the bottom alignment. * @param marginBottom the bottom alignment.
*/ */
public ColumnLayoutHint(Alignment alignment, float marginLeft, public ColumnLayoutHint(Alignment alignment, float marginLeft, float marginRight, float marginTop, float marginBottom) {
float marginRight, float marginTop, float marginBottom) {
super(alignment, marginLeft, marginRight, marginTop, marginBottom); super(alignment, marginLeft, marginRight, marginTop, marginBottom);
} }
@ -56,14 +54,11 @@ public class ColumnLayoutHint extends VerticalLayoutHint {
* @param resetY if <code>true</code>, the y coordinate will be reset to the * @param resetY if <code>true</code>, the y coordinate will be reset to the
* point before layouting the element. * point before layouting the element.
*/ */
public ColumnLayoutHint(Alignment alignment, float marginLeft, public ColumnLayoutHint(Alignment alignment, float marginLeft, float marginRight, float marginTop, float marginBottom,
float marginRight, float marginTop, float marginBottom,
boolean resetY) { boolean resetY) {
super(alignment, marginLeft, marginRight, marginTop, marginBottom, super(alignment, marginLeft, marginRight, marginTop, marginBottom, resetY);
resetY);
} }
/** /**
* @return a {@link VerticalLayoutHintBuilder} for creating a * @return a {@link VerticalLayoutHintBuilder} for creating a
* {@link VerticalLayoutHint} using a fluent API. * {@link VerticalLayoutHint} using a fluent API.

View file

@ -4,11 +4,9 @@ import org.xbib.graphics.pdfbox.layout.elements.Document;
import org.xbib.graphics.pdfbox.layout.elements.Element; import org.xbib.graphics.pdfbox.layout.elements.Element;
/** /**
* Each element in a document is * Each element in a document {@link Document#add(Element, LayoutHint)}
* {@link Document#add(Element, LayoutHint) * is accompanied by a hint, which gives some notes to the current layout on how
* accompanied} by a hint, which gives some notes to the current layout on how
* to layout the element. * to layout the element.
*/ */
public interface LayoutHint { public interface LayoutHint {
} }

View file

@ -0,0 +1,14 @@
package org.xbib.graphics.pdfbox.layout.elements.render;
public enum Layouts {
VERTICAL,
COLUMN;
public Layout getLayout() {
switch (name()) {
case "VERTICAL": return new VerticalLayout();
case "COLUMN": return new ColumnLayout();
}
throw new IllegalArgumentException();
}
}

View file

@ -100,8 +100,7 @@ public class RenderContext implements Renderer, Closeable, DrawContext, DrawList
* {@link Document document} margins. * {@link Document document} margins.
*/ */
public Position getUpperLeft() { public Position getUpperLeft() {
return new Position(getPageFormat().getMarginLeft(), getPageHeight() return new Position(getPageFormat().getMarginLeft(), getPageHeight() - getPageFormat().getMarginTop());
- getPageFormat().getMarginTop());
} }
/** /**
@ -109,8 +108,7 @@ public class RenderContext implements Renderer, Closeable, DrawContext, DrawList
* {@link Document document} margins. * {@link Document document} margins.
*/ */
public Position getLowerRight() { public Position getLowerRight() {
return new Position(getPageWidth() - getPageFormat().getMarginRight(), return new Position(getPageWidth() - getPageFormat().getMarginRight(), getPageFormat().getMarginBottom());
getPageFormat().getMarginBottom());
} }
/** /**

View file

@ -13,20 +13,22 @@ import org.xbib.graphics.pdfbox.layout.text.Alignment;
*/ */
public class VerticalLayoutHint implements LayoutHint { public class VerticalLayoutHint implements LayoutHint {
public final static VerticalLayoutHint LEFT = new VerticalLayoutHint( public final static VerticalLayoutHint LEFT = new VerticalLayoutHint(Alignment.LEFT);
Alignment.LEFT);
public final static VerticalLayoutHint CENTER = new VerticalLayoutHint( public final static VerticalLayoutHint CENTER = new VerticalLayoutHint(Alignment.CENTER);
Alignment.CENTER);
public final static VerticalLayoutHint RIGHT = new VerticalLayoutHint( public final static VerticalLayoutHint RIGHT = new VerticalLayoutHint(Alignment.RIGHT);
Alignment.RIGHT);
private final Alignment alignment; private final Alignment alignment;
private final float marginLeft; private final float marginLeft;
private final float marginRight; private final float marginRight;
private final float marginTop; private final float marginTop;
private final float marginBottom; private final float marginBottom;
private final boolean resetY; private final boolean resetY;
/** /**
@ -54,8 +56,7 @@ public class VerticalLayoutHint implements LayoutHint {
* @param marginTop the top alignment. * @param marginTop the top alignment.
* @param marginBottom the bottom alignment. * @param marginBottom the bottom alignment.
*/ */
public VerticalLayoutHint(Alignment alignment, float marginLeft, public VerticalLayoutHint(Alignment alignment, float marginLeft, float marginRight, float marginTop, float marginBottom) {
float marginRight, float marginTop, float marginBottom) {
this(alignment, marginLeft, marginRight, marginTop, marginBottom, false); this(alignment, marginLeft, marginRight, marginTop, marginBottom, false);
} }
@ -70,8 +71,7 @@ public class VerticalLayoutHint implements LayoutHint {
* @param resetY if <code>true</code>, the y coordinate will be reset to the * @param resetY if <code>true</code>, the y coordinate will be reset to the
* point before layouting the element. * point before layouting the element.
*/ */
public VerticalLayoutHint(Alignment alignment, float marginLeft, public VerticalLayoutHint(Alignment alignment, float marginLeft, float marginRight, float marginTop, float marginBottom,
float marginRight, float marginTop, float marginBottom,
boolean resetY) { boolean resetY) {
this.alignment = alignment; this.alignment = alignment;
this.marginLeft = marginLeft; this.marginLeft = marginLeft;
@ -126,40 +126,45 @@ public class VerticalLayoutHint implements LayoutHint {
* {@link VerticalLayoutHint} using a fluent API. * {@link VerticalLayoutHint} using a fluent API.
*/ */
public static class VerticalLayoutHintBuilder { public static class VerticalLayoutHintBuilder {
protected Alignment alignment = Alignment.LEFT; protected Alignment alignment = Alignment.LEFT;
protected float marginLeft = 0;
protected float marginRight = 0; protected float marginLeft = 0f;
protected float marginTop = 0;
protected float marginBottom = 0; protected float marginRight = 0f;
protected float marginTop = 0f;
protected float marginBottom = 0f;
protected boolean resetY = false; protected boolean resetY = false;
public VerticalLayoutHintBuilder alignment(final Alignment alignment) { public VerticalLayoutHintBuilder alignment(Alignment alignment) {
this.alignment = alignment; this.alignment = alignment;
return this; return this;
} }
public VerticalLayoutHintBuilder marginLeft(final float marginLeft) { public VerticalLayoutHintBuilder marginLeft(float marginLeft) {
this.marginLeft = marginLeft; this.marginLeft = marginLeft;
return this; return this;
} }
public VerticalLayoutHintBuilder marginRight(final float marginRight) { public VerticalLayoutHintBuilder marginRight(float marginRight) {
this.marginRight = marginRight; this.marginRight = marginRight;
return this; return this;
} }
public VerticalLayoutHintBuilder marginTop(final float marginTop) { public VerticalLayoutHintBuilder marginTop(float marginTop) {
this.marginTop = marginTop; this.marginTop = marginTop;
return this; return this;
} }
public VerticalLayoutHintBuilder marginBottom(final float marginBottom) { public VerticalLayoutHintBuilder marginBottom(float marginBottom) {
this.marginBottom = marginBottom; this.marginBottom = marginBottom;
return this; return this;
} }
public VerticalLayoutHintBuilder margins(float marginLeft, public VerticalLayoutHintBuilder margins(float marginLeft, float marginRight, float marginTop, float marginBottom) {
float marginRight, float marginTop, float marginBottom) {
this.marginLeft = marginLeft; this.marginLeft = marginLeft;
this.marginRight = marginRight; this.marginRight = marginRight;
this.marginTop = marginTop; this.marginTop = marginTop;
@ -167,16 +172,13 @@ public class VerticalLayoutHint implements LayoutHint {
return this; return this;
} }
public VerticalLayoutHintBuilder resetY(final boolean resetY) { public VerticalLayoutHintBuilder resetY(boolean resetY) {
this.resetY = resetY; this.resetY = resetY;
return this; return this;
} }
public VerticalLayoutHint build() { public VerticalLayoutHint build() {
return new VerticalLayoutHint(alignment, marginLeft, marginRight, return new VerticalLayoutHint(alignment, marginLeft, marginRight, marginTop, marginBottom, resetY);
marginTop, marginBottom, resetY);
} }
} }
} }

View file

@ -4,14 +4,18 @@ import org.xbib.graphics.barcode.HumanReadableLocation;
import org.xbib.graphics.barcode.Symbol; import org.xbib.graphics.barcode.Symbol;
import org.xbib.graphics.barcode.Symbols; import org.xbib.graphics.barcode.Symbols;
import org.xbib.graphics.pdfbox.layout.elements.BarcodeElement; import org.xbib.graphics.pdfbox.layout.elements.BarcodeElement;
import org.xbib.graphics.pdfbox.layout.elements.render.VerticalLayoutHint;
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.Alignment;
import org.xbib.graphics.pdfbox.layout.text.Position; 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;
import java.util.Locale; import java.util.Locale;
import static org.xbib.graphics.pdfbox.layout.util.PdfUtil.mmToPt;
public class BarcodeCommand implements Command { public class BarcodeCommand implements Command {
@Override @Override
@ -27,17 +31,28 @@ public class BarcodeCommand implements Command {
throw new IOException(e); throw new IOException(e);
} }
if (settings.containsSetting("x") && settings.containsSetting("y")) { if (settings.containsSetting("x") && settings.containsSetting("y")) {
element.setAbsolutePosition(new Position(settings.getAsFloat("x", 0f), settings.getAsFloat("y", 0f))); element.setAbsolutePosition(new Position(mmToPt(settings.getAsFloat("x", 0f)), mmToPt(settings.getAsFloat("y", 0f))));
} }
if (settings.containsSetting("width")) { if (settings.containsSetting("width")) {
element.setWidth(settings.getAsFloat("width", element.getWidth())); element.setWidth(settings.getAsFloat("width", element.getWidth()));
} }
if (settings.containsSetting("height")) { if (settings.containsSetting("height")) {
element.setWidth(settings.getAsFloat("height", element.getHeight())); element.setHeight(settings.getAsFloat("height", element.getHeight()));
} }
if (settings.containsSetting("scale")) { if (settings.containsSetting("scalex")) {
element.setScale(settings.getAsFloat("scale", element.getScale())); element.setScaleX(settings.getAsFloat("scalex", element.getScaleX()));
} }
state.elements.peek().add(element); if (settings.containsSetting("scaley")) {
element.setScaleY(settings.getAsFloat("scaley", element.getScaleY()));
}
Alignment alignment = Alignment.valueOf(settings.get("alignment", "left").toUpperCase(Locale.ROOT));
String margin = settings.get("margin", "0 0 0 0");
String[] margins = margin.split(" ");
float marginleft = Float.parseFloat(margins[0]);
float marginright = Float.parseFloat(margins[1]);
float margintop = Float.parseFloat(margins[2]);
float marginbottom = Float.parseFloat(margins[3]);
VerticalLayoutHint verticalLayoutHint = new VerticalLayoutHint(alignment, marginleft, marginright, margintop, marginbottom, true);
state.elements.peek().add(element, verticalLayoutHint);
} }
} }

View file

@ -2,45 +2,83 @@ package org.xbib.graphics.pdfbox.layout.script.command;
import org.xbib.graphics.pdfbox.layout.color.ColorFactory; import org.xbib.graphics.pdfbox.layout.color.ColorFactory;
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.font.Font; import org.xbib.graphics.pdfbox.layout.font.Font;
import org.xbib.graphics.pdfbox.layout.font.Fonts; import org.xbib.graphics.pdfbox.layout.font.Fonts;
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.table.BorderStyle; import org.xbib.graphics.pdfbox.layout.table.BorderStyle;
import org.xbib.graphics.pdfbox.layout.table.BorderStyleInterface; import org.xbib.graphics.pdfbox.layout.table.BorderStyleInterface;
import org.xbib.graphics.pdfbox.layout.table.HorizontalAlignment;
import org.xbib.graphics.pdfbox.layout.table.Markup;
import org.xbib.graphics.pdfbox.layout.table.ParagraphCell;
import org.xbib.graphics.pdfbox.layout.table.TextCell; import org.xbib.graphics.pdfbox.layout.table.TextCell;
import org.xbib.graphics.pdfbox.layout.table.VerticalAlignment;
import org.xbib.graphics.pdfbox.layout.text.Alignment;
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 CellCommand implements Command { public class CellCommand 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 {
TextCell.Builder cell = TextCell.builder(); if (settings.containsSetting("value")) {
cell.text(settings.get("value")); TextCell.Builder cell = TextCell.builder();
cell.fontSize(settings.getAsFloat("size", 11.0f)); cell.padding(settings.getAsFloat("padding", 0f));
Document document = state.getDocument(); cell.text(settings.get("value"));
Font font = Fonts.valueOf(settings.get("font", "helvetica").toUpperCase(Locale.ROOT)).getFont(document); cell.fontSize(settings.getAsFloat("fontsize", 11.0f));
cell.font(font); Document document = state.getDocument();
cell.padding(settings.getAsFloat("padding", 0f)); Font font = Fonts.valueOf(settings.get("font", "helvetica").toUpperCase(Locale.ROOT)).getFont(document);
Color color = ColorFactory.web(settings.get("color", "black")); cell.font(font);
cell.textColor(color); Color color = ColorFactory.web(settings.get("color", "black"));
if (settings.containsSetting("backgroundcolor")) { cell.textColor(color);
Color backgroundColor = ColorFactory.web(settings.get("backgroundcolor", "black")); if (settings.containsSetting("backgroundcolor")) {
cell.backgroundColor(backgroundColor); Color backgroundColor = ColorFactory.web(settings.get("backgroundcolor", "black"));
cell.backgroundColor(backgroundColor);
}
if (settings.containsSetting("bordercolor")) {
Color borderColor = ColorFactory.web(settings.get("bordercolor", "black"));
cell.borderColor(borderColor);
}
cell.borderWidth(settings.getAsFloat("borderwidth", 0f));
BorderStyleInterface styleInterface = BorderStyle.valueOf(settings.get("borderstyle", "solid").toUpperCase(Locale.ROOT));
cell.borderStyle(styleInterface);
if (settings.containsSetting("horizontalalignment")) {
cell.horizontalAlignment(HorizontalAlignment.valueOf(settings.get("horizontalalignment", "left").toUpperCase(Locale.ROOT)));
}
if (settings.containsSetting("verticalalignment")) {
cell.verticalAlignment(VerticalAlignment.valueOf(settings.get("verticalalignment", "left").toUpperCase(Locale.ROOT)));
}
cell.colSpan(settings.getAsInt("colspan", 1));
cell.rowSpan(settings.getAsInt("rowspan", 1));
state.elements.peek().add(cell.build());
} else if (settings.containsSetting("markup")) {
ParagraphCell.Builder cell = ParagraphCell.builder();
cell.colSpan(settings.getAsInt("colspan", 1));
cell.rowSpan(settings.getAsInt("rowspan", 1));
Paragraph paragraph = new Paragraph();
if (settings.containsSetting("x") && settings.containsSetting("y")) {
paragraph.setAbsolutePosition(new Position(mmToPt(settings.getAsFloat("x", 0f)), mmToPt(settings.getAsFloat("y", 0f))));
}
if (settings.containsSetting("width")) {
paragraph.setMaxWidth(settings.getAsFloat("width", 0f));
}
if (settings.containsSetting("alignment")) {
paragraph.setAlignment(Alignment.valueOf(settings.get("alignment", "left").toUpperCase(Locale.ROOT)));
}
cell.paragraph(paragraph);
String value = settings.get("markup");
float size = settings.getAsFloat("fontsize", 11.0f);
Document document = state.getDocument();
Font font = Fonts.valueOf(settings.get("font", "helvetica").toUpperCase(Locale.ROOT)).getFont(document);
cell.add(new Markup().setValue(value).setFont(font).setFontSize(size));
state.elements.peek().add(cell.build());
} }
if (settings.containsSetting("bordercolor")) {
Color borderColor = ColorFactory.web(settings.get("bordercolor", "black"));
cell.borderColor(borderColor);
}
cell.borderWidth(settings.getAsFloat("borderwidth", 0f));
BorderStyleInterface styleInterface = BorderStyle.valueOf(settings.get("borderstyle", "solid").toUpperCase(Locale.ROOT));
cell.borderStyle(styleInterface);
cell.colSpan(settings.getAsInt("colspan", 1));
cell.rowSpan(settings.getAsInt("rowspan", 1));
state.elements.peek().add(cell.build());
} }
} }

View file

@ -11,7 +11,9 @@ public class ColumnlayoutCommand 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 {
ColumnLayout columnLayout = new ColumnLayout(settings.getAsInt("columns", 2), settings.getAsFloat("spacing", 10f)); ColumnLayout columnLayout = new ColumnLayout();
columnLayout.setColumnCount(settings.getAsInt("columns", 2));
columnLayout.setColumnSpacing(settings.getAsFloat("spacing", 10f));
state.elements.peek().add(columnLayout); state.elements.peek().add(columnLayout);
} }
} }

View file

@ -11,18 +11,20 @@ import org.xbib.settings.Settings;
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 ImageCommand implements Command { public class ImageCommand 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 {
ImageElement imageElement = new ImageElement(settings.get("value")); ImageElement imageElement = new ImageElement(settings.get("value"));
if (settings.containsSetting("x") && settings.containsSetting("y")) { if (settings.containsSetting("x") && settings.containsSetting("y")) {
imageElement.setAbsolutePosition(new Position(settings.getAsFloat("x", 0f), settings.getAsFloat("y", 0f))); imageElement.setAbsolutePosition(new Position(mmToPt(settings.getAsFloat("x", 0f)), mmToPt(settings.getAsFloat("y", 0f))));
} }
if (settings.containsSetting("width")) { if (settings.containsSetting("width")) {
imageElement.setWidth(settings.getAsFloat("width", imageElement.getWidth())); imageElement.setWidth(settings.getAsFloat("width", imageElement.getWidth()));
} }
if (settings.containsSetting("height")) { if (settings.containsSetting("height")) {
imageElement.setWidth(settings.getAsFloat("height", imageElement.getHeight())); imageElement.setHeight(settings.getAsFloat("height", imageElement.getHeight()));
} }
if (settings.containsSetting("scale")) { if (settings.containsSetting("scale")) {
imageElement.setScale(settings.getAsFloat("scale", imageElement.getScale())); imageElement.setScale(settings.getAsFloat("scale", imageElement.getScale()));
@ -35,6 +37,6 @@ public class ImageCommand implements Command {
float margintop = Float.parseFloat(margins[2]); float margintop = Float.parseFloat(margins[2]);
float marginbottom = Float.parseFloat(margins[3]); float marginbottom = Float.parseFloat(margins[3]);
VerticalLayoutHint verticalLayoutHint = new VerticalLayoutHint(alignment, marginleft, marginright, margintop, marginbottom, true); VerticalLayoutHint verticalLayoutHint = new VerticalLayoutHint(alignment, marginleft, marginright, margintop, marginbottom, true);
state.elements.peek().add(imageElement); state.elements.peek().add(imageElement, verticalLayoutHint);
} }
} }

View file

@ -0,0 +1,16 @@
package org.xbib.graphics.pdfbox.layout.script.command;
import org.xbib.graphics.pdfbox.layout.script.Engine;
import org.xbib.graphics.pdfbox.layout.script.State;
import org.xbib.settings.Settings;
import java.io.IOException;
import java.util.Locale;
public class LayoutCommand implements Command {
@Override
public void execute(Engine engine, State state, Settings settings) throws IOException {
String layout = settings.get("layout", "vertical").toUpperCase(Locale.ROOT);
}
}

View file

@ -1,6 +1,7 @@
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.elements.Paragraph;
import org.xbib.graphics.pdfbox.layout.elements.render.VerticalLayoutHint;
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.Alignment; import org.xbib.graphics.pdfbox.layout.text.Alignment;
@ -10,13 +11,15 @@ import org.xbib.settings.Settings;
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 ParagraphCommand implements Command { 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 {
Paragraph paragraph = new Paragraph(); Paragraph paragraph = new Paragraph();
if (settings.containsSetting("x") && settings.containsSetting("y")) { if (settings.containsSetting("x") && settings.containsSetting("y")) {
paragraph.setAbsolutePosition(new Position(settings.getAsFloat("x", 0f), settings.getAsFloat("y", 0f))); paragraph.setAbsolutePosition(new Position(mmToPt(settings.getAsFloat("x", 0f)), mmToPt(settings.getAsFloat("y", 0f))));
} }
if (settings.containsSetting("width")) { if (settings.containsSetting("width")) {
paragraph.setMaxWidth(settings.getAsFloat("width", 0f)); paragraph.setMaxWidth(settings.getAsFloat("width", 0f));
@ -27,6 +30,15 @@ public class ParagraphCommand implements Command {
state.elements.push(paragraph); state.elements.push(paragraph);
engine.executeElements(settings); engine.executeElements(settings);
state.elements.pop(); state.elements.pop();
state.elements.peek().add(paragraph); Alignment alignment = Alignment.valueOf(settings.get("layout.alignment", "left").toUpperCase(Locale.ROOT));
String margin = settings.get("layout.margin", "0 0 0 0");
String[] margins = margin.split(" ");
float marginleft = Float.parseFloat(margins[0]);
float marginright = Float.parseFloat(margins[1]);
float margintop = Float.parseFloat(margins[2]);
float marginbottom = Float.parseFloat(margins[3]);
boolean resetY = settings.getAsBoolean("layout.resety", false);
VerticalLayoutHint verticalLayoutHint = new VerticalLayoutHint(alignment, marginleft, marginright, margintop, marginbottom, resetY);
state.elements.peek().add(paragraph, verticalLayoutHint);
} }
} }

View file

@ -1,11 +1,20 @@
package org.xbib.graphics.pdfbox.layout.script.command; package org.xbib.graphics.pdfbox.layout.script.command;
import org.xbib.graphics.pdfbox.layout.color.ColorFactory;
import org.xbib.graphics.pdfbox.layout.elements.Document;
import org.xbib.graphics.pdfbox.layout.font.Fonts;
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.table.BorderStyle;
import org.xbib.graphics.pdfbox.layout.table.BorderStyleInterface;
import org.xbib.graphics.pdfbox.layout.table.HorizontalAlignment;
import org.xbib.graphics.pdfbox.layout.table.Row; import org.xbib.graphics.pdfbox.layout.table.Row;
import org.xbib.graphics.pdfbox.layout.table.VerticalAlignment;
import org.xbib.settings.Settings; import org.xbib.settings.Settings;
import java.awt.Color;
import java.io.IOException; import java.io.IOException;
import java.util.Locale;
public class RowCommand implements Command { public class RowCommand implements Command {
@ -13,6 +22,28 @@ public class RowCommand implements Command {
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)); row.padding(settings.getAsFloat("padding", 0f));
row.fontSize(settings.getAsFloat("fontsize", 11.0f));
Document document = state.getDocument();
row.font(Fonts.valueOf(settings.get("font", "helvetica").toUpperCase(Locale.ROOT)).getFont(document));
Color color = ColorFactory.web(settings.get("color", "black"));
row.textColor(color);
if (settings.containsSetting("backgroundcolor")) {
Color backgroundColor = ColorFactory.web(settings.get("backgroundcolor", "black"));
row.backgroundColor(backgroundColor);
}
if (settings.containsSetting("bordercolor")) {
Color borderColor = ColorFactory.web(settings.get("bordercolor", "black"));
row.borderColor(borderColor);
}
row.borderWidth(settings.getAsFloat("borderwidth", 0f));
BorderStyleInterface styleInterface = BorderStyle.valueOf(settings.get("borderstyle", "solid").toUpperCase(Locale.ROOT));
row.borderStyle(styleInterface);
if (settings.containsSetting("horizontalalignment")) {
row.horizontalAlignment(HorizontalAlignment.valueOf(settings.get("horizontalalignment", "left").toUpperCase(Locale.ROOT)));
}
if (settings.containsSetting("verticalalignment")) {
row.verticalAlignment(VerticalAlignment.valueOf(settings.get("verticalalignment", "left").toUpperCase(Locale.ROOT)));
}
state.elements.push(row); state.elements.push(row);
engine.executeElements(settings); engine.executeElements(settings);
state.elements.pop(); state.elements.pop();

View file

@ -3,21 +3,29 @@ package org.xbib.graphics.pdfbox.layout.script.command;
import org.xbib.graphics.pdfbox.layout.elements.TableElement; import org.xbib.graphics.pdfbox.layout.elements.TableElement;
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;
import static org.xbib.graphics.pdfbox.layout.util.PdfUtil.mmToPt;
public class TableCommand implements Command { public class TableCommand 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 {
TableElement tableElement = new TableElement(); TableElement tableElement = new TableElement();
if (settings.containsSetting("columnwidths")) { if (settings.containsSetting("columnwidths")) {
String columnWidths = settings.get("columnwidths"); String columnwidths = settings.get("columnwidths");
for (String columnWidth : columnWidths.split(" ")) { String[] widths = columnwidths.split(" ");
tableElement.addColumnOfWidth(Float.parseFloat(columnWidth)); for (String width : widths) {
tableElement.addColumnOfWidth(mmToPt(Float.parseFloat(width)));
} }
} }
if (settings.containsSetting("x") && settings.containsSetting("y")) {
tableElement.setAbsolutePosition(new Position(mmToPt(settings.getAsFloat("x", 0f)), mmToPt(settings.getAsFloat("y", 0f))));
}
state.elements.push(tableElement); state.elements.push(tableElement);
engine.executeElements(settings); engine.executeElements(settings);
state.elements.pop(); state.elements.pop();

View file

@ -1,23 +1,55 @@
package org.xbib.graphics.pdfbox.layout.script.command; package org.xbib.graphics.pdfbox.layout.script.command;
import org.xbib.graphics.pdfbox.layout.elements.Document; import org.xbib.graphics.pdfbox.layout.elements.Document;
import org.xbib.graphics.pdfbox.layout.elements.Element;
import org.xbib.graphics.pdfbox.layout.elements.Paragraph;
import org.xbib.graphics.pdfbox.layout.elements.TextElement; import org.xbib.graphics.pdfbox.layout.elements.TextElement;
import org.xbib.graphics.pdfbox.layout.elements.render.VerticalLayoutHint;
import org.xbib.graphics.pdfbox.layout.font.Font; import org.xbib.graphics.pdfbox.layout.font.Font;
import org.xbib.graphics.pdfbox.layout.font.Fonts; import org.xbib.graphics.pdfbox.layout.font.Fonts;
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.Alignment;
import org.xbib.graphics.pdfbox.layout.text.Position;
import org.xbib.settings.Settings; import org.xbib.settings.Settings;
import java.util.Locale; import java.util.Locale;
import static org.xbib.graphics.pdfbox.layout.util.PdfUtil.mmToPt;
public class TextCommand implements Command { public class TextCommand implements Command {
@Override @Override
public void execute(Engine engine, State state, Settings settings) { public void execute(Engine engine, State state, Settings settings) {
String value = settings.get("value"); String value = settings.get("value");
float size = settings.getAsFloat("size", 11.0f); float size = settings.getAsFloat("fontsize", 11.0f);
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);
state.elements.peek().add(new TextElement(value, font, size)); Element element = state.elements.peek();
if (element instanceof Paragraph) {
element.add(new TextElement(value, font, size));
} else if (element instanceof Document) {
Paragraph paragraph = new Paragraph();
if (settings.containsSetting("x") && settings.containsSetting("y")) {
paragraph.setAbsolutePosition(new Position(mmToPt(settings.getAsFloat("x", 0f)), mmToPt(settings.getAsFloat("y", 0f))));
}
if (settings.containsSetting("width")) {
paragraph.setMaxWidth(settings.getAsFloat("width", 0f));
}
if (settings.containsSetting("alignment")) {
paragraph.setAlignment(Alignment.valueOf(settings.get("alignment", "left").toUpperCase(Locale.ROOT)));
}
paragraph.add(new TextElement(value, font, size));
Alignment alignment = Alignment.valueOf(settings.get("layout.alignment", "left").toUpperCase(Locale.ROOT));
String margin = settings.get("layout.margin", "0 0 0 0");
String[] margins = margin.split(" ");
float marginleft = Float.parseFloat(margins[0]);
float marginright = Float.parseFloat(margins[1]);
float margintop = Float.parseFloat(margins[2]);
float marginbottom = Float.parseFloat(margins[3]);
boolean resetY = settings.getAsBoolean("layout.resety", false);
VerticalLayoutHint verticalLayoutHint = new VerticalLayoutHint(alignment, marginleft, marginright, margintop, marginbottom, resetY);
element.add(paragraph, verticalLayoutHint);
}
} }
} }

View file

@ -1,11 +1,10 @@
package org.xbib.graphics.pdfbox.layout.table; package org.xbib.graphics.pdfbox.layout.table;
import org.xbib.graphics.pdfbox.layout.elements.Element;
import org.xbib.graphics.pdfbox.layout.table.render.AbstractCellRenderer; import org.xbib.graphics.pdfbox.layout.table.render.AbstractCellRenderer;
import org.xbib.graphics.pdfbox.layout.table.render.Renderer; import org.xbib.graphics.pdfbox.layout.table.render.Renderer;
import java.awt.Color; import java.awt.Color;
public abstract class AbstractCell implements Element { public abstract class AbstractCell implements Cell {
private static final float DEFAULT_MIN_HEIGHT = 10f; private static final float DEFAULT_MIN_HEIGHT = 10f;
@ -13,7 +12,7 @@ public abstract class AbstractCell implements Element {
private int rowSpan = 1; private int rowSpan = 1;
protected AbstractCellRenderer<AbstractCell> drawer; protected AbstractCellRenderer<Cell> renderer;
private Row row; private Row row;
@ -29,26 +28,90 @@ public abstract class AbstractCell implements Element {
this.colSpan = colSpan; this.colSpan = colSpan;
} }
@Override
public int getColSpan() {
return colSpan;
}
public void setRowSpan(int rowSpan) { public void setRowSpan(int rowSpan) {
this.rowSpan = rowSpan; this.rowSpan = rowSpan;
} }
public float getPaddingBottom() { @Override
return parameters.getPaddingBottom(); public int getRowSpan() {
return rowSpan;
}
@Override
public void setColumn(Column column) {
this.column = column;
} }
public float getPaddingTop() { public Column getColumn() {
return parameters.getPaddingTop(); return column;
} }
@Override
public void setRow(Row row) {
this.row = row;
}
public Row getRow() {
return row;
}
@Override
public void setWidth(float width) {
this.width = width;
}
public float getWidth() {
return width;
}
public void setMinHeight(float minHeight) {
this.minHeight = minHeight;
}
@Override
public float getMinHeight() {
return minHeight;
}
@Override
public float getHeight() {
assertIsRendered();
return getRowSpan() > 1 ? calculateHeightForRowSpan() : getMinHeight();
}
public void setParameters(Parameters parameters) {
this.parameters = parameters;
}
@Override
public Parameters getParameters() {
return parameters;
}
@Override
public float getPaddingLeft() { public float getPaddingLeft() {
return parameters.getPaddingLeft(); return parameters.getPaddingLeft();
} }
@Override
public float getPaddingRight() { public float getPaddingRight() {
return parameters.getPaddingRight(); return parameters.getPaddingRight();
} }
@Override
public float getPaddingTop() {
return parameters.getPaddingTop();
}
@Override
public float getPaddingBottom() {
return parameters.getPaddingBottom();
}
public float getHorizontalPadding() { public float getHorizontalPadding() {
return parameters.getPaddingLeft() + parameters.getPaddingRight(); return parameters.getPaddingLeft() + parameters.getPaddingRight();
} }
@ -57,137 +120,105 @@ public abstract class AbstractCell implements Element {
return parameters.getPaddingTop() + parameters.getPaddingBottom(); return parameters.getPaddingTop() + parameters.getPaddingBottom();
} }
@Override
public float getBorderWidthTop() { public float getBorderWidthTop() {
return hasBorderTop() ? parameters.getBorderWidthTop() : 0; return hasBorderTop() ? parameters.getBorderWidthTop() : 0;
} }
@Override
public boolean hasBorderTop() { public boolean hasBorderTop() {
return parameters.getBorderWidthTop() != null && parameters.getBorderWidthTop() > 0; return parameters.getBorderWidthTop() != null && parameters.getBorderWidthTop() > 0;
} }
@Override
public float getBorderWidthBottom() { public float getBorderWidthBottom() {
return hasBorderBottom() ? parameters.getBorderWidthBottom() : 0; return hasBorderBottom() ? parameters.getBorderWidthBottom() : 0;
} }
@Override
public boolean hasBorderBottom() { public boolean hasBorderBottom() {
return parameters.getBorderWidthBottom() != null && parameters.getBorderWidthBottom() > 0; return parameters.getBorderWidthBottom() != null && parameters.getBorderWidthBottom() > 0;
} }
@Override
public float getBorderWidthLeft() { public float getBorderWidthLeft() {
return hasBorderLeft() ? parameters.getBorderWidthLeft() : 0; return hasBorderLeft() ? parameters.getBorderWidthLeft() : 0;
} }
@Override
public boolean hasBorderLeft() { public boolean hasBorderLeft() {
return parameters.getBorderWidthLeft() != null && parameters.getBorderWidthLeft() > 0; return parameters.getBorderWidthLeft() != null && parameters.getBorderWidthLeft() > 0;
} }
@Override
public float getBorderWidthRight() { public float getBorderWidthRight() {
return hasBorderRight() ? parameters.getBorderWidthRight() : 0; return hasBorderRight() ? parameters.getBorderWidthRight() : 0;
} }
@Override
public boolean hasBorderRight() { public boolean hasBorderRight() {
return parameters.getBorderWidthRight() != null && parameters.getBorderWidthRight() > 0; return parameters.getBorderWidthRight() != null && parameters.getBorderWidthRight() > 0;
} }
@Override
public BorderStyleInterface getBorderStyleTop() { public BorderStyleInterface getBorderStyleTop() {
return parameters.getBorderStyleTop(); return parameters.getBorderStyleTop();
} }
@Override
public BorderStyleInterface getBorderStyleBottom() { public BorderStyleInterface getBorderStyleBottom() {
return parameters.getBorderStyleBottom(); return parameters.getBorderStyleBottom();
} }
@Override
public BorderStyleInterface getBorderStyleLeft() { public BorderStyleInterface getBorderStyleLeft() {
return parameters.getBorderStyleLeft(); return parameters.getBorderStyleLeft();
} }
@Override
public BorderStyleInterface getBorderStyleRight() { public BorderStyleInterface getBorderStyleRight() {
return parameters.getBorderStyleRight(); return parameters.getBorderStyleRight();
} }
@Override
public boolean hasBackgroundColor() { public boolean hasBackgroundColor() {
return parameters.getBackgroundColor() != null; return parameters.getBackgroundColor() != null;
} }
@Override
public Color getBackgroundColor() { public Color getBackgroundColor() {
return parameters.getBackgroundColor(); return parameters.getBackgroundColor();
} }
@Override
public Color getBorderColor() { public Color getBorderColor() {
return parameters.getBorderColor(); return parameters.getBorderColor();
} }
@Override
public boolean isHorizontallyAligned(HorizontalAlignment alignment) {
return parameters.getHorizontalAlignment() == alignment;
}
@Override
public boolean isVerticallyAligned(VerticalAlignment alignment) {
return parameters.getVerticalAlignment() == alignment;
}
public boolean isWordBreak() { public boolean isWordBreak() {
return parameters.isWordBreak(); return parameters.isWordBreak();
} }
public Column getColumn() { public void setRenderer(AbstractCellRenderer<Cell> renderer) {
return column; this.renderer = renderer;
} }
public static float getDefaultMinHeight() { @Override
return DEFAULT_MIN_HEIGHT; public Renderer getRenderer() {
return this.renderer != null ? this.renderer.withCell(this) : createDefaultRenderer();
} }
public float getMinHeight() { @Override
return minHeight;
}
public float getWidth() {
return width;
}
public int getColSpan() {
return colSpan;
}
public int getRowSpan() {
return rowSpan;
}
public Row getRow() {
return row;
}
public Parameters getParameters() {
return parameters;
}
public void setColumn(Column column) {
this.column = column;
}
public void setDrawer(AbstractCellRenderer<AbstractCell> drawer) {
this.drawer = drawer;
}
public void setMinHeight(float minHeight) {
this.minHeight = minHeight;
}
public void setRow(Row row) {
this.row = row;
}
public void setParameters(Parameters parameters) {
this.parameters = parameters;
}
public void setWidth(float width) {
this.width = width;
}
public float getHeight() {
assertIsRendered();
return getRowSpan() > 1 ? calculateHeightForRowSpan() : getMinHeight();
}
public Renderer getDrawer() {
return this.drawer != null ? this.drawer.withCell(this) : createDefaultDrawer();
}
protected abstract Renderer createDefaultDrawer();
public float calculateHeightForRowSpan() { public float calculateHeightForRowSpan() {
Row currentRow = row; Row currentRow = row;
float result = currentRow.getHeight(); float result = currentRow.getHeight();
@ -204,11 +235,5 @@ public abstract class AbstractCell implements Element {
} }
} }
public boolean isHorizontallyAligned(HorizontalAlignment alignment) { protected abstract Renderer createDefaultRenderer();
return getParameters().getHorizontalAlignment() == alignment;
}
public boolean isVerticallyAligned(VerticalAlignment alignment) {
return getParameters().getVerticalAlignment() == alignment;
}
} }

View file

@ -9,7 +9,14 @@ import java.util.List;
public abstract class AbstractTextCell extends AbstractCell { public abstract class AbstractTextCell extends AbstractCell {
protected float lineSpacing = 1f; private Float textHeight;
private float lineSpacing = 1f;
@Override
public float getMinHeight() {
return Math.max((getVerticalPadding() + getTextHeight()), super.getMinHeight());
}
public Font getFont() { public Font getFont() {
return parameters.getFont(); return parameters.getFont();
@ -23,19 +30,16 @@ public abstract class AbstractTextCell extends AbstractCell {
return parameters.getTextColor(); return parameters.getTextColor();
} }
private Float textHeight;
public abstract String getText(); public abstract String getText();
public void setLineSpacing(float lineSpacing) {
this.lineSpacing = lineSpacing;
}
public float getLineSpacing() { public float getLineSpacing() {
return lineSpacing; return lineSpacing;
} }
@Override
public float getMinHeight() {
return Math.max((getVerticalPadding() + getTextHeight()), super.getMinHeight());
}
public float getTextHeight() { public float getTextHeight() {
if (this.textHeight != null) { if (this.textHeight != null) {
return this.textHeight; return this.textHeight;
@ -66,7 +70,7 @@ public abstract class AbstractTextCell extends AbstractCell {
private float getMaxWidthOfText() { private float getMaxWidthOfText() {
float columnsWidth = getColumn().getWidth(); float columnsWidth = getColumn().getWidth();
if (getColSpan() > 1) { if (getColSpan() > 0) {
Column currentColumn = getColumn(); Column currentColumn = getColumn();
for (int i = 1; i < getColSpan(); i++) { for (int i = 1; i < getColSpan(); i++) {
columnsWidth += currentColumn.getNext().getWidth(); columnsWidth += currentColumn.getNext().getWidth();

View file

@ -0,0 +1,78 @@
package org.xbib.graphics.pdfbox.layout.table;
import org.xbib.graphics.pdfbox.layout.elements.Element;
import org.xbib.graphics.pdfbox.layout.table.render.Renderer;
import java.awt.Color;
public interface Cell extends Element {
int getRowSpan();
int getColSpan();
void setRow(Row row);
Row getRow();
void setColumn(Column column);
Column getColumn();
void setWidth(float width);
Parameters getParameters();
float getMinHeight();
float getWidth();
float getHeight();
Renderer getRenderer();
boolean hasBackgroundColor();
Color getBackgroundColor();
Color getBorderColor();
float getPaddingLeft();
float getPaddingRight();
float getPaddingTop();
float getPaddingBottom();
boolean hasBorderLeft();
boolean hasBorderRight();
boolean hasBorderTop();
boolean hasBorderBottom();
float getBorderWidthLeft();
float getBorderWidthRight();
float getBorderWidthTop();
float getBorderWidthBottom();
BorderStyleInterface getBorderStyleLeft();
BorderStyleInterface getBorderStyleRight();
BorderStyleInterface getBorderStyleTop();
BorderStyleInterface getBorderStyleBottom();
float calculateHeightForRowSpan();
boolean isHorizontallyAligned(HorizontalAlignment alignment);
boolean isVerticallyAligned(VerticalAlignment alignment);
}

View file

@ -0,0 +1,73 @@
package org.xbib.graphics.pdfbox.layout.table;
import org.xbib.graphics.pdfbox.layout.elements.Drawable;
import org.xbib.graphics.pdfbox.layout.table.render.DrawableCellRenderer;
import org.xbib.graphics.pdfbox.layout.table.render.Renderer;
public class DrawableCell extends AbstractCell {
private Drawable drawable;
public DrawableCell() {
}
public void setDrawable(Drawable drawable) {
this.drawable = drawable;
}
public Drawable getDrawable() {
return drawable;
}
@Override
protected Renderer createDefaultRenderer() {
return new DrawableCellRenderer(this);
}
public static Builder builder() {
return new Builder();
}
public static class Builder {
private Drawable drawable;
private final Parameters parameters;
private int colSpan;
private int rowSpan;
private Builder() {
this.parameters = new Parameters();
}
public Builder drawable(Drawable drawable) {
this.drawable = drawable;
return this;
}
public Builder colSpan(int colSpan) {
this.colSpan = colSpan;
return this;
}
public Builder rowSpan(int rowSpan) {
this.rowSpan = rowSpan;
return this;
}
public DrawableCell build() {
DrawableCell cell = new DrawableCell();
cell.setDrawable(drawable);
cell.setParameters(parameters);
if (colSpan > 0) {
cell.setColSpan(colSpan);
}
if (rowSpan > 0) {
cell.setRowSpan(rowSpan);
}
return cell;
}
}
}

View file

@ -40,7 +40,7 @@ public class ImageCell extends AbstractCell {
} }
@Override @Override
protected Renderer createDefaultDrawer() { protected Renderer createDefaultRenderer() {
return new ImageCellRenderer(this); return new ImageCellRenderer(this);
} }
@ -49,21 +49,16 @@ public class ImageCell extends AbstractCell {
float scaledWidth = image.getWidth() * getScale(); float scaledWidth = image.getWidth() * getScale();
float scaledHeight = image.getHeight() * getScale(); float scaledHeight = image.getHeight() * getScale();
final float resultingWidth = getWidth() - getHorizontalPadding(); final float resultingWidth = getWidth() - getHorizontalPadding();
// maybe reduce the image to fit in column
if (scaledWidth > resultingWidth) { if (scaledWidth > resultingWidth) {
scaledHeight = (resultingWidth / scaledWidth) * scaledHeight; scaledHeight = (resultingWidth / scaledWidth) * scaledHeight;
scaledWidth = resultingWidth; scaledWidth = resultingWidth;
} }
if (maxHeight > 0.0f && scaledHeight > maxHeight) { if (maxHeight > 0.0f && scaledHeight > maxHeight) {
scaledWidth = (maxHeight / scaledHeight) * scaledWidth; scaledWidth = (maxHeight / scaledHeight) * scaledWidth;
scaledHeight = maxHeight; scaledHeight = maxHeight;
} }
sizes.x = scaledWidth; sizes.x = scaledWidth;
sizes.y = scaledHeight; sizes.y = scaledHeight;
return sizes; return sizes;
} }

View file

@ -3,34 +3,35 @@ 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 java.io.IOException;
public class Markup implements ParagraphProcessor { public class Markup implements ParagraphProcessor {
private String markup; private String value;
private Font font; private Font font;
private Float fontSize; private Float fontSize;
public void setMarkup(String markup) { public Markup setValue(String value) {
this.markup = markup; this.value = value;
return this;
} }
public String getMarkup() { public String getValue() {
return markup; return value;
} }
public void setFont(Font font) { public Markup setFont(Font font) {
this.font = font; this.font = font;
return this;
} }
public Font getFont() { public Font getFont() {
return font; return font;
} }
public void setFontSize(Float fontSize) { public Markup setFontSize(Float fontSize) {
this.fontSize = fontSize; this.fontSize = fontSize;
return this;
} }
public Float getFontSize() { public Float getFontSize() {
@ -40,7 +41,7 @@ public class Markup implements ParagraphProcessor {
@Override @Override
public void process(Paragraph paragraph, Parameters parameters) { public void process(Paragraph paragraph, Parameters parameters) {
float fontSize = getFontSize() != null ? getFontSize() : parameters.getFontSize(); float fontSize = getFontSize() != null ? getFontSize() : parameters.getFontSize();
paragraph.addMarkup(getMarkup(), fontSize, font); paragraph.addMarkup(getValue(), fontSize, font);
} }
} }

View file

@ -1,17 +1,19 @@
package org.xbib.graphics.pdfbox.layout.table; package org.xbib.graphics.pdfbox.layout.table;
import org.xbib.graphics.pdfbox.layout.elements.Paragraph;
import org.xbib.graphics.pdfbox.layout.table.render.Renderer; import org.xbib.graphics.pdfbox.layout.table.render.Renderer;
import org.xbib.graphics.pdfbox.layout.table.render.ParagraphCellRenderer; import org.xbib.graphics.pdfbox.layout.table.render.ParagraphCellRenderer;
import java.io.IOException; import java.io.IOException;
import java.io.UncheckedIOException; import java.io.UncheckedIOException;
import java.util.ArrayList;
import java.util.List; import java.util.List;
public class ParagraphCell extends AbstractCell { public class ParagraphCell extends AbstractCell {
protected float lineSpacing = 1f; protected float lineSpacing = 1f;
private Paragraph paragraph; private CellParagraph cellParagraph;
public void setLineSpacing(float lineSpacing) { public void setLineSpacing(float lineSpacing) {
this.lineSpacing = lineSpacing; this.lineSpacing = lineSpacing;
@ -21,60 +23,111 @@ public class ParagraphCell extends AbstractCell {
return lineSpacing; return lineSpacing;
} }
public void setParagraph(Paragraph paragraph) { public void setCellParagraph(CellParagraph cellParagraph) {
this.paragraph = paragraph; this.cellParagraph = cellParagraph;
} }
public Paragraph getParagraph() { public CellParagraph getCellParagraph() {
return paragraph; return cellParagraph;
} }
@Override @Override
public void setWidth(float width) { public void setWidth(float width) {
super.setWidth(width); super.setWidth(width);
while (getParagraph().getWrappedParagraph().removeLast() != null) { //while (getCellParagraph().getParagraph().removeLast() != null) {
} //}
for (ParagraphProcessor p : getParagraph().getProcessables()) { for (ParagraphProcessor p : getCellParagraph().getParagraphProcessors()) {
try { try {
p.process(getParagraph().getWrappedParagraph(), getParameters()); p.process(getCellParagraph().getParagraph(), getParameters());
} catch (IOException exception) { } catch (IOException exception) {
throw new UncheckedIOException(exception); throw new UncheckedIOException(exception);
} }
} }
org.xbib.graphics.pdfbox.layout.elements.Paragraph wrappedParagraph = paragraph.getWrappedParagraph(); Paragraph paragraph = cellParagraph.getParagraph();
wrappedParagraph.setLineSpacing(getLineSpacing()); paragraph.setLineSpacing(getLineSpacing());
wrappedParagraph.setApplyLineSpacingToFirstLine(false); paragraph.setApplyLineSpacingToFirstLine(false);
wrappedParagraph.setMaxWidth(width - getHorizontalPadding()); paragraph.setMaxWidth(width - getHorizontalPadding());
} }
@Override @Override
protected Renderer createDefaultDrawer() { protected Renderer createDefaultRenderer() {
return new ParagraphCellRenderer(this); return new ParagraphCellRenderer(this);
} }
@Override @Override
public float getMinHeight() { public float getMinHeight() {
float height = paragraph.getWrappedParagraph().getHeight() + getVerticalPadding(); float height = cellParagraph.getParagraph().getHeight() + getVerticalPadding();
return Math.max(height, super.getMinHeight()); return Math.max(height, super.getMinHeight());
} }
public static class Paragraph { public static class CellParagraph {
private final List<ParagraphProcessor> processables; private final Paragraph paragraph;
private final org.xbib.graphics.pdfbox.layout.elements.Paragraph wrappedParagraph = private final List<ParagraphProcessor> paragraphProcessors;
new org.xbib.graphics.pdfbox.layout.elements.Paragraph();
public Paragraph(List<ParagraphProcessor> processables) { public CellParagraph(Paragraph paragraph, List<ParagraphProcessor> processables) {
this.processables = processables; this.paragraph = paragraph;
this.paragraphProcessors = processables;
} }
public List<ParagraphProcessor> getProcessables() { public List<ParagraphProcessor> getParagraphProcessors() {
return processables; return paragraphProcessors;
} }
public org.xbib.graphics.pdfbox.layout.elements.Paragraph getWrappedParagraph() { public Paragraph getParagraph() {
return wrappedParagraph; return paragraph;
}
}
public static Builder builder() {
return new Builder();
}
public static class Builder {
private final Parameters parameters;
private int colSpan;
private int rowSpan;
private Paragraph paragraph;
private final List<ParagraphProcessor> processors;
private Builder() {
this.parameters = new Parameters();
this.processors = new ArrayList<>();
}
public Builder colSpan(int colSpan) {
this.colSpan = colSpan;
return this;
}
public Builder rowSpan(int rowSpan) {
this.rowSpan = rowSpan;
return this;
}
public Builder paragraph(Paragraph paragraph) {
this.paragraph = paragraph;
return this;
}
public Builder add(ParagraphProcessor processor) {
this.processors.add(processor);
return this;
}
public ParagraphCell build() {
ParagraphCell cell = new ParagraphCell();
cell.setParameters(parameters);
cell.setColSpan(colSpan);
cell.setRowSpan(rowSpan);
cell.setCellParagraph(new CellParagraph(paragraph, processors));
return cell;
} }
} }
} }

View file

@ -1,6 +1,8 @@
package org.xbib.graphics.pdfbox.layout.table; package org.xbib.graphics.pdfbox.layout.table;
import org.xbib.graphics.pdfbox.layout.elements.Drawable;
import org.xbib.graphics.pdfbox.layout.elements.Element; import org.xbib.graphics.pdfbox.layout.elements.Element;
import org.xbib.graphics.pdfbox.layout.elements.HorizontalRuler;
import org.xbib.graphics.pdfbox.layout.font.Font; import org.xbib.graphics.pdfbox.layout.font.Font;
import java.awt.Color; import java.awt.Color;
@ -15,7 +17,7 @@ public class Row {
private Table table; private Table table;
private List<AbstractCell> cells; private List<Cell> cells;
private Parameters parameters; private Parameters parameters;
@ -23,7 +25,7 @@ public class Row {
private Row next; private Row next;
private Row(List<AbstractCell> cells) { private Row(List<Cell> cells) {
this.cells = cells; this.cells = cells;
} }
@ -43,15 +45,19 @@ public class Row {
return DEFAULT_HEIGHT; return DEFAULT_HEIGHT;
} }
public List<AbstractCell> getCells() { public List<Cell> getCells() {
return cells; return cells;
} }
public void setTable(Table table) {
this.table = table;
}
public Table getTable() { public Table getTable() {
return table; return table;
} }
public void setCells(List<AbstractCell> cells) { public void setCells(List<Cell> cells) {
this.cells = cells; this.cells = cells;
} }
@ -63,10 +69,6 @@ public class Row {
this.next = next; this.next = next;
} }
public void setTable(Table table) {
this.table = table;
}
public float getHeight() { public float getHeight() {
if (table == null) { if (table == null) {
throw new TableNotYetBuiltException(); throw new TableNotYetBuiltException();
@ -74,7 +76,7 @@ public class Row {
if (height == null) { if (height == null) {
this.height = getCells().stream() this.height = getCells().stream()
.filter(cell -> cell.getRowSpan() == 1) .filter(cell -> cell.getRowSpan() == 1)
.map(AbstractCell::getHeight) .map(Cell::getHeight)
.max(naturalOrder()) .max(naturalOrder())
.orElse(DEFAULT_HEIGHT); .orElse(DEFAULT_HEIGHT);
} }
@ -92,7 +94,7 @@ public class Row {
public static class Builder implements Element { public static class Builder implements Element {
private final List<AbstractCell> cells = new ArrayList<>(); private final List<Cell> cells = new ArrayList<>();
private final Parameters parameters = new Parameters(); private final Parameters parameters = new Parameters();
@ -101,7 +103,14 @@ public class Row {
@Override @Override
public Builder add(Element element) { public Builder add(Element element) {
cells.add((AbstractCell) element); if (element instanceof Cell) {
cells.add((Cell) element);
} else if (element instanceof HorizontalRuler) {
Cell cell = DrawableCell.builder()
.drawable((Drawable) element)
.build();
cells.add(cell);
}
return this; return this;
} }

View file

@ -162,12 +162,10 @@ public class Table {
// Store how many cells can or better have to be omitted in the next rows // Store how many cells can or better have to be omitted in the next rows
// due to cells in this row that declare row spanning // due to cells in this row that declare row spanning
updateRowSpanCellsSet(row.getCells()); updateRowSpanCellsSet(row.getCells());
if (!rows.isEmpty()) { if (!rows.isEmpty()) {
rows.get(rows.size() - 1).setNext(row); rows.get(rows.size() - 1).setNext(row);
} }
rows.add(row); rows.add(row);
return this; return this;
} }
@ -183,19 +181,14 @@ public class Table {
// Put every cell coordinate in the set which needs to be skipped because it is // Put every cell coordinate in the set which needs to be skipped because it is
// "contained" in another cell due to row spanning. // "contained" in another cell due to row spanning.
// The coordinates are those of the table how it would look like without any spanning. // The coordinates are those of the table how it would look like without any spanning.
private void updateRowSpanCellsSet(List<AbstractCell> cells) { private void updateRowSpanCellsSet(List<Cell> cells) {
int currentColumn = 0; int currentColumn = 0;
for (Cell cell : cells) {
for (AbstractCell cell : cells) {
while (rowSpanCells.contains(new Point(rows.size(), currentColumn))) { while (rowSpanCells.contains(new Point(rows.size(), currentColumn))) {
currentColumn++; currentColumn++;
} }
if (cell.getRowSpan() > 1) { if (cell.getRowSpan() > 1) {
for (int rowsToSpan = 0; rowsToSpan < cell.getRowSpan(); rowsToSpan++) { for (int rowsToSpan = 0; rowsToSpan < cell.getRowSpan(); rowsToSpan++) {
// Skip first row's cell, because that is a regular cell // Skip first row's cell, because that is a regular cell
if (rowsToSpan >= 1) { if (rowsToSpan >= 1) {
for (int colSpan = 0; colSpan < cell.getColSpan(); colSpan++) { for (int colSpan = 0; colSpan < cell.getColSpan(); colSpan++) {
@ -204,7 +197,6 @@ public class Table {
} }
} }
} }
currentColumn += cell.getColSpan(); currentColumn += cell.getColSpan();
} }
} }
@ -310,7 +302,7 @@ public class Table {
row.getParameters().fillingMergeBy(table.getSettings()); row.getParameters().fillingMergeBy(table.getSettings());
} }
int columnIndex = 0; int columnIndex = 0;
for (AbstractCell cell : row.getCells()) { for (Cell cell : row.getCells()) {
cell.getParameters().fillingMergeBy(row.getParameters()); cell.getParameters().fillingMergeBy(row.getParameters());
cell.setRow(row); cell.setRow(row);
while (table.isRowSpanAt(rowIndex, columnIndex)) { while (table.isRowSpanAt(rowIndex, columnIndex)) {
@ -333,9 +325,9 @@ public class Table {
private void correctHeightOfCellsDueToRowSpanningIfNecessaryFor(Table table) { private void correctHeightOfCellsDueToRowSpanningIfNecessaryFor(Table table) {
for (int i = 0; i < table.getRows().size(); i++) { for (int i = 0; i < table.getRows().size(); i++) {
final Optional<AbstractCell> highestSpanningCell = rows.get(i).getCells().stream() final Optional<Cell> highestSpanningCell = rows.get(i).getCells().stream()
.filter(x -> x.getRowSpan() > 1) .filter(x -> x.getRowSpan() > 1)
.max(Comparator.comparing(AbstractCell::getMinHeight)); .max(Comparator.comparing(Cell::getMinHeight));
if (highestSpanningCell.isPresent()) { if (highestSpanningCell.isPresent()) {
final float heightOfHighestCell = highestSpanningCell.get().getMinHeight(); final float heightOfHighestCell = highestSpanningCell.get().getMinHeight();
float regularHeightOfRows = 0; float regularHeightOfRows = 0;

View file

@ -162,12 +162,12 @@ public class TableRenderer {
protected void drawRow(Point2D.Float start, Row row, int rowIndex, BiConsumer<Renderer, RenderContext> consumer) { protected void drawRow(Point2D.Float start, Row row, int rowIndex, BiConsumer<Renderer, RenderContext> consumer) {
float x = start.x; float x = start.x;
int columnCounter = 0; int columnCounter = 0;
for (AbstractCell cell : row.getCells()) { for (Cell cell : row.getCells()) {
while (table.isRowSpanAt(rowIndex, columnCounter)) { while (table.isRowSpanAt(rowIndex, columnCounter)) {
x += table.getColumns().get(columnCounter).getWidth(); x += table.getColumns().get(columnCounter).getWidth();
columnCounter++; columnCounter++;
} }
consumer.accept(cell.getDrawer(), new RenderContext(pdDocument, contentStream, page, new Point2D.Float(x, start.y))); consumer.accept(cell.getRenderer(), new RenderContext(pdDocument, contentStream, page, new Point2D.Float(x, start.y)));
x += cell.getWidth(); x += cell.getWidth();
columnCounter += cell.getColSpan(); columnCounter += cell.getColSpan();
} }
@ -179,7 +179,7 @@ public class TableRenderer {
private Float getHighestCellOf(Row row) { private Float getHighestCellOf(Row row) {
return row.getCells().stream() return row.getCells().stream()
.map(AbstractCell::getHeight) .map(Cell::getHeight)
.max(Comparator.naturalOrder()) .max(Comparator.naturalOrder())
.orElse(row.getHeight()); .orElse(row.getHeight());
} }

View file

@ -9,7 +9,8 @@ public class TextCell extends AbstractTextCell {
protected String text; protected String text;
protected Renderer createDefaultDrawer() { @Override
protected Renderer createDefaultRenderer() {
return new TextCellRenderer<>(this); return new TextCellRenderer<>(this);
} }

View file

@ -7,7 +7,7 @@ public class VerticalTextCell extends AbstractTextCell {
private String text; private String text;
protected Renderer createDefaultDrawer() { protected Renderer createDefaultRenderer() {
return new VerticalTextCellRenderer(this); return new VerticalTextCellRenderer(this);
} }

View file

@ -3,12 +3,13 @@ package org.xbib.graphics.pdfbox.layout.table.render;
import static org.xbib.graphics.pdfbox.layout.table.VerticalAlignment.BOTTOM; import static org.xbib.graphics.pdfbox.layout.table.VerticalAlignment.BOTTOM;
import static org.xbib.graphics.pdfbox.layout.table.VerticalAlignment.MIDDLE; import static org.xbib.graphics.pdfbox.layout.table.VerticalAlignment.MIDDLE;
import org.apache.pdfbox.pdmodel.PDPageContentStream; import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.xbib.graphics.pdfbox.layout.table.AbstractCell; import org.xbib.graphics.pdfbox.layout.table.Cell;
import org.xbib.graphics.pdfbox.layout.util.RenderUtil;
import java.awt.Color; import java.awt.Color;
import java.awt.geom.Point2D; import java.awt.geom.Point2D;
public abstract class AbstractCellRenderer<T extends AbstractCell> implements Renderer { public abstract class AbstractCellRenderer<T extends Cell> implements Renderer {
protected T cell; protected T cell;

View file

@ -0,0 +1,38 @@
package org.xbib.graphics.pdfbox.layout.table.render;
import org.xbib.graphics.pdfbox.layout.elements.Drawable;
import org.xbib.graphics.pdfbox.layout.table.DrawableCell;
import org.xbib.graphics.pdfbox.layout.text.Position;
import org.xbib.graphics.pdfbox.layout.text.WidthRespecting;
import java.io.IOException;
import java.io.UncheckedIOException;
public class DrawableCellRenderer extends AbstractCellRenderer<DrawableCell> {
public DrawableCellRenderer(DrawableCell cell) {
this.cell = cell;
}
@Override
public void renderContent(RenderContext renderContext) {
Drawable drawable = cell.getDrawable();
if (drawable instanceof WidthRespecting) {
WidthRespecting widthRespecting = (WidthRespecting) drawable;
widthRespecting.setMaxWidth(cell.getWidth());
}
float x = renderContext.getStartingPoint().x + cell.getPaddingLeft();
float y = renderContext.getStartingPoint().y + getAdaptionForVerticalAlignment();
Position position = new Position(x, y);
try {
drawable.draw(renderContext.getPdDocument(), renderContext.getContentStream(), position,null);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
@Override
protected float calculateInnerHeight() {
return 0;
}
}

View file

@ -3,7 +3,6 @@ package org.xbib.graphics.pdfbox.layout.table.render;
import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream; import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotation;
import org.xbib.graphics.pdfbox.layout.elements.Paragraph; import org.xbib.graphics.pdfbox.layout.elements.Paragraph;
import org.xbib.graphics.pdfbox.layout.table.HorizontalAlignment; import org.xbib.graphics.pdfbox.layout.table.HorizontalAlignment;
import org.xbib.graphics.pdfbox.layout.table.ParagraphCell; import org.xbib.graphics.pdfbox.layout.table.ParagraphCell;
@ -12,8 +11,6 @@ import org.xbib.graphics.pdfbox.layout.text.DrawContext;
import org.xbib.graphics.pdfbox.layout.text.Position; import org.xbib.graphics.pdfbox.layout.text.Position;
import org.xbib.graphics.pdfbox.layout.text.annotations.AnnotationDrawListener; import org.xbib.graphics.pdfbox.layout.text.annotations.AnnotationDrawListener;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.Map; import java.util.Map;
@ -33,30 +30,20 @@ public class ParagraphCellRenderer extends AbstractCellRenderer<ParagraphCell> {
@Override @Override
public void renderContent(RenderContext renderContext) { public void renderContent(RenderContext renderContext) {
if (renderContext.getPage() == null) { Paragraph paragraph = cell.getCellParagraph().getParagraph();
throw new PageNotSetException("Page is not set in drawing context. Please ensure the page is set on table drawer.");
}
Paragraph paragraph = cell.getParagraph().getWrappedParagraph();
AnnotationDrawListener annotationDrawListener = createAndGetAnnotationDrawListenerWith(renderContext);
float x = renderContext.getStartingPoint().x + cell.getPaddingLeft(); float x = renderContext.getStartingPoint().x + cell.getPaddingLeft();
float y = renderContext.getStartingPoint().y + getAdaptionForVerticalAlignment(); float y = renderContext.getStartingPoint().y + getAdaptionForVerticalAlignment();
AnnotationDrawListener annotationDrawListener = createAndGetAnnotationDrawListenerWith(renderContext);
paragraph.drawText(renderContext.getContentStream(), paragraph.drawText(renderContext.getContentStream(),
new Position(x, y), new Position(x, y),
ALIGNMENT_MAP.getOrDefault(cell.getParameters().getHorizontalAlignment(), Alignment.LEFT), ALIGNMENT_MAP.getOrDefault(cell.getParameters().getHorizontalAlignment(), Alignment.LEFT),
annotationDrawListener annotationDrawListener
); );
annotationDrawListener.afterPage(null);
annotationDrawListener.afterRender();
try {
renderContext.getPage().getAnnotations().forEach(PDAnnotation::constructAppearances);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
} }
@Override @Override
protected float calculateInnerHeight() { protected float calculateInnerHeight() {
return cell.getParagraph().getWrappedParagraph().getHeight(); return cell.getCellParagraph().getParagraph().getHeight();
} }
private AnnotationDrawListener createAndGetAnnotationDrawListenerWith(RenderContext renderContext) { private AnnotationDrawListener createAndGetAnnotationDrawListenerWith(RenderContext renderContext) {

View file

@ -6,6 +6,7 @@ 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.util.PdfUtil; import org.xbib.graphics.pdfbox.layout.util.PdfUtil;
import org.xbib.graphics.pdfbox.layout.util.RenderUtil;
import java.awt.Color; import java.awt.Color;
import java.io.IOException; import java.io.IOException;
@ -43,9 +44,9 @@ public class TextCellRenderer<T extends AbstractTextCell> extends AbstractCellRe
throw new UncheckedIOException(exception); throw new UncheckedIOException(exception);
} }
} }
PositionedStyledText text = new PositionedStyledText(xOffset, yOffset, PositionedStyledText positionedStyledText = new PositionedStyledText(xOffset, yOffset, line,
line, currentFont, currentFontSize, currentTextColor); currentFont, currentFontSize, currentTextColor);
drawText(renderContext, text); RenderUtil.drawText(renderContext.getContentStream(), positionedStyledText);
} }
} }
@ -54,17 +55,16 @@ public class TextCellRenderer<T extends AbstractTextCell> extends AbstractCellRe
return cell.getTextHeight(); return cell.getTextHeight();
} }
private float calculateYOffset(Font currentFont, float currentFontSize, int lineIndex) { private float calculateYOffset(Font currentFont, float currentFontSize, int lineIndex) {
return PdfUtil.getFontHeight(currentFont, currentFontSize) + return PdfUtil.getFontHeight(currentFont, currentFontSize) +
(lineIndex > 0 ? PdfUtil.getFontHeight(currentFont, currentFontSize) * cell.getLineSpacing() : 0f); (lineIndex > 0 ? PdfUtil.getFontHeight(currentFont, currentFontSize) * cell.getLineSpacing() : 0f);
} }
static boolean isNotLastLine(List<String> lines, int i) { private static boolean isNotLastLine(List<String> lines, int i) {
return i != lines.size() - 1; return i != lines.size() - 1;
} }
protected float calculateCharSpacingFor(String line) { private float calculateCharSpacingFor(String line) {
float charSpacing = 0; float charSpacing = 0;
if (line.length() > 1) { if (line.length() > 1) {
float size = PdfUtil.getStringWidth(line, cell.getFont(), cell.getFontSize()); float size = PdfUtil.getStringWidth(line, cell.getFont(), cell.getFontSize());
@ -76,13 +76,9 @@ public class TextCellRenderer<T extends AbstractTextCell> extends AbstractCellRe
return charSpacing; return charSpacing;
} }
protected List<String> calculateAndGetLines(Font currentFont, float currentFontSize, float maxWidth) { private List<String> calculateAndGetLines(Font currentFont, float currentFontSize, float maxWidth) {
return cell.isWordBreak() return cell.isWordBreak()
? PdfUtil.getOptimalTextBreakLines(cell.getText(), currentFont, currentFontSize, maxWidth) ? PdfUtil.getOptimalTextBreakLines(cell.getText(), currentFont, currentFontSize, maxWidth)
: Collections.singletonList(cell.getText()); : Collections.singletonList(cell.getText());
} }
protected void drawText(RenderContext renderContext, PositionedStyledText positionedStyledText) {
RenderUtil.drawText(renderContext.getContentStream(), positionedStyledText);
}
} }

View file

@ -3,6 +3,8 @@ package org.xbib.graphics.pdfbox.layout.text;
import org.apache.pdfbox.pdmodel.PDPageContentStream; import org.apache.pdfbox.pdmodel.PDPageContentStream;
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.TextSequenceUtil;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
@ -223,9 +225,8 @@ public class TextFlow implements TextSequence, WidthRespecting {
@Override @Override
public void drawText(PDPageContentStream contentStream, Position upperLeft, public void drawText(PDPageContentStream contentStream, Position upperLeft,
Alignment alignment, DrawListener drawListener) { Alignment alignment, DrawListener drawListener) {
TextSequenceUtil.drawText(this, contentStream, upperLeft, drawListener, alignment, TextSequenceUtil.drawText(this, contentStream, upperLeft, drawListener,
getMaxWidth(), getLineSpacing(), alignment, getMaxWidth(), getLineSpacing(), isApplyLineSpacingToFirstLine());
isApplyLineSpacingToFirstLine());
} }
public void drawTextRightAligned(PDPageContentStream contentStream, public void drawTextRightAligned(PDPageContentStream contentStream,

View file

@ -3,6 +3,8 @@ package org.xbib.graphics.pdfbox.layout.text;
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.FontDescriptor; import org.xbib.graphics.pdfbox.layout.font.FontDescriptor;
import org.xbib.graphics.pdfbox.layout.util.TextSequenceUtil;
import java.awt.Color; import java.awt.Color;
import java.io.IOException; import java.io.IOException;
import java.io.UncheckedIOException; import java.io.UncheckedIOException;

View file

@ -19,6 +19,12 @@ public final class PdfUtil {
public static final String NEW_LINE_REGEX = "\\r?\\n"; public static final String NEW_LINE_REGEX = "\\r?\\n";
public static final float MM_TO_UNITS = 1.0f / 25.4f * 72.0f;
public static float mmToPt(float number) {
return number * MM_TO_UNITS;
}
/** /**
* Computes the width of a String (in points). * Computes the width of a String (in points).
* *

View file

@ -1,7 +1,10 @@
package org.xbib.graphics.pdfbox.layout.table.render; package org.xbib.graphics.pdfbox.layout.util;
import static org.xbib.graphics.pdfbox.layout.table.BorderStyle.SOLID; import static org.xbib.graphics.pdfbox.layout.table.BorderStyle.SOLID;
import org.apache.pdfbox.pdmodel.PDPageContentStream; import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.xbib.graphics.pdfbox.layout.table.render.PositionedLine;
import org.xbib.graphics.pdfbox.layout.table.render.PositionedRectangle;
import org.xbib.graphics.pdfbox.layout.table.render.PositionedStyledText;
import java.awt.Color; import java.awt.Color;
import java.io.IOException; import java.io.IOException;

View file

@ -1,11 +1,21 @@
package org.xbib.graphics.pdfbox.layout.text; package org.xbib.graphics.pdfbox.layout.util;
import org.apache.pdfbox.pdmodel.PDPageContentStream; import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.xbib.graphics.pdfbox.layout.elements.Dividable.Divided; import org.xbib.graphics.pdfbox.layout.elements.Dividable.Divided;
import org.xbib.graphics.pdfbox.layout.elements.Paragraph; import org.xbib.graphics.pdfbox.layout.elements.Paragraph;
import org.xbib.graphics.pdfbox.layout.font.FontDescriptor; import org.xbib.graphics.pdfbox.layout.font.FontDescriptor;
import org.xbib.graphics.pdfbox.layout.util.Pair; import org.xbib.graphics.pdfbox.layout.text.Alignment;
import org.xbib.graphics.pdfbox.layout.util.WordBreakerFactory; import org.xbib.graphics.pdfbox.layout.text.DrawListener;
import org.xbib.graphics.pdfbox.layout.text.Indent;
import org.xbib.graphics.pdfbox.layout.text.NewLine;
import org.xbib.graphics.pdfbox.layout.text.Position;
import org.xbib.graphics.pdfbox.layout.text.ReplacedWhitespace;
import org.xbib.graphics.pdfbox.layout.text.StyledText;
import org.xbib.graphics.pdfbox.layout.text.TextFlow;
import org.xbib.graphics.pdfbox.layout.text.TextFragment;
import org.xbib.graphics.pdfbox.layout.text.TextLine;
import org.xbib.graphics.pdfbox.layout.text.TextSequence;
import org.xbib.graphics.pdfbox.layout.text.WrappingNewLine;
import java.io.IOException; import java.io.IOException;
import java.io.UncheckedIOException; import java.io.UncheckedIOException;
import java.util.ArrayList; import java.util.ArrayList;
@ -134,71 +144,47 @@ public class TextSequenceUtil {
return result; return result;
} }
private static WordWrapContext wordWrap(final WordWrapContext context, private static WordWrapContext wordWrap(WordWrapContext context, float maxWidth, TextFlow result) {
final float maxWidth, final TextFlow result) {
TextFragment word = context.getWord(); TextFragment word = context.getWord();
TextFragment moreToWrap = null; TextFragment moreToWrap = null;
float indentation = context.getIndentation(); float indentation = context.getIndentation();
float lineLength = context.getLineLength(); float lineLength = context.getLineLength();
boolean isWrappedLine = context.isWrappedLine(); boolean isWrappedLine = context.isWrappedLine();
if (isWrappedLine && lineLength == indentation) { if (isWrappedLine && lineLength == indentation) {
// start of line, replace leading blanks if
TextFragment[] replaceLeadingBlanks = replaceLeadingBlanks(word); TextFragment[] replaceLeadingBlanks = replaceLeadingBlanks(word);
word = replaceLeadingBlanks[0]; word = replaceLeadingBlanks[0];
if (replaceLeadingBlanks.length > 1) { if (replaceLeadingBlanks.length > 1) {
result.add(replaceLeadingBlanks[1]); result.add(replaceLeadingBlanks[1]);
} }
} }
FontDescriptor fontDescriptor = word.getFontDescriptor(); FontDescriptor fontDescriptor = word.getFontDescriptor();
float length = word.getWidth(); float length = word.getWidth();
if (maxWidth > 0 && lineLength + length > maxWidth) { if (maxWidth > 0 && lineLength + length > maxWidth) {
// word exceeds max width, so create new line
// break hard, if the text does not fit in a full (next) line
boolean breakHard = indentation + length > maxWidth; boolean breakHard = indentation + length > maxWidth;
Pair<TextFragment> brokenWord = breakWord(word, length, maxWidth Pair<TextFragment> brokenWord = breakWord(word, length, maxWidth
- lineLength, maxWidth - indentation, breakHard); - lineLength, maxWidth - indentation, breakHard);
if (brokenWord != null) { if (brokenWord != null) {
// word is broken
word = brokenWord.getFirst(); word = brokenWord.getFirst();
length = word.getWidth(); length = word.getWidth();
moreToWrap = brokenWord.getSecond(); moreToWrap = brokenWord.getSecond();
result.add(word); result.add(word);
if (length > 0) { if (length > 0) {
lineLength += length; lineLength += length;
} }
} else { } else {
if (lineLength == indentation) { if (lineLength == indentation) {
// Begin of line and word could now be broke...
// Well, so we have to use it as it is,
// it won't get any better in the next line
result.add(word); result.add(word);
if (length > 0) { if (length > 0) {
lineLength += length; lineLength += length;
} }
} else { } else {
// give it another try in a new line, there
// will be more space.
moreToWrap = word; moreToWrap = word;
if (result.getLast() != null) { if (result.getLast() != null) {
// since the current word is not used, take
// font descriptor of last line. Otherwise
// the line break might be to high
fontDescriptor = result.getLast().getFontDescriptor(); fontDescriptor = result.getLast().getFontDescriptor();
} }
} }
} }
// wrap line only if not empty
if (lineLength > indentation) { if (lineLength > indentation) {
// and terminate it with a new line
result.add(new WrappingNewLine(fontDescriptor)); result.add(new WrappingNewLine(fontDescriptor));
isWrappedLine = true; isWrappedLine = true;
if (indentation > 0) { if (indentation > 0) {
@ -206,24 +192,20 @@ public class TextSequenceUtil {
} }
lineLength = indentation; lineLength = indentation;
} }
} else { } else {
// word fits, so just add it
result.add(word); result.add(word);
if (length > 0) { if (length > 0) {
lineLength += length; lineLength += length;
} }
} }
return new WordWrapContext(moreToWrap, lineLength, indentation, isWrappedLine);
return new WordWrapContext(moreToWrap, lineLength, indentation,
isWrappedLine);
} }
/** /**
* Replaces leading whitespace by {@link ReplacedWhitespace}. * Replaces leading whitespace by {@link ReplacedWhitespace}.
* *
* @param word the fragment to replace * @param word the fragment to replace
* @return * @return text fragments
*/ */
private static TextFragment[] replaceLeadingBlanks(final TextFragment word) { private static TextFragment[] replaceLeadingBlanks(final TextFragment word) {
String text = word.getText(); String text = word.getText();
@ -232,7 +214,6 @@ public class TextSequenceUtil {
&& Character.isWhitespace(text.charAt(splitIndex))) { && Character.isWhitespace(text.charAt(splitIndex))) {
++splitIndex; ++splitIndex;
} }
if (splitIndex == 0) { if (splitIndex == 0) {
return new TextFragment[]{word}; return new TextFragment[]{word};
} else { } else {
@ -257,7 +238,7 @@ public class TextSequenceUtil {
* @param text the text to de-wrap. * @param text the text to de-wrap.
* @return the de-wrapped text. * @return the de-wrapped text.
*/ */
public static TextFlow deWrap(final TextSequence text) { public static TextFlow deWrap(TextSequence text) {
TextFlow result = new TextFlow(); TextFlow result = new TextFlow();
for (TextFragment fragment : text) { for (TextFragment fragment : text) {
if (fragment instanceof WrappingNewLine) { if (fragment instanceof WrappingNewLine) {
@ -268,7 +249,6 @@ public class TextSequenceUtil {
result.add(fragment); result.add(fragment);
} }
} }
if (text instanceof TextFlow) { if (text instanceof TextFlow) {
result.setLineSpacing(((TextFlow) text).getLineSpacing()); result.setLineSpacing(((TextFlow) text).getLineSpacing());
} }
@ -283,8 +263,7 @@ public class TextSequenceUtil {
* @param maxWidth the max width to fit. * @param maxWidth the max width to fit.
* @return the word-wrapped text lines. * @return the word-wrapped text lines.
*/ */
public static List<TextLine> wordWrapToLines(final TextSequence text, public static List<TextLine> wordWrapToLines(TextSequence text, float maxWidth) {
final float maxWidth) {
return getLines(wordWrap(text, maxWidth)); return getLines(wordWrap(text, maxWidth));
} }
@ -305,11 +284,9 @@ public class TextSequenceUtil {
leftMargin = ((StyledText) text).getLeftMargin(); leftMargin = ((StyledText) text).getLeftMargin();
rightMargin = ((StyledText) text).getRightMargin(); rightMargin = ((StyledText) text).getRightMargin();
} }
String[] words = text.getText().split(" ", -1); String[] words = text.getText().split(" ", -1);
for (int index = 0; index < words.length; ++index) { for (int index = 0; index < words.length; ++index) {
String newWord = index == 0 ? words[index] : " " + words[index]; String newWord = index == 0 ? words[index] : " " + words[index];
float currentLeftMargin = 0; float currentLeftMargin = 0;
float currentRightMargin = 0; float currentRightMargin = 0;
if (index == 0) { if (index == 0) {
@ -336,15 +313,13 @@ public class TextSequenceUtil {
* @param rightMargin the new right margin. * @param rightMargin the new right margin.
* @return the derived text fragment. * @return the derived text fragment.
*/ */
protected static TextFragment deriveFromExisting( protected static TextFragment deriveFromExisting(TextFragment toDeriveFrom, String text, float leftMargin,
final TextFragment toDeriveFrom, final String text, float rightMargin) {
final float leftMargin, final float rightMargin) {
if (toDeriveFrom instanceof StyledText) { if (toDeriveFrom instanceof StyledText) {
return ((StyledText) toDeriveFrom).inheritAttributes(text, return ((StyledText) toDeriveFrom).inheritAttributes(text,
leftMargin, rightMargin); leftMargin, rightMargin);
} }
return new StyledText(text, toDeriveFrom.getFontDescriptor(), return new StyledText(text, toDeriveFrom.getFontDescriptor(), toDeriveFrom.getColor(), 0, leftMargin, rightMargin);
toDeriveFrom.getColor(), 0, leftMargin, rightMargin);
} }
private static Pair<TextFragment> breakWord(TextFragment word, private static Pair<TextFragment> breakWord(TextFragment word,

View file

@ -1,7 +1,7 @@
package org.xbib.graphics.pdfbox.layout.util; package org.xbib.graphics.pdfbox.layout.util;
import org.xbib.graphics.pdfbox.layout.font.FontDescriptor; import org.xbib.graphics.pdfbox.layout.font.FontDescriptor;
import org.xbib.graphics.pdfbox.layout.text.TextSequenceUtil;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;

View file

@ -8,7 +8,6 @@ import org.xbib.graphics.pdfbox.layout.elements.render.ColumnLayout;
import org.xbib.graphics.pdfbox.layout.elements.render.VerticalLayoutHint; import org.xbib.graphics.pdfbox.layout.elements.render.VerticalLayoutHint;
import org.xbib.graphics.pdfbox.layout.font.BaseFont; import org.xbib.graphics.pdfbox.layout.font.BaseFont;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.OutputStream;
public class ColumnsTest { public class ColumnsTest {
@ -33,27 +32,20 @@ public class ColumnsTest {
+ "gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.\n"; + "gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.\n";
Document document = new Document(40, 50, 40, 60); Document document = new Document(40, 50, 40, 60);
Paragraph title = new Paragraph(); Paragraph title = new Paragraph();
title.addMarkup("*This Text is organized in Colums*", 20, BaseFont.TIMES); title.addMarkup("*This Text is organized in Colums*", 20, BaseFont.TIMES);
document.add(title, VerticalLayoutHint.CENTER); document.add(title, VerticalLayoutHint.CENTER);
document.add(new VerticalSpacer(5)); document.add(new VerticalSpacer(5));
document.add(new ColumnLayout().setColumnCount(2).setColumnSpacing(10f));
// use column layout from now on
document.add(new ColumnLayout(2, 10));
Paragraph paragraph1 = new Paragraph(); Paragraph paragraph1 = new Paragraph();
paragraph1.addMarkup(text1, 11, BaseFont.TIMES); paragraph1.addMarkup(text1, 11, BaseFont.TIMES);
document.add(paragraph1); document.add(paragraph1);
Paragraph paragraph2 = new Paragraph(); Paragraph paragraph2 = new Paragraph();
paragraph2.addMarkup(text2, 12, BaseFont.HELVETICA); paragraph2.addMarkup(text2, 12, BaseFont.HELVETICA);
document.add(paragraph2); document.add(paragraph2);
Paragraph paragraph3 = new Paragraph(); Paragraph paragraph3 = new Paragraph();
paragraph3.addMarkup(text1, 8, BaseFont.COURIER); paragraph3.addMarkup(text1, 8, BaseFont.COURIER);
document.add(paragraph3); document.add(paragraph3);
document.add(paragraph1); document.add(paragraph1);
document.add(paragraph3); document.add(paragraph3);
document.add(paragraph1); document.add(paragraph1);

View file

@ -18,7 +18,7 @@ import org.xbib.graphics.pdfbox.layout.font.BaseFont;
import org.xbib.graphics.pdfbox.layout.text.Position; import org.xbib.graphics.pdfbox.layout.text.Position;
import org.xbib.graphics.pdfbox.layout.text.TextFlow; import org.xbib.graphics.pdfbox.layout.text.TextFlow;
import org.xbib.graphics.pdfbox.layout.text.TextFlowUtil; import org.xbib.graphics.pdfbox.layout.text.TextFlowUtil;
import org.xbib.graphics.pdfbox.layout.text.TextSequenceUtil; import org.xbib.graphics.pdfbox.layout.util.TextSequenceUtil;
import java.awt.Color; import java.awt.Color;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;

View file

@ -49,11 +49,9 @@ public class LandscapeTest {
PageFormat a5_landscape = PageFormat.builder().A5().landscape().margins(10, 50, 0, 30).build(); PageFormat a5_landscape = PageFormat.builder().A5().landscape().margins(10, 50, 0, 30).build();
PageFormat a4_portrait = PageFormat.builder().margins(40, 50, 40, 60).build(); PageFormat a4_portrait = PageFormat.builder().margins(40, 50, 40, 60).build();
Document document = new Document(a4_portrait); Document document = new Document(a4_portrait);
document.add(titleA4, VerticalLayoutHint.CENTER); document.add(titleA4, VerticalLayoutHint.CENTER);
document.add(new VerticalSpacer(5)); document.add(new VerticalSpacer(5));
document.add(new ColumnLayout(2, 10)); document.add(new ColumnLayout().setColumnCount(2).setColumnSpacing(10f));
document.add(paragraph2); document.add(paragraph2);
document.add(paragraph1); document.add(paragraph1);
document.add(paragraph1); document.add(paragraph1);
@ -68,7 +66,7 @@ public class LandscapeTest {
document.add(new VerticalLayout()); document.add(new VerticalLayout());
document.add(titleA5, VerticalLayoutHint.CENTER); document.add(titleA5, VerticalLayoutHint.CENTER);
document.add(new VerticalSpacer(5)); document.add(new VerticalSpacer(5));
document.add(new ColumnLayout(2, 10)); document.add(new ColumnLayout().setColumnCount(2).setColumnSpacing(10f));
document.add(paragraph1); document.add(paragraph1);
document.add(paragraph3); document.add(paragraph3);
@ -80,7 +78,7 @@ public class LandscapeTest {
document.add(new VerticalLayout()); document.add(new VerticalLayout());
document.add(titleA4, VerticalLayoutHint.CENTER); document.add(titleA4, VerticalLayoutHint.CENTER);
document.add(new VerticalSpacer(5)); document.add(new VerticalSpacer(5));
document.add(new ColumnLayout(2, 10)); document.add(new ColumnLayout().setColumnCount(2).setColumnSpacing(10f));
document.add(paragraph2); document.add(paragraph2);
document.add(paragraph1); document.add(paragraph1);
@ -96,7 +94,7 @@ public class LandscapeTest {
document.add(new VerticalLayout()); document.add(new VerticalLayout());
document.add(titleA5, VerticalLayoutHint.CENTER); document.add(titleA5, VerticalLayoutHint.CENTER);
document.add(new VerticalSpacer(5)); document.add(new VerticalSpacer(5));
document.add(new ColumnLayout(2, 10)); document.add(new ColumnLayout().setColumnCount(2).setColumnSpacing(10f));
document.add(paragraph1); document.add(paragraph1);
document.add(paragraph3); document.add(paragraph3);

View file

@ -22,7 +22,7 @@ public class LineSpacingTest {
// create document without margins // create document without margins
Document document = new Document(); Document document = new Document();
document.add(new ColumnLayout(2, 5)); document.add(new ColumnLayout().setColumnCount(2).setColumnSpacing(5f));
Paragraph left = new Paragraph(); Paragraph left = new Paragraph();
// no line spacing for the first line // no line spacing for the first line

View file

@ -11,7 +11,7 @@ import org.xbib.graphics.pdfbox.layout.font.BaseFont;
import org.xbib.graphics.pdfbox.layout.text.Position; import org.xbib.graphics.pdfbox.layout.text.Position;
import org.xbib.graphics.pdfbox.layout.text.TextFlow; import org.xbib.graphics.pdfbox.layout.text.TextFlow;
import org.xbib.graphics.pdfbox.layout.text.TextFlowUtil; import org.xbib.graphics.pdfbox.layout.text.TextFlowUtil;
import org.xbib.graphics.pdfbox.layout.text.TextSequenceUtil; import org.xbib.graphics.pdfbox.layout.util.TextSequenceUtil;
import java.io.FileOutputStream; import java.io.FileOutputStream;
public class ListenerTest { public class ListenerTest {

View file

@ -15,7 +15,7 @@ import org.xbib.graphics.pdfbox.layout.text.DrawContext;
import org.xbib.graphics.pdfbox.layout.text.Position; import org.xbib.graphics.pdfbox.layout.text.Position;
import org.xbib.graphics.pdfbox.layout.text.TextFlow; import org.xbib.graphics.pdfbox.layout.text.TextFlow;
import org.xbib.graphics.pdfbox.layout.text.TextFlowUtil; import org.xbib.graphics.pdfbox.layout.text.TextFlowUtil;
import org.xbib.graphics.pdfbox.layout.text.TextSequenceUtil; import org.xbib.graphics.pdfbox.layout.util.TextSequenceUtil;
import org.xbib.graphics.pdfbox.layout.text.annotations.AnnotationDrawListener; import org.xbib.graphics.pdfbox.layout.text.annotations.AnnotationDrawListener;
import java.awt.Color; import java.awt.Color;
import java.io.FileOutputStream; import java.io.FileOutputStream;

View file

@ -53,7 +53,7 @@ public class RotationTest {
document.add(titleA4, VerticalLayoutHint.CENTER); document.add(titleA4, VerticalLayoutHint.CENTER);
document.add(new VerticalSpacer(5)); document.add(new VerticalSpacer(5));
document.add(new ColumnLayout(2, 10)); document.add(new ColumnLayout().setColumnCount(2).setColumnSpacing(10f));
document.add(paragraph2); document.add(paragraph2);
document.add(paragraph1); document.add(paragraph1);
@ -68,7 +68,7 @@ public class RotationTest {
document.add(new VerticalLayout()); document.add(new VerticalLayout());
document.add(titleA5, VerticalLayoutHint.CENTER); document.add(titleA5, VerticalLayoutHint.CENTER);
document.add(new VerticalSpacer(5)); document.add(new VerticalSpacer(5));
document.add(new ColumnLayout(2, 10)); document.add(new ColumnLayout().setColumnCount(2).setColumnSpacing(10f));
document.add(paragraph2); document.add(paragraph2);
document.add(paragraph1); document.add(paragraph1);
@ -83,7 +83,7 @@ public class RotationTest {
document.add(new VerticalLayout()); document.add(new VerticalLayout());
document.add(titleA4, VerticalLayoutHint.CENTER); document.add(titleA4, VerticalLayoutHint.CENTER);
document.add(new VerticalSpacer(5)); document.add(new VerticalSpacer(5));
document.add(new ColumnLayout(2, 10)); document.add(new ColumnLayout().setColumnCount(2).setColumnSpacing(10f));
document.add(paragraph2); document.add(paragraph2);
document.add(paragraph1); document.add(paragraph1);
@ -98,7 +98,7 @@ public class RotationTest {
document.add(new VerticalLayout()); document.add(new VerticalLayout());
document.add(titleA5, VerticalLayoutHint.CENTER); document.add(titleA5, VerticalLayoutHint.CENTER);
document.add(new VerticalSpacer(5)); document.add(new VerticalSpacer(5));
document.add(new ColumnLayout(2, 10)); document.add(new ColumnLayout().setColumnCount(2).setColumnSpacing(10f));
document.add(paragraph2); document.add(paragraph2);
document.add(paragraph1); document.add(paragraph1);

View file

@ -22,4 +22,19 @@ public class ScriptTest {
} }
engine.close(); engine.close();
} }
@Test
public void deckblatt() throws Exception {
Settings settings = Settings.settingsBuilder()
.loadFromResource("json", getClass().getResourceAsStream("deckblatt.json"))
.build();
Engine engine = new Engine();
engine.execute(settings);
int i = 0;
for (Document document : engine.getState().getDocuments()) {
document.render().save(new FileOutputStream("build/deckblatt" + (i++) + ".pdf")).close();
}
engine.close();
}
} }

View file

@ -0,0 +1,108 @@
{
"type": "document",
"margin": "10 10 10 10",
"author": "Jörg Prante",
"creator": "org.xbib.graphics.pdfbox.layout",
"elements": [
{
"type": "image",
"x": 10,
"y": 290,
"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=="
},
{
"type": "text",
"x": 70,
"y": 290,
"value": "*Aufsatzbestellung*",
"fontsize": 24
},
{
"type": "barcode",
"x": 70,
"y": 280,
"symbol": "Code3Of9Extended",
"value": "1234567890",
"scalex": 2.0,
"scaley": 1.0
},
{
"type": "table",
"x": 10,
"y": 260,
"columnwidths": "40 150",
"elements": [
{
"type": "row",
"elements": [
{
"type": "cell",
"markup": "*This* is markup"
},
{
"type": "cell",
"value": "Hello World"
}
]
},
{
"type": "row",
"elements": [
{
"type": "cell",
"markup": "*This* is markup",
"fontsize": 12
},
{
"type": "cell",
"markup": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
"fontsize": 12
}
]
},
{
"type": "row",
"elements": [
{
"type": "horizontalruler",
"linewidth": 0.5
},
{
"type": "horizontalruler",
"linewidth": 0.5
}
]
},
{
"type": "row",
"elements": [
{
"type": "cell",
"markup": "*This* is markup"
},
{
"type": "cell",
"value": "Hello World",
"fontsize": 20
}
]
},
{
"type": "row",
"elements": [
{
"type": "cell",
"markup": "*This* is markup"
},
{
"type": "cell",
"value": "Hello World",
"fontsize": 36
}
]
}
]
}
]
}