fix PDF chart font Helvetica selection, fix stroke in underline annotations

This commit is contained in:
Jörg Prante 2021-03-02 23:21:04 +01:00
parent a091bc52cf
commit 49278772e8
20 changed files with 114 additions and 219 deletions

View file

@ -4,8 +4,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledOnOs;
import org.junit.jupiter.api.condition.OS;
import org.xbib.graphics.barcode.Code93;
import org.xbib.graphics.barcode.render.BarcodeGraphicsRenderer;
import org.xbib.graphics.barcode.MaxiCode;
@ -24,7 +22,6 @@ import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Locale;
@DisabledOnOs(OS.MAC)
public class EPSRendererTest {
private Locale originalDefaultLocale;
@ -98,7 +95,7 @@ public class EPSRendererTest {
int height = (int) (symbol.getHeight() * magnification);
Rectangle rectangle = new Rectangle(0, 0, width, height);
EPSGraphics2D epsGraphics2D = new EPSGraphics2D(rectangle);
epsGraphics2D.setFont(new Font(Font.SANS_SERIF, Font.PLAIN, 12));
epsGraphics2D.setFont(Font.decode("Dialog"));
BarcodeGraphicsRenderer barcodeGraphicsRenderer = new BarcodeGraphicsRenderer(epsGraphics2D, rectangle,
magnification, paper, ink, false, false);
barcodeGraphicsRenderer.render(symbol);

View file

@ -4,8 +4,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledOnOs;
import org.junit.jupiter.api.condition.OS;
import org.xbib.graphics.barcode.Code93;
import org.xbib.graphics.barcode.MaxiCode;
import org.xbib.graphics.barcode.AbstractSymbol;
@ -24,7 +22,6 @@ import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Locale;
@DisabledOnOs({OS.MAC, OS.LINUX})
public class PDFRendererTest {
private Locale originalDefaultLocale;
@ -98,8 +95,7 @@ public class PDFRendererTest {
int height = (int) (symbol.getHeight() * magnification);
Rectangle rectangle = new Rectangle(0, 0, width, height);
PDFGraphics2D pdfGraphics2D = new PDFGraphics2D(rectangle);
// we need a trick here to generate HELVETICA font statements
pdfGraphics2D.setFont(new Font(Font.SANS_SERIF, Font.PLAIN, 12));
pdfGraphics2D.setFont(Font.decode("Dialog")); // Helvetica
BarcodeGraphicsRenderer barcodeGraphicsRenderer = new BarcodeGraphicsRenderer(pdfGraphics2D,
rectangle, magnification, paper, ink, false, false);
barcodeGraphicsRenderer.render(symbol);

View file

@ -4,8 +4,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledOnOs;
import org.junit.jupiter.api.condition.OS;
import org.xbib.graphics.barcode.Code93;
import org.xbib.graphics.barcode.MaxiCode;
import org.xbib.graphics.barcode.AbstractSymbol;
@ -24,7 +22,6 @@ import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Locale;
@DisabledOnOs(OS.MAC)
public class SvgRendererTest {
private Locale originalDefaultLocale;
@ -98,7 +95,7 @@ public class SvgRendererTest {
int height = (int) (symbol.getHeight() * magnification);
Rectangle rectangle = new Rectangle(0, 0, width, height);
SVGGraphics2D svgGraphics2D = new SVGGraphics2D(rectangle);
svgGraphics2D.setFont(new Font(Font.SANS_SERIF, Font.PLAIN, 12));
svgGraphics2D.setFont(Font.decode("Dialog"));
BarcodeGraphicsRenderer barcodeGraphicsRenderer = new BarcodeGraphicsRenderer(svgGraphics2D,
rectangle, magnification, paper, ink, false, false);
barcodeGraphicsRenderer.render(symbol);

View file

@ -1,6 +1,7 @@
This work is derived from XChart by Tim Molter
http://knowm.org/open-source/xchart/
https://github.com/timmolter/xchart
Apache License 2.0

View file

@ -361,7 +361,7 @@ public abstract class Chart<ST extends Styler, S extends Series> {
}
public BufferedImage getBufferedImage() {
BufferedImage bufferedImage = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
BufferedImage bufferedImage = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D graphics2D = bufferedImage.createGraphics();
paint(graphics2D, getWidth(), getHeight());
return bufferedImage;

View file

@ -1,7 +1,6 @@
package org.xbib.graphics.pdfbox.layout.elements;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.xbib.graphics.pdfbox.layout.elements.render.Layout;
import org.xbib.graphics.pdfbox.layout.elements.render.LayoutHint;
import org.xbib.graphics.pdfbox.layout.elements.render.RenderContext;
@ -55,11 +54,11 @@ public class Document implements RenderListener {
* @param marginTop the top margin
* @param marginBottom the bottom margin
*/
public Document(float marginLeft, float marginRight, float marginTop,
public Document(float marginLeft,
float marginRight,
float marginTop,
float marginBottom) {
this(PageFormat.with()
.margins(marginLeft, marginRight, marginTop, marginBottom)
.build());
this(PageFormat.with().margins(marginLeft, marginRight, marginTop, marginBottom).build());
}
/**
@ -68,7 +67,7 @@ public class Document implements RenderListener {
*
* @param pageFormat the page format box to use.
*/
public Document(final PageFormat pageFormat) {
public Document(PageFormat pageFormat) {
this.pageFormat = pageFormat;
}
@ -77,7 +76,7 @@ public class Document implements RenderListener {
*
* @param element the element to add
*/
public void add(final Element element) {
public void add(Element element) {
add(element, new VerticalLayoutHint());
}
@ -87,24 +86,15 @@ public class Document implements RenderListener {
* @param element the element to add
* @param layoutHint the hint for the {@link Layout}.
*/
public void add(final Element element, final LayoutHint layoutHint) {
public void add(Element element, LayoutHint layoutHint) {
elements.add(createEntry(element, layoutHint));
}
private Entry<Element, LayoutHint> createEntry(final Element element,
final LayoutHint layoutHint) {
private Entry<Element, LayoutHint> createEntry(Element element,
LayoutHint layoutHint) {
return new SimpleEntry<>(element, layoutHint);
}
/**
* Removes the given element.
*
* @param element the element to remove.
*/
public void remove(final Element element) {
elements.remove(element);
}
/**
* @return the page format to use as default.
*/
@ -112,72 +102,20 @@ public class Document implements RenderListener {
return pageFormat;
}
/**
* @return the left document margin.
* @deprecated use {@link #getPageFormat()} instead.
*/
@Deprecated
public float getMarginLeft() {
return getPageFormat().getMarginLeft();
}
/**
* @return the right document margin.
* @deprecated use {@link #getPageFormat()} instead.
*/
@Deprecated
public float getMarginRight() {
return getPageFormat().getMarginRight();
}
/**
* @return the top document margin.
* @deprecated use {@link #getPageFormat()} instead.
*/
@Deprecated
public float getMarginTop() {
return getPageFormat().getMarginTop();
}
/**
* @return the bottom document margin.
* @deprecated use {@link #getPageFormat()} instead.
*/
@Deprecated
public float getMarginBottom() {
return getPageFormat().getMarginBottom();
}
/**
* @return the media box to use.
* @deprecated use {@link #getPageFormat()} instead.
*/
@Deprecated
public PDRectangle getMediaBox() {
return getPageFormat().getMediaBox();
}
/**
* @return the orientation to use.
* @deprecated use {@link #getPageFormat()} instead.
*/
@Deprecated
public Orientation getOrientation() {
return getPageFormat().getOrientation();
}
/**
* @return the media box width minus margins.
*/
public float getPageWidth() {
return getMediaBox().getWidth() - getMarginLeft() - getMarginRight();
return pageFormat.getMediaBox().getWidth() -
pageFormat.getMarginLeft() - pageFormat.getMarginRight();
}
/**
* @return the media box height minus margins.
*/
public float getPageHeight() {
return getMediaBox().getHeight() - getMarginTop() - getMarginBottom();
return pageFormat.getMediaBox().getHeight() -
pageFormat.getMarginTop() - pageFormat.getMarginBottom();
}
/**
@ -215,15 +153,6 @@ public class Document implements RenderListener {
}
}
/**
* Removes a {@link Renderer} .
*
* @param renderer the renderer to remove.
*/
public void removeRenderer(final Renderer renderer) {
customRenderer.remove(renderer);
}
/**
* Renders all elements and returns the resulting {@link PDDocument}.
*
@ -298,17 +227,8 @@ public class Document implements RenderListener {
}
}
/**
* Removes a {@link RenderListener} .
*
* @param listener the listener to remove.
*/
public void removeRenderListener(final RenderListener listener) {
renderListener.remove(listener);
}
@Override
public void beforePage(final RenderContext renderContext)
public void beforePage(RenderContext renderContext)
throws IOException {
for (RenderListener listener : renderListener) {
listener.beforePage(renderContext);
@ -316,10 +236,9 @@ public class Document implements RenderListener {
}
@Override
public void afterPage(final RenderContext renderContext) throws IOException {
public void afterPage(RenderContext renderContext) throws IOException {
for (RenderListener listener : renderListener) {
listener.afterPage(renderContext);
}
}
}

View file

@ -3,7 +3,6 @@ package org.xbib.graphics.pdfbox.layout.elements.render;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.util.Matrix;
import org.xbib.graphics.pdfbox.layout.elements.ControlElement;
import org.xbib.graphics.pdfbox.layout.elements.Document;
@ -83,28 +82,6 @@ public class RenderContext implements Renderer, Closeable, DrawContext, DrawList
resetPositionToLeftEndOfPage();
}
/**
* @return the orientation to use for the page. If no special
* {@link #setPageFormat(PageFormat) page format} is set, the
* {@link Document#getOrientation() document orientation} is used.
* @deprecated use {@link #getPageFormat()} instead.
*/
@Deprecated
public Orientation getOrientation() {
return getPageFormat().getOrientation();
}
/**
* @return the media box to use for the page. If no special
* {@link #setPageFormat(PageFormat) page format} is set, the
* {@link Document#getMediaBox() document media box} is used.
* @deprecated use {@link #getPageFormat()} instead.
*/
@Deprecated
public PDRectangle getMediaBox() {
return getPageFormat().getMediaBox();
}
public void setPageFormat(final PageFormat pageFormat) {
if (pageFormat == null) {
this.pageFormat = document.getPageFormat();
@ -279,14 +256,6 @@ public class RenderContext implements Renderer, Closeable, DrawContext, DrawList
return getContentStream();
}
/**
* @return the current PDPage.
*/
@Deprecated
public PDPage getPage() {
return getCurrentPage();
}
/**
* @return the current PDPageContentStream.
*/
@ -302,10 +271,10 @@ public class RenderContext implements Renderer, Closeable, DrawContext, DrawList
}
@Override
public boolean render(RenderContext renderContext, Element element,
public boolean render(RenderContext renderContext,
Element element,
LayoutHint layoutHint) throws IOException {
boolean success = getLayout()
.render(renderContext, element, layoutHint);
boolean success = getLayout().render(renderContext, element, layoutHint);
if (success) {
return true;
}
@ -327,7 +296,7 @@ public class RenderContext implements Renderer, Closeable, DrawContext, DrawList
return false;
}
protected boolean render(final PositionControl positionControl) {
protected boolean render(PositionControl positionControl) {
if (positionControl instanceof MarkPosition) {
setMarkedPosition(getCurrentPosition());
return true;
@ -401,16 +370,12 @@ public class RenderContext implements Renderer, Closeable, DrawContext, DrawList
*/
public boolean closePage() throws IOException {
if (contentStream != null) {
annotationDrawListener.afterPage(this);
document.afterPage(this);
if (getPageFormat().getRotation() != 0) {
int currentRotation = getCurrentPage().getRotation();
getCurrentPage().setRotation(
currentRotation + getPageFormat().getRotation());
getCurrentPage().setRotation(currentRotation + getPageFormat().getRotation());
}
contentStream.close();
contentStream = null;
return true;

View file

@ -3,7 +3,6 @@ package org.xbib.graphics.pdfbox.layout.shape;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.logging.Logger;
/**
* This is a container for all information needed to perform a stroke.
@ -176,18 +175,14 @@ public class Stroke {
*/
public void applyTo(PDPageContentStream contentStream) throws IOException {
if (getCapStyle() != null) {
Logger.getLogger("").info(" cap style = " + getCapStyle().value());
contentStream.setLineCapStyle(getCapStyle().value());
}
if (getJoinStyle() != null) {
Logger.getLogger("").info(" join style = " + getJoinStyle().value());
contentStream.setLineJoinStyle(getJoinStyle().value());
}
if (getDashPattern() != null) {
Logger.getLogger("").info(" dash pattern = " + Arrays.asList(getDashPattern().getPattern()));
contentStream.setLineDashPattern(getDashPattern().getPattern(), getDashPattern().getPhase());
}
Logger.getLogger("").info(" line width = " + getLineWidth());
contentStream.setLineWidth(getLineWidth());
}

View file

@ -116,7 +116,7 @@ public class StyledText implements TextFragment {
* @return the ascent of the associated font.
* @throws IOException by pdfbox.
*/
public float getAsent() throws IOException {
public float getAscent() throws IOException {
return getFontDescriptor().getSize() * getFontDescriptor().getSelectedFont().getFontDescriptor().getAscent() / 1000;
}

View file

@ -88,11 +88,9 @@ public class TextFlowUtil {
if (fragment instanceof AnnotationCharacters.AnnotationControlCharacter) {
AnnotationCharacters.AnnotationControlCharacter<?> annotationControlCharacter = (AnnotationCharacters.AnnotationControlCharacter<?>) fragment;
if (annotationMap.containsKey(annotationControlCharacter.getAnnotationType())) {
annotationMap.remove(annotationControlCharacter
.getAnnotationType());
annotationMap.remove(annotationControlCharacter.getAnnotationType());
} else {
annotationMap.put(
annotationControlCharacter.getAnnotationType(),
annotationMap.put(annotationControlCharacter.getAnnotationType(),
annotationControlCharacter.getAnnotation());
}
}

View file

@ -205,7 +205,7 @@ public class TextLine implements TextSequence {
contentStream.endText();
if (drawListener != null) {
drawListener.drawn(styledText,
new Position(x, y + styledText.getAsent()),
new Position(x, y + styledText.getAscent()),
styledText.getWidthWithoutMargin(),
styledText.getHeight());
}

View file

@ -210,7 +210,8 @@ public class AnnotationCharacters {
* constant for the system property
* <code>pdfbox.layout.underline.baseline.offset.scale.default</code>.
*/
public final static String UNDERLINE_DEFAULT_BASELINE_OFFSET_SCALE_PROPERTY = "pdfbox.layout.underline.baseline.offset.scale.default";
public final static String UNDERLINE_DEFAULT_BASELINE_OFFSET_SCALE_PROPERTY =
"pdfbox.layout.underline.baseline.offset.scale.default";
private static Float defaultBaselineOffsetScale;
private final UnderlineAnnotation line;
@ -218,7 +219,6 @@ public class AnnotationCharacters {
protected UnderlineControlCharacter(String baselineOffsetScaleValue,
String lineWeightValue) {
super("UNDERLINE", UnderlineControlCharacterFactory.TO_ESCAPE);
float baselineOffsetScale = parseFloat(baselineOffsetScaleValue,
getdefaultBaselineOffsetScale());
float lineWeight = parseFloat(lineWeightValue, 1f);
@ -248,15 +248,11 @@ public class AnnotationCharacters {
private static float getdefaultBaselineOffsetScale() {
if (defaultBaselineOffsetScale == null) {
defaultBaselineOffsetScale = Float
.parseFloat(System
.getProperty(
UNDERLINE_DEFAULT_BASELINE_OFFSET_SCALE_PROPERTY,
"-0.1"));
defaultBaselineOffsetScale =
Float.parseFloat(System.getProperty(UNDERLINE_DEFAULT_BASELINE_OFFSET_SCALE_PROPERTY, "-0.1"));
}
return defaultBaselineOffsetScale;
}
}
/**
@ -267,7 +263,7 @@ public class AnnotationCharacters {
public interface AnnotationControlCharacterFactory<T extends AnnotationControlCharacter<? extends Annotation>>
extends ControlCharacterFactory {
T createControlCharacter(String text, Matcher matcher,
final List<CharSequence> charactersSoFar);
List<CharSequence> charactersSoFar);
}
@ -277,8 +273,8 @@ public class AnnotationCharacters {
public static abstract class AnnotationControlCharacter<T extends Annotation>
extends ControlCharacter {
protected AnnotationControlCharacter(final String description,
final String characterToEscape) {
protected AnnotationControlCharacter(String description,
String characterToEscape) {
super(description, characterToEscape);
}

View file

@ -14,7 +14,7 @@ import org.xbib.graphics.pdfbox.layout.text.Position;
* This listener has to be passed to all
* {@link DrawableText#drawText(org.apache.pdfbox.pdmodel.PDPageContentStream, Position, Alignment, DrawListener)
* draw()} methods, in order collect all annotation metadata. After all drawing
* is done, you have to call {@link #finalizeAnnotations()} which creates all
* is done, you have to call {@link #afterRender()} which creates all
* necessary annotations and sets them to the corresponding pages. This listener
* is used by the the rendering API, but you may also use it with the low-level
* text API.
@ -49,11 +49,6 @@ public class AnnotationDrawListener implements DrawListener, RenderListener {
}
}
@Deprecated
public void finalizeAnnotations() {
afterRender();
}
@Override
public void beforePage(RenderContext renderContext) {
for (AnnotationProcessor annotationProcessor : annotationProcessors) {
@ -68,11 +63,9 @@ public class AnnotationDrawListener implements DrawListener, RenderListener {
}
}
public void afterRender() {
for (AnnotationProcessor annotationProcessor : annotationProcessors) {
annotationProcessor.afterRender(drawContext.getPdDocument());
}
}
}

View file

@ -10,8 +10,9 @@ public class Annotations {
*/
public static class UnderlineAnnotation implements Annotation {
private float baselineOffsetScale = 0f;
private float lineWeight = 1f;
private final float baselineOffsetScale;
private final float lineWeight;
public UnderlineAnnotation(float baselineOffsetScale, float lineWeight) {
this.baselineOffsetScale = baselineOffsetScale;
@ -31,7 +32,6 @@ public class Annotations {
return "UnderlineAnnotation [baselineOffsetScale="
+ baselineOffsetScale + ", lineWeight=" + lineWeight + "]";
}
}
/**
@ -51,6 +51,7 @@ public class Annotations {
}
private final String hyperlinkUri;
private final LinkStyle linkStyle;
/**

View file

@ -34,37 +34,39 @@ import java.util.Map.Entry;
public class HyperlinkAnnotationProcessor implements AnnotationProcessor {
private final Map<String, PageAnchor> anchorMap = new HashMap<>();
private final Map<PDPage, List<Hyperlink>> linkMap = new HashMap<>();
@Override
public void annotatedObjectDrawn(Annotated drawnObject,
DrawContext drawContext, Position upperLeft, float width,
DrawContext drawContext,
Position upperLeft,
float width,
float height) {
if (!(drawnObject instanceof AnnotatedStyledText)) {
return;
}
AnnotatedStyledText annotatedText = (AnnotatedStyledText) drawnObject;
handleHyperlinkAnnotations(annotatedText, drawContext, upperLeft,
width, height);
handleHyperlinkAnnotations(annotatedText, drawContext, upperLeft, width, height);
handleAnchorAnnotations(annotatedText, drawContext, upperLeft);
}
protected void handleAnchorAnnotations(AnnotatedStyledText annotatedText,
DrawContext drawContext, Position upperLeft) {
Iterable<AnchorAnnotation> anchorAnnotations = annotatedText
.getAnnotationsOfType(AnchorAnnotation.class);
DrawContext drawContext,
Position upperLeft) {
Iterable<AnchorAnnotation> anchorAnnotations =
annotatedText.getAnnotationsOfType(AnchorAnnotation.class);
for (AnchorAnnotation anchorAnnotation : anchorAnnotations) {
anchorMap.put(
anchorAnnotation.getAnchor(),
new PageAnchor(drawContext.getCurrentPage(), upperLeft
.getX(), upperLeft.getY()));
anchorMap.put(anchorAnnotation.getAnchor(),
new PageAnchor(drawContext.getCurrentPage(), upperLeft.getX(), upperLeft.getY()));
}
}
protected void handleHyperlinkAnnotations(
AnnotatedStyledText annotatedText, DrawContext drawContext,
Position upperLeft, float width, float height) {
protected void handleHyperlinkAnnotations(AnnotatedStyledText annotatedText,
DrawContext drawContext,
Position upperLeft,
float width,
float height) {
Iterable<HyperlinkAnnotation> hyperlinkAnnotations = annotatedText
.getAnnotationsOfType(HyperlinkAnnotation.class);
for (HyperlinkAnnotation hyperlinkAnnotation : hyperlinkAnnotations) {
@ -74,10 +76,8 @@ public class HyperlinkAnnotationProcessor implements AnnotationProcessor {
bounds.setLowerLeftY(upperLeft.getY() - height);
bounds.setUpperRightX(upperLeft.getX() + width);
bounds.setUpperRightY(upperLeft.getY());
links.add(new Hyperlink(bounds, annotatedText.getColor(),
hyperlinkAnnotation.getLinkStyle(), hyperlinkAnnotation
.getHyperlinkURI()));
hyperlinkAnnotation.getLinkStyle(), hyperlinkAnnotation.getHyperlinkURI()));
}
}
@ -116,8 +116,11 @@ public class HyperlinkAnnotationProcessor implements AnnotationProcessor {
}
}
private static PDAnnotationLink createLink(PDPage page, PDRectangle rect, Color color,
LinkStyle linkStyle, final String uri) {
private static PDAnnotationLink createLink(PDPage page,
PDRectangle rect,
Color color,
LinkStyle linkStyle,
String uri) {
PDAnnotationLink pdLink = createLink(page, rect, color, linkStyle);
PDActionURI actionUri = new PDActionURI();
actionUri.setURI(uri);
@ -127,7 +130,9 @@ public class HyperlinkAnnotationProcessor implements AnnotationProcessor {
private static PDBorderStyleDictionary noBorder;
private static PDAnnotationLink createLink(PDPage page, PDRectangle rect, Color color,
private static PDAnnotationLink createLink(PDPage page,
PDRectangle rect,
Color color,
LinkStyle linkStyle) {
PDAnnotationLink pdLink = new PDAnnotationLink();
if (linkStyle == LinkStyle.none) {
@ -146,8 +151,11 @@ public class HyperlinkAnnotationProcessor implements AnnotationProcessor {
return pdLink;
}
private static PDAnnotationLink createLink(PDPage page, PDRectangle rect, Color color,
LinkStyle linkStyle, final PDDestination destination) {
private static PDAnnotationLink createLink(PDPage page,
PDRectangle rect,
Color color,
LinkStyle linkStyle,
PDDestination destination) {
PDAnnotationLink pdLink = createLink(page, rect, color, linkStyle);
PDActionGoTo gotoAction = new PDActionGoTo();
gotoAction.setDestination(destination);
@ -155,12 +163,18 @@ public class HyperlinkAnnotationProcessor implements AnnotationProcessor {
return pdLink;
}
private static PDRectangle transformToPageRotation(final PDRectangle rect, final PDPage page) {
private static PDRectangle transformToPageRotation(PDRectangle rect,
PDPage page) {
AffineTransform transform = transformToPageRotation(page);
if (transform == null) {
return rect;
}
float[] points = new float[]{rect.getLowerLeftX(), rect.getLowerLeftY(), rect.getUpperRightX(), rect.getUpperRightY()};
float[] points = {
rect.getLowerLeftX(),
rect.getLowerLeftY(),
rect.getUpperRightX(),
rect.getUpperRightY()
};
float[] rotatedPoints = new float[4];
transform.transform(points, 0, rotatedPoints, 0, 2);
PDRectangle rotated = new PDRectangle();
@ -171,7 +185,7 @@ public class HyperlinkAnnotationProcessor implements AnnotationProcessor {
return rotated;
}
private static AffineTransform transformToPageRotation(final PDPage page) {
private static AffineTransform transformToPageRotation(PDPage page) {
int pageRotation = page.getRotation();
if (pageRotation == 0) {
return null;
@ -179,8 +193,7 @@ public class HyperlinkAnnotationProcessor implements AnnotationProcessor {
float pageWidth = page.getMediaBox().getHeight();
float pageHeight = page.getMediaBox().getWidth();
AffineTransform transform = new AffineTransform();
transform.rotate(pageRotation * Math.PI / 180, pageHeight / 2,
pageWidth / 2);
transform.rotate(pageRotation * Math.PI / 180, pageHeight / 2, pageWidth / 2);
double offset = Math.abs(pageHeight - pageWidth) / 2;
transform.translate(-offset, offset);
return transform;
@ -197,8 +210,7 @@ public class HyperlinkAnnotationProcessor implements AnnotationProcessor {
String anchor = hyperlink.getHyperlinkURI().substring(1);
PageAnchor pageAnchor = anchorMap.get(anchor);
if (pageAnchor == null) {
throw new IllegalArgumentException(String.format(
"anchor named '%s' not found", anchor));
throw new IllegalArgumentException(String.format("anchor named '%s' not found", anchor));
}
PDPageXYZDestination xyzDestination = new PDPageXYZDestination();
xyzDestination.setPage(pageAnchor.getPage());
@ -209,8 +221,11 @@ public class HyperlinkAnnotationProcessor implements AnnotationProcessor {
}
private static class PageAnchor {
private final PDPage page;
private final float x;
private final float y;
public PageAnchor(PDPage page, float x, float y) {
@ -238,9 +253,13 @@ public class HyperlinkAnnotationProcessor implements AnnotationProcessor {
}
private static class Hyperlink {
private final PDRectangle rect;
private final Color color;
private final String hyperlinkUri;
private final LinkStyle linkStyle;
public Hyperlink(PDRectangle rect, Color color, LinkStyle linkStyle,

View file

@ -90,9 +90,20 @@ public class UnderlineAnnotationProcessor implements AnnotationProcessor {
}
contentStream.moveTo(start.getX(), start.getY());
contentStream.lineTo(end.getX(), end.getY());
contentStream.stroke();
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
@Override
public String toString() {
return "Line{" +
"start=" + start +
", end=" + end +
", stroke=" + stroke +
", color=" + color +
'}';
}
}
}

View file

@ -243,8 +243,7 @@ public class CustomAnnotationTest {
float pageWidth = page.getMediaBox().getHeight();
float pageHeight = page.getMediaBox().getWidth();
AffineTransform transform = new AffineTransform();
transform.rotate(pageRotation * Math.PI / 180, pageHeight / 2,
pageWidth / 2);
transform.rotate(pageRotation * Math.PI / 180, pageHeight / 2, pageWidth / 2);
double offset = Math.abs(pageHeight - pageWidth) / 2;
transform.translate(-offset, offset);
return transform;

View file

@ -7,10 +7,10 @@ import org.xbib.graphics.pdfbox.layout.font.BaseFont;
import java.io.FileOutputStream;
import java.io.OutputStream;
public class Links {
public class LinksTest {
@Test
public void main() throws Exception {
public void test() throws Exception {
String text1 = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, "
+ "sed diam nonumy eirmod tempor invidunt ut labore et dolore magna "
+ "aliquyam erat, _sed diam_ voluptua. At vero eos et *accusam et justo* "
@ -31,7 +31,6 @@ public class Links {
Document document = new Document(40, 60, 40, 60);
Paragraph paragraph0 = new Paragraph();
paragraph0.addMarkup("This is a link to {link[https://github.com/ralfstuckert/pdfbox-layout]}PDFBox-Layout{link}.\n\n", 11, BaseFont.TIMES);
paragraph0.addMarkup("Now the same link with color instead of underline {color:#ff5000}{link:none[https://github.com/ralfstuckert/pdfbox-layout]}PDFBox-Layout{link}{color:#000000}.\n\n", 11, BaseFont.TIMES);

View file

@ -24,9 +24,11 @@ public class MarkupTest {
+ "gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.\n\n";
Document document = new Document(40, 60, 40, 60);
Paragraph paragraph = new Paragraph();
paragraph.addMarkup(text1, 11, BaseFont.TIMES);
document.add(paragraph);
paragraph = new Paragraph();
paragraph.addMarkup("Markup supports *bold*, _italic_, and *even _mixed* markup_.\n\n",
11, BaseFont.TIMES);
@ -41,6 +43,11 @@ public class MarkupTest {
11, BaseFont.TIMES);
document.add(paragraph, new VerticalLayoutHint(Alignment.LEFT, 0, 0, 30, 0));
paragraph = new Paragraph();
paragraph.addMarkup("And here comes a link to an internal anchor name {color:#ff5000}{link[#hello]}hello{link}{color:#000000}.\n\n", 11, BaseFont.TIMES);
paragraph.addMarkup("\n\n{anchor:hello}Here{anchor} comes the internal anchor named *hello*\n\n", 11, BaseFont.COURIER);
document.add(paragraph);
paragraph = new Paragraph();
text1 = "\nAlso, you can do all that indentation stuff much easier with markup, e.g. simple indentation\n"
+ "--At vero eos et accusam\n\n"

View file

@ -19,7 +19,8 @@ public class FontDrawerTest {
Font anyFontItalic = anyFont.deriveFont(Font.ITALIC);
Font anyFontBoldItalic = anyFont.deriveFont(Font.BOLD | Font.ITALIC);
Assertions.assertEquals(PDType1Font.COURIER, CoreFontDrawer.chooseMatchingCourier(anyFont));
Assertions.assertEquals(PDType1Font.COURIER,
CoreFontDrawer.chooseMatchingCourier(anyFont));
assertEquals(PDType1Font.COURIER_BOLD,
CoreFontDrawer.chooseMatchingCourier(anyFontBold));
assertEquals(PDType1Font.COURIER_OBLIQUE,
@ -36,7 +37,8 @@ public class FontDrawerTest {
assertEquals(PDType1Font.HELVETICA_BOLD_OBLIQUE,
CoreFontDrawer.chooseMatchingHelvetica(anyFontBoldItalic));
assertEquals(PDType1Font.TIMES_ROMAN, CoreFontDrawer.chooseMatchingTimes(anyFont));
assertEquals(PDType1Font.TIMES_ROMAN,
CoreFontDrawer.chooseMatchingTimes(anyFont));
assertEquals(PDType1Font.TIMES_BOLD,
CoreFontDrawer.chooseMatchingTimes(anyFontBold));
assertEquals(PDType1Font.TIMES_ITALIC,