Change 89652 Don't use the same File Reader object thinger from multiple threads. Instead create a copy, so that each thread has its own copy. This way we don't close files from one thread while trying to read the same file from another thread. UPDATED JAVA CLASS: com/lowagie/text/pdf/TrueTypeFontUnicode.java < TrueTypeFontSubSet sb = new TrueTypeFontSubSet(fileName, rf, longTag, directoryOffset, false); --- > TrueTypeFontSubSet sb = new TrueTypeFontSubSet(fileName, new RandomAccessFileOrArray(rf), longTag, directoryOffset, false); change 87379 adding JDK 1.4.x 's Bidi checking to see if incoming string requires Bidi operation, and if it needs bidi operation then creating PDF only Bidiline object to reverse the arabic text. UPDATED JAVA CLASS: com/lowagie/text/pdf/PdfGraphics2D.java boolean bBidi = false; + 420 try { + 421 // ask jdk for Bidi class, only available jdk 1.4.x above + 422 // check to see if our text requires bidi operation. + 423 Class bidiClass = Class.forName("java.text.Bidi"); + 424 Class clParams[] = new Class[3]; + 425 clParams[0] = char[].class; + 426 clParams[1] = int.class; + 427 clParams[2] = int.class; + 428 Method requiresBidi = bidiClass.getMethod("requiresBidi", clParams); + 429 + 430 Object params[] = new Object[3]; + 431 params[0] = s.toCharArray(); + 432 params[1] = new Integer(0); + 433 params[2] = new Integer(s.length()); + 434 Object retObj = requiresBidi.invoke(null, params); + 435 + 436 if(retObj != null && retObj instanceof Boolean) { + 437 if(((Boolean)retObj).booleanValue()) { + 438 forgroundcb.beginText(); + 439 forgroundcb.setFontAndSize(baseFont, fontSize); 440 - forgroundcb.beginText(); - forgroundcb.setFontAndSize(baseFont, fontSize); + 441 BidiLine bidiLine = new BidiLine(); + 442 Chunk ck = new Chunk(s, new com.lowagie.text.Font(baseFont, fontSize, font.getStyle(), null)); + 443 bidiLine.addChunk(new PdfChunk(ck, null)); + 444 + 445 PdfLine line = bidiLine.processLine(baseFont.getWidth(s), Element.ALIGN_RIGHT, PdfWriter.RUN_DIRECTION_RTL, PangoArabicShapping.ar_lig); + 446 forgroundcb.setTextMatrix((float)mx[0], (float)mx[1], (float)mx[2], (float)mx[3], (float)mx[4], (float)mx[5]); + 447 forgroundcb.showTextKerned(line.getChunk(0).toString()); + 448 forgroundcb.endText(); + 449 bBidi = true; + 450 } + 451 } + 452 + 453 + 454 }catch (Exception e){ + 455 bBidi = false; + 456 } + 457 + 458 if(!bBidi) { + 459 forgroundcb.beginText(); + 460 forgroundcb.setFontAndSize(baseFont, fontSize); + 461 forgroundcb.setTextMatrix((float)mx[0], (float)mx[1], (float)mx[2], (float)mx[3], (float)mx[4], (float)mx[5]); + 462 + 463 forgroundcb.showText(s); + 464 forgroundcb.endText(); + 465 } 466 - forgroundcb.setTextMatrix((float)mx[0], (float)mx[1], (float)mx[2], (float)mx[3], (float)mx[4], (float)mx[5]); - forgroundcb.showText(s); - forgroundcb.endText(); 467 setTransform(at); changlist 87606 Itext uses text strings in the font face to identify the font style. It looks for string like "italic", "bold", "Normal", "Oblique" to flag the font style. This technique works fine for most fonts out there, but lino font files use abbrevated "it" to stand for italic fonts. UPDATED JAVA CLASS: com/lowagie/text/FontFactory.java 729 fs = Font.NORMAL; 730 if (lcf.toLowerCase().indexOf("bold") != -1) fs |= Font.BOLD; - if (lcf.toLowerCase().indexOf("italic") != -1 || lcf.toLowerCase().indexOf("oblique") != -1) fs |= Font.ITALIC; + 731 if (lcf.toLowerCase().indexOf("italic") != -1 || lcf.toLowerCase().indexOf("oblique") != -1 || lcf.toLowerCase().indexOf("it") != -1) + 732 fs |= Font.ITALIC; 733 if ((s & Font.BOLDITALIC) == fs) { 734 fontname = f; 735 found = true; change 58117 some text was wrongfully cut due to mis-calculation on the margin + string location to cut off text writting in the margin area. However, orginal equation did not properly assign bottom and top margin calculation. this will fix it. UPDATED JAVA CLASS: com/lowagie/text/pdf/PdfGraphics2D.java 393 inverse.getMatrix(mx); 394 - float orig_topline = (float)orig_mx[5] + topmargin; - float orig_bottomline = (float)orig_mx[5] + bottommargin; - float topline = (float)mx[5] + topmargin; - float bottomline = (float)mx[5] + bottommargin; + 395 // check to see if the string location is mistakenly inside of margin area + 396 float string_location_plus_bottom_margin = (float)orig_mx[5] + bottommargin; + 397 float string_location_plus_top_margin = (float)mx[5] + topmargin; 398 - if(!bHeaderfooter && (orig_topline > height || orig_bottomline > height - || topline > height || bottomline > height)) + 399 if(!bHeaderfooter && (string_location_plus_bottom_margin > height || string_location_plus_top_margin > height)) 400 { + 401 // set back the original transformation so + 402 // we did not change this due to invalid string location 403 setTransform(at); 404 return; 405 } change 86546 fix checksum duplication code UPDATED JAVA CLASS: com/lowagie/text/Image.java, com/lowagie/text/ImgWMF.java, com/lowagie/text/Jpeg.java Edit //depot/ColdFusion/cf_main/tools/itext/src/com/lowagie/text/Image.java#4 1489 Checksum checksumEngine = new Adler32(); 1490 checksumEngine.update(bytes, 0, bytes.length); 1491 long checksum = checksumEngine.getValue(); - - // Compute CRC-32 checksum - checksumEngine = new CRC32(); - checksumEngine.update(bytes, 0, bytes.length); - checksum = checksumEngine.getValue(); - + 1492 1493 // The checksum engine can be reused again for a different byte array by calling reset() 1494 checksumEngine.reset(); 1495 Edit //depot/ColdFusion/cf_main/tools/itext/src/com/lowagie/text/ImgWMF.java#3 113 rawData = img; 114 originalData = img; 115 processParameters(); + 116 mySerialId = new Long(getByteArrayCheckSum(img)); 117 } 118 119 /** Edit //depot/ColdFusion/cf_main/tools/itext/src/com/lowagie/text/Jpeg.java#3 155 rawData = img; 156 originalData = img; 157 processParameters(); + 158 mySerialId = new Long(getByteArrayCheckSum(img)); 159 } 160 161 /** 170 this(img); 171 scaledWidth = width; 172 scaledHeight = height; + 173 mySerialId = new Long(getByteArrayCheckSum(img)); 174 } 175 176 // private static methods change 86509 Use checksum for image tracking, if it is the same image then it is no longer added to the document. this is drastic enhancement for ememory usage and speed of the PDF formation. Also added wait image timeout, so we do not do blocking on waitonimage. UPDATED JAVA CLASS: com/lowagie/text/Image.java, com/lowagie/text/ImgCCITT.java, com/lowagie/text/ImgRaw.java, com/lowagie/text/pdf/PdfGraphics2D.java Edit //depot/ColdFusion/cf_main/tools/itext/src/com/lowagie/text/Image.java#3 57 import java.net.MalformedURLException; 58 import java.util.Properties; 59 import java.util.Set; + 60 import java.util.zip.Checksum; + 61 import java.util.zip.Adler32; + 62 import java.util.zip.CRC32; 63 import java.awt.color.ICC_Profile; 64 import com.lowagie.text.pdf.PdfTemplate; 65 import com.lowagie.text.pdf.codec.CCITTG4Encoder; 1477 public void setUrl(URL url) { 1478 this.url = url; 1479 } + 1480 + 1481 /** + 1482 * getting ByteArray CheckSum base on Adler-32 + 1483 * @param bytes + 1484 * @return + 1485 */ + 1486 public static long getByteArrayCheckSum(byte[] bytes) + 1487 { + 1488 // Compute Adler-32 checksum + 1489 Checksum checksumEngine = new Adler32(); + 1490 checksumEngine.update(bytes, 0, bytes.length); + 1491 long checksum = checksumEngine.getValue(); + 1492 + 1493 // Compute CRC-32 checksum + 1494 checksumEngine = new CRC32(); + 1495 checksumEngine.update(bytes, 0, bytes.length); + 1496 checksum = checksumEngine.getValue(); + 1497 + 1498 // The checksum engine can be reused again for a different byte array by calling reset() + 1499 checksumEngine.reset(); + 1500 + 1501 return checksum; + 1502 + 1503 } + 1504 1505 } Edit //depot/ColdFusion/cf_main/tools/itext/src/com/lowagie/text/ImgCCITT.java#3 142 rawData = data; 143 plainWidth = width(); 144 plainHeight = height(); + 145 mySerialId = new Long(getByteArrayCheckSum(data)); 146 } 147 } Edit //depot/ColdFusion/cf_main/tools/itext/src/com/lowagie/text/ImgRaw.java#3 93 rawData = data; 94 plainWidth = width(); 95 plainHeight = height(); + 96 mySerialId = new Long(getByteArrayCheckSum(data)); 97 } 98 } Edit //depot/ColdFusion/cf_main/tools/itext/src/com/lowagie/text/pdf/PdfGraphics2D.java#9 1624 double[] mx = new double[6]; 1625 inverse.getMatrix(mx); 1626 - try { + 1627 try { 1628 com.lowagie.text.Image image = com.lowagie.text.Image.getInstance(img, bgColor); 1629 if (mask!=null) { 1630 com.lowagie.text.Image msk = com.lowagie.text.Image.getInstance(mask, null, true); 1796 mediaTracker = new MediaTracker(new PdfGraphics2D.fakeComponent()); 1797 mediaTracker.addImage(image, 0); 1798 try { - mediaTracker.waitForID(0); + 1799 mediaTracker.waitForID(0, 60000); //add 60 s wait timeout 1800 } 1801 catch (InterruptedException e) { 1802 // empty on purpose change 86449 adding margin into pdf graphics2d to avoid printing text outside of the page margin. Also added headerfooter region checking. we allow header/footer print within the maring area. UPDATED JAVA CLASS: com/lowagie/text/pdf/PdfContentByte.java, com/lowagie/text/pdf/PdfGraphics2D.java Edit //depot/ColdFusion/cf_main/tools/itext/src/com/lowagie/text/pdf/PdfContentByte.java#3 2302 * @return a Graphics2D 2303 */ 2304 public java.awt.Graphics2D createGraphics(float width, float height) { - return createGraphics(width, height, null); + 2305 return createGraphics(width, height, 0, 0, null); 2306 } 2307 2308 /** Gets a Graphics2D to write on. The graphics 2312 * @param fontMapper the mapping from awt fonts to BaseFont 2313 * @return a Graphics2D 2314 */ - public java.awt.Graphics2D createGraphics(float width, float height, FontMapper fontMapper) { - return new PdfGraphics2D(this, width, height, fontMapper); + 2315 public java.awt.Graphics2D createGraphics(float width, float height, float topmargin, float bottommargin, FontMapper fontMapper) { + 2316 return new PdfGraphics2D(this, width, height, topmargin, bottommargin, fontMapper); 2317 } 2318 2319 PageResources getPageResources() { Edit //depot/ColdFusion/cf_main/tools/itext/src/com/lowagie/text/pdf/PdfGraphics2D.java#8 177 private Shape _missingImageOutline = null; 178 private PdfGraphics2D parent = null; 179 + 180 private float topmargin = 0; + 181 private float bottommargin = 0; + 182 private boolean bHeaderfooter = false; + 183 184 private PdfGraphics2D() { 185 } 186 188 * Constructor for PDFGraphics2D. 189 * 190 */ - PdfGraphics2D(PdfContentByte cb, float width, float height, FontMapper fontMapper) { + 191 PdfGraphics2D(PdfContentByte cb, float width, float height, float topmargin, float bottommargin, FontMapper fontMapper) { 192 super(); 193 if(debugmode) debug("PdfGraphics2D(PdfContentByte cb, float width, float height, FontMapper fontMapper) " + "width " + width + " height " + height + " FontMapper " + fontMapper); 194 this.transform = new AffineTransform(); 204 cb.saveState(); 205 this.width = width; 206 this.height = height; + 207 this.topmargin = topmargin; + 208 this.bottommargin = bottommargin; 209 clip = new Area(new Rectangle2D.Float(0, 0, width, height)); 210 clip(clip); 211 originalStroke = stroke = oldStroke = strokeOne; 382 at2.translate(x, y); 383 at2.concatenate(font.getTransform()); 384 setTransform(at2); + 385 double[] orig_mx = new double[6]; + 386 at2.getMatrix(orig_mx); + 387 388 AffineTransform inverse = this.normalizeMatrix(); 389 AffineTransform flipper = AffineTransform.getScaleInstance(1,-1); 390 inverse.concatenate(flipper); 391 double[] mx = new double[6]; 392 inverse.getMatrix(mx); 393 + 394 float orig_topline = (float)orig_mx[5] + topmargin; + 395 float orig_bottomline = (float)orig_mx[5] + bottommargin; + 396 float topline = (float)mx[5] + topmargin; + 397 float bottomline = (float)mx[5] + bottommargin; + 398 + 399 if(!bHeaderfooter && (orig_topline > height || orig_bottomline > height + 400 || topline > height || bottomline > height)) + 401 { + 402 setTransform(at); + 403 return; + 404 } + 405 406 if(debugmode) 407 { 408 String fullfontnames = extractStringfromStringArray(baseFont.getFullFontName()); 1049 g2.cb.saveState(); 1050 g2.width = this.width; 1051 g2.height = this.height; + 1052 g2.topmargin = this.topmargin; + 1053 g2.bottommargin = this.bottommargin; + 1054 g2.bHeaderfooter = this.bHeaderfooter; 1055 g2.followPath(new Area(new Rectangle2D.Float(0, 0, width, height)), CLIP); 1056 if (this.clip != null) 1057 g2.clip = new Area(this.clip); 1495 } 1496 } 1497 + 1498 public void setHeaderFooter(boolean b){ + 1499 bHeaderfooter = b; + 1500 } + 1501 + 1502 public boolean isHeaderFooter() { + 1503 return bHeaderfooter; + 1504 } + 1505 1506 /////////////////////////////////////////////// 1507 // 1508 // Change 86337 by sgong Add '/usr/X11R6/lib/X11/fonts/TrueType' to the list of directories that Blackstone scans for fonts. UDATED JAVA CLASS: com/lowagie/text/FontFactory.java 659 count += registerDirectory("/usr/share/fonts/default/TrueType"); 660 count += registerDirectory("/usr/X11R6/lib/X11/fonts/ttf"); 661 count += registerDirectory("/usr/X11R6/lib/X11/fonts/truetype"); + 662 count += registerDirectory("/usr/X11R6/lib/X11/fonts/TrueType"); 663 count += registerDirectory("/usr/X11R6/lib/X11/fonts/TTF"); 664 return count; 665 } Change 86023 To solve the problem of background image overlapping text, we will call create PdfGraphics2D's default PdfContentByte to use the pdfwriter.getContentByteUnder to draw images on the bottom of the Graphics2D canvas. In order for this to work, changed PdfGraphics2D's drawString method need to use the forground PdfContentByte using pdfwriter.getContentByte. we still see some table background color not displayed, but this is a big improvement from what we had before. UDATED JAVA CLASS: com/lowagie/text/pdf/PdfGraphics2D.java Edit //depot/ColdFusion/cf_main/tools/itext/src/com/lowagie/text/pdf/PdfGraphics2D.java#7 362 */ 363 public void drawString(String s, float x, float y) { 364 - setFillPaint(); + 365 PdfContentByte forgroundcb = cb.getPdfWriter().getDirectContent(); + 366 + 367 setFillPaint(forgroundcb); + 368 369 if (onlyShapes) { 370 TextLayout tl = new TextLayout(s, this.font, new FontRenderContext(new AffineTransform(), false, true)); 371 tl.draw(this, x, y); 392 baseFont.getWidth(s) + " FontType " + baseFont.getFontType() + " Encoding " + baseFont.getEncoding() 393 + " embeded " + baseFont.isEmbedded()+ "] " + " inverse-flipped-transform " + inverse); 394 } - cb.beginText(); - cb.setFontAndSize(baseFont, fontSize); + 395 + 396 + 397 forgroundcb.beginText(); + 398 forgroundcb.setFontAndSize(baseFont, fontSize); 399 - cb.setTextMatrix((float)mx[0], (float)mx[1], (float)mx[2], (float)mx[3], (float)mx[4], (float)mx[5]); - cb.showText(s); - cb.endText(); + 400 forgroundcb.setTextMatrix((float)mx[0], (float)mx[1], (float)mx[2], (float)mx[3], (float)mx[4], (float)mx[5]); + 401 forgroundcb.showText(s); + 402 forgroundcb.endText(); 403 setTransform(at); 404 405 if(underline) 751 752 private void setStrokeDiff(Stroke newStroke, Stroke oldStroke) { 753 if(debugmode) debug("setStrokeDiff(Stroke newStroke, Stroke oldStroke): " + "newStroke " + newStroke + " oldStrok " + oldStroke); + 754 755 if (newStroke == oldStroke) 756 return; 757 if (!(newStroke instanceof BasicStroke)) 1625 } 1626 } 1627 + 1628 private void setFillPaint(PdfContentByte cb) { + 1629 if (checkNewPaint(paintFill)) { + 1630 paintFill = paint; + 1631 setPaint(false, 0, 0, true, cb); + 1632 } + 1633 } + 1634 1635 private void setStrokePaint() { 1636 if (checkNewPaint(paintStroke)) { 1637 paintStroke = paint; 1640 } 1641 1642 private void setPaint(boolean invert, double xoffset, double yoffset, boolean fill) { + 1643 setPaint(invert, xoffset, yoffset, fill, cb); + 1644 } + 1645 + 1646 private void setPaint(boolean invert, double xoffset, double yoffset, boolean fill, PdfContentByte contentByte) { + 1647 1648 if (paint instanceof Color) { 1649 Color color = (Color)paint; 1650 int alpha = color.getAlpha(); 1657 gs.setFillOpacity((float)alpha / 255f); 1658 fillGState[alpha] = gs; 1659 } - cb.setGState(gs); + 1660 contentByte.setGState(gs); 1661 } - cb.setColorFill(color); + 1662 contentByte.setColorFill(color); 1663 } 1664 else { 1665 if (alpha != currentStrokeGState) { 1670 gs.setStrokeOpacity((float)alpha / 255f); 1671 strokeGState[alpha] = gs; 1672 } - cb.setGState(gs); + 1673 contentByte.setGState(gs); 1674 } - cb.setColorStroke(color); + 1675 contentByte.setColorStroke(color); 1676 } 1677 } 1678 else if (paint instanceof GradientPaint) { 1683 transform.transform(p2, p2); 1684 Color c1 = gp.getColor1(); 1685 Color c2 = gp.getColor2(); - PdfShading shading = PdfShading.simpleAxial(cb.getPdfWriter(), (float)p1.getX(), normalizeY((float)p1.getY()), (float)p2.getX(), normalizeY((float)p2.getY()), c1, c2); + 1686 PdfShading shading = PdfShading.simpleAxial(contentByte.getPdfWriter(), (float)p1.getX(), normalizeY((float)p1.getY()), (float)p2.getX(), normalizeY((float)p2.getY()), c1, c2); 1687 PdfShadingPattern pat = new PdfShadingPattern(shading); 1688 if (fill) - cb.setShadingFill(pat); + 1689 contentByte.setShadingFill(pat); 1690 else - cb.setShadingStroke(pat); + 1691 contentByte.setShadingStroke(pat); 1692 } 1693 else if (paint instanceof TexturePaint) { 1694 try { 1696 BufferedImage img = tp.getImage(); 1697 Rectangle2D rect = tp.getAnchorRect(); 1698 com.lowagie.text.Image image = com.lowagie.text.Image.getInstance(img, null); - PdfPatternPainter pattern = cb.createPattern(image.width(), image.height()); + 1699 PdfPatternPainter pattern = contentByte.createPattern(image.width(), image.height()); 1700 AffineTransform inverse = this.normalizeMatrix(); 1701 inverse.scale(rect.getWidth() / image.width(), -rect.getHeight() / image.height()); 1702 double[] mx = new double[6]; 1705 image.setAbsolutePosition(0,0); 1706 pattern.addImage(image); 1707 if (fill) - cb.setPatternFill(pattern); + 1708 contentByte.setPatternFill(pattern); 1709 else - cb.setPatternStroke(pattern); + 1710 contentByte.setPatternStroke(pattern); 1711 } catch (Exception ex) { 1712 if (fill) - cb.setColorFill(Color.gray); + 1713 contentByte.setColorFill(Color.gray); 1714 else - cb.setColorStroke(Color.gray); + 1715 contentByte.setColorStroke(Color.gray); 1716 } 1717 } 1718 else { 1737 g.drawImage(img,tx,null); 1738 } 1739 com.lowagie.text.Image image = com.lowagie.text.Image.getInstance(img, null); - PdfPatternPainter pattern = cb.createPattern(width, height); + 1740 PdfPatternPainter pattern = contentByte.createPattern(width, height); 1741 image.setAbsolutePosition(0,0); 1742 pattern.addImage(image); 1743 if (fill) - cb.setPatternFill(pattern); + 1744 contentByte.setPatternFill(pattern); 1745 else - cb.setPatternStroke(pattern); + 1746 contentByte.setPatternStroke(pattern); 1747 } catch (Exception ex) { 1748 if (fill) - cb.setColorFill(Color.gray); + 1749 contentByte.setColorFill(Color.gray); 1750 else - cb.setColorStroke(Color.gray); + 1751 contentByte.setColorStroke(Color.gray); 1752 } 1753 } 1754 } Change 85605 Remove the isFontNameLegal() method from documentServiceImpl, and use the version in fontFactory. UPDATED JAVA CLASS: com/lowagie/text/FontFactory.java Edit //depot/ColdFusion/cf_main/tools/itext/src/com/lowagie/text/FontFactory.java#9 484 register(path, null); 485 } 486 - - private static boolean isFontNameLegal(String str) { + 487 public static boolean isFontNameLegal(String str) { 488 if (str==null) { 489 return false; 490 } 492 boolean rc=true; 493 for (int i=0; i < str.length(); i++) { 494 char ch = str.charAt(i); - if (Character.isLetterOrDigit(ch) || Character.isSpace(ch)) { + 495 if (Character.isLetterOrDigit(ch) || Character.isSpace(ch) || + 496 Character.getType(ch)==Character.CURRENCY_SYMBOL || Character.getType(ch)==Character.DASH_PUNCTUATION) { 497 } else { 498 rc=false; 499 break; 502 return rc; 503 } 504 - 505 /** 506 * Register a font file and use an alias for the font contained in it. 507 * Change 85603 by song We always have some foreign fonts that contains unicode characters that fails in the wddx serialization/deserialization. To fix this problem, we now define valid font name/font family name as a string combination of of numbers, letters, currency symbol, dashes, and space characters. If the font name contains other characters, we will refuse to register the file. UPDATED JAVA CLASS: com/lowagie/text/FontFactory.java Edit //depot/ColdFusion/cf_main/tools/itext/src/com/lowagie/text/FontFactory.java#8 484 register(path, null); 485 } 486 + 487 + 488 private static boolean isFontNameLegal(String str) { + 489 if (str==null) { + 490 return false; + 491 } + 492 + 493 boolean rc=true; + 494 for (int i=0; i < str.length(); i++) { + 495 char ch = str.charAt(i); + 496 if (Character.isLetterOrDigit(ch) || Character.isSpace(ch)) { + 497 } else { + 498 rc=false; + 499 break; + 500 } + 501 } + 502 return rc; + 503 } + 504 + 505 506 /** 507 * Register a font file and use an alias for the font contained in it. 508 * 521 String fullName = null; 522 String familyName = null; 523 String[][] names = (String[][])allNames[2]; + 524 + 525 /** + 526 * We look for font name in the default code page + 527 * + 528 */ 529 for (int i = 0; i < names.length; i++) { 530 if ("0".equals(names[i][2])) { 531 fullName = names[i][3]; 532 break; 533 } 534 } + 535 /** + 536 * No leagl font name found in the default code page + 537 * we look for it in the english code page. + 538 */ + 539 if ((!isFontNameLegal(fullName))) + 540 for (int i = 0; i < names.length; i++) { + 541 if ("1033".equals(names[i][2])) { + 542 fullName = names[i][3]; + 543 break; + 544 } + 545 } + 546 547 // register all the font names with all the locales 548 for (int i = 0; i < names.length; i++) { 549 trueTypeFonts.setProperty(names[i][3], path); 550 } - if (fullName != null) { + 551 if (isFontNameLegal(fullName)) { + 552 553 // Currently only adobe is the only commercial open type font vendor. 554 // The adobe otf files sometimes use the same font Family name for multiple font files. 555 // That means the fonts won't show up correctly in the font administrator page. 566 for (int i = 0; i < names.length; i++) { 567 if ("0".equals(names[i][2])) { 568 familyName = names[i][3]; - HashSet tmp = (HashSet) fontFamilies.get(familyName); - if (tmp == null) { - tmp = new HashSet(); - } - tmp.add(fullName); - fontFamilies.put(familyName, tmp); 569 break; 570 } 571 } - } + 572 + 573 if (!isFontNameLegal(familyName)) { + 574 for (int i = 0; i < names.length; i++) { + 575 if ("1033".equals(names[i][2])) { + 576 familyName = names[i][3]; + 577 break; + 578 } + 579 } + 580 } + 581 if (!isFontNameLegal(familyName)) { + 582 throw new DocumentException("Font file " + path + " does not have a legal font name"); + 583 } + 584 HashSet tmp = (HashSet) fontFamilies.get(familyName); + 585 if (tmp == null) { + 586 tmp = new HashSet(); + 587 } + 588 tmp.add(fullName); + 589 fontFamilies.put(familyName, tmp); + 590 } 591 } 592 else if (path.toLowerCase().endsWith(".ttc")) { 593 if (alias != null) Change 85317 added altText handling for missing images, created freeText PdfAnnotation and square float pointer for missing object. This does not effect regular images because PDF does not have a way to add altText without effect image look and feel, also does not have 508 screen reader capability without drawing Text on top of the image. UPDATED JAVA CLASS: com.lowagie.test.pdf.PdfGraphics2D.java Edit //depot/ColdFusion/cf_main/tools/itext/src/com/lowagie/text/pdf/PdfGraphics2D.java#6 100 import java.util.Set; 101 import java.util.Iterator; 102 import java.awt.font.TextAttribute; + 103 import java.io.IOException; 104 + 105 import com.lowagie.text.BadElementException; + 106 import com.lowagie.text.Annotation; 107 + 108 109 public class PdfGraphics2D extends Graphics2D implements G2DLink{ 110 111 private static final int FILL = 1; 172 private static boolean itextdebuglink = (System.getProperty("itextdebuglink") != null 173 && ((String) System.getProperty("itextdebuglink")).equalsIgnoreCase("true")); 174 + 175 // this is use for setting altText - 508 complain. + 176 private Shape _imageOutline = null; + 177 private Shape _missingImageOutline = null; + 178 private PdfGraphics2D parent = null; + 179 180 private PdfGraphics2D() { 181 } 182 445 446 if(itextdebuglink) debug("addAltText(java.awt.Image image, String altText )" + 447 " image " + image + " altText " + altText ); - /* try - { - PdfWriter writer = cb.getPdfWriter(); - PdfDocument doc = writer.getPdfDocument(); - com.lowagie.text.Image img = com.lowagie.text.Image.getInstance(image, image.getGraphics().getColor()); - img.setAnnotation(new Annotation(altText,altText, 0, 0, 0, 0)); + 448 + 449 + 450 if(_imageOutline!= null) { + 451 //showAltText(_imageOutline, altText, "SQUARE"); + 452 _imageOutline = null; + 453 } + 454 else { + 455 if(_missingImageOutline != null) + 456 { + 457 try{ + 458 com.lowagie.text.Image.getInstance(image, null); + 459 }catch(IOException e){ + 460 + 461 showAltText(_missingImageOutline, altText, "FREETEXT"); + 462 showAltText(_missingImageOutline, altText, "SQUARE"); + 463 _missingImageOutline = null; 464 - doc.add(img); + 465 }catch(Exception e){ + 466 // do nothing + 467 } + 468 } 469 } - catch (Exception e) - { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. - }*/ + 470 471 472 } 473 482 public void addAltText(java.awt.Shape s, String altText) { 483 if(itextdebuglink) debug("addAltText(java.awt.Shape s, String altText))" + 484 " Shape " + s + " altText " + altText ); - /* try - { - Rectangle2D r = s.getBounds2D(); - double w = r.getWidth(); - double h = r.getHeight(); - double x = r.getX(); - double y = r.getY(); - Annotation ann = new Annotation(altText,altText, (float)x, (float)y, (float)(x+w), (float)(y+h)); - PdfWriter writer = cb.getPdfWriter(); - PdfDocument doc = writer.getPdfDocument(); - doc.add(ann); + 485 + 486 if(s != null) { + 487 //showAltText(s, altText, "SQUARE"); + 488 } + 489 + 490 } + 491 + 492 private void showAltText(Shape s, String altText, String type) + 493 { + 494 Rectangle2D rect = s.getBounds2D(); + 495 + 496 double rec_width = rect.getWidth(); + 497 double rec_height = rect.getHeight(); + 498 double x = rect.getX(); + 499 double y = rect.getY(); + 500 + 501 AffineTransform at = getTransform(); + 502 AffineTransform at2 = getTransform(); + 503 at2.translate(x, y); + 504 at2.concatenate(font.getTransform()); + 505 setTransform(at2); + 506 AffineTransform inverse = this.normalizeMatrix(); + 507 AffineTransform flipper = AffineTransform.getScaleInstance(1,-1); + 508 inverse.concatenate(flipper); + 509 double[] mx = new double[6]; + 510 inverse.getMatrix(mx); + 511 + 512 PdfWriter writer = cb.getPdfWriter(); + 513 + 514 com.lowagie.text.Rectangle r = new com.lowagie.text.Rectangle((float)mx[4], + 515 (float)mx[5] - (float)rec_height, + 516 (float)mx[4] + (float)rec_width, + 517 (float)mx[5]); + 518 + 519 if(type.equals("FREETEXT")) { + 520 PdfAnnotation annot = new PdfAnnotation(writer, r); + 521 annot.put(PdfName.SUBTYPE, PdfName.FREETEXT); + 522 annot.put(PdfName.CONTENTS, new PdfString(altText, PdfObject.TEXT_UNICODE)); + 523 cb.addAnnotation(annot); + 524 } + 525 else if (type.equals("LINE")) { + 526 PdfAnnotation annot = PdfAnnotation.createLine(writer, r, + 527 altText,(float)mx[4], + 528 (float)mx[5] - (float)rec_height, + 529 (float)mx[4] + (float)rec_width, + 530 (float)mx[5]); + 531 cb.addAnnotation(annot); + 532 } + 533 else if (type.equals("SQUARE")) { + 534 PdfAnnotation annot = PdfAnnotation.createSquareCirlcle(writer, r, + 535 altText,true); + 536 cb.addAnnotation(annot); 537 } - catch (DocumentException e) - { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. - }*/ + 538 else if(type.equals("TEXT")) { + 539 cb.beginText(); + 540 cb.setFontAndSize(baseFont, fontSize); 541 + 542 cb.setTextMatrix((float)mx[0], (float)mx[1], (float)mx[2], (float)mx[3], (float)mx[4], (float)mx[5]); + 543 cb.showText(altText); + 544 cb.endText(); + 545 } + 546 setTransform(at); 547 } 548 549 /** 1004 if(debugmode) debug("create()"); 1005 1006 PdfGraphics2D g2 = new PdfGraphics2D(); + 1007 g2.parent = this; + 1008 g2._imageOutline = this._imageOutline; + 1009 g2._missingImageOutline = this._missingImageOutline; 1010 g2.onlyShapes = this.onlyShapes; 1011 g2.transform = new AffineTransform(this.transform); 1012 g2.baseFonts = this.baseFonts; 1157 if(debugmode) debug("clipRect(int x, int y, int width, int height): " + "x " + x + " y "+ y + " width " + width + " height " + height); 1158 1159 Rectangle2D rect = new Rectangle2D.Double(x,y,width,height); + 1160 if(parent!=null) parent._missingImageOutline = rect; 1161 clip(rect); 1162 } 1163 1254 public void fillRect(int x, int y, int width, int height) { 1255 if(debugmode) debug("fillRect(int x, int y, int width, int height): "+ "x " + x + " y "+ y + " width " + width + " height " + height); 1256 - fill(new Rectangle(x,y,width,height)); + 1257 Rectangle rect = new Rectangle(x,y,width,height); + 1258 fill(rect); 1259 } 1260 1261 /** 1572 private boolean drawImage(Image img, Image mask, AffineTransform xform, Color bgColor, ImageObserver obs) { 1573 if (xform==null) return true; 1574 + 1575 double x = xform.getScaleX(); + 1576 double y = xform.getScaleY(); + 1577 1578 xform.translate(0, img.getHeight(obs)); 1579 xform.scale(img.getWidth(obs), img.getHeight(obs)); 1580 1594 msk.setInvertMask(true); 1595 image.setImageMask(msk); 1596 } + 1597 + 1598 if(parent!=null) parent._imageOutline = new Rectangle((int)x, (int)y, img.getWidth(obs), img.getHeight(obs)); + 1599 1600 cb.addImage(image, (float)mx[0], (float)mx[1], (float)mx[2], (float)mx[3], (float)mx[4], (float)mx[5]); 1601 1602 } catch (Exception ex) { Change 85084 If a font file can be read by both the Java native font class and iText font class, then the font file is usable in CF. Open type font files can be read by Itext, but can't be read by either SUN JDK1.3, or SUN JDK1.4, the only time a open type font can be used is in CFReport/PDF output. With this check-in, we allow otf file to be registered. The otf fonts will be displayed in the font admin page. It can be added, or dropped. If a OTF font is being used in situations where it is not supported, we throw DocumentFontException and show the actual font file name which caused the problem. UPDATE JAVA CLASS: com/lowagie/text/FontFactory.java Edit //depot/ColdFusion/cf_main/tools/itext/src/com/lowagie/text/FontFactory.java#7 513 trueTypeFonts.setProperty(names[i][3], path); 514 } 515 if (fullName != null) { - names = (String[][])allNames[1]; + 516 // Currently only adobe is the only commercial open type font vendor. + 517 // The adobe otf files sometimes use the same font Family name for multiple font files. + 518 // That means the fonts won't show up correctly in the font administrator page. + 519 // To work around this problem, we look for font names in the windows platform, rather + 520 // than the mac platform + 521 // + 522 // See the open font names spec in + 523 // http://partners.adobe.com/asn/tech/type/opentype/recom.jsp + 524 if (path.toLowerCase().endsWith(".otf")) { + 525 names = (String[][])allNames[2]; + 526 } else + 527 names = (String[][])allNames[1]; + 528 529 for (int i = 0; i < names.length; i++) { 530 if ("0".equals(names[i][2])) { 531 familyName = names[i][3]; Change 84538 adding debug print out for pdfGraphics2d in order to see what funcitons are called and what parameters passing in. -Ditextdebug=true and -Ditextdebuglink=true need to be set. UPDATED JAVA CLASS: com/lowagie/text/pdf/PdfGraphics2D.java 90 import java.awt.RenderingHints.Key; 91 import java.awt.geom.NoninvertibleTransformException; 92 import java.awt.geom.Point2D; - import java.awt.geom.GeneralPath; 93 import java.text.CharacterIterator; 94 import java.text.AttributedCharacterIterator; 95 import java.util.Map; 162 163 public static int AFM_DIVISOR = 1000; // used to calculate coordinates 164 + 165 private static boolean debugmode = (System.getProperty("itextdebug")!= null + 166 && ((String)System.getProperty("itextdebug")).equalsIgnoreCase("true")); + 167 + 168 private static boolean itextdebuglink = (System.getProperty("itextdebuglink") != null + 169 && ((String) System.getProperty("itextdebuglink")).equalsIgnoreCase("true")); + 170 171 private PdfGraphics2D() { 172 } 173 adding print if(debugmode) to the class Change 83407 1) Update the PdfWriter to ignore missing internal reference link if not present. UPDATED JAVA CLASS: com/lowagie/text/pdf/PdfWriter.java#4 edit Edit //depot/ColdFusion/cf_main/tools/itext/src/com/lowagie/text/pdf/PdfWriter.java#3 1235 String name = (String)i.next(); 1236 Object obj[] = (Object[])dest.get(name); 1237 PdfDestination destination = (PdfDestination)obj[2]; - if (destination == null) - throw new RuntimeException("The name '" + name + "' has no local destination."); - if (obj[1] == null) - obj[1] = getPdfIndirectReference(); - PdfIndirectObject iob = body.add(destination, (PdfIndirectReference)obj[1]); + 1238 + 1239 // ignore if destination is null + 1240 //if (destination == null) + 1241 // throw new RuntimeException("The name '" + name + "' has no local destination."); + 1242 + 1243 if (destination != null) + 1244 { + 1245 if (obj[1] == null) + 1246 obj[1] = getPdfIndirectReference(); + 1247 PdfIndirectObject iob = body.add(destination, (PdfIndirectReference)obj[1]); + 1248 } 1249 } 1250 } 1251 Change 83387 1) extend G2DLink interface to PdfGraphics2D.java to enable PDF links - added addLink function to enable links. - addAltText still under development 2) update the iText build.xml to include G2DLink interface. UPDATED JAVA CLASS: ... //depot/ColdFusion/cf_main/tools/itext/build.xml#4 edit ... //depot/ColdFusion/cf_main/tools/itext/lib/G2DLink.jar#1 add ... //depot/ColdFusion/cf_main/tools/itext/src/com/lowagie/text/pdf/PdfGraphics2D.java#4 edit (added addLink function to enable links.) Edit //depot/ColdFusion/cf_main/tools/itext/build.xml#3 27 28 29 + 30 31 32 33 40 41 42 + 43 44 45 46 697 698 699 - + Add //depot/ColdFusion/cf_main/tools/itext/lib/G2DLink.jar Edit //depot/ColdFusion/cf_main/tools/itext/src/com/lowagie/text/pdf/PdfGraphics2D.java#3 104 - public class PdfGraphics2D extends Graphics2D { - + 105 + 106 public class PdfGraphics2D extends Graphics2D implements G2DLink{ + 107 + 381 + 382 383 /** + 384 * Define the 'alt' text associated with an image. This method should be called after + 385 * each image is drawn on the screen, even if the alt text is empty. + 386 * + 387 * @param image Reference to the Image Object previously drawn on the screen + 388 * @param altText The alt text, or "" if no alt text is defined. + 389 */ + 390 public void addAltText(java.awt.Image image, String altText ) { + 391 + 392 /* try + 393 { + 394 PdfWriter writer = cb.getPdfWriter(); + 395 PdfDocument doc = writer.getPdfDocument(); + 396 com.lowagie.text.Image img = com.lowagie.text.Image.getInstance(image, image.getGraphics().getColor()); + 397 img.setAnnotation(new Annotation(altText,altText, 0, 0, 0, 0)); + 398 + 399 doc.add(img); + 400 } + 401 catch (Exception e) + 402 { + 403 e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + 404 }*/ + 405 + 406 } + 407 + 408 + 409 /** + 410 * Define the 'alt' text associated with each clickable region. This method should be called after + 411 * each region is drawn on the screen, even if the alt text is empty. + 412 * + 413 * @param s Each clickable region + 414 * @param altText altText The alt text, or "" if no alt text is defined. + 415 */ + 416 public void addAltText(java.awt.Shape s, String altText) { + 417 + 418 /* try + 419 { + 420 Rectangle2D r = s.getBounds2D(); + 421 double w = r.getWidth(); + 422 double h = r.getHeight(); + 423 double x = r.getX(); + 424 double y = r.getY(); + 425 Annotation ann = new Annotation(altText,altText, (float)x, (float)y, (float)(x+w), (float)(y+h)); + 426 PdfWriter writer = cb.getPdfWriter(); + 427 PdfDocument doc = writer.getPdfDocument(); + 428 doc.add(ann); + 429 } + 430 catch (DocumentException e) + 431 { + 432 e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + 433 }*/ + 434 + 435 } + 436 + 437 /** + 438 * Enable Links and Anchors in the PDF document + 439 * + 440 * @param resource - external links (i.e. http://www.yahoo.com), internal reference + 441 * anchor (i.e. #topofdocument), internal reference target where anchor point to + 442 * (i.e. topofdocument) + 443 * + 444 * @param linkType - 0 external_link, + 445 * 1 internal_reference_anchor, + 446 * 2 internal_reference_name + 447 * @param trans - Transform Matrix for the shape + 448 * @param s - Opaque Shape defines the region of the image or text where + 449 * it is sensitive to mouse clicking. + 450 * + 451 */ + 452 public void addLink(String resource, int linkType, AffineTransform trans, Shape s) { + 453 + 454 AffineTransform at = getTransform(); + 455 AffineTransform at2 = getTransform(); + 456 + 457 at2.concatenate(trans); + 458 setTransform(at2); + 459 AffineTransform inverse = this.normalizeMatrix(); + 460 AffineTransform flipper = AffineTransform.getScaleInstance(1,-1); + 461 inverse.concatenate(flipper); + 462 + 463 double rec_width = 0; + 464 double rec_height = 0; + 465 s = trans.createTransformedShape(s); + 466 Rectangle2D r = s.getBounds2D(); + 467 rec_width = r.getWidth(); + 468 rec_height = r.getHeight(); + 469 + 470 double[] mx = new double[6]; + 471 inverse.getMatrix(mx); + 472 + 473 PdfWriter writer = cb.getPdfWriter(); + 474 PdfAction action = null; + 475 + 476 if(linkType == internal_reference_anchor) { + 477 PdfDocument doc = writer.getPdfDocument(); + 478 PdfDestination destination = new PdfDestination(PdfDestination.XYZ, (float)mx[4], (float)mx[5], 0); + 479 doc.localDestination(resource, destination); + 480 } + 481 else { + 482 if(linkType == external_link ) { + 483 action = new PdfAction(resource); + 484 PdfAnnotation a = new PdfAnnotation( writer, + 485 (float)mx[4], + 486 (float)mx[5] - (float)rec_height, + 487 (float)mx[4] + (float)rec_width, + 488 (float)mx[5], + 489 action); + 490 + 491 cb.addAnnotation(a); + 492 } + 493 else if (linkType == internal_reference_target ) { + 494 PdfDocument doc = writer.getPdfDocument(); + 495 String target = null; + 496 + 497 int index = -1; + 498 if((index = resource.indexOf('#')) >= 0) { + 499 target = resource.substring(index+1, resource.length()); + 500 } + 501 else { + 502 target = resource; + 503 } + 504 + 505 doc.localGoto(target, (float)mx[4], + 506 (float)mx[5] - (float)rec_height, + 507 (float)mx[4] + (float)rec_width, + 508 (float)mx[5]); + 509 } + 510 } + 511 + 512 setTransform(at); + 513 + 514 } + 515 Change 78165 Add a method in iTextFactory to return font path for true type fonts. UPDATED JAVA CLASS: com/lowagie/text/FontFactory.java Edit //depot/ColdFusion/cf_main/tools/itext/src/com/lowagie/text/FontFactory.java#6 653 return fontFamilies; 654 } 655 + 656 public static String getFontPath(String family, int style) { + 657 String fontname = family; + 658 HashSet tmp = (HashSet) fontFamilies.get(fontname); + 659 if (tmp != null) { + 660 // some bugs were fixed here by Daniel Marczisovszky + 661 String lowercasefontname = fontname.toLowerCase(); + 662 int s = style == Font.UNDEFINED ? Font.NORMAL : style; + 663 int fs = Font.NORMAL; + 664 boolean found = false; + 665 for (Iterator i = tmp.iterator(); i.hasNext(); ) { + 666 String f = (String) i.next(); + 667 String lcf = f.toLowerCase(); + 668 fs = Font.NORMAL; + 669 if (lcf.toLowerCase().indexOf("bold") != -1) fs |= Font.BOLD; + 670 if (lcf.toLowerCase().indexOf("italic") != -1 || lcf.toLowerCase().indexOf("oblique") != -1) fs |= Font.ITALIC; + 671 if ((s & Font.BOLDITALIC) == fs) { + 672 fontname = f; + 673 found = true; + 674 break; + 675 } + 676 } + 677 if (style != Font.UNDEFINED && found) { + 678 style &= ~fs; + 679 } + 680 } + 681 fontname = trueTypeFonts.getProperty(fontname); + 682 return fontname; + 683 } 684 } Change 76958 itext/src/com/lowagie/text/Font.java -- change getCalculatedBaseFont method to include embeding option, before it is always false for embed. (to maintain the original method, added a simple redirect method, with embed always false). itext/src/com/lowagie/text/pdf/BaseFont.java -- change CreateFont method, comment out force to embed when encoding is IDENTITY-H, update in the TrueTypeFontUnicode to handle not embeded situations itext/src/com/lowagie/text/pdf/TrueTypeFontUnicode -- change the constructor checking for embed true, automatic throw exception behavior. Also change the WriteFont method, to handle the embedded = false situation. Edit //depot/ColdFusion/cf_main/tools/itext/src/com/lowagie/text/Font.java#3 612 return baseFont; 613 } 614 + 615 /** + 616 * maintain the original method + 617 * @param specialEncoding + 618 * @return + 619 */ + 620 public BaseFont getCalculatedBaseFont(boolean specialEncoding) + 621 { + 622 return getCalculatedBaseFont(specialEncoding, false); + 623 } 624 /** Gets the BaseFont this class represents. 625 * For the built-in fonts a BaseFont is calculated. 626 * @param specialEncoding true to use the special encoding for Symbol and ZapfDingbats, 627 * false to always use Cp1252 628 * @return the BaseFont this class represents 629 */ - public BaseFont getCalculatedBaseFont(boolean specialEncoding) { + 630 public BaseFont getCalculatedBaseFont(boolean specialEncoding, boolean embed) { 631 if (baseFont != null) 632 return baseFont; 633 int style = this.style; 702 break; 703 } 704 try { - cfont = BaseFont.createFont(fontName, encoding, false); + 705 cfont = BaseFont.createFont(fontName, encoding, embed); 706 } 707 catch (Exception ee) { 708 throw new ExceptionConverter(ee); Edit //depot/ColdFusion/cf_main/tools/itext/src/com/lowagie/text/pdf/BaseFont.java#3 360 boolean isCJKFont = isBuiltinFonts14 ? false : CJKFont.isCJKFont(nameBase, encoding); 361 if (isBuiltinFonts14 || isCJKFont) 362 embedded = false; - else if (encoding.equals(IDENTITY_H) || encoding.equals(IDENTITY_V)) - embedded = true; + 363 + 364 // Should not force to embed, update in the TrueTypeFontUnicode to handle the + 365 // not embeded situations + 366 //else if (encoding.equals(IDENTITY_H) || encoding.equals(IDENTITY_V)) + 367 // embedded = true; + 368 369 BaseFont fontFound = null; 370 BaseFont fontBuilt = null; 371 String key = name + "\n" + encoding + "\n" + embedded; Edit //depot/ColdFusion/cf_main/tools/itext/src/com/lowagie/text/pdf/TrueTypeFontUnicode.java#3 81 TrueTypeFontUnicode(String ttFile, String enc, boolean emb, byte ttfAfm[]) throws DocumentException, IOException { 82 String nameBase = getBaseName(ttFile); 83 String ttcName = getTTCName(nameBase); + 84 85 if (nameBase.length() < ttFile.length()) { 86 style = ttFile.substring(nameBase.length()); 87 } 92 if (ttcName.length() < nameBase.length()) 93 ttcIndex = nameBase.substring(ttcName.length() + 1); 94 fontType = FONT_TYPE_TTUNI; - if ((fileName.toLowerCase().endsWith(".ttf") || fileName.toLowerCase().endsWith(".otf") || fileName.toLowerCase().endsWith(".ttc")) && ((enc.equals(IDENTITY_H) || enc.equals(IDENTITY_V)) && emb)) { + 95 if ((fileName.toLowerCase().endsWith(".ttf") || fileName.toLowerCase().endsWith(".otf") || fileName.toLowerCase().endsWith(".ttc")) && ((enc.equals(IDENTITY_H) || enc.equals(IDENTITY_V)))) { 96 process(ttfAfm); - if (os_2.fsType == 2) + 97 if (os_2.fsType == 2 && emb) 98 throw new DocumentException(fileName + style + " cannot be embedded due to licensing restrictions."); 99 // Sivan 100 if ((cmap31 == null && !fontSpecific) || (cmap10 == null && fontSpecific)) 308 PdfObject pobj = null; 309 PdfIndirectObject obj = null; 310 // sivan: cff - if (cff) { - RandomAccessFileOrArray rf2 = new RandomAccessFileOrArray(rf); - byte b[] = new byte[cffLength]; - try { - rf2.reOpen(); - rf2.seek(cffOffset); - rf2.readFully(b); - } finally { - try { - rf2.close(); - } catch (Exception e) { - // empty on purpose - } - } - - CFFFont cffFont = new CFFFont(new RandomAccessFileOrArray(b)); - // test if we can find the font by name and if it's a type1 CFF - if (cffFont.exists(fontName) && !cffFont.isCID(fontName)) { - byte[] cid = cffFont.getCID( (cffFont.getNames())[0] ); - if (cid != null) b=cid; - } - // if the font is already CID, or not found by name, or - // getCID returned null, we just use the data in the CFF - // table and hope for the best. - - - // for debugging, force a reparsing - /* - java.lang.System.err.println(""); - java.lang.System.err.println(""); - java.lang.System.err.println(""); - CFFFont dummy = new CFFFont(java.nio.ByteBuffer.wrap(b)); - java.lang.System.err.println(""); - java.lang.System.err.println(""); - java.lang.System.err.println(""); - */ - pobj = new StreamFont(b, "CIDFontType0C"); - obj = writer.addToBody(pobj); - ind_font = obj.getIndirectReference(); - } else { - TrueTypeFontSubSet sb = new TrueTypeFontSubSet(fileName, rf, longTag, directoryOffset, false); - byte b[] = sb.process(); - int lengths[] = new int[]{b.length}; - pobj = new StreamFont(b, lengths); - obj = writer.addToBody(pobj); - ind_font = obj.getIndirectReference(); + 311 if ( embedded ) + 312 { + 313 if (cff) { + 314 RandomAccessFileOrArray rf2 = new RandomAccessFileOrArray(rf); + 315 byte b[] = new byte[cffLength]; + 316 try { + 317 rf2.reOpen(); + 318 rf2.seek(cffOffset); + 319 rf2.readFully(b); + 320 } finally { + 321 try { + 322 rf2.close(); + 323 } catch (Exception e) { + 324 // empty on purpose + 325 } + 326 } + 327 + 328 CFFFont cffFont = new CFFFont(new RandomAccessFileOrArray(b)); + 329 // test if we can find the font by name and if it's a type1 CFF + 330 if (cffFont.exists(fontName) && !cffFont.isCID(fontName)) { + 331 byte[] cid = cffFont.getCID( (cffFont.getNames())[0] ); + 332 if (cid != null) b=cid; + 333 } + 334 // if the font is already CID, or not found by name, or + 335 // getCID returned null, we just use the data in the CFF + 336 // table and hope for the best. + 337 + 338 + 339 // for debugging, force a reparsing + 340 /* + 341 java.lang.System.err.println(""); + 342 java.lang.System.err.println(""); + 343 java.lang.System.err.println(""); + 344 CFFFont dummy = new CFFFont(java.nio.ByteBuffer.wrap(b)); + 345 java.lang.System.err.println(""); + 346 java.lang.System.err.println(""); + 347 java.lang.System.err.println(""); + 348 */ + 349 pobj = new StreamFont(b, "CIDFontType0C"); + 350 obj = writer.addToBody(pobj); + 351 ind_font = obj.getIndirectReference(); + 352 } else { + 353 TrueTypeFontSubSet sb = new TrueTypeFontSubSet(fileName, rf, longTag, directoryOffset, false); + 354 byte b[] = sb.process(); + 355 int lengths[] = new int[]{b.length}; + 356 pobj = new StreamFont(b, lengths); + 357 obj = writer.addToBody(pobj); + 358 ind_font = obj.getIndirectReference(); + 359 } 360 } - String subsetPrefix = createSubsetPrefix(); + 361 + 362 String subsetPrefix = ""; + 363 if(embedded) subsetPrefix = createSubsetPrefix(); + 364 365 //if (cff) subsetPrefix = ""; 366 PdfDictionary dic = getFontDescriptor(ind_font, subsetPrefix); 367 obj = writer.addToBody(dic); Change 77009 itext/src/com/lowagie/text/FontFactory.java.Adding TTF directory typical to unix machines (ttf folder in uppercase). Edit //depot/ColdFusion/cf_main/tools/itext/src/com/lowagie/text/FontFactory.java#5 599 count += registerDirectory("/usr/share/fonts/default/TrueType"); 600 count += registerDirectory("/usr/X11R6/lib/X11/fonts/ttf"); 601 count += registerDirectory("/usr/X11R6/lib/X11/fonts/truetype"); + 602 count += registerDirectory("/usr/X11R6/lib/X11/fonts/TTF"); 603 return count; 604 } 605 Change 76036 add "/usr/X11R6/lib/X11/fonts/truetype" to one of these directories FontService will automatically scan for fonts on server start. Edit //depot/ColdFusion/cf_main/tools/itext/src/com/lowagie/text/FontFactory.java#4 598 count += registerDirectory("/usr/openwin/lib/X11/fonts/TrueType"); 599 count += registerDirectory("/usr/share/fonts/default/TrueType"); 600 count += registerDirectory("/usr/X11R6/lib/X11/fonts/ttf"); + 601 count += registerDirectory("/usr/X11R6/lib/X11/fonts/truetype"); 602 return count; 603 } 604 Change 87750 if the font face name contains "it", then we consider the font face italic. public static Font getFont(String fontname, String encoding, boolean embedded, float size, int style, Color color) { if (fontname == null) return new Font(Font.UNDEFINED, size, style, color); HashSet tmp = (HashSet) fontFamilies.get(fontname); if (tmp != null) { // some bugs were fixed here by Daniel Marczisovszky String lowercasefontname = fontname.toLowerCase(); int s = style == Font.UNDEFINED ? Font.NORMAL : style; int fs = Font.NORMAL; boolean found = false; for (Iterator i = tmp.iterator(); i.hasNext(); ) { String f = (String) i.next(); String lcf = f.toLowerCase(); fs = Font.NORMAL; if (lcf.toLowerCase().indexOf("bold") != -1) fs |= Font.BOLD; < if (lcf.toLowerCase().indexOf("italic") != -1 || lcf.toLowerCase().indexOf("oblique") != -1) fs |= Font.ITALIC; -> if (lcf.toLowerCase().indexOf("italic") != -1 || lcf.toLowerCase().indexOf("oblique") != -1 || lcf.toLowerCase().indexOf("it") != -1) fs |= Font.ITALIC; if ((s & Font.BOLDITALIC) == fs) { fontname = f; found = true; break; } } if (style != Font.UNDEFINED && found) { style &= ~fs; } } changelist 88282 update com.lowagie.text.pdf.PdfGraphics2D.java change the drawString function's contentByte to use default contentByte object, this has no effect on the background image. /** * @see Graphics2D#drawString(String, float, float) */ public void drawString(String s, float x, float y) { < PdfContentByte forgroundcb = cb.getPdfWriter().getDirectContent(); -> PdfContentByte forgroundcb = cb;//cb.getPdfWriter().getDirectContent(); setFillPaint(forgroundcb); if (onlyShapes) { TextLayout tl = new TextLayout(s, this.font, new FontRenderContext(new AffineTransform(), false, true)); tl.draw(this, x, y); }