| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910 |
- package com.ymwk.icvp.pdfToOfdBao;
- import org.apache.commons.io.IOUtils;
- import org.apache.fontbox.ttf.CmapLookup;
- import org.apache.fontbox.ttf.TrueTypeFont;
- import org.apache.fontbox.util.BoundingBox;
- import org.apache.pdfbox.contentstream.PDFGraphicsStreamEngine;
- import org.apache.pdfbox.cos.COSName;
- import org.apache.pdfbox.pdmodel.PDPage;
- import org.apache.pdfbox.pdmodel.common.PDStream;
- import org.apache.pdfbox.pdmodel.font.*;
- import org.apache.pdfbox.pdmodel.graphics.color.PDColor;
- import org.apache.pdfbox.pdmodel.graphics.color.PDColorSpace;
- import org.apache.pdfbox.pdmodel.graphics.image.PDImage;
- import org.apache.pdfbox.pdmodel.graphics.state.PDGraphicsState;
- import org.apache.pdfbox.pdmodel.graphics.state.RenderingMode;
- import org.apache.pdfbox.text.TextPosition;
- import org.apache.pdfbox.util.Matrix;
- import org.apache.pdfbox.util.Vector;
- import org.bouncycastle.crypto.Digest;
- import org.bouncycastle.crypto.digests.MD5Digest;
- import org.dom4j.Element;
- import org.ofdrw.core.OFDElement;
- import org.ofdrw.core.basicStructure.pageObj.layer.CT_Layer;
- import org.ofdrw.core.basicStructure.pageObj.layer.block.ImageObject;
- import org.ofdrw.core.basicStructure.pageObj.layer.block.PathObject;
- import org.ofdrw.core.basicStructure.pageObj.layer.block.TextObject;
- import org.ofdrw.core.basicType.ST_Array;
- import org.ofdrw.core.basicType.ST_ID;
- import org.ofdrw.core.basicType.ST_RefID;
- import org.ofdrw.core.graph.pathObj.AbbreviatedData;
- import org.ofdrw.core.graph.pathObj.CT_Path;
- import org.ofdrw.core.pageDescription.clips.CT_Clip;
- import org.ofdrw.core.pageDescription.clips.Clips;
- import org.ofdrw.core.pageDescription.color.color.CT_Color;
- import org.ofdrw.core.text.CT_CGTransform;
- import org.ofdrw.core.text.TextCode;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import javax.imageio.ImageIO;
- import java.awt.geom.*;
- import java.io.ByteArrayOutputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.util.ArrayList;
- import java.util.List;
- public class OFDPageDrawer extends PDFGraphicsStreamEngine {
- private final Logger logger = LoggerFactory.getLogger(this.getClass());
- private GeneralPath linePath = new GeneralPath();
- private int clipWindingRule = -1;
- private OFDCreator ofdCreator;
- private CT_Layer ctLayer;
- private float scale;
- private PDPage page;
- private float PX2MM = 2.834175f;
- private int pageRotation;
- private Area lastClip;
- public CT_Layer getCtLayer() {
- // 获取时,从队列添加
- for (Element ele : queue) {
- ctLayer.add(ele);
- }
- return ctLayer;
- }
- protected OFDPageDrawer(int idx, PDPage page, OFDCreator ofdCreator, float scale) throws IOException {
- super(page);
- this.page = page;
- this.ofdCreator = ofdCreator;
- ctLayer = this.ofdCreator.createLayer();
- this.scale = scale;
- }
- public void drawPage() throws IOException {
- processPage(this.getPage());
- }
- @Override
- public void appendRectangle(Point2D p0, Point2D p1, Point2D p2, Point2D p3) throws IOException {
- linePath.moveTo((float) p0.getX(), (float) p0.getY());
- linePath.lineTo((float) p1.getX(), (float) p1.getY());
- linePath.lineTo((float) p2.getX(), (float) p2.getY());
- linePath.lineTo((float) p3.getX(), (float) p3.getY());
- linePath.closePath();
- }
- @Override
- public void drawImage(PDImage pdImage) throws IOException {
- ByteArrayOutputStream bosImage = new ByteArrayOutputStream();
- String suffix = "png";
- ImageIO.write(pdImage.getImage(), suffix, bosImage);
- String name = String.format("%s.%s", bcMD5(bosImage.toByteArray()), suffix);
- ofdCreator.putImage(name, bosImage.toByteArray(), suffix);
- Matrix ctmNew = this.getGraphicsState().getCurrentTransformationMatrix();
- float imageXScale = ctmNew.getScalingFactorX();
- float imageYScale = ctmNew.getScalingFactorY();
- double x = ctmNew.getTranslateX() * scale;
- double y = (page.getCropBox().getHeight() - ctmNew.getTranslateY() - imageYScale) * scale;
- double w = imageXScale * scale;
- double h = imageYScale * scale;
- ImageObject imageObject = new ImageObject(ofdCreator.getNextRid());
- imageObject.setBoundary(x, y, w, h);
- imageObject.setResourceID(new ST_RefID(ST_ID.getInstance(ofdCreator.getImageMap().get(name))));
- imageObject.setCTM(ST_Array.getInstance(String.format("%.0f 0 0 %.0f 0 0", w, h)));
- setImageClip(imageObject, x, y, w, h);
- ctLayer.add(imageObject);
- }
- private String getPointsFromClipArea(Area area, double x, double y, double w, double h) {
- String abbreviatedData = "";
- double[] coords = new double[6];
- for (PathIterator pi = area.getPathIterator(null);
- !pi.isDone();
- pi.next()) {
- switch (pi.currentSegment(coords)) {
- case PathIterator.SEG_MOVETO:
- abbreviatedData += String.format("M %.1f %.1f ", (coords[0] * scale - x) / w, ((page.getCropBox().getHeight() - coords[1]) * scale - y) / h);
- break;
- case PathIterator.SEG_LINETO:
- abbreviatedData += String.format("L %.1f %.1f ", (coords[0] * scale - x) / w, ((page.getCropBox().getHeight() - coords[1]) * scale - y) / h);
- break;
- case PathIterator.SEG_CUBICTO:
- abbreviatedData += String.format("B %.1f %.1f %.1f %.1f %.1f %.1f ", (coords[0] * scale - x) / w, ((page.getCropBox().getHeight() - coords[1]) * scale - y) / h, (coords[2] * scale - x) / w, ((page.getCropBox().getHeight() - coords[3]) * scale - y) / h, (coords[4] * scale - x) / w, ((page.getCropBox().getHeight() - coords[5]) * scale - y) / h);
- break;
- case PathIterator.SEG_CLOSE:
- abbreviatedData += " C";
- }
- }
- return abbreviatedData;
- }
- private void setImageClip(ImageObject imageObject, double ix, double iy, double iw, double ih) {
- Area clippingPath = this.getGraphicsState().getCurrentClippingPath();
- if (clippingPath != lastClip) {
- if (clippingPath.getPathIterator((AffineTransform) null).isDone()) {
- return;
- } else {
- double w = (clippingPath.getBounds().width * scale);
- double h = (clippingPath.getBounds().height * scale);
- double x = (clippingPath.getBounds().x * scale);
- double y = (page.getCropBox().getHeight() - clippingPath.getBounds().y - clippingPath.getBounds().height) * scale;
- x = Double.parseDouble(String.format("%.2f", x));
- y = Double.parseDouble(String.format("%.2f", y));
- w = Double.parseDouble(String.format("%.0f", w));
- h = Double.parseDouble(String.format("%.0f", h));
- double clipX = Math.abs(x - ix) / iw;
- double clipY = Math.abs(y - iy) / ih;
- double clipW = w / iw;
- double clipH = h / ih;
- lastClip = clippingPath;
- String abbreviatedData = getPointsFromClipArea(clippingPath, x, y, w, h);
- if (abbreviatedData.contains("B") || (clipX >= 0 && clipY >= 0 && (clipW >= 0 && clipW <= 1) && (clipH >= 0 && clipH <= 1))) {
- OFDElement abbreviatedDataEle = OFDElement.getInstance("AbbreviatedData");
- abbreviatedDataEle.setText(abbreviatedData);
- CT_Path ctPath = new CT_Path();
- ctPath.setFill(true);
- ctPath.setStroke(false);
- ctPath.setBoundary(clipX, clipY, clipW, clipH);
- ctPath.add(abbreviatedDataEle);
- org.ofdrw.core.pageDescription.clips.Area area = new org.ofdrw.core.pageDescription.clips.Area();
- area.add(ctPath);
- CT_Clip ct_clip = new CT_Clip();
- ct_clip.addArea(area);
- Clips clips = new Clips();
- clips.addClip(ct_clip);
- imageObject.setClips(clips);
- }
- }
- }
- }
- private String bcMD5(byte[] imageBytes) {
- Digest digest = new MD5Digest();
- digest.update(imageBytes, 0, imageBytes.length);
- byte[] md5Bytes = new byte[digest.getDigestSize()];
- digest.doFinal(md5Bytes, 0);
- return org.bouncycastle.util.encoders.Hex.toHexString(md5Bytes);
- }
- @Override
- public void clip(int windingRule) throws IOException {
- clipWindingRule = windingRule;
- }
- @Override
- public void moveTo(float x, float y) throws IOException {
- linePath.moveTo(x, y);
- }
- @Override
- public void lineTo(float x, float y) throws IOException {
- linePath.lineTo(x, y);
- }
- @Override
- public void curveTo(float x1, float y1, float x2, float y2, float x3, float y3) throws IOException {
- linePath.curveTo(x1, y1, x2, y2, x3, y3);
- }
- @Override
- public Point2D getCurrentPoint() throws IOException {
- return linePath.getCurrentPoint();
- }
- @Override
- public void closePath() throws IOException {
- linePath.closePath();
- }
- @Override
- public void endPath() throws IOException {
- if (clipWindingRule != -1) {
- linePath.setWindingRule(clipWindingRule);
- getGraphicsState().intersectClippingPath(linePath);
- clipWindingRule = -1;
- }
- linePath.reset();
- }
- @Override
- public void strokePath() throws IOException {
- ctLayer.add(getPathObject(false));
- linePath.reset();
- }
- @Override
- public void fillPath(int i) throws IOException {
- ctLayer.add(getPathObject(true));
- linePath.reset();
- }
- /**
- * 获取路径对象
- */
- private PathObject getPathObject(boolean fill) throws IOException {
- double x = 0, y = 0;
- float w = page.getCropBox().getWidth() * scale;
- float h = page.getCropBox().getHeight() * scale;
- double lineWidth = getGraphicsState().getLineWidth() * scale;
- PathObject path = new PathObject(ST_ID.getInstance(String.valueOf(ofdCreator.getNextRid())));
- path.setLineWidth(lineWidth);
- path.setBoundary(x, y, w, h);
- AbbreviatedData data = new AbbreviatedData();
- drawLine(linePath.getPathIterator(null), data, h);
- if (fill) {
- CT_Color nonStrokeColor = getNonStrokeColor();
- if (nonStrokeColor != null) {
- path.setFillColor(nonStrokeColor);
- path.setFill(true);
- path.setStroke(false);
- }
- } else {
- CT_Color strokeColor = getStrokeColor();
- if (strokeColor != null) {
- path.setStroke(true);
- path.setFill(false);
- path.setStrokeColor(strokeColor);
- } else {
- path.setStroke(false);
- }
- }
- path.setAbbreviatedData(data);
- return path;
- }
- /**
- * 获取非stroke颜色
- */
- private CT_Color getNonStrokeColor() throws IOException {
- PDColor color = getGraphicsState().getNonStrokingColor();
- if (color == null) {
- return null;
- }
- return getColor(color);
- }
- /**
- * 获取stroke颜色
- */
- private CT_Color getStrokeColor() throws IOException {
- PDColor color = getGraphicsState().getStrokingColor();
- if (color == null) {
- return null;
- }
- return getColor(color);
- }
- /**
- * 画线
- */
- private void drawLine(PathIterator iterator, AbbreviatedData data, float height) throws IOException {
- double[] coords = new double[6];
- while (!iterator.isDone()) {
- switch (iterator.currentSegment(coords)) {
- case PathIterator.SEG_MOVETO:
- data.moveTo(coords[0] * scale, height - coords[1] * scale);
- break;
- case PathIterator.SEG_LINETO:
- data.lineTo(coords[0] * scale, height - coords[1] * scale);
- break;
- case PathIterator.SEG_CUBICTO:
- data.B(coords[0] * scale, height - coords[1] * scale,
- coords[2] * scale, height - coords[3] * scale,
- coords[4] * scale, height - coords[5] * scale);
- break;
- case PathIterator.SEG_CLOSE:
- data.close();
- closePath();
- break;
- default:
- break;
- }
- iterator.next();
- }
- }
- @Override
- public void fillAndStrokePath(int windingRule) throws IOException {
- GeneralPath path = (GeneralPath) this.linePath.clone();
- this.fillPath(windingRule);
- this.linePath = path;
- this.strokePath();
- }
- @Override
- public void shadingFill(COSName cosName) throws IOException {
- }
- private TextObject $textObj = null;
- private TextCode $textCode = null;
- private Double $deltaX = 0d;
- private List<String> $deltaXList = null;
- private Double $deltaY = 0d;
- private List<String> $deltaYList = null;
- private StringBuffer $text = null;
- // 字符索引
- private int $stringIndex = 0;
- private List<String> $glyphs = null;
- private CmapLookup $cmap = null;
- private byte[] textByte;
- // 字体转换索引
- private List<String> $cgTransforms = null;
- /**
- * 元素队列
- */
- private List<Element> queue = new ArrayList<Element>();
- @Override
- protected void showText(byte[] string) throws IOException {
- // 初始化
- $stringIndex = 0;
- $textObj = null;
- $textCode = null;
- $deltaX = 0d;
- $deltaY = 0d;
- $text = new StringBuffer();
- $glyphs = new ArrayList<String>();
- $deltaXList = new ArrayList<String>();
- $deltaYList = new ArrayList<String>();
- $cgTransforms = new ArrayList<String>();
- $cmap = null;
- textByte = string;
- // 处理文字
- super.showText(string);
- // 完成添加文字
- String text = $text.toString();
- if (null == text || "".equals(text)) {
- return;
- }
- if ($glyphs != null && $glyphs.size() > 0) {
- // 添加字符变换
- addCGTransform(text);
- }
- if ($deltaXList != null && $deltaXList.size() > 0) {
- // 宽度根据所有字体累加
- Double deltaWidth = $textObj.getBoundary().getWidth();
- for (String w : $deltaXList) {
- deltaWidth += Double.valueOf(w);
- }
- $textObj.setBoundary($textObj.getBoundary().setWidth(deltaWidth));
- $textCode.setDeltaX(new ST_Array($deltaXList.toArray(new String[$deltaXList.size()])));
- }
- if ($deltaYList != null && $deltaYList.size() > 0) {
- // 高度根据所有字体累加
- Double deltaHeight = $textObj.getBoundary().getHeight();
- for (String h : $deltaYList) {
- deltaHeight += Double.valueOf(h);
- }
- $textObj.setBoundary($textObj.getBoundary().setHeight(deltaHeight));
- $textCode.setDeltaY(new ST_Array($deltaYList.toArray(new String[$deltaYList.size()])));
- }
- // 扩展
- drawTextParam();
- $textCode.setContent(text);
- $textObj.addTextCode($textCode);
- queue.add($textObj);
- }
- /**
- * Glyph bounding boxes.
- */
- @Override
- protected void showGlyph(Matrix textRenderingMatrix, PDFont font, int code,
- Vector displacement) throws IOException {
- String unicode = font.toUnicode(code);
- boolean isUnicode = false;
- if (null == unicode || "".equals(unicode)) {
- unicode = "¤";// 占位符
- isUnicode = true;
- }
- $cgTransforms.add($stringIndex + "-" + unicode.length());
- PDGraphicsState state = getGraphicsState();
- RenderingMode renderingMode = state.getTextState().getRenderingMode();
- Matrix ctm = state.getCurrentTransformationMatrix();
- float fontSize = state.getTextState().getFontSize();
- float horizontalScaling = state.getTextState().getHorizontalScaling()
- / 100f;
- Matrix textMatrix = getTextMatrix();
- double angle = getRotate(textRenderingMatrix);
- BoundingBox bbox = font.getBoundingBox();
- if (bbox.getLowerLeftY() < Short.MIN_VALUE) {
- // PDFBOX-2158 and PDFBOX-3130
- // files by Salmat eSolutions / ClibPDF Library
- bbox.setLowerLeftY(-(bbox.getLowerLeftY() + 65536));
- }
- // 1/2 the bbox is used as the height todo: why?
- float glyphHeight = bbox.getHeight() / 2;
- // sometimes the bbox has very high values, but CapHeight is OK
- PDFontDescriptor fontDescriptor = font.getFontDescriptor();
- if (fontDescriptor != null) {
- float capHeight = fontDescriptor.getCapHeight();
- if (Float.compare(capHeight, 0) != 0 && (capHeight < glyphHeight
- || Float.compare(glyphHeight, 0) == 0)) {
- glyphHeight = capHeight;
- }
- // PDFBOX-3464, PDFBOX-4480, PDFBOX-4553:
- // sometimes even CapHeight has very high value, but Ascent and
- // Descent are ok
- float ascent = fontDescriptor.getAscent();
- float descent = fontDescriptor.getDescent();
- if (capHeight > ascent && ascent > 0 && descent < 0
- && ((ascent - descent) / 2 < glyphHeight
- || Float.compare(glyphHeight, 0) == 0)) {
- glyphHeight = (ascent - descent) / 2;
- }
- }
- // transformPoint from glyph space -> text space
- float height;
- if (font instanceof PDType3Font) {
- height = font.getFontMatrix().transformPoint(0, glyphHeight).y;
- } else {
- height = glyphHeight / 1000;
- }
- float displacementX = displacement.getX();
- // the sorting algorithm is based on the width of the character. As the
- // displacement
- // for vertical characters doesn't provide any suitable value for it, we
- // have to
- // calculate our own
- TrueTypeFont ttf = null;
- if (font instanceof PDTrueTypeFont) {
- ttf = ((PDTrueTypeFont) font).getTrueTypeFont();
- } else if (font instanceof PDType0Font) {
- PDCIDFont cidFont = ((PDType0Font) font).getDescendantFont();
- if (cidFont instanceof PDCIDFontType2) {
- ttf = ((PDCIDFontType2) cidFont).getTrueTypeFont();
- }
- }
- if (font.isVertical()) {
- displacementX = font.getWidth(code) / 1000;
- // there may be an additional scaling factor for true type fonts
- if (ttf != null && ttf.getUnitsPerEm() != 1000) {
- displacementX *= 1000f / ttf.getUnitsPerEm();
- }
- }
- //
- // legacy calculations which were previously in PDFStreamEngine
- //
- // DO NOT USE THIS CODE UNLESS YOU ARE WORKING WITH PDFTextStripper.
- // THIS CODE IS DELIBERATELY INCORRECT
- //
- // (modified) combined displacement, this is calculated *without* taking
- // the character
- // spacing and word spacing into account, due to legacy code in
- // TextStripper
- float tx = displacementX * fontSize * horizontalScaling;
- float ty = displacement.getY() * fontSize;
- // (modified) combined displacement matrix
- Matrix td = Matrix.getTranslateInstance(tx, ty);
- // (modified) text rendering matrix
- Matrix nextTextRenderingMatrix = td.multiply(textMatrix).multiply(ctm); // text
- // space
- // ->
- // device
- // space
- float nextX = nextTextRenderingMatrix.getTranslateX();
- float nextY = nextTextRenderingMatrix.getTranslateY();
- float dxDisplay = nextX - textRenderingMatrix.getTranslateX();
- float dyDisplay = height * textRenderingMatrix.getScalingFactorY();
- float glyphSpaceToTextSpaceFactor = 1 / 1000f;
- if (font instanceof PDType3Font) {
- glyphSpaceToTextSpaceFactor = font.getFontMatrix().getScaleX();
- }
- float spaceWidthText = 0;
- try {
- spaceWidthText = font.getSpaceWidth() * glyphSpaceToTextSpaceFactor;
- } catch (Throwable exception) {
- logger.error(exception.getMessage(), exception);
- }
- if (spaceWidthText == 0) {
- spaceWidthText = font.getAverageFontWidth()
- * glyphSpaceToTextSpaceFactor;
- spaceWidthText *= .80f;
- }
- if (spaceWidthText == 0) {
- spaceWidthText = 1.0f; // if could not find font, use a generic
- // value
- }
- // the space width has to be transformed into display units
- float spaceWidthDisplay = spaceWidthText
- * textRenderingMatrix.getScalingFactorX();
- if (angle == 0d) {
- fontSize = textRenderingMatrix.getScaleY() / PX2MM;
- }
- // 修复字体水平旋转,大小为空
- if (fontSize == 0) {
- fontSize = dyDisplay / PX2MM;
- }
- TextPosition textPosition = new TextPosition(pageRotation,
- page.getCropBox().getWidth(), page.getCropBox().getHeight(), textRenderingMatrix,
- nextX, nextY, Math.abs(dyDisplay), dxDisplay,
- Math.abs(spaceWidthDisplay), unicode, new int[]{code}, font,
- fontSize, (int) (fontSize * textMatrix.getScalingFactorX()));
- String fontName = "";
- if (font.getFontDescriptor() != null) {
- fontName = font.getFontDescriptor().getFontFamily();
- if (null == fontName || "".equals(fontName)) {
- fontName = font.getName();
- }
- }
- boolean willBeSubset = font.isEmbedded() || font.willBeSubset();
- String text = unicode;
- $text.append(text);
- int fontInt = 1;
- if ($stringIndex == 0) {
- long textID = ofdCreator.getNextRid();
- $textObj = new TextObject(textID);
- String fontHash = "" + font.hashCode();
- String fontId = ofdCreator.getFontMap().get(fontHash);
- if (fontId == null) {
- byte[] fontBytes = writeFont(font);
- fontId = ofdCreator.putFont(fontHash, fontName, fontName, fontBytes, ".otf");
- }
- fontInt = Integer.valueOf(fontId);
- $textCode = new TextCode();
- AffineTransform transform = new AffineTransform();
- transform.rotate(Math.toRadians(angle), textPosition.getWidth(),
- textPosition.getHeight());
- if (angle == 0)
- {
- $textCode.setX(0d);
- $textCode.setY((double)fontSize);
- $textObj.setBoundary(
- textPosition.getX() / PX2MM,
- Math.abs(
- textPosition.getY() / PX2MM
- - fontSize),
- textRenderingMatrix.getScaleX()
- / PX2MM,
- dyDisplay).setFont(fontInt)
- .setSize((double)fontSize);
- }
- else
- {
- $textCode.setX(0d);
- $textCode.setY(0d);
- $textObj.setBoundary(0, 0, textPosition.getX(),
- textPosition.getY()).setFont(fontInt).setSize(fontSize / (double)PX2MM);
- }
- }
- Integer glyphId = code;
- if (font instanceof PDTrueTypeFont) {
- PDTrueTypeFont ttfFont = (PDTrueTypeFont) font;
- glyphId = ttfFont.codeToGID(code);
- } else if (font instanceof PDType1CFont) {
- PDType1CFont type1CFont = (PDType1CFont) font;
- String name = type1CFont.codeToName(code);
- glyphId = type1CFont.getCFFType1Font().nameToGID(name);
- }
- if ($stringIndex == 0 && ttf != null && willBeSubset) {
- try {
- $cmap = ttf.getUnicodeCmapLookup();
- } catch (Exception e) {
- //logger.warn("加载字体异常",e);
- }
- /**
- * 存在cmap,从cmap中获取glyphId,否则code即为glyphId<br>
- * 详见PDFDebugger查看pdf内部结构方法源码 <br>
- *
- * @link org.apache.pdfbox.debugger.PDFDebugger
- */
- if ($cmap != null && ttf != null && willBeSubset) {
- glyphId = $cmap.getGlyphId(text.codePointAt(0));
- }
- }
- // unicode编码字体
- if (isUnicode || glyphId == 0) {
- glyphId = code;
- }
- if (willBeSubset) {
- $glyphs.add("" + glyphId);
- }
- Double topLeftX = textPosition.getX() / (double) PX2MM;
- if ($stringIndex > 0 && $deltaX.compareTo(topLeftX) != 0) {
- Double w = topLeftX - $deltaX;
- $deltaXList.add("" + w);
- }
- $deltaX = topLeftX;
- Double topLeftY = textPosition.getY() / (double) PX2MM;
- if ($stringIndex > 0 && $deltaY.compareTo(topLeftY) != 0) {
- Double h = topLeftY - $deltaY;
- $deltaYList.add("" + h);
- }
- $deltaY = topLeftY;
- Float scaleX = 1f;
- Float scaleY = 1f;
- Float lineWidth = state.getLineWidth();
- // 粗体
- if (renderingMode.isStroke() && lineWidth != null) {
- // minimum line width as used by Adobe Reader
- if (lineWidth < 0.25) {
- lineWidth = 0.25f;
- }
- $textObj.setLineWidth(
- lineWidth.doubleValue() / PX2MM);
- }
- if (angle == 0d) {
- $textObj.setCTM(
- new ST_Array(scaleX, ctm.getShearX() / PX2MM,
- ctm.getShearY() / PX2MM, scaleY, 0, 0));
- } else {
- $textObj.setCTM(new ST_Array(
- nextTextRenderingMatrix.getScaleX(),
- nextTextRenderingMatrix.getShearX(),
- nextTextRenderingMatrix.getShearY(),
- nextTextRenderingMatrix.getScaleY(),
- textPosition.getX() / PX2MM,
- textPosition.getY() / PX2MM));
- }
- if (nextTextRenderingMatrix.getScaleX() != nextTextRenderingMatrix.getScaleY()) {
- $textObj.setHScale((double) nextTextRenderingMatrix.getScaleX());
- }
- $stringIndex++;
- }
- private byte[] writeFont(PDFont font) {
- byte[] fontBytes = null;
- InputStream is = null;
- try {
- if (font instanceof PDTrueTypeFont) {
- PDTrueTypeFont f = (PDTrueTypeFont) font;
- is = f.getTrueTypeFont().getOriginalData();
- } else if (font instanceof PDType0Font) {
- PDType0Font type0Font = (PDType0Font) font;
- if (type0Font.getDescendantFont() instanceof PDCIDFontType2) {
- PDCIDFontType2 ff = (PDCIDFontType2) type0Font
- .getDescendantFont();
- is = ff.getTrueTypeFont().getOriginalData();
- } else if (type0Font
- .getDescendantFont() instanceof PDCIDFontType0) {
- // a Type0 CIDFont contains CFF font
- PDCIDFontType0 cidType0Font = (PDCIDFontType0) type0Font
- .getDescendantFont();
- PDFontDescriptor s = cidType0Font.getFontDescriptor();
- PDStream s1 = s.getFontFile();
- if (s1 != null) {
- is = s1.createInputStream();
- }
- PDStream s2 = s.getFontFile2();
- if (s2 != null) {
- is = s2.createInputStream();
- }
- PDStream s3 = s.getFontFile3();
- if (s3 != null) {
- is = s3.createInputStream();
- }
- } else {
- PDType0Font f = (PDType0Font) font;
- PDFontDescriptor s = f.getFontDescriptor();
- PDStream s1 = s.getFontFile();
- if (s1 != null) {
- is = s1.createInputStream();
- }
- PDStream s2 = s.getFontFile2();
- if (s2 != null) {
- is = s2.createInputStream();
- }
- PDStream s3 = s.getFontFile3();
- if (s3 != null) {
- is = s3.createInputStream();
- }
- }
- } else if (font instanceof PDType1Font) {
- PDType1Font f = (PDType1Font) font;
- PDFontDescriptor s = f.getFontDescriptor();
- PDStream s1 = s.getFontFile();
- if (s1 != null) {
- is = s1.createInputStream();
- }
- PDStream s2 = s.getFontFile2();
- if (s2 != null) {
- is = s2.createInputStream();
- }
- PDStream s3 = s.getFontFile3();
- if (s3 != null) {
- is = s3.createInputStream();
- }
- } else if (font instanceof PDType1CFont) {
- PDType1CFont f = (PDType1CFont) font;
- PDFontDescriptor s = f.getFontDescriptor();
- PDStream s1 = s.getFontFile();
- if (s1 != null) {
- is = s1.createInputStream();
- }
- PDStream s2 = s.getFontFile2();
- if (s2 != null) {
- is = s2.createInputStream();
- }
- PDStream s3 = s.getFontFile3();
- if (s3 != null) {
- is = s3.createInputStream();
- }
- } else if (font instanceof PDType3Font) {
- PDType3Font f = (PDType3Font) font;
- PDFontDescriptor s = f.getFontDescriptor();
- PDStream s1 = s.getFontFile();
- if (s1 != null) {
- is = s1.createInputStream();
- }
- PDStream s2 = s.getFontFile2();
- if (s2 != null) {
- is = s2.createInputStream();
- }
- PDStream s3 = s.getFontFile3();
- if (s3 != null) {
- is = s3.createInputStream();
- }
- }
- if (is != null) {
- fontBytes = IOUtils.toByteArray(is);
- } else {
- logger.error("生成字体文件异常:" + font.getClass());
- }
- } catch (Exception e) {
- logger.error("生成字体文件异常:" + font.getName(), e);
- } finally {
- IOUtils.closeQuietly(is);
- }
- return fontBytes;
- }
- /**
- * 绘画文字扩展属性<br/>
- * <p>
- * 绘画文字扩展属性
- * </p>
- *
- * @throws IOException 异常
- */
- private void drawTextParam() throws IOException {
- PDGraphicsState state = getGraphicsState();
- RenderingMode renderingMode = state.getTextState().getRenderingMode();
- setColor($textObj, state.getNonStrokingColor(), true);
- if (renderingMode.isFill()) {
- $textObj.setFill(true);
- }
- setColor($textObj, state.getStrokingColor(), false);
- if (renderingMode.isStroke()) {
- $textObj.setStroke(true);
- }
- }
- /**
- * 计算旋转角度<br/>
- * <p>
- * 计算旋转角度
- * </p>
- *
- * @param textMatrix
- * @return
- */
- private double getRotate(Matrix textMatrix) {
- double angle = 180 * Math.atan2(Float.valueOf(textMatrix.getShearX()),
- Float.valueOf(textMatrix.getScaleY())) / Math.PI;
- if (angle < 0) {
- angle = 360 + angle;
- }
- return angle;
- }
- private void setColor(Object object, PDColor color,
- boolean noStroke) throws IOException {
- if (color == null) {
- return;
- }
- CT_Color ctColor = getColor(color);
- if (noStroke) {
- ctColor.setOFDName("FillColor");
- if (object instanceof TextObject) {
- TextObject o = (TextObject) object;
- o.setFillColor(ctColor);
- } else if (object instanceof PathObject) {
- PathObject o = (PathObject) object;
- o.setFillColor(ctColor);
- } else if (object instanceof CT_Path) {
- CT_Path o = (CT_Path) object;
- o.setFillColor(ctColor);
- }
- } else {
- ctColor.setOFDName("StrokeColor");
- if (object instanceof TextObject) {
- TextObject o = (TextObject) object;
- o.setStrokeColor(ctColor);
- } else if (object instanceof PathObject) {
- PathObject o = (PathObject) object;
- o.setStrokeColor(ctColor);
- } else if (object instanceof CT_Path) {
- CT_Path o = (CT_Path) object;
- o.setStrokeColor(ctColor);
- }
- }
- }
- private CT_Color getColor(PDColor color) throws IOException {
- CT_Color ctColor = new CT_Color();
- if (color != null) {
- PDColorSpace colorSpace = color.getColorSpace();
- float[] rgb = colorSpace.toRGB(color.getComponents());
- ctColor = CT_Color.rgb(toRgbNumber(rgb[0]), toRgbNumber(rgb[1]), toRgbNumber(rgb[2]));
- }
- return ctColor;
- }
- /**
- * 添加字符变换
- *
- * @param text
- */
- private void addCGTransform(String text) {
- int total = text.length();
- CT_CGTransform cgTransform = new CT_CGTransform();
- cgTransform.setCodePosition(0);
- cgTransform.setGlyphCount(total);
- cgTransform.setCodeCount(total);
- cgTransform.setGlyphs(new ST_Array($glyphs.toArray(new String[$glyphs.size()])));
- $textObj.addCGTransform(cgTransform);
- }
- /**
- * 转换为rgb
- */
- private int toRgbNumber(float color) {
- return color < 0 ? 0 : (int) ((color > 1 ? 1 : color) * 255);
- }
- }
|