KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > fop > render > afp > modca > PresentationTextData


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17
18 /* $Id: PresentationTextData.java 426576 2006-07-28 15:44:37Z jeremias $ */
19
20 package org.apache.fop.render.afp.modca;
21
22 import java.awt.Color JavaDoc;
23 import java.io.ByteArrayOutputStream JavaDoc;
24 import java.io.IOException JavaDoc;
25 import java.io.OutputStream JavaDoc;
26
27 import org.apache.fop.render.afp.tools.BinaryUtils;
28
29 /**
30  * Presentation text data contains the graphic characters and the control
31  * sequences necessary to position the characters within the object space. The
32  * data consists of: - graphic characters to be presented - control sequences
33  * that position them - modal control sequences that adjust the positions by
34  * small amounts - other functions causing text to be presented with differences
35  * in appearance.
36  *
37  * The graphic characters are expected to conform to a coded font representation
38  * so that they can be translated from the code point in the object data to the
39  * character in the coded font. The units of measure for linear displacements
40  * are derived from the PresentationTextDescriptor or from the hierarchical
41  * defaults.
42  *
43  * In addition to graphic character code points, Presentation Text data can
44  * contain embedded control sequences. These are strings of two or more bytes
45  * which signal an alternate mode of processing for the content of the current
46  * Presentation Text data.
47  *
48  */

