
org.jpedal.fonts.glyph.PdfJavaGlyphs Maven / Gradle / Ivy
/* * =========================================== * Java Pdf Extraction Decoding Access Library * =========================================== * * Project Info: http://www.idrsolutions.com * Help section for developers at http://www.idrsolutions.com/support/ * * (C) Copyright 1997-2016 IDRsolutions and Contributors. * * This file is part of JPedal/JPDF2HTML5 * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * --------------- * PdfJavaGlyphs.java * --------------- */ package org.jpedal.fonts.glyph; import org.jpedal.fonts.FontMappings; import org.jpedal.fonts.objects.FontData; import org.jpedal.parser.DecoderOptions; import org.jpedal.render.DynamicVectorRenderer; import org.jpedal.utils.StringUtils; import java.awt.geom.Area; import java.awt.geom.AffineTransform; import java.awt.font.GlyphVector; import java.awt.font.FontRenderContext; import java.awt.*; import java.io.Serializable; import java.util.Collections; import java.util.HashMap; import java.util.Map; import org.jpedal.fonts.StandardFonts; import org.jpedal.fonts.tt.Table; public class PdfJavaGlyphs implements PdfGlyphs,Serializable{ protected boolean hasGIDtoCID; /**shapes we have already drawn to speed up plotting, or
if the shape * is not in the cache. */ public final PdfGlyph getEmbeddedCachedShape(final int idx) { // using local variable instead of sync'ing final PdfGlyph[] cache = cachedEmbeddedShapes; if(cache==null) { return null; } else if(idxnull
if there are none*/ private Area[] cachedShapes; private AffineTransform[] cachedAt; /**lookup to translate CMAP chars*/ public int[] CMAP_Translate; protected int glyphCount; public boolean isFontInstalled; /**default font to use in display*/ public String defaultFont = "Lucida Sans"; /**lookup for font names less any + suffix*/ public String fontName="default"; //some fonts need to be remapped (ie Arial-BoldMT to Arial,Bold) public String logicalfontName="default"; Map chars=new HashMap(); Map displayValues=new HashMap(); Map embeddedChars=new HashMap(); /**flag is CID font is identity matrix*/ private boolean isIdentity; private boolean isFontEmbedded; private boolean hasWidths=true; public void flush(){ cachedShapes = null; cachedAt = null; } @Override public String getBaseFontName() { return baseFontName; } public void setBaseFontName(final String baseFontName) { this.baseFontName=baseFontName; } public String baseFontName=""; public boolean isSubsetted; /**copy of Trm so we can choose if cache should be flushed*/ public float[][] lastTrm=new float[3][3]; /**current font to plot, ornull
if not used yet*/ private Font unscaledFont; public boolean isArialInstalledLocally; private int maxCharCount=255; public boolean isCIDFont; public String font_family_name; public int style; int size; String weight,testFont; /**used to render page by drawing routines*/ public static final FontRenderContext frc =new FontRenderContext(null, true, true); /**list of installed fonts*/ private static String[] fontList; /** * used for standard non-substituted version * @param Trm * @param rawInt * @param displayValue * @param currentWidth */ @Override public Area getStandardGlyph(final float[][]Trm, final int rawInt, final String displayValue, final float currentWidth, final boolean isSTD) { //either calculate the glyph to draw or reuse if already drawn Area transformedGlyph2 = getCachedShape(rawInt); if (transformedGlyph2 == null) { double dY = -1,dX=1,y=0; AffineTransform at; //allow for text running up the page if ((Trm[1][0] < 0 && Trm[0][1] >= 0)||(Trm[0][1] < 0 && Trm[1][0] >= 0)) { dX=1f; dY=-1f; } if (isSTD) { transformedGlyph2=getGlyph(displayValue, currentWidth); //hack to fix problem with Java Arial font if(transformedGlyph2!=null && rawInt==146 && isArialInstalledLocally) { y = -(transformedGlyph2.getBounds().height - transformedGlyph2.getBounds().y); } }else { GlyphVector gv1 =null; //do not show CID fonts as Lucida unless match if(!isCIDFont|| isFontInstalled) { gv1 = getUnscaledFont().createGlyphVector(frc, displayValue); } if(gv1!=null){ transformedGlyph2 = new Area(gv1.getOutline()); //put glyph into display position double glyphX=gv1.getOutline().getBounds2D().getX(); //ensure inside box if(glyphX<0){ glyphX=-glyphX; at =AffineTransform.getTranslateInstance(glyphX*2,0); transformedGlyph2.transform(at); //x=-glyphX*2; } final double glyphWidth=gv1.getVisualBounds().getWidth()+(glyphX*2); final double scaleFactor=currentWidth/glyphWidth; if(scaleFactor<1) { dX *= scaleFactor; } } } //create shape for text using transformation to make correct size at =new AffineTransform(dX*Trm[0][0],dX*Trm[0][1],dY*Trm[1][0],dY*Trm[1][1] ,0,y); if(transformedGlyph2!=null){ transformedGlyph2.transform(at); } //save so we can reuse if it occurs again in this TJ command setCachedShape(rawInt, transformedGlyph2,at); } return transformedGlyph2; } /**returns a generic glyph using inbuilt fonts*/ public Area getGlyph(final String displayValue, final float currentWidth){ boolean fontMatched=true; /**use default if cannot be displayed*/ GlyphVector gv1=null; //remap font if needed String xx=displayValue; /**commented out 18/8/04 when font code updated*/ //if cannot display return to Lucida if(!getUnscaledFont().canDisplay(xx.charAt(0))){ xx=displayValue; fontMatched=false; } if(this.isCIDFont && isFontEmbedded && fontMatched){ gv1=null; }else if(fontMatched){ gv1 =getUnscaledFont().createGlyphVector(frc, xx); }else{ Font tempFont = new Font(defaultFont, 0, 1); if(!tempFont.canDisplay(xx.charAt(0))) { tempFont = new Font("lucida", 0, 1); } if(tempFont.canDisplay(xx.charAt(0))) { gv1 = tempFont.createGlyphVector(frc, xx); } } //gv1 =getUnscaledFont().createGlyphVector(frc, xx); Area transformedGlyph2 = null; if(gv1!=null){ transformedGlyph2=new Area(gv1.getOutline()); //put glyph into display position double glyphX=gv1.getOutline().getBounds2D().getX(); //double glyphY=gv1.getOutline().getBounds2D().getY(); final double width=gv1.getOutline().getBounds2D().getWidth(); AffineTransform at; if(!hasWidths){ //center for looks //try standard values which are indexed under NAME of char //String charName = StandardFonts.getUnicodeChar(StandardFonts.WIN, rawInt); final float leading=(float)(currentWidth-(width+glyphX+glyphX))/2; if(leading>0){ at =AffineTransform.getTranslateInstance(leading,0); transformedGlyph2.transform(at); } }else{ if(glyphX<0){ //ensure inside box glyphX=-glyphX; at =AffineTransform.getTranslateInstance(glyphX,0); transformedGlyph2.transform(at); } final double scaleFactor=currentWidth/(transformedGlyph2.getBounds2D().getWidth()); if(scaleFactor<1) { at =AffineTransform.getScaleInstance(scaleFactor,1); transformedGlyph2.transform(at); } } } return transformedGlyph2; } /** * Caches the specified shape. */ public final void setCachedShape(final int idx, final Area shape, final AffineTransform at) { // using local variable instead of sync'ing Area[] cache = cachedShapes; AffineTransform[] atCache=cachedAt; if (cache == null){ cachedShapes = cache = new Area[maxCharCount]; cachedAt = atCache = new AffineTransform[maxCharCount]; } if(shape==null) { cache[idx] = null; } else { cache[idx] = shape; } if(shape!=null && at!=null) { atCache[idx] = at; } } /** * Returns the specified shape from the cache, ornull
if the shape * is not in the cache. */ public final AffineTransform getCachedTransform(final int idx) { // using local variable instead of sync'ing final AffineTransform[] cache = cachedAt; if(cache==null) { return null; } else { return cache[idx]; } } /** * Returns the specified shape from the cache, ornull
if the shape * is not in the cache. */ public final Area getCachedShape(final int idx) { // using local variable instead of sync'ing final Area[] cache = cachedShapes; if(cache==null) { return null; } else{ final Area currentShape=cache[idx]; if(currentShape==null) { return null; } else { return currentShape; } } //return cache == null ? null : (Area)cache[idx].clone(); //return cache == null ? null : cache[idx]; } public void init(final int maxCharCount, final boolean isCIDFont) { this.maxCharCount=maxCharCount; this.isCIDFont=isCIDFont; } /**set the font being used or try to approximate*/ public final void setFont(String name, final int size) { this.size=size; //allow user to totally over-ride //passing in this allows user to reset any global variables //set in this method as well. //Helper is a static instance of the inteface JPedalHelper if(DecoderOptions.Helper!=null){ final Font f=DecoderOptions.Helper.setFont(this, StringUtils.convertHexChars(name),size); //if you want to implement JPedalHelper but not //use this function, just return null if(f!=null) { this.style = f.getStyle(); this.font_family_name = f.getFamily(); this.unscaledFont = f; return; } } name=StandardFonts.expandName(name); //set defaults this.font_family_name=name; this.style =Font.PLAIN; String mappedName=null; if(font_family_name==null) { font_family_name = this.fontName; } testFont=font_family_name; if(font_family_name!=null) { testFont = font_family_name.toLowerCase(); } //pick up any weight in type 3 font or - standard font mapped to Java int pointer = font_family_name.indexOf(','); if ((pointer == -1))//&&(StandardFonts.javaFontList.get(font_family_name)!=null)) { pointer = font_family_name.indexOf('-'); } if (pointer != -1) { //see if present with , mappedName=(String) FontMappings.fontSubstitutionAliasTable.get(testFont); weight =testFont.substring(pointer + 1, testFont.length()); style = getWeight(weight); font_family_name = font_family_name.substring(0, pointer).toLowerCase(); testFont=font_family_name; if(testFont.endsWith("mt")) { testFont = testFont.substring(0, testFont.length() - 2); } } //remap if not type 3 match if(mappedName==null) { mappedName = (String) FontMappings.fontSubstitutionAliasTable.get(testFont); } if((mappedName!=null)&&(mappedName.equals("arialbd"))) { mappedName = "arial-bold"; } if(mappedName!=null){ font_family_name=mappedName; pointer = font_family_name.indexOf('-'); if(pointer!=-1){ font_family_name=font_family_name.toLowerCase(); weight =font_family_name.substring(pointer + 1, font_family_name.length()); style = getWeight(weight); font_family_name = font_family_name.substring(0, pointer); } testFont=font_family_name.toLowerCase(); if(testFont.endsWith("mt")) { testFont = testFont.substring(0, testFont.length() - 2); } } } /** * work out style (ITALIC, BOLD) */ private static int getWeight(String weight) { int style=Font.PLAIN; if(weight.endsWith("mt")) { weight = weight.substring(0, weight.length() - 2); } if (weight.contains("heavy")) { style = Font.BOLD; } else if (weight.contains("bold")) { style = Font.BOLD; } else if (weight.contains("roman")) { style = Font.ROMAN_BASELINE; } if (weight.contains("italic")) { style += Font.ITALIC; } else if (weight.contains("oblique")) { style += Font.ITALIC; } return style; } /** * Returns the unscaled font, initializing it first if it hasn't been used before. */ public final Font getUnscaledFont() { if (unscaledFont == null && font_family_name!=null) { //Recheck if (fontList == null) { //Make sure lowercase fontList = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames(); for (int i = 0; i < fontList.length; i++) { fontList[i] = fontList[i].toLowerCase(); } } //see if installed if (fontList != null) { //check exact first boolean isFound = false; int count = fontList.length; for (int i = 0; i < count; i++) { if ((fontList[i].equals(testFont)) || ((weight == null) && (testFont.startsWith(fontList[i])))) { isFontInstalled = true; font_family_name = fontList[i]; i = count; isFound = true; } } if (!isFound) { count = fontList.length; for (int i = 0; i < count; i++) { if ((fontList[i].equals(testFont)) || ((weight == null) && (testFont.startsWith(fontList[i])))) { isFontInstalled = true; font_family_name = fontList[i]; i = count; } } } //hack for windows as some odd things going on if (isFontInstalled && font_family_name.equals("arial")) { isArialInstalledLocally = true; } } /**approximate display if not installed*/ if (!isFontInstalled) { //try to approximate font if (weight == null) { //pick up any weight final String test = font_family_name.toLowerCase(); style = getWeight(test); } font_family_name = defaultFont; } unscaledFont = new Font(font_family_name, style, size); } /**commenting out this broke originaldoc.pdf*/ if (unscaledFont == null) { unscaledFont = new Font(defaultFont, Font.PLAIN, 1); } return unscaledFont; } protected PdfGlyph[] cachedEmbeddedShapes; protected int localBias,globalBias; /** * Caches the specified shape. */ public final void setEmbeddedCachedShape(final int idx, final PdfGlyph shape) { // using local variable instead of sync'ing PdfGlyph[] cache = cachedEmbeddedShapes; if (cache == null) { cachedEmbeddedShapes = cache = new PdfGlyph[maxCharCount]; } if(idxnull
© 2015 - 2025 Weber Informatics LLC | Privacy Policy