add rotation, work on positions, add transform command

This commit is contained in:
Jörg Prante 2022-01-18 18:36:58 +01:00
parent d7066d586e
commit 630d50bce7
38 changed files with 366 additions and 134 deletions

View file

@ -24,6 +24,6 @@ public class ControlElement implements Element {
@Override @Override
public String toString() { public String toString() {
return "ControlElement [NEWPAGE=" + NEWPAGE + ", name=" + name + "]"; return "ControlElement [name=" + name + "]";
} }
} }

View file

@ -251,6 +251,16 @@ public class PageFormat implements Element {
return this; return this;
} }
public PageFormatBuilder mediaBox(float x, float y, float width, float height) {
PDRectangle rectangle = new PDRectangle();
rectangle.setLowerLeftX(x);
rectangle.setLowerLeftY(y);
rectangle.setUpperRightX(x + width);
rectangle.setUpperRightY(y + height);
mediaBox(rectangle);
return this;
}
/** /**
* Sets the media box to the given size. * Sets the media box to the given size.
* *

View file

@ -64,8 +64,10 @@ public class PathElement implements Drawable, Element {
} }
@Override @Override
public void draw(PDDocument pdDocument, PDPageContentStream contentStream, public void draw(PDDocument pdDocument,
Position upperLeft, DrawListener drawListener) throws IOException { PDPageContentStream contentStream,
Position upperLeft,
DrawListener drawListener) throws IOException {
path.draw(pdDocument, contentStream, upperLeft, getWidth(), getHeight(), color, stroke, drawListener); path.draw(pdDocument, contentStream, upperLeft, getWidth(), getHeight(), color, stroke, drawListener);
} }

View file

@ -0,0 +1,74 @@
package org.xbib.graphics.pdfbox.layout.element;
import java.io.IOException;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.util.Matrix;
import org.xbib.graphics.pdfbox.layout.text.DrawListener;
import org.xbib.graphics.pdfbox.layout.text.Position;
public class TransformElement implements Element, Drawable {
private Float translateX;
private Float translateY;
private Float scaleX;
private Float scaleY;
private Float rotateX;
private Float rotateY;
private Float angle;
@Override
public float getWidth() throws IOException {
return 0;
}
@Override
public float getHeight() throws IOException {
return 0;
}
@Override
public Position getAbsolutePosition() throws IOException {
return null;
}
@Override
public Drawable removeLeadingEmptyVerticalSpace() throws IOException {
return this;
}
public void setTranslate(Float x, Float y) {
this.translateX = x;
this.translateY = y;
}
public void setScale(Float scaleX, Float scaleY) {
this.scaleX = scaleX;
this.scaleY = scaleY;
}
public void setRotate(Float angle, Float rotateX, Float rotateY) {
this.angle = angle;
this.rotateX = rotateX;
this.rotateY = rotateY;
}
@Override
public void draw(PDDocument pdDocument, PDPageContentStream contentStream, Position upperLeft, DrawListener drawListener) throws IOException {
if (translateX != null && translateY != null) {
contentStream.transform(Matrix.getTranslateInstance(translateX, translateY));
}
if (scaleX != null && scaleY != null) {
contentStream.transform(Matrix.getScaleInstance(scaleX, scaleY));
}
if (angle != null && rotateX != null && rotateY != null){
contentStream.transform(Matrix.getRotateInstance(Math.toRadians(angle), rotateX, rotateY));
}
}
}

View file

@ -9,4 +9,6 @@ import org.xbib.graphics.pdfbox.layout.element.Element;
* to layout the element. * to layout the element.
*/ */
public interface LayoutHint { public interface LayoutHint {
LayoutHint NOP = new VerticalLayoutHint.VerticalLayoutHintBuilder().resetY(false).build();
} }

View file

