00001
00007
00008
00009 #include "NPWBase.h"
00010
00011 #if !defined(NPWNoFloat)
00012 # include <math.h>
00013 #endif
00014
00016 #define kHeaderStr "%PDF-1.5\n"
00017
00019 #define Chk(e) \
00020 do { \
00021 err = (e); \
00022 if (err != kNPWErrOk) \
00023 return err; \
00024 } while (0)
00025
00027 #define ChkG(e) \
00028 do { \
00029 err = (e); \
00030 if (err != kNPWErrOk) \
00031 goto error; \
00032 } while (0)
00033
00034 #define kDigits 8
00035
00037 #define hex(n) ((n) >= 10 ? 'a' - 10 + (n) : '0' + (n))
00038
00039 void NPWInit(NPW *pdf)
00040 {
00041 pdf->fonts = kNPWFontAll;
00042 pdf->offset = 0;
00043 pdf->writingObject = FALSE;
00044 pdf->alloc = NULL;
00045 pdf->write = NULL;
00046 pdf->xref = NULL;
00047 pdf->xrefSize = pdf->xrefCount = 0;
00048 pdf->page = NULL;
00049 pdf->pageSize = pdf->pageCount = 0;
00050 pdf->info = kNPWNoRef;
00051 pdf->filter = kNPWFilterNone;
00052 pdf->asciiBufCount = pdf->asciiFilterLineLength = 0;
00053 }
00054
00055 void NPWSetAllocCallback(NPW *pdf,
00056 NPWAllocCB alloc, void *userData)
00057 {
00058 pdf->alloc = alloc;
00059 pdf->allocUserData = userData;
00060 }
00061
00062 void NPWSetWriteCallback(NPW *pdf,
00063 NPWWriteCB write, void *userData)
00064 {
00065 pdf->write = write;
00066 pdf->writeUserData = userData;
00067 }
00068
00069 void NPWSetFonts(NPW *pdf, NPWInt fonts)
00070 {
00071 pdf->fonts = fonts;
00072 }
00073
00074 NPWErr NPWWrite(NPW *pdf, NPWConstText str, NPWInt length)
00075 {
00076 NPWErr err = kNPWErrOk;
00077
00078 if (length < 0)
00079 for (length = 0; str[length] != '\0'; length++)
00080 ;
00081 if (pdf->write)
00082 err = pdf->write(str, length, pdf->writeUserData);
00083 pdf->offset += length;
00084 return err;
00085 }
00086
00087 NPWErr NPWWriteInt(NPW *pdf, NPWInt i, NPWInt pad)
00088 {
00089 NPWChar str[12];
00090 NPWInt len = 0;
00091 NPWInt j;
00092
00093 if (i == 0 && pad < 0)
00094 str[len++] = '0';
00095 else
00096 {
00097 if (i < 0)
00098 {
00099 str[len++] = '-';
00100 i = -i;
00101 pad--;
00102 }
00103 if (pad < 0)
00104 {
00105
00106 for (j = i; j > 0; j /= 10, len++)
00107 ;
00108
00109 for (j = 1; i > 0; i /= 10, j++)
00110 str[len - j] = '0' + i % 10;
00111 }
00112 else
00113 {
00114 len += pad;
00115 for (j = 1; j <= pad; i /= 10, j++)
00116 str[len - j] = '0' + i % 10;
00117 }
00118 }
00119
00120 return NPWWrite(pdf, str, len);
00121 }
00122
00123 #if !defined(NPWNoFloat)
00124 NPWErr NPWWriteFloat(NPW *pdf, NPWFloat x)
00125 {
00126 NPWInt n, i;
00127 NPWFloat pw10;
00128 NPWChar d;
00129 NPWChar frac[kDigits];
00130 NPWErr err;
00131
00132
00133 if (x < 0)
00134 {
00135 Chk(NPWWrite(pdf, "-", 1));
00136 x = -x;
00137 }
00138
00139
00140 if (x > 1e30)
00141 return kNPWNumTooLarge;
00142
00143
00144 for (pw10 = 1, n = 1; 10 * pw10 <= x; pw10 *= 10, n++)
00145 ;
00146 do
00147 {
00148 d = '0' + (int)fmod(floor(x / pw10), 10);
00149 Chk(NPWWrite(pdf, &d, 1));
00150 pw10 /= 10;
00151 } while (pw10 > 0.5);
00152
00153
00154 for (i = 0, pw10 = 10; n + i < kDigits; i++, pw10 *= 10)
00155 frac[i] = '0' + (int)fmod(floor(x * pw10), 10);
00156 while (i > 0 && frac[i - 1] == '0')
00157 i--;
00158 if (i > 0)
00159 {
00160 Chk(NPWWrite(pdf, ".", 1));
00161 Chk(NPWWrite(pdf, frac, i));
00162 }
00163 return kNPWErrOk;
00164 }
00165 #endif
00166
00167 NPWErr NPWWriteString(NPW *pdf, NPWConstText str, NPWInt length)
00168 {
00169 NPWInt i, j;
00170 NPWChar str1[8];
00171 NPWErr err;
00172
00173 Chk(NPWWrite(pdf, "(", 1));
00174 for (i = 0; length < 0 ? str[i] : i < length; )
00175 {
00176 for (j = 0;
00177 (length < 0 || i + j < length)
00178 && (str[i + j] < 0
00179 || (str[i + j] >= ' ' && str[i + j] != '(' && str[i + j] != ')'));
00180 j++)
00181 ;
00182 if (j > 0)
00183 Chk(NPWWrite(pdf, str + i, j));
00184 i += j;
00185 if (length < 0 ? str[i] : i < length)
00186 {
00187 str1[0] = '\\';
00188 j = 2;
00189 switch (str[i])
00190 {
00191 case 10:
00192 str1[1] = 'n';
00193 break;
00194 case 13:
00195 str1[1] = 'r';
00196 break;
00197 case 9:
00198 str1[1] = 't';
00199 break;
00200 case 8:
00201 str1[1] = 'b';
00202 break;
00203 case '(':
00204 str1[1] = '(';
00205 break;
00206 case ')':
00207 str1[1] = ')';
00208 break;
00209 default:
00210 str1[1] = '0' + (0777 & str[i]) / 0100;
00211 str1[2] = '0' + (077 & str[i]) / 010;
00212 str1[3] = '0' + (07 & str[i]);
00213 j = 4;
00214 break;
00215 }
00216 Chk(NPWWrite(pdf, str1, j));
00217 i++;
00218 }
00219 }
00220 Chk(NPWWrite(pdf, ")", 1));
00221 return kNPWErrOk;
00222 }
00223
00225 typedef struct
00226 {
00227 NPWInt offset;
00228 NPWBoolean done;
00229 NPWBoolean run;
00230 NPWByte val;
00231 NPWInt rem;
00232 } RLState;
00233
00234 #define kRLEOD 128
00235
00236
00239 static void RLInit(RLState *rl)
00240 {
00241 rl->offset = 0;
00242 rl->done = FALSE;
00243 rl->run = FALSE;
00244 rl->val = 0;
00245 rl->rem = 0;
00246 }
00247
00254 static NPWByte RLNextByte(RLState *rl, NPWByte const *b, NPWInt len)
00255 {
00256 if (rl->run)
00257 {
00258 rl->run = FALSE;
00259 rl->rem = 0;
00260 return rl->val;
00261 }
00262 else if (rl->rem > 0)
00263 {
00264 rl->rem--;
00265 return b[rl->offset++];
00266 }
00267 else if (rl->offset >= len)
00268 {
00269 rl->done = TRUE;
00270 return kRLEOD;
00271 }
00272 else
00273 {
00274
00275 NPWInt n;
00276
00277
00278 for (n = 1;
00279 n < 128 && rl->offset + n < len && b[rl->offset + n] == b[rl->offset];
00280 n++)
00281 ;
00282 if (n >= 2)
00283 {
00284 rl->val = b[rl->offset];
00285 rl->offset += n;
00286 rl->run = TRUE;
00287 return (NPWByte)(257 - n);
00288 }
00289
00290
00291 for (n = 1;
00292 n < 128 && rl->offset + n < len
00293 && b[rl->offset + n] != b[rl->offset + n - 1];
00294 n++)
00295 ;
00296 if (rl->offset + n < len && b[rl->offset + n - 1] == b[rl->offset + n])
00297 n--;
00298 rl->rem = n;
00299 return (NPWByte)(n - 1);
00300 }
00301 }
00302
00303 void NPWFilterBegin(NPW *pdf, NPWInt filter)
00304 {
00305 pdf->filter = filter;
00306 pdf->asciiBufCount = 0;
00307 pdf->asciiFilterLineLength = 0;
00308 }
00309
00317 static NPWErr writeA85(NPW *pdf,
00318 NPWByte const b[], NPWInt n, NPWBoolean end)
00319 {
00320 NPWInt i;
00321 NPWChar s[5];
00322 NPWUInt32 x;
00323 NPWErr err;
00324
00325 for (i = 0, x = 0; i < n; i++)
00326 x = (x << 8) | b[i];
00327 if (n < 4)
00328 x <<= 8 * (4 - n);
00329 for (i = 0; i < 5; i++, x /= 85)
00330 s[4 - i] = '!' + x % 85;
00331 if (n == 4
00332 && s[0] == '!' && s[1] == '!' && s[2] == '!' && s[3] == '!' && s[4] == '!')
00333 err = NPWWrite(pdf, "z", 1);
00334 else
00335 err = NPWWrite(pdf, s, 1 + n);
00336 if (err == kNPWErrOk && end)
00337 err = NPWWrite(pdf, "~>\n", -1);
00338 return err;
00339 }
00340
00346 static NPWErr writeAHex(NPW *pdf, NPWByte b)
00347 {
00348 NPWChar s[2];
00349
00350 s[0] = hex(b >> 4);
00351 s[1] = hex(b & 0xf);
00352 return NPWWrite(pdf, s, 2);
00353 }
00354
00355 NPWErr NPWFilterWrite(NPW *pdf, NPWByte const *b, NPWInt n)
00356 {
00357 NPWInt i = 0;
00358 RLState rl;
00359 NPWErr err;
00360
00361 if (pdf->filter & kNPWFilterRunLength)
00362 RLInit(&rl);
00363
00364
00365 if (pdf->filter & kNPWFilterRunLength)
00366 {
00367 if (pdf->filter & kNPWFilterASCII85)
00368 while (!rl.done)
00369 {
00370 pdf->asciiBuf[pdf->asciiBufCount++] = RLNextByte(&rl, b, n);
00371
00372 if (pdf->asciiBufCount == 4)
00373 {
00374 Chk(writeA85(pdf, pdf->asciiBuf, 4, FALSE));
00375 pdf->asciiBufCount = 0;
00376 }
00377 }
00378 else if (pdf->filter & kNPWFilterASCIIHex)
00379 while (!rl.done)
00380 Chk(writeAHex(pdf, RLNextByte(&rl, b, n)));
00381 else
00382 while (!rl.done)
00383 {
00384
00385 pdf->asciiBuf[0] = RLNextByte(&rl, b, n);
00386 Chk(NPWWrite(pdf, (NPWConstText)pdf->asciiBuf, 1));
00387 }
00388 }
00389 else
00390 if (pdf->filter & kNPWFilterASCII85)
00391 {
00392 for (; i < n; i++)
00393 {
00394 pdf->asciiBuf[pdf->asciiBufCount++] = b[i];
00395
00396 if (pdf->asciiBufCount == 4)
00397 {
00398 Chk(writeA85(pdf, pdf->asciiBuf, 4, FALSE));
00399 pdf->asciiBufCount = 0;
00400 }
00401 }
00402 }
00403 else if (pdf->filter & kNPWFilterASCIIHex)
00404 for (; i < n; i++)
00405 Chk(writeAHex(pdf, b[i]));
00406 else
00407 Chk(NPWWrite(pdf, (NPWConstText)b, n));
00408
00409 return kNPWErrOk;
00410 }
00411
00412 NPWErr NPWFilterEnd(NPW *pdf)
00413 {
00414 if (pdf->filter & kNPWFilterASCII85)
00415 return writeA85(pdf, pdf->asciiBuf, pdf->asciiBufCount, TRUE);
00416 else
00417 return NPWWrite(pdf, "\n", 1);
00418 }
00419
00423 static NPWErr addXRef(NPW *pdf)
00424 {
00425 if (pdf->xrefCount >= pdf->xrefSize)
00426 {
00427 if (pdf->alloc)
00428 {
00429 NPWErr err;
00430
00431 pdf->xrefSize = pdf->xref ? 2 * pdf->xrefSize : 16;
00432 Chk(pdf->alloc((void **)&pdf->xref,
00433 pdf->xrefSize * sizeof(NPWXRef),
00434 pdf->allocUserData));
00435 }
00436 else
00437 return kNPWErrNotEnoughMemory;
00438 }
00439 pdf->xref[pdf->xrefCount].offset = pdf->offset;
00440 pdf->xref[pdf->xrefCount].generation = 0;
00441 pdf->xrefCount++;
00442 return kNPWErrOk;
00443 }
00444
00449 static NPWErr reserveXRef(NPW *pdf, NPWRef *ref)
00450 {
00451 if (pdf->xrefCount >= pdf->xrefSize)
00452 {
00453 if (pdf->alloc)
00454 {
00455 NPWErr err;
00456
00457 pdf->xrefSize = pdf->xref ? 2 * pdf->xrefSize : 16;
00458 Chk(pdf->alloc((void **)&pdf->xref,
00459 pdf->xrefSize * sizeof(NPWXRef),
00460 pdf->allocUserData));
00461 }
00462 else
00463 return kNPWErrNotEnoughMemory;
00464 }
00465 pdf->xref[pdf->xrefCount].offset = -1;
00466 pdf->xref[pdf->xrefCount].generation = -1;
00467 pdf->xrefCount++;
00468 if (ref)
00469 *ref = pdf->xrefCount;
00470 return kNPWErrOk;
00471 }
00472
00477 static NPWErr writeHeader(NPW *pdf)
00478 {
00479 return NPWWrite(pdf, kHeaderStr, -1);
00480 }
00481
00482 NPWErr NPWBeginObj(NPW *pdf, NPWRef *ref)
00483 {
00484 NPWErr err;
00485
00486 if (pdf->writingObject)
00487 return kNPWErrNestedObject;
00488
00489 Chk(addXRef(pdf));
00490 Chk(NPWWriteInt(pdf, pdf->xrefCount, -1));
00491 Chk(NPWWrite(pdf, " 0 obj\n", -1));
00492 if (ref)
00493 *ref = pdf->xrefCount;
00494 pdf->writingObject = TRUE;
00495 return kNPWErrOk;
00496 }
00497
00504 static NPWErr beginReservedObj(NPW *pdf, NPWRef *ref)
00505 {
00506 NPWInt i;
00507 NPWErr err;
00508
00509 if (pdf->writingObject)
00510 return kNPWErrNestedObject;
00511
00512 for (i = pdf->xrefCount - 1; i >= 0 && pdf->xref[i].offset >= 0; i--)
00513 ;
00514 if (i < 0)
00515 return kNPWErrInternal;
00516 pdf->xref[i].offset = pdf->offset;
00517 pdf->xref[i].generation = 0;
00518 Chk(NPWWriteInt(pdf, i + 1, -1));
00519 Chk(NPWWrite(pdf, " 0 obj\n", -1));
00520 if (ref)
00521 *ref = i + 1;
00522 pdf->writingObject = TRUE;
00523 return kNPWErrOk;
00524 }
00525
00526 NPWErr NPWEndObj(NPW *pdf)
00527 {
00528 if (!pdf->writingObject)
00529 return kNPWErrUnbalancedObj;
00530 pdf->writingObject = FALSE;
00531 return NPWWrite(pdf, "endobj\n\n", -1);
00532 }
00533
00534 static NPWErr writePage(NPW *pdf, NPWInt i, NPWRef parent, NPWRef *ref)
00535 {
00536 NPWInt j;
00537 NPWBoolean oneSize;
00538 NPWErr err;
00539
00540 for (j = 0, oneSize = TRUE; j < pdf->pageCount; j++)
00541 oneSize &= pdf->page[j].width == pdf->page[0].width
00542 && pdf->page[j].height == pdf->page[0].height;
00543
00544 Chk(NPWBeginObj(pdf, ref));
00545 Chk(NPWWrite(pdf, "<<\n/Type /Page\n/Parent ", -1));
00546 Chk(NPWWriteInt(pdf, parent, -1));
00547 Chk(NPWWrite(pdf, " 0 R\n", -1));
00548 if (pdf->page[i].contents >= 0)
00549 {
00550 Chk(NPWWrite(pdf, "/Contents ", -1));
00551 Chk(NPWWriteInt(pdf, pdf->page[i].contents, -1));
00552 Chk(NPWWrite(pdf, " 0 R\n", -1));
00553 }
00554 if (!oneSize)
00555 {
00556 Chk(NPWWrite(pdf, "/MediaBox [0 0 ", -1));
00557 Chk(NPWWriteInt(pdf, pdf->page[i].width, -1));
00558 Chk(NPWWrite(pdf, " ", -1));
00559 Chk(NPWWriteInt(pdf, pdf->page[i].height, -1));
00560 Chk(NPWWrite(pdf, "]\n", -1));
00561 }
00562 Chk(NPWWrite(pdf, ">>\n", -1));
00563 Chk(NPWEndObj(pdf));
00564 return kNPWErrOk;
00565 }
00566
00567 static NPWErr writePages(NPW *pdf, NPWRef *ref)
00568 {
00569 NPWInt i;
00570 NPWBoolean oneSize;
00571 NPWErr err;
00572
00573 Chk(NPWBeginObj(pdf, ref));
00574 Chk(NPWWrite(pdf, "<<\n/Type /Pages\n/Kids\n[\n", -1));
00575 for (i = 0, oneSize = TRUE; i < pdf->pageCount; i++)
00576 {
00577 Chk(NPWWriteInt(pdf, *ref + 1 + i, -1));
00578 Chk(NPWWrite(pdf, " 0 R\n", -1));
00579 oneSize &= pdf->page[i].width == pdf->page[0].width
00580 && pdf->page[i].height == pdf->page[0].height;
00581 }
00582 Chk(NPWWrite(pdf, "]\n/Count ", -1));
00583 Chk(NPWWriteInt(pdf, pdf->pageCount, -1));
00584 Chk(NPWWrite(pdf, "\n", -1));
00585 if (pdf->pageCount > 0 && oneSize)
00586 {
00587 Chk(NPWWrite(pdf, "/MediaBox [0 0 ", -1));
00588 Chk(NPWWriteInt(pdf, pdf->page[0].width, -1));
00589 Chk(NPWWrite(pdf, " ", -1));
00590 Chk(NPWWriteInt(pdf, pdf->page[0].height, -1));
00591 Chk(NPWWrite(pdf, "]\n", -1));
00592 }
00593 if (pdf->fonts != kNPWFontNone)
00594 {
00595 Chk(NPWWrite(pdf, "/Resources\n<<\n/Font\n<<\n", -1));
00596 if (pdf->fonts & kNPWFontCourier)
00597 Chk(NPWWrite(pdf,
00598 NPWFontNameCourier
00599 " << /Type /Font /Subtype /Type1 /BaseFont /Courier /Encoding /WinAnsiEncoding >>\n",
00600 -1));
00601 if (pdf->fonts & kNPWFontCourierOblique)
00602 Chk(NPWWrite(pdf,
00603 NPWFontNameCourierOblique
00604 " << /Type /Font /Subtype /Type1 /BaseFont /Courier-Oblique /Encoding /WinAnsiEncoding >>\n",
00605 -1));
00606 if (pdf->fonts & kNPWFontCourierBold)
00607 Chk(NPWWrite(pdf,
00608 NPWFontNameCourierBold
00609 " << /Type /Font /Subtype /Type1 /BaseFont /Courier-Bold /Encoding /WinAnsiEncoding >>\n",
00610 -1));
00611 if (pdf->fonts & kNPWFontCourierBoldOblique)
00612 Chk(NPWWrite(pdf,
00613 NPWFontNameCourierBoldOblique
00614 " << /Type /Font /Subtype /Type1 /BaseFont /Courier-BoldOblique /Encoding /WinAnsiEncoding >>\n",
00615 -1));
00616 if (pdf->fonts & kNPWFontHelvetica)
00617 Chk(NPWWrite(pdf,
00618 NPWFontNameHelvetica
00619 " << /Type /Font /Subtype /Type1 /BaseFont /Helvetica /Encoding /WinAnsiEncoding >>\n",
00620 -1));
00621 if (pdf->fonts & kNPWFontHelveticaOblique)
00622 Chk(NPWWrite(pdf,
00623 NPWFontNameHelveticaOblique
00624 " << /Type /Font /Subtype /Type1 /BaseFont /Helvetica-Oblique /Encoding /WinAnsiEncoding >>\n",
00625 -1));
00626 if (pdf->fonts & kNPWFontHelveticaBold)
00627 Chk(NPWWrite(pdf,
00628 NPWFontNameHelveticaBold
00629 " << /Type /Font /Subtype /Type1 /BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding >>\n",
00630 -1));
00631 if (pdf->fonts & kNPWFontHelveticaBoldOblique)
00632 Chk(NPWWrite(pdf,
00633 NPWFontNameHelveticaBoldOblique
00634 " << /Type /Font /Subtype /Type1 /BaseFont /Helvetica-BoldOblique /Encoding /WinAnsiEncoding >>\n",
00635 -1));
00636 if (pdf->fonts & kNPWFontTimesRoman)
00637 Chk(NPWWrite(pdf,
00638 NPWFontNameTimesRoman
00639 " << /Type /Font /Subtype /Type1 /BaseFont /Times-Roman /Encoding /WinAnsiEncoding >>\n",
00640 -1));
00641 if (pdf->fonts & kNPWFontTimesItalic)
00642 Chk(NPWWrite(pdf,
00643 NPWFontNameTimesItalic
00644 " << /Type /Font /Subtype /Type1 /BaseFont /Times-Italic /Encoding /WinAnsiEncoding >>\n",
00645 -1));
00646 if (pdf->fonts & kNPWFontTimesBold)
00647 Chk(NPWWrite(pdf,
00648 NPWFontNameTimesBold
00649 " << /Type /Font /Subtype /Type1 /BaseFont /Times-Bold /Encoding /WinAnsiEncoding >>\n",
00650 -1));
00651 if (pdf->fonts & kNPWFontTimesBoldItalic)
00652 Chk(NPWWrite(pdf,
00653 NPWFontNameTimesBoldItalic
00654 " << /Type /Font /Subtype /Type1 /BaseFont /Times-BoldItalic /Encoding /WinAnsiEncoding >>\n",
00655 -1));
00656 if (pdf->fonts & kNPWFontSymbol)
00657 Chk(NPWWrite(pdf,
00658 NPWFontNameSymbol
00659 " << /Type /Font /Subtype /Type1 /BaseFont /Symbol /Encoding /WinAnsiEncoding >>\n",
00660 -1));
00661 if (pdf->fonts & kNPWFontZapfDingbats)
00662 Chk(NPWWrite(pdf,
00663 NPWFontNameZapfDingbats
00664 " << /Type /Font /Subtype /Type1 /BaseFont /ZapfDingbats /Encoding /WinAnsiEncoding >>\n",
00665 -1));
00666 Chk(NPWWrite(pdf, ">>\n>>\n", -1));
00667 }
00668 Chk(NPWWrite(pdf, ">>\n", -1));
00669 Chk(NPWEndObj(pdf));
00670
00671 return kNPWErrOk;
00672 }
00673
00680 static NPWErr writeCatalog(NPW *pdf, NPWRef pages, NPWRef *ref)
00681 {
00682 NPWErr err;
00683
00684 Chk(NPWBeginObj(pdf, ref));
00685 Chk(NPWWrite(pdf, "<<\n/Type /Catalog\n/Pages ", -1));
00686 Chk(NPWWriteInt(pdf, pages, -1));
00687 Chk(NPWWrite(pdf, " 0 R\n>>\n", -1));
00688 Chk(NPWEndObj(pdf));
00689 return kNPWErrOk;
00690 }
00691
00692 NPWErr NPWBeginPage(NPW *pdf, NPWInt width, NPWInt height)
00693 {
00694 NPWRef ref;
00695 NPWErr err;
00696
00697
00698 if (pdf->offset == 0)
00699 Chk(writeHeader(pdf));
00700
00701
00702 if (pdf->pageCount >= pdf->pageSize)
00703 {
00704 if (pdf->alloc)
00705 {
00706 pdf->pageSize = pdf->page ? 2 * pdf->pageSize : 16;
00707 Chk(pdf->alloc((void **)&pdf->page,
00708 pdf->pageSize * sizeof(NPWPage),
00709 pdf->allocUserData));
00710 }
00711 else
00712 return kNPWErrNotEnoughMemory;
00713 }
00714 pdf->page[pdf->pageCount].width = width;
00715 pdf->page[pdf->pageCount].height = height;
00716 Chk(NPWBeginObj(pdf, &pdf->page[pdf->pageCount].contents));
00717
00718
00719 Chk(NPWWrite(pdf, "<< /Length ", -1));
00720 Chk(reserveXRef(pdf, &ref));
00721 Chk(NPWWriteInt(pdf, ref, -1));
00722 Chk(NPWWrite(pdf, " 0 R >>\nstream\n", -1));
00723 pdf->page[pdf->pageCount].streamOffset = pdf->offset;
00724
00725 pdf->pageCount++;
00726
00727 return kNPWErrOk;
00728 }
00729
00730 NPWErr NPWEndPage(NPW *pdf)
00731 {
00732 NPWInt length;
00733 NPWInt err;
00734
00735
00736 length = pdf->offset - pdf->page[pdf->pageCount - 1].streamOffset;
00737 Chk(NPWWrite(pdf, "endstream\n", -1));
00738 Chk(NPWEndObj(pdf));
00739
00740
00741 Chk(beginReservedObj(pdf, NULL));
00742 Chk(NPWWriteInt(pdf, length, -1));
00743 Chk(NPWWrite(pdf, "\n", -1));
00744 Chk(NPWEndObj(pdf));
00745 return kNPWErrOk;
00746 }
00747
00748 NPWErr NPWTerminate(NPW *pdf)
00749 {
00750 NPWOffset xrefTableOffset;
00751 NPWInt i;
00752 NPWRef pages, root;
00753 NPWErr err;
00754
00755
00756 if (pdf->offset == 0)
00757 ChkG(writeHeader(pdf));
00758
00759
00760 ChkG(writePages(pdf, &pages));
00761
00762
00763 for (i = 0; i < pdf->pageCount; i++)
00764 ChkG(writePage(pdf, i, pages, NULL));
00765
00766
00767 ChkG(writeCatalog(pdf, pages, &root));
00768
00769
00770 xrefTableOffset = pdf->offset;
00771
00772
00773 NPWWrite(pdf, "xref\n0 ", -1);
00774 NPWWriteInt(pdf, pdf->xrefCount + 1, -1);
00775 NPWWrite(pdf, "\n", -1);
00776 NPWWrite(pdf, "0000000000 65535 f \n", -1);
00777 for (i = 0; i < pdf->xrefCount; i++)
00778 {
00779 NPWWriteInt(pdf, pdf->xref[i].offset, 10);
00780 NPWWrite(pdf, " ", -1);
00781 NPWWriteInt(pdf, pdf->xref[i].generation, 5);
00782 NPWWrite(pdf, " n \n", -1);
00783 }
00784
00785
00786 NPWWrite(pdf, "trailer\n<<\n", -1);
00787 NPWWrite(pdf, "/Size ", -1);
00788 NPWWriteInt(pdf, pdf->xrefCount, -1);
00789 NPWWrite(pdf, "\n", -1);
00790 NPWWrite(pdf, "/Root ", -1);
00791 NPWWriteInt(pdf, root, -1);
00792 NPWWrite(pdf, " 0 R\n", -1);
00793 if (pdf->info != kNPWNoRef)
00794 {
00795 ChkG(NPWWrite(pdf, "/Info ", -1));
00796 ChkG(NPWWriteInt(pdf, pdf->info, -1));
00797 ChkG(NPWWrite(pdf, " 0 R\n", -1));
00798 }
00799 NPWWrite(pdf, ">>\n", -1);
00800
00801
00802 NPWWrite(pdf, "startxref\n", -1);
00803 NPWWriteInt(pdf, xrefTableOffset, -1);
00804 NPWWrite(pdf, "\n", -1);
00805
00806
00807 NPWWrite(pdf, "%%EOF\n", -1);
00808
00809 error:
00810
00811 if (pdf->alloc)
00812 {
00813 if (pdf->xref)
00814 (void)pdf->alloc((void **)&pdf->xref, -1, pdf->allocUserData);
00815 if (pdf->page)
00816 (void)pdf->alloc((void **)&pdf->page, -1, pdf->allocUserData);
00817 }
00818
00819 return err;
00820 }