001: /*
002: Copyright © 2006,2007 Stefano Chizzolini. http://clown.stefanochizzolini.it
003:
004: Contributors:
005: * Stefano Chizzolini (original code developer, http://www.stefanochizzolini.it):
006: contributed code is Copyright © 2006,2007 by Stefano Chizzolini.
007:
008: This file should be part of the source code distribution of "PDF Clown library"
009: (the Program): see the accompanying README files for more info.
010:
011: This Program is free software; you can redistribute it and/or modify it under
012: the terms of the GNU General Public License as published by the Free Software
013: Foundation; either version 2 of the License, or (at your option) any later version.
014:
015: This Program is distributed in the hope that it will be useful, but WITHOUT ANY
016: WARRANTY, either expressed or implied; without even the implied warranty of
017: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the License for more details.
018:
019: You should have received a copy of the GNU General Public License along with this
020: Program (see README files); if not, go to the GNU website (http://www.gnu.org/).
021:
022: Redistribution and use, with or without modification, are permitted provided that such
023: redistributions retain the above copyright notice, license and disclaimer, along with
024: this list of conditions.
025: */
026:
027: package it.stefanochizzolini.clown.objects;
028:
029: import it.stefanochizzolini.clown.files.File;
030:
031: import java.util.regex.Matcher;
032: import java.util.regex.Pattern;
033:
034: /**
035: PDF literal string object [PDF:1.6:3.2.3].
036: */
037: /*
038: NOTE: Text strings meaning is tied to their applicable encoding:
039: * text strings inside the document's content streams are to be intended in accordance to
040: the encoding of the currently-selected font;
041: * text strings outside the document's content streams can be represented either by
042: PDFDocEncoding [PDF:1.6:D] or Unicode encoding [PDF:1.6:3.8.1].
043: */
044: /*
045: NOTE: As literal objects are textual, their characters are unescaped when deserialized,
046: whilst escaped when serialized only.
047: */
048: public class PdfLiteral extends PdfAtomicObject<String> implements
049: IPdfString {
050: // <static>
051: // <fields>
052: /*
053: NOTE: Literal lexical conventions prescribe that the following reserved characters
054: are to be escaped when placed inside strings' character sequences:
055: - \n Line feed (LF)
056: - \r Carriage return (CR)
057: - \t Horizontal tab (HT)
058: - \b Backspace (BS)
059: - \f Form feed (FF)
060: - \( Left parenthesis
061: - \) Right parenthesis
062: - \\ Backslash
063: */
064: private static final Pattern UnescapedPattern = Pattern
065: .compile("[\\n\\r\\t\\u0008\\f\\(\\)\\\\]");
066:
067: // </fields>
068:
069: // <interface>
070: // <public>
071: /**
072: Converts a string value to a PDF-formatted string literal.
073: */
074: public static String toPdf(String value) {
075: /*
076: NOTE: Any reserved character MUST be escaped.
077: */
078: StringBuilder buffer = new StringBuilder("(");
079:
080: int index = 0;
081: Matcher unescapedMatcher = UnescapedPattern.matcher(value);
082: while (unescapedMatcher.find()) {
083: int start = unescapedMatcher.start();
084: if (start > index) {
085: buffer.append(value.substring(index, start));
086: }
087:
088: buffer.append('\\');
089: char unescapedChar = unescapedMatcher.group(0).charAt(0);
090: switch (unescapedChar) {
091: case '\n':
092: buffer.append('n');
093: break;
094: case '\r':
095: buffer.append('r');
096: break;
097: case '\t':
098: buffer.append('t');
099: break;
100: case '\b':
101: buffer.append('b');
102: break;
103: case '\f':
104: buffer.append('f');
105: break;
106: case '(':
107: case ')':
108: case '\\':
109: buffer.append(unescapedChar);
110: break;
111: }
112:
113: index = unescapedMatcher.end();
114: }
115: if (index < value.length()) {
116: buffer.append(value.substring(index));
117: }
118:
119: buffer.append(")");
120:
121: return buffer.toString();
122: }
123:
124: // </public>
125: // </interface>
126: // </static>
127:
128: // <dynamic>
129: // <constructors>
130: public PdfLiteral() {
131: }
132:
133: public PdfLiteral(String value) {
134: setValue(value);
135: }
136:
137: // </constructors>
138:
139: // <interface>
140: // <public>
141: @Override
142: public Object clone(File context) {
143: // Shallow copy.
144: PdfLiteral clone = (PdfLiteral) super .clone();
145:
146: // Deep copy.
147: /* NOTE: No mutable object to be cloned. */
148:
149: return clone;
150: }
151:
152: @Override
153: public String toPdf() {
154: return PdfLiteral.toPdf(getValue());
155: }
156:
157: // <IPdfString>
158: public String getStringValue() {
159: return getValue();
160: }
161:
162: public void setStringValue(String value) {
163: setValue(value);
164: }
165: // </IPdfString>
166: // </public>
167: // </interface>
168: // </dynamic>
169: // </class>
170: }
|