001: /*
002: * $Id: GlyfCompound.java,v 1.2 2007/12/20 18:33:30 rbair Exp $
003: *
004: * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
005: * Santa Clara, California 95054, U.S.A. All rights reserved.
006: *
007: * This library is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU Lesser General Public
009: * License as published by the Free Software Foundation; either
010: * version 2.1 of the License, or (at your option) any later version.
011: *
012: * This library is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this library; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
020: */
021:
022: package com.sun.pdfview.font.ttf;
023:
024: import java.nio.ByteBuffer;
025: import java.util.ArrayList;
026: import java.util.List;
027:
028: /**
029: * A single simple glyph in a pdf font.
030: */
031: public class GlyfCompound extends Glyf {
032: /** flags */
033: private static final int ARG_1_AND_2_ARE_WORDS = 0x1;
034: private static final int ARGS_ARE_XY_VALUES = 0x2;
035: private static final int ROUND_XY_TO_GRID = 0x4;
036: private static final int WE_HAVE_A_SCALE = 0x8;
037: private static final int MORE_COMPONENTS = 0x20;
038: private static final int WE_HAVE_AN_X_AND_Y_SCALE = 0x40;
039: private static final int WE_HAVE_A_TWO_BY_TWO = 0x80;
040: private static final int WE_HAVE_INSTRUCTIONS = 0x100;
041: private static final int USE_MY_METRICS = 0x200;
042: private static final int OVERLAP_COMPOUND = 0x400;
043:
044: /** the flags for each compound glyph */
045: private GlyfComponent[] components;
046:
047: /** the instructions for the compound as a whole */
048: private byte[] instructions;
049:
050: /**
051: * Creates a new instance of a simple glyf
052: */
053: protected GlyfCompound() {
054: }
055:
056: /**
057: * Set the data for this glyf.
058: */
059: @Override
060: public void setData(ByteBuffer data) {
061: // int pos = data.position();
062: // byte[] prdata = new byte[data.remaining()];
063: // data.get(prdata);
064: // HexDump.printData(prdata);
065: // data.position(pos);
066:
067: // read the contour end points
068: List comps = new ArrayList();
069: GlyfComponent cur = null;
070: boolean hasInstructions = false;
071:
072: do {
073: cur = new GlyfComponent();
074: cur.flags = data.getShort();
075: cur.glyphIndex = data.getShort();
076:
077: // read either e/f or matching points, as shorts or bytes...
078: if (((cur.flags & ARG_1_AND_2_ARE_WORDS) != 0)
079: && ((cur.flags & ARGS_ARE_XY_VALUES) != 0)) {
080: cur.e = data.getShort();
081: cur.f = data.getShort();
082: } else if (!((cur.flags & ARG_1_AND_2_ARE_WORDS) != 0)
083: && ((cur.flags & ARGS_ARE_XY_VALUES) != 0)) {
084: cur.e = (float) data.get();
085: cur.f = (float) data.get();
086: } else if (((cur.flags & ARG_1_AND_2_ARE_WORDS) != 0)
087: && !((cur.flags & ARGS_ARE_XY_VALUES) != 0)) {
088: cur.compoundPoint = data.getShort();
089: cur.componentPoint = data.getShort();
090: } else {
091: cur.compoundPoint = data.get();
092: cur.componentPoint = data.get();
093: }
094:
095: // read the linear transform
096: if ((cur.flags & WE_HAVE_A_SCALE) != 0) {
097: cur.a = (float) data.getShort() / (float) (1 << 14);
098: cur.d = cur.a;
099: } else if ((cur.flags & WE_HAVE_AN_X_AND_Y_SCALE) != 0) {
100: cur.a = (float) data.getShort() / (float) (1 << 14);
101: cur.d = (float) data.getShort() / (float) (1 << 14);
102: } else if ((cur.flags & WE_HAVE_A_TWO_BY_TWO) != 0) {
103: cur.a = (float) data.getShort() / (float) (1 << 14);
104: cur.b = (float) data.getShort() / (float) (1 << 14);
105: cur.c = (float) data.getShort() / (float) (1 << 14);
106: cur.d = (float) data.getShort() / (float) (1 << 14);
107: }
108:
109: if ((cur.flags & WE_HAVE_INSTRUCTIONS) != 0) {
110: hasInstructions = true;
111: }
112:
113: comps.add(cur);
114: } while ((cur.flags & MORE_COMPONENTS) != 0);
115:
116: GlyfComponent[] componentArray = new GlyfComponent[comps.size()];
117: comps.toArray(componentArray);
118: setComponents(componentArray);
119:
120: byte[] instr = null;
121: if (hasInstructions) {
122: // read the instructions
123: short numInstructions = data.getShort();
124: instr = new byte[numInstructions];
125: for (int i = 0; i < instr.length; i++) {
126: instr[i] = data.get();
127: }
128: } else {
129: instr = new byte[0];
130: }
131: setInstructions(instr);
132: }
133:
134: /**
135: * Get the data in this glyf as a byte buffer. Not implemented.
136: */
137: @Override
138: public ByteBuffer getData() {
139: ByteBuffer buf = super .getData();
140:
141: // don't flip the buffer, since it may be used by subclasses
142: return buf;
143: }
144:
145: /**
146: * Get the length of this glyf. Not implemented.
147: */
148: @Override
149: public short getLength() {
150:
151: // start with the length of the superclass
152: short length = super .getLength();
153: return length;
154: }
155:
156: /**
157: * Get the number of components in this compound
158: */
159: public int getNumComponents() {
160: return components.length;
161: }
162:
163: /**
164: * Get a given flag
165: */
166: public short getFlag(int index) {
167: return components[index].flags;
168: }
169:
170: /**
171: * Get the glyf index for a given glyf
172: */
173: public short getGlyphIndex(int index) {
174: return components[index].glyphIndex;
175: }
176:
177: /**
178: * Get the base affine transform. This is based on a whacy formula
179: * defined in the true type font spec.
180: */
181: public double[] getTransform(int index) {
182: GlyfComponent gc = components[index];
183:
184: float m = (float) Math.max(Math.abs(gc.a), Math.abs(gc.b));
185: if (Math.abs(Math.abs(gc.a) - Math.abs(gc.c)) < (33 / 65536)) {
186: m *= 2;
187: }
188:
189: float n = (float) Math.max(Math.abs(gc.c), Math.abs(gc.d));
190: if (Math.abs(Math.abs(gc.c) - Math.abs(gc.d)) < (33 / 65536)) {
191: n *= 2;
192: }
193:
194: float e = m * gc.e;
195: float f = n * gc.f;
196:
197: return new double[] { gc.a, gc.b, gc.c, gc.d, e, f };
198: }
199:
200: /**
201: * Get the point in the compound glyph to match
202: */
203: public int getCompoundPoint(int index) {
204: return components[index].compoundPoint;
205: }
206:
207: /**
208: * Get the point in the component glyph to match
209: */
210: public int getComponentPoint(int index) {
211: return components[index].componentPoint;
212: }
213:
214: /**
215: * Determine whether args 1 and 2 are words or bytes
216: */
217: public boolean argsAreWords(int index) {
218: return ((getFlag(index) & ARG_1_AND_2_ARE_WORDS) != 0);
219: }
220:
221: /**
222: * Determine whether args 1 and 2 are xy values or point indices
223: */
224: public boolean argsAreXYValues(int index) {
225: return ((getFlag(index) & ARGS_ARE_XY_VALUES) != 0);
226: }
227:
228: /**
229: * Determine whether to round XY values to the grid
230: */
231: public boolean roundXYToGrid(int index) {
232: return ((getFlag(index) & ROUND_XY_TO_GRID) != 0);
233: }
234:
235: /**
236: * Determine whether there is a simple scale
237: */
238: public boolean hasAScale(int index) {
239: return ((getFlag(index) & WE_HAVE_A_SCALE) != 0);
240: }
241:
242: /**
243: * Determine whether there are more components left to read
244: */
245: protected boolean moreComponents(int index) {
246: return ((getFlag(index) & MORE_COMPONENTS) != 0);
247: }
248:
249: /**
250: * Determine whether there are separate scales on X and Y
251: */
252: protected boolean hasXYScale(int index) {
253: return ((getFlag(index) & WE_HAVE_AN_X_AND_Y_SCALE) != 0);
254: }
255:
256: /**
257: * Determine whether there is a 2x2 transform
258: */
259: protected boolean hasTwoByTwo(int index) {
260: return ((getFlag(index) & WE_HAVE_A_TWO_BY_TWO) != 0);
261: }
262:
263: /**
264: * Determine whether there are instructions
265: */
266: protected boolean hasInstructions(int index) {
267: return ((getFlag(index) & WE_HAVE_INSTRUCTIONS) != 0);
268: }
269:
270: /**
271: * Use the metrics of this component for the compound
272: */
273: public boolean useMetrics(int index) {
274: return ((getFlag(index) & USE_MY_METRICS) != 0);
275: }
276:
277: /**
278: * This component overlaps the existing compound
279: */
280: public boolean overlapCompound(int index) {
281: return ((getFlag(index) & OVERLAP_COMPOUND) != 0);
282: }
283:
284: /**
285: * Set the components
286: */
287: void setComponents(GlyfComponent[] components) {
288: this .components = components;
289: }
290:
291: /**
292: * Get the number of instructions
293: */
294: public short getNumInstructions() {
295: return (short) instructions.length;
296: }
297:
298: /**
299: * Get a given instruction
300: */
301: public byte getInstruction(int index) {
302: return instructions[index];
303: }
304:
305: /**
306: * Set the instructions
307: */
308: protected void setInstructions(byte[] instructions) {
309: this .instructions = instructions;
310: }
311:
312: /**
313: * The record for a single component of this compound glyph
314: */
315: class GlyfComponent {
316: /** flags */
317: short flags;
318:
319: /** the index of the component glyf */
320: short glyphIndex;
321:
322: /** the points to match */
323: int compoundPoint;
324: int componentPoint;
325:
326: /** affine transform of this component */
327: float a = 1.0f;
328: float b = 0.0f;
329: float c = 0.0f;
330: float d = 1.0f;
331: float e = 0.0f;
332: float f = 0.0f;
333: }
334: }
|