001: /*
002: Copyright (C) Etymon Systems, Inc. <http://www.etymon.com/>
003: */
004:
005: package com.etymon.pj;
006:
007: import java.util.*;
008: import java.io.*;
009: import java.nio.*;
010: import com.etymon.pj.exception.*;
011: import com.etymon.pj.object.*;
012: import com.etymon.pj.object.pagemark.*;
013: import com.etymon.pjx.*;
014: import com.etymon.pjx.util.*;
015:
016: /**
017: @author Nassib Nassar
018: @deprecated
019: */
020: public class PjxConvert {
021:
022: protected static final PdfName PDFNAME_LENGTH = new PdfName(
023: "Length");
024:
025: public static PjObject toPjObject(PdfObject obj)
026: throws com.etymon.pj.exception.PdfFormatException {
027:
028: if (obj instanceof PdfNull) {
029: return new PjNull();
030: }
031:
032: if (obj instanceof PdfBoolean) {
033: return new PjBoolean(((PdfBoolean) obj).getBoolean());
034: }
035:
036: if (obj instanceof PdfInteger) {
037: return new PjNumber((float) ((PdfInteger) obj).getInt());
038: }
039:
040: if (obj instanceof PdfFloat) {
041: return new PjNumber(((PdfFloat) obj).getFloat());
042: }
043:
044: if (obj instanceof PdfString) {
045: return new PjString(((PdfString) obj).getString());
046: }
047:
048: if (obj instanceof PdfName) {
049: return new PjName(((PdfName) obj).getString());
050: }
051:
052: if (obj instanceof PdfArray) {
053: List list = ((PdfArray) obj).getList();
054: Vector v = new Vector();
055: for (Iterator it = list.iterator(); it.hasNext();) {
056: v.addElement(toPjObject((PdfObject) it.next()));
057: }
058: return new PjArray(v);
059: }
060:
061: if (obj instanceof PdfDictionary) {
062: Map map = ((PdfDictionary) obj).getMap();
063: Hashtable h = new Hashtable();
064: for (Iterator it = map.keySet().iterator(); it.hasNext();) {
065: Object key = it.next();
066: h.put(toPjObject((PdfObject) key),
067: toPjObject((PdfObject) map.get(key)));
068: }
069:
070: // figure out what kind of dictionary we have
071: PjDictionary dictionary = new PjDictionary(h);
072: if (PjPage.isLike(dictionary)) {
073: return new PjPage(h);
074: } else if (PjPages.isLike(dictionary)) {
075: return new PjPages(h);
076: } else if (PjFontType1.isLike(dictionary)) {
077: return new PjFontType1(h);
078: } else if (PjFontDescriptor.isLike(dictionary)) {
079: return new PjFontDescriptor(h);
080: } else if (PjResources.isLike(dictionary)) {
081: return new PjResources(h);
082: } else if (PjCatalog.isLike(dictionary)) {
083: return new PjCatalog(h);
084: } else if (PjInfo.isLike(dictionary)) {
085: return new PjInfo(h);
086: } else if (PjEncoding.isLike(dictionary)) {
087: return new PjEncoding(h);
088: } else {
089: return dictionary;
090: }
091: }
092:
093: if (obj instanceof PdfStream) {
094: PdfStream stream = (PdfStream) obj;
095: PjDictionary d = (PjDictionary) (toPjObject(stream
096: .getDictionary()));
097: ByteBuffer streambuffer = stream.getBuffer();
098: byte[] ba = new byte[streambuffer.capacity()];
099: streambuffer.position(0);
100: streambuffer.limit(streambuffer.capacity());
101: streambuffer.get(ba);
102: return new PjStream(
103: new PjStreamDictionary(d.getHashtable()), ba);
104: }
105:
106: if (obj instanceof PdfReference) {
107: PdfReference ref = (PdfReference) obj;
108: return new PjReference(new PjNumber(ref.getObjectNumber()),
109: new PjNumber(ref.getGenerationNumber()));
110: }
111:
112: throw new com.etymon.pj.exception.PdfFormatException(
113: "Error converting object from PJX format.");
114:
115: }
116:
117: public static PdfObject toPjxObject(PjObject obj)
118: throws com.etymon.pj.exception.PdfFormatException {
119:
120: if (obj instanceof PjNull) {
121: return PdfNull.valueOf();
122: }
123:
124: if (obj instanceof PjBoolean) {
125: return PdfBoolean.valueOf(((PjBoolean) obj).getBoolean());
126: }
127:
128: if (obj instanceof PjNumber) {
129: PjNumber n = (PjNumber) obj;
130: float f = n.getFloat();
131: int x = n.getInt();
132: if (f == x) {
133: return new PdfInteger(x);
134: } else {
135: return new PdfFloat(f);
136: }
137: }
138:
139: if (obj instanceof PjString) {
140: return new PdfString(((PjString) obj).getString());
141: }
142:
143: if (obj instanceof PjName) {
144: return new PdfName(((PjName) obj).getString());
145: }
146:
147: if (obj instanceof PjArray) {
148: Vector v = ((PjArray) obj).getVector();
149: int vsize = v.size();
150: ArrayList list = new ArrayList(vsize);
151: for (int x = 0; x < vsize; x++) {
152: list.add(toPjxObject((PjObject) v.elementAt(x)));
153: }
154: return new PdfArray(list);
155: }
156:
157: if (obj instanceof PjDictionary) {
158: Hashtable h = ((PjDictionary) obj).getHashtable();
159: HashMap map = new HashMap(h.size());
160: for (Enumeration m = h.keys(); m.hasMoreElements();) {
161: PjObject key = (PjObject) m.nextElement();
162: PjObject value = (PjObject) h.get(key);
163: map.put(toPjxObject(key), toPjxObject(value));
164: }
165: return new PdfDictionary(map);
166: }
167:
168: if (obj instanceof PjStream) {
169: PjStream os = (PjStream) obj;
170: byte[] ob = os.getBuffer();
171: ByteBuffer buffer = ByteBuffer.allocateDirect(ob.length);
172: buffer.put(ob);
173: Map map = ((PdfDictionary) toPjxObject(os
174: .getStreamDictionary())).getMap();
175: HashMap dictionary = new HashMap(map.size());
176: dictionary.putAll(map);
177: dictionary.put(PDFNAME_LENGTH, new PdfInteger(ob.length));
178: buffer.position(0);
179: return new PdfStream(new PdfDictionary(dictionary), buffer);
180: }
181:
182: if (obj instanceof PjReference) {
183: PjReference r = (PjReference) obj;
184: return new PdfReference(r.getObjNumber().getInt(), r
185: .getGenNumber().getInt());
186: }
187:
188: throw new com.etymon.pj.exception.PdfFormatException(
189: "Error converting object from PJ format.");
190:
191: }
192:
193: /**
194: This method is provided for compatibility with PJ.
195: @throws IOException
196: @throws PdfFormatException
197: @deprecated
198: */
199: public static List pjxGetFields(PdfManager manager)
200: throws IOException, com.etymon.pjx.PdfFormatException {
201:
202: synchronized (manager) {
203:
204: PdfModifier mod = new PdfModifier(manager);
205:
206: ArrayList fieldList = new ArrayList();
207:
208: // get the Catalog
209: PdfDictionary catalog = mod.getCatalog();
210:
211: // get the AcroForm
212: PdfDictionary acroForm;
213: try {
214: acroForm = (PdfDictionary) (manager
215: .getObjectIndirect((PdfObject) catalog.getMap()
216: .get(new PdfName("AcroForm"))));
217: } catch (ClassCastException e) {
218: throw new com.etymon.pjx.PdfFormatException(
219: "AcroForm object is not a dictionary.");
220: }
221:
222: if (acroForm == null) {
223: return fieldList;
224: }
225:
226: // for now we assume that all root fields have no
227: // children; so we treat Fields as an array
228:
229: // get Fields array
230: PdfArray fields = (PdfArray) (acroForm.getMap()
231: .get(new PdfName("Fields")));
232: if (fields == null) {
233: return fieldList;
234: }
235: List fieldsV = fields.getList();
236:
237: // loop through all fields
238: int fieldsV_n = fieldsV.size();
239: for (int x = 0; x < fieldsV_n; x++) {
240:
241: // get the field object
242: PdfReference fieldRef;
243: try {
244: fieldRef = (PdfReference) (fieldsV.get(x));
245: } catch (ClassCastException e) {
246: throw new com.etymon.pjx.PdfFormatException(
247: "Fields array element is not a reference.");
248: }
249:
250: pjxGetFieldsAddField(manager, fieldList, fieldRef);
251:
252: }
253:
254: return fieldList;
255: }
256: }
257:
258: /**
259: @deprecated
260: */
261: private static void pjxGetFieldsAddField(PdfManager manager,
262: ArrayList fieldList, PdfReference fieldRef)
263: throws IOException, com.etymon.pjx.PdfFormatException {
264:
265: // resolve field reference
266: PdfDictionary field;
267: try {
268: field = (PdfDictionary) (manager
269: .getObjectIndirect(fieldRef));
270: } catch (ClassCastException e) {
271: throw new com.etymon.pjx.PdfFormatException(
272: "Field object is not a dictionary.");
273: }
274:
275: Map fieldHt = field.getMap();
276:
277: // add the field to the list
278: fieldList.add(field);
279:
280: // check if there are any kids
281: PdfArray kids;
282: try {
283: kids = (PdfArray) (manager
284: .getObjectIndirect((PdfObject) (fieldHt
285: .get(new PdfName("Kids")))));
286: } catch (ClassCastException e) {
287: throw new com.etymon.pjx.PdfFormatException(
288: "Kids object is not an array.");
289: }
290:
291: // if there are kids, descend the tree
292: if (kids != null) {
293: List kidsV = kids.getList();
294: int kidsV_n = kidsV.size();
295: for (int x = 0; x < kidsV_n; x++) {
296:
297: // get the field object
298: PdfReference fieldRef2;
299: try {
300: fieldRef2 = (PdfReference) (kidsV.get(x));
301: } catch (ClassCastException e) {
302: throw new com.etymon.pjx.PdfFormatException(
303: "Kids array element is not a reference.");
304: }
305:
306: pjxGetFieldsAddField(manager, fieldList, fieldRef2);
307:
308: }
309: }
310:
311: }
312:
313: /**
314: This method is provided for compatibility with PJ.
315: @throws PdfFormatException
316: @deprecated
317: */
318: public static void pjxUpdateFieldValue(PdfManager manager,
319: PdfDictionary origField, PdfDictionary field, String value)
320: throws IOException, com.etymon.pjx.PdfFormatException {
321:
322: synchronized (manager) {
323:
324: try {
325:
326: Map origFieldHtRO = origField.getMap();
327: HashMap origFieldHt = new HashMap(origFieldHtRO.size());
328: origFieldHt.putAll(origFieldHtRO);
329:
330: Map fieldHt = field.getMap();
331:
332: // store old value for use in search/replace within appeareances stream(s)
333: PdfString oldValue = (PdfString) (fieldHt
334: .get(new PdfName("V")));
335:
336: PdfString valueString = new PdfString(value);
337: origFieldHt.put(new PdfName("V"), valueString);
338: origFieldHt.put(new PdfName("DV"), valueString);
339:
340: // determine quadding
341: PdfInteger q = (PdfInteger) (manager
342: .getObjectIndirect((PdfObject) (fieldHt
343: .get(new PdfName("Q")))));
344: boolean leftJustified = false;
345: boolean centered = false;
346: boolean rightJustified = false;
347: if (q == null) {
348: leftJustified = true;
349: } else {
350: switch (q.getInt()) {
351: case 1:
352: centered = true;
353: break;
354: case 2:
355: rightJustified = true;
356: break;
357: default:
358: leftJustified = true;
359: }
360: }
361:
362: PdfDictionary ap = (PdfDictionary) (manager
363: .getObjectIndirect((PdfObject) (fieldHt
364: .get(new PdfName("AP")))));
365: if (ap != null) {
366: Map apHtReadOnly = ap.getMap();
367: HashMap apHt = new HashMap(apHtReadOnly.size());
368: apHt.putAll(apHtReadOnly);
369: PdfObject apnObj = (PdfObject) (apHt
370: .get(new PdfName("N")));
371: int apnId;
372: PdfReference apnRef;
373: PdfObject apn;
374: PdfDictionary apnDict;
375: byte[] apnBuffer;
376: if (apnObj instanceof PdfReference) {
377: // it's an indirect object
378: apnRef = (PdfReference) apnObj;
379: apnId = apnRef.getObjectNumber();
380: apn = manager.getObjectIndirect(apnRef);
381: } else {
382: // if it's not an indirect object, let's make it indirect
383: apnId = manager.addObject(apnObj);
384: apnRef = new PdfReference(apnId, 0);
385: apHt.put(new PdfName("N"), apnRef);
386: apn = apnObj;
387: }
388:
389: // "/C" = center text
390: // this assumes Courier 10 pt; we can add support
391: // for others if needed.
392: // it also assumes a page width of 8.5"; this also could
393: // be adjusted or read from the document.
394:
395: float rectX1 = 0;
396: float rectX2 = 0;
397: float rectWidth = 0;
398: if (centered) {
399: // adjust RECT
400: PdfArray rect = (PdfArray) (fieldHt
401: .get(new PdfName("Rect")));
402: List rectList = rect.getList();
403: rectX1 = ((PdfNumber) rectList.get(0))
404: .getFloat();
405: rectX2 = ((PdfNumber) rectList.get(2))
406: .getFloat();
407: rectWidth = rectX2 - rectX1;
408: }
409:
410: if ((apn != null) && (apn instanceof PdfStream)) {
411: // if centered: remove any text matrix adjustments.
412: // get page mark operators
413: PjStream apnPj = (PjStream) PjxConvert
414: .toPjObject(apn);
415: Vector pmVector = new StreamParser()
416: .parse(apnPj.flateDecompress());
417: if (oldValue != null) {
418: pjxReplaceTextData(pmVector, oldValue,
419: valueString);
420: }
421: if (centered) {
422: pjxAdjustTextMatrixX(pmVector, rectWidth);
423: }
424: // reconstruct stream from modified pmVector
425: ByteArrayOutputStream baos = new ByteArrayOutputStream();
426: for (int pmX = 0; pmX < pmVector.size(); pmX++) {
427: PageMark pm = (PageMark) (pmVector
428: .elementAt(pmX));
429: try {
430: pm.writePdf(baos);
431: } catch (IOException e) {
432: e.printStackTrace();
433: }
434: }
435: byte[] ba = baos.toByteArray();
436: PjStream temp = new PjStream(apnPj
437: .getStreamDictionary(), ba);
438: manager.setObject(PjxConvert.toPjxObject(temp),
439: apnId);
440: }
441: }
442: } catch (com.etymon.pj.exception.PdfFormatException e) {
443: throw new com.etymon.pjx.PdfFormatException(e
444: .getMessage());
445: } catch (com.etymon.pj.exception.InvalidPdfObjectException f) {
446: throw new com.etymon.pjx.PdfFormatException(f
447: .getMessage());
448: }
449: }
450: }
451:
452: // used exclusively by updateFieldValue()
453: /**
454: @deprecated
455: */
456: private static void pjxReplaceTextData(Vector pmVector,
457: PdfString oldText, PdfString newText)
458: throws com.etymon.pj.exception.PdfFormatException {
459:
460: // this method replaces text data oldS with newS
461:
462: int pmX = pmVector.size();
463:
464: PjString oldTextPj = (PjString) PjxConvert.toPjObject(oldText);
465: PjString newTextPj = (PjString) PjxConvert.toPjObject(newText);
466:
467: // no particular reason for searching backwards; just
468: // because this was adapted from clearTextMatrixX()
469: while (pmX > 0) {
470:
471: pmX--;
472: PageMark pm = (PageMark) (pmVector.elementAt(pmX));
473:
474: if (pm instanceof XTj) {
475: XTj tj = (XTj) pm;
476: if (tj.getText().equals(oldTextPj)) {
477: XTj newTj = new XTj(newTextPj);
478: pmVector.setElementAt(newTj, pmX);
479: }
480: }
481:
482: }
483: }
484:
485: // used exclusively by updateFieldValue()
486: /**
487: @deprecated
488: */
489: private static void pjxAdjustTextMatrixX(Vector pmVector,
490: float rectWidth) {
491: // this method examines the last text matrix in
492: // pmVector and sets the X matrix value in order to
493: // center the text written by the subsequent Tj
494: // operator.
495:
496: int pmX = pmVector.size();
497: float textWidth = 0;
498: float rectCenter = rectWidth / 2;
499:
500: while (pmX > 0) {
501:
502: pmX--;
503: PageMark pm = (PageMark) (pmVector.elementAt(pmX));
504:
505: if (pm instanceof XTj) {
506: XTj tj = (XTj) pm;
507: textWidth = tj.getText().getString().length() * 6;
508: }
509:
510: if (pm instanceof XTm) {
511: float newX = rectCenter - (textWidth / 2);
512: if (newX < 0) {
513: newX = 0;
514: }
515: XTm tm = (XTm) pm;
516: XTm newTm = new XTm(tm.getA(), tm.getB(), tm.getC(), tm
517: .getD(), new PjNumber(newX), tm.getY());
518: pmVector.setElementAt(newTm, pmX);
519: pmX = 0; // Tm found, now we can stop
520: }
521:
522: }
523: }
524:
525: // used exclusively by updateFieldValue()
526: /**
527: @deprecated
528: */
529: private static void pjxClearTextMatrixX(Vector pmVector) {
530: // this method examines the last text matrix in
531: // pmVector and sets the X matrix value to 0.
532:
533: int pmX = pmVector.size();
534:
535: while (pmX > 0) {
536:
537: pmX--;
538: PageMark pm = (PageMark) (pmVector.elementAt(pmX));
539:
540: if (pm instanceof XTm) {
541: XTm tm = (XTm) pm;
542: XTm newTm = new XTm(tm.getA(), tm.getB(), tm.getC(), tm
543: .getD(), PjNumber.ZERO, tm.getY());
544: pmVector.setElementAt(newTm, pmX);
545: pmX = 0; // Tm found, now we can stop
546: }
547:
548: }
549: }
550:
551: /**
552: Returns a clone of a field node such that all inherited
553: attributes of the given field node are made explicit. For
554: example, if the V key is not defined in the given field
555: node, this method ascends the field tree (via the Parent
556: reference) looking for an ancestor node that does contain a
557: value for the V key; if it finds one, it assigns that value
558: in the cloned (returned) field node. This is done for all
559: inheritable attributes.
560: This method is provided for compatibility with PJ. It will
561: be transitioned toward a dedicated field class.
562: @param manager the manager associated with the PDF document.
563: @param d a field node for which inherited attributes are to
564: be retrieved.
565: @return a cloned copy of the given field node with actual
566: values substituted for all inherited attributes.
567: @exception PdfFormatException
568: @deprecated
569: */
570: public static PdfDictionary pjxInheritFieldAttributes(
571: PdfManager manager, PdfDictionary d) throws IOException,
572: com.etymon.pjx.PdfFormatException {
573: synchronized (manager) {
574: try {
575: PjDictionary node = (PjDictionary) PjxConvert
576: .toPjObject(d);
577: PjDictionary newNode;
578: try {
579: newNode = (PjDictionary) (node.clone());
580: } catch (CloneNotSupportedException e) {
581: throw new com.etymon.pj.exception.InvalidPdfObjectException(
582: e.getMessage());
583: }
584: Hashtable ht = newNode.getHashtable();
585: PjObject parentRef = (PjObject) (newNode.getHashtable()
586: .get(PjName.PARENT));
587: while (parentRef != null) {
588: PjObject parentObj = PjxConvert.toPjObject(manager
589: .getObjectIndirect(PjxConvert
590: .toPjxObject(parentRef)));
591: if (!(parentObj instanceof PjDictionary)) {
592: throw new com.etymon.pj.exception.InvalidPdfObjectException(
593: "Ancestor of field node is not a dictionary.");
594: }
595: PjDictionary parent = (PjDictionary) parentObj;
596: pjxInheritFieldAttributesCollapse(PjName.FT, ht,
597: newNode, parent);
598: pjxInheritFieldAttributesCollapse(PjName.V, ht,
599: newNode, parent);
600: pjxInheritFieldAttributesCollapse(PjName.DV, ht,
601: newNode, parent);
602: pjxInheritFieldAttributesCollapse(PjName.FF, ht,
603: newNode, parent);
604: pjxInheritFieldAttributesCollapse(PjName.DR, ht,
605: newNode, parent);
606: pjxInheritFieldAttributesCollapse(PjName.DA, ht,
607: newNode, parent);
608: pjxInheritFieldAttributesCollapse(PjName.Q, ht,
609: newNode, parent);
610: pjxInheritFieldAttributesCollapse(PjName.OPT, ht,
611: newNode, parent);
612: pjxInheritFieldAttributesCollapse(PjName.TOPINDEX,
613: ht, newNode, parent);
614: pjxInheritFieldAttributesCollapse(PjName.MAXLEN,
615: ht, newNode, parent);
616: parentRef = (PjObject) (parent.getHashtable()
617: .get(PjName.PARENT));
618: }
619: return (PdfDictionary) PjxConvert.toPjxObject(newNode);
620: } catch (com.etymon.pj.exception.PdfFormatException e) {
621: throw new com.etymon.pjx.PdfFormatException(e
622: .getMessage());
623: } catch (com.etymon.pj.exception.InvalidPdfObjectException f) {
624: throw new com.etymon.pjx.PdfFormatException(f
625: .getMessage());
626: }
627: }
628: }
629:
630: // used exclusively by inheritFieldAttributes()
631: /**
632: @deprecated
633: */
634: private static void pjxInheritFieldAttributesCollapse(PjName name,
635: Hashtable ht, PjDictionary newNode, PjDictionary parent) {
636:
637: if (ht.get(name) == null) {
638: Object obj = parent.getHashtable().get(name);
639: if (obj != null) {
640: ht.put(name, obj);
641: }
642: }
643: }
644:
645: }
|