home *** CD-ROM | disk | FTP | other *** search
/ PSION CD 2 / PsionCDVol2.iso / Programs / 720 / PDF090B4-SorceCode / pdf / GfxState.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-30  |  32.2 KB  |  1,385 lines

  1. //========================================================================
  2. //
  3. // GfxState.cc
  4. //
  5. // Copyright 1996 Derek B. Noonburg
  6. //
  7. //========================================================================
  8. //
  9. // Ported to EPOC by Sander van der Wal
  10. //
  11. // $Log: GfxState.cpp $
  12. // Revision 1.4  2000-09-24 21:09:35+02  svdwal
  13. // Memory leak fixed
  14. //
  15. // Revision 1.3  2000-09-21 14:44:54+02  svdwal
  16. // Some xpdf 0.91 bugfixes added
  17. //
  18. // Revision 1.2  2000-09-17 13:38:23+02  svdwal
  19. // Ported
  20. //
  21.  
  22. #ifdef __GNUC__
  23. #pragma implementation
  24. #endif
  25.  
  26. #ifndef __E32DEF_H__
  27. #include <e32def.h> // remove warning about NULL redefinition
  28. #endif
  29.  
  30. #ifndef __E32MATH_H__
  31. #include <e32math.h>
  32. #endif
  33.  
  34. // --o C library
  35. #include <math.h>
  36.  
  37. #include "gmem.h"
  38.  
  39. #include "Error.h"
  40. #include "Object.h"
  41. #include "GfxState.h"
  42.  
  43. #include "Pdf.rsg"
  44.  
  45. static const TInt KSubpathSizeIncrement = 16;
  46. static const TInt KPathSizeIncrement = 16;
  47.  
  48. //------------------------------------------------------------------------
  49. // GfxColor
  50. //------------------------------------------------------------------------
  51. #ifdef FIXCOLOR
  52. void GfxColor::setGray(int gray) {
  53.   if (gray < 0) {
  54.     gray = 0;
  55.   } else if (gray > 255) {
  56.     gray = 255;
  57.   }
  58.   r = g = b = gray;
  59. }
  60.  
  61.  
  62. void GfxColor::setCMYK(int c, int m, int y, int k) {
  63.   if ((r = 255 - (c + k)) < 0) {
  64.     r = 0;
  65.   } else if (r > 255) {
  66.     r = 255;
  67.   }
  68.   if ((g = 255 - (m + k)) < 0) {
  69.     g = 0;
  70.   } else if (g > 255) {
  71.     g = 255;
  72.   }
  73.   if ((b = 255 - (y + k)) < 0) {
  74.     b = 0;
  75.   } else if (b > 255) {
  76.     b = 255;
  77.   }
  78. }
  79.  
  80. void GfxColor::setRGB(int r1, int g1, int b1) {
  81.   if ((r = r1) < 0) {
  82.     r = 0;
  83.   } else if (r1 > 255) {
  84.     r = 255;
  85.   }
  86.   if ((g = g1) < 0) {
  87.     g = 0;
  88.   } else if (g1 > 255) {
  89.     g = 255;
  90.   }
  91.   if ((b = b1) < 0) {
  92.     b = 0;
  93.   } else if (b1 > 255) {
  94.     b = 255;
  95.   }
  96. }
  97. #else
  98. void GfxColor::setGray(double gray) {
  99.   if (gray < 0) {
  100.     r = g = b = 0;
  101.   } else if (gray > 1) {
  102.     r = g = b = 1;
  103.   } else {
  104.     r = g = b = gray;
  105.   }
  106. }
  107.  
  108. void GfxColor::setCMYK(double c, double m, double y, double k) {
  109.   if ((r = 1 - (c + k)) < 0) {
  110.     r = 0;
  111.   } else if (r > 1) {
  112.     r = 1;
  113.   }
  114.   if ((g = 1 - (m + k)) < 0) {
  115.     g = 0;
  116.   } else if (g > 1) {
  117.     g = 1;
  118.   }
  119.   if ((b = 1 - (y + k)) < 0) {
  120.     b = 0;
  121.   } else if (b > 1) {
  122.     b = 1;
  123.   }
  124. }
  125.  
  126. void GfxColor::setRGB(double r1, double g1, double b1) {
  127.   if (r1 < 0) {
  128.     r = 0;
  129.   } else if (r1 > 1) {
  130.     r = 1;
  131.   } else {
  132.     r = r1;
  133.   }
  134.   if (g1 < 0) {
  135.     g = 0;
  136.   } else if (g1 > 1) {
  137.     g = 1;
  138.   } else {
  139.     g = g1;
  140.   }
  141.   if (b1 < 0) {
  142.     b = 0;
  143.   } else if (b1 > 1) {
  144.     b = 1;
  145.   } else {
  146.     b = b1;
  147.   }
  148. }
  149. #endif
  150.  
  151. //------------------------------------------------------------------------
  152. // GfxColorSpace
  153. //------------------------------------------------------------------------
  154.  
  155. void GfxColorSpace::ConstructL(Object *colorSpace) {
  156.   RAutoObject csObj;
  157.   RAutoObject obj, obj2;
  158.   char *s;
  159.   int x;
  160.   int i, j;
  161.  
  162.   ok = gTrue;
  163.   lookup = NULL;
  164.   
  165.   // check for Separation, DeviceN and Pattern colorspaces
  166.   colorSpace->copyL(&csObj);
  167.   sepFunc = NULL;
  168.   if (colorSpace->isArray()) {
  169.     colorSpace->arrayGetL(0, &obj);
  170.     if (obj.isName("Separation") || obj.isName("DeviceN")) {
  171.       csObj.free();
  172.       colorSpace->arrayGetL(2, &csObj);
  173.       sepFunc = new(ELeave) Function();
  174.       sepFunc->ConstructL(colorSpace->arrayGetL(3, &obj2));
  175.       obj2.free();
  176.       if (!sepFunc->isOk()) {
  177.         delete sepFunc;
  178.         sepFunc = NULL;
  179.       }
  180.     } 
  181.     else if (obj.isName("Pattern")) {
  182.       csObj.free();
  183.       colorSpace->arrayGetL(1, &csObj);
  184.     }
  185.     obj.free();
  186.   }
  187.  
  188.   // get mode
  189.   indexed = gFalse;
  190.   if (csObj.isName()) {
  191.     setMode(&csObj);
  192.   } else if (csObj.isArray()) {
  193.     csObj.arrayGetL(0, &obj);
  194.     if (obj.isName("Indexed") || obj.isName("I")) {
  195.       indexed = gTrue;
  196.       setMode(csObj.arrayGetL(1, &obj2));
  197.       obj2.free();
  198.     }
  199.     else {
  200.       setMode(&csObj);
  201.     }
  202.     obj.free();
  203.   } else {
  204.     goto err1;
  205.   }
  206.   if (!ok) {
  207.     goto err1;
  208.   }
  209.  
  210.   if (indexed) {
  211.     // get lookup table for indexed colorspace
  212.     csObj.arrayGetL(2, &obj);
  213.     if (!obj.isInt())
  214.       goto err2;
  215.     indexHigh = obj.getInt();
  216.     obj.free();
  217.     lookup = (Guchar (*)[4])User::AllocL((indexHigh + 1) * 4 * sizeof(Guchar));
  218.     csObj.arrayGetL(3, &obj);
  219.     if (obj.isStream()) {
  220.       obj.streamReset();
  221.       for (i = 0; i <= indexHigh; ++i) {
  222.         for (j = 0; j < numComps; ++j) {
  223.           if ((x = obj.streamGetChar()) == EOF)
  224.            goto err2;
  225.           lookup[i][j] = (Guchar)x;
  226.         }
  227.       }
  228.     } 
  229.     else if (obj.isString()) {
  230.       s = obj.getString()->getCString();
  231.       for (i = 0; i <= indexHigh; ++i)
  232.         for (j = 0; j < numComps; ++j)
  233.           lookup[i][j] = (Guchar)*s++;
  234.     } 
  235.     else {
  236.       goto err2;
  237.     }
  238.     obj.free();
  239.   }
  240.  
  241.   csObj.free();
  242.   return;
  243.  
  244.  err2:
  245.   obj.free();
  246.  err1:
  247.   csObj.free();
  248.   ok = gFalse;
  249. }
  250.  
  251. GfxColorSpace::GfxColorSpace(GfxColorMode mode1) {
  252.   sepFunc = NULL;
  253.   mode = mode1;
  254.   indexed = gFalse;
  255.   switch (mode) {
  256.   case colorGray: numComps = 1; break;
  257.   case colorCMYK: numComps = 4; break;
  258.   case colorRGB:  numComps = 3; break;
  259.   }
  260.   lookup = NULL;
  261.   ok = gTrue;
  262. }
  263.  
  264. GfxColorSpace::~GfxColorSpace() {
  265.   delete sepFunc;
  266.   User::Free(lookup);
  267. }
  268.  
  269.  
  270. void GfxColorSpace::ConstructL(GfxColorSpace *colorSpace) {
  271.   int size;
  272.  
  273.   if (colorSpace->sepFunc)
  274.     sepFunc = colorSpace->sepFunc->copyL();
  275.   else
  276.     sepFunc = NULL;
  277.   mode = colorSpace->mode;
  278.   indexed = colorSpace->indexed;
  279.   numComps = colorSpace->numComps;
  280.   indexHigh = colorSpace->indexHigh;
  281.   if (indexed) {
  282.     size = (indexHigh + 1) * 4 * sizeof(Guchar);
  283.     lookup = (Guchar (*)[4])User::AllocL(size);
  284.     Mem::Copy(lookup, colorSpace->lookup, size);
  285.   } else {
  286.     lookup = NULL;
  287.   }
  288.   ok = gTrue;
  289. }
  290.  
  291. GfxColorSpace *GfxColorSpace::copyL()
  292.   GfxColorSpace* self = new(ELeave)  GfxColorSpace();
  293.   CleanupStack::PushL(self);
  294.   self->ConstructL(this);
  295.   CleanupStack::Pop(); // self
  296.   return self;
  297. }
  298.  
  299. void GfxColorSpace::setMode(Object *colorSpace) {
  300.   RAutoObject obj;
  301.  
  302.   if (colorSpace->isName("DeviceGray") || colorSpace->isName("G")) {
  303.     mode = colorGray;
  304.     numComps = 1;
  305.   } else if (colorSpace->isName("DeviceRGB") || colorSpace->isName("RGB")) {
  306.     mode = colorRGB;
  307.     numComps = 3;
  308.   } else if (colorSpace->isName("DeviceCMYK") || colorSpace->isName("CMYK")) {
  309.     mode = colorCMYK;
  310.     numComps = 4;
  311.   } else if (colorSpace->isArray()) {
  312.     colorSpace->arrayGetL(0, &obj);
  313.     if (obj.isName("CalGray")) {
  314.       mode = colorGray;
  315.       numComps = 1;
  316.     } else if (obj.isName("CalRGB")) {
  317.       mode = colorRGB;
  318.       numComps = 3;
  319.     } else if (obj.isName("CalCMYK")) {
  320.       mode = colorCMYK;
  321.       numComps = 4;
  322.     } else if (obj.isName("ICCBased")) {
  323.       obj.free();
  324.       // try the Alternate colorspace. If there's none, use N
  325.       colorSpace->arrayGetL(1, &obj);
  326.       if (obj.isStream()) {
  327.         obj.streamReset();
  328.         RAutoObject obj2;
  329.         obj.streamGetDict()->lookupL("Alternate", &obj2);
  330.         if (obj2.isNone()) {
  331.           obj.streamGetDict()->lookupL("N", &obj2);
  332.           if (obj2.isInt()) {
  333.             switch (numComps = obj2.getInt()) {
  334.             case 1: mode = colorGray; break;
  335.             case 3: mode = colorRGB;  break;
  336.             case 4: mode = colorCMYK; break;
  337.             default:
  338.               ok = gFalse;  
  339.             }
  340.           }
  341.           else
  342.             ok = gFalse; // N is not optional
  343.         }
  344.         else       
  345.           setMode(&obj2);
  346.       } 
  347.       else
  348.         ok = gFalse; // must be a stream 
  349.     }
  350.     else {
  351.       ok = gFalse;
  352.     }
  353.     obj.free();
  354.   } else {
  355.     ok = gFalse;
  356.   }
  357. }
  358.  
  359. #ifdef FIXCOLOR
  360. void GfxColorSpace::getColor(int x[4], GfxColor *color) {
  361.   int y[4];
  362.   Guchar *p;
  363.  
  364.   if (sepFunc) {
  365.     sepFunc->transform(x, y);
  366.   } else {
  367.     y[0] = x[0];
  368.     y[1] = x[1];
  369.     y[2] = x[2];
  370.     y[3] = x[3];
  371.   }
  372.  
  373.   if (indexed) {
  374.     p = lookup[x[0]];
  375.     switch (mode) {
  376.     case colorGray:
  377.       color->setGray(p[0]);
  378.       break;
  379.     case colorCMYK:
  380.       color->setCMYK(p[0], p[1], p[2], p[3]);
  381.       break;
  382.     case colorRGB:
  383.       color->setRGB(p[0], p[1], p[2]);
  384.       break;
  385.     }
  386.   } 
  387.   else {
  388.     switch (mode) {
  389.     case colorGray:
  390.       color->setGray(x[0]);
  391.       break;
  392.     case colorCMYK:
  393.       color->setCMYK(x[0], x[1], x[2], x[3]);
  394.       break;
  395.     case colorRGB:
  396.       color->setRGB(x[0], x[1], x[2]);
  397.       break;
  398.     }
  399.   }
  400. }
  401. #else
  402. void GfxColorSpace::getColor(double x[4], GfxColor *color) {
  403.   double y[4];
  404.   Guchar *p;
  405.  
  406.   if (sepFunc) {
  407.     sepFunc->transform(x, y);
  408.   } else {
  409.     y[0] = x[0];
  410.     y[1] = x[1];
  411.     y[2] = x[2];
  412.     y[3] = x[3];
  413.   }
  414.   if (indexed) {
  415.     p = lookup[(int)(y[0] + 0.5)];
  416.     switch (mode) {
  417.     case colorGray:
  418.       color->setGray(p[0] / 255.0);
  419.       break;
  420.     case colorCMYK:
  421.       color->setCMYK(p[0] / 255.0, p[1] / 255.0, p[2] / 255.0, p[3] / 255.0);
  422.       break;
  423.     case colorRGB:
  424.       color->setRGB(p[0] / 255.0, p[1] / 255.0, p[2] / 255.0);
  425.       break;
  426.     }
  427.   } else {
  428.     switch (mode) {
  429.     case colorGray:
  430.       color->setGray(y[0]);
  431.       break;
  432.     case colorCMYK:
  433.       color->setCMYK(y[0], y[1], y[2], y[3]);
  434.       break;
  435.     case colorRGB:
  436.       color->setRGB(y[0], y[1], y[2]);
  437.       break;
  438.     }
  439.   }
  440. }
  441. #endif
  442.  
  443. //------------------------------------------------------------------------
  444. // Function
  445. //------------------------------------------------------------------------
  446.  
  447. void Function::ConstructL(Object *funcObj) 
  448. {
  449.   Stream *str;
  450.   Dict *dict;
  451.   int nSamples, sampleBits;
  452.   double sampleMul;
  453.   RAutoObject obj1, obj2;
  454.   Guint buf, bitMask;
  455.   int bits;
  456.   int s;
  457.   int i;
  458.  
  459.   ok = gFalse;
  460.   samples = NULL;
  461.  
  462.   if (!funcObj->isStream()) {
  463.     error(-1, R_EXPECTED_FUNCTION_DICTIONARY);
  464.     goto err3;
  465.   }
  466.   str = funcObj->getStream();
  467.   dict = str->getDict();
  468.  
  469.   //----- FunctionType
  470.   if (!dict->lookupL("FunctionType", &obj1)->isInt() ||
  471.       obj1.getInt() != 0) {
  472.     error(-1, R_UNKNOWN_FUNCTION_TYPE);
  473.     goto err2;
  474.   }
  475.   obj1.free();
  476.  
  477.   //----- Domain
  478.   if (!dict->lookupL("Domain", &obj1)->isArray()) {
  479.     error(-1, R_FUNCTION_IS_MISSING_DOMAIN);
  480.     goto err2;
  481.   }
  482.   m = obj1.arrayGetLength() / 2;
  483.   if (m > 1) {
  484.     error(-1, R_FUNCTIONS_WITH_MORE_THAN_1_INPUT_ARE_UNSUPPORTED);
  485.     goto err2;
  486.   }
  487.   for (i = 0; i < m; ++i) {
  488.     obj1.arrayGetL(2*i, &obj2);
  489.     if (!obj2.isNum()) {
  490.       error(-1, R_ILLEGAL_VALUE_IN_FUNCTION_DOMAIN_ARRAY);
  491.       goto err1;
  492.     }
  493.     domain[i][0] = obj2.getNum();
  494.     obj2.free();
  495.     obj1.arrayGetL(2*i+1, &obj2);
  496.     if (!obj2.isNum()) {
  497.       error(-1, R_ILLEGAL_VALUE_IN_FUNCTION_DOMAIN_ARRAY);
  498.       goto err1;
  499.     }
  500.     domain[i][1] = obj2.getNum();
  501.     obj2.free();
  502.   }
  503.   obj1.free();
  504.  
  505.   //----- Range
  506.   if (!dict->lookupL("Range", &obj1)->isArray()) {
  507.     error(-1, R_FUNCTION_IS_MISSING_RANGE);
  508.     goto err2;
  509.   }
  510.   n = obj1.arrayGetLength() / 2;
  511.   if (n > 4) {
  512.     error(-1, R_FUNCTIONS_WITH_MORE_THAN_4_OUTPUTS_ARE_UNSUPPORTED);
  513.     goto err2;
  514.   }
  515.   for (i = 0; i < n; ++i) {
  516.     obj1.arrayGetL(2*i, &obj2);
  517.     if (!obj2.isNum()) {
  518.       error(-1, R_ILLEGAL_VALUE_IN_FUNCTION_RANGE_ARRAY);
  519.       goto err1;
  520.     }
  521.     range[i][0] = obj2.getNum();
  522.     obj2.free();
  523.     obj1.arrayGetL(2*i+1, &obj2);
  524.     if (!obj2.isNum()) {
  525.       error(-1, R_ILLEGAL_VALUE_IN_FUNCTION_RANGE_ARRAY);
  526.       goto err1;
  527.     }
  528.     range[i][1] = obj2.getNum();
  529.     obj2.free();
  530.   }
  531.   obj1.free();
  532.  
  533.   //----- Size
  534.   if (!dict->lookupL("Size", &obj1)->isArray() ||
  535.       obj1.arrayGetLength() != m) {
  536.     error(-1, R_FUNCTION_HAS_MISSING_OR_INVALID_SIZE_ARRAY);
  537.     goto err2;
  538.   }
  539.   for (i = 0; i < m; ++i) {
  540.     obj1.arrayGetL(i, &obj2);
  541.     if (!obj2.isInt()) {
  542.       error(-1, R_ILLEGAL_VALUE_IN_FUNCTION_SIZE_ARRAY);
  543.       goto err1;
  544.     }
  545.     sampleSize[i] = obj2.getInt();
  546.     obj2.free();
  547.   }
  548.   obj1.free();
  549.  
  550.   //----- BitsPerSample
  551.   if (!dict->lookupL("BitsPerSample", &obj1)->isInt()) {
  552.     error(-1, R_FUNCTION_HAS_MISSING_OR_INVALID_BITSPERSAMPLE);
  553.     goto err2;
  554.   }
  555.   sampleBits = obj1.getInt();
  556.   sampleMul = 1.0 / (double)((1 << sampleBits) - 1);
  557.   obj1.free();
  558.  
  559.   //----- Encode
  560.   if (dict->lookupL("Encode", &obj1)->isArray() &&
  561.       obj1.arrayGetLength() == 2*m) {
  562.     for (i = 0; i < m; ++i) {
  563.       obj1.arrayGetL(2*i, &obj2);
  564.       if (!obj2.isNum()) {
  565.     error(-1, R_ILLEGAL_VALUE_IN_FUNCTION_ENCODE_ARRAY);
  566.     goto err1;
  567.       }
  568.       encode[i][0] = obj2.getNum();
  569.       obj2.free();
  570.       obj1.arrayGetL(2*i+1, &obj2);
  571.       if (!obj2.isNum()) {
  572.     error(-1, R_ILLEGAL_VALUE_IN_FUNCTION_ENCODE_ARRAY);
  573.     goto err1;
  574.       }
  575.       encode[i][1] = obj2.getNum();
  576.       obj2.free();
  577.     }
  578.   } else {
  579.     for (i = 0; i < m; ++i) {
  580.       encode[i][0] = 0;
  581.       encode[i][1] = sampleSize[i] - 1;
  582.     }
  583.   }
  584.   obj1.free();
  585.  
  586.   //----- Decode
  587.   if (dict->lookupL("Decode", &obj1)->isArray() &&
  588.       obj1.arrayGetLength() == 2*n) {
  589.     for (i = 0; i < n; ++i) {
  590.       obj1.arrayGetL(2*i, &obj2);
  591.       if (!obj2.isNum()) {
  592.     error(-1, R_ILLEGAL_VALUE_IN_FUNCTION_DECODE_ARRAY);
  593.     goto err1;
  594.       }
  595.       decode[i][0] = obj2.getNum();
  596.       obj2.free();
  597.       obj1.arrayGetL(2*i+1, &obj2);
  598.       if (!obj2.isNum()) {
  599.     error(-1, R_ILLEGAL_VALUE_IN_FUNCTION_DECODE_ARRAY);
  600.     goto err1;
  601.       }
  602.       decode[i][1] = obj2.getNum();
  603.       obj2.free();
  604.     }
  605.   } else {
  606.     for (i = 0; i < n; ++i) {
  607.       decode[i][0] = range[i][0];
  608.       decode[i][1] = range[i][1];
  609.     }
  610.   }
  611.   obj1.free();
  612.  
  613.   //----- samples
  614.   nSamples = n;
  615.   for (i = 0; i < m; ++i)
  616.     nSamples *= sampleSize[i];
  617.   samples = (double *)User::AllocL(nSamples * sizeof(double));
  618.   buf = 0;
  619.   bits = 0;
  620.   bitMask = (1 << sampleBits) - 1;
  621.   str->reset();
  622.   for (i = 0; i < nSamples; ++i) {
  623.     if (sampleBits == 8) {
  624.       s = str->getChar();
  625.     } else if (sampleBits == 16) {
  626.       s = str->getChar();
  627.       s = (s << 8) + str->getChar();
  628.     } else if (sampleBits == 32) {
  629.       s = str->getChar();
  630.       s = (s << 8) + str->getChar();
  631.       s = (s << 8) + str->getChar();
  632.       s = (s << 8) + str->getChar();
  633.     } else {
  634.       while (bits < sampleBits) {
  635.     buf = (buf << 8) | (str->getChar() & 0xff);
  636.     bits += 8;
  637.       }
  638.       s = (buf >> (bits - sampleBits)) & bitMask;
  639.       bits -= sampleBits;
  640.     }
  641.     samples[i] = (double)s * sampleMul;
  642.   }
  643.  
  644.   ok = gTrue;
  645.   return;
  646.  
  647.  err1:
  648.   obj2.free();
  649.  err2:
  650.   obj1.free();
  651.  err3:
  652.   return;
  653. }
  654.  
  655.  
  656. void Function::ConstructL(Function *func)
  657. {
  658.   int nSamples, i;
  659.  
  660.   m = func->m;
  661.   n = func->n;
  662.   Mem::Copy(domain, func->domain, sizeof(domain));
  663.   Mem::Copy(range, func->range, sizeof(range));
  664.   Mem::Copy(sampleSize, func->sampleSize, sizeof(sampleSize));
  665.   Mem::Copy(encode, func->encode, sizeof(encode));
  666.   Mem::Copy(decode, func->decode, sizeof(decode));
  667.  
  668.   nSamples = n;
  669.   for (i = 0; i < m; ++i)
  670.     nSamples *= sampleSize[i];
  671.   samples = (double *)User::AllocL(nSamples * sizeof(double));
  672.   Mem::Copy(samples, func->samples, nSamples * sizeof(double));
  673.  
  674.   ok = gTrue;
  675. }
  676.  
  677. Function::~Function() {
  678.   User::Free(samples);
  679. }
  680.  
  681. Function *Function::copyL()
  682.   Function* self = new(ELeave) Function(); 
  683.   CleanupStack::PushL(self);
  684.   self->ConstructL(this);
  685.   CleanupStack::Pop(); // self
  686.   return self;
  687. }
  688.  
  689.  
  690. #ifdef FIXCOLOR
  691. void Function::transform(int* in, int* out) {
  692.   int e[4];
  693.   double s;
  694.   double x0, x1;
  695.   int e0, e1;
  696.   double efrac;
  697.   int i;
  698.  
  699.   // map input values into sample array
  700.   for (i = 0; i < m; ++i) {
  701.     e[i] = ((in[i] - domain[i][0]) / (domain[i][1] - domain[i][0])) *
  702.            (encode[i][1] - encode[i][0]) + encode[i][0];
  703.     if (e[i] < 0)
  704.       e[i] = 0;
  705.     else if (e[i] > sampleSize[i] - 1)
  706.       e[i] = sampleSize[i] - 1;
  707.   }
  708.  
  709.   for (i = 0; i < n; ++i) {
  710.  
  711.     // m-linear interpolation
  712.     // (only m=1 is currently supported)
  713.     e0 = (int)floor(e[0]);
  714.     e1 = (int)ceil(e[0]);
  715.     efrac = e[0] - e0;
  716.     x0 = samples[e0 * n + i];
  717.     x1 = samples[e1 * n + i];
  718.     s = (1 - efrac) * x0 + efrac * x1;
  719.  
  720.     // map output values to range
  721.     out[i] = s * (decode[i][1] - decode[i][0]) + decode[i][0];
  722.     if (out[i] < range[i][0])
  723.       out[i] = range[i][0];
  724.     else if (out[i] > range[i][1])
  725.       out[i] = range[i][1];
  726.   }
  727. }
  728. #else
  729. void Function::transform(double *in, double *out) {
  730.   double e[4];
  731.   double s;
  732.   double x0, x1;
  733.   int e0, e1;
  734.   double efrac;
  735.   int i;
  736.  
  737.   // map input values into sample array
  738.   for (i = 0; i < m; ++i) {
  739.     e[i] = ((in[i] - domain[i][0]) / (domain[i][1] - domain[i][0])) *
  740.            (encode[i][1] - encode[i][0]) + encode[i][0];
  741.     if (e[i] < 0)
  742.       e[i] = 0;
  743.     else if (e[i] > sampleSize[i] - 1)
  744.       e[i] = sampleSize[i] - 1;
  745.   }
  746.  
  747.   for (i = 0; i < n; ++i) {
  748.  
  749.     // m-linear interpolation
  750.     // (only m=1 is currently supported)
  751.     e0 = (int)floor(e[0]);
  752.     e1 = (int)ceil(e[0]);
  753.     efrac = e[0] - e0;
  754.     x0 = samples[e0 * n + i];
  755.     x1 = samples[e1 * n + i];
  756.     s = (1 - efrac) * x0 + efrac * x1;
  757.  
  758.     // map output values to range
  759.     out[i] = s * (decode[i][1] - decode[i][0]) + decode[i][0];
  760.     if (out[i] < range[i][0])
  761.       out[i] = range[i][0];
  762.     else if (out[i] > range[i][1])
  763.       out[i] = range[i][1];
  764.   }
  765. }
  766. #endif
  767.  
  768. //------------------------------------------------------------------------
  769. // GfxImageColorMap
  770. //------------------------------------------------------------------------
  771. GfxImageColorMap::GfxImageColorMap(GfxColorSpace *aColorSpace): colorSpace(aColorSpace)  {}
  772.  
  773. void GfxImageColorMap::ConstructL(int bits1, Object *decode) {
  774.   GfxColor color;
  775. #ifdef FIXCOLOR
  776.   int x[4];
  777. #else
  778.   double x[4];
  779. #endif
  780.   int maxPixel;
  781.   RAutoObject obj;
  782.   int i, j;
  783.  
  784.   ok = gTrue;
  785.  
  786.   // bits per component and colorspace
  787.   bits = bits1;
  788.   maxPixel = (1 << bits) - 1;
  789.   mode = colorSpace->getMode();
  790.  
  791.   // work around a bug in Distiller (?)
  792.   if (colorSpace->isIndexed() && maxPixel > colorSpace->getIndexHigh()) {
  793.     maxPixel = colorSpace->getIndexHigh();
  794.   }
  795.  
  796.   // get decode map
  797.   if (decode->isNull()) {
  798.     if (colorSpace->isIndexed()) {
  799.       indexed = gTrue;
  800.       numComps = 1;
  801. #if defined(FIXCOLOR)
  802.       decodeLow[0] = 0;
  803.       decodeRange[0] = maxPixel * 255;
  804. #else
  805.       decodeLow[0] = 0;
  806.       decodeRange[0] = maxPixel;
  807. #endif
  808.     } else {
  809.       indexed = gFalse;
  810.       numComps = colorSpace->getNumPixelComps();
  811.       for (i = 0; i < numComps; ++i) {
  812. #if defined(FIXCOLOR)
  813.     decodeLow[i] = 0;
  814.     decodeRange[i] = 255;
  815. #else
  816.         decodeLow[i] = 0;
  817.         decodeRange[i] = 1;
  818. #endif
  819.       }
  820.     }
  821.   } 
  822.   else if (decode->isArray()) {
  823.     numComps = decode->arrayGetLength() / 2;
  824.     if (numComps != colorSpace->getNumPixelComps())
  825.       goto err1;
  826.     indexed = colorSpace->isIndexed();
  827.     for (i = 0; i < numComps; ++i) {
  828.       decode->arrayGetL(2*i, &obj);
  829.       if (!obj.isNum())
  830.         goto err2;
  831. #if defined(FIXCOLOR)
  832.       decodeLow[i] = (int)(obj.getNum() * 255.0);
  833. #else
  834.       decodeLow[i] = obj.getNum();
  835. #endif
  836.       obj.free();
  837.       decode->arrayGetL(2*i+1, &obj);
  838.       if (!obj.isNum())
  839.         goto err2;
  840. #if defined(FIXCOLOR)
  841.       decodeRange[i] = (int)(obj.getNum() * 255.0) - decodeLow[i];
  842. #else
  843.       decodeRange[i] = obj.getNum() - decodeLow[i];
  844. #endif
  845.       obj.free();
  846.     }
  847.   } else {
  848.     goto err1;
  849.   }
  850.  
  851.   // construct lookup table
  852. #ifdef FIXCOLOR
  853.   lookup = (int (*)[4])User::AllocL((maxPixel + 1) * 4 * sizeof(int));
  854. #else
  855.   lookup = (double (*)[4])User::AllocL((maxPixel + 1) * 4 * sizeof(double));
  856. #endif
  857.   if (indexed) {
  858.     for (i = 0; i <= maxPixel; ++i) {
  859. #ifdef FIXCOLOR
  860.       x[0] = i;
  861. #else
  862.       x[0] = (double)i;
  863. #endif
  864.       colorSpace->getColor(x, &color);
  865.       lookup[i][0] = color.getR();
  866.       lookup[i][1] = color.getG();
  867.       lookup[i][2] = color.getB();
  868.     }
  869.   } else {
  870.     for (i = 0; i <= maxPixel; ++i)
  871.       for (j = 0; j < numComps; ++j)
  872.     lookup[i][j] = decodeLow[j] + (i * decodeRange[j]) / maxPixel;
  873.   }
  874.  
  875.   return;
  876.  
  877.  err2:
  878.   obj.free();
  879.  err1:
  880.   ok = gFalse;
  881. }
  882.  
  883. GfxImageColorMap::~GfxImageColorMap() {
  884.   delete colorSpace;
  885.   User::Free(lookup);
  886. }
  887.  
  888. /*
  889. #if defined(FIXCOLOR)
  890. void GfxImageColorMap::getColor(Guchar x[4], GfxColor *color) {
  891.   int y[4];
  892.   int i;
  893.  
  894.   if (simpleDecode) {
  895.     for (i = 0; i < decodeComps; ++i) {
  896.       y[i] = (((int)x[i]) * 255) / maxPixel;
  897.     }
  898.   } else if (indexDecode) {
  899.     y[0] = x[0];
  900.   } else {
  901.     for (i = 0; i < decodeComps; ++i) {
  902.       y[i] = (decodeLow[i] + (((int)x[i]) * decodeRange[i]) / maxPixel) / 256;
  903. //      y[i] = decodeLow[i] + (((int)x[i]) * decodeRange[i]) / maxPixel;
  904.     }
  905.   }
  906.   colorSpace->getColor(y, color);
  907. }
  908. #else
  909. */
  910. void GfxImageColorMap::getColor(Guchar x[4], GfxColor *color) {
  911. #ifdef FIXCOLOR
  912.   int* p;
  913. #else
  914.   double *p;
  915. #endif
  916.  
  917.   if (indexed) {
  918.     p = lookup[x[0]];
  919.     color->setRGB(p[0], p[1], p[2]);
  920.   } else {
  921.     switch (mode) {
  922.     case colorGray:
  923.       color->setGray(lookup[x[0]][0]);
  924.       break;
  925.     case colorCMYK:
  926.       color->setCMYK(lookup[x[0]][0], lookup[x[1]][1],
  927.              lookup[x[2]][2], lookup[x[3]][3]);
  928.       break;
  929.     case colorRGB:
  930.       color->setRGB(lookup[x[0]][0], lookup[x[1]][1], lookup[x[2]][2]);
  931.       break;
  932.     }
  933.   }
  934. }
  935. //#endif
  936.  
  937. //------------------------------------------------------------------------
  938. // GfxSubpath and GfxPath
  939. //------------------------------------------------------------------------
  940.  
  941. void GfxSubpath::ConstructL(double x1, double y1) {
  942.   size = 16;
  943.   x = (double *)User::AllocL(size * sizeof(double));
  944.   y = (double *)User::AllocL(size * sizeof(double));
  945.   curve = (GBool *)User::AllocL(size * sizeof(GBool));
  946.   n = 1;
  947.   x[0] = x1;
  948.   y[0] = y1;
  949.   curve[0] = gFalse;
  950.   closed = gFalse;
  951. }
  952.  
  953. GfxSubpath::~GfxSubpath() {
  954.   User::Free(x);
  955.   User::Free(y);
  956.   User::Free(curve);
  957. }
  958.  
  959. // Used for copy().
  960. void GfxSubpath::ConstructL(GfxSubpath *subpath) {
  961.   size = subpath->size;
  962.   n = subpath->n;
  963.   x = (double *)User::AllocL(size * sizeof(double));
  964.   y = (double *)User::AllocL(size * sizeof(double));
  965.   curve = (GBool *)User::AllocL(size * sizeof(GBool));
  966.   Mem::Copy(x, subpath->x, n * sizeof(double));
  967.   Mem::Copy(y, subpath->y, n * sizeof(double));
  968.   Mem::Copy(curve, subpath->curve, n * sizeof(GBool));
  969.   closed = subpath->closed;
  970. }
  971.  
  972. GfxSubpath *GfxSubpath::copyL()
  973.   GfxSubpath* self = new(ELeave) GfxSubpath();
  974.   CleanupStack::PushL(self);
  975.   self->ConstructL(this);
  976.   CleanupStack::Pop(); // self
  977.   return self;
  978. }
  979.  
  980. void GfxSubpath::lineTo(double x1, double y1) {
  981.   if (n >= size) {
  982.     size += KSubpathSizeIncrement;
  983.     x = (double *)User::ReAllocL(x, size * sizeof(double));
  984.     y = (double *)User::ReAllocL(y, size * sizeof(double));
  985.     curve = (GBool *)User::ReAllocL(curve, size * sizeof(GBool));
  986.   }
  987.   x[n] = x1;
  988.   y[n] = y1;
  989.   curve[n] = gFalse;
  990.   ++n;
  991. }
  992.  
  993. void GfxSubpath::curveTo(double x1, double y1, double x2, double y2,
  994.              double x3, double y3) {
  995.   if (n+3 > size) {
  996.     size += KSubpathSizeIncrement;
  997.     x = (double *)User::ReAllocL(x, size * sizeof(double));
  998.     y = (double *)User::ReAllocL(y, size * sizeof(double));
  999.     curve = (GBool *)User::ReAllocL(curve, size * sizeof(GBool));
  1000.   }
  1001.   x[n] = x1;
  1002.   y[n] = y1;
  1003.   x[n+1] = x2;
  1004.   y[n+1] = y2;
  1005.   x[n+2] = x3;
  1006.   y[n+2] = y3;
  1007.   curve[n] = curve[n+1] = gTrue;
  1008.   curve[n+2] = gFalse;
  1009.   n += 3;
  1010. }
  1011.  
  1012. void GfxSubpath::close() {
  1013.   if (x[n-1] != x[0] || y[n-1] != y[0]) {
  1014.     lineTo(x[0], y[0]);
  1015.   }
  1016.   closed = gTrue;
  1017. }
  1018.  
  1019. void GfxPath::ConstructL() {
  1020.   justMoved = gFalse;
  1021.   size = 16;
  1022.   n = 0;
  1023.   firstX = firstY = 0;
  1024.   subpaths = (GfxSubpath **)User::AllocL(size * sizeof(GfxSubpath *));
  1025. }
  1026.  
  1027. GfxPath::~GfxPath() {
  1028.   int i;
  1029.  
  1030.   if (subpaths)
  1031.     for (i = 0; i < n; ++i)
  1032.       delete subpaths[i];
  1033.   User::Free(subpaths);
  1034. }
  1035.  
  1036. // Used for copy().
  1037. void GfxPath::ConstructL(GBool justMoved1, double firstX1, double firstY1,
  1038.          GfxSubpath **subpaths1, int n1, int size1) {
  1039.   int i;
  1040.  
  1041.   justMoved = justMoved1;
  1042.   firstX = firstX1;
  1043.   firstY = firstY1;
  1044.   size = size1;
  1045.   n = 0;
  1046.   subpaths = (GfxSubpath **)User::AllocL(size * sizeof(GfxSubpath *));
  1047.   // init with no subpaths for cleanup
  1048.   n = n1;
  1049.   for (i = 0; i < n; ++i)
  1050.     subpaths[i] = 0;
  1051.   for (i = 0; i < n; ++i)
  1052.     subpaths[i] = subpaths1[i]->copyL();
  1053. }
  1054.  
  1055. GfxPath *GfxPath::copyL()
  1056.   GfxPath* self = new(ELeave) GfxPath();
  1057.   CleanupStack::PushL(self);
  1058.   self->ConstructL(justMoved, firstX, firstY, subpaths, n, size); 
  1059.   CleanupStack::Pop(); // self
  1060.   return self;
  1061. }
  1062.  
  1063. void GfxPath::moveTo(double x, double y) {
  1064.   justMoved = gTrue;
  1065.   firstX = x;
  1066.   firstY = y;
  1067. }
  1068.  
  1069. void GfxPath::lineTo(double x, double y) {
  1070.   if (justMoved) {
  1071.     if (n >= size) {
  1072.       size += KPathSizeIncrement;
  1073.       subpaths = (GfxSubpath **) 
  1074.         User::ReAllocL(subpaths, size * sizeof(GfxSubpath *));
  1075.     }
  1076.     // increment after allocation so subpath can be cleaned up
  1077.     subpaths[n] = new(ELeave)  GfxSubpath();
  1078.     ++n;
  1079.     subpaths[n-1]->ConstructL(firstX, firstY);
  1080.     justMoved = gFalse;
  1081.   }
  1082.   subpaths[n-1]->lineTo(x, y);
  1083. }
  1084.  
  1085. void GfxPath::curveTo(double x1, double y1, double x2, double y2,
  1086.          double x3, double y3) {
  1087.   if (justMoved) {
  1088.     if (n >= size) {
  1089.       size += KPathSizeIncrement;
  1090.       subpaths = (GfxSubpath **)
  1091.         User::ReAllocL(subpaths, size * sizeof(GfxSubpath *));
  1092.     }
  1093.     // increment after allocation so subpath can be cleaned up
  1094.     subpaths[n] = new(ELeave)  GfxSubpath();
  1095.     ++n;
  1096.     subpaths[n-1]->ConstructL(firstX, firstY);
  1097.     justMoved = gFalse;
  1098.   }
  1099.   subpaths[n-1]->curveTo(x1, y1, x2, y2, x3, y3);
  1100. }
  1101.  
  1102.  
  1103. //------------------------------------------------------------------------
  1104. // GfxState
  1105. //------------------------------------------------------------------------
  1106.  
  1107. void GfxState::ConstructL(int dpi, double px1a, double py1a, double px2a, double py2a,
  1108.            int rotate, GBool upsideDown) {
  1109.   double k;
  1110.  
  1111.   px1 = px1a;
  1112.   py1 = py1a;
  1113.   px2 = px2a;
  1114.   py2 = py2a;
  1115.   k = (double)dpi / 72.0;
  1116.   if (rotate == 90) {
  1117.     ctm[0] = 0;
  1118.     ctm[1] = upsideDown ? k : -k;
  1119.     ctm[2] = k;
  1120.     ctm[3] = 0;
  1121.     ctm[4] = -k * py1;
  1122.     ctm[5] = k * (upsideDown ? -px1 : px2);
  1123.     pageWidth = (int)(k * (py2 - py1));
  1124.     pageHeight = (int)(k * (px2 - px1));
  1125.   } else if (rotate == 180) {
  1126.     ctm[0] = -k;
  1127.     ctm[1] = 0;
  1128.     ctm[2] = 0;
  1129.     ctm[3] = upsideDown ? k : -k;
  1130.     ctm[4] = k * px2;
  1131.     ctm[5] = k * (upsideDown ? -py1 : py2);
  1132.     pageWidth = (int)(k * (px2 - px1));
  1133.     pageHeight = (int)(k * (py2 - py1));
  1134.   } else if (rotate == 270) {
  1135.     ctm[0] = 0;
  1136.     ctm[1] = upsideDown ? -k : k;
  1137.     ctm[2] = -k;
  1138.     ctm[3] = 0;
  1139.     ctm[4] = k * py2;
  1140.     ctm[5] = k * (upsideDown ? px2 : -px1);
  1141.     pageWidth = (int)(k * (py2 - py1));
  1142.     pageHeight = (int)(k * (px2 - px1));
  1143.   } else {
  1144.     ctm[0] = k;
  1145.     ctm[1] = 0;
  1146.     ctm[2] = 0;
  1147.     ctm[3] = upsideDown ? -k : k;
  1148.     ctm[4] = -k * px1;
  1149.     ctm[5] = k * (upsideDown ? py2 : -py1);
  1150.     pageWidth = (int)(k * (px2 - px1));
  1151.     pageHeight = (int)(k * (py2 - py1));
  1152.   }
  1153.  
  1154.   fillColorSpace = new(ELeave)  GfxColorSpace(colorGray);
  1155.   strokeColorSpace = new(ELeave)  GfxColorSpace(colorGray);
  1156.   fillColor.setGray(0);
  1157.   strokeColor.setGray(0);
  1158.  
  1159.   lineWidth = 1;
  1160.   lineDash = NULL;
  1161.   lineDashLength = 0;
  1162.   lineDashStart = 0;
  1163.   flatness = 0;
  1164.   lineJoin = 0;
  1165.   lineCap = 0;
  1166.   miterLimit = 10;
  1167.  
  1168.   font = NULL;
  1169.   fontSize = 0;
  1170.   textMat[0] = 1; textMat[1] = 0;
  1171.   textMat[2] = 0; textMat[3] = 1;
  1172.   textMat[4] = 0; textMat[5] = 0;
  1173.   charSpace = 0;
  1174.   wordSpace = 0;
  1175.   horizScaling = 1;
  1176.   leading = 0;
  1177.   rise = 0;
  1178.   render = 0;
  1179.  
  1180.   path = new(ELeave)  GfxPath();
  1181.   path->ConstructL();
  1182.   curX = curY = 0;
  1183.   lineX = lineY = 0;
  1184.  
  1185.   saved = NULL;
  1186. }
  1187.  
  1188. GfxState::~GfxState() {
  1189.   delete fillColorSpace;
  1190.   delete strokeColorSpace;
  1191.   User::Free(lineDash);
  1192.   delete path;
  1193.   delete saved;
  1194. }
  1195.  
  1196. // Used for copy();
  1197. void GfxState::ConstructL(GfxState *state) {
  1198.   
  1199.   Mem::Copy(this, state, sizeof(GfxState));
  1200.   // clear pointers first, so cleanup won't delete vars twice
  1201.   fillColorSpace = 0;
  1202.   strokeColorSpace = 0;
  1203.   lineDash = 0;
  1204.   path = 0;
  1205.   saved = NULL;
  1206.   if (state->fillColorSpace)
  1207.     fillColorSpace = state->fillColorSpace->copyL();
  1208.   if (state->strokeColorSpace)
  1209.     strokeColorSpace = state->strokeColorSpace->copyL();
  1210.   if (lineDashLength > 0) {
  1211.     lineDash = (double *)User::AllocL(lineDashLength * sizeof(double));
  1212.     Mem::Copy(lineDash, state->lineDash, lineDashLength * sizeof(double));
  1213.   } 
  1214.   path = state->path->copyL();
  1215. }
  1216.  
  1217. GfxState *GfxState::copyL()
  1218.   GfxState* self = new(ELeave) GfxState();
  1219.   CleanupStack::PushL(self);
  1220.   self->ConstructL(this); 
  1221.   CleanupStack::Pop(); // self
  1222.   return self;
  1223. }
  1224.  
  1225.  
  1226. void GfxState::transform(double x1, double y1, double *x2, double *y2)
  1227.   *x2 = ctm[0] * x1 + ctm[2] * y1 + ctm[4];
  1228.   *y2 = ctm[1] * x1 + ctm[3] * y1 + ctm[5];
  1229. }
  1230.  
  1231. void GfxState::transformDelta(double x1, double y1, double *x2, double *y2)
  1232.   *x2 = ctm[0] * x1 + ctm[2] * y1;
  1233.   *y2 = ctm[1] * x1 + ctm[3] * y1; 
  1234. }
  1235.  
  1236. void GfxState::textTransform(double x1, double y1, double *x2, double *y2)
  1237.   *x2 = textMat[0] * x1 + textMat[2] * y1 + textMat[4];
  1238.   *y2 = textMat[1] * x1 + textMat[3] * y1 + textMat[5]; 
  1239. }
  1240.  
  1241. void GfxState::textTransformDelta(double x1, double y1, double *x2, double *y2)
  1242.   *x2 = textMat[0] * x1 + textMat[2] * y1;
  1243.   *y2 = textMat[1] * x1 + textMat[3] * y1; 
  1244. }
  1245.  
  1246. // special when y1 == 0
  1247. void GfxState::textTransformDelta(double x1, double *x2, double *y2)
  1248. {
  1249.   *x2 = textMat[0] * x1;
  1250.   *y2 = textMat[1] * x1; 
  1251. }
  1252.  
  1253. double GfxState::transformWidth(double w) {
  1254.   double x, y;
  1255.  
  1256.   x = ctm[0] + ctm[2];
  1257.   y = ctm[1] + ctm[3];
  1258.   double res;
  1259.   (void)Math::Sqrt(res, 0.5 * (x * x + y * y));
  1260.   return w * res;
  1261. }
  1262.  
  1263. double GfxState::getTransformedFontSize() {
  1264.   double x1, y1, x2, y2;
  1265.   
  1266.   x1 = textMat[2] * fontSize;
  1267.   y1 = textMat[3] * fontSize;
  1268.   x2 = ctm[0] * x1 + ctm[2] * y1;
  1269.   y2 = ctm[1] * x1 + ctm[3] * y1;
  1270.   double res;
  1271.   (void)Math::Sqrt(res,x2 * x2 + y2 * y2);
  1272.   return res;
  1273. }
  1274.  
  1275. void GfxState::getFontTransMat(double *m11, double *m12,
  1276.                    double *m21, double *m22) {
  1277.   *m11 = (textMat[0] * ctm[0] + textMat[1] * ctm[2]) * fontSize;
  1278.   *m12 = (textMat[0] * ctm[1] + textMat[1] * ctm[3]) * fontSize;
  1279.   *m21 = (textMat[2] * ctm[0] + textMat[3] * ctm[2]) * fontSize;
  1280.   *m22 = (textMat[2] * ctm[1] + textMat[3] * ctm[3]) * fontSize;
  1281. }
  1282.  
  1283. void GfxState::setCTM(double a, double b, double c,
  1284.               double d, double e, double f) {
  1285.   ctm[0] = a;
  1286.   ctm[1] = b;
  1287.   ctm[2] = c;
  1288.   ctm[3] = d;
  1289.   ctm[4] = e;
  1290.   ctm[5] = f;
  1291. }
  1292.  
  1293. void GfxState::concatCTM(double a, double b, double c,
  1294.              double d, double e, double f) {
  1295.   double a1 = ctm[0];
  1296.   double b1 = ctm[1];
  1297.   double c1 = ctm[2];
  1298.   double d1 = ctm[3];
  1299.  
  1300.   ctm[0] = a * a1 + b * c1;
  1301.   ctm[1] = a * b1 + b * d1;
  1302.   ctm[2] = c * a1 + d * c1;
  1303.   ctm[3] = c * b1 + d * d1;
  1304.   ctm[4] = e * a1 + f * c1 + ctm[4];
  1305.   ctm[5] = e * b1 + f * d1 + ctm[5];
  1306. }
  1307.  
  1308. void GfxState::setTextMat(double a, double b, double c,
  1309.           double d, double e, double f)
  1310.   textMat[0] = a; textMat[1] = b; textMat[2] = c;
  1311.   textMat[3] = d; textMat[4] = e; textMat[5] = f; 
  1312. }
  1313.  
  1314. void GfxState::setFillColorSpace(GfxColorSpace *colorSpace) {
  1315.   delete fillColorSpace;
  1316.   fillColorSpace = colorSpace;
  1317. }
  1318.  
  1319. void GfxState::setStrokeColorSpace(GfxColorSpace *colorSpace) {
  1320.   delete strokeColorSpace;
  1321.   strokeColorSpace = colorSpace;
  1322. }
  1323.  
  1324. void GfxState::setLineDash(double *dash, int length, double start) {
  1325.   User::Free(lineDash);
  1326.   lineDash = dash;
  1327.   lineDashLength = length;
  1328.   lineDashStart = start;
  1329. }
  1330.  
  1331. void GfxState::clearPath() {
  1332.   delete path;
  1333.   path = 0;
  1334.   path = new(ELeave)  GfxPath();
  1335.   path->ConstructL();
  1336. }
  1337.  
  1338. void GfxState::textShift(double tx) {
  1339.   double dx, dy;
  1340.  
  1341.   // faster transform with zero height
  1342.   textTransformDelta(tx, 0, &dx, &dy);
  1343.   curX += dx;
  1344.   curY += dy;
  1345. }
  1346.  
  1347. void GfxState::textShift(double tx, double ty) {
  1348.   double dx, dy;
  1349.  
  1350.   textTransformDelta(tx, ty, &dx, &dy);
  1351.   curX += dx;
  1352.   curY += dy;
  1353. }
  1354.  
  1355. GfxState *GfxState::save() {
  1356.   GfxState *newState;
  1357.  
  1358.   newState = copyL();
  1359.   newState->saved = this;
  1360.   return newState;
  1361. }
  1362.  
  1363. GfxState *GfxState::restore() {
  1364.   GfxState *oldState;
  1365.  
  1366.   if (saved) {
  1367.     oldState = saved;
  1368.     saved = NULL;
  1369.     delete this;
  1370.   } else {
  1371.     oldState = this;
  1372.   }
  1373.   return oldState;
  1374. }
  1375.