001: /* ====================================================================
002: Licensed to the Apache Software Foundation (ASF) under one or more
003: contributor license agreements. See the NOTICE file distributed with
004: this work for additional information regarding copyright ownership.
005: The ASF licenses this file to You under the Apache License, Version 2.0
006: (the "License"); you may not use this file except in compliance with
007: the License. You may obtain a copy of the License at
008:
009: http://www.apache.org/licenses/LICENSE-2.0
010:
011: Unless required by applicable law or agreed to in writing, software
012: distributed under the License is distributed on an "AS IS" BASIS,
013: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: See the License for the specific language governing permissions and
015: limitations under the License.
016: ==================================================================== */
017:
018: package org.apache.poi.hwpf.sprm;
019:
020: import org.apache.poi.hwpf.usermodel.CharacterProperties;
021: import org.apache.poi.hwpf.usermodel.DateAndTime;
022: import org.apache.poi.hwpf.usermodel.BorderCode;
023: import org.apache.poi.hwpf.usermodel.ShadingDescriptor;
024: import org.apache.poi.hwpf.model.StyleSheet;
025: import org.apache.poi.util.LittleEndian;
026:
027: public class CharacterSprmUncompressor {
028: public CharacterSprmUncompressor() {
029: }
030:
031: public static CharacterProperties uncompressCHP(
032: CharacterProperties parent, byte[] grpprl, int offset) {
033: CharacterProperties newProperties = null;
034: try {
035: newProperties = (CharacterProperties) parent.clone();
036: } catch (CloneNotSupportedException cnse) {
037: throw new RuntimeException(
038: "There is no way this exception should happen!!");
039: }
040: SprmIterator sprmIt = new SprmIterator(grpprl, offset);
041:
042: while (sprmIt.hasNext()) {
043: SprmOperation sprm = (SprmOperation) sprmIt.next();
044: unCompressCHPOperation(parent, newProperties, sprm);
045: }
046:
047: return newProperties;
048: }
049:
050: /**
051: * Used in decompression of a chpx. This performs an operation defined by
052: * a single sprm.
053: *
054: * @param oldCHP The base CharacterProperties.
055: * @param newCHP The current CharacterProperties.
056: * @param operand The operand defined by the sprm (See Word file format spec)
057: * @param param The parameter defined by the sprm (See Word file format spec)
058: * @param varParam The variable length parameter defined by the sprm. (See
059: * Word file format spec)
060: * @param grpprl The entire chpx that this operation is a part of.
061: * @param offset The offset in the grpprl of the next sprm
062: * @param styleSheet The StyleSheet for this document.
063: */
064: static void unCompressCHPOperation(CharacterProperties oldCHP,
065: CharacterProperties newCHP, SprmOperation sprm) {
066:
067: switch (sprm.getOperation()) {
068: case 0:
069: newCHP.setFRMarkDel(getFlag(sprm.getOperand()));
070: break;
071: case 0x1:
072: newCHP.setFRMark(getFlag(sprm.getOperand()));
073: break;
074: case 0x2:
075: newCHP.setFFldVanish(getFlag(sprm.getOperand()));
076: break;
077: case 0x3:
078: newCHP.setFcPic(sprm.getOperand());
079: newCHP.setFSpec(true);
080: break;
081: case 0x4:
082: newCHP.setIbstRMark((short) sprm.getOperand());
083: break;
084: case 0x5:
085: newCHP.setDttmRMark(new DateAndTime(sprm.getGrpprl(), sprm
086: .getGrpprlOffset()));
087: break;
088: case 0x6:
089: newCHP.setFData(getFlag(sprm.getOperand()));
090: break;
091: case 0x7:
092: //don't care about this
093: break;
094: case 0x8:
095: //short chsDiff = (short)((param & 0xff0000) >>> 16);
096: int operand = sprm.getOperand();
097: short chsDiff = (short) (operand & 0x0000ff);
098: newCHP.setFChsDiff(getFlag(chsDiff));
099: newCHP.setChse((short) (operand & 0xffff00));
100: break;
101: case 0x9:
102: newCHP.setFSpec(true);
103: newCHP.setFtcSym((short) LittleEndian.getShort(sprm
104: .getGrpprl(), sprm.getGrpprlOffset()));
105: newCHP.setXchSym((short) LittleEndian.getShort(sprm
106: .getGrpprl(), sprm.getGrpprlOffset() + 2));
107: break;
108: case 0xa:
109: newCHP.setFOle2(getFlag(sprm.getOperand()));
110: break;
111: case 0xb:
112:
113: // Obsolete
114: break;
115: case 0xc:
116: newCHP.setIcoHighlight((byte) sprm.getOperand());
117: newCHP.setFHighlight(getFlag(sprm.getOperand()));
118: break;
119: case 0xd:
120:
121: // undocumented
122: break;
123: case 0xe:
124: newCHP.setFcObj(sprm.getOperand());
125: break;
126: case 0xf:
127:
128: // undocumented
129: break;
130: case 0x10:
131:
132: // undocumented
133: break;
134:
135: // undocumented till 0x30
136:
137: case 0x11:
138: break;
139: case 0x12:
140: break;
141: case 0x13:
142: break;
143: case 0x14:
144: break;
145: case 0x15:
146: break;
147: case 0x16:
148: break;
149: case 0x17:
150: break;
151: case 0x18:
152: break;
153: case 0x19:
154: break;
155: case 0x1a:
156: break;
157: case 0x1b:
158: break;
159: case 0x1c:
160: break;
161: case 0x1d:
162: break;
163: case 0x1e:
164: break;
165: case 0x1f:
166: break;
167: case 0x20:
168: break;
169: case 0x21:
170: break;
171: case 0x22:
172: break;
173: case 0x23:
174: break;
175: case 0x24:
176: break;
177: case 0x25:
178: break;
179: case 0x26:
180: break;
181: case 0x27:
182: break;
183: case 0x28:
184: break;
185: case 0x29:
186: break;
187: case 0x2a:
188: break;
189: case 0x2b:
190: break;
191: case 0x2c:
192: break;
193: case 0x2d:
194: break;
195: case 0x2e:
196: break;
197: case 0x2f:
198: break;
199: case 0x30:
200: newCHP.setIstd(sprm.getOperand());
201: break;
202: case 0x31:
203:
204: //permutation vector for fast saves, who cares!
205: break;
206: case 0x32:
207: newCHP.setFBold(false);
208: newCHP.setFItalic(false);
209: newCHP.setFOutline(false);
210: newCHP.setFStrike(false);
211: newCHP.setFShadow(false);
212: newCHP.setFSmallCaps(false);
213: newCHP.setFCaps(false);
214: newCHP.setFVanish(false);
215: newCHP.setKul((byte) 0);
216: newCHP.setIco((byte) 0);
217: break;
218: case 0x33:
219: try {
220: // preserve the fSpec setting from the original CHP
221: boolean fSpec = newCHP.isFSpec();
222: newCHP = (CharacterProperties) oldCHP.clone();
223: newCHP.setFSpec(fSpec);
224:
225: } catch (CloneNotSupportedException e) {
226: //do nothing
227: }
228: return;
229: case 0x34:
230:
231: // undocumented
232: break;
233: case 0x35:
234: newCHP.setFBold(getCHPFlag((byte) sprm.getOperand(), oldCHP
235: .isFBold()));
236: break;
237: case 0x36:
238: newCHP.setFItalic(getCHPFlag((byte) sprm.getOperand(),
239: oldCHP.isFItalic()));
240: break;
241: case 0x37:
242: newCHP.setFStrike(getCHPFlag((byte) sprm.getOperand(),
243: oldCHP.isFStrike()));
244: break;
245: case 0x38:
246: newCHP.setFOutline(getCHPFlag((byte) sprm.getOperand(),
247: oldCHP.isFOutline()));
248: break;
249: case 0x39:
250: newCHP.setFShadow(getCHPFlag((byte) sprm.getOperand(),
251: oldCHP.isFShadow()));
252: break;
253: case 0x3a:
254: newCHP.setFSmallCaps(getCHPFlag((byte) sprm.getOperand(),
255: oldCHP.isFSmallCaps()));
256: break;
257: case 0x3b:
258: newCHP.setFCaps(getCHPFlag((byte) sprm.getOperand(), oldCHP
259: .isFCaps()));
260: break;
261: case 0x3c:
262: newCHP.setFVanish(getCHPFlag((byte) sprm.getOperand(),
263: oldCHP.isFVanish()));
264: break;
265: case 0x3d:
266: newCHP.setFtcAscii((short) sprm.getOperand());
267: break;
268: case 0x3e:
269: newCHP.setKul((byte) sprm.getOperand());
270: break;
271: case 0x3f:
272: operand = sprm.getOperand();
273: int hps = operand & 0xff;
274: if (hps != 0) {
275: newCHP.setHps(hps);
276: }
277:
278: //byte cInc = (byte)(((byte)(param & 0xfe00) >>> 4) >> 1);
279: byte cInc = (byte) ((operand & 0xff00) >>> 8);
280: cInc = (byte) (cInc >>> 1);
281: if (cInc != 0) {
282: newCHP
283: .setHps(Math.max(newCHP.getHps() + (cInc * 2),
284: 2));
285: }
286:
287: //byte hpsPos = (byte)((param & 0xff0000) >>> 8);
288: byte hpsPos = (byte) ((operand & 0xff0000) >>> 16);
289: if (hpsPos != 0x80) {
290: newCHP.setHpsPos(hpsPos);
291: }
292: boolean fAdjust = (operand & 0x0100) > 0;
293: if (fAdjust && hpsPos != 128 && hpsPos != 0
294: && oldCHP.getHpsPos() == 0) {
295: newCHP.setHps(Math.max(newCHP.getHps() + (-2), 2));
296: }
297: if (fAdjust && hpsPos == 0 && oldCHP.getHpsPos() != 0) {
298: newCHP.setHps(Math.max(newCHP.getHps() + 2, 2));
299: }
300: break;
301: case 0x40:
302: newCHP.setDxaSpace(sprm.getOperand());
303: break;
304: case 0x41:
305: newCHP.setLidDefault((short) sprm.getOperand());
306: break;
307: case 0x42:
308: newCHP.setIco((byte) sprm.getOperand());
309: break;
310: case 0x43:
311: newCHP.setHps(sprm.getOperand());
312: break;
313: case 0x44:
314: byte hpsLvl = (byte) sprm.getOperand();
315: newCHP.setHps(Math.max(newCHP.getHps() + (hpsLvl * 2), 2));
316: break;
317: case 0x45:
318: newCHP.setHpsPos((short) sprm.getOperand());
319: break;
320: case 0x46:
321: if (sprm.getOperand() != 0) {
322: if (oldCHP.getHpsPos() == 0) {
323: newCHP.setHps(Math.max(newCHP.getHps() + (-2), 2));
324: }
325: } else {
326: if (oldCHP.getHpsPos() != 0) {
327: newCHP.setHps(Math.max(newCHP.getHps() + 2, 2));
328: }
329: }
330: break;
331: case 0x47:
332: /*CharacterProperties genCHP = new CharacterProperties ();
333: genCHP.setFtcAscii (4);
334: genCHP = (CharacterProperties) unCompressProperty (varParam, genCHP,
335: styleSheet);
336: CharacterProperties styleCHP = styleSheet.getStyleDescription (oldCHP.
337: getBaseIstd ()).getCHP ();
338: if (genCHP.isFBold () == newCHP.isFBold ())
339: {
340: newCHP.setFBold (styleCHP.isFBold ());
341: }
342: if (genCHP.isFItalic () == newCHP.isFItalic ())
343: {
344: newCHP.setFItalic (styleCHP.isFItalic ());
345: }
346: if (genCHP.isFSmallCaps () == newCHP.isFSmallCaps ())
347: {
348: newCHP.setFSmallCaps (styleCHP.isFSmallCaps ());
349: }
350: if (genCHP.isFVanish () == newCHP.isFVanish ())
351: {
352: newCHP.setFVanish (styleCHP.isFVanish ());
353: }
354: if (genCHP.isFStrike () == newCHP.isFStrike ())
355: {
356: newCHP.setFStrike (styleCHP.isFStrike ());
357: }
358: if (genCHP.isFCaps () == newCHP.isFCaps ())
359: {
360: newCHP.setFCaps (styleCHP.isFCaps ());
361: }
362: if (genCHP.getFtcAscii () == newCHP.getFtcAscii ())
363: {
364: newCHP.setFtcAscii (styleCHP.getFtcAscii ());
365: }
366: if (genCHP.getFtcFE () == newCHP.getFtcFE ())
367: {
368: newCHP.setFtcFE (styleCHP.getFtcFE ());
369: }
370: if (genCHP.getFtcOther () == newCHP.getFtcOther ())
371: {
372: newCHP.setFtcOther (styleCHP.getFtcOther ());
373: }
374: if (genCHP.getHps () == newCHP.getHps ())
375: {
376: newCHP.setHps (styleCHP.getHps ());
377: }
378: if (genCHP.getHpsPos () == newCHP.getHpsPos ())
379: {
380: newCHP.setHpsPos (styleCHP.getHpsPos ());
381: }
382: if (genCHP.getKul () == newCHP.getKul ())
383: {
384: newCHP.setKul (styleCHP.getKul ());
385: }
386: if (genCHP.getDxaSpace () == newCHP.getDxaSpace ())
387: {
388: newCHP.setDxaSpace (styleCHP.getDxaSpace ());
389: }
390: if (genCHP.getIco () == newCHP.getIco ())
391: {
392: newCHP.setIco (styleCHP.getIco ());
393: }
394: if (genCHP.getLidDefault () == newCHP.getLidDefault ())
395: {
396: newCHP.setLidDefault (styleCHP.getLidDefault ());
397: }
398: if (genCHP.getLidFE () == newCHP.getLidFE ())
399: {
400: newCHP.setLidFE (styleCHP.getLidFE ());
401: }*/
402: break;
403: case 0x48:
404: newCHP.setIss((byte) sprm.getOperand());
405: break;
406: case 0x49:
407: newCHP.setHps(LittleEndian.getShort(sprm.getGrpprl(), sprm
408: .getGrpprlOffset()));
409: break;
410: case 0x4a:
411: int increment = LittleEndian.getShort(sprm.getGrpprl(),
412: sprm.getGrpprlOffset());
413: newCHP.setHps(Math.max(newCHP.getHps() + increment, 8));
414: break;
415: case 0x4b:
416: newCHP.setHpsKern(sprm.getOperand());
417: break;
418: case 0x4c:
419: // unCompressCHPOperation (oldCHP, newCHP, 0x47, param, varParam,
420: // styleSheet, opSize);
421: break;
422: case 0x4d:
423: float percentage = (float) sprm.getOperand() / 100.0f;
424: int add = (int) ((float) percentage * (float) newCHP
425: .getHps());
426: newCHP.setHps(newCHP.getHps() + add);
427: break;
428: case 0x4e:
429: newCHP.setYsr((byte) sprm.getOperand());
430: break;
431: case 0x4f:
432: newCHP.setFtcAscii((short) sprm.getOperand());
433: break;
434: case 0x50:
435: newCHP.setFtcFE((short) sprm.getOperand());
436: break;
437: case 0x51:
438: newCHP.setFtcOther((short) sprm.getOperand());
439: break;
440: case 0x52:
441:
442: // undocumented
443: break;
444: case 0x53:
445: newCHP.setFDStrike(getFlag(sprm.getOperand()));
446: break;
447: case 0x54:
448: newCHP.setFImprint(getFlag(sprm.getOperand()));
449: break;
450: case 0x55:
451: newCHP.setFSpec(getFlag(sprm.getOperand()));
452: break;
453: case 0x56:
454: newCHP.setFObj(getFlag(sprm.getOperand()));
455: break;
456: case 0x57:
457: byte[] buf = sprm.getGrpprl();
458: int offset = sprm.getGrpprlOffset();
459: newCHP.setFPropMark(buf[offset]);
460: newCHP.setIbstPropRMark((short) LittleEndian.getShort(buf,
461: offset + 1));
462: newCHP.setDttmPropRMark(new DateAndTime(buf, offset + 3));
463: break;
464: case 0x58:
465: newCHP.setFEmboss(getFlag(sprm.getOperand()));
466: break;
467: case 0x59:
468: newCHP.setSfxtText((byte) sprm.getOperand());
469: break;
470:
471: // undocumented till 0x61
472: case 0x5a:
473: break;
474: case 0x5b:
475: break;
476: case 0x5c:
477: break;
478: case 0x5d:
479: break;
480: case 0x5e:
481: break;
482: case 0x5f:
483: break;
484: case 0x60:
485: break;
486: case 0x61:
487: break;
488: case 0x62:
489: byte[] xstDispFldRMark = new byte[32];
490: buf = sprm.getGrpprl();
491: offset = sprm.getGrpprlOffset();
492: newCHP.setFDispFldRMark(buf[offset]);
493: newCHP.setIbstDispFldRMark((short) LittleEndian.getShort(
494: buf, offset + 1));
495: newCHP
496: .setDttmDispFldRMark(new DateAndTime(buf,
497: offset + 3));
498: System.arraycopy(buf, offset + 7, xstDispFldRMark, 0, 32);
499: newCHP.setXstDispFldRMark(xstDispFldRMark);
500: break;
501: case 0x63:
502: newCHP.setIbstRMarkDel((short) sprm.getOperand());
503: break;
504: case 0x64:
505: newCHP.setDttmRMarkDel(new DateAndTime(sprm.getGrpprl(),
506: sprm.getGrpprlOffset()));
507: break;
508: case 0x65:
509: newCHP.setBrc(new BorderCode(sprm.getGrpprl(), sprm
510: .getGrpprlOffset()));
511: break;
512: case 0x66:
513: newCHP.setShd(new ShadingDescriptor(sprm.getGrpprl(), sprm
514: .getGrpprlOffset()));
515: break;
516: case 0x67:
517:
518: // Obsolete
519: break;
520: case 0x68:
521: break;
522:
523: // undocumented till 0x6c
524:
525: case 0x69:
526: break;
527: case 0x6a:
528: break;
529: case 0x6b:
530: break;
531: case 0x6c:
532: break;
533: case 0x6d:
534: newCHP.setLidDefault((short) sprm.getOperand());
535: break;
536: case 0x6e:
537: newCHP.setLidFE((short) sprm.getOperand());
538: break;
539: case 0x6f:
540: newCHP.setIdctHint((byte) sprm.getOperand());
541: break;
542: case 0x70:
543: newCHP.setIco24(sprm.getOperand());
544: break;
545: }
546: }
547:
548: /**
549: * Converts an int into a boolean. If the int is non-zero, it returns true.
550: * Otherwise it returns false.
551: *
552: * @param x The int to convert.
553: *
554: * @return A boolean whose value depends on x.
555: */
556: public static boolean getFlag(int x) {
557: if (x != 0) {
558: return true;
559: } else {
560: return false;
561: }
562: }
563:
564: private static boolean getCHPFlag(byte x, boolean oldVal) {
565: /*
566: switch(x)
567: {
568: case 0:
569: return false;
570: case 1:
571: return true;
572: case (byte)0x80:
573: return oldVal;
574: case (byte)0x81:
575: return !oldVal;
576: default:
577: return false;
578: }
579: */
580: if (x == 0) {
581: return false;
582: } else if (x == 1) {
583: return true;
584: } else if ((x & 0x81) == 0x80) {
585: return oldVal;
586: } else if ((x & 0x81) == 0x81) {
587: return !oldVal;
588: } else {
589: return false;
590: }
591: }
592:
593: }
|