@ -153,8 +153,7 @@ public class RenderContext implements Renderer, Closeable, DrawContext, DrawList
* current y. * current y.
*/ */
public void resetPositionToLeft() { public void resetPositionToLeft() {
currentPosition = new Position(getUpperLeft().getX(), currentPosition = new Position(getUpperLeft().getX(), currentPosition.getY());
currentPosition.getY());
} }
/** /**
@ -162,8 +161,7 @@ public class RenderContext implements Renderer, Closeable, DrawContext, DrawList
* y of {@link #getMaxPositionOnPage()}. * y of {@link #getMaxPositionOnPage()}.
*/ */
protected void resetPositionToLeftEndOfPage() { protected void resetPositionToLeftEndOfPage() {
currentPosition = new Position(getUpperLeft().getX(), currentPosition = new Position(getUpperLeft().getX(), getMaxPositionOnPage().getY());
getMaxPositionOnPage().getY());
} }
/** /**
@ -339,7 +337,6 @@ public class RenderContext implements Renderer, Closeable, DrawContext, DrawList
this.page = new PDPage(getPageFormat().getMediaBox()); this.page = new PDPage(getPageFormat().getMediaBox());
this.pdDocument.addPage(page); this.pdDocument.addPage(page);
this.contentStream = new PDPageContentStream(pdDocument, page, PDPageContentStream.AppendMode.APPEND, true); this.contentStream = new PDPageContentStream(pdDocument, page, PDPageContentStream.AppendMode.APPEND, true);
// fix orientation
if (getPageOrientation() != getPageFormat().getOrientation()) { if (getPageOrientation() != getPageFormat().getOrientation()) {
if (isPageTilted()) { if (isPageTilted()) {
page.setRotation(0); page.setRotation(0);

View file

@ -78,10 +78,9 @@ public class VerticalLayout implements Layout {
public void render(RenderContext renderContext, Drawable drawable, LayoutHint layoutHint) throws IOException { public void render(RenderContext renderContext, Drawable drawable, LayoutHint layoutHint) throws IOException {
if (drawable.getAbsolutePosition() != null) { if (drawable.getAbsolutePosition() != null) {
renderAbsolute(renderContext, drawable, layoutHint, renderAbsolute(renderContext, drawable, drawable.getAbsolutePosition());
drawable.getAbsolutePosition());
} else { } else {
renderReleative(renderContext, drawable, layoutHint); renderRelative(renderContext, drawable, layoutHint);
} }
} }
@ -90,12 +89,12 @@ public class VerticalLayout implements Layout {
* *
* @param renderContext the context providing all rendering state. * @param renderContext the context providing all rendering state.
* @param drawable the drawable to draw. * @param drawable the drawable to draw.
* @param layoutHint the layout hint used to layout.
* @param position the left upper position to start drawing at. * @param position the left upper position to start drawing at.
* @throws IOException by pdfbox * @throws IOException by pdfbox
*/ */
protected void renderAbsolute(RenderContext renderContext, protected void renderAbsolute(RenderContext renderContext,
Drawable drawable, LayoutHint layoutHint, Position position) throws IOException { Drawable drawable,
Position position) throws IOException {
drawable.draw(renderContext.getPdDocument(), renderContext.getContentStream(), position, renderContext); drawable.draw(renderContext.getPdDocument(), renderContext.getContentStream(), position, renderContext);
} }
@ -104,29 +103,27 @@ public class VerticalLayout implements Layout {
* current position}. This method is responsible taking any top or bottom * current position}. This method is responsible taking any top or bottom
* margin described by the (Vertical-)LayoutHint into account. The actual * margin described by the (Vertical-)LayoutHint into account. The actual
* rendering of the drawable is performed by * rendering of the drawable is performed by
* {@link #layoutAndDrawReleative(RenderContext, Drawable, LayoutHint)}. * {@link #layoutAndDrawRelative(RenderContext, Drawable, LayoutHint)}.
* *
* @param renderContext the context providing all rendering state. * @param renderContext the context providing all rendering state.
* @param drawable the drawable to draw. * @param drawable the drawable to draw.
* @param layoutHint the layout hint used to layout. * @param layoutHint the layout hint used to layout.
* @throws IOException by pdfbox * @throws IOException by pdfbox
*/ */
protected void renderReleative(RenderContext renderContext, protected void renderRelative(RenderContext renderContext,
Drawable drawable, LayoutHint layoutHint) throws IOException { Drawable drawable,
LayoutHint layoutHint) throws IOException {
VerticalLayoutHint verticalLayoutHint = null; VerticalLayoutHint verticalLayoutHint = null;
if (layoutHint instanceof VerticalLayoutHint) { if (layoutHint instanceof VerticalLayoutHint) {
verticalLayoutHint = (VerticalLayoutHint) layoutHint; verticalLayoutHint = (VerticalLayoutHint) layoutHint;
if (verticalLayoutHint.getMarginTop() > 0) { if (verticalLayoutHint.getMarginTop() > 0) {
layoutAndDrawReleative(renderContext, new VerticalSpacer( layoutAndDrawRelative(renderContext, new VerticalSpacer(verticalLayoutHint.getMarginTop()), verticalLayoutHint);
verticalLayoutHint.getMarginTop()), verticalLayoutHint);
} }
} }
layoutAndDrawReleative(renderContext, drawable, verticalLayoutHint); layoutAndDrawRelative(renderContext, drawable, verticalLayoutHint);
if (verticalLayoutHint != null) { if (verticalLayoutHint != null) {
if (verticalLayoutHint.getMarginBottom() > 0) { if (verticalLayoutHint.getMarginBottom() > 0) {
layoutAndDrawReleative(renderContext, new VerticalSpacer( layoutAndDrawRelative(renderContext, new VerticalSpacer(verticalLayoutHint.getMarginBottom()), verticalLayoutHint);
verticalLayoutHint.getMarginBottom()),
verticalLayoutHint);
} }
} }
} }
@ -135,7 +132,7 @@ public class VerticalLayout implements Layout {
* Adjusts the width of the drawable (if it is {@link WidthRespecting}), and * Adjusts the width of the drawable (if it is {@link WidthRespecting}), and
* divides it onto multiple pages if necessary. Actual drawing is delegated * divides it onto multiple pages if necessary. Actual drawing is delegated
* to * to
* {@link #drawReletivePartAndMovePosition(RenderContext, Drawable, LayoutHint, boolean)} * {@link #drawRelativePartAndMovePosition(RenderContext, Drawable, LayoutHint, boolean)}
* . * .
* *
* @param renderContext the context providing all rendering state. * @param renderContext the context providing all rendering state.
@ -143,11 +140,12 @@ public class VerticalLayout implements Layout {
* @param layoutHint the layout hint used to layout. * @param layoutHint the layout hint used to layout.
* @throws IOException by pdfbox * @throws IOException by pdfbox
*/ */
protected void layoutAndDrawReleative(RenderContext renderContext, protected void layoutAndDrawRelative(RenderContext renderContext,
Drawable drawable, LayoutHint layoutHint) throws IOException { Drawable drawable,
LayoutHint layoutHint) throws IOException {
float targetWidth = getTargetWidth(renderContext); float targetWidth = getTargetWidth(renderContext);
boolean movePosition = true; boolean movePosition = true;
VerticalLayoutHint verticalLayoutHint = null; VerticalLayoutHint verticalLayoutHint;
if (layoutHint instanceof VerticalLayoutHint) { if (layoutHint instanceof VerticalLayoutHint) {
verticalLayoutHint = (VerticalLayoutHint) layoutHint; verticalLayoutHint = (VerticalLayoutHint) layoutHint;
targetWidth -= verticalLayoutHint.getMarginLeft(); targetWidth -= verticalLayoutHint.getMarginLeft();
@ -171,17 +169,13 @@ public class VerticalLayout implements Layout {
dividable = new Cutter(drawablePart); dividable = new Cutter(drawablePart);
} }
Dividable.Divided divided = dividable.divide(renderContext.getRemainingHeight(), renderContext.getHeight()); Dividable.Divided divided = dividable.divide(renderContext.getRemainingHeight(), renderContext.getHeight());
drawReletivePartAndMovePosition(renderContext, divided.getFirst(), drawRelativePartAndMovePosition(renderContext, divided.getFirst(), layoutHint, true);
layoutHint, true);
// new page // new page
turnPage(renderContext); turnPage(renderContext);
drawablePart = divided.getTail(); drawablePart = divided.getTail();
drawablePart = removeLeadingEmptyVerticalSpace(drawablePart, renderContext); drawablePart = removeLeadingEmptyVerticalSpace(drawablePart, renderContext);
} }
drawRelativePartAndMovePosition(renderContext, drawablePart, layoutHint, movePosition);
drawReletivePartAndMovePosition(renderContext, drawablePart,
layoutHint, movePosition);
if (drawable instanceof WidthRespecting) { if (drawable instanceof WidthRespecting) {
if (oldMaxWidth < 0) { if (oldMaxWidth < 0) {
((WidthRespecting) drawable).setMaxWidth(oldMaxWidth); ((WidthRespecting) drawable).setMaxWidth(oldMaxWidth);
@ -199,14 +193,13 @@ public class VerticalLayout implements Layout {
* @param renderContext the context providing all rendering state. * @param renderContext the context providing all rendering state.
* @param drawable the drawable to draw. * @param drawable the drawable to draw.
* @param layoutHint the layout hint used to layout. * @param layoutHint the layout hint used to layout.
* @param movePosition indicates if the position should be moved (vertically) after * @param movePosition indicates if the position should be moved (vertically) after drawing.
* drawing.
* @throws IOException by pdfbox * @throws IOException by pdfbox
*/ */
protected void drawReletivePartAndMovePosition( protected void drawRelativePartAndMovePosition(RenderContext renderContext,
final RenderContext renderContext, Drawable drawable, Drawable drawable,
final LayoutHint layoutHint, final boolean movePosition) LayoutHint layoutHint,
throws IOException { boolean movePosition) throws IOException {
PDPageContentStream contentStream = renderContext.getContentStream(); PDPageContentStream contentStream = renderContext.getContentStream();
PageFormat pageFormat = renderContext.getPageFormat(); PageFormat pageFormat = renderContext.getPageFormat();
float offsetX = 0; float offsetX = 0;

View file

@ -47,7 +47,7 @@ public class BarcodeCommand implements Command {
} }
Alignment alignment = Alignment.valueOf(settings.get("alignment", "left").toUpperCase(Locale.ROOT)); Alignment alignment = Alignment.valueOf(settings.get("alignment", "left").toUpperCase(Locale.ROOT));
String margin = settings.get("margin", "0 0 0 0"); String margin = settings.get("margin", "0 0 0 0");
String[] margins = margin.split(" "); String[] margins = margin.split("\\s+");
float marginleft = Float.parseFloat(margins[0]); float marginleft = Float.parseFloat(margins[0]);
float marginright = Float.parseFloat(margins[1]); float marginright = Float.parseFloat(margins[1]);
float margintop = Float.parseFloat(margins[2]); float margintop = Float.parseFloat(margins[2]);

View file

@ -32,7 +32,7 @@ public class CellCommand implements Command {
TextCell.Builder cell = TextCell.builder(); TextCell.Builder cell = TextCell.builder();
if (settings.containsSetting("padding")) { if (settings.containsSetting("padding")) {
String padding = settings.get("padding", "0 0 0 0"); String padding = settings.get("padding", "0 0 0 0");
String[] paddings = padding.split(" "); String[] paddings = padding.split("\\s+");
float paddingLeft = Float.parseFloat(paddings[0]); float paddingLeft = Float.parseFloat(paddings[0]);
float paddingRight = Float.parseFloat(paddings[1]); float paddingRight = Float.parseFloat(paddings[1]);
float paddingTop = Float.parseFloat(paddings[2]); float paddingTop = Float.parseFloat(paddings[2]);

View file

@ -44,7 +44,7 @@ public class ChartCommand implements Command {
} }
Alignment alignment = Alignment.valueOf(settings.get("alignment", "left").toUpperCase(Locale.ROOT)); Alignment alignment = Alignment.valueOf(settings.get("alignment", "left").toUpperCase(Locale.ROOT));
String margin = settings.get("margin", "0 0 0 0"); String margin = settings.get("margin", "0 0 0 0");
String[] margins = margin.split(" "); String[] margins = margin.split("\\s+");
float marginleft = Float.parseFloat(margins[0]); float marginleft = Float.parseFloat(margins[0]);
float marginright = Float.parseFloat(margins[1]); float marginright = Float.parseFloat(margins[1]);
float margintop = Float.parseFloat(margins[2]); float margintop = Float.parseFloat(margins[2]);

View file

@ -10,36 +10,63 @@ import java.io.IOException;
import java.time.Instant; import java.time.Instant;
import java.util.Locale; import java.util.Locale;
import static org.xbib.graphics.pdfbox.layout.util.PdfUtil.mmToPt;
public class DocumentCommand implements Command { public class DocumentCommand implements Command {
@Override @Override
public void execute(Engine engine, State state, Settings settings) throws IOException { public void execute(Engine engine, State state, Settings settings) throws IOException {
String margin = settings.get("margin", "0 0 0 0"); PageFormat.PageFormatBuilder pageFormat = PageFormat.builder();
String[] margins = margin.split(" "); if (settings.containsSetting("pageformat")) {
PageFormat pageFormat = PageFormat.builder() pageFormat.pageFormat(settings.get("pageformat", "A4"));
.marginLeft(Float.parseFloat(margins[0])) }
.marginRight(Float.parseFloat(margins[1])) if (settings.containsSetting("mediabox")) {
.marginTop(Float.parseFloat(margins[2])) String mediabox = settings.get("mediabox");
.marginBottom(Float.parseFloat(margins[3])) String[] s = mediabox.split("\\s+");
.pageFormat(settings.get("format", "A4")) // x y width height
.orientation(settings.get("orientiation", "portrait").toUpperCase(Locale.ROOT)) pageFormat.mediaBox(mmToPt(Float.parseFloat(s[0])), mmToPt(Float.parseFloat(s[1])),
.build(); mmToPt(Float.parseFloat(s[2])), mmToPt(Float.parseFloat(s[3])));
Document document = new Document(pageFormat); }
Instant instant = Instant.now(); pageFormat.orientation(settings.get("orientation", "portrait").toUpperCase(Locale.ROOT));
document.setCreationDate(instant); if (settings.containsSetting("margin")) {
document.setModificationDate(instant); String margin = settings.get("margin", "0 0 0 0");
String[] margins = margin.split("\\s+");
pageFormat
.marginLeft(Float.parseFloat(margins[0]))
.marginRight(Float.parseFloat(margins[1]))
.marginTop(Float.parseFloat(margins[2]))
.marginBottom(Float.parseFloat(margins[3]));
}
Document document = new Document(pageFormat.build());
if (settings.containsSetting("author")) { if (settings.containsSetting("author")) {
document.setAuthor(settings.get("author")); document.setAuthor(settings.get("author"));
} }
if (settings.containsSetting("creator")) { if (settings.containsSetting("creator")) {
document.setCreator(settings.get("creator")); document.setCreator(settings.get("creator"));
} }
if (settings.containsSetting("producer")) {
document.setProducer(settings.get("producer"));
}
if (settings.containsSetting("subject")) { if (settings.containsSetting("subject")) {
document.setSubject(settings.get("subject")); document.setSubject(settings.get("subject"));
} }
if (settings.containsSetting("title")) { if (settings.containsSetting("title")) {
document.setTitle(settings.get("title")); document.setTitle(settings.get("title"));
} }
if (settings.containsSetting("keywords")) {
document.setKeywords(settings.get("keywords"));
}
Instant instant = Instant.now();
if (settings.containsSetting("creationdate")) {
document.setCreationDate(Instant.parse(settings.get("creationdate")));
} else {
document.setCreationDate(instant);
}
if (settings.containsSetting("modificationddate")) {
document.setModificationDate(Instant.parse(settings.get("modificationddate")));
} else {
document.setModificationDate(instant);
}
state.elements.push(document); state.elements.push(document);
engine.executeElements(settings); engine.executeElements(settings);
} }

View file

@ -18,7 +18,7 @@ public class HorizontalrulerCommand implements Command {
@Override @Override
public void execute(Engine engine, State state, Settings settings) throws IOException { public void execute(Engine engine, State state, Settings settings) throws IOException {
Stroke.StrokeBuilder strokeBuilder = Stroke.builder() Stroke.StrokeBuilder strokeBuilder = Stroke.builder()
.capStyle(Stroke.CapStyle.valueOf(settings.get("capstyie", "cap").toUpperCase(Locale.ROOT))) .capStyle(Stroke.CapStyle.valueOf(settings.get("capstyle", "cap").toUpperCase(Locale.ROOT)))
.joinStyle(Stroke.JoinStyle.valueOf(settings.get("joinstyle", "miter").toUpperCase(Locale.ROOT))) .joinStyle(Stroke.JoinStyle.valueOf(settings.get("joinstyle", "miter").toUpperCase(Locale.ROOT)))
.lineWidth(settings.getAsFloat("linewidth", 1f)); .lineWidth(settings.getAsFloat("linewidth", 1f));
if (settings.containsSetting("dash")) { if (settings.containsSetting("dash")) {

View file

@ -42,7 +42,7 @@ public class ImageCommand implements Command {
} }
Alignment alignment = Alignment.valueOf(settings.get("alignment", "left").toUpperCase(Locale.ROOT)); Alignment alignment = Alignment.valueOf(settings.get("alignment", "left").toUpperCase(Locale.ROOT));
String margin = settings.get("margin", "0 0 0 0"); String margin = settings.get("margin", "0 0 0 0");
String[] margins = margin.split(" "); String[] margins = margin.split("\\s+");
float marginleft = Float.parseFloat(margins[0]); float marginleft = Float.parseFloat(margins[0]);
float marginright = Float.parseFloat(margins[1]); float marginright = Float.parseFloat(margins[1]);
float margintop = Float.parseFloat(margins[2]); float margintop = Float.parseFloat(margins[2]);

View file

@ -28,14 +28,17 @@ public class ParagraphCommand implements Command {
paragraph.setAlignment(Alignment.valueOf(settings.get("alignment", "left").toUpperCase(Locale.ROOT))); paragraph.setAlignment(Alignment.valueOf(settings.get("alignment", "left").toUpperCase(Locale.ROOT)));
} }
if (settings.containsSetting("linespacing")) { if (settings.containsSetting("linespacing")) {
paragraph.setLineSpacing(settings.getAsFloat("linespacing", -1f)); paragraph.setLineSpacing(settings.getAsFloat("linespacing", 1.2f));
}
if (settings.containsSetting("rotation")) {
paragraph.setRotation(settings.getAsFloat("rotation", 0f));
} }
state.elements.push(paragraph); state.elements.push(paragraph);
engine.executeElements(settings); engine.executeElements(settings);
state.elements.pop(); state.elements.pop();
Alignment alignment = Alignment.valueOf(settings.get("layout.alignment", "left").toUpperCase(Locale.ROOT)); Alignment alignment = Alignment.valueOf(settings.get("layout.alignment", "left").toUpperCase(Locale.ROOT));
String margin = settings.get("layout.margin", "0 0 0 0"); String margin = settings.get("layout.margin", "0 0 0 0");
String[] margins = margin.split(" "); String[] margins = margin.split("\\s+");
float marginleft = Float.parseFloat(margins[0]); float marginleft = Float.parseFloat(margins[0]);
float marginright = Float.parseFloat(margins[1]); float marginright = Float.parseFloat(margins[1]);
float margintop = Float.parseFloat(margins[2]); float margintop = Float.parseFloat(margins[2]);

View file

@ -2,8 +2,11 @@ package org.xbib.graphics.pdfbox.layout.element.scripting.command;
import org.xbib.graphics.pdfbox.layout.color.ColorFactory; import org.xbib.graphics.pdfbox.layout.color.ColorFactory;
import org.xbib.graphics.pdfbox.layout.element.PathElement; import org.xbib.graphics.pdfbox.layout.element.PathElement;
import org.xbib.graphics.pdfbox.layout.element.render.LayoutHint;
import org.xbib.graphics.pdfbox.layout.element.scripting.Engine; import org.xbib.graphics.pdfbox.layout.element.scripting.Engine;
import org.xbib.graphics.pdfbox.layout.element.scripting.State; import org.xbib.graphics.pdfbox.layout.element.scripting.State;
import org.xbib.graphics.pdfbox.layout.shape.LinePosiiton;
import org.xbib.graphics.pdfbox.layout.shape.MovePosition;
import org.xbib.graphics.pdfbox.layout.shape.Path; import org.xbib.graphics.pdfbox.layout.shape.Path;
import org.xbib.graphics.pdfbox.layout.shape.Stroke; import org.xbib.graphics.pdfbox.layout.shape.Stroke;
import org.xbib.graphics.pdfbox.layout.text.Position; import org.xbib.graphics.pdfbox.layout.text.Position;
@ -13,6 +16,7 @@ import java.awt.Color;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import static org.xbib.graphics.pdfbox.layout.util.PdfUtil.mmToPt;
public class PathCommand implements Command { public class PathCommand implements Command {
@ -23,30 +27,40 @@ public class PathCommand implements Command {
return; return;
} }
List<Position> list = new ArrayList<>(); List<Position> list = new ArrayList<>();
String[] s = value.split(" "); String[] s = value.split("\\s+");
Position position = null; Position position = null; //new Position(0, 0);
if (s.length > 0) { if (s.length > 0) {
if (settings.getAsBoolean("absolute", false)) { for (int i = 0; i < s.length; i += 3) {
position = new Position(Float.parseFloat(s[0]), Float.parseFloat(s[1])); String command = s[i];
list.add(position); float x = mmToPt(Float.parseFloat(s[i + 1]));
} else { float y = mmToPt(Float.parseFloat(s[i + 2]));
Position p = new Position(Float.parseFloat(s[0]), Float.parseFloat(s[1])); Position p;
list.add(p); switch (command.toUpperCase(Locale.ROOT)) {
} case "M":
for (int i = 2; i < s.length; i += 2) { p = new MovePosition(x, y);
Position p = new Position(Float.parseFloat(s[i]), Float.parseFloat(s[i + 1])); break;
case "L":
p = new LinePosiiton(x, y);
break;
default:
p = new Position(x, y);
break;
}
list.add(p); list.add(p);
if (i == 0 && settings.getAsBoolean("position", false)) {
position = p;
}
} }
} }
Path path = new Path(list); Path path = new Path(list);
Stroke.StrokeBuilder strokeBuilder = Stroke.builder() Stroke.StrokeBuilder strokeBuilder = Stroke.builder()
.capStyle(Stroke.CapStyle.valueOf(settings.get("capstyie", "cap").toUpperCase(Locale.ROOT))) .capStyle(Stroke.CapStyle.valueOf(settings.get("capstyle", "cap").toUpperCase(Locale.ROOT)))
.joinStyle(Stroke.JoinStyle.valueOf(settings.get("joinstyle", "miter").toUpperCase(Locale.ROOT))) .joinStyle(Stroke.JoinStyle.valueOf(settings.get("joinstyle", "miter").toUpperCase(Locale.ROOT)))
.lineWidth(settings.getAsFloat("linewidth", 1f)); .lineWidth(settings.getAsFloat("linewidth", 1f));
if (settings.containsSetting("dash")) { if (settings.containsSetting("dash")) {
strokeBuilder.dashPattern(new Stroke.DashPattern(settings.getAsFloat("dash", 1f))); strokeBuilder.dashPattern(new Stroke.DashPattern(settings.getAsFloat("dash", 1f)));
} }
Color color = ColorFactory.web(settings.get("color", "black")); Color color = ColorFactory.web(settings.get("color", "black"));
state.elements.peek().add(new PathElement(path, strokeBuilder.build(), color, position)); state.elements.peek().add(new PathElement(path, strokeBuilder.build(), color, position), LayoutHint.NOP);
} }
} }

View file

@ -23,7 +23,7 @@ public class RowCommand implements Command {
Row.Builder row = Row.builder(); Row.Builder row = Row.builder();
if (settings.containsSetting("padding")) { if (settings.containsSetting("padding")) {
String padding = settings.get("padding", "0 0 0 0"); String padding = settings.get("padding", "0 0 0 0");
String[] paddings = padding.split(" "); String[] paddings = padding.split("\\s+");
float paddingLeft = Float.parseFloat(paddings[0]); float paddingLeft = Float.parseFloat(paddings[0]);
float paddingRight = Float.parseFloat(paddings[1]); float paddingRight = Float.parseFloat(paddings[1]);
float paddingTop = Float.parseFloat(paddings[2]); float paddingTop = Float.parseFloat(paddings[2]);

View file

@ -17,7 +17,7 @@ public class TableCommand implements Command {
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");
String[] widths = columnwidths.split(" "); String[] widths = columnwidths.split("\\s+");
for (String width : widths) { for (String width : widths) {
tableElement.addColumnOfWidth(mmToPt(Float.parseFloat(width))); tableElement.addColumnOfWidth(mmToPt(Float.parseFloat(width)));
} }
@ -27,7 +27,7 @@ public class TableCommand implements Command {
} }
if (settings.containsSetting("padding")) { if (settings.containsSetting("padding")) {
String padding = settings.get("padding", "0 0 0 0"); String padding = settings.get("padding", "0 0 0 0");
String[] paddings = padding.split(" "); String[] paddings = padding.split("\\s+");
float paddingLeft = Float.parseFloat(paddings[0]); float paddingLeft = Float.parseFloat(paddings[0]);
float paddingRight = Float.parseFloat(paddings[1]); float paddingRight = Float.parseFloat(paddings[1]);
float paddingTop = Float.parseFloat(paddings[2]); float paddingTop = Float.parseFloat(paddings[2]);

View file

@ -22,27 +22,34 @@ 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("fontsize", 11.0f); float fontsize = 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);
Element element = state.elements.peek(); Element element = state.elements.peek();
if (element instanceof Paragraph) { if (element instanceof Paragraph) {
element.add(new TextElement(value, font, size)); element.add(new TextElement(value, font, fontsize));
} else if (element instanceof Document) { } else if (element instanceof Document) {
// wrap text into a paragraph
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(mmToPt(settings.getAsFloat("x", 0f)), mmToPt(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(mmToPt(settings.getAsFloat("width", 0f)));
} }
if (settings.containsSetting("alignment")) { if (settings.containsSetting("alignment")) {
paragraph.setAlignment(Alignment.valueOf(settings.get("alignment", "left").toUpperCase(Locale.ROOT))); paragraph.setAlignment(Alignment.valueOf(settings.get("alignment", "left").toUpperCase(Locale.ROOT)));
} }
paragraph.add(new TextElement(value, font, size)); if (settings.containsSetting("linespacing")) {
paragraph.setLineSpacing(settings.getAsFloat("linespacing", 1.2f));
}
if (settings.containsSetting("rotation")) {
paragraph.setRotation(settings.getAsFloat("rotation", 0f));
}
paragraph.add(new TextElement(value, font, fontsize));
Alignment alignment = Alignment.valueOf(settings.get("layout.alignment", "left").toUpperCase(Locale.ROOT)); Alignment alignment = Alignment.valueOf(settings.get("layout.alignment", "left").toUpperCase(Locale.ROOT));
String margin = settings.get("layout.margin", "0 0 0 0"); String margin = settings.get("layout.margin", "0 0 0 0");
String[] margins = margin.split(" "); String[] margins = margin.split("\\s+");
float marginleft = Float.parseFloat(margins[0]); float marginleft = Float.parseFloat(margins[0]);
float marginright = Float.parseFloat(margins[1]); float marginright = Float.parseFloat(margins[1]);
float margintop = Float.parseFloat(margins[2]); float margintop = Float.parseFloat(margins[2]);
@ -50,6 +57,8 @@ public class TextCommand implements Command {
boolean resetY = settings.getAsBoolean("layout.resety", false); boolean resetY = settings.getAsBoolean("layout.resety", false);
VerticalLayoutHint verticalLayoutHint = new VerticalLayoutHint(alignment, marginleft, marginright, margintop, marginbottom, resetY); VerticalLayoutHint verticalLayoutHint = new VerticalLayoutHint(alignment, marginleft, marginright, margintop, marginbottom, resetY);
element.add(paragraph, verticalLayoutHint); element.add(paragraph, verticalLayoutHint);
} else {
throw new UnsupportedOperationException();
} }
} }
} }

View file

@ -0,0 +1,28 @@
package org.xbib.graphics.pdfbox.layout.element.scripting.command;
import java.io.IOException;
import org.xbib.graphics.pdfbox.layout.element.TransformElement;
import org.xbib.graphics.pdfbox.layout.element.render.LayoutHint;
import org.xbib.graphics.pdfbox.layout.element.scripting.Engine;
import org.xbib.graphics.pdfbox.layout.element.scripting.State;
import org.xbib.settings.Settings;
import static org.xbib.graphics.pdfbox.layout.util.PdfUtil.mmToPt;
public class TransformCommand implements Command {
@Override
public void execute(Engine engine, State state, Settings settings) throws IOException {
TransformElement element = new TransformElement();
if (settings.containsSetting("scalex") && settings.containsSetting("scaley")) {
element.setScale(settings.getAsFloat("scalex", null), settings.getAsFloat("scaley", null));
}
if (settings.containsSetting("translatex") && settings.containsSetting("translatey")) {
element.setTranslate(mmToPt(settings.getAsFloat("translatex", null)), mmToPt(settings.getAsFloat("translatey", null)));
}
if (settings.containsSetting("angle") && settings.containsSetting("rotatex") && settings.containsSetting("rotatey")) {
element.setRotate(settings.getAsFloat("angle", null), mmToPt(settings.getAsFloat("rotatex", null)), mmToPt(settings.getAsFloat("rotatey", null)));
}
state.elements.peek().add(element, LayoutHint.NOP);
}
}

View file

@ -0,0 +1,15 @@
package org.xbib.graphics.pdfbox.layout.shape;
import org.xbib.graphics.pdfbox.layout.text.Position;
public class LinePosiiton extends Position {
/**
* Creates a position at the given coordinates for line position.
*
* @param x the x coordinate.
* @param y the y coordinate.
*/
public LinePosiiton(float x, float y) {
super(x, y);
}
}

View file

@ -0,0 +1,15 @@
package org.xbib.graphics.pdfbox.layout.shape;
import org.xbib.graphics.pdfbox.layout.text.Position;
public class MovePosition extends Position {
/**
* Creates a position at the given coordinates for move operation.
*
* @param x the x coordinate.
* @param y the y coordinate.
*/
public MovePosition(float x, float y) {
super(x, y);
}
}

View file

@ -26,22 +26,18 @@ public class Path implements Shape {
Color color, Color color,
Stroke stroke, Stroke stroke,
DrawListener drawListener) throws IOException { DrawListener drawListener) throws IOException {
contentStream.saveGraphicsState();
float x = upperLeft.getX(); float x = upperLeft.getX();
float y = upperLeft.getY() - stroke.getLineWidth() / 2; float y = upperLeft.getY() - stroke.getLineWidth() / 2;
contentStream.setStrokingColor(color); contentStream.setStrokingColor(color);
stroke.applyTo(contentStream); stroke.applyTo(contentStream);
boolean move = true;
for (Position p : list) { for (Position p : list) {
if (move) { if (p instanceof MovePosition) {
contentStream.moveTo(x + p.getX(), y + p.getY()); contentStream.moveTo(x + p.getX(), y + p.getY());
move = false; } else if (p instanceof LinePosiiton) {
} else {
contentStream.lineTo(x + p.getX(), y + p.getY()); contentStream.lineTo(x + p.getX(), y + p.getY());
} }
} }
contentStream.stroke(); contentStream.stroke();
contentStream.restoreGraphicsState();
if (drawListener != null) { if (drawListener != null) {
drawListener.drawn(this, upperLeft, width, height); drawListener.drawn(this, upperLeft, width, height);
} }

View file

@ -58,7 +58,7 @@ public class StyledText implements ParagraphProcessor {
String[] lines = getText().split(PdfUtil.NEW_LINE_REGEX); String[] lines = getText().split(PdfUtil.NEW_LINE_REGEX);
for (int i = 0; i < lines.length; i++) { for (int i = 0; i < lines.length; i++) {
FontDescriptor fontDescriptor = new FontDescriptor(actualFont, actualFontSize); FontDescriptor fontDescriptor = new FontDescriptor(actualFont, actualFontSize);
paragraph.add(new org.xbib.graphics.pdfbox.layout.text.StyledText(lines[i], fontDescriptor, actualColor, 0f, 0, 0)); paragraph.add(new org.xbib.graphics.pdfbox.layout.text.StyledText(lines[i], fontDescriptor, actualColor, 0f, 0, 0, 0));
if (i < lines.length - 1) { if (i < lines.length - 1) {
paragraph.add(new org.xbib.graphics.pdfbox.layout.text.NewLine(new FontDescriptor(actualFont, actualFontSize))); paragraph.add(new org.xbib.graphics.pdfbox.layout.text.NewLine(new FontDescriptor(actualFont, actualFontSize)));
} }

View file

@ -104,7 +104,7 @@ public class Indent extends ControlFragment {
break; break;
} }
} }
styledText = new StyledText(label, fontDescriptor, getColor(), 0, marginLeft, marginRight); styledText = new StyledText(label, fontDescriptor, getColor(), 0, marginLeft, marginRight, 0);
} catch (IOException e) { } catch (IOException e) {
throw new UncheckedIOException(e); throw new UncheckedIOException(e);
} }
@ -117,7 +117,7 @@ public class Indent extends ControlFragment {
*/ */
public Indent(final float indentPt) { public Indent(final float indentPt) {
super("", DEFAULT_FONT_DESCRIPTOR); super("", DEFAULT_FONT_DESCRIPTOR);
styledText = new StyledText("", getFontDescriptor(), getColor(), 0, indentPt, 0); styledText = new StyledText("", getFontDescriptor(), getColor(), 0, indentPt, 0, 0);
} }
private float calculateIndent(float indentWidth, SpaceUnit indentUnit, final FontDescriptor fontDescriptor) private float calculateIndent(float indentWidth, SpaceUnit indentUnit, final FontDescriptor fontDescriptor)

View file

@ -7,6 +7,7 @@ package org.xbib.graphics.pdfbox.layout.text;
public class Position { public class Position {
private final float x; private final float x;
private final float y; private final float y;
/** /**

View file

@ -22,6 +22,8 @@ public class StyledText implements TextFragment {
private final float baselineOffset; private final float baselineOffset;
private final float rotation;
/** /**
* The cached (calculated) width of the text. * The cached (calculated) width of the text.
*/ */
@ -45,7 +47,7 @@ public class StyledText implements TextFragment {
* @param color the color to use. * @param color the color to use.
*/ */
public StyledText(String text, FontDescriptor fontDescriptor, Color color) { public StyledText(String text, FontDescriptor fontDescriptor, Color color) {
this(text, fontDescriptor, color, 0, 0, 0); this(text, fontDescriptor, color, 0, 0, 0, 0);
} }
/** /**
@ -57,11 +59,12 @@ public class StyledText implements TextFragment {
* @param baselineOffset the offset of the baseline. * @param baselineOffset the offset of the baseline.
* @param leftMargin the margin left to the text. * @param leftMargin the margin left to the text.
* @param rightMargin the margin right to the text. * @param rightMargin the margin right to the text.
* @param rotation the rotation of the text, 0 is unrotated
*/ */
public StyledText(String text, public StyledText(String text,
FontDescriptor fontDescriptor, FontDescriptor fontDescriptor,
Color color, Color color,
float baselineOffset, float leftMargin, float rightMargin) { float baselineOffset, float leftMargin, float rightMargin, float rotation) {
if (text.contains("\n")) { if (text.contains("\n")) {
throw new IllegalArgumentException("StyledText must not contain line breaks, use TextFragment.LINEBREAK for that"); throw new IllegalArgumentException("StyledText must not contain line breaks, use TextFragment.LINEBREAK for that");
} }
@ -77,6 +80,7 @@ public class StyledText implements TextFragment {
this.leftMargin = leftMargin; this.leftMargin = leftMargin;
this.rightMargin = rightMargin; this.rightMargin = rightMargin;
this.baselineOffset = baselineOffset; this.baselineOffset = baselineOffset;
this.rotation = rotation;
} }
/** /**
@ -124,6 +128,10 @@ public class StyledText implements TextFragment {
return baselineOffset; return baselineOffset;
} }
public float getRotation() {
return rotation;
}
@Override @Override
public Color getColor() { public Color getColor() {
return color; return color;
@ -164,8 +172,7 @@ public class StyledText implements TextFragment {
} }
public StyledText inheritAttributes(String text, float leftMargin, float rightMargin) { public StyledText inheritAttributes(String text, float leftMargin, float rightMargin) {
return new StyledText(text, getFontDescriptor(), getColor(), return new StyledText(text, getFontDescriptor(), getColor(), getBaselineOffset(), leftMargin, rightMargin, getRotation());
getBaselineOffset(), leftMargin, rightMargin);
} }
private static float getWidth(FontDescriptor fontDescriptor, String text) { private static float getWidth(FontDescriptor fontDescriptor, String text) {
@ -181,6 +188,6 @@ public class StyledText implements TextFragment {
return "StyledText [text=" + text + ", fontDescriptor=" return "StyledText [text=" + text + ", fontDescriptor="
+ fontDescriptor + ", width=" + width + ", color=" + color + fontDescriptor + ", width=" + width + ", color=" + color
+ ", leftMargin=" + leftMargin + ", rightMargin=" + rightMargin + ", leftMargin=" + leftMargin + ", rightMargin=" + rightMargin
+ ", baselineOffset=" + baselineOffset + "]"; + ", baselineOffset=" + baselineOffset + ",rotation=" + rotation + "]";
} }
} }

View file

@ -53,6 +53,8 @@ public class TextFlow implements TextSequence, WidthRespecting {
private float lineSpacing = DEFAULT_LINE_SPACING; private float lineSpacing = DEFAULT_LINE_SPACING;
private float rotation = 0f;
private float maxWidth = -1; private float maxWidth = -1;
private boolean applyLineSpacingToFirstLine = true; private boolean applyLineSpacingToFirstLine = true;
@ -71,15 +73,15 @@ public class TextFlow implements TextSequence, WidthRespecting {
} }
public void addText(String text, float fontSize, Font font) { public void addText(String text, float fontSize, Font font) {
add(TextFlowUtil.createTextFlow(text, new FontDescriptor(font, fontSize), lineSpacing)); add(TextFlowUtil.createTextFlow(text, new FontDescriptor(font, fontSize), lineSpacing, rotation));
} }
public void addMarkup(String markup, FontDescriptor fontDescriptor) { public void addMarkup(String markup, FontDescriptor fontDescriptor) {
add(TextFlowUtil.createTextFlowFromMarkup(markup, fontDescriptor, lineSpacing)); add(TextFlowUtil.createTextFlowFromMarkup(markup, fontDescriptor, lineSpacing, rotation));
} }
public void addMarkup(String markup, float fontSize, Font font) { public void addMarkup(String markup, float fontSize, Font font) {
add(TextFlowUtil.createTextFlowFromMarkup(markup, new FontDescriptor(font, fontSize), lineSpacing)); add(TextFlowUtil.createTextFlowFromMarkup(markup, new FontDescriptor(font, fontSize), lineSpacing, rotation));
} }
public void addIndent(String label, float indentWidth, SpaceUnit indentUnit, float fontsize, Font font) { public void addIndent(String label, float indentWidth, SpaceUnit indentUnit, float fontsize, Font font) {
@ -158,14 +160,6 @@ public class TextFlow implements TextSequence, WidthRespecting {
clearCache(); clearCache();
} }
/**
* @return the factor multiplied with the height to calculate the line
* spacing.
*/
public float getLineSpacing() {
return lineSpacing;
}
/** /**
* Sets the factor multiplied with the height to calculate the line spacing. * Sets the factor multiplied with the height to calculate the line spacing.
* *
@ -176,6 +170,14 @@ public class TextFlow implements TextSequence, WidthRespecting {
clearCache(); clearCache();
} }
/**
* @return the factor multiplied with the height to calculate the line
* spacing.
*/
public float getLineSpacing() {
return lineSpacing;
}
/** /**
* Indicates if the line spacing should be applied to the first line. Makes * Indicates if the line spacing should be applied to the first line. Makes
* sense if there is text above to achieve an equal spacing. In case you * sense if there is text above to achieve an equal spacing. In case you
@ -201,6 +203,14 @@ public class TextFlow implements TextSequence, WidthRespecting {
this.applyLineSpacingToFirstLine = applyLineSpacingToFirstLine; this.applyLineSpacingToFirstLine = applyLineSpacingToFirstLine;
} }
public void setRotation(float rotation) {
this.rotation = rotation;
}
public float getRotation() {
return rotation;
}
@Override @Override
public float getWidth() { public float getWidth() {
Float width = getCachedValue(WIDTH, Float.class); Float width = getCachedValue(WIDTH, Float.class);

View file

@ -15,8 +15,9 @@ import java.util.regex.Matcher;
public class TextFlowUtil { public class TextFlowUtil {
public static TextFlow createTextFlow(String text, FontDescriptor descriptor, float linespacing) { public static TextFlow createTextFlow(String text, FontDescriptor descriptor,
return createTextFlow(fromPlainText(text), descriptor, linespacing); float linespacing, float rotation) {
return createTextFlow(fromPlainText(text), descriptor, linespacing, rotation);
} }
/** /**
@ -51,8 +52,9 @@ public class TextFlowUtil {
* @param linespacing the line spacing * @param linespacing the line spacing
* @return the created text flow. * @return the created text flow.
*/ */
public static TextFlow createTextFlowFromMarkup(String markup, FontDescriptor descriptor, float linespacing) { public static TextFlow createTextFlowFromMarkup(String markup, FontDescriptor descriptor,
return createTextFlow(fromMarkup(markup), descriptor, linespacing); float linespacing, float rotation) {
return createTextFlow(fromMarkup(markup), descriptor, linespacing, rotation);
} }
/** /**
@ -63,7 +65,8 @@ public class TextFlowUtil {
* @param linespacing the line spacing * @param linespacing the line spacing
* @return the created text flow. * @return the created text flow.
*/ */
protected static TextFlow createTextFlow(Iterable<CharSequence> parts, FontDescriptor descriptor, float linespacing) { protected static TextFlow createTextFlow(Iterable<CharSequence> parts, FontDescriptor descriptor,
float linespacing, float rotation) {
final TextFlow textFlow = new TextFlow(); final TextFlow textFlow = new TextFlow();
textFlow.setLineSpacing(linespacing); textFlow.setLineSpacing(linespacing);
boolean bold = false; boolean bold = false;
@ -133,8 +136,7 @@ public class TextFlowUtil {
} }
FontDescriptor fontDescriptor = new FontDescriptor(descriptor.getFont(), currentFontSize, bold, italic); FontDescriptor fontDescriptor = new FontDescriptor(descriptor.getFont(), currentFontSize, bold, italic);
if (annotationMap.isEmpty()) { if (annotationMap.isEmpty()) {
StyledText styledText = new StyledText(fragment.toString(), fontDescriptor, StyledText styledText = new StyledText(fragment.toString(), fontDescriptor, color, baselineOffset, 0, 0, rotation);
color, baselineOffset, 0, 0);
textFlow.add(styledText); textFlow.add(styledText);
} else { } else {
AnnotatedStyledText styledText = AnnotatedStyledText styledText =
@ -165,10 +167,8 @@ public class TextFlowUtil {
* @param text the original text. * @param text the original text.
* @return the create char sequence. * @return the create char sequence.
*/ */
public static Iterable<CharSequence> fromPlainText( public static Iterable<CharSequence> fromPlainText(final Iterable<CharSequence> text) {
final Iterable<CharSequence> text) { Iterable<CharSequence> result = splitByControlCharacter(ControlCharacters.NEWLINE_FACTORY, text);
Iterable<CharSequence> result = splitByControlCharacter(
ControlCharacters.NEWLINE_FACTORY, text);
result = unescapeBackslash(result); result = unescapeBackslash(result);
return result; return result;
} }

View file

@ -191,6 +191,10 @@ public class TextLine implements TextSequence {
matrix = matrix.multiply(new Matrix(1, 0, 0, 1, gap, baselineDelta)); matrix = matrix.multiply(new Matrix(1, 0, 0, 1, gap, baselineDelta));
x += gap; x += gap;
} }
boolean isRotated = styledText.getRotation() > 0f;
if (isRotated) {
matrix.rotate(Math.toRadians(styledText.getRotation()));
}
contentStream.beginText(); contentStream.beginText();
contentStream.setTextMatrix(matrix); contentStream.setTextMatrix(matrix);
if (!styledText.getFontDescriptor().equals(lastFontDesc)) { if (!styledText.getFontDescriptor().equals(lastFontDesc)) {
@ -271,7 +275,5 @@ public class TextLine implements TextSequence {
public void remove() { public void remove() {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
} }
} }

View file

@ -35,7 +35,7 @@ public class AnnotatedStyledText extends StyledText implements Annotated {
final float rightMargin, final float rightMargin,
final float baselineOffset, final float baselineOffset,
Collection<? extends Annotation> annotations) { Collection<? extends Annotation> annotations) {
super(text, fontDescriptor, color, baselineOffset, leftMargin, rightMargin); super(text, fontDescriptor, color, baselineOffset, leftMargin, rightMargin, 0);
if (annotations != null) { if (annotations != null) {
this.annotations.addAll(annotations); this.annotations.addAll(annotations);
} }

View file

@ -316,10 +316,9 @@ public class TextSequenceUtil {
protected static TextFragment deriveFromExisting(TextFragment toDeriveFrom, String text, float leftMargin, protected static TextFragment deriveFromExisting(TextFragment toDeriveFrom, String text, float leftMargin,
float rightMargin) { 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(), toDeriveFrom.getColor(), 0, leftMargin, rightMargin); return new StyledText(text, toDeriveFrom.getFontDescriptor(), toDeriveFrom.getColor(), 0, leftMargin, rightMargin, 0);
} }
private static Pair<TextFragment> breakWord(TextFragment word, private static Pair<TextFragment> breakWord(TextFragment word,

View file

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

View file

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

View file

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

View file

@ -12,7 +12,7 @@ import org.xbib.graphics.pdfbox.layout.element.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;
public class RotationTest { public class PageFormatRotationTest {
@Test @Test
public void test() throws Exception { public void test() throws Exception {

View file

@ -0,0 +1,28 @@
package org.xbib.graphics.pdfbox.layout.test;
import java.io.FileOutputStream;
import org.junit.jupiter.api.Test;
import org.xbib.graphics.pdfbox.layout.element.Document;
import org.xbib.graphics.pdfbox.layout.element.Paragraph;
import org.xbib.graphics.pdfbox.layout.font.BaseFont;
public class TextRotationTest {
@Test
public void test() throws Exception {
Document document = new Document(40, 60, 40, 60);
Paragraph paragraph = new Paragraph();
paragraph.addMarkup("Hello there, here is text text text text text text text text text text text text text text text text" +
" text text text text text text text text text text text",
10, BaseFont.HELVETICA);
paragraph.setMaxWidth(100);
document.add(paragraph);
paragraph = new Paragraph();
paragraph.setRotation(90);
paragraph.addMarkup("Hello\u00a0Text\u00a0Rotation", 10, BaseFont.HELVETICA);
document.add(paragraph);
document.render().save(new FileOutputStream("build/textrotation.pdf")).close();
}
}

View file

@ -37,13 +37,13 @@ public class TableTest {
try (PDPageContentStream contentStream = new PDPageContentStream(document, page)) { try (PDPageContentStream contentStream = new PDPageContentStream(document, page)) {
Table myTable = Table.builder() Table myTable = Table.builder()
.addColumnsOfWidth(200, 200) .addColumnsOfWidth(200, 200)
.padding(2) .padding(2, 2, 2, 2)
.addRow(Row.builder() .addRow(Row.builder()
.add(TextCell.builder().text("One One").borderWidth(4).backgroundColor(Color.WHITE).build()) .add(TextCell.builder().text("One One").borderWidth(4).backgroundColor(Color.WHITE).build())
.add(TextCell.builder().text("One Two").borderWidth(0).backgroundColor(Color.YELLOW).build()) .add(TextCell.builder().text("One Two").borderWidth(0).backgroundColor(Color.YELLOW).build())
.build()) .build())
.addRow(Row.builder() .addRow(Row.builder()
.padding(10) .padding(10, 10 ,10 ,10)
.add(TextCell.builder().text("Two One").textColor(Color.RED).build()) .add(TextCell.builder().text("Two One").textColor(Color.RED).build())
.add(TextCell.builder().text("Two Two") .add(TextCell.builder().text("Two Two")
.borderWidthRight(1f) .borderWidthRight(1f)

View file

@ -27,7 +27,7 @@
{ {
"type": "text", "type": "text",
"value": "Hello World 1", "value": "Hello World 1",
"size": 24, "fontsize": 24,
"font": "helvetica" "font": "helvetica"
} }
] ]
@ -38,7 +38,7 @@
{ {
"type": "text", "type": "text",
"value": "Hello World 2", "value": "Hello World 2",
"size": 24, "fontsize": 24,
"font": "helvetica" "font": "helvetica"
} }
] ]
@ -49,7 +49,7 @@
{ {
"type": "text", "type": "text",
"value": "Hello World 3", "value": "Hello World 3",
"size": 24, "fontsize": 24,
"font": "helvetica" "font": "helvetica"
} }
] ]
@ -63,7 +63,7 @@
{ {
"type": "text", "type": "text",
"value": "Hello World 4", "value": "Hello World 4",
"size": 16, "fontsize": 16,
"font": "notosans" "font": "notosans"
} }
] ]
@ -74,7 +74,7 @@
{ {
"type": "text", "type": "text",
"value": "Hello World 5", "value": "Hello World 5",
"size": 20, "fontsize": 20,
"font": "notosans" "font": "notosans"
} }
] ]
@ -172,7 +172,7 @@
{ {
"type": "text", "type": "text",
"value": "Hello World 6", "value": "Hello World 6",
"size": 20, "fontsize": 20,
"font": "notosans" "font": "notosans"
} }
] ]