49 public class PresentationTextData extends AbstractAFPObject {
50
51     /**
52      * The maximum size of the presentation text data.
53      */

54     private static final int MAX_SIZE = 8192;
55
56     /**
57      * The afp data relating to this presentaion text data.
58      */

59     private ByteArrayOutputStream JavaDoc _baos = new ByteArrayOutputStream JavaDoc(1024);
60
61     /**
62      * The current x coordinate.
63      */

64     private int _currentXCoordinate = -1;
65
66     /**
67      * The current y cooridnate
68      */

69     private int _currentYCoordinate = -1;
70
71     /**
72      * The current font
73      */

74     private String JavaDoc _currentFont = "";
75
76     /**
77      * The current orientation
78      */

79     private int _currentOrientation = 0;
80
81     /**
82      * The current color
83      */

84     private Color JavaDoc _currentColor = new Color JavaDoc(0, 0, 0);
85
86     /**
87      * The current variable space increment
88      */

89     private int _currentVariableSpaceCharacterIncrement = 0;
90
91     /**
92      * The current inter character adjustment
93      */

94     private int _currentInterCharacterAdjustment = 0;
95
96     /**
97      * Default constructor for the PresentationTextData.
98      */

99     public PresentationTextData() {
100
101         this(false);
102
103     }
104
105     /**
106      * Constructor for the PresentationTextData, the boolean flag indicate
107      * whether the control sequence prefix should be set to indicate the start
108      * of a new control sequence.
109      *
110      * @param controlInd
111      * The control sequence indicator.
112      */

113     public PresentationTextData(boolean controlInd) {
114
115         _baos.write(new byte[] { 0x5A, // Structured field identifier
116
0x00, // Record length byte 1
117
0x00, // Record length byte 2
118
(byte) 0xD3, // PresentationTextData identifier byte 1
119
(byte) 0xEE, // PresentationTextData identifier byte 2
120
(byte) 0x9B, // PresentationTextData identifier byte 3
121
0x00, // Flag
122
0x00, // Reserved
123
0x00, // Reserved
124
}, 0, 9);
125
126         if (controlInd) {
127             _baos.write(new byte[] { 0x2B, (byte) 0xD3 }, 0, 2);
128         }
129
130     }
131
132     /**
133      * The Set Coded Font Local control sequence activates a coded font and
134      * specifies the character attributes to be used. This is a modal control
135      * sequence.
136      *
137      * @param font
138      * The font local identifier.
139      * @param afpdata
140      * The output stream to which data should be written.
141      */

142     private void setCodedFont(byte font, ByteArrayOutputStream JavaDoc afpdata) {
143
144         // Avoid unnecessary specification of the font
145
if (String.valueOf(font).equals(_currentFont)) {
146             return;
147         } else {
148             _currentFont = String.valueOf(font);
149         }
150
151         afpdata.write(new byte[] { 0x03, (byte) 0xF1, font, }, 0, 3);
152
153     }
154
155     /**
156      * Establishes the current presentation position on the baseline at a new
157      * I-axis coordinate, which is a specified number of measurement units from
158      * the B-axis. There is no change to the current B-axis coordinate.
159      *
160      * @param coordinate
161      * The coordinate for the inline move.
162      * @param afpdata
163      * The output stream to which data should be written.
164      */

165     private void absoluteMoveInline(int coordinate,
166         ByteArrayOutputStream JavaDoc afpdata) {
167
168         byte[] b = BinaryUtils.convert(coordinate, 2);
169
170         afpdata.write(new byte[] { 0x04, (byte) 0xC7, b[0], b[1], }, 0, 4);
171
172         _currentXCoordinate = coordinate;
173
174     }
175
176     /**
177      * Establishes the baseline and the current presentation position at a new
178      * B-axis coordinate, which is a specified number of measurement units from
179      * the I-axis. There is no change to the current I-axis coordinate.
180      *
181      * @param coordinate
182      * The coordinate for the baseline move.
183      * @param afpdata
184      * The output stream to which data should be written.
185      */

186     private void absoluteMoveBaseline(int coordinate,
187         ByteArrayOutputStream JavaDoc afpdata) {
188
189         byte[] b = BinaryUtils.convert(coordinate, 2);
190
191         afpdata.write(new byte[] { 0x04, (byte) 0xD3, b[0], b[1], }, 0, 4);
192
193         _currentYCoordinate = coordinate;
194
195     }
196
197     /**
198      * The Transparent Data control sequence contains a sequence of code points
199      * that are presented without a scan for embedded control sequences.
200      *
201      * @param data
202      * The text data to add.
203      * @param afpdata
204      * The output stream to which data should be written.
205      */

206     private void addTransparentData(byte[] data, ByteArrayOutputStream JavaDoc afpdata) {
207
208         // Calculate the length
209
int l = data.length + 2;
210
211         if (l > 255) {
212             // Check that we are not exceeding the maximum length
213
throw new IllegalArgumentException JavaDoc(
214                 "Transparent data is longer than 253 bytes: " + data);
215         }
216
217         afpdata.write(new byte[] { BinaryUtils.convert(l)[0], (byte) 0xDB, },
218             0, 2);
219
220         afpdata.write(data, 0, data.length);
221
222     }
223
224     /**
225      * Draws a line of specified length and specified width in the B-direction
226      * from the current presentation position. The location of the current
227      * presentation position is unchanged.
228      *
229      * @param length
230      * The length of the rule.
231      * @param width
232      * The width of the rule.
233      * @param afpdata
234      * The output stream to which data should be written.
235      */

236     private void drawBaxisRule(int length, int width,
237         ByteArrayOutputStream JavaDoc afpdata) {
238
239         afpdata.write(new byte[] { 0x07, // Length
240
(byte) 0xE7, // Type
241
}, 0, 2);
242
243         // Rule length
244
byte[] data1 = BinaryUtils.shortToByteArray((short) length);
245         afpdata.write(data1, 0, data1.length);
246         // Rule width
247
byte[] data2 = BinaryUtils.shortToByteArray((short) width);
248         afpdata.write(data2, 0, data2.length);
249         // Rule width fraction
250
afpdata.write(0x00);
251
252     }
253
254     /**
255      * Draws a line of specified length and specified width in the I-direction
256      * from the current presentation position. The location of the current
257      * presentation position is unchanged.
258      *
259      * @param length
260      * The length of the rule.
261      * @param width
262      * The width of the rule.
263      * @param afpdata
264      * The output stream to which data should be written.
265      */

266     private void drawIaxisRule(int length, int width,
267         ByteArrayOutputStream JavaDoc afpdata) {
268
269         afpdata.write(new byte[] { 0x07, // Length
270
(byte) 0xE5, // Type
271
}, 0, 2);
272
273         // Rule length
274
byte[] data1 = BinaryUtils.shortToByteArray((short) length);
275         afpdata.write(data1, 0, data1.length);
276         // Rule width
277
byte[] data2 = BinaryUtils.shortToByteArray((short) width);
278         afpdata.write(data2, 0, data2.length);
279         // Rule width fraction
280
afpdata.write(0x00);
281
282     }
283
284     /**
285      * Create the presentation text data for the byte array of data.
286      *
287      * @param fontNumber
288      * The font resource identifier.
289      * @param x
290      * The x coordinate for the text data.
291      * @param y
292      * The y coordinate for the text data.
293      * @param orientation
294      * The orientation of the text data.
295      * @param col
296      * The text color.
297      * @param vsci
298      * The variable space character increment.
299      * @param ica
300      * The inter character adjustment.
301      * @param data
302      * The text data to be created.
303      * @throws MaximumSizeExceededException
304      */

305     public void createTextData(int fontNumber, int x, int y, int orientation,
306         Color JavaDoc col, int vsci, int ica, byte[] data)
307         throws MaximumSizeExceededException {
308
309         ByteArrayOutputStream JavaDoc afpdata = new ByteArrayOutputStream JavaDoc();
310
311         if (_currentOrientation != orientation) {
312             setTextOrientation(orientation, afpdata);
313             _currentOrientation = orientation;
314             _currentXCoordinate = -1;
315             _currentYCoordinate = -1;
316         }
317
318         // Avoid unnecessary specification of the Y co-ordinate
319
if (y != _currentYCoordinate) {
320             absoluteMoveBaseline(y, afpdata);
321             _currentXCoordinate = -1;
322         }
323
324         // Avoid unnecessary specification of the X co-ordinate
325
if (x != _currentXCoordinate) {
326             absoluteMoveInline(x, afpdata);
327         }
328
329         // Avoid unnecessary specification of the variable space increment
330
if (vsci != _currentVariableSpaceCharacterIncrement) {
331             setVariableSpaceCharacterIncrement(vsci, afpdata);
332             _currentVariableSpaceCharacterIncrement = vsci;
333         }
334
335         // Avoid unnecessary specification of the inter character adjustment
336
if (ica != _currentInterCharacterAdjustment) {
337             setInterCharacterAdjustment(ica, afpdata);
338             _currentInterCharacterAdjustment = ica;
339         }
340
341         // Avoid unnecessary specification of the text color
342
if (!col.equals(_currentColor)) {
343             setExtendedTextColor(col, afpdata);
344             _currentColor = col;
345         }
346
347         setCodedFont(BinaryUtils.convert(fontNumber)[0], afpdata);
348         addTransparentData(data, afpdata);
349         _currentXCoordinate = -1;
350
351         int s = afpdata.size();
352
353         if (_baos.size() + s > MAX_SIZE) {
354             _currentXCoordinate = -1;
355             _currentYCoordinate = -1;
356             throw new MaximumSizeExceededException();
357         }
358
359         byte[] outputdata = afpdata.toByteArray();
360         _baos.write(outputdata, 0, outputdata.length);
361
362     }
363
364     /**
365      * Drawing of lines using the starting and ending coordinates, thickness and
366      * colour arguments.
367      *
368      * @param x1
369      * The starting X coordinate.
370      * @param y1
371      * The starting Y coordinate.
372      * @param x2
373      * The ending X coordinate.
374      * @param y2
375      * The ending Y coordinate.
376      * @param thickness
377      * The line thickness.
378      * @param orientation
379      * The orientation of the text data.
380      * @param col
381      * The text color.
382      */

383     public void createLineData(int x1, int y1, int x2, int y2, int thickness,
384         int orientation, Color JavaDoc col) throws MaximumSizeExceededException {
385
386         ByteArrayOutputStream JavaDoc afpdata = new ByteArrayOutputStream JavaDoc();
387
388         if (_currentOrientation != orientation) {
389             setTextOrientation(orientation, afpdata);
390             _currentOrientation = orientation;
391         }
392
393         // Avoid unnecessary specification of the Y coordinate
394
if (y1 != _currentYCoordinate) {
395             absoluteMoveBaseline(y1, afpdata);
396         }
397
398         // Avoid unnecessary specification of the X coordinate
399
if (x1 != _currentXCoordinate) {
400             absoluteMoveInline(x1, afpdata);
401         }
402
403         if (!col.equals(_currentColor)) {
404             setExtendedTextColor(col, afpdata);
405             _currentColor = col;
406         }
407
408         if (y1 == y2) {
409             drawIaxisRule(x2 - x1, thickness, afpdata);
410         } else if (x1 == x2) {
411             drawBaxisRule(y2 - y1, thickness, afpdata);
412         } else {
413             return;
414         }
415
416         int s = afpdata.size();
417
418         if (_baos.size() + s > MAX_SIZE) {
419             _currentXCoordinate = -1;
420             _currentYCoordinate = -1;
421             throw new MaximumSizeExceededException();
422         }
423
424         byte[] outputdata = afpdata.toByteArray();
425         _baos.write(outputdata, 0, outputdata.length);
426
427     }
428
429     /**
430      * The Set Text Orientation control sequence establishes the I-direction and
431      * B-direction for the subsequent text. This is a modal control sequence.
432      *
433      * Semantics: This control sequence specifies the I-axis and B-axis
434      * orientations with respect to the Xp-axis for the current Presentation
435      * Text object. The orientations are rotational values expressed in degrees
436      * and minutes.
437      *
438      * @param orientation
439      * The text orientation (0,90, 180, 270).
440      * @param afpdata
441      * The output stream to which data should be written.
442      */

443     private void setTextOrientation(int orientation,
444         ByteArrayOutputStream JavaDoc afpdata) {
445
446         afpdata.write(new byte[] { 0x06, (byte) 0xF7, }, 0, 2);
447
448         switch (orientation) {
449             case 90:
450                 afpdata.write(0x2D);
451                 afpdata.write(0x00);
452                 afpdata.write(0x5A);
453                 afpdata.write(0x00);
454                 break;
455             case 180:
456                 afpdata.write(0x5A);
457                 afpdata.write(0x00);
458                 afpdata.write(0x87);
459                 afpdata.write(0x00);
460                 break;
461             case 270:
462                 afpdata.write(0x87);
463                 afpdata.write(0x00);
464                 afpdata.write(0x00);
465                 afpdata.write(0x00);
466                 break;
467             default:
468                 afpdata.write(0x00);
469                 afpdata.write(0x00);
470                 afpdata.write(0x2D);
471                 afpdata.write(0x00);
472                 break;
473         }
474
475     }
476
477     /**
478      * The Set Extended Text Color control sequence specifies a color value and
479      * defines the color space and encoding for that value. The specified color
480      * value is applied to foreground areas of the text presentation space.
481      * This is a modal control sequence.
482      *
483      * @param col
484      * The color to be set.
485      * @param afpdata
486      * The output stream to which data should be written.
487      */

488     private void setExtendedTextColor(Color JavaDoc col,
489         ByteArrayOutputStream JavaDoc afpdata) {
490
491         afpdata.write(new byte[] {
492               15 // Control sequence length
493
, (byte)0x81 // Control sequence function type
494
, 0x00 // Reserved; must be zero
495
, 0x01 // Color space - 0x01 = RGB
496
, 0x00 // Reserved; must be zero
497
, 0x00 // Reserved; must be zero
498
, 0x00 // Reserved; must be zero
499
, 0x00 // Reserved; must be zero
500
, 8 // Number of bits in component 1
501
, 8 // Number of bits in component 2
502
, 8 // Number of bits in component 3
503
, 0 // Number of bits in component 4
504
, (byte)(col.getRed()) // Red intensity
505
, (byte)(col.getGreen()) // Green intensity
506
, (byte)(col.getBlue()) // Blue intensity
507
}, 0, 15);
508
509     }
510
511     /**
512      * //TODO
513      * This is a modal control sequence.
514      *
515      * @param incr
516      * The increment to be set.
517      * @param afpdata
518      * The output stream to which data should be written.
519      */

520     private void setVariableSpaceCharacterIncrement(int incr,
521         ByteArrayOutputStream JavaDoc afpdata) {
522
523         byte[] b = BinaryUtils.convert(incr, 2);
524
525         afpdata.write(new byte[] {
526               4 // Control sequence length
527
, (byte)0xC5 // Control sequence function type
528
, b[0]
529             , b[1]
530         }, 0, 4);
531
532     }
533
534     /**
535      * //TODO
536      * This is a modal control sequence.
537      *
538      * @param incr
539      * The increment to be set.
540      * @param afpdata
541      * The output stream to which data should be written.
542      */

543     private void setInterCharacterAdjustment(int incr,
544         ByteArrayOutputStream JavaDoc afpdata) {
545
546         byte[] b = BinaryUtils.convert(Math.abs(incr), 2);
547
548         afpdata.write(new byte[] {
549               5 // Control sequence length
550
, (byte)0xC3 // Control sequence function type
551
, b[0]
552             , b[1]
553             , (byte)(incr >= 0 ? 0 : 1) // Direction
554
}, 0, 5);
555
556     }
557
558     /**
559      * Accessor method to write the AFP datastream for
560      * the text data.
561      * @param os The stream to write to
562      * @throws java.io.IOException
563      */

564     public void writeDataStream(OutputStream JavaDoc os)
565         throws IOException JavaDoc {
566
567         byte[] data = _baos.toByteArray();
568         byte[] size = BinaryUtils.convert(data.length - 1, 2);
569         data[1] = size[0];
570         data[2] = size[1];
571
572         os.write(data);
573
574     }
575
576     /**
577      * A control sequence is a sequence of bytes that specifies a control
578      * function. A control sequence consists of a control sequence introducer
579      * and zero or more parameters. The control sequence can extend multiple
580      * presentation text data objects, but must eventually be terminated. This
581      * method terminates the control sequence.
582      *
583      * @throws MaximumSizeExceededException
584      */

585     public void endControlSequence() throws MaximumSizeExceededException {
586
587         byte[] data = new byte[2];
588         data[0] = 0x02;
589         data[1] = (byte) 0xF8;
590
591         if (data.length + _baos.size() > MAX_SIZE) {
592             throw new MaximumSizeExceededException();
593         }
594
595         _baos.write(data, 0, data.length);
596
597     }
598
599 }
Popular Tags