use of org.apache.pdfbox.pdmodel.graphics.state.PDGraphicsState in project pdfbox by apache.
the class PDFStreamEngine method initPage.
/**
* Initialises the stream engine for the given page.
*/
private void initPage(PDPage page) {
if (page == null) {
throw new IllegalArgumentException("Page cannot be null");
}
currentPage = page;
graphicsStack.clear();
graphicsStack.push(new PDGraphicsState(page.getCropBox()));
textMatrix = null;
textLineMatrix = null;
resources = null;
initialMatrix = page.getMatrix();
}
use of org.apache.pdfbox.pdmodel.graphics.state.PDGraphicsState in project pdfbox by apache.
the class PDFStreamEngine method processStream.
/**
* Process a content stream.
*
* @param contentStream the content stream
* @throws IOException if there is an exception while processing the stream
*/
private void processStream(PDContentStream contentStream) throws IOException {
PDResources parent = pushResources(contentStream);
Stack<PDGraphicsState> savedStack = saveGraphicsStack();
Matrix parentMatrix = initialMatrix;
// transform the CTM using the stream's matrix
getGraphicsState().getCurrentTransformationMatrix().concatenate(contentStream.getMatrix());
// the stream's initial matrix includes the parent CTM, e.g. this allows a scaled form
initialMatrix = getGraphicsState().getCurrentTransformationMatrix().clone();
// clip to bounding box
PDRectangle bbox = contentStream.getBBox();
clipToRect(bbox);
processStreamOperators(contentStream);
initialMatrix = parentMatrix;
restoreGraphicsStack(savedStack);
popResources(parent);
}
use of org.apache.pdfbox.pdmodel.graphics.state.PDGraphicsState in project pdfbox by apache.
the class PDFStreamEngine method processTilingPattern.
/**
* Process the given tiling pattern. Allows the pattern matrix to be overridden for custom
* rendering.
*
* @param tilingPattern the tiling pattern
* @param color color to use, if this is an uncoloured pattern, otherwise null.
* @param colorSpace color space to use, if this is an uncoloured pattern, otherwise null.
* @param patternMatrix the pattern matrix, may be overridden for custom rendering.
* @throws IOException if there is an error reading or parsing the tiling pattern content stream.
*/
protected final void processTilingPattern(PDTilingPattern tilingPattern, PDColor color, PDColorSpace colorSpace, Matrix patternMatrix) throws IOException {
PDResources parent = pushResources(tilingPattern);
Matrix parentMatrix = initialMatrix;
initialMatrix = Matrix.concatenate(initialMatrix, patternMatrix);
// save the original graphics state
Stack<PDGraphicsState> savedStack = saveGraphicsStack();
// save a clean state (new clipping path, line path, etc.)
Rectangle2D bbox = tilingPattern.getBBox().transform(patternMatrix).getBounds2D();
PDRectangle rect = new PDRectangle((float) bbox.getX(), (float) bbox.getY(), (float) bbox.getWidth(), (float) bbox.getHeight());
graphicsStack.push(new PDGraphicsState(rect));
// non-colored patterns have to be given a color
if (colorSpace != null) {
color = new PDColor(color.getComponents(), colorSpace);
getGraphicsState().setNonStrokingColorSpace(colorSpace);
getGraphicsState().setNonStrokingColor(color);
getGraphicsState().setStrokingColorSpace(colorSpace);
getGraphicsState().setStrokingColor(color);
}
// transform the CTM using the stream's matrix
getGraphicsState().getCurrentTransformationMatrix().concatenate(patternMatrix);
// clip to bounding box
clipToRect(tilingPattern.getBBox());
processStreamOperators(tilingPattern);
initialMatrix = parentMatrix;
restoreGraphicsStack(savedStack);
popResources(parent);
}
use of org.apache.pdfbox.pdmodel.graphics.state.PDGraphicsState in project pdfbox by apache.
the class PDFStreamEngine method showText.
/**
* Process text from the PDF Stream. You should override this method if you want to
* perform an action when encoded text is being processed.
*
* @param string the encoded text
* @throws IOException if there is an error processing the string
*/
protected void showText(byte[] string) throws IOException {
PDGraphicsState state = getGraphicsState();
PDTextState textState = state.getTextState();
// get the current font
PDFont font = textState.getFont();
if (font == null) {
LOG.warn("No current font, will use default");
font = PDFontFactory.createDefaultFont();
}
float fontSize = textState.getFontSize();
float horizontalScaling = textState.getHorizontalScaling() / 100f;
float charSpacing = textState.getCharacterSpacing();
// put the text state parameters into matrix form
Matrix parameters = new Matrix(// 0
fontSize * horizontalScaling, // 0
0, // 0
0, // 0
fontSize, 0, // 1
textState.getRise());
// read the stream until it is empty
InputStream in = new ByteArrayInputStream(string);
while (in.available() > 0) {
// decode a character
int before = in.available();
int code = font.readCode(in);
int codeLength = before - in.available();
String unicode = font.toUnicode(code);
// Word spacing shall be applied to every occurrence of the single-byte character code
// 32 in a string when using a simple font or a composite font that defines code 32 as
// a single-byte code.
float wordSpacing = 0;
if (codeLength == 1 && code == 32) {
wordSpacing += textState.getWordSpacing();
}
// text rendering matrix (text space -> device space)
Matrix ctm = state.getCurrentTransformationMatrix();
Matrix textRenderingMatrix = parameters.multiply(textMatrix).multiply(ctm);
// changes to vertical text should be tested with PDFBOX-2294 and PDFBOX-1422
if (font.isVertical()) {
// position vector, in text space
Vector v = font.getPositionVector(code);
// apply the position vector to the horizontal origin to get the vertical origin
textRenderingMatrix.translate(v);
}
// get glyph's horizontal and vertical displacements, in text space
Vector w = font.getDisplacement(code);
// process the decoded glyph
saveGraphicsState();
Matrix textMatrixOld = textMatrix;
Matrix textLineMatrixOld = textLineMatrix;
showGlyph(textRenderingMatrix, font, code, unicode, w);
textMatrix = textMatrixOld;
textLineMatrix = textLineMatrixOld;
restoreGraphicsState();
// calculate the combined displacements
float tx, ty;
if (font.isVertical()) {
tx = 0;
ty = w.getY() * fontSize + charSpacing + wordSpacing;
} else {
tx = (w.getX() * fontSize + charSpacing + wordSpacing) * horizontalScaling;
ty = 0;
}
// update the text matrix
textMatrix.concatenate(Matrix.getTranslateInstance(tx, ty));
}
}
use of org.apache.pdfbox.pdmodel.graphics.state.PDGraphicsState in project pdfbox by apache.
the class PageDrawer method getStroke.
// create a new stroke based on the current CTM and the current stroke
private BasicStroke getStroke() {
PDGraphicsState state = getGraphicsState();
// apply the CTM
float lineWidth = transformWidth(state.getLineWidth());
// minimum line width as used by Adobe Reader
if (lineWidth < 0.25) {
lineWidth = 0.25f;
}
PDLineDashPattern dashPattern = state.getLineDashPattern();
int phaseStart = dashPattern.getPhase();
float[] dashArray = dashPattern.getDashArray();
// apply the CTM
for (int i = 0; i < dashArray.length; ++i) {
// minimum line dash width avoids JVM crash,
// see PDFBOX-2373, PDFBOX-2929, PDFBOX-3204, PDFBOX-3813
// also avoid 0 in array like "[ 0 1000 ] 0 d", see PDFBOX-3724
float w = transformWidth(dashArray[i]);
dashArray[i] = Math.max(w, 0.062f);
}
phaseStart = (int) transformWidth(phaseStart);
// avoid also infinite and NaN values (PDFBOX-3360)
if (dashArray.length == 0 || Float.isInfinite(phaseStart) || Float.isNaN(phaseStart)) {
dashArray = null;
} else {
for (int i = 0; i < dashArray.length; ++i) {
if (Float.isInfinite(dashArray[i]) || Float.isNaN(dashArray[i])) {
dashArray = null;
break;
}
}
}
return new BasicStroke(lineWidth, state.getLineCap(), state.getLineJoin(), state.getMiterLimit(), dashArray, phaseStart);
}
Aggregations