use of org.apache.pdfbox.pdmodel.graphics.state.PDTextState in project pdfbox by apache.
the class PreflightContentStream method validateText.
/**
* Process the validation of a Text operand contains in a ContentStream This validation checks that :
* <UL>
* <li>The font isn't missing if the Rendering Mode isn't 3
* <li>The font metrics are consistent
* <li>All character used in the text are defined in the font program.
* </UL>
*
* @param string
* @throws IOException
*/
public void validateText(byte[] string) throws IOException {
// TextSize accessible through the TextState
PDTextState textState = getGraphicsState().getTextState();
final RenderingMode renderingMode = textState.getRenderingMode();
final PDFont font = textState.getFont();
if (font == null) {
// Unable to decode the Text without Font
registerError("Text operator can't be processed without a Font", ERROR_FONTS_UNKNOWN_FONT_REF);
return;
}
FontContainer<?> fontContainer = context.getFontContainer(font.getCOSObject());
if (renderingMode == RenderingMode.NEITHER && (fontContainer == null || !fontContainer.isEmbeddedFont())) {
// font not embedded and rendering mode is 3. Valid case and nothing to check
return;
} else if (fontContainer == null) {
// Font Must be embedded if the RenderingMode isn't 3
if (font.getName() == null) {
registerError("invalid font dictionary", ERROR_FONTS_UNKNOWN_FONT_REF);
} else {
registerError("font '" + font.getName() + "' is missing", ERROR_FONTS_UNKNOWN_FONT_REF);
}
return;
} else if (!fontContainer.isValid() && !fontContainer.errorsAleadyMerged()) {
context.addValidationErrors(fontContainer.getAllErrors());
fontContainer.setErrorsAlreadyMerged(true);
return;
}
if (!fontContainer.isValid() && fontContainer.errorsAleadyMerged()) {
// font already computed
return;
}
InputStream in = new ByteArrayInputStream(string);
while (in.available() > 0) {
try {
int code = font.readCode(in);
fontContainer.checkGlyphWidth(code);
} catch (IOException e) {
registerError("Encoding can't interpret the character code", ERROR_FONTS_ENCODING_ERROR, e);
return;
} catch (GlyphException e) {
if (renderingMode != RenderingMode.NEITHER) {
registerError(e.getMessage(), e.getErrorCode(), e);
return;
}
}
}
}
use of org.apache.pdfbox.pdmodel.graphics.state.PDTextState in project pdfbox by apache.
the class PDFStreamEngine method showTextStrings.
/**
* Called when a string of text with spacing adjustments is to be shown.
*
* @param array array of encoded text strings and adjustments
* @throws IOException if there was an error showing the text
*/
public void showTextStrings(COSArray array) throws IOException {
PDTextState textState = getGraphicsState().getTextState();
float fontSize = textState.getFontSize();
float horizontalScaling = textState.getHorizontalScaling() / 100f;
PDFont font = textState.getFont();
boolean isVertical = false;
if (font != null) {
isVertical = font.isVertical();
}
for (COSBase obj : array) {
if (obj instanceof COSNumber) {
float tj = ((COSNumber) obj).floatValue();
// calculate the combined displacements
float tx, ty;
if (isVertical) {
tx = 0;
ty = -tj / 1000 * fontSize;
} else {
tx = -tj / 1000 * fontSize * horizontalScaling;
ty = 0;
}
applyTextAdjustment(tx, ty);
} else if (obj instanceof COSString) {
byte[] string = ((COSString) obj).getBytes();
showText(string);
} else {
throw new IOException("Unknown type in array for TJ operation:" + obj);
}
}
}
use of org.apache.pdfbox.pdmodel.graphics.state.PDTextState 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));
}
}
Aggregations