1 /*
2 Source File : CFFPrimitiveReader.cpp
3
4
5 Copyright 2011 Gal Kahana PDFWriter
6
7 Licensed under the Apache License, Version 2.0 (the "License");
8 you may not use this file except in compliance with the License.
9 You may obtain a copy of the License at
10
11 http://www.apache.org/licenses/LICENSE-2.0
12
13 Unless required by applicable law or agreed to in writing, software
14 distributed under the License is distributed on an "AS IS" BASIS,
15 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 See the License for the specific language governing permissions and
17 limitations under the License.
18
19
20 */
21 #include "CFFPrimitiveReader.h"
22 #include <math.h>
23
24
25 using namespace PDFHummus;
26
27
CFFPrimitiveReader(IByteReaderWithPosition * inCFFFile)28 CFFPrimitiveReader::CFFPrimitiveReader(IByteReaderWithPosition* inCFFFile)
29 {
30 SetStream(inCFFFile);
31 }
32
~CFFPrimitiveReader(void)33 CFFPrimitiveReader::~CFFPrimitiveReader(void)
34 {
35 }
36
SetStream(IByteReaderWithPosition * inCFFFile)37 void CFFPrimitiveReader::SetStream(IByteReaderWithPosition* inCFFFile)
38 {
39 mCFFFile = inCFFFile;
40 if(inCFFFile)
41 {
42 mCurrentOffsize = 1;
43 mInitialPosition = inCFFFile->GetCurrentPosition();
44 mInternalState = PDFHummus::eSuccess;
45 }
46 else
47 {
48 mInternalState = PDFHummus::eFailure;
49 }
50 }
51
52
SetOffset(LongFilePositionType inNewOffset)53 void CFFPrimitiveReader::SetOffset(LongFilePositionType inNewOffset)
54 {
55 if(mInternalState != PDFHummus::eFailure)
56 mCFFFile->SetPosition(mInitialPosition + inNewOffset);
57 }
58
Skip(LongBufferSizeType inToSkip)59 void CFFPrimitiveReader::Skip(LongBufferSizeType inToSkip)
60 {
61 if(mInternalState != PDFHummus::eFailure)
62 mCFFFile->Skip(inToSkip);
63 }
64
GetInternalState()65 EStatusCode CFFPrimitiveReader::GetInternalState()
66 {
67 return mInternalState;
68 }
69
GetCurrentPosition()70 LongFilePositionType CFFPrimitiveReader::GetCurrentPosition()
71 {
72 if(mInternalState != PDFHummus::eFailure)
73 return mCFFFile->GetCurrentPosition() - mInitialPosition;
74 else
75 return 0;
76 }
77
ReadByte(Byte & outValue)78 EStatusCode CFFPrimitiveReader::ReadByte(Byte& outValue)
79 {
80 if(PDFHummus::eFailure == mInternalState)
81 return PDFHummus::eFailure;
82
83 Byte buffer;
84 EStatusCode status = (mCFFFile->Read(&buffer,1) == 1 ? PDFHummus::eSuccess : PDFHummus::eFailure);
85
86 if(PDFHummus::eFailure == status)
87 mInternalState = PDFHummus::eFailure;
88 outValue = buffer;
89 return status;
90 }
91
Read(Byte * ioBuffer,LongBufferSizeType inBufferSize)92 EStatusCode CFFPrimitiveReader::Read(Byte* ioBuffer,LongBufferSizeType inBufferSize)
93 {
94 if(PDFHummus::eFailure == mInternalState)
95 return PDFHummus::eFailure;
96
97 EStatusCode status = (mCFFFile->Read(ioBuffer,inBufferSize) == inBufferSize ? PDFHummus::eSuccess : PDFHummus::eFailure);
98
99 if(PDFHummus::eFailure == status)
100 mInternalState = PDFHummus::eFailure;
101 return status;
102 }
103
ReadCard8(Byte & outValue)104 EStatusCode CFFPrimitiveReader::ReadCard8(Byte& outValue)
105 {
106 return ReadByte(outValue);
107 }
108
ReadCard16(unsigned short & outValue)109 EStatusCode CFFPrimitiveReader::ReadCard16(unsigned short& outValue)
110 {
111 Byte byte1,byte2;
112
113 if(ReadByte(byte1) != PDFHummus::eSuccess)
114 return PDFHummus::eFailure;
115
116 if(ReadByte(byte2) != PDFHummus::eSuccess)
117 return PDFHummus::eFailure;
118
119
120 outValue = ((unsigned short)byte1 << 8) + byte2;
121
122 return PDFHummus::eSuccess;
123
124 }
Read2ByteSigned(short & outValue)125 EStatusCode CFFPrimitiveReader::Read2ByteSigned(short& outValue)
126 {
127 unsigned short buffer;
128 EStatusCode status = ReadCard16(buffer);
129
130 if(status != PDFHummus::eSuccess)
131 return PDFHummus::eFailure;
132
133 outValue = (short)buffer;
134 return PDFHummus::eSuccess;
135 }
136
137
SetOffSize(Byte inOffSize)138 void CFFPrimitiveReader::SetOffSize(Byte inOffSize)
139 {
140 mCurrentOffsize = inOffSize;
141 }
142
143
ReadOffset(unsigned long & outValue)144 EStatusCode CFFPrimitiveReader::ReadOffset(unsigned long& outValue)
145 {
146 EStatusCode status = PDFHummus::eFailure;
147
148 switch(mCurrentOffsize)
149 {
150 case 1:
151 Byte byteBuffer;
152 status = ReadCard8(byteBuffer);
153 if(PDFHummus::eSuccess == status)
154 outValue = byteBuffer;
155 break;
156 case 2:
157 unsigned short shortBuffer;
158 status = ReadCard16(shortBuffer);
159 if(PDFHummus::eSuccess == status)
160 outValue = shortBuffer;
161 break;
162 case 3:
163 status = Read3ByteUnsigned(outValue);
164 break;
165 case 4:
166 status = Read4ByteUnsigned(outValue);
167 break;
168
169 }
170
171 return status;
172 }
173
Read3ByteUnsigned(unsigned long & outValue)174 EStatusCode CFFPrimitiveReader::Read3ByteUnsigned(unsigned long& outValue)
175 {
176 Byte byte1,byte2,byte3;
177
178 if(ReadByte(byte1) != PDFHummus::eSuccess)
179 return PDFHummus::eFailure;
180
181 if(ReadByte(byte2) != PDFHummus::eSuccess)
182 return PDFHummus::eFailure;
183
184 if(ReadByte(byte3) != PDFHummus::eSuccess)
185 return PDFHummus::eFailure;
186
187 outValue = ((unsigned long)byte1 << 16) + ((unsigned long)byte2 << 8) + byte3;
188
189 return PDFHummus::eSuccess;
190 }
191
Read4ByteUnsigned(unsigned long & outValue)192 EStatusCode CFFPrimitiveReader::Read4ByteUnsigned(unsigned long& outValue)
193 {
194 Byte byte1,byte2,byte3,byte4;
195
196 if(ReadByte(byte1) != PDFHummus::eSuccess)
197 return PDFHummus::eFailure;
198
199 if(ReadByte(byte2) != PDFHummus::eSuccess)
200 return PDFHummus::eFailure;
201
202 if(ReadByte(byte3) != PDFHummus::eSuccess)
203 return PDFHummus::eFailure;
204
205 if(ReadByte(byte4) != PDFHummus::eSuccess)
206 return PDFHummus::eFailure;
207
208 outValue = ((unsigned long)byte1 << 24) +
209 ((unsigned long)byte2 << 16) +
210 ((unsigned long)byte3 << 8) +
211 byte4;
212
213 return PDFHummus::eSuccess;
214 }
215
Read4ByteSigned(long & outValue)216 EStatusCode CFFPrimitiveReader::Read4ByteSigned(long& outValue)
217 {
218 unsigned long buffer;
219 EStatusCode status = Read4ByteUnsigned(buffer);
220
221 if(status != PDFHummus::eSuccess)
222 return PDFHummus::eFailure;
223
224 outValue = (int)buffer; // very important to cast to 32, to get the sign right
225
226 return PDFHummus::eSuccess;
227 }
228
229
ReadOffSize(Byte & outValue)230 EStatusCode CFFPrimitiveReader::ReadOffSize(Byte& outValue)
231 {
232 return ReadCard8(outValue);
233 }
234
ReadSID(unsigned short & outValue)235 EStatusCode CFFPrimitiveReader::ReadSID(unsigned short& outValue)
236 {
237 return ReadCard16(outValue);
238 }
239
ReadIntegerOperand(Byte inFirstByte,long & outValue)240 EStatusCode CFFPrimitiveReader::ReadIntegerOperand(Byte inFirstByte,long& outValue)
241 {
242 Byte byte0,byte1;
243 EStatusCode status = PDFHummus::eSuccess;
244
245 byte0 = inFirstByte;
246
247 if(byte0 >= 32 && byte0 <= 246)
248 {
249 outValue = (long)byte0 - 139;
250 }
251 else if(byte0 >= 247 && byte0 <= 250)
252 {
253 if(ReadByte(byte1) != PDFHummus::eSuccess)
254 return PDFHummus::eFailure;
255
256 outValue = (byte0-247) * 256 + byte1 + 108;
257 }
258 else if (byte0 >= 251 && byte0 <= 254)
259 {
260 if(ReadByte(byte1) != PDFHummus::eSuccess)
261 return PDFHummus::eFailure;
262
263 outValue = -(long)((long)byte0-251) * 256 - byte1 - 108;
264 }
265 else if (28 == byte0)
266 {
267 short buffer = 0;
268 status = Read2ByteSigned(buffer);
269 outValue = buffer;
270 }
271 else if(29 == byte0)
272 {
273 status = Read4ByteSigned(outValue);
274 }
275 else
276 status = PDFHummus::eFailure;
277
278 return status;
279 }
280
ReadRealOperand(double & outValue,long & outRealValueFractalEnd)281 EStatusCode CFFPrimitiveReader::ReadRealOperand(double& outValue,long& outRealValueFractalEnd)
282 {
283 double integerPart = 0;
284 double fractionPart = 0;
285 double powerPart = 0;
286 double result;
287 bool hasNegative = false;
288 bool hasFraction = false;
289 bool hasPositivePower = false;
290 bool hasNegativePower = false;
291 bool notDone = true;
292 double fractionDecimal = 1;
293 outRealValueFractalEnd = 0;
294 Byte buffer;
295 Byte nibble[2];
296 EStatusCode status = PDFHummus::eSuccess;
297
298 do
299 {
300 status = ReadByte(buffer);
301 if(status != PDFHummus::eSuccess)
302 break;
303
304 nibble[0] = (buffer >> 4) & 0xf;
305 nibble[1] = buffer & 0xf;
306
307 for(int i = 0; i <2; ++i)
308 {
309 switch(nibble[i])
310 {
311 case 0xa:
312 hasFraction = true;
313 break;
314 case 0xb:
315 hasPositivePower = true;
316 break;
317 case 0xc:
318 hasNegativePower = true;
319 break;
320 case 0xd:
321 // reserved
322 break;
323 case 0xe:
324 hasNegative = true;
325 break;
326 case 0xf:
327 notDone = false;
328 break;
329 default: // numbers
330 if(hasPositivePower || hasNegativePower)
331 {
332 powerPart = powerPart*10 + nibble[i];
333 }
334 else if(hasFraction)
335 {
336 fractionPart = fractionPart * 10 + nibble[i];
337 fractionDecimal *= 10;
338 ++outRealValueFractalEnd;
339 }
340 else
341 integerPart = integerPart * 10 + nibble[i];
342
343 }
344 }
345 }while(notDone);
346
347 if(PDFHummus::eSuccess == status)
348 {
349 result = integerPart + fractionPart/fractionDecimal;
350 if(hasNegativePower || hasPositivePower)
351 result = result * pow(10,hasNegativePower ? -powerPart : powerPart);
352 if(hasNegative)
353 result = -1*result;
354 outValue = result;
355 }
356 return status;
357 }
358
IsDictOperator(Byte inCandidate)359 bool CFFPrimitiveReader::IsDictOperator(Byte inCandidate)
360 {
361 return (inCandidate <= 27 || 31 == inCandidate);
362 }
363
ReadDictOperator(Byte inFirstByte,unsigned short & outOperator)364 EStatusCode CFFPrimitiveReader::ReadDictOperator(Byte inFirstByte,unsigned short& outOperator)
365 {
366 if(12 == inFirstByte)
367 {
368 Byte buffer;
369 if(ReadByte(buffer) == PDFHummus::eSuccess)
370 {
371 outOperator = ((unsigned short)inFirstByte << 8) | buffer;
372 return PDFHummus::eSuccess;
373 }
374 else
375 return PDFHummus::eFailure;
376 }
377 else
378 {
379 outOperator = inFirstByte;
380 return PDFHummus::eSuccess;
381 }
382 }
383
ReadDictOperand(Byte inFirstByte,DictOperand & outOperand)384 EStatusCode CFFPrimitiveReader::ReadDictOperand(Byte inFirstByte,DictOperand& outOperand)
385 {
386 if(30 == inFirstByte) // real
387 {
388 outOperand.IsInteger = false;
389 return ReadRealOperand(outOperand.RealValue,outOperand.RealValueFractalEnd);
390 }
391 else if(28 == inFirstByte ||
392 29 == inFirstByte ||
393 (32 <= inFirstByte && inFirstByte <= 246) ||
394 (247 <= inFirstByte && inFirstByte <= 250) ||
395 (251 <= inFirstByte && inFirstByte <= 254))
396 {
397 outOperand.IsInteger = true;
398 return ReadIntegerOperand(inFirstByte,outOperand.IntegerValue);
399 }
400 else
401 return PDFHummus::eFailure; // not an operand
402 }
403