Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import java.io.InputStream;
import java.util.Objects;

import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.pdmodel.AbstractGlyphLayoutProcessor;
import org.apache.pdfbox.pdmodel.ContentStreamForGlyphLayoutInterface;
import org.apache.pdfbox.pdmodel.GlyphLayoutProcessorInterface;
Expand All @@ -48,18 +49,30 @@
public class GlyphLayoutProcessorAwt extends AbstractGlyphLayoutProcessor implements GlyphLayoutProcessorInterface
{

private final GlyphLayoutFontLoaderAwt glyphLayoutFontLoaderAwt;
private final GlyphLayoutFontLoaderAwt glyphLayoutFontLoaderAwt = new GlyphLayoutFontLoaderAwt();


/**
* Constructs a GlyphLayoutProcessorFop with options
*
*/
public GlyphLayoutProcessorAwt(AbstractGlyphLayoutProcessor.GlyphLayoutProcessorOptions options)
{
super(options);
}

/**
* Constructs a GlyphLayoutProcessorAwt
*
*/
public GlyphLayoutProcessorAwt()
{
this.glyphLayoutFontLoaderAwt = new GlyphLayoutFontLoaderAwt();
super();
}

/**


/**
* Checks if glyphs needed for text are missing in awtFont
*
* @param text text to be checked
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,11 @@
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;

import org.apache.pdfbox.Loader;

import org.apache.pdfbox.pdmodel.AbstractGlyphLayoutProcessor;
import org.junit.jupiter.api.Test;

import org.apache.pdfbox.pdmodel.PDDocument;
Expand Down Expand Up @@ -90,14 +93,47 @@ class GlyphLayoutDin91379Test extends TestBase
+ "⁹ ⁿ ₀ ₁ ₂ ₃ ₄ ₅ ₆ ₇ ₈ ₉ ™ ∞ ≤ ≥\n"
+ "Additional non-letters (not included in DIN 91379): – — •�";

/**
* Test, no ActualText
* @throws IOException
* @throws FontFormatException
* @throws URISyntaxException
*/
@Test
void testGlyphLayoutDin91379NoActualText() throws IOException, FontFormatException, URISyntaxException {
testGlyphLayoutDin91379(false, "");
}

/**
* Test with ActualText
* @throws IOException
* @throws FontFormatException
* @throws URISyntaxException
*/
@Test
void testGlyphLayoutDin91379() throws IOException, FontFormatException, URISyntaxException
void testGlyphLayoutDin91379UseActualText() throws IOException, FontFormatException, URISyntaxException {
testGlyphLayoutDin91379(true, "_ActualText");
}

/**
* Test GlyphLayoutProcessorAwt with letters and sequences from DIN 91379
* @param useActualText
* @throws IOException
* @throws FontFormatException
* @throws URISyntaxException
*/
void testGlyphLayoutDin91379(boolean useActualText, String sActualText) throws IOException, FontFormatException, URISyntaxException
{
GlyphLayoutProcessorAwt glyphLayoutProcessor = new GlyphLayoutProcessorAwt();
AbstractGlyphLayoutProcessor.GlyphLayoutProcessorOptions options = new AbstractGlyphLayoutProcessor.GlyphLayoutProcessorOptions();
if (useActualText) {
options.useActualText();
}
GlyphLayoutProcessorAwt glyphLayoutProcessor = new GlyphLayoutProcessorAwt(options);

String outputName = "GlyphLayoutDIN91379.pdf";
String outputName = String.format("GlyphLayoutDIN91379%s.pdf", sActualText);
String outputPDFFilename = "target/" + outputName;
String outputTextFilename = "target/GlyphLayoutDIN91379.txt";
String outputTextFilename = String.format("target/GlyphLayoutDIN91379%s.txt", sActualText);

float fontSize = 12.0f;

try (PDDocument doc = new PDDocument())
Expand Down Expand Up @@ -133,7 +169,7 @@ void testGlyphLayoutDin91379() throws IOException, FontFormatException, URISynta
os.write (0xBB);
os.write (0xBF);

try (Writer writer = new BufferedWriter(new OutputStreamWriter(os, "utf-8")))
try (Writer writer = new BufferedWriter(new OutputStreamWriter(os, StandardCharsets.UTF_8)))
{
//TODO compare this output with the input, like in TextStripper test
// Not yet correct as of 4.7.2026
Expand All @@ -158,7 +194,7 @@ private void showComposites(PDPageContentStream cs, PDType0Font font, float font
if (!line.isEmpty())
{
showCompositesLine(cs, font, fontSize, x, y, line);
y -= fontSize * 1.5;
y -= fontSize * 1.5f;
}
}
}
Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
public class GlyphLayoutProcessorFop extends AbstractGlyphLayoutProcessor implements GlyphLayoutProcessorInterface
{

private final GlyphLayoutFontLoaderFop glyphLayoutFontLoaderFop;
private final GlyphLayoutFontLoaderFop glyphLayoutFontLoaderFop = new GlyphLayoutFontLoaderFop();

/*
Before you call GlyphMapping.doGlyphMapping to position the glyphs,
Expand All @@ -54,13 +54,22 @@ public class GlyphLayoutProcessorFop extends AbstractGlyphLayoutProcessor implem
*/
private static final float FOP_FONTSIZE_FACTOR = 1000f;

/**
* Constructs a GlyphLayoutProcessorFop with options
*
*/
public GlyphLayoutProcessorFop(AbstractGlyphLayoutProcessor.GlyphLayoutProcessorOptions options)
{
super(options);
}

/**
* Constructs a GlyphLayoutProcessorFop
*
*/
public GlyphLayoutProcessorFop()
{
this.glyphLayoutFontLoaderFop = new GlyphLayoutFontLoaderFop();
super();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,11 @@
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.apache.pdfbox.pdmodel.AbstractGlyphLayoutProcessor;
import org.junit.jupiter.api.Test;

import org.apache.pdfbox.Loader;
Expand Down Expand Up @@ -90,14 +92,44 @@ class GlyphLayoutDin91379Test extends TestBase
+ "⁹ ⁿ ₀ ₁ ₂ ₃ ₄ ₅ ₆ ₇ ₈ ₉ ™ ∞ ≤ ≥\n"
+ "Additional non-letters (not included in DIN 91379): – — •�";

/**
* Test, no ActualText
* @throws IOException
* @throws URISyntaxException
*/
@Test
void testGlyphLayoutDin91379NoActualText() throws IOException, URISyntaxException {
testGlyphLayoutDin91379(false, "");
}

/**
* Test with ActualText
* @throws IOException
* @throws URISyntaxException
*/
@Test
void testGlyphLayoutDin91379() throws IOException, URISyntaxException
void testGlyphLayoutDin91379UseActualText() throws IOException, URISyntaxException {
testGlyphLayoutDin91379(true, "_ActualText");
}

/**
* Test GlyphLayoutProcessorAwt with letters and sequences from DIN 91379
* @param useActualText
* @throws IOException
* @throws URISyntaxException
*/
void testGlyphLayoutDin91379(boolean useActualText, String sActualText) throws IOException, URISyntaxException
{
GlyphLayoutProcessorFop glyphLayoutProcessor = new GlyphLayoutProcessorFop();
AbstractGlyphLayoutProcessor.GlyphLayoutProcessorOptions options = new AbstractGlyphLayoutProcessor.GlyphLayoutProcessorOptions();
if (useActualText) {
options.useActualText();
}
GlyphLayoutProcessorFop glyphLayoutProcessor = new GlyphLayoutProcessorFop(options);

String outputName = "GlyphLayoutDIN91379.pdf";
String outputName = String.format("GlyphLayoutDIN91379%s.pdf", sActualText);
String outputPDFFilename = "target/" + outputName;
String outputTextFilename = "target/GlyphLayoutDIN91379.txt";
String outputTextFilename = String.format("target/GlyphLayoutDIN91379%s.txt", sActualText);

float fontSize = 12.0f;

try (PDDocument doc = new PDDocument())
Expand Down Expand Up @@ -132,7 +164,7 @@ void testGlyphLayoutDin91379() throws IOException, URISyntaxException
os.write (0xBB);
os.write (0xBF);

try (Writer writer = new BufferedWriter(new OutputStreamWriter(os, "utf-8")))
try (Writer writer = new BufferedWriter(new OutputStreamWriter(os, StandardCharsets.UTF_8)))
{
//TODO compare this output with the input, like in TextStripper test
// Not yet correct as of 4.7.2026
Expand All @@ -157,7 +189,7 @@ private void showComposites(PDPageContentStream cs, PDType0Font font, float font
if (!line.isEmpty())
{
showCompositesLine(cs, font, fontSize, x, y, line);
y -= fontSize * 1.5;
y -= fontSize * 1.5f;
}
}
}
Expand Down
Binary file not shown.
1 change: 1 addition & 0 deletions pdfbox/src/main/java/org/apache/pdfbox/cos/COSName.java
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,7 @@ public final class COSName extends COSBase implements Comparable<COSName>
public static final COSName SORT = getPDFName("Sort");
public static final COSName SOUND = getPDFName("Sound");
public static final COSName SPLIT = getPDFName("Split");
public static final COSName SPAN = getPDFName("Span");
public static final COSName SS = getPDFName("SS");
public static final COSName ST = getPDFName("St");
public static final COSName STANDARD_ENCODING = getPDFName("StandardEncoding");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@

package org.apache.pdfbox.pdmodel;

import org.apache.pdfbox.cos.COSDictionary;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.cos.COSString;
import org.apache.pdfbox.pdmodel.documentinterchange.markedcontent.PDPropertyList;
import org.apache.pdfbox.pdmodel.font.PDType0Font;

import java.io.IOException;
Expand All @@ -33,6 +37,35 @@
*/
public abstract class AbstractGlyphLayoutProcessor implements GlyphLayoutProcessorInterface
{
/**
*
*/
private final boolean useActualText;

/**
* Options for GlyphLayoutProcessor
*/
public static class GlyphLayoutProcessorOptions {
private boolean useActualText;

/**
* Turn usage of ActualText on
* @return this
*/
public GlyphLayoutProcessorOptions useActualText() {
useActualText = true;
return this;
}

/**
* Returns the state of useActualText
* @return true, if ActualText is used, falls otherwise
*/
public boolean getUseActualText() {
return useActualText;
}
}

/**
* Class for text and Bidi-Level
*/
Expand All @@ -58,6 +91,22 @@ public int getBidiLevel()
}
}

/**
* Creates an AbstractGlyphLayoutProcessor with the given options
* @param options Options for creation
*/
public AbstractGlyphLayoutProcessor(GlyphLayoutProcessorOptions options) {
useActualText = options.useActualText;
}

/**
* Creates an AbstractGlyphLayoutProcessor with standard options
*/
public AbstractGlyphLayoutProcessor() {
useActualText = false;
}


/**
* Compute the string width for a unidirectional string
* @param font to be used
Expand Down Expand Up @@ -88,6 +137,30 @@ public float getStringWidth(PDType0Font font, float fontSize, String text) throw
return width;
}


/**
* Begin a marked content sequence for ActualText
*
* @param contentStream the content stream
* @param text the text to be written as ActualText
* @throws IOException If the content stream could not be written
*/
protected void beginMarkedContentForActualText(ContentStreamForGlyphLayoutInterface contentStream, String text) throws IOException {
COSDictionary dict = new COSDictionary();
dict.setItem(COSName.ACTUAL_TEXT, new COSString(text));
PDPropertyList propertyList = PDPropertyList.create(dict);
contentStream.beginMarkedContent(COSName.SPAN, propertyList);
}

/**
* End a marked content sequence.
*
* @throws IOException If the content stream could not be written
*/
protected void endMarkedContent(ContentStreamForGlyphLayoutInterface contentStream) throws IOException {
contentStream.endMarkedContent();
}

/**
* Shows unidirectional text using glyph positioning (if needed)
*
Expand Down Expand Up @@ -117,11 +190,17 @@ protected abstract void showTextUni(ContentStreamForGlyphLayoutInterface content
public void showText(ContentStreamForGlyphLayoutInterface contentStream, PDType0Font font, float fontSize, String text)
throws IOException
{
if (useActualText) {
beginMarkedContentForActualText(contentStream, text);
}
List<TextAndBidiLevel> textAndBidiLevels = doBidiSplittingAndReordering(text);
for (TextAndBidiLevel textAndBidiLevel: textAndBidiLevels)
{
showTextUni(contentStream, font, fontSize, textAndBidiLevel.getText(), textAndBidiLevel.getBidiLevel());
}
if (useActualText) {
endMarkedContent(contentStream);
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
*/
package org.apache.pdfbox.pdmodel;

import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.pdmodel.documentinterchange.markedcontent.PDPropertyList;

import java.io.IOException;

public interface ContentStreamForGlyphLayoutInterface
Expand Down Expand Up @@ -46,4 +49,21 @@ public interface ContentStreamForGlyphLayoutInterface
* @throws IOException If the content stream could not be written.
*/
void setTextRise(float rise) throws IOException;


/**
* Begin a marked content sequence with a reference to an entry in the page resources' Properties dictionary.
*
* @param tag the tag to be added to the content stream
* @param propertyList property list to be added to the content stream
* @throws IOException If the content stream could not be written
*/
void beginMarkedContent(COSName tag, PDPropertyList propertyList) throws IOException;

/**
* End a marked content sequence.
*
* @throws IOException If the content stream could not be written
*/
void endMarkedContent() throws IOException;
}