From 2acbe5089e47421824a26c043ff586bfa5465754 Mon Sep 17 00:00:00 2001 From: Patrick Corless Date: Thu, 4 Mar 2021 23:49:26 -0700 Subject: [PATCH] GH-80 further toUnicode and text selection improvements. --- .../pobjects/fonts/zfont/TrueTypeFont.java | 4 ++ .../fonts/zfont/fontFiles/ZFontTrueType.java | 4 +- .../fonts/zfont/fontFiles/ZFontType0.java | 4 +- .../fonts/zfont/fontFiles/ZFontType1.java | 4 +- .../fonts/zfont/fontFiles/ZFontType1C.java | 5 +-- .../fonts/zfont/fontFiles/ZFontType2.java | 4 +- .../fonts/zfont/fontFiles/ZFontType3.java | 4 +- .../fonts/zfont/fontFiles/ZSimpleFont.java | 44 +++++++++++++------ .../core/pobjects/graphics/TextSprite.java | 31 ++++--------- .../parser/content/AbstractContentParser.java | 1 - .../util/parser/content/ContentParser.java | 2 +- 11 files changed, 55 insertions(+), 52 deletions(-) diff --git a/core/core-awt/src/main/java/org/icepdf/core/pobjects/fonts/zfont/TrueTypeFont.java b/core/core-awt/src/main/java/org/icepdf/core/pobjects/fonts/zfont/TrueTypeFont.java index abb3affc6..800a0685c 100644 --- a/core/core-awt/src/main/java/org/icepdf/core/pobjects/fonts/zfont/TrueTypeFont.java +++ b/core/core-awt/src/main/java/org/icepdf/core/pobjects/fonts/zfont/TrueTypeFont.java @@ -20,6 +20,10 @@ public TrueTypeFont(Library library, HashMap entries) { public synchronized void init() { super.init(); inited = true; + if (encoding == null) { + encoding = Encoding.standardEncoding; + font = font.deriveFont(encoding, toUnicodeCMap); + } } diff --git a/core/core-awt/src/main/java/org/icepdf/core/pobjects/fonts/zfont/fontFiles/ZFontTrueType.java b/core/core-awt/src/main/java/org/icepdf/core/pobjects/fonts/zfont/fontFiles/ZFontTrueType.java index e6080382e..bc30f9bd0 100644 --- a/core/core-awt/src/main/java/org/icepdf/core/pobjects/fonts/zfont/fontFiles/ZFontTrueType.java +++ b/core/core-awt/src/main/java/org/icepdf/core/pobjects/fonts/zfont/fontFiles/ZFontTrueType.java @@ -203,7 +203,7 @@ public FontFile deriveFont(float[] widths, int firstCh, float missingWidth, floa font.descent = descent; font.widths = widths; font.cMap = diff; - font.bbox = calculateBbox(bbox); + font.bbox = bbox; return font; } @@ -215,7 +215,7 @@ public FontFile deriveFont(Map widths, int firstCh, float missin font.ascent = ascent; font.descent = descent; font.cMap = diff; - font.bbox = calculateBbox(bbox); + font.bbox = bbox; return font; } diff --git a/core/core-awt/src/main/java/org/icepdf/core/pobjects/fonts/zfont/fontFiles/ZFontType0.java b/core/core-awt/src/main/java/org/icepdf/core/pobjects/fonts/zfont/fontFiles/ZFontType0.java index 59e256d85..7f1424ae7 100644 --- a/core/core-awt/src/main/java/org/icepdf/core/pobjects/fonts/zfont/fontFiles/ZFontType0.java +++ b/core/core-awt/src/main/java/org/icepdf/core/pobjects/fonts/zfont/fontFiles/ZFontType0.java @@ -168,7 +168,7 @@ public FontFile deriveFont(float[] widths, int firstCh, float missingWidth, floa font.descent = descent; font.widths = widths; font.cMap = diff != null ? diff : font.cMap; - font.bbox = calculateBbox(bbox); + font.bbox = bbox; return font; } @@ -181,7 +181,7 @@ public FontFile deriveFont(Map widths, int firstCh, float missin font.ascent = ascent; font.descent = descent; font.cMap = diff; - font.bbox = calculateBbox(bbox); + font.bbox = bbox; return font; // } else { // return this; diff --git a/core/core-awt/src/main/java/org/icepdf/core/pobjects/fonts/zfont/fontFiles/ZFontType1.java b/core/core-awt/src/main/java/org/icepdf/core/pobjects/fonts/zfont/fontFiles/ZFontType1.java index f6f45a1bc..a43f96dcd 100644 --- a/core/core-awt/src/main/java/org/icepdf/core/pobjects/fonts/zfont/fontFiles/ZFontType1.java +++ b/core/core-awt/src/main/java/org/icepdf/core/pobjects/fonts/zfont/fontFiles/ZFontType1.java @@ -114,7 +114,7 @@ public FontFile deriveFont(float[] widths, int firstCh, float missingWidth, floa font.descent = descent; font.widths = widths; font.cMap = diff != null ? diff : font.cMap; - font.bbox = calculateBbox(bbox); + font.bbox = bbox; return font; } @@ -126,7 +126,7 @@ public FontFile deriveFont(Map widths, int firstCh, float missin font.ascent = ascent; font.descent = descent; font.cMap = diff; - font.bbox = calculateBbox(bbox); + font.bbox = bbox; return font; } diff --git a/core/core-awt/src/main/java/org/icepdf/core/pobjects/fonts/zfont/fontFiles/ZFontType1C.java b/core/core-awt/src/main/java/org/icepdf/core/pobjects/fonts/zfont/fontFiles/ZFontType1C.java index e90cc1f6e..ae4980e4c 100644 --- a/core/core-awt/src/main/java/org/icepdf/core/pobjects/fonts/zfont/fontFiles/ZFontType1C.java +++ b/core/core-awt/src/main/java/org/icepdf/core/pobjects/fonts/zfont/fontFiles/ZFontType1C.java @@ -95,10 +95,9 @@ public FontFile deriveFont(float[] widths, int firstCh, float missingWidth, floa font.firstCh = firstCh; font.ascent = ascent; font.descent = descent; - font.bbox = calculateBbox(bbox); font.widths = widths; font.cMap = diff != null ? diff : font.cMap; - font.bbox = calculateBbox(bbox); + font.bbox = bbox; return font; } @@ -110,7 +109,7 @@ public FontFile deriveFont(Map widths, int firstCh, float missin font.ascent = ascent; font.descent = descent; font.cMap = diff; - font.bbox = calculateBbox(bbox); + font.bbox = bbox; return font; } diff --git a/core/core-awt/src/main/java/org/icepdf/core/pobjects/fonts/zfont/fontFiles/ZFontType2.java b/core/core-awt/src/main/java/org/icepdf/core/pobjects/fonts/zfont/fontFiles/ZFontType2.java index ee3a3e586..4556cfa25 100644 --- a/core/core-awt/src/main/java/org/icepdf/core/pobjects/fonts/zfont/fontFiles/ZFontType2.java +++ b/core/core-awt/src/main/java/org/icepdf/core/pobjects/fonts/zfont/fontFiles/ZFontType2.java @@ -155,7 +155,7 @@ public FontFile deriveFont(float[] widths, int firstCh, float missingWidth, floa font.ascent = ascent; font.descent = descent; font.cMap = diff; - font.bbox = calculateBbox(bbox); + font.bbox = bbox; return font; } @@ -166,7 +166,7 @@ public FontFile deriveFont(Map widths, int firstCh, float missin font.ascent = ascent; font.descent = descent; font.cMap = diff; - font.bbox = calculateBbox(bbox); + font.bbox = bbox; return font; } diff --git a/core/core-awt/src/main/java/org/icepdf/core/pobjects/fonts/zfont/fontFiles/ZFontType3.java b/core/core-awt/src/main/java/org/icepdf/core/pobjects/fonts/zfont/fontFiles/ZFontType3.java index c47d0ca4f..b825df368 100644 --- a/core/core-awt/src/main/java/org/icepdf/core/pobjects/fonts/zfont/fontFiles/ZFontType3.java +++ b/core/core-awt/src/main/java/org/icepdf/core/pobjects/fonts/zfont/fontFiles/ZFontType3.java @@ -114,7 +114,7 @@ public FontFile deriveFont(float[] widths, int firstCh, float missingWidth, floa font.missingWidth = missingWidth; font.ascent = ascent; font.descent = descent; - font.bbox = calculateBbox(bbox); + font.bbox = bbox; // todo diff cmap, likely not a type3 thing, see if an example shows up. return font; } @@ -128,7 +128,7 @@ public FontFile deriveFont(Map widths, int firstCh, float missin font.missingWidth = missingWidth; font.ascent = ascent; font.descent = descent; - font.bbox = calculateBbox(bbox); + font.bbox = bbox; return font; } diff --git a/core/core-awt/src/main/java/org/icepdf/core/pobjects/fonts/zfont/fontFiles/ZSimpleFont.java b/core/core-awt/src/main/java/org/icepdf/core/pobjects/fonts/zfont/fontFiles/ZSimpleFont.java index 4a8d4f2d0..d891fb298 100644 --- a/core/core-awt/src/main/java/org/icepdf/core/pobjects/fonts/zfont/fontFiles/ZSimpleFont.java +++ b/core/core-awt/src/main/java/org/icepdf/core/pobjects/fonts/zfont/fontFiles/ZSimpleFont.java @@ -8,6 +8,7 @@ import java.awt.*; import java.awt.geom.AffineTransform; +import java.awt.geom.Area; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.io.IOException; @@ -147,9 +148,33 @@ public void drawEstring(Graphics2D g, String estr, float x, float y, long layout } } + @Override + public Shape getEstringOutline(String estr, float x, float y) { + try { + String name = codeToName(estr); + Shape glyph = fontBoxFont.getPath(name); + if (encoding != null && !fontBoxFont.hasGlyph(name)) { + name = encoding.getName(estr.charAt(0)); + if (name != null) { + glyph = fontBoxFont.getPath(name); + } + } + + Area outline = new Area(glyph); + AffineTransform transform = new AffineTransform(); + transform.translate(x, y); + transform.concatenate(fontTransform); + outline = outline.createTransformedArea(transform); + return outline; + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + @Override public Rectangle2D getMaxCharBounds() { - return bbox; + return calculateBbox(bbox); } @Override @@ -236,11 +261,6 @@ public String getFormat() { return null; } - @Override - public Shape getEstringOutline(String estr, float x, float y) { - return null; - } - @Override public ByteEncoding getByteEncoding() { return null; @@ -284,14 +304,10 @@ protected char getCharDiff(char character) { protected Rectangle2D calculateBbox(Rectangle2D bbox) { if (bbox != null) { - double scaleX = 0.001 / fontMatrix.getScaleX(); - double scaleY = 0.001 / fontMatrix.getScaleY(); - - return new Rectangle2D.Double( - bbox.getX() * scaleX, - bbox.getY() * scaleY, - bbox.getWidth() * scaleX, - bbox.getHeight() * scaleY); + AffineTransform af = new AffineTransform(); +// af.scale(size, size); + af.concatenate(fontMatrix); + return af.createTransformedShape(bbox).getBounds2D(); } return this.bbox; } diff --git a/core/core-awt/src/main/java/org/icepdf/core/pobjects/graphics/TextSprite.java b/core/core-awt/src/main/java/org/icepdf/core/pobjects/graphics/TextSprite.java index 9d5bdf6bb..92fbe9116 100644 --- a/core/core-awt/src/main/java/org/icepdf/core/pobjects/graphics/TextSprite.java +++ b/core/core-awt/src/main/java/org/icepdf/core/pobjects/graphics/TextSprite.java @@ -22,6 +22,7 @@ import java.awt.*; import java.awt.geom.AffineTransform; import java.awt.geom.Area; +import java.awt.geom.GeneralPath; import java.awt.geom.Rectangle2D; import java.util.ArrayList; @@ -106,19 +107,11 @@ public GlyphText addText(String cid, String unicode, float x, float y, float wid // we can change the bounds of glyphBounds as this is what needs to be normalized // to page space // IMPORTANT: where working in Java Coordinates with any of the Font bounds - double descent = font.getDescent(); - double ascent = font.getAscent(); + float descent = (float) font.getDescent(); + float ascent = (float) font.getAscent(); float w = width;//(float)stringBounds.getWidth(); - float h = (float) (ascent - descent); + float h = ascent - descent; - Rectangle2D bbox = font.getMaxCharBounds(); - - if (h <= 0.0f) { - h = (float) bbox.getHeight(); - } - if (w <= 0.0f) { - w = (float) bbox.getWidth(); - } // zero height will not intersect with clip rectangle and maybe have visibility issues. // we generally get here if the font.getAscent is zero and as a result must compensate. if (h <= 0.0f) { @@ -130,16 +123,13 @@ public GlyphText addText(String cid, String unicode, float x, float y, float wid h = font.getSize(); } } - // apply fontsize. +// Rectangle2D.Float glyphBounds = new Rectangle2D.Float(x, y - ascent, w, h); h *= Math.abs(font.getSize()); - descent *= Math.abs(font.getSize()); - Rectangle2D.Float glyphBounds; - // irregular negative layout of text, need to create the bbox appropriately. if (w < 0.0f || font.getSize() < 0) { - glyphBounds = new Rectangle2D.Float(x + width, y - (float) descent, -w, h); + glyphBounds = new Rectangle2D.Float(x + width, y - ascent, -w, h); } else { - glyphBounds = new Rectangle2D.Float(x, y - h - (float) descent, w, h); + glyphBounds = new Rectangle2D.Float(x, y - ascent, w, h); } // add bounds to total text bounds. @@ -296,7 +286,6 @@ public void setFontSize(int fontSize) { this.fontSize = fontSize; } - /* private void drawBoundBox(Graphics2D gg) { // draw the characters @@ -319,12 +308,11 @@ private void drawBoundBox(Graphics2D gg) { gg.setColor(oldColor); gg.setStroke(oldStroke); } - */ public void setFont(FontFile font) { this.font = font; } - /* + private void drawGyphBox(Graphics2D gg, GlyphText glyphSprite) { // draw the characters @@ -349,9 +337,6 @@ private void drawGyphBox(Graphics2D gg, GlyphText glyphSprite) { } - - */ - /** * Tests if the interior of the TextSprite bounds intersects the * interior of a specified shape. diff --git a/core/core-awt/src/main/java/org/icepdf/core/util/parser/content/AbstractContentParser.java b/core/core-awt/src/main/java/org/icepdf/core/util/parser/content/AbstractContentParser.java index 39e1e49ca..c87390603 100644 --- a/core/core-awt/src/main/java/org/icepdf/core/util/parser/content/AbstractContentParser.java +++ b/core/core-awt/src/main/java/org/icepdf/core/util/parser/content/AbstractContentParser.java @@ -1467,7 +1467,6 @@ private static void drawString( // glyph placement params float currentX, currentY; float newAdvanceX, newAdvanceY; - // Iterate through displayText to calculate the the new advanceX value for (int i = 0; i < textLength; i++) { currentChar = displayText.charAt(i); diff --git a/core/core-awt/src/main/java/org/icepdf/core/util/parser/content/ContentParser.java b/core/core-awt/src/main/java/org/icepdf/core/util/parser/content/ContentParser.java index 599ff03ff..5c6b3f6c8 100644 --- a/core/core-awt/src/main/java/org/icepdf/core/util/parser/content/ContentParser.java +++ b/core/core-awt/src/main/java/org/icepdf/core/util/parser/content/ContentParser.java @@ -142,7 +142,7 @@ public ContentParser parse(byte[][] streamBytes, Page page) try { yBTstart = parseText(lexer, shapes, yBTstart); } catch (Exception e) { - logger.log(Level.FINEST, "Error parsing text block", e); + logger.log(Level.SEVERE, "Error parsing text block", e); } finally { inTextBlock = false; }