Source Code Cross Referenced for PDAppearance.java in  » PDF » PDFBox-0.7.3 » org » pdfbox » pdmodel » interactive » form » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » PDF » PDFBox 0.7.3 » org.pdfbox.pdmodel.interactive.form 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /**
002:         * Copyright (c) 2003-2006, www.pdfbox.org
003:         * All rights reserved.
004:         *
005:         * Redistribution and use in source and binary forms, with or without
006:         * modification, are permitted provided that the following conditions are met:
007:         *
008:         * 1. Redistributions of source code must retain the above copyright notice,
009:         *    this list of conditions and the following disclaimer.
010:         * 2. Redistributions in binary form must reproduce the above copyright notice,
011:         *    this list of conditions and the following disclaimer in the documentation
012:         *    and/or other materials provided with the distribution.
013:         * 3. Neither the name of pdfbox; nor the names of its
014:         *    contributors may be used to endorse or promote products derived from this
015:         *    software without specific prior written permission.
016:         *
017:         * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
018:         * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
019:         * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
020:         * DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
021:         * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
022:         * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
023:         * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
024:         * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
025:         * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
026:         * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
027:         *
028:         * http://www.pdfbox.org
029:         *
030:         */package org.pdfbox.pdmodel.interactive.form;
031:
032:        import java.io.ByteArrayInputStream;
033:        import java.io.ByteArrayOutputStream;
034:        import java.io.IOException;
035:        import java.io.OutputStream;
036:        import java.io.PrintWriter;
037:
038:        import java.util.ArrayList;
039:        import java.util.Iterator;
040:        import java.util.List;
041:        import java.util.Map;
042:
043:        import org.pdfbox.cos.COSArray;
044:        import org.pdfbox.cos.COSDictionary;
045:        import org.pdfbox.cos.COSFloat;
046:        import org.pdfbox.cos.COSName;
047:        import org.pdfbox.cos.COSNumber;
048:        import org.pdfbox.cos.COSStream;
049:        import org.pdfbox.cos.COSString;
050:
051:        import org.pdfbox.pdfparser.PDFStreamParser;
052:        import org.pdfbox.pdfwriter.ContentStreamWriter;
053:
054:        import org.pdfbox.pdmodel.PDResources;
055:
056:        import org.pdfbox.pdmodel.common.PDRectangle;
057:
058:        import org.pdfbox.pdmodel.font.PDFont;
059:        import org.pdfbox.pdmodel.font.PDFontDescriptor;
060:        import org.pdfbox.pdmodel.font.PDSimpleFont;
061:
062:        import org.pdfbox.pdmodel.interactive.action.PDAdditionalActions;
063:        import org.pdfbox.pdmodel.interactive.annotation.PDAppearanceDictionary;
064:        import org.pdfbox.pdmodel.interactive.annotation.PDAppearanceStream;
065:        import org.pdfbox.pdmodel.interactive.annotation.PDAnnotationWidget;
066:
067:        import org.pdfbox.util.PDFOperator;
068:
069:        /**
070:         * This one took me a while, but i'm proud to say that it handles
071:         * the appearance of a textbox. This allows you to apply a value to
072:         * a field in the document and handle the appearance so that the
073:         * value is actually visible too.
074:         * The problem was described by Ben Litchfield, the author of the
075:         * example: org.pdfbox.examlpes.fdf.ImportFDF. So Ben, here is the
076:         * solution.
077:         *
078:         * @author sug
079:         * @author <a href="mailto:ben@benlitchfield.com">Ben Litchfield</a>
080:         * @version $Revision: 1.19 $
081:         */
082:        public class PDAppearance {
083:            private PDVariableText parent;
084:
085:            private String value;
086:            private COSString defaultAppearance;
087:
088:            private PDAcroForm acroForm;
089:            private List widgets = new ArrayList();
090:
091:            /**
092:             * Constructs a COSAppearnce from the given field.
093:             *
094:             * @param theAcroForm the acro form that this field is part of.
095:             * @param field the field which you wish to control the appearance of
096:             * @throws IOException If there is an error creating the appearance.
097:             */
098:            public PDAppearance(PDAcroForm theAcroForm, PDVariableText field)
099:                    throws IOException {
100:                acroForm = theAcroForm;
101:                parent = field;
102:
103:                widgets = field.getKids();
104:                if (widgets == null) {
105:                    widgets = new ArrayList();
106:                    widgets.add(field.getWidget());
107:                }
108:
109:                defaultAppearance = getDefaultAppearance();
110:
111:            }
112:
113:            /**
114:             * Returns the default apperance of a textbox. If the textbox
115:             * does not have one, then it will be taken from the AcroForm.
116:             * @return The DA element
117:             */
118:            private COSString getDefaultAppearance() {
119:
120:                COSString dap = parent.getDefaultAppearance();
121:                if (dap == null) {
122:                    COSArray kids = (COSArray) parent.getDictionary()
123:                            .getDictionaryObject("Kids");
124:                    if (kids != null && kids.size() > 0) {
125:                        COSDictionary firstKid = (COSDictionary) kids
126:                                .getObject(0);
127:                        dap = (COSString) firstKid.getDictionaryObject("DA");
128:                    }
129:                    if (dap == null) {
130:                        dap = (COSString) acroForm.getDictionary()
131:                                .getDictionaryObject(COSName.getPDFName("DA"));
132:                    }
133:                }
134:                return dap;
135:            }
136:
137:            private int getQ() {
138:                int q = parent.getQ();
139:                if (parent.getDictionary().getDictionaryObject("Q") == null) {
140:                    COSArray kids = (COSArray) parent.getDictionary()
141:                            .getDictionaryObject("Kids");
142:                    if (kids != null && kids.size() > 0) {
143:                        COSDictionary firstKid = (COSDictionary) kids
144:                                .getObject(0);
145:                        COSNumber qNum = (COSNumber) firstKid
146:                                .getDictionaryObject("Q");
147:                        if (qNum != null) {
148:                            q = qNum.intValue();
149:                        }
150:                    }
151:                }
152:                return q;
153:            }
154:
155:            /**
156:             * Extracts the original appearance stream into a list of tokens.
157:             *
158:             * @return The tokens in the original appearance stream
159:             */
160:            private List getStreamTokens(PDAppearanceStream appearanceStream)
161:                    throws IOException {
162:                List tokens = null;
163:                if (appearanceStream != null) {
164:                    tokens = getStreamTokens(appearanceStream.getStream());
165:                }
166:                return tokens;
167:            }
168:
169:            private List getStreamTokens(COSString string) throws IOException {
170:                PDFStreamParser parser;
171:
172:                List tokens = null;
173:                if (string != null) {
174:                    ByteArrayInputStream stream = new ByteArrayInputStream(
175:                            string.getBytes());
176:                    parser = new PDFStreamParser(stream, acroForm.getDocument()
177:                            .getDocument().getScratchFile());
178:                    parser.parse();
179:                    tokens = parser.getTokens();
180:                }
181:                return tokens;
182:            }
183:
184:            private List getStreamTokens(COSStream stream) throws IOException {
185:                PDFStreamParser parser;
186:
187:                List tokens = null;
188:                if (stream != null) {
189:                    parser = new PDFStreamParser(stream);
190:                    parser.parse();
191:                    tokens = parser.getTokens();
192:                }
193:                return tokens;
194:            }
195:
196:            /**
197:             * Tests if the apperance stream already contains content.
198:             *
199:             * @return true if it contains any content
200:             */
201:            private boolean containsMarkedContent(List stream) {
202:                return stream.contains(PDFOperator.getOperator("BMC"));
203:            }
204:
205:            /**
206:             * This is the public method for setting the appearance stream.
207:             *
208:             * @param apValue the String value which the apperance shoud represent
209:             *
210:             * @throws IOException If there is an error creating the stream.
211:             */
212:            public void setAppearanceValue(String apValue) throws IOException {
213:                // MulitLine check and set
214:                if (parent.isMultiline() && apValue.indexOf('\n') != -1) {
215:                    apValue = convertToMultiLine(apValue);
216:                }
217:
218:                value = apValue;
219:                Iterator widgetIter = widgets.iterator();
220:                while (widgetIter.hasNext()) {
221:                    Object next = widgetIter.next();
222:                    PDAnnotationWidget widget = null;
223:                    if (next instanceof  PDField) {
224:                        widget = ((PDField) next).getWidget();
225:                    } else {
226:                        widget = (PDAnnotationWidget) next;
227:                    }
228:                    PDAdditionalActions actions = widget.getActions();
229:                    if (actions != null
230:                            && actions.getF() != null
231:                            && widget.getDictionary().getDictionaryObject("AP") == null) {
232:                        //do nothing because the field will be formatted by acrobat
233:                        //when it is opened.  See FreedomExpressions.pdf for an example of this.
234:                    } else {
235:
236:                        PDAppearanceDictionary appearance = widget
237:                                .getAppearance();
238:                        if (appearance == null) {
239:                            appearance = new PDAppearanceDictionary();
240:                            widget.setAppearance(appearance);
241:                        }
242:
243:                        Map normalAppearance = appearance.getNormalAppearance();
244:                        PDAppearanceStream appearanceStream = (PDAppearanceStream) normalAppearance
245:                                .get("default");
246:                        if (appearanceStream == null) {
247:                            COSStream cosStream = new COSStream(acroForm
248:                                    .getDocument().getDocument()
249:                                    .getScratchFile());
250:                            appearanceStream = new PDAppearanceStream(cosStream);
251:                            appearanceStream.setBoundingBox(widget
252:                                    .getRectangle()
253:                                    .createRetranslatedRectangle());
254:                            appearance.setNormalAppearance(appearanceStream);
255:                        }
256:
257:                        List tokens = getStreamTokens(appearanceStream);
258:                        List daTokens = getStreamTokens(getDefaultAppearance());
259:                        PDFont pdFont = getFontAndUpdateResources(tokens,
260:                                appearanceStream);
261:
262:                        if (!containsMarkedContent(tokens)) {
263:                            ByteArrayOutputStream output = new ByteArrayOutputStream();
264:
265:                            //BJL 9/25/2004 Must prepend existing stream
266:                            //because it might have operators to draw things like
267:                            //rectangles and such
268:                            ContentStreamWriter writer = new ContentStreamWriter(
269:                                    output);
270:                            writer.writeTokens(tokens);
271:
272:                            output.write(" /Tx BMC\n".getBytes());
273:                            insertGeneratedAppearance(widget, output, pdFont,
274:                                    tokens, appearanceStream);
275:                            output.write(" EMC".getBytes());
276:                            writeToStream(output.toByteArray(),
277:                                    appearanceStream);
278:                        } else {
279:                            if (tokens != null) {
280:                                if (daTokens != null) {
281:                                    int bmcIndex = tokens.indexOf(PDFOperator
282:                                            .getOperator("BMC"));
283:                                    int emcIndex = tokens.indexOf(PDFOperator
284:                                            .getOperator("EMC"));
285:                                    if (bmcIndex != -1 && emcIndex != -1
286:                                            && emcIndex == bmcIndex + 1) {
287:                                        //if the EMC immediately follows the BMC index then should
288:                                        //insert the daTokens inbetween the two markers.
289:                                        tokens.addAll(emcIndex, daTokens);
290:                                    }
291:                                }
292:                                ByteArrayOutputStream output = new ByteArrayOutputStream();
293:                                ContentStreamWriter writer = new ContentStreamWriter(
294:                                        output);
295:                                float fontSize = calculateFontSize(pdFont,
296:                                        appearanceStream.getBoundingBox(),
297:                                        tokens, null);
298:                                boolean foundString = false;
299:                                for (int i = 0; i < tokens.size(); i++) {
300:                                    if (tokens.get(i) instanceof  COSString) {
301:                                        foundString = true;
302:                                        COSString drawnString = ((COSString) tokens
303:                                                .get(i));
304:                                        drawnString.reset();
305:                                        drawnString.append(apValue.getBytes());
306:                                    }
307:                                }
308:                                int setFontIndex = tokens.indexOf(PDFOperator
309:                                        .getOperator("Tf"));
310:                                tokens.set(setFontIndex - 1, new COSFloat(
311:                                        fontSize));
312:                                if (foundString) {
313:                                    writer.writeTokens(tokens);
314:                                } else {
315:                                    int bmcIndex = tokens.indexOf(PDFOperator
316:                                            .getOperator("BMC"));
317:                                    int emcIndex = tokens.indexOf(PDFOperator
318:                                            .getOperator("EMC"));
319:
320:                                    if (bmcIndex != -1) {
321:                                        writer.writeTokens(tokens, 0,
322:                                                bmcIndex + 1);
323:                                    } else {
324:                                        writer.writeTokens(tokens);
325:                                    }
326:                                    output.write("\n".getBytes());
327:                                    insertGeneratedAppearance(widget, output,
328:                                            pdFont, tokens, appearanceStream);
329:                                    if (emcIndex != -1) {
330:                                        writer.writeTokens(tokens, emcIndex,
331:                                                tokens.size());
332:                                    }
333:                                }
334:                                writeToStream(output.toByteArray(),
335:                                        appearanceStream);
336:                            } else {
337:                                //hmm?
338:                            }
339:                        }
340:                    }
341:                }
342:            }
343:
344:            private void insertGeneratedAppearance(
345:                    PDAnnotationWidget fieldWidget, OutputStream output,
346:                    PDFont pdFont, List tokens,
347:                    PDAppearanceStream appearanceStream) throws IOException {
348:                PrintWriter printWriter = new PrintWriter(output, true);
349:                float fontSize = 0.0f;
350:                PDRectangle boundingBox = null;
351:                boundingBox = appearanceStream.getBoundingBox();
352:                if (boundingBox == null) {
353:                    boundingBox = fieldWidget.getRectangle()
354:                            .createRetranslatedRectangle();
355:                }
356:                printWriter.println("BT");
357:                if (defaultAppearance != null) {
358:                    String daString = defaultAppearance.getString();
359:                    PDFStreamParser daParser = new PDFStreamParser(
360:                            new ByteArrayInputStream(daString.getBytes()), null);
361:                    daParser.parse();
362:                    List daTokens = daParser.getTokens();
363:                    fontSize = calculateFontSize(pdFont, boundingBox, tokens,
364:                            daTokens);
365:                    int fontIndex = daTokens.indexOf(PDFOperator
366:                            .getOperator("Tf"));
367:                    if (fontIndex != -1) {
368:                        daTokens.set(fontIndex - 1, new COSFloat(fontSize));
369:                    }
370:                    ContentStreamWriter daWriter = new ContentStreamWriter(
371:                            output);
372:                    daWriter.writeTokens(daTokens);
373:                }
374:                printWriter.println(getTextPosition(boundingBox, pdFont,
375:                        fontSize, tokens));
376:                int q = getQ();
377:                if (q == PDTextbox.QUADDING_LEFT) {
378:                    //do nothing because left is default
379:                } else if (q == PDTextbox.QUADDING_CENTERED
380:                        || q == PDTextbox.QUADDING_RIGHT) {
381:                    float fieldWidth = boundingBox.getWidth();
382:                    float stringWidth = (pdFont.getStringWidth(value) / 1000)
383:                            * fontSize;
384:                    float adjustAmount = fieldWidth - stringWidth - 4;
385:
386:                    if (q == PDTextbox.QUADDING_CENTERED) {
387:                        adjustAmount = adjustAmount / 2.0f;
388:                    }
389:
390:                    printWriter.println(adjustAmount + " 0 Td");
391:                } else {
392:                    throw new IOException("Error: Unknown justification value:"
393:                            + q);
394:                }
395:                printWriter.println("(" + value + ") Tj");
396:                printWriter.println("ET");
397:                printWriter.flush();
398:            }
399:
400:            private PDFont getFontAndUpdateResources(List tokens,
401:                    PDAppearanceStream appearanceStream) throws IOException {
402:
403:                PDFont retval = null;
404:                PDResources streamResources = appearanceStream.getResources();
405:                PDResources formResources = acroForm.getDefaultResources();
406:                if (formResources != null) {
407:                    if (streamResources == null) {
408:                        streamResources = new PDResources();
409:                        appearanceStream.setResources(streamResources);
410:                    }
411:
412:                    COSString da = getDefaultAppearance();
413:                    if (da != null) {
414:                        String data = da.getString();
415:                        PDFStreamParser streamParser = new PDFStreamParser(
416:                                new ByteArrayInputStream(data.getBytes()), null);
417:                        streamParser.parse();
418:                        tokens = streamParser.getTokens();
419:                    }
420:
421:                    int setFontIndex = tokens.indexOf(PDFOperator
422:                            .getOperator("Tf"));
423:                    COSName cosFontName = (COSName) tokens
424:                            .get(setFontIndex - 2);
425:                    String fontName = cosFontName.getName();
426:                    retval = (PDFont) streamResources.getFonts().get(fontName);
427:                    if (retval == null) {
428:                        retval = (PDFont) formResources.getFonts()
429:                                .get(fontName);
430:                        streamResources.getFonts().put(fontName, retval);
431:                    }
432:                }
433:                return retval;
434:            }
435:
436:            private String convertToMultiLine(String line) {
437:                int currIdx = 0;
438:                int lastIdx = 0;
439:                StringBuffer result = new StringBuffer(line.length() + 64);
440:                while ((currIdx = line.indexOf('\n', lastIdx)) > -1) {
441:                    result.append(line.substring(lastIdx, currIdx));
442:                    result.append(" ) Tj\n0 -13 Td\n(");
443:                    lastIdx = currIdx + 1;
444:                }
445:                result.append(line.substring(lastIdx));
446:                return result.toString();
447:            }
448:
449:            /**
450:             * Writes the stream to the actual stream in the COSStream.
451:             *
452:             * @throws IOException If there is an error writing to the stream
453:             */
454:            private void writeToStream(byte[] data,
455:                    PDAppearanceStream appearanceStream) throws IOException {
456:                OutputStream out = appearanceStream.getStream()
457:                        .createUnfilteredStream();
458:                out.write(data);
459:                out.flush();
460:            }
461:
462:            /**
463:             * w in an appearance stream represents the lineWidth.
464:             * @return the linewidth
465:             */
466:            private float getLineWidth(List tokens) {
467:
468:                float retval = 1;
469:                if (tokens != null) {
470:                    int btIndex = tokens.indexOf(PDFOperator.getOperator("BT"));
471:                    int wIndex = tokens.indexOf(PDFOperator.getOperator("w"));
472:                    //the w should only be used if it is before the first BT.
473:                    if ((wIndex > 0) && (wIndex < btIndex)) {
474:                        retval = ((COSNumber) tokens.get(wIndex - 1))
475:                                .floatValue();
476:                    }
477:                }
478:                return retval;
479:            }
480:
481:            private PDRectangle getSmallestDrawnRectangle(
482:                    PDRectangle boundingBox, List tokens) {
483:                PDRectangle smallest = boundingBox;
484:                for (int i = 0; i < tokens.size(); i++) {
485:                    Object next = tokens.get(i);
486:                    if (next == PDFOperator.getOperator("re")) {
487:                        COSNumber x = (COSNumber) tokens.get(i - 4);
488:                        COSNumber y = (COSNumber) tokens.get(i - 3);
489:                        COSNumber width = (COSNumber) tokens.get(i - 2);
490:                        COSNumber height = (COSNumber) tokens.get(i - 1);
491:                        PDRectangle potentialSmallest = new PDRectangle();
492:                        potentialSmallest.setLowerLeftX(x.floatValue());
493:                        potentialSmallest.setLowerLeftY(y.floatValue());
494:                        potentialSmallest.setUpperRightX(x.floatValue()
495:                                + width.floatValue());
496:                        potentialSmallest.setUpperRightY(y.floatValue()
497:                                + height.floatValue());
498:                        if (smallest == null
499:                                || smallest.getLowerLeftX() < potentialSmallest
500:                                        .getLowerLeftX()
501:                                || smallest.getUpperRightY() > potentialSmallest
502:                                        .getUpperRightY()) {
503:                            smallest = potentialSmallest;
504:                        }
505:
506:                    }
507:                }
508:                return smallest;
509:            }
510:
511:            /**
512:             * My "not so great" method for calculating the fontsize.
513:             * It does not work superb, but it handles ok.
514:             * @return the calculated font-size
515:             *
516:             * @throws IOException If there is an error getting the font height.
517:             */
518:            private float calculateFontSize(PDFont pdFont,
519:                    PDRectangle boundingBox, List tokens, List daTokens)
520:                    throws IOException {
521:                float fontSize = 0;
522:                if (daTokens != null) {
523:                    //daString looks like   "BMC /Helv 3.4 Tf EMC"
524:
525:                    int fontIndex = daTokens.indexOf(PDFOperator
526:                            .getOperator("Tf"));
527:                    if (fontIndex != -1) {
528:                        fontSize = ((COSNumber) daTokens.get(fontIndex - 1))
529:                                .floatValue();
530:                    }
531:                }
532:                if (parent.doNotScroll()) {
533:                    //if we don't scroll then we will shrink the font to fit into the text area.
534:                    float widthAtFontSize1 = pdFont.getStringWidth(value);
535:                    float availableWidth = boundingBox.getWidth();
536:                    float perfectFitFontSize = availableWidth
537:                            / widthAtFontSize1;
538:                } else if (fontSize == 0) {
539:                    float lineWidth = getLineWidth(tokens);
540:                    float stringWidth = pdFont.getStringWidth(value);
541:                    float height = 0;
542:                    if (pdFont instanceof  PDSimpleFont) {
543:                        height = ((PDSimpleFont) pdFont).getFontDescriptor()
544:                                .getFontBoundingBox().getHeight();
545:                    } else {
546:                        //now much we can do, so lets assume font is square and use width
547:                        //as the height
548:                        height = pdFont.getAverageFontWidth();
549:                    }
550:                    height = height / 1000f;
551:
552:                    float availHeight = getAvailableHeight(boundingBox,
553:                            lineWidth);
554:                    fontSize = (availHeight / height);
555:                }
556:                return fontSize;
557:            }
558:
559:            /**
560:             * Calculates where to start putting the text in the box.
561:             * The positioning is not quite as accurate as when Acrobat
562:             * places the elements, but it works though.
563:             *
564:             * @return the sting for representing the start position of the text
565:             *
566:             * @throws IOException If there is an error calculating the text position.
567:             */
568:            private String getTextPosition(PDRectangle boundingBox,
569:                    PDFont pdFont, float fontSize, List tokens)
570:                    throws IOException {
571:                float lineWidth = getLineWidth(tokens);
572:                float pos = 0.0f;
573:                if (parent.isMultiline()) {
574:                    int rows = (int) (getAvailableHeight(boundingBox, lineWidth) / ((int) fontSize));
575:                    pos = ((rows) * fontSize) - fontSize;
576:                } else {
577:                    if (pdFont instanceof  PDSimpleFont) {
578:                        //BJL 9/25/2004
579:                        //This algorithm is a little bit of black magic.  It does
580:                        //not appear to be documented anywhere.  Through examining a few
581:                        //PDF documents and the value that Acrobat places in there I
582:                        //have determined that the below method of computing the position
583:                        //is correct for certain documents, but maybe not all.  It does
584:                        //work f1040ez.pdf and Form_1.pdf
585:                        PDFontDescriptor fd = ((PDSimpleFont) pdFont)
586:                                .getFontDescriptor();
587:                        float bBoxHeight = boundingBox.getHeight();
588:                        float fontHeight = fd.getFontBoundingBox().getHeight()
589:                                + 2 * fd.getDescent();
590:                        fontHeight = (fontHeight / 1000) * fontSize;
591:                        pos = (bBoxHeight - fontHeight) / 2;
592:                    } else {
593:                        throw new IOException(
594:                                "Error: Don't know how to calculate the position for non-simple fonts");
595:                    }
596:                }
597:                PDRectangle innerBox = getSmallestDrawnRectangle(boundingBox,
598:                        tokens);
599:                float xInset = 2 + 2 * (boundingBox.getWidth() - innerBox
600:                        .getWidth());
601:                return Math.round(xInset) + " " + pos + " Td";
602:            }
603:
604:            /**
605:             * calculates the available width of the box.
606:             * @return the calculated available width of the box
607:             */
608:            private float getAvailableWidth(PDRectangle boundingBox,
609:                    float lineWidth) {
610:                return boundingBox.getWidth() - 2 * lineWidth;
611:            }
612:
613:            /**
614:             * calculates the available height of the box.
615:             * @return the calculated available height of the box
616:             */
617:            private float getAvailableHeight(PDRectangle boundingBox,
618:                    float lineWidth) {
619:                return boundingBox.getHeight() - 2 * lineWidth;
620:            }
621:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.