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