/*
* Copyright 2006-2017 ICEsoft Technologies Canada Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS
* IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
package org.icepdf.core.pobjects.graphics.text;
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import java.awt.geom.Rectangle2D;
import java.util.logging.Logger;
/**
* Glyph Sprite contains glyph bound and textual information for drawing
* and text extraction. The Object is used as a child of TextSprite
* for painting and as a child of TextWord for text extraction and selection.
*
* @since 4.0
*/
public class GlyphText extends AbstractText {
private static final Logger logger =
Logger.getLogger(GlyphText.class.toString());
// x and y coordinates used for painting glyph
private float x, y;
// character code used to represent glyph, maybe ascii or CID value
private String cid;
// Unicode/ASCII value that is represented by glyph, a cid can be
// represented by one or more characters.
private String unicode;
public GlyphText(float x, float y, Rectangle2D.Float bounds,
String cid, String unicode) {
this.x = x;
this.y = y;
this.bounds = bounds;
this.textExtractionBounds = new Rectangle2D.Float(bounds.x, bounds.y, bounds.width, bounds.height);
this.cid = cid;
this.unicode = unicode;
}
/**
* Maps the glyph bounds to user space
*
* @param af transform from glyph space to user space
* @param af1 transform from glyph space, if shear is detected the
* extracted bounds are rotated back to the portrait layout.
*/
public void normalizeToUserSpace(AffineTransform af, AffineTransform af1) {
// map the coordinates from glyph space to user space.
GeneralPath generalPath = new GeneralPath(bounds);
generalPath.transform(af);
bounds = (Rectangle2D.Float) generalPath.getBounds2D();
// we have some portrait type layouts where the text is actually
// running on the y-axis. The reason for this is Tm that specifies
// a -1 shear which is basically a 90 degree rotation. Which breaks
// our left to right top down text extraction logic (PDF-854).
if (af1 != null && af1.getShearX() < -1) {
// adjust of the rotation, move the text back to a normal layout.
generalPath = new GeneralPath(bounds);
generalPath.transform(new AffineTransform(0, -1, 1, 0, 0, 0));
textExtractionBounds = (Rectangle2D.Float) generalPath.getBounds2D();
} else if (af1 != null && af1.getShearY() < -1) {
// adjust of the rotation, move the text back to a normal layout.
generalPath = new GeneralPath(bounds);
generalPath.transform(new AffineTransform(0, 1, -1, 0, 0, 0));
textExtractionBounds = (Rectangle2D.Float) generalPath.getBounds2D();
} else {
// 99% of the time we just use the bounds.
textExtractionBounds = bounds;
}
}
public String getCid() {
return cid;
}
public String getUnicode() {
return unicode;
}
public float getX() {
return x;
}
public float getY() {
return y;
}
public Rectangle2D.Float getBounds() {
return bounds;
}
}