add transform to underline annotations

This commit is contained in:
Jörg Prante 2023-08-23 11:24:05 +02:00
parent 97ed576828
commit b3167d16ce
14 changed files with 88 additions and 58 deletions

View file

@ -1,5 +1,5 @@
group = org.xbib.graphics
name = graphics
version = 4.5.2
version = 4.5.3
org.gradle.warning.mode = ALL

View file

@ -274,8 +274,7 @@ public class RenderContext implements Renderer, Closeable, DrawContext, DrawList
if (positionElement instanceof ResetPosition) {
currentPosition = new Position(getMarkedPosition().getX(), getMarkedPosition().getY());
}
if (positionElement instanceof SetPosition) {
SetPosition setPosition = (SetPosition) positionElement;
if (positionElement instanceof SetPosition setPosition) {
Float x = setPosition.getX();
if (x == null) {
x = getCurrentPosition().getX();
@ -287,8 +286,7 @@ public class RenderContext implements Renderer, Closeable, DrawContext, DrawList
currentPosition = new Position(x, y);
return true;
}
if (positionElement instanceof MovePosition) {
MovePosition movePosition = (MovePosition) positionElement;
if (positionElement instanceof MovePosition movePosition) {
movePositionBy(movePosition.getX(), movePosition.getY());
return true;
}

View file

@ -202,21 +202,14 @@ public class VerticalLayout implements Layout {
PDPageContentStream contentStream = renderContext.getCurrentPageContentStream();
PageFormat pageFormat = renderContext.getPageFormat();
float offsetX = 0;
if (layoutHint instanceof VerticalLayoutHint) {
VerticalLayoutHint verticalLayoutHint = (VerticalLayoutHint) layoutHint;
if (layoutHint instanceof VerticalLayoutHint verticalLayoutHint) {
Alignment alignment = verticalLayoutHint.getAlignment();
float horizontalExtraSpace = getTargetWidth(renderContext) - drawable.getWidth();
switch (alignment) {
case RIGHT:
offsetX = horizontalExtraSpace - verticalLayoutHint.getMarginRight();
break;
case CENTER:
offsetX = horizontalExtraSpace / 2f;
break;
default:
offsetX = verticalLayoutHint.getMarginLeft();
break;
}
offsetX = switch (alignment) {
case RIGHT -> horizontalExtraSpace - verticalLayoutHint.getMarginRight();
case CENTER -> horizontalExtraSpace / 2f;
default -> verticalLayoutHint.getMarginLeft();
};
}
contentStream.saveGraphicsState();
if (renderContext.getTransform() != null) {

View file

@ -4,6 +4,7 @@ import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.xbib.graphics.pdfbox.layout.element.Paragraph;
import org.xbib.graphics.pdfbox.layout.element.render.Transform;
import org.xbib.graphics.pdfbox.layout.table.HorizontalAlignment;
import org.xbib.graphics.pdfbox.layout.table.ParagraphCell;
import org.xbib.graphics.pdfbox.layout.text.Alignment;
@ -49,21 +50,26 @@ public class ParagraphCellRenderer extends AbstractCellRenderer<ParagraphCell> {
private AnnotationDrawListener createAndGetAnnotationDrawListenerWith(TableRenderContext tableRenderContext) {
return new AnnotationDrawListener(new DrawContext() {
@Override
public PDDocument getPdDocument() {
return tableRenderContext.getPdDocument();
}
@Override
public PDDocument getPdDocument() {
return tableRenderContext.getPdDocument();
}
@Override
public PDPage getCurrentPage() {
return tableRenderContext.getPage();
}
@Override
public PDPage getCurrentPage() {
return tableRenderContext.getPage();
}
@Override
public PDPageContentStream getCurrentPageContentStream() {
return tableRenderContext.getContentStream();
}
});
@Override
public PDPageContentStream getCurrentPageContentStream() {
return tableRenderContext.getContentStream();
}
@Override
public Transform getTransform() {
return null;
}
});
}
}

View file

@ -16,7 +16,10 @@ public class TableRenderContext {
private final Point2D.Float startingPoint;
public TableRenderContext(PDDocument pdDocument, PDPageContentStream contentStream, PDPage page, Point2D.Float startingPoint) {
public TableRenderContext(PDDocument pdDocument,
PDPageContentStream contentStream,
PDPage page,
Point2D.Float startingPoint) {
this.pdDocument = pdDocument;
this.contentStream = contentStream;
this.page = page;

View file

@ -3,6 +3,7 @@ package org.xbib.graphics.pdfbox.layout.text;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.xbib.graphics.pdfbox.layout.element.render.Transform;
/**
* Provides the current page and document to draw to.
@ -23,4 +24,7 @@ public interface DrawContext {
* @return the current page content stream.
*/
PDPageContentStream getCurrentPageContentStream();
Transform getTransform();
}

View file

@ -11,7 +11,6 @@ public class ReplacedWhitespace extends ControlFragment {
public ReplacedWhitespace(String replacedSpace, FontDescriptor fontDescriptor) {
super("", fontDescriptor);
this.replacedSpace = replacedSpace;
}

View file

@ -121,8 +121,7 @@ public class TextFlowUtil {
currentIndent = last;
}
indentStack.push(currentIndent);
FontDescriptor fontDescriptor =
new FontDescriptor(descriptor.getFonts(), descriptor.getSize(), bold, italic);
FontDescriptor fontDescriptor = new FontDescriptor(descriptor.getFonts(), descriptor.getSize(), bold, italic);
textFlow.add(currentIndent.createNewIndent(fontDescriptor, color));
}
}
@ -138,8 +137,7 @@ public class TextFlowUtil {
StyledText styledText = new StyledText(fragment.toString(), fontDescriptor, color, baselineOffset, 0, 0, rotation);
textFlow.add(styledText);
} else {
AnnotatedStyledText styledText =
new AnnotatedStyledText(fragment.toString(), fontDescriptor,
AnnotatedStyledText styledText = new AnnotatedStyledText(fragment.toString(), fontDescriptor,
color, baselineOffset, 0, 0, annotationMap.values());
textFlow.add(styledText);
}
@ -226,13 +224,10 @@ public class TextFlowUtil {
List<CharSequence> result = new ArrayList<>();
boolean beginOfLine = true;
for (CharSequence current : markup) {
if (current instanceof String) {
String string = (String) current;
if (current instanceof String string) {
int begin = 0;
if (!controlCharacterFactory.patternMatchesBeginOfLine()
|| beginOfLine) {
Matcher matcher = controlCharacterFactory.getPattern()
.matcher(string);
if (!controlCharacterFactory.patternMatchesBeginOfLine() || beginOfLine) {
Matcher matcher = controlCharacterFactory.getPattern().matcher(string);
while (matcher.find()) {
String part = string.substring(begin, matcher.start());
begin = matcher.end();

View file

@ -1,6 +1,5 @@
package org.xbib.graphics.pdfbox.layout.text.annotations;
import org.xbib.graphics.pdfbox.layout.font.Font;
import org.xbib.graphics.pdfbox.layout.font.FontDescriptor;
import org.xbib.graphics.pdfbox.layout.text.StyledText;
import java.awt.Color;
@ -84,7 +83,8 @@ public class AnnotatedStyledText extends StyledText implements Annotated {
}
@Override
public AnnotatedStyledText inheritAttributes(String text, float leftMargin,
public AnnotatedStyledText inheritAttributes(String text,
float leftMargin,
float rightMargin) {
return new AnnotatedStyledText(text, getFontDescriptor(), getColor(),
getBaselineOffset(), leftMargin, rightMargin, annotations);

View file

@ -33,7 +33,7 @@ public class AnnotationDrawListener implements DrawListener, RenderListener {
* @param drawContext the context which provides the {@link PDDocument} and the
* {@link PDPage} currently drawn to.
*/
public AnnotationDrawListener(final DrawContext drawContext) {
public AnnotationDrawListener(DrawContext drawContext) {
this.drawContext = drawContext;
annotationProcessors = AnnotationProcessorFactory.createAnnotationProcessors();
}

View file

@ -37,16 +37,18 @@ public class HyperlinkAnnotationProcessor implements AnnotationProcessor {
private final Map<PDPage, List<Hyperlink>> linkMap = new HashMap<>();
public HyperlinkAnnotationProcessor() {
}
@Override
public void annotatedObjectDrawn(Annotated drawnObject,
DrawContext drawContext,
Position upperLeft,
float width,
float height) {
if (!(drawnObject instanceof AnnotatedStyledText)) {
if (!(drawnObject instanceof AnnotatedStyledText annotatedText)) {
return;
}
AnnotatedStyledText annotatedText = (AnnotatedStyledText) drawnObject;
handleHyperlinkAnnotations(annotatedText, drawContext, upperLeft, width, height);
handleAnchorAnnotations(annotatedText, drawContext, upperLeft);
}

View file

@ -2,6 +2,7 @@ package org.xbib.graphics.pdfbox.layout.text.annotations;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.xbib.graphics.pdfbox.layout.element.render.Transform;
import org.xbib.graphics.pdfbox.layout.shape.Stroke;
import org.xbib.graphics.pdfbox.layout.text.DrawContext;
import org.xbib.graphics.pdfbox.layout.position.Position;
@ -19,7 +20,10 @@ import java.util.List;
*/
public class UnderlineAnnotationProcessor implements AnnotationProcessor {
private final List<Line> linesOnPage = new ArrayList<>();
private final List<Line> lines = new ArrayList<>();
public UnderlineAnnotationProcessor() {
}
@Override
public void annotatedObjectDrawn(Annotated drawnObject,
@ -38,27 +42,27 @@ public class UnderlineAnnotationProcessor implements AnnotationProcessor {
Position start = new Position(upperLeft.getX(), upperLeft.getY() - ascent + baselineOffset);
Position end = new Position(start.getX() + width, start.getY());
Stroke stroke = Stroke.builder().lineWidth(thickness).build();
Line line = new Line(start, end, stroke, drawnText.getColor());
linesOnPage.add(line);
Line line = new Line(start, end, stroke, drawnText.getColor(), drawContext.getTransform());
lines.add(line);
}
}
@Override
public void beforePage(DrawContext drawContext) {
linesOnPage.clear();
lines.clear();
}
@Override
public void afterPage(DrawContext drawContext) {
for (Line line : linesOnPage) {
for (Line line : lines) {
line.draw(drawContext.getCurrentPageContentStream());
}
linesOnPage.clear();
lines.clear();
}
@Override
public void afterRender(PDDocument document) {
linesOnPage.clear();
lines.clear();
}
private static class Line {
@ -71,16 +75,23 @@ public class UnderlineAnnotationProcessor implements AnnotationProcessor {
private final Color color;
public Line(Position start, Position end, Stroke stroke, Color color) {
private final Transform transform;
public Line(Position start, Position end, Stroke stroke, Color color, Transform transform) {
super();
this.start = start;
this.end = end;
this.stroke = stroke;
this.color = color;
this.transform = transform;
}
public void draw(PDPageContentStream contentStream) {
try {
if (transform != null) {
contentStream.saveGraphicsState();
contentStream.transform(transform.getMatrix());
}
if (color != null) {
contentStream.setStrokingColor(color);
}
@ -90,6 +101,9 @@ public class UnderlineAnnotationProcessor implements AnnotationProcessor {
contentStream.moveTo(start.getX(), start.getY());
contentStream.lineTo(end.getX(), end.getY());
contentStream.stroke();
if (transform != null) {
contentStream.restoreGraphicsState();
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}

View file

@ -6,6 +6,7 @@ import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.util.Matrix;
import org.junit.jupiter.api.Test;
import org.xbib.graphics.pdfbox.layout.element.PageFormat;
import org.xbib.graphics.pdfbox.layout.element.render.Transform;
import org.xbib.graphics.pdfbox.layout.font.FontDescriptor;
import org.xbib.graphics.pdfbox.layout.shape.RoundRect;
import org.xbib.graphics.pdfbox.layout.shape.Shape;
@ -32,8 +33,7 @@ public class LowLevelText {
float pageWidth = page.getMediaBox().getWidth();
float pageHeight = page.getMediaBox().getHeight();
pdDocument.addPage(page);
final PDPageContentStream contentStream =
new PDPageContentStream(pdDocument, page, PDPageContentStream.AppendMode.APPEND, true);
final PDPageContentStream contentStream = new PDPageContentStream(pdDocument, page, PDPageContentStream.AppendMode.APPEND, true);
AnnotationDrawListener annotationDrawListener = new AnnotationDrawListener(new DrawContext() {
@ -52,6 +52,11 @@ public class LowLevelText {
return contentStream;
}
@Override
public Transform getTransform() {
return null;
}
});
annotationDrawListener.beforePage(null);

View file

@ -215,6 +215,17 @@
"font": "notosans"
}
]
},
{
"type": "paragraph",
"elements": [
{
"type": "markup",
"text": "__{0.25:}Hello World 7__",
"fontsize": 20,
"font": "notosans"
}
]
}
]
}