1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * Copyright (C) 2016 Mopria Alliance, Inc. 4 * Copyright (C) 2013 Hewlett-Packard Development Company, L.P. 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 #include "../../media.h" 20 #include <PCLmGenerator.h> 21 22 #include <assert.h> 23 #include <math.h> 24 #include <zlib.h> 25 #include <stdio.h> 26 #include <string.h> 27 #include <stdlib.h> 28 #include <genPCLm.h> 29 30 #define TAG "genPCLm" 31 32 #define STRIP_HEIGHT 16 33 #define JPEG_QUALITY 100 34 #define TEMP_BUFF_SIZE 10000000 35 #define DEFAULT_OUTBUFF_SIZE 64*5120*3*10 36 #define STANDARD_SCALE_FOR_PDF 72.0 37 #define KID_STRING_SIZE 1000 38 #define CATALOG_OBJ_NUMBER 1 39 #define PAGES_OBJ_NUMBER 2 40 #define ADOBE_RGB_SIZE 284 41 42 #define rgb_2_gray(r, g, b) (ubyte)(0.299*(double)r+0.587*(double)g+0.114*(double)b) 43 44 static PCLmSUserSettingsType PCLmSSettings; 45 46 /* 47 * Shift the strip image right in the strip buffer by leftMargin pixels. 48 * 49 * Assumptions: The strip buffer was allocated large enough to handle the shift; if not 50 * then the image data on the right will get clipped. 51 * 52 * We allocate a full strip (height and width), but then only copy numLinesThisCall from 53 * the original buffer to the newly allocated buffer. This pads the strips for JPEG processing. 54 */ 55 static ubyte *shiftStripByLeftMargin(ubyte *ptrToStrip, sint32 currSourceWidth, 56 sint32 currStripHeight, sint32 numLinesThisCall, sint32 currMediaWidth, sint32 leftMargin, 57 colorSpaceDisposition destColorSpace) { 58 ubyte *fromPtr, *toPtr, *newStrip; 59 sint32 scanLineWidth; 60 61 if (destColorSpace == grayScale) { 62 scanLineWidth = currMediaWidth; 63 64 // Allocate a full strip 65 newStrip = (ubyte *) malloc(scanLineWidth * currStripHeight); 66 memset(newStrip, 0xff, scanLineWidth * currStripHeight); 67 for (int i = 0; i < numLinesThisCall; i++) { 68 toPtr = newStrip + leftMargin + (i * currMediaWidth); 69 fromPtr = ptrToStrip + (i * currSourceWidth); 70 memcpy(toPtr, fromPtr, currSourceWidth); 71 } 72 } else { 73 scanLineWidth = currMediaWidth * 3; 74 sint32 srcScanlineWidth = currSourceWidth * 3; 75 sint32 shiftAmount = leftMargin * 3; 76 newStrip = (ubyte *) malloc(scanLineWidth * currStripHeight); 77 memset(newStrip, 0xff, scanLineWidth * currStripHeight); 78 for (int i = 0; i < numLinesThisCall; i++) { 79 toPtr = newStrip + shiftAmount + (i * scanLineWidth); 80 fromPtr = ptrToStrip + (i * srcScanlineWidth); 81 memcpy(toPtr, fromPtr, srcScanlineWidth); 82 } 83 } 84 85 return newStrip; 86 } 87 88 #ifdef SUPPORT_WHITE_STRIPS 89 90 bool PCLmGenerator::isWhiteStrip(void *pInBuffer, int inBufferSize) { 91 uint32 *ptr = (uint32 *) pInBuffer; 92 for (int i = 0; i < inBufferSize / 4; i++, ptr++) { 93 if (*ptr != 0xffffffff) { 94 return false; 95 } 96 } 97 return true; 98 } 99 100 #endif 101 102 void PCLmGenerator::Cleanup(void) { 103 if (allocatedOutputBuffer) { 104 free(allocatedOutputBuffer); 105 allocatedOutputBuffer = NULL; 106 currOutBuffSize = 0; 107 } 108 109 if (leftoverScanlineBuffer) { 110 free(leftoverScanlineBuffer); 111 leftoverScanlineBuffer = NULL; 112 } 113 if (scratchBuffer) { 114 free(scratchBuffer); 115 scratchBuffer = NULL; 116 } 117 if (xRefTable) { 118 free(xRefTable); 119 xRefTable = NULL; 120 } 121 if (KidsArray) { 122 free(KidsArray); 123 KidsArray = NULL; 124 } 125 } 126 127 int PCLmGenerator::errorOutAndCleanUp() { 128 Cleanup(); 129 jobOpen = job_errored; 130 return genericFailure; 131 } 132 133 static sint32 startXRef = 0; 134 static sint32 endXRef = 0; 135 136 /* 137 * DO NOT EDIT UNTIL YOU READ THE HEADER FILE DESCRIPTION. 138 */ 139 void PCLmGenerator::fixXRef() { 140 if (!startXRef || !mirrorBackside) { 141 return; 142 } 143 144 if (currDuplexDisposition == duplex_longEdge && !(pageCount % 2) && mirrorBackside) { 145 assert(startXRef); 146 sint32 start = startXRef; 147 sint32 end = endXRef - 1; 148 sint32 aSize = endXRef - startXRef - 1; 149 150 sint32 *tmpArray = (sint32 *) malloc(aSize * 20); 151 152 sint32 xRefI = startXRef; 153 for (int i = 0; i < aSize + 1; i++, xRefI++) { 154 *(tmpArray + i) = xRefTable[xRefI + 1] - xRefTable[xRefI]; 155 } 156 157 // Reorder header and image sizes 158 for (int i = 0; i < aSize + 1; i += 2, xRefI++) { 159 sint32 t = *(tmpArray + i); 160 *(tmpArray + i) = *(tmpArray + i + 1); 161 *(tmpArray + i + 1) = t; 162 } 163 164 xRefI = aSize; 165 for (int i = start + 1, j = aSize; i < end + 2; i++, start++, xRefI--, j--) { 166 xRefTable[i] = (xRefTable[i - 1] + *(tmpArray + j)); 167 } 168 169 for (int i = startXRef + 2; i < endXRef; i++) { 170 xRefTable[i] += 2; 171 } 172 173 sint32 k = endXRef - 1; 174 int i; 175 sint32 lSize = (endXRef - startXRef) / 2; 176 for (i = startXRef; i < startXRef + lSize; i++, k--) { 177 sint32 t = xRefTable[i]; 178 xRefTable[i] = xRefTable[k]; 179 xRefTable[k] = t; 180 } 181 free(tmpArray); 182 } 183 184 startXRef = 0; 185 } 186 187 bool PCLmGenerator::addXRef(sint32 xRefObj) { 188 #define XREF_ARRAY_SIZE 100 189 if (!xRefTable) { 190 xRefTable = (sint32 *) malloc(XREF_ARRAY_SIZE * sizeof(sint32)); 191 assert(xRefTable); 192 xRefTable[0] = 0; 193 xRefIndex++; 194 } 195 196 xRefTable[xRefIndex] = xRefObj; 197 xRefIndex++; 198 199 if (!(xRefIndex % XREF_ARRAY_SIZE)) { 200 xRefTable = (sint32 *) realloc(xRefTable, (((xRefIndex + XREF_ARRAY_SIZE) * 201 sizeof(sint32)))); 202 } 203 return true; 204 } 205 206 bool PCLmGenerator::addKids(sint32 kidObj) { 207 #define KID_ARRAY_SIZE 20 208 if (!KidsArray) { 209 KidsArray = (sint32 *) malloc(KID_ARRAY_SIZE * sizeof(sint32)); 210 assert(KidsArray); 211 } 212 213 KidsArray[numKids] = kidObj; 214 numKids++; 215 216 if (!(numKids % KID_ARRAY_SIZE)) { 217 KidsArray = (sint32 *) realloc(KidsArray, ((numKids + KID_ARRAY_SIZE) * sizeof(sint32))); 218 } 219 return true; 220 } 221 222 void PCLmGenerator::initOutBuff(char *buff, sint32 size) { 223 currBuffPtr = outBuffPtr = buff; 224 outBuffSize = size; 225 totalBytesWrittenToCurrBuff = 0; 226 memset(buff, 0, size); 227 } 228 229 void PCLmGenerator::writeStr2OutBuff(char *str) { 230 sint32 strSize = strlen(str); 231 // Make sure we have enough room for the copy 232 char *maxSize = currBuffPtr + strSize; 233 assert(maxSize - outBuffPtr < outBuffSize); 234 memcpy(currBuffPtr, str, strSize); 235 currBuffPtr += strSize; 236 totalBytesWrittenToCurrBuff += strSize; 237 totalBytesWrittenToPCLmFile += strSize; 238 } 239 240 void PCLmGenerator::write2Buff(ubyte *buff, int buffSize) { 241 char *maxSize = currBuffPtr + buffSize; 242 if (maxSize - outBuffPtr > outBuffSize) { 243 assert(0); 244 } 245 memcpy(currBuffPtr, buff, buffSize); 246 currBuffPtr += buffSize; 247 totalBytesWrittenToCurrBuff += buffSize; 248 totalBytesWrittenToPCLmFile += buffSize; 249 } 250 251 int PCLmGenerator::statOutputFileSize() { 252 addXRef(totalBytesWrittenToPCLmFile); 253 return (1); 254 } 255 256 void PCLmGenerator::writePDFGrammarTrailer(int imageWidth, int imageHeight) { 257 int i; 258 char KidsString[KID_STRING_SIZE]; 259 260 sprintf(pOutStr, "%%============= PCLm: FileBody: Object 1 - Catalog\n"); 261 writeStr2OutBuff(pOutStr); 262 statOutputFileSize(); 263 sprintf(pOutStr, "%d 0 obj\n", CATALOG_OBJ_NUMBER); 264 writeStr2OutBuff(pOutStr); 265 sprintf(pOutStr, "<<\n"); 266 writeStr2OutBuff(pOutStr); 267 sprintf(pOutStr, "/Type /Catalog\n"); 268 writeStr2OutBuff(pOutStr); 269 sprintf(pOutStr, "/Pages %d 0 R\n", PAGES_OBJ_NUMBER); 270 writeStr2OutBuff(pOutStr); 271 sprintf(pOutStr, ">>\n"); 272 writeStr2OutBuff(pOutStr); 273 sprintf(pOutStr, "endobj\n"); 274 writeStr2OutBuff(pOutStr); 275 276 sprintf(pOutStr, "%%============= PCLm: FileBody: Object 2 - page tree \n"); 277 writeStr2OutBuff(pOutStr); 278 statOutputFileSize(); 279 sprintf(pOutStr, "%d 0 obj\n", PAGES_OBJ_NUMBER); 280 writeStr2OutBuff(pOutStr); 281 sprintf(pOutStr, "<<\n"); 282 writeStr2OutBuff(pOutStr); 283 sprintf(pOutStr, "/Count %ld\n", numKids); 284 writeStr2OutBuff(pOutStr); 285 286 // Define the Kids for this document as an indirect array 287 sprintf(KidsString, "/Kids [ "); 288 writeStr2OutBuff(KidsString); 289 for (i = 0; i < numKids; i++) { 290 sprintf(KidsString, "%ld 0 R ", KidsArray[i]); 291 writeStr2OutBuff(KidsString); 292 } 293 294 sprintf(KidsString, "]\n"); 295 writeStr2OutBuff(KidsString); 296 297 sprintf(pOutStr, "/Type /Pages\n"); 298 writeStr2OutBuff(pOutStr); 299 sprintf(pOutStr, ">>\n"); 300 writeStr2OutBuff(pOutStr); 301 sprintf(pOutStr, "endobj\n"); 302 writeStr2OutBuff(pOutStr); 303 304 sprintf(pOutStr, "%%============= PCLm: cross-reference section: object 0, 6 entries\n"); 305 writeStr2OutBuff(pOutStr); 306 statOutputFileSize(); 307 308 // Fix up the xref table for backside duplex 309 fixXRef(); 310 311 xRefStart = xRefIndex - 1; 312 313 sprintf(pOutStr, "xref\n"); 314 writeStr2OutBuff(pOutStr); 315 sprintf(pOutStr, "0 %d\n", 1); 316 writeStr2OutBuff(pOutStr); 317 318 // Note the attempt to write exactly 20 bytes 319 sprintf(pOutStr, "0000000000 65535 f \n"); 320 writeStr2OutBuff(pOutStr); 321 sprintf(pOutStr, "%d %ld\n", PAGES_OBJ_NUMBER + 1, xRefIndex - 4); 322 writeStr2OutBuff(pOutStr); 323 for (i = 1; i < xRefIndex - 3; i++) { 324 sprintf(pOutStr, "%010ld %05d n \n", xRefTable[i], 0); 325 writeStr2OutBuff(pOutStr); 326 } 327 328 // sprintf(pOutStr,"<</AIMetaData 32 0 R/AIPDFPrivateData1 33 0 R/AIPDFPrivateData10 34 0\n"); 329 330 // Now add the catalog and page object 331 sprintf(pOutStr, "%d 2\n", CATALOG_OBJ_NUMBER); 332 writeStr2OutBuff(pOutStr); 333 sprintf(pOutStr, "%010ld %05d n \n", xRefTable[xRefIndex - 3], 0); 334 writeStr2OutBuff(pOutStr); 335 sprintf(pOutStr, "%010ld %05d n \n", xRefTable[xRefIndex - 2], 0); 336 writeStr2OutBuff(pOutStr); 337 338 sprintf(pOutStr, "%%============= PCLm: File Trailer\n"); 339 writeStr2OutBuff(pOutStr); 340 sprintf(pOutStr, "trailer\n"); 341 writeStr2OutBuff(pOutStr); 342 sprintf(pOutStr, "<<\n"); 343 writeStr2OutBuff(pOutStr); 344 // sprintf(pOutStr,"/Info %d 0\n", infoObj); writeStr2OutBuff(pOutStr); 345 sprintf(pOutStr, "/Size %ld\n", xRefIndex - 1); 346 writeStr2OutBuff(pOutStr); 347 sprintf(pOutStr, "/Root %d 0 R\n", CATALOG_OBJ_NUMBER); 348 writeStr2OutBuff(pOutStr); 349 sprintf(pOutStr, ">>\n"); 350 writeStr2OutBuff(pOutStr); 351 sprintf(pOutStr, "startxref\n"); 352 writeStr2OutBuff(pOutStr); 353 sprintf(pOutStr, "%ld\n", xRefTable[xRefStart]); 354 writeStr2OutBuff(pOutStr); 355 sprintf(pOutStr, "%%%%EOF\n"); 356 writeStr2OutBuff(pOutStr); 357 } 358 359 bool PCLmGenerator::injectAdobeRGBCS() { 360 if (adobeRGBCS_firstTime) { 361 // We need to inject the ICC object for AdobeRGB 362 sprintf(pOutStr, "%%============= PCLm: ICC Profile\n"); 363 writeStr2OutBuff(pOutStr); 364 statOutputFileSize(); 365 sprintf(pOutStr, "%ld 0 obj\n", objCounter); 366 objCounter++; 367 writeStr2OutBuff(pOutStr); 368 sprintf(pOutStr, "[/ICCBased %ld 0 R]\n", objCounter); 369 writeStr2OutBuff(pOutStr); 370 371 sprintf(pOutStr, "endobj\n"); 372 writeStr2OutBuff(pOutStr); 373 statOutputFileSize(); 374 sprintf(pOutStr, "%ld 0 obj\n", objCounter); 375 objCounter++; 376 writeStr2OutBuff(pOutStr); 377 sprintf(pOutStr, "<<\n"); 378 writeStr2OutBuff(pOutStr); 379 sprintf(pOutStr, "/N 3\n"); 380 writeStr2OutBuff(pOutStr); 381 sprintf(pOutStr, "/Alternate /DeviceRGB\n"); 382 writeStr2OutBuff(pOutStr); 383 sprintf(pOutStr, "/Length %u\n", ADOBE_RGB_SIZE + 1); 384 writeStr2OutBuff(pOutStr); 385 sprintf(pOutStr, "/Filter /FlateDecode\n"); 386 writeStr2OutBuff(pOutStr); 387 sprintf(pOutStr, ">>\n"); 388 writeStr2OutBuff(pOutStr); 389 sprintf(pOutStr, "stream\n"); 390 writeStr2OutBuff(pOutStr); 391 392 FILE *inFile; 393 if (!(inFile = fopen("flate_colorspace.bin", "rb"))) { 394 fprintf(stderr, "can't open %s\n", "flate_colorspace.bin"); 395 return 0; 396 } 397 398 ubyte *buffIn = (unsigned char *) malloc(ADOBE_RGB_SIZE); 399 assert(buffIn); 400 401 sint32 bytesRead = fread(buffIn, 1, ADOBE_RGB_SIZE, inFile); 402 assert(bytesRead == ADOBE_RGB_SIZE); 403 fclose(inFile); 404 write2Buff(buffIn, bytesRead); 405 if (buffIn) { 406 free(buffIn); 407 } 408 409 sprintf(pOutStr, "\nendstream\n"); 410 writeStr2OutBuff(pOutStr); 411 sprintf(pOutStr, "endobj\n"); 412 writeStr2OutBuff(pOutStr); 413 } 414 415 adobeRGBCS_firstTime = false; 416 return true; 417 } 418 419 bool PCLmGenerator::colorConvertSource(colorSpaceDisposition srcCS, colorSpaceDisposition dstCS, 420 ubyte *strip, sint32 stripWidth, sint32 stripHeight) { 421 if (srcCS == deviceRGB && dstCS == grayScale) { 422 // Do an inplace conversion from RGB -> 8 bpp gray 423 ubyte *srcPtr = strip; 424 ubyte *dstPtr = strip; 425 for (int h = 0; h < stripHeight; h++) { 426 for (int w = 0; w < stripWidth; w++, dstPtr++, srcPtr += 3) { 427 *dstPtr = (ubyte) rgb_2_gray(*srcPtr, *(srcPtr + 1), *(srcPtr + 2)); 428 } 429 } 430 dstNumComponents = 1; 431 } else { 432 assert(0); 433 } 434 435 return true; 436 } 437 438 int PCLmGenerator::injectRLEStrip(ubyte *RLEBuffer, int numBytes, int imageWidth, int imageHeight, 439 colorSpaceDisposition destColorSpace, bool whiteStrip) { 440 bool printedImageTransform = false; 441 442 if (currDuplexDisposition == duplex_longEdge && !(pageCount % 2) && mirrorBackside) { 443 if (!startXRef) { 444 startXRef = xRefIndex; 445 } 446 447 injectImageTransform(); 448 printedImageTransform = true; 449 } 450 451 if (destColorSpace == adobeRGB) { 452 injectAdobeRGBCS(); 453 } 454 455 // Inject LZ compressed image into PDF file 456 sprintf(pOutStr, "%%============= PCLm: FileBody: Strip Stream: RLE Image \n"); 457 writeStr2OutBuff(pOutStr); 458 statOutputFileSize(); 459 460 if (currDuplexDisposition == duplex_longEdge && !(pageCount % 2) && mirrorBackside) { 461 sprintf(pOutStr, "%ld 0 obj\n", objCounter - 1); 462 objCounter++; 463 writeStr2OutBuff(pOutStr); 464 } else { 465 sprintf(pOutStr, "%ld 0 obj\n", objCounter); 466 objCounter++; 467 writeStr2OutBuff(pOutStr); 468 } 469 470 sprintf(pOutStr, "<<\n"); 471 writeStr2OutBuff(pOutStr); 472 sprintf(pOutStr, "/Width %d\n", imageWidth); 473 writeStr2OutBuff(pOutStr); 474 if (destColorSpace == deviceRGB) { 475 sprintf(pOutStr, "/ColorSpace /DeviceRGB\n"); 476 writeStr2OutBuff(pOutStr); 477 } else if (destColorSpace == adobeRGB) { 478 sprintf(pOutStr, "/ColorSpace 5 0 R\n"); 479 writeStr2OutBuff(pOutStr); 480 } else { 481 sprintf(pOutStr, "/ColorSpace /DeviceGray\n"); 482 writeStr2OutBuff(pOutStr); 483 } 484 sprintf(pOutStr, "/Height %d\n", imageHeight); 485 writeStr2OutBuff(pOutStr); 486 sprintf(pOutStr, "/Filter /RunLengthDecode\n"); 487 writeStr2OutBuff(pOutStr); 488 sprintf(pOutStr, "/Subtype /Image\n"); 489 writeStr2OutBuff(pOutStr); 490 sprintf(pOutStr, "/Length %d\n", numBytes); 491 writeStr2OutBuff(pOutStr); 492 sprintf(pOutStr, "/Type /XObject\n"); 493 writeStr2OutBuff(pOutStr); 494 sprintf(pOutStr, "/BitsPerComponent 8\n"); 495 writeStr2OutBuff(pOutStr); 496 #ifdef SUPPORT_WHITE_STRIPS 497 if (whiteStrip) { 498 sprintf(pOutStr, "/Name /WhiteStrip\n"); 499 writeStr2OutBuff(pOutStr); 500 } else { 501 sprintf(pOutStr, "/Name /ColorStrip\n"); 502 writeStr2OutBuff(pOutStr); 503 } 504 #endif 505 506 sprintf(pOutStr, ">>\n"); 507 writeStr2OutBuff(pOutStr); 508 sprintf(pOutStr, "stream\n"); 509 writeStr2OutBuff(pOutStr); 510 511 // Write the zlib compressed strip to the PDF output file 512 write2Buff(RLEBuffer, numBytes); 513 sprintf(pOutStr, "\nendstream\n"); 514 writeStr2OutBuff(pOutStr); 515 sprintf(pOutStr, "endobj\n"); 516 writeStr2OutBuff(pOutStr); 517 518 if (!printedImageTransform) { 519 injectImageTransform(); 520 } 521 522 endXRef = xRefIndex; 523 524 return (1); 525 } 526 527 int PCLmGenerator::injectLZStrip(ubyte *LZBuffer, int numBytes, int imageWidth, int imageHeight, 528 colorSpaceDisposition destColorSpace, bool whiteStrip) { 529 bool printedImageTransform = false; 530 531 if (currDuplexDisposition == duplex_longEdge && !(pageCount % 2) && mirrorBackside) { 532 if (!startXRef) { 533 startXRef = xRefIndex; 534 } 535 536 injectImageTransform(); 537 printedImageTransform = true; 538 } 539 540 if (destColorSpace == adobeRGB) { 541 injectAdobeRGBCS(); 542 } 543 544 // Inject LZ compressed image into PDF file 545 sprintf(pOutStr, "%%============= PCLm: FileBody: Strip Stream: zlib Image \n"); 546 writeStr2OutBuff(pOutStr); 547 statOutputFileSize(); 548 549 if (currDuplexDisposition == duplex_longEdge && !(pageCount % 2) && mirrorBackside) { 550 sprintf(pOutStr, "%ld 0 obj\n", objCounter - 1); 551 objCounter++; 552 writeStr2OutBuff(pOutStr); 553 } else { 554 sprintf(pOutStr, "%ld 0 obj\n", objCounter); 555 objCounter++; 556 writeStr2OutBuff(pOutStr); 557 } 558 559 sprintf(pOutStr, "<<\n"); 560 writeStr2OutBuff(pOutStr); 561 sprintf(pOutStr, "/Width %d\n", imageWidth); 562 writeStr2OutBuff(pOutStr); 563 if (destColorSpace == deviceRGB) { 564 sprintf(pOutStr, "/ColorSpace /DeviceRGB\n"); 565 writeStr2OutBuff(pOutStr); 566 } else if (destColorSpace == adobeRGB) { 567 sprintf(pOutStr, "/ColorSpace 5 0 R\n"); 568 writeStr2OutBuff(pOutStr); 569 } else { 570 sprintf(pOutStr, "/ColorSpace /DeviceGray\n"); 571 writeStr2OutBuff(pOutStr); 572 } 573 sprintf(pOutStr, "/Height %d\n", imageHeight); 574 writeStr2OutBuff(pOutStr); 575 sprintf(pOutStr, "/Filter /FlateDecode\n"); 576 writeStr2OutBuff(pOutStr); 577 sprintf(pOutStr, "/Subtype /Image\n"); 578 writeStr2OutBuff(pOutStr); 579 sprintf(pOutStr, "/Length %d\n", numBytes); 580 writeStr2OutBuff(pOutStr); 581 sprintf(pOutStr, "/Type /XObject\n"); 582 writeStr2OutBuff(pOutStr); 583 sprintf(pOutStr, "/BitsPerComponent 8\n"); 584 writeStr2OutBuff(pOutStr); 585 #ifdef SUPPORT_WHITE_STRIPS 586 if (whiteStrip) { 587 sprintf(pOutStr, "/Name /WhiteStrip\n"); 588 writeStr2OutBuff(pOutStr); 589 } else { 590 sprintf(pOutStr, "/Name /ColorStrip\n"); 591 writeStr2OutBuff(pOutStr); 592 } 593 #endif 594 595 sprintf(pOutStr, ">>\n"); 596 writeStr2OutBuff(pOutStr); 597 sprintf(pOutStr, "stream\n"); 598 writeStr2OutBuff(pOutStr); 599 600 // Write the zlib compressed strip to the PDF output file 601 write2Buff(LZBuffer, numBytes); 602 sprintf(pOutStr, "\nendstream\n"); 603 writeStr2OutBuff(pOutStr); 604 sprintf(pOutStr, "endobj\n"); 605 writeStr2OutBuff(pOutStr); 606 607 if (!printedImageTransform) { 608 injectImageTransform(); 609 } 610 611 endXRef = xRefIndex; 612 613 return (1); 614 } 615 616 void PCLmGenerator::injectImageTransform() { 617 char str[512]; 618 int strLength; 619 sprintf(str, "q /image Do Q\n"); 620 strLength = strlen(str); 621 622 // Output image transformation information 623 sprintf(pOutStr, "%%============= PCLm: Object - Image Transformation \n"); 624 writeStr2OutBuff(pOutStr); 625 statOutputFileSize(); 626 if (currDuplexDisposition == duplex_longEdge && !(pageCount % 2) && mirrorBackside) { 627 sprintf(pOutStr, "%ld 0 obj\n", objCounter + 1); 628 objCounter++; 629 writeStr2OutBuff(pOutStr); 630 } else { 631 sprintf(pOutStr, "%ld 0 obj\n", objCounter); 632 objCounter++; 633 writeStr2OutBuff(pOutStr); 634 } 635 sprintf(pOutStr, "<<\n"); 636 writeStr2OutBuff(pOutStr); 637 sprintf(pOutStr, "/Length %d\n", strLength); 638 writeStr2OutBuff(pOutStr); 639 sprintf(pOutStr, ">>\n"); 640 writeStr2OutBuff(pOutStr); 641 sprintf(pOutStr, "stream\n"); 642 writeStr2OutBuff(pOutStr); 643 sprintf(pOutStr, "%s", str); 644 writeStr2OutBuff(pOutStr); 645 sprintf(pOutStr, "endstream\n"); 646 writeStr2OutBuff(pOutStr); 647 sprintf(pOutStr, "endobj\n"); 648 writeStr2OutBuff(pOutStr); 649 } 650 651 int PCLmGenerator::injectJPEG(char *jpeg_Buff, int imageWidth, int imageHeight, int numCompBytes, 652 colorSpaceDisposition destColorSpace, bool whiteStrip) { 653 char str[512]; 654 655 bool printedImageTransform = false; 656 657 if (currDuplexDisposition == duplex_longEdge && !(pageCount % 2) && mirrorBackside) { 658 if (!startXRef) { 659 startXRef = xRefIndex; 660 } 661 662 injectImageTransform(); 663 printedImageTransform = true; 664 } 665 666 yPosition += imageHeight; 667 668 if (destColorSpace == adobeRGB) { 669 injectAdobeRGBCS(); 670 } 671 672 // Inject PDF JPEG into output file 673 sprintf(pOutStr, "%%============= PCLm: FileBody: Strip Stream: jpeg Image \n"); 674 writeStr2OutBuff(pOutStr); 675 statOutputFileSize(); 676 if (currDuplexDisposition == duplex_longEdge && !(pageCount % 2) && mirrorBackside) { 677 sprintf(pOutStr, "%ld 0 obj\n", objCounter - 1); 678 objCounter++; 679 writeStr2OutBuff(pOutStr); 680 } else { 681 sprintf(pOutStr, "%ld 0 obj\n", objCounter); 682 objCounter++; 683 writeStr2OutBuff(pOutStr); 684 } 685 sprintf(pOutStr, "<<\n"); 686 writeStr2OutBuff(pOutStr); 687 sprintf(pOutStr, "/Width %d\n", imageWidth); 688 writeStr2OutBuff(pOutStr); 689 if (destColorSpace == deviceRGB) { 690 sprintf(pOutStr, "/ColorSpace /DeviceRGB\n"); 691 writeStr2OutBuff(pOutStr); 692 } else if (destColorSpace == adobeRGB) { 693 sprintf(pOutStr, "/ColorSpace 5 0 R\n"); 694 writeStr2OutBuff(pOutStr); 695 } else { 696 sprintf(pOutStr, "/ColorSpace /DeviceGray\n"); 697 writeStr2OutBuff(pOutStr); 698 } 699 sprintf(pOutStr, "/Height %d\n", imageHeight); 700 writeStr2OutBuff(pOutStr); 701 sprintf(pOutStr, "/Filter /DCTDecode\n"); 702 writeStr2OutBuff(pOutStr); 703 sprintf(pOutStr, "/Subtype /Image\n"); 704 writeStr2OutBuff(pOutStr); 705 sprintf(pOutStr, "/Length %d\n", numCompBytes); 706 writeStr2OutBuff(pOutStr); 707 sprintf(pOutStr, "/Type /XObject\n"); 708 writeStr2OutBuff(pOutStr); 709 sprintf(pOutStr, "/BitsPerComponent 8\n"); 710 writeStr2OutBuff(pOutStr); 711 #ifdef SUPPORT_WHITE_STRIPS 712 if (whiteStrip) { 713 sprintf(pOutStr, "/Name /WhiteStrip\n"); 714 writeStr2OutBuff(pOutStr); 715 } else { 716 sprintf(pOutStr, "/Name /ColorStrip\n"); 717 writeStr2OutBuff(pOutStr); 718 } 719 #endif 720 sprintf(pOutStr, ">>\n"); 721 writeStr2OutBuff(pOutStr); 722 sprintf(pOutStr, "stream\n"); 723 writeStr2OutBuff(pOutStr); 724 725 write2Buff((ubyte *) jpeg_Buff, numCompBytes); 726 sprintf(pOutStr, "\nendstream\n"); 727 writeStr2OutBuff(pOutStr); 728 sprintf(pOutStr, "endobj\n"); 729 writeStr2OutBuff(pOutStr); 730 731 sprintf(str, "q /image Do Q\n"); 732 733 if (!printedImageTransform) { 734 injectImageTransform(); 735 } 736 737 endXRef = xRefIndex; 738 739 return (1); 740 } 741 742 /* 743 * Writes str to buffer if the size of buffer is less than TEMP_BUFF_SIZE 744 */ 745 void writeStr2Buff(char *buffer, char *str) { 746 int buffSize; 747 char *buffPos; 748 749 buffSize = strlen(buffer) + strlen(str); 750 if (buffSize > TEMP_BUFF_SIZE) { 751 assert(0); 752 } 753 754 buffSize = strlen(buffer); 755 buffPos = buffer + buffSize; 756 sprintf(buffPos, "%s", str); 757 758 buffSize = strlen(buffer); 759 if (buffSize > TEMP_BUFF_SIZE) { 760 printf("tempBuff size exceeded: buffSize=%d\n", buffSize); 761 assert(0); 762 } 763 } 764 765 void PCLmGenerator::writePDFGrammarPage(int imageWidth, int imageHeight, int numStrips, 766 colorSpaceDisposition destColorSpace) { 767 int i, imageRef = objCounter + 2, buffSize; 768 int yAnchor; 769 char str[512]; 770 char *tempBuffer; 771 int startImageIndex = 0; 772 int numLinesLeft = 0; 773 774 if (destColorSpace == adobeRGB && 1 == pageCount) { 775 imageRef += 2; // Add 2 for AdobeRGB 776 } 777 778 tempBuffer = (char *) malloc(TEMP_BUFF_SIZE); 779 assert(tempBuffer); 780 memset(tempBuffer, 0x0, TEMP_BUFF_SIZE); 781 782 sprintf(pOutStr, "%%============= PCLm: FileBody: Object 3 - page object\n"); 783 writeStr2OutBuff(pOutStr); 784 statOutputFileSize(); 785 sprintf(pOutStr, "%ld 0 obj\n", objCounter); 786 writeStr2OutBuff(pOutStr); 787 addKids(objCounter); 788 objCounter++; 789 sprintf(pOutStr, "<<\n"); 790 writeStr2OutBuff(pOutStr); 791 sprintf(pOutStr, "/Type /Page\n"); 792 writeStr2OutBuff(pOutStr); 793 sprintf(pOutStr, "/Parent %d 0 R\n", PAGES_OBJ_NUMBER); 794 writeStr2OutBuff(pOutStr); 795 sprintf(pOutStr, "/Resources <<\n"); 796 writeStr2OutBuff(pOutStr); 797 // sprintf(pOutStr,"/ProcSet [ /PDF /ImageC ]\n"); writeStr2OutBuff(pOutStr); 798 sprintf(pOutStr, "/XObject <<\n"); 799 writeStr2OutBuff(pOutStr); 800 801 if (topMarginInPix) { 802 for (i = 0; i < numFullInjectedStrips; i++, startImageIndex++) { 803 sprintf(str, "/Image%d %d 0 R\n", startImageIndex, imageRef); 804 sprintf(pOutStr, "%s", str); 805 writeStr2OutBuff(pOutStr); 806 imageRef += 2; 807 } 808 if (numPartialScanlinesToInject) { 809 sprintf(str, "/Image%d %d 0 R\n", startImageIndex, imageRef); 810 sprintf(pOutStr, "%s", str); 811 writeStr2OutBuff(pOutStr); 812 imageRef += 2; 813 startImageIndex++; 814 } 815 } 816 817 for (i = startImageIndex; i < numStrips + startImageIndex; i++) { 818 sprintf(str, "/Image%d %d 0 R\n", i, imageRef); 819 // sprintf(pOutStr,"/ImageA 4 0 R /ImageB 6 0 R >>\n"); writeStr2OutBuff(pOutStr); 820 sprintf(pOutStr, "%s", str); 821 writeStr2OutBuff(pOutStr); 822 imageRef += 2; 823 } 824 sprintf(pOutStr, ">>\n"); 825 writeStr2OutBuff(pOutStr); 826 sprintf(pOutStr, ">>\n"); 827 writeStr2OutBuff(pOutStr); 828 if (currMediaOrientationDisposition == landscapeOrientation) { 829 pageOrigin = mediaWidth; 830 sprintf(pOutStr, "/MediaBox [ 0 0 %d %d ]\n", mediaHeight, mediaWidth); 831 writeStr2OutBuff(pOutStr); 832 } else { 833 pageOrigin = mediaHeight; 834 sprintf(pOutStr, "/MediaBox [ 0 0 %d %d ]\n", mediaWidth, mediaHeight); 835 writeStr2OutBuff(pOutStr); 836 } 837 sprintf(pOutStr, "/Contents [ %ld 0 R ]\n", objCounter); 838 writeStr2OutBuff(pOutStr); 839 #ifdef PIECEINFO_SUPPORTED 840 sprintf(pOutStr,"/PieceInfo <</HPAddition %d 0 R >> \n",9997); writeStr2OutBuff(pOutStr); 841 #endif 842 sprintf(pOutStr, ">>\n"); 843 writeStr2OutBuff(pOutStr); 844 sprintf(pOutStr, "endobj\n"); 845 writeStr2OutBuff(pOutStr); 846 847 // Create the FileBody stream first, so we know the Length of the stream 848 if (reverseOrder) { 849 yAnchor = 0; 850 } else { 851 yAnchor = (int) ((pageOrigin * STANDARD_SCALE) + 0.99); // Round up 852 } 853 854 // Setup the CTM so that we can send device-resolution coordinates 855 sprintf(pOutStr, 856 "%%Image Transformation Matrix: width, skewX, skewY, height, xAnchor, yAnchor\n"); 857 writeStr2OutBuff(pOutStr); 858 sprintf(str, "%f 0 0 %f 0 0 cm\n", STANDARD_SCALE_FOR_PDF / currRenderResolutionInteger, 859 STANDARD_SCALE_FOR_PDF / currRenderResolutionInteger); 860 writeStr2Buff(tempBuffer, str); 861 862 startImageIndex = 0; 863 if (topMarginInPix) { 864 for (i = 0; i < numFullInjectedStrips; i++) { 865 if (reverseOrder) { 866 yAnchor += numFullScanlinesToInject; 867 } else { 868 yAnchor -= numFullScanlinesToInject; 869 } 870 871 sprintf(str, "/P <</MCID 0>> BDC q\n"); 872 writeStr2Buff(tempBuffer, str); 873 874 sprintf(str, "%%Image Transformation Matrix: width, skewX, skewY, height, " 875 "xAnchor, yAnchor\n"); 876 writeStr2Buff(tempBuffer, str); 877 878 sprintf(str, "%d 0 0 %ld 0 %d cm\n", imageWidth * scaleFactor, 879 numFullScanlinesToInject * scaleFactor, yAnchor * scaleFactor); 880 writeStr2Buff(tempBuffer, str); 881 882 sprintf(str, "/Image%d Do Q\n", startImageIndex); 883 writeStr2Buff(tempBuffer, str); 884 885 startImageIndex++; 886 } 887 if (numPartialScanlinesToInject) { 888 if (reverseOrder) { 889 yAnchor += numPartialScanlinesToInject; 890 } else { 891 yAnchor -= numPartialScanlinesToInject; 892 } 893 894 sprintf(str, "/P <</MCID 0>> BDC q\n"); 895 writeStr2Buff(tempBuffer, str); 896 897 sprintf(str, "%%Image Transformation Matrix: width, skewX, skewY, height, xAnchor, " 898 "yAnchor\n"); 899 900 writeStr2Buff(tempBuffer, str); 901 902 sprintf(str, "%d 0 0 %ld 0 %d cm\n", imageWidth * scaleFactor, 903 numPartialScanlinesToInject * scaleFactor, yAnchor * scaleFactor); 904 writeStr2Buff(tempBuffer, str); 905 906 sprintf(str, "/Image%d Do Q\n", startImageIndex); 907 writeStr2Buff(tempBuffer, str); 908 909 startImageIndex++; 910 } 911 } 912 913 for (i = startImageIndex; i < numStrips + startImageIndex; i++) { 914 // last strip may have less lines than currStripHeight. Update yAnchor using left over lines 915 if (i == (numStrips + startImageIndex - 1)) { 916 numLinesLeft = currSourceHeight - ((numStrips - 1) * currStripHeight); 917 918 if (reverseOrder) { 919 yAnchor += numLinesLeft; 920 } else { 921 yAnchor -= numLinesLeft; 922 } 923 } else { 924 if (reverseOrder) { 925 yAnchor += currStripHeight; 926 } else { 927 yAnchor -= currStripHeight; 928 } 929 } 930 931 sprintf(str, "/P <</MCID 0>> BDC q\n"); 932 writeStr2Buff(tempBuffer, str); 933 934 sprintf(str, 935 "%%Image Transformation Matrix: width, skewX, skewY, height, xAnchor, yAnchor\n"); 936 writeStr2Buff(tempBuffer, str); 937 938 // last strip may have less lines than currStripHeight 939 if (i == (numStrips + startImageIndex - 1)) { 940 sprintf(str, "%d 0 0 %d 0 %d cm\n", imageWidth * scaleFactor, 941 numLinesLeft * scaleFactor, yAnchor * scaleFactor); 942 writeStr2Buff(tempBuffer, str); 943 } else if (yAnchor < 0) { 944 sint32 newH = currStripHeight + yAnchor; 945 sprintf(str, "%d 0 0 %ld 0 %d cm\n", imageWidth * scaleFactor, newH * scaleFactor, 946 0 * scaleFactor); 947 writeStr2Buff(tempBuffer, str); 948 } else { 949 sprintf(str, "%d 0 0 %ld 0 %d cm\n", imageWidth * scaleFactor, 950 currStripHeight * scaleFactor, yAnchor * scaleFactor); 951 writeStr2Buff(tempBuffer, str); 952 } 953 954 sprintf(str, "/Image%d Do Q\n", i); 955 writeStr2Buff(tempBuffer, str); 956 } 957 958 // Resulting buffer size 959 buffSize = strlen(tempBuffer); 960 961 sprintf(pOutStr, "%%============= PCLm: FileBody: Page Content Stream object\n"); 962 writeStr2OutBuff(pOutStr); 963 statOutputFileSize(); 964 sprintf(pOutStr, "%ld 0 obj\n", objCounter); 965 writeStr2OutBuff(pOutStr); 966 sprintf(pOutStr, "<<\n"); 967 writeStr2OutBuff(pOutStr); 968 969 sprintf(pOutStr, "/Length %d\n", buffSize); 970 writeStr2OutBuff(pOutStr); 971 sprintf(pOutStr, ">>\n"); 972 writeStr2OutBuff(pOutStr); 973 sprintf(pOutStr, "stream\n"); 974 writeStr2OutBuff(pOutStr); 975 976 // Now write the FileBody stream 977 write2Buff((ubyte *) tempBuffer, buffSize); 978 979 sprintf(pOutStr, "endstream\n"); 980 writeStr2OutBuff(pOutStr); 981 sprintf(pOutStr, "endobj\n"); 982 writeStr2OutBuff(pOutStr); 983 objCounter++; 984 if (tempBuffer) { 985 free(tempBuffer); 986 } 987 } 988 989 /* 990 * Mirrors the source image in preparation for backside duplex support 991 */ 992 static bool prepImageForBacksideDuplex(ubyte *imagePtr, sint32 imageHeight, sint32 imageWidth, 993 sint32 numComponents) { 994 sint32 numBytes = imageHeight * imageWidth * numComponents; 995 ubyte *head, *tail, t0, t1, t2; 996 997 if (numComponents == 3) { 998 for (head = imagePtr, tail = imagePtr + numBytes - 1; tail > head;) { 999 t0 = *head; 1000 t1 = *(head + 1); 1001 t2 = *(head + 2); 1002 1003 *head = *(tail - 2); 1004 *(head + 1) = *(tail - 1); 1005 *(head + 2) = *(tail - 0); 1006 *tail = t2; 1007 *(tail - 1) = t1; 1008 *(tail - 2) = t0; 1009 1010 head += 3; 1011 tail -= 3; 1012 } 1013 } else { 1014 for (head = imagePtr, tail = imagePtr + numBytes; tail > head;) { 1015 t0 = *head; 1016 *head = *tail; 1017 *tail = t0; 1018 head++; 1019 tail--; 1020 } 1021 } 1022 //origTail++; 1023 return true; 1024 } 1025 1026 bool PCLmGenerator::getInputBinString(jobInputBin bin, char *returnStr) { 1027 returnStr[0] = '\0'; 1028 1029 switch (bin) { 1030 case alternate: 1031 strcpy(returnStr, "alternate"); 1032 break; 1033 case alternate_roll: 1034 strcpy(returnStr, "alternate_roll"); 1035 break; 1036 case auto_select: 1037 strcpy(returnStr, "auto_select"); 1038 break; 1039 case bottom: 1040 strcpy(returnStr, "bottom"); 1041 break; 1042 case center: 1043 strcpy(returnStr, "center"); 1044 break; 1045 case disc: 1046 strcpy(returnStr, "disc"); 1047 break; 1048 case envelope: 1049 strcpy(returnStr, "envelope"); 1050 break; 1051 case hagaki: 1052 strcpy(returnStr, "hagaki"); 1053 break; 1054 case large_capacity: 1055 strcpy(returnStr, "large_capacity"); 1056 break; 1057 case left: 1058 strcpy(returnStr, "left"); 1059 break; 1060 case main_tray: 1061 strcpy(returnStr, "main_tray"); 1062 break; 1063 case main_roll: 1064 strcpy(returnStr, "main_roll"); 1065 break; 1066 case manual: 1067 strcpy(returnStr, "manual"); 1068 break; 1069 case middle: 1070 strcpy(returnStr, "middle"); 1071 break; 1072 case photo: 1073 strcpy(returnStr, "photo"); 1074 break; 1075 case rear: 1076 strcpy(returnStr, "rear"); 1077 break; 1078 case right: 1079 strcpy(returnStr, "right"); 1080 break; 1081 case side: 1082 strcpy(returnStr, "side"); 1083 break; 1084 case top: 1085 strcpy(returnStr, "top"); 1086 break; 1087 case tray_1: 1088 strcpy(returnStr, "tray_1"); 1089 break; 1090 case tray_2: 1091 strcpy(returnStr, "tray_2"); 1092 break; 1093 case tray_3: 1094 strcpy(returnStr, "tray_3"); 1095 break; 1096 case tray_4: 1097 strcpy(returnStr, "tray_4"); 1098 break; 1099 case tray_5: 1100 strcpy(returnStr, "tray_5"); 1101 break; 1102 case tray_N: 1103 strcpy(returnStr, "tray_N"); 1104 break; 1105 default: 1106 assert(0); 1107 break; 1108 } 1109 return true; 1110 } 1111 1112 bool PCLmGenerator::getOutputBin(jobOutputBin bin, char *returnStr) { 1113 if (returnStr) { 1114 returnStr[0] = '\0'; 1115 } 1116 1117 switch (bin) { 1118 case top_output: 1119 strcpy(returnStr, "top_output"); 1120 break; 1121 case middle_output: 1122 strcpy(returnStr, "middle_output"); 1123 break; 1124 case bottom_output: 1125 strcpy(returnStr, "bottom_output"); 1126 break; 1127 case side_output: 1128 strcpy(returnStr, "side_output"); 1129 break; 1130 case center_output: 1131 strcpy(returnStr, "center_output"); 1132 break; 1133 case rear_output: 1134 strcpy(returnStr, "rear_output"); 1135 break; 1136 case face_up: 1137 strcpy(returnStr, "face_up"); 1138 break; 1139 case face_down: 1140 strcpy(returnStr, "face_down"); 1141 break; 1142 case large_capacity_output: 1143 strcpy(returnStr, "large_capacity_output"); 1144 break; 1145 case stacker_N: 1146 strcpy(returnStr, "stacker_N"); 1147 break; 1148 case mailbox_N: 1149 strcpy(returnStr, "mailbox_N"); 1150 break; 1151 case tray_1_output: 1152 strcpy(returnStr, "tray_1_output"); 1153 break; 1154 case tray_2_output: 1155 strcpy(returnStr, "tray_2_output"); 1156 break; 1157 case tray_3_output: 1158 strcpy(returnStr, "tray_3_output"); 1159 break; 1160 case tray_4_output: 1161 strcpy(returnStr, "tray_4_output"); 1162 break; 1163 default: 1164 assert(0); 1165 break; 1166 } 1167 return true; 1168 } 1169 1170 void PCLmGenerator::writeJobTicket() { 1171 // Write JobTicket 1172 char inputBin[256]; 1173 char outputBin[256]; 1174 1175 if (!m_pPCLmSSettings) { 1176 return; 1177 } 1178 1179 getInputBinString(m_pPCLmSSettings->userInputBin, &inputBin[0]); 1180 getOutputBin(m_pPCLmSSettings->userOutputBin, &outputBin[0]); 1181 strcpy(inputBin, inputBin); 1182 strcpy(outputBin, outputBin); 1183 1184 sprintf(pOutStr, "%% genPCLm (Ver: %f)\n", PCLM_Ver); 1185 writeStr2OutBuff(pOutStr); 1186 sprintf(pOutStr, "%%============= Job Ticket =============\n"); 1187 writeStr2OutBuff(pOutStr); 1188 sprintf(pOutStr, "%% PCLmS-Job-Ticket\n"); 1189 writeStr2OutBuff(pOutStr); 1190 sprintf(pOutStr, "%% job-ticket-version: 0.1\n"); 1191 writeStr2OutBuff(pOutStr); 1192 sprintf(pOutStr, "%% epcl-version: 1.01\n"); 1193 writeStr2OutBuff(pOutStr); 1194 sprintf(pOutStr, "%% JobSection\n"); 1195 writeStr2OutBuff(pOutStr); 1196 sprintf(pOutStr, "%% job-id: xxx\n"); 1197 writeStr2OutBuff(pOutStr); 1198 sprintf(pOutStr, "%% MediaHandlingSection\n"); 1199 writeStr2OutBuff(pOutStr); 1200 sprintf(pOutStr, "%% media-size-name: %s\n", currMediaName); 1201 writeStr2OutBuff(pOutStr); 1202 sprintf(pOutStr, "%% media-type: %s\n", m_pPCLmSSettings->userMediaType); 1203 writeStr2OutBuff(pOutStr); 1204 sprintf(pOutStr, "%% media-source: %s\n", inputBin); 1205 writeStr2OutBuff(pOutStr); 1206 sprintf(pOutStr, "%% sides: xxx\n"); 1207 writeStr2OutBuff(pOutStr); 1208 sprintf(pOutStr, "%% output-bin: %s\n", outputBin); 1209 writeStr2OutBuff(pOutStr); 1210 sprintf(pOutStr, "%% RenderingSection\n"); 1211 writeStr2OutBuff(pOutStr); 1212 if (currCompressionDisposition == compressDCT) { 1213 sprintf(pOutStr, "%% pclm-compression-method: JPEG\n"); 1214 writeStr2OutBuff(pOutStr); 1215 } else if (currCompressionDisposition == compressFlate) { 1216 sprintf(pOutStr, "%% pclm-compression-method: FLATE\n"); 1217 writeStr2OutBuff(pOutStr); 1218 } else { 1219 sprintf(pOutStr, "%% pclm-compression-method: RLE\n"); 1220 writeStr2OutBuff(pOutStr); 1221 } 1222 sprintf(pOutStr, "%% strip-height: %ld\n", currStripHeight); 1223 writeStr2OutBuff(pOutStr); 1224 1225 if (destColorSpace == deviceRGB) { 1226 sprintf(pOutStr, "%% print-color-mode: deviceRGB\n"); 1227 writeStr2OutBuff(pOutStr); 1228 } else if (destColorSpace == adobeRGB) { 1229 sprintf(pOutStr, "%% print-color-mode: adobeRGB\n"); 1230 writeStr2OutBuff(pOutStr); 1231 } else if (destColorSpace == grayScale) { 1232 sprintf(pOutStr, "%% print-color-mode: gray\n"); 1233 writeStr2OutBuff(pOutStr); 1234 } 1235 1236 sprintf(pOutStr, "%% print-quality: %d\n", m_pPCLmSSettings->userPageQuality); 1237 writeStr2OutBuff(pOutStr); 1238 sprintf(pOutStr, "%% printer-resolution: %d\n", currRenderResolutionInteger); 1239 writeStr2OutBuff(pOutStr); 1240 sprintf(pOutStr, "%% print-content-optimized: xxx\n"); 1241 writeStr2OutBuff(pOutStr); 1242 sprintf(pOutStr, "%% orientation-requested: %d\n", m_pPCLmSSettings->userOrientation); 1243 writeStr2OutBuff(pOutStr); 1244 1245 if (PCLmSSettings.userCopies == 0) { 1246 PCLmSSettings.userCopies = 1; 1247 } 1248 1249 sprintf(pOutStr, "%% copies: %d\n", m_pPCLmSSettings->userCopies); 1250 writeStr2OutBuff(pOutStr); 1251 sprintf(pOutStr, "%% pclm-raster-back-side: xxx\n"); 1252 writeStr2OutBuff(pOutStr); 1253 if (currRenderResolutionInteger) { 1254 sprintf(pOutStr, "%% margins-pre-applied: TRUE\n"); 1255 writeStr2OutBuff(pOutStr); 1256 } else { 1257 sprintf(pOutStr, "%% margins-pre-applied: FALSE\n"); 1258 writeStr2OutBuff(pOutStr); 1259 } 1260 sprintf(pOutStr, "%% PCLmS-Job-Ticket-End\n"); 1261 writeStr2OutBuff(pOutStr); 1262 } 1263 1264 void PCLmGenerator::writePDFGrammarHeader() { 1265 // sprintf(pOutStr,"%%============= PCLm: File Header \n"); writeStr2OutBuff(pOutStr); 1266 sprintf(pOutStr, "%%PDF-1.7\n"); 1267 writeStr2OutBuff(pOutStr); 1268 sprintf(pOutStr, "%%PCLm 1.0\n"); 1269 writeStr2OutBuff(pOutStr); 1270 } 1271 1272 int PCLmGenerator::RLEEncodeImage(ubyte *in, ubyte *out, int inLength) { 1273 ubyte *imgPtr = in; 1274 ubyte *endPtr = in + inLength; 1275 ubyte *origOut = out; 1276 ubyte c; 1277 sint32 cnt = 0; 1278 1279 while (imgPtr < endPtr) { 1280 c = *imgPtr++; 1281 cnt = 1; 1282 1283 // Figure out how many repeating bytes are in the image 1284 while (*imgPtr == c && cnt < inLength) { 1285 if (imgPtr > endPtr) { 1286 break; 1287 } 1288 cnt++; 1289 imgPtr++; 1290 } 1291 1292 if (cnt > 1) { 1293 /* If cnt > 1, then output repeating byte specification 1294 * The syntax is "byte-count repeateByte", where byte-count is 257-byte-count. 1295 * Since the cnt value is a byte, if the repeateCnt is > 128 then we need to put 1296 * out multiple repeat-blocks (Referred to as method 1) range is 128-256 1297 */ 1298 while (cnt > 128) { 1299 *out++ = 129; // i.e. 257-129==128 1300 *out++ = c; 1301 cnt -= 128; 1302 } 1303 // Now handle the repeats that are < 128 1304 if (cnt) { 1305 *out++ = (257 - cnt); // i.e. cnt==2: 257-255=2 1306 *out++ = c; 1307 } 1308 } else { 1309 /* If cnt==1, then this is a literal run - no repeating bytes found. 1310 * The syntax is "byte-count literal-run", where byte-count is < 128 and 1311 * literal-run is the non-repeating bytes of the input stream. 1312 * Referred to as method 2, range is 0-127 1313 */ 1314 ubyte *start, *p; 1315 sint32 i; 1316 start = (imgPtr - 1); // The first byte of the literal run 1317 1318 // Now find the end of the literal run 1319 for (cnt = 1, p = start; *p != *imgPtr; p++, imgPtr++, cnt++) { 1320 if (imgPtr >= endPtr) break; 1321 } 1322 if (!(imgPtr == endPtr)) { 1323 imgPtr--; 1324 // imgPtr incremented 1 too many 1325 } 1326 cnt--; 1327 // Blocks of literal bytes can't exceed 128 bytes, so output multiple 1328 // literal-run blocks if > 128 1329 while (cnt > 128) { 1330 *out++ = 127; 1331 for (i = 0; i < 128; i++) { 1332 *out++ = *start++; 1333 } 1334 cnt -= 128; 1335 } 1336 // Now output the leftover literal run 1337 *out++ = cnt - 1; 1338 for (i = 0; i < cnt; i++) { 1339 *out++ = *start++; 1340 } 1341 } 1342 } 1343 // Now, write the end-of-compression marker (byte 128) into the output stream 1344 *out++ = 128; 1345 // Return the compressed size 1346 return ((int) (out - origOut)); 1347 } 1348 1349 PCLmGenerator::PCLmGenerator() { 1350 strcpy(currMediaName, "LETTER"); 1351 currDuplexDisposition = simplex; 1352 currCompressionDisposition = compressDCT; 1353 currMediaOrientationDisposition = portraitOrientation; 1354 currRenderResolution = res600; 1355 currStripHeight = STRIP_HEIGHT; 1356 1357 // Default media h/w to letter specification 1358 mediaWidthInPixels = 0; 1359 mediaHeightInPixels = 0; 1360 mediaWidth = 612; 1361 mediaHeight = 792; 1362 destColorSpace = deviceRGB; 1363 sourceColorSpace = deviceRGB; 1364 scaleFactor = 1; 1365 jobOpen = job_closed; 1366 scratchBuffer = NULL; 1367 pageCount = 0; 1368 1369 currRenderResolutionInteger = 600; 1370 STANDARD_SCALE = (float) currRenderResolutionInteger / (float) STANDARD_SCALE_FOR_PDF; 1371 yPosition = 0; 1372 numKids = 0; 1373 1374 // XRefTable storage 1375 xRefIndex = 0; 1376 xRefStart = 0; 1377 1378 objCounter = PAGES_OBJ_NUMBER + 1; 1379 totalBytesWrittenToPCLmFile = 0; 1380 1381 // Initialize first index in xRefTable 1382 xRefTable = NULL; 1383 KidsArray = NULL; 1384 1385 // Initialize the output Buffer 1386 allocatedOutputBuffer = NULL; 1387 1388 // Initialize the leftover scanline logic 1389 leftoverScanlineBuffer = 0; 1390 1391 adobeRGBCS_firstTime = true; 1392 mirrorBackside = true; 1393 1394 topMarginInPix = 0; 1395 leftMarginInPix = 0; 1396 m_pPCLmSSettings = NULL; 1397 } 1398 1399 PCLmGenerator::~PCLmGenerator() { 1400 Cleanup(); 1401 } 1402 1403 int PCLmGenerator::StartJob(void **pOutBuffer, int *iOutBufferSize) { 1404 /* Allocate the output buffer; we don't know much at this point, so make the output buffer size 1405 * the worst case dimensions; when we get a startPage, we will resize it appropriately 1406 */ 1407 outBuffSize = DEFAULT_OUTBUFF_SIZE; 1408 *iOutBufferSize = outBuffSize; 1409 *pOutBuffer = (ubyte *) malloc(outBuffSize); // This multipliy by 10 needs to be removed... 1410 1411 if (NULL == *pOutBuffer) { 1412 return (errorOutAndCleanUp()); 1413 } 1414 1415 currOutBuffSize = outBuffSize; 1416 1417 if (NULL == *pOutBuffer) { 1418 return (errorOutAndCleanUp()); 1419 } 1420 1421 allocatedOutputBuffer = *pOutBuffer; 1422 initOutBuff((char *) *pOutBuffer, outBuffSize); 1423 writePDFGrammarHeader(); 1424 *iOutBufferSize = totalBytesWrittenToCurrBuff; 1425 jobOpen = job_open; 1426 1427 return success; 1428 } 1429 1430 int PCLmGenerator::EndJob(void **pOutBuffer, int *iOutBufferSize) { 1431 if (NULL == allocatedOutputBuffer) { 1432 return (errorOutAndCleanUp()); 1433 } 1434 1435 *pOutBuffer = allocatedOutputBuffer; 1436 1437 initOutBuff((char *) *pOutBuffer, outBuffSize); 1438 1439 // Write PDF trailer 1440 writePDFGrammarTrailer(currSourceWidth, currSourceHeight); 1441 1442 *iOutBufferSize = totalBytesWrittenToCurrBuff; 1443 1444 jobOpen = job_closed; 1445 1446 if (xRefTable) { 1447 free(xRefTable); 1448 xRefTable = NULL; 1449 } 1450 if (KidsArray) { 1451 free(KidsArray); 1452 KidsArray = NULL; 1453 } 1454 1455 return success; 1456 } 1457 1458 int PCLmGenerator::StartPage(PCLmPageSetup *PCLmPageContent, void **pOutBuffer, 1459 int *iOutBufferSize) { 1460 int numImageStrips; 1461 // Save the resolution information 1462 currRenderResolution = PCLmPageContent->destinationResolution; 1463 1464 *pOutBuffer = allocatedOutputBuffer; 1465 1466 if (currRenderResolution == res300) { 1467 currRenderResolutionInteger = 300; 1468 } else if (currRenderResolution == res600) { 1469 currRenderResolutionInteger = 600; 1470 } else if (currRenderResolution == res1200) { 1471 currRenderResolutionInteger = 1200; 1472 } else { 1473 assert(0); 1474 } 1475 1476 // Recalculate STANDARD_SCALE to reflect the job resolution 1477 STANDARD_SCALE = (float) currRenderResolutionInteger / (float) STANDARD_SCALE_FOR_PDF; 1478 1479 // Use the values set by the caller 1480 currSourceWidth = PCLmPageContent->SourceWidthPixels; 1481 currSourceHeight = PCLmPageContent->SourceHeightPixels; 1482 1483 // Save off the media information 1484 mediaWidth = (int) (PCLmPageContent->mediaWidth); 1485 mediaHeight = (int) (PCLmPageContent->mediaHeight); 1486 1487 // Use the values set by the caller 1488 mediaWidthInPixels = PCLmPageContent->mediaWidthInPixels; 1489 mediaHeightInPixels = PCLmPageContent->mediaHeightInPixels; 1490 1491 topMarginInPix = (int) (((PCLmPageContent->mediaHeightOffset / STANDARD_SCALE_FOR_PDF) * 1492 currRenderResolutionInteger) + 0.50); 1493 leftMarginInPix = (int) (((PCLmPageContent->mediaWidthOffset / STANDARD_SCALE_FOR_PDF) * 1494 currRenderResolutionInteger) + 0.50); 1495 1496 if (topMarginInPix % 16) { 1497 // Round to nearest 16 scanline boundary to ensure decompressability. 1498 int i = topMarginInPix % 16; 1499 if (i < (16 / 2)) { 1500 topMarginInPix -= i; 1501 } else { 1502 topMarginInPix += (16 - i); 1503 } 1504 } 1505 1506 if (leftMarginInPix % 16) { 1507 // Round to nearest 16 scanline boundary to ensure decompressability. 1508 int i = leftMarginInPix % 16; 1509 if (i < (16 / 2)) { 1510 leftMarginInPix -= i; 1511 } else { 1512 leftMarginInPix += (16 - i); 1513 } 1514 } 1515 1516 currCompressionDisposition = PCLmPageContent->compTypeRequested; 1517 1518 if (strlen(PCLmPageContent->mediaSizeName)) { 1519 strcpy(currMediaName, PCLmPageContent->mediaSizeName); 1520 } 1521 1522 currStripHeight = PCLmPageContent->stripHeight; 1523 if (!currStripHeight) { 1524 numImageStrips = 1; 1525 currStripHeight = currSourceHeight; 1526 } else { 1527 // Need to know how many strips will be inserted into PDF file 1528 float numImageStripsReal = ceil((float) currSourceHeight / (float) currStripHeight); 1529 numImageStrips = (int) numImageStripsReal; 1530 } 1531 1532 if (PCLmPageContent->srcColorSpaceSpefication == grayScale) { 1533 srcNumComponents = 1; 1534 } else { 1535 srcNumComponents = 3; 1536 } 1537 1538 if (PCLmPageContent->dstColorSpaceSpefication == grayScale) { 1539 dstNumComponents = 1; 1540 } else { 1541 dstNumComponents = 3; 1542 } 1543 1544 currDuplexDisposition = PCLmPageContent->duplexDisposition; 1545 1546 destColorSpace = PCLmPageContent->dstColorSpaceSpefication; 1547 1548 // Calculate how large the output buffer needs to be based upon the page specifications 1549 int tmp_outBuffSize = mediaWidthInPixels * currStripHeight * dstNumComponents; 1550 1551 if (tmp_outBuffSize > currOutBuffSize) { 1552 // Realloc the pOutBuffer to the correct size 1553 *pOutBuffer = realloc(*pOutBuffer, tmp_outBuffSize); 1554 1555 if (*pOutBuffer == NULL) { 1556 // realloc failed and prev buffer not freed 1557 return errorOutAndCleanUp(); 1558 } 1559 1560 outBuffSize = currOutBuffSize = tmp_outBuffSize; 1561 allocatedOutputBuffer = *pOutBuffer; 1562 if (NULL == allocatedOutputBuffer) { 1563 return (errorOutAndCleanUp()); 1564 } 1565 } 1566 1567 initOutBuff((char *) *pOutBuffer, outBuffSize); 1568 1569 // Keep track of the page count 1570 pageCount++; 1571 1572 // If we are on a backside and doing duplex, prep for reverse strip order 1573 if (currDuplexDisposition == duplex_longEdge && !(pageCount % 2) && mirrorBackside) { 1574 reverseOrder = true; 1575 } else { 1576 reverseOrder = false; 1577 } 1578 1579 // Calculate the number of injected strips, if any 1580 if (topMarginInPix) { 1581 if (topMarginInPix <= currStripHeight) { 1582 numFullInjectedStrips = 1; 1583 numFullScanlinesToInject = topMarginInPix; 1584 numPartialScanlinesToInject = 0; 1585 } else { 1586 numFullInjectedStrips = topMarginInPix / currStripHeight; 1587 numFullScanlinesToInject = currStripHeight; 1588 numPartialScanlinesToInject = 1589 topMarginInPix - (numFullInjectedStrips * currStripHeight); 1590 } 1591 } 1592 1593 writeJobTicket(); 1594 writePDFGrammarPage(mediaWidthInPixels, mediaHeightInPixels, numImageStrips, destColorSpace); 1595 *iOutBufferSize = totalBytesWrittenToCurrBuff; 1596 1597 if (!scratchBuffer) { 1598 // We need to pad the scratchBuffer size to allow for compression expansion (RLE can create 1599 // compressed segments that are slightly larger than the source. 1600 size_t len = (size_t) currStripHeight * mediaWidthInPixels * srcNumComponents * 2; 1601 scratchBuffer = (ubyte *) malloc(len); 1602 if (!scratchBuffer) { 1603 return errorOutAndCleanUp(); 1604 } 1605 } 1606 1607 mirrorBackside = PCLmPageContent->mirrorBackside; 1608 firstStrip = true; 1609 1610 return success; 1611 } 1612 1613 int PCLmGenerator::EndPage(void **pOutBuffer, int *iOutBufferSize) { 1614 *pOutBuffer = allocatedOutputBuffer; 1615 initOutBuff((char *) *pOutBuffer, outBuffSize); 1616 *iOutBufferSize = totalBytesWrittenToCurrBuff; 1617 1618 // Free up the scratchbuffer at endpage, to allow the next page to have a different size 1619 if (scratchBuffer) { 1620 free(scratchBuffer); 1621 scratchBuffer = NULL; 1622 } 1623 1624 return success; 1625 } 1626 1627 int PCLmGenerator::Encapsulate(void *pInBuffer, int inBufferSize, int thisHeight, 1628 void **pOutBuffer, int *iOutBufferSize) { 1629 int numCompBytes; 1630 int scanlineWidth = mediaWidthInPixels * srcNumComponents; 1631 int numLinesThisCall = thisHeight; 1632 void *savedInBufferPtr = NULL; 1633 void *tmpBuffer = NULL; 1634 void *localInBuffer; 1635 ubyte *newStripPtr = NULL; 1636 1637 if (leftoverScanlineBuffer) { 1638 ubyte *whereAreWe; 1639 sint32 scanlinesThisTime; 1640 // The leftover scanlines have already been processed (color-converted and flipped), so 1641 // just put them into the output buffer. 1642 1643 // Allocate a temporary buffer to copy leftover and new data into 1644 tmpBuffer = malloc(scanlineWidth * currStripHeight); 1645 if (!tmpBuffer) { 1646 return (errorOutAndCleanUp()); 1647 } 1648 1649 // Copy leftover scanlines into tmpBuffer 1650 memcpy(tmpBuffer, leftoverScanlineBuffer, scanlineWidth * numLeftoverScanlines); 1651 1652 whereAreWe = (ubyte *) tmpBuffer + (scanlineWidth * numLeftoverScanlines); 1653 1654 scanlinesThisTime = currStripHeight - numLeftoverScanlines; 1655 1656 // Copy enough scanlines from the real inBuffer to fill out the tmpBuffer 1657 memcpy(whereAreWe, pInBuffer, scanlinesThisTime * scanlineWidth); 1658 1659 // Now copy the remaining scanlines from pInBuffer to the leftoverBuffer 1660 numLeftoverScanlines = thisHeight - scanlinesThisTime; 1661 assert(leftoverScanlineBuffer); 1662 whereAreWe = (ubyte *) pInBuffer + (scanlineWidth * numLeftoverScanlines); 1663 memcpy(leftoverScanlineBuffer, whereAreWe, scanlineWidth * numLeftoverScanlines); 1664 numLinesThisCall = thisHeight = currStripHeight; 1665 1666 savedInBufferPtr = pInBuffer; 1667 localInBuffer = tmpBuffer; 1668 } else { 1669 localInBuffer = pInBuffer; 1670 } 1671 1672 if (thisHeight > currStripHeight) { 1673 // Copy raw raster into leftoverScanlineBuffer 1674 ubyte *ptr; 1675 numLeftoverScanlines = thisHeight - currStripHeight; 1676 leftoverScanlineBuffer = malloc(scanlineWidth * numLeftoverScanlines); 1677 if (!leftoverScanlineBuffer) { 1678 return (errorOutAndCleanUp()); 1679 } 1680 ptr = (ubyte *) localInBuffer + scanlineWidth * numLeftoverScanlines; 1681 memcpy(leftoverScanlineBuffer, ptr, scanlineWidth * numLeftoverScanlines); 1682 thisHeight = currStripHeight; 1683 } 1684 1685 if (NULL == allocatedOutputBuffer) { 1686 if (tmpBuffer) { 1687 free(tmpBuffer); 1688 } 1689 return (errorOutAndCleanUp()); 1690 } 1691 *pOutBuffer = allocatedOutputBuffer; 1692 initOutBuff((char *) *pOutBuffer, outBuffSize); 1693 1694 if (currDuplexDisposition == duplex_longEdge && !(pageCount % 2)) { 1695 if (mirrorBackside) { 1696 prepImageForBacksideDuplex((ubyte *) localInBuffer, numLinesThisCall, currSourceWidth, 1697 srcNumComponents); 1698 } 1699 } 1700 1701 if (destColorSpace == grayScale && 1702 (sourceColorSpace == deviceRGB || sourceColorSpace == adobeRGB)) { 1703 colorConvertSource(sourceColorSpace, grayScale, (ubyte *) localInBuffer, currSourceWidth, 1704 numLinesThisCall); 1705 // Adjust the scanline width accordingly 1706 scanlineWidth = mediaWidthInPixels * dstNumComponents; 1707 } 1708 1709 if (leftMarginInPix) { 1710 newStripPtr = shiftStripByLeftMargin((ubyte *) localInBuffer, currSourceWidth, 1711 currStripHeight, numLinesThisCall, mediaWidthInPixels, leftMarginInPix, 1712 destColorSpace); 1713 } 1714 1715 bool whiteStrip = false; 1716 #ifdef SUPPORT_WHITE_STRIPS 1717 if (!firstStrip) { 1718 // PCLm does not print a blank page if all the strips are marked as "/Name /WhiteStrip" 1719 // so only apply /WhiteStrip to strips after the first 1720 whiteStrip = isWhiteStrip(pInBuffer, thisHeight * currSourceWidth * srcNumComponents); 1721 } 1722 #endif 1723 1724 if (currCompressionDisposition == compressDCT) { 1725 if (firstStrip && topMarginInPix) { 1726 ubyte whitePt = 0xff; 1727 1728 ubyte *tmpStrip = (ubyte *) malloc(scanlineWidth * topMarginInPix); 1729 memset(tmpStrip, whitePt, scanlineWidth * topMarginInPix); 1730 1731 for (sint32 stripCntr = 0; stripCntr < numFullInjectedStrips; stripCntr++) { 1732 write_JPEG_Buff(scratchBuffer, JPEG_QUALITY, mediaWidthInPixels, 1733 (sint32) numFullScanlinesToInject, tmpStrip, currRenderResolutionInteger, 1734 destColorSpace, &numCompBytes); 1735 injectJPEG((char *) scratchBuffer, mediaWidthInPixels, 1736 (sint32) numFullScanlinesToInject, numCompBytes, destColorSpace, true); 1737 } 1738 1739 if (numPartialScanlinesToInject) { 1740 // Handle the leftover strip 1741 write_JPEG_Buff(scratchBuffer, JPEG_QUALITY, mediaWidthInPixels, 1742 numPartialScanlinesToInject, tmpStrip, currRenderResolutionInteger, 1743 destColorSpace, &numCompBytes); 1744 injectJPEG((char *) scratchBuffer, mediaWidthInPixels, numPartialScanlinesToInject, 1745 numCompBytes, destColorSpace, true); 1746 } 1747 1748 free(tmpStrip); 1749 } 1750 firstStrip = false; 1751 1752 // We are always going to compress the full strip height, even though the image may be less; 1753 // this allows the compressed images to be symmetric 1754 if (numLinesThisCall < currStripHeight) { 1755 sint32 numLeftoverBytes = (currStripHeight - numLinesThisCall) * currSourceWidth * 3; 1756 sint32 numImagedBytes = numLinesThisCall * currSourceWidth * 3; 1757 1758 // End-of-page: we have to white-out the unused section of the source image 1759 memset((ubyte *) localInBuffer + numImagedBytes, 0xff, numLeftoverBytes); 1760 } 1761 1762 if (newStripPtr) { 1763 write_JPEG_Buff(scratchBuffer, JPEG_QUALITY, mediaWidthInPixels, currStripHeight, 1764 newStripPtr, currRenderResolutionInteger, destColorSpace, &numCompBytes); 1765 1766 free(newStripPtr); 1767 newStripPtr = NULL; 1768 } else { 1769 write_JPEG_Buff(scratchBuffer, JPEG_QUALITY, mediaWidthInPixels, currStripHeight, 1770 (JSAMPLE *) localInBuffer, currRenderResolutionInteger, destColorSpace, 1771 &numCompBytes); 1772 } 1773 1774 injectJPEG((char *) scratchBuffer, mediaWidthInPixels, currStripHeight, numCompBytes, 1775 destColorSpace, whiteStrip); 1776 } else if (currCompressionDisposition == compressFlate) { 1777 uint32 len = numLinesThisCall * scanlineWidth; 1778 uLongf destSize = len; 1779 int result; 1780 1781 if (firstStrip && topMarginInPix) { 1782 ubyte whitePt = 0xff; 1783 1784 // We need to inject a blank image-strip with a height==topMarginInPix 1785 ubyte *tmpStrip = (ubyte *) malloc(scanlineWidth * topMarginInPix); 1786 uLongf tmpDestSize = destSize; 1787 memset(tmpStrip, whitePt, scanlineWidth * topMarginInPix); 1788 1789 for (sint32 stripCntr = 0; stripCntr < numFullInjectedStrips; stripCntr++) { 1790 result = compress(scratchBuffer, &tmpDestSize, (const Bytef *) tmpStrip, 1791 scanlineWidth * numFullScanlinesToInject); 1792 injectLZStrip(scratchBuffer, tmpDestSize, mediaWidthInPixels, 1793 numFullScanlinesToInject, destColorSpace, true); 1794 } 1795 if (numPartialScanlinesToInject) { 1796 result = compress(scratchBuffer, &tmpDestSize, (const Bytef *) tmpStrip, 1797 scanlineWidth * numPartialScanlinesToInject); 1798 injectLZStrip(scratchBuffer, tmpDestSize, mediaWidthInPixels, 1799 numPartialScanlinesToInject, destColorSpace, true); 1800 } 1801 free(tmpStrip); 1802 } 1803 firstStrip = false; 1804 1805 if (newStripPtr) { 1806 result = compress(scratchBuffer, &destSize, (const Bytef *) newStripPtr, 1807 scanlineWidth * numLinesThisCall); 1808 free(newStripPtr); 1809 newStripPtr = NULL; 1810 } else { 1811 // Dump the source data 1812 result = compress(scratchBuffer, &destSize, (const Bytef *) localInBuffer, 1813 scanlineWidth * numLinesThisCall); 1814 } 1815 injectLZStrip(scratchBuffer, destSize, mediaWidthInPixels, numLinesThisCall, destColorSpace, 1816 whiteStrip); 1817 } else if (currCompressionDisposition == compressRLE) { 1818 int compSize; 1819 if (firstStrip && topMarginInPix) { 1820 ubyte whitePt = 0xff; 1821 1822 // We need to inject a blank image-strip with a height==topMarginInPix 1823 1824 ubyte *tmpStrip = (ubyte *) malloc(scanlineWidth * topMarginInPix); 1825 memset(tmpStrip, whitePt, scanlineWidth * topMarginInPix); 1826 1827 for (sint32 stripCntr = 0; stripCntr < numFullInjectedStrips; stripCntr++) { 1828 compSize = RLEEncodeImage(tmpStrip, scratchBuffer, 1829 scanlineWidth * numFullScanlinesToInject); 1830 injectRLEStrip(scratchBuffer, compSize, mediaWidthInPixels, 1831 numFullScanlinesToInject, destColorSpace, true); 1832 } 1833 1834 if (numPartialScanlinesToInject) { 1835 compSize = RLEEncodeImage(tmpStrip, scratchBuffer, 1836 scanlineWidth * numPartialScanlinesToInject); 1837 injectRLEStrip(scratchBuffer, compSize, mediaWidthInPixels, 1838 numPartialScanlinesToInject, destColorSpace, true); 1839 } 1840 1841 free(tmpStrip); 1842 } 1843 firstStrip = false; 1844 1845 if (newStripPtr) { 1846 compSize = RLEEncodeImage(newStripPtr, scratchBuffer, 1847 scanlineWidth * numLinesThisCall); 1848 free(newStripPtr); 1849 newStripPtr = NULL; 1850 } else { 1851 compSize = RLEEncodeImage((ubyte *) localInBuffer, scratchBuffer, 1852 scanlineWidth * numLinesThisCall); 1853 } 1854 1855 injectRLEStrip(scratchBuffer, compSize, mediaWidthInPixels, numLinesThisCall, 1856 destColorSpace, whiteStrip); 1857 } else { 1858 assert(0); 1859 } 1860 1861 *iOutBufferSize = totalBytesWrittenToCurrBuff; 1862 1863 if (savedInBufferPtr) { 1864 pInBuffer = savedInBufferPtr; 1865 } 1866 1867 if (tmpBuffer) { 1868 free(tmpBuffer); 1869 } 1870 1871 if (newStripPtr) { 1872 free(newStripPtr); 1873 } 1874 1875 return success; 1876 } 1877 1878 int PCLmGenerator::GetPclmMediaDimensions(const char *mediaRequested, 1879 PCLmPageSetup *myPageInfo) { 1880 int i = 0; 1881 int result = 99; 1882 1883 int iRenderResolutionInteger = 0; 1884 if (myPageInfo->destinationResolution == res300) { 1885 iRenderResolutionInteger = 300; 1886 } else if (myPageInfo->destinationResolution == res600) { 1887 iRenderResolutionInteger = 600; 1888 } else if (myPageInfo->destinationResolution == res1200) { 1889 iRenderResolutionInteger = 1200; 1890 } else { 1891 assert(0); 1892 } 1893 1894 for (i = 0; i < SUPPORTED_MEDIA_SIZE_COUNT; i++) { 1895 if (strcasecmp(mediaRequested, SupportedMediaSizes[i].PCL6Name) == 0) { 1896 myPageInfo->mediaWidth = floorf( 1897 _MI_TO_POINTS(SupportedMediaSizes[i].WidthInInches)); 1898 myPageInfo->mediaHeight = floorf( 1899 _MI_TO_POINTS(SupportedMediaSizes[i].HeightInInches)); 1900 myPageInfo->mediaWidthInPixels = floorf( 1901 _MI_TO_PIXELS(SupportedMediaSizes[i].WidthInInches, 1902 iRenderResolutionInteger)); 1903 myPageInfo->mediaHeightInPixels = floorf( 1904 _MI_TO_PIXELS(SupportedMediaSizes[i].HeightInInches, 1905 iRenderResolutionInteger)); 1906 result = i; 1907 break; // we found a match, so break out of loop 1908 } 1909 } 1910 1911 if (i == SUPPORTED_MEDIA_SIZE_COUNT) { 1912 // media size not found, defaulting to letter 1913 printf("PCLmGenerator get_pclm_media_size(): media size, %s, NOT FOUND, setting to letter", 1914 mediaRequested); 1915 result = GetPclmMediaDimensions("LETTER", myPageInfo); 1916 } 1917 1918 return result; 1919 } 1920 1921 void PCLmGenerator::FreeBuffer(void *pBuffer) { 1922 if (jobOpen == job_closed && pBuffer) { 1923 if (pBuffer == allocatedOutputBuffer) { 1924 allocatedOutputBuffer = NULL; 1925 } 1926 free(pBuffer); 1927 } 1928 } 1929