home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 110 / EnigmaAmiga110CD.iso / indispensabili / utility / apdf / xpdf-0.80 / xpdf / gfxstate.cc < prev    next >
C/C++ Source or Header  |  1999-04-05  |  22KB  |  953 lines

  1. //========================================================================
  2. //
  3. // GfxState.cc
  4. //
  5. // Copyright 1996 Derek B. Noonburg
  6. //
  7. //========================================================================
  8.  
  9. #ifdef __GNUC__
  10. #pragma implementation
  11. #endif
  12.  
  13. #include <stddef.h>
  14. #include <math.h>
  15. #include <string.h> // for memcpy()
  16. #include "gmem.h"
  17. #include "Error.h"
  18. #include "Object.h"
  19. #include "GfxState.h"
  20.  
  21. //------------------------------------------------------------------------
  22. // GfxColor
  23. //------------------------------------------------------------------------
  24.  
  25. void GfxColor::setCMYK(double c, double m, double y, double k) {
  26.   if ((r = 1 - (c + k)) < 0)
  27.     r = 0;
  28.   if ((g = 1 - (m + k)) < 0)
  29.     g = 0;
  30.   if ((b = 1 - (y + k)) < 0)
  31.     b = 0;
  32. }
  33.  
  34. //------------------------------------------------------------------------
  35. // GfxColorSpace
  36. //------------------------------------------------------------------------
  37.  
  38. GfxColorSpace::GfxColorSpace(Object *colorSpace) {
  39.   Object csObj;
  40.   Object obj, obj2;
  41.   char *s;
  42.   int x;
  43.   int i, j;
  44.  
  45.   ok = gTrue;
  46.   lookup = NULL;
  47.  
  48.   // check for Separation colorspace
  49.   colorSpace->copy(&csObj);
  50.   sepFunc = NULL;
  51.   if (colorSpace->isArray()) {
  52.     colorSpace->arrayGet(0, &obj);
  53.     if (obj.isName("Separation")) {
  54.       csObj.free();
  55.       colorSpace->arrayGet(2, &csObj);
  56.       sepFunc = new Function(colorSpace->arrayGet(3, &obj2));
  57.       obj2.free();
  58.       if (!sepFunc->isOk()) {
  59.     delete sepFunc;
  60.     sepFunc = NULL;
  61.       }
  62.     }
  63.     obj.free();
  64.   }
  65.  
  66.   // get mode
  67.   indexed = gFalse;
  68.   if (csObj.isName()) {
  69.     setMode(&csObj);
  70.   } else if (csObj.isArray()) {
  71.     csObj.arrayGet(0, &obj);
  72.     if (obj.isName("Indexed") || obj.isName("I")) {
  73.       indexed = gTrue;
  74.       setMode(csObj.arrayGet(1, &obj2));
  75.       obj2.free();
  76.     } else {
  77.       setMode(&csObj);
  78.     }
  79.     obj.free();
  80.   } else {
  81.     goto err1;
  82.   }
  83.   if (!ok)
  84.     return;
  85.  
  86.   // get lookup table for indexed colorspace
  87.   if (indexed) {
  88.     csObj.arrayGet(2, &obj);
  89.     if (!obj.isInt())
  90.       goto err2;
  91.     indexHigh = obj.getInt();
  92.     obj.free();
  93.     lookup = (Guchar (*)[4])gmalloc((indexHigh + 1) * 4 * sizeof(Guchar));
  94.     csObj.arrayGet(3, &obj);
  95.     if (obj.isStream()) {
  96.       obj.streamReset();
  97.       for (i = 0; i <= indexHigh; ++i) {
  98.     for (j = 0; j < numComps; ++j) {
  99.       if ((x = obj.streamGetChar()) == EOF)
  100.         goto err2;
  101.       lookup[i][j] = (Guchar)x;
  102.     }
  103.       }
  104.     } else if (obj.isString()) {
  105.       s = obj.getString()->getCString();
  106.       for (i = 0; i <= indexHigh; ++i)
  107.     for (j = 0; j < numComps; ++j)
  108.       lookup[i][j] = (Guchar)*s++;
  109.     } else {
  110.       goto err2;
  111.     }
  112.     obj.free();
  113.   }
  114.  
  115.   csObj.free();
  116.   return;
  117.  
  118.  err2:
  119.   obj.free();
  120.  err1:
  121.   csObj.free();
  122.   ok = gFalse;
  123. }
  124.  
  125. GfxColorSpace::GfxColorSpace(GfxColorMode mode1) {
  126.   sepFunc = NULL;
  127.   mode = mode1;
  128.   indexed = gFalse;
  129.   switch (mode) {
  130.   case colorGray: numComps = 1; break;
  131.   case colorCMYK: numComps = 4; break;
  132.   case colorRGB:  numComps = 3; break;
  133.   }
  134.   lookup = NULL;
  135.   ok = gTrue;
  136. }
  137.  
  138. GfxColorSpace::~GfxColorSpace() {
  139.   if (sepFunc)
  140.     delete sepFunc;
  141.   gfree(lookup);
  142. }
  143.  
  144. GfxColorSpace::GfxColorSpace(GfxColorSpace *colorSpace) {
  145.   int size;
  146.  
  147.   if (colorSpace->sepFunc)
  148.     sepFunc = colorSpace->sepFunc->copy();
  149.   else
  150.     sepFunc = NULL;
  151.   mode = colorSpace->mode;
  152.   indexed = colorSpace->indexed;
  153.   numComps = colorSpace->numComps;
  154.   indexHigh = colorSpace->indexHigh;
  155.   if (indexed) {
  156.     size = (indexHigh + 1) * 4 * sizeof(Guchar);
  157.     lookup = (Guchar (*)[4])gmalloc(size);
  158.     memcpy(lookup, colorSpace->lookup, size);
  159.   } else {
  160.     lookup = NULL;
  161.   }
  162.   ok = gTrue;
  163. }
  164.  
  165. void GfxColorSpace::setMode(Object *colorSpace) {
  166.   Object obj;
  167.  
  168.   if (colorSpace->isName("DeviceGray") || colorSpace->isName("G")) {
  169.     mode = colorGray;
  170.     numComps = 1;
  171.   } else if (colorSpace->isName("DeviceRGB") || colorSpace->isName("RGB")) {
  172.     mode = colorRGB;
  173.     numComps = 3;
  174.   } else if (colorSpace->isName("DeviceCMYK") || colorSpace->isName("CMYK")) {
  175.     mode = colorCMYK;
  176.     numComps = 4;
  177.   } else if (colorSpace->isArray()) {
  178.     colorSpace->arrayGet(0, &obj);
  179.     if (obj.isName("CalGray")) {
  180.       mode = colorGray;
  181.       numComps = 1;
  182.     } else if (obj.isName("CalRGB")) {
  183.       mode = colorRGB;
  184.       numComps = 3;
  185.     } else if (obj.isName("CalCMYK")) {
  186.       mode = colorCMYK;
  187.       numComps = 4;
  188.     } else {
  189.       ok = gFalse;
  190.     }
  191.     obj.free();
  192.   } else {
  193.     ok = gFalse;
  194.   }
  195. }
  196.  
  197. void GfxColorSpace::getColor(double x[4], GfxColor *color) {
  198.   double y[4];
  199.   Guchar *p;
  200.  
  201.   if (sepFunc) {
  202.     sepFunc->transform(x, y);
  203.   } else {
  204.     y[0] = x[0];
  205.     y[1] = x[1];
  206.     y[2] = x[2];
  207.     y[3] = x[3];
  208.   }
  209.   if (indexed) {
  210.     p = lookup[(int)(y[0] + 0.5)];
  211.     switch (mode) {
  212.     case colorGray:
  213.       color->setGray(p[0] / 255.0);
  214.       break;
  215.     case colorCMYK:
  216.       color->setCMYK(p[0] / 255.0, p[1] / 255.0, p[2] / 255.0, p[3] / 255.0);
  217.       break;
  218.     case colorRGB:
  219.       color->setRGB(p[0] / 255.0, p[1] / 255.0, p[2] / 255.0);
  220.       break;
  221.     }
  222.   } else {
  223.     switch (mode) {
  224.     case colorGray:
  225.       color->setGray(y[0]);
  226.       break;
  227.     case colorCMYK:
  228.       color->setCMYK(y[0], y[1], y[2], y[3]);
  229.       break;
  230.     case colorRGB:
  231.       color->setRGB(y[0], y[1], y[2]);
  232.       break;
  233.     }
  234.   }
  235. }
  236.  
  237. //------------------------------------------------------------------------
  238. // Function
  239. //------------------------------------------------------------------------
  240.  
  241. Function::Function(Object *funcObj) {
  242.   Stream *str;
  243.   Dict *dict;
  244.   int nSamples, sampleBits;
  245.   double sampleMul;
  246.   Object obj1, obj2;
  247.   Guint buf, bitMask;
  248.   int bits;
  249.   int s;
  250.   int i;
  251.  
  252.   ok = gFalse;
  253.   samples = NULL;
  254.  
  255.   if (!funcObj->isStream()) {
  256.     error(-1, "Expected function dictionary");
  257.     goto err3;
  258.   }
  259.   str = funcObj->getStream();
  260.   dict = str->getDict();
  261.  
  262.   //----- FunctionType
  263.   if (!dict->lookup("FunctionType", &obj1)->isInt() ||
  264.       obj1.getInt() != 0) {
  265.     error(-1, "Unknown function type");
  266.     goto err2;
  267.   }
  268.   obj1.free();
  269.  
  270.   //----- Domain
  271.   if (!dict->lookup("Domain", &obj1)->isArray()) {
  272.     error(-1, "Function is missing domain");
  273.     goto err2;
  274.   }
  275.   m = obj1.arrayGetLength() / 2;
  276.   if (m > 4) {
  277.     error(-1, "Functions with more than 1 input are unsupported");
  278.     goto err2;
  279.   }
  280.   for (i = 0; i < m; ++i) {
  281.     obj1.arrayGet(2*i, &obj2);
  282.     if (!obj2.isNum()) {
  283.       error(-1, "Illegal value in function domain array");
  284.       goto err1;
  285.     }
  286.     domain[i][0] = obj2.getNum();
  287.     obj2.free();
  288.     obj1.arrayGet(2*i+1, &obj2);
  289.     if (!obj2.isNum()) {
  290.       error(-1, "Illegal value in function domain array");
  291.       goto err1;
  292.     }
  293.     domain[i][1] = obj2.getNum();
  294.     obj2.free();
  295.   }
  296.   obj1.free();
  297.  
  298.   //----- Range
  299.   if (!dict->lookup("Range", &obj1)->isArray()) {
  300.     error(-1, "Function is missing range");
  301.     goto err2;
  302.   }
  303.   n = obj1.arrayGetLength() / 2;
  304.   if (n > 4) {
  305.     error(-1, "Functions with more than 4 outputs are unsupported");
  306.     goto err2;
  307.   }
  308.   for (i = 0; i < n; ++i) {
  309.     obj1.arrayGet(2*i, &obj2);
  310.     if (!obj2.isNum()) {
  311.       error(-1, "Illegal value in function range array");
  312.       goto err1;
  313.     }
  314.     range[i][0] = obj2.getNum();
  315.     obj2.free();
  316.     obj1.arrayGet(2*i+1, &obj2);
  317.     if (!obj2.isNum()) {
  318.       error(-1, "Illegal value in function range array");
  319.       goto err1;
  320.     }
  321.     range[i][1] = obj2.getNum();
  322.     obj2.free();
  323.   }
  324.   obj1.free();
  325.  
  326.   //----- Size
  327.   if (!dict->lookup("Size", &obj1)->isArray() ||
  328.       obj1.arrayGetLength() != m) {
  329.     error(-1, "Function has missing or invalid size array");
  330.     goto err2;
  331.   }
  332.   for (i = 0; i < m; ++i) {
  333.     obj1.arrayGet(i, &obj2);
  334.     if (!obj2.isInt()) {
  335.       error(-1, "Illegal value in function size array");
  336.       goto err1;
  337.     }
  338.     sampleSize[i] = obj2.getInt();
  339.     obj2.free();
  340.   }
  341.   obj1.free();
  342.  
  343.   //----- BitsPerSample
  344.   if (!dict->lookup("BitsPerSample", &obj1)->isInt()) {
  345.     error(-1, "Function has missing or invalid BitsPerSample");
  346.     goto err2;
  347.   }
  348.   sampleBits = obj1.getInt();
  349.   sampleMul = 1.0 / (double)((1 << sampleBits) - 1);
  350.   obj1.free();
  351.  
  352.   //----- Encode
  353.   if (dict->lookup("Encode", &obj1)->isArray() &&
  354.       obj1.arrayGetLength() == 2*m) {
  355.     for (i = 0; i < m; ++i) {
  356.       obj1.arrayGet(2*i, &obj2);
  357.       if (!obj2.isNum()) {
  358.     error(-1, "Illegal value in function encode array");
  359.     goto err1;
  360.       }
  361.       encode[i][0] = obj2.getNum();
  362.       obj2.free();
  363.       obj1.arrayGet(2*i+1, &obj2);
  364.       if (!obj2.isNum()) {
  365.     error(-1, "Illegal value in function encode array");
  366.     goto err1;
  367.       }
  368.       encode[i][1] = obj2.getNum();
  369.       obj2.free();
  370.     }
  371.   } else {
  372.     for (i = 0; i < m; ++i) {
  373.       encode[i][0] = 0;
  374.       encode[i][1] = sampleSize[i] - 1;
  375.     }
  376.   }
  377.   obj1.free();
  378.  
  379.   //----- Decode
  380.   if (dict->lookup("Decode", &obj1)->isArray() &&
  381.       obj1.arrayGetLength() == 2*n) {
  382.     for (i = 0; i < n; ++i) {
  383.       obj1.arrayGet(2*i, &obj2);
  384.       if (!obj2.isNum()) {
  385.     error(-1, "Illegal value in function decode array");
  386.     goto err1;
  387.       }
  388.       decode[i][0] = obj2.getNum();
  389.       obj2.free();
  390.       obj1.arrayGet(2*i+1, &obj2);
  391.       if (!obj2.isNum()) {
  392.     error(-1, "Illegal value in function decode array");
  393.     goto err1;
  394.       }
  395.       decode[i][1] = obj2.getNum();
  396.       obj2.free();
  397.     }
  398.   } else {
  399.     for (i = 0; i < n; ++i) {
  400.       decode[i][0] = range[i][0];
  401.       decode[i][1] = range[i][1];
  402.     }
  403.   }
  404.   obj1.free();
  405.  
  406.   //----- samples
  407.   nSamples = n;
  408.   for (i = 0; i < m; ++i)
  409.     nSamples *= sampleSize[i];
  410.   samples = (double *)gmalloc(nSamples * sizeof(double));
  411.   buf = 0;
  412.   bits = 0;
  413.   bitMask = (1 << sampleBits) - 1;
  414.   str->reset();
  415.   for (i = 0; i < nSamples; ++i) {
  416.     if (sampleBits == 8) {
  417.       s = str->getChar();
  418.     } else if (sampleBits == 16) {
  419.       s = str->getChar();
  420.       s = (s << 8) + str->getChar();
  421.     } else if (sampleBits == 32) {
  422.       s = str->getChar();
  423.       s = (s << 8) + str->getChar();
  424.       s = (s << 8) + str->getChar();
  425.       s = (s << 8) + str->getChar();
  426.     } else {
  427.       while (bits < sampleBits) {
  428.     buf = (buf << 8) | (str->getChar() & 0xff);
  429.     bits += 8;
  430.       }
  431.       s = (buf >> (bits - sampleBits)) & bitMask;
  432.       bits -= sampleBits;
  433.     }
  434.     samples[i] = (double)s * sampleMul;
  435.   }
  436.  
  437.   ok = gTrue;
  438.   return;
  439.  
  440.  err1:
  441.   obj2.free();
  442.  err2:
  443.   obj1.free();
  444.  err3:
  445.   return;
  446. }
  447.  
  448. Function::Function(Function *func) {
  449.   int nSamples, i;
  450.  
  451.   m = func->m;
  452.   n = func->n;
  453.   memcpy(domain, func->domain, sizeof(domain));
  454.   memcpy(range, func->range, sizeof(range));
  455.   memcpy(sampleSize, func->sampleSize, sizeof(sampleSize));
  456.   memcpy(encode, func->encode, sizeof(encode));
  457.   memcpy(decode, func->decode, sizeof(decode));
  458.  
  459.   nSamples = n;
  460.   for (i = 0; i < m; ++i)
  461.     nSamples *= sampleSize[i];
  462.   samples = (double *)gmalloc(nSamples * sizeof(double));
  463.   memcpy(samples, func->samples, nSamples * sizeof(double));
  464.  
  465.   ok = gTrue;
  466. }
  467.  
  468. Function::~Function() {
  469.   if (samples)
  470.     gfree(samples);
  471. }
  472.  
  473. void Function::transform(double *in, double *out) {
  474.   double e[4];
  475.   double s;
  476.   double x0, x1;
  477.   int e0, e1;
  478.   double efrac;
  479.   int i;
  480.  
  481.   // map input values into sample array
  482.   for (i = 0; i < m; ++i) {
  483.     e[i] = ((in[i] - domain[i][0]) / (domain[i][1] - domain[i][0])) *
  484.        (encode[i][1] - encode[i][0]) + encode[i][0];
  485.     if (e[i] < 0)
  486.       e[i] = 0;
  487.     else if (e[i] > sampleSize[i] - 1)
  488.       e[i] = sampleSize[i] - 1;
  489.   }
  490.  
  491.   for (i = 0; i < n; ++i) {
  492.  
  493.     // m-linear interpolation
  494.     // (only m=1 is currently supported)
  495.     e0 = (int)floor(e[0]);
  496.     e1 = (int)ceil(e[0]);
  497.     efrac = e[0] - e0;
  498.     x0 = samples[e0 * n + i];
  499.     x1 = samples[e1 * n + i];
  500.     s = (1 - efrac) * x0 + efrac * x1;
  501.  
  502.     // map output values to range
  503.     out[i] = s * (decode[i][1] - decode[i][0]) + decode[i][0];
  504.     if (out[i] < range[i][0])
  505.       out[i] = range[i][0];
  506.     else if (out[i] > range[i][1])
  507.       out[i] = range[i][1];
  508.   }
  509. }
  510.  
  511. //------------------------------------------------------------------------
  512. // GfxImageColorMap
  513. //------------------------------------------------------------------------
  514.  
  515. GfxImageColorMap::GfxImageColorMap(int bits1, Object *decode,
  516.                    GfxColorSpace *colorSpace1) {
  517.   GfxColor color;
  518.   double x[4];
  519.   int maxPixel;
  520.   Object obj;
  521.   int i, j;
  522.  
  523.   ok = gTrue;
  524.  
  525.   // bits per component and colorspace
  526.   bits = bits1;
  527.   maxPixel = (1 << bits) - 1;
  528.   colorSpace = colorSpace1;
  529.   mode = colorSpace->getMode();
  530.  
  531.   // get decode map
  532.   if (decode->isNull()) {
  533.     if (colorSpace->isIndexed()) {
  534.       indexed = gTrue;
  535.       numComps = 1;
  536.       decodeLow[0] = 0;
  537.       decodeRange[0] = maxPixel;
  538.     } else {
  539.       indexed = gFalse;
  540.       numComps = colorSpace->getNumPixelComps();
  541.       for (i = 0; i < numComps; ++i) {
  542.     decodeLow[i] = 0;
  543.     decodeRange[i] = 1;
  544.       }
  545.     }
  546.   } else if (decode->isArray()) {
  547.     numComps = decode->arrayGetLength() / 2;
  548.     if (numComps != colorSpace->getNumPixelComps())
  549.       goto err1;
  550.     indexed = colorSpace->isIndexed();
  551.     for (i = 0; i < numComps; ++i) {
  552.       decode->arrayGet(2*i, &obj);
  553.       if (!obj.isNum())
  554.     goto err2;
  555.       decodeLow[i] = obj.getNum();
  556.       obj.free();
  557.       decode->arrayGet(2*i+1, &obj);
  558.       if (!obj.isNum())
  559.     goto err2;
  560.       decodeRange[i] = obj.getNum() - decodeLow[i];
  561.       obj.free();
  562.     }
  563.   } else {
  564.     goto err1;
  565.   }
  566.  
  567.   // construct lookup table
  568.   lookup = (double (*)[4])gmalloc((maxPixel + 1) * 4 * sizeof(double));
  569.   if (indexed) {
  570.     for (i = 0; i <= maxPixel; ++i) {
  571.       x[0] = (double)i;
  572.       colorSpace->getColor(x, &color);
  573.       lookup[i][0] = color.getR();
  574.       lookup[i][1] = color.getG();
  575.       lookup[i][2] = color.getB();
  576.     }
  577.   } else {
  578.     for (i = 0; i <= maxPixel; ++i)
  579.       for (j = 0; j < numComps; ++j)
  580.     lookup[i][j] = decodeLow[j] + (i * decodeRange[j]) / maxPixel;
  581.   }
  582.  
  583.   return;
  584.  
  585.  err2:
  586.   obj.free();
  587.  err1:
  588.   ok = gFalse;
  589. }
  590.  
  591. GfxImageColorMap::~GfxImageColorMap() {
  592.   delete colorSpace;
  593.   gfree(lookup);
  594. }
  595.  
  596. void GfxImageColorMap::getColor(Guchar x[4], GfxColor *color) {
  597.   double *p;
  598.  
  599.   if (indexed) {
  600.     p = lookup[x[0]];
  601.     color->setRGB(p[0], p[1], p[2]);
  602.   } else {
  603.     switch (mode) {
  604.     case colorGray:
  605.       color->setGray(lookup[x[0]][0]);
  606.       break;
  607.     case colorCMYK:
  608.       color->setCMYK(lookup[x[0]][0], lookup[x[1]][1],
  609.              lookup[x[2]][2], lookup[x[3]][3]);
  610.       break;
  611.     case colorRGB:
  612.       color->setRGB(lookup[x[0]][0], lookup[x[1]][1], lookup[x[2]][2]);
  613.       break;
  614.     }
  615.   }
  616. }
  617.  
  618. //------------------------------------------------------------------------
  619. // GfxSubpath and GfxPath
  620. //------------------------------------------------------------------------
  621.  
  622. GfxSubpath::GfxSubpath(double x1, double y1) {
  623.   size = 16;
  624.   x = (double *)gmalloc(size * sizeof(double));
  625.   y = (double *)gmalloc(size * sizeof(double));
  626.   curve = (GBool *)gmalloc(size * sizeof(GBool));
  627.   n = 1;
  628.   x[0] = x1;
  629.   y[0] = y1;
  630.   curve[0] = gFalse;
  631. }
  632.  
  633. GfxSubpath::~GfxSubpath() {
  634.   gfree(x);
  635.   gfree(y);
  636.   gfree(curve);
  637. }
  638.  
  639. // Used for copy().
  640. GfxSubpath::GfxSubpath(GfxSubpath *subpath) {
  641.   size = subpath->size;
  642.   n = subpath->n;
  643.   x = (double *)gmalloc(size * sizeof(double));
  644.   y = (double *)gmalloc(size * sizeof(double));
  645.   curve = (GBool *)gmalloc(size * sizeof(GBool));
  646.   memcpy(x, subpath->x, n * sizeof(double));
  647.   memcpy(y, subpath->y, n * sizeof(double));
  648.   memcpy(curve, subpath->curve, n * sizeof(GBool));
  649. }
  650.  
  651. void GfxSubpath::lineTo(double x1, double y1) {
  652.   if (n >= size) {
  653.     size += 16;
  654.     x = (double *)grealloc(x, size * sizeof(double));
  655.     y = (double *)grealloc(y, size * sizeof(double));
  656.     curve = (GBool *)grealloc(curve, size * sizeof(GBool));
  657.   }
  658.   x[n] = x1;
  659.   y[n] = y1;
  660.   curve[n] = gFalse;
  661.   ++n;
  662. }
  663.  
  664. void GfxSubpath::curveTo(double x1, double y1, double x2, double y2,
  665.              double x3, double y3) {
  666.   if (n+3 > size) {
  667.     size += 16;
  668.     x = (double *)grealloc(x, size * sizeof(double));
  669.     y = (double *)grealloc(y, size * sizeof(double));
  670.     curve = (GBool *)grealloc(curve, size * sizeof(GBool));
  671.   }
  672.   x[n] = x1;
  673.   y[n] = y1;
  674.   x[n+1] = x2;
  675.   y[n+1] = y2;
  676.   x[n+2] = x3;
  677.   y[n+2] = y3;
  678.   curve[n] = curve[n+1] = gTrue;
  679.   curve[n+2] = gFalse;
  680.   n += 3;
  681. }
  682.  
  683. GfxPath::GfxPath() {
  684.   justMoved = gFalse;
  685.   size = 16;
  686.   n = 0;
  687.   subpaths = (GfxSubpath **)gmalloc(size * sizeof(GfxSubpath *));
  688. }
  689.  
  690. GfxPath::~GfxPath() {
  691.   int i;
  692.  
  693.   for (i = 0; i < n; ++i)
  694.     delete subpaths[i];
  695.   gfree(subpaths);
  696. }
  697.  
  698. // Used for copy().
  699. GfxPath::GfxPath(GBool justMoved1, double firstX1, double firstY1,
  700.          GfxSubpath **subpaths1, int n1, int size1) {
  701.   int i;
  702.  
  703.   justMoved = justMoved1;
  704.   firstX = firstX1;
  705.   firstY = firstY1;
  706.   size = size1;
  707.   n = n1;
  708.   subpaths = (GfxSubpath **)gmalloc(size * sizeof(GfxSubpath *));
  709.   for (i = 0; i < n; ++i)
  710.     subpaths[i] = subpaths1[i]->copy();
  711. }
  712.  
  713. void GfxPath::moveTo(double x, double y) {
  714.   justMoved = gTrue;
  715.   firstX = x;
  716.   firstY = y;
  717. }
  718.  
  719. void GfxPath::lineTo(double x, double y) {
  720.   if (justMoved) {
  721.     if (n >= size) {
  722.       size += 16;
  723.       subpaths = (GfxSubpath **)
  724.            grealloc(subpaths, size * sizeof(GfxSubpath *));
  725.     }
  726.     subpaths[n] = new GfxSubpath(firstX, firstY);
  727.     ++n;
  728.     justMoved = gFalse;
  729.   }
  730.   subpaths[n-1]->lineTo(x, y);
  731. }
  732.  
  733. void GfxPath::curveTo(double x1, double y1, double x2, double y2,
  734.          double x3, double y3) {
  735.   if (justMoved) {
  736.     if (n >= size) {
  737.       size += 16;
  738.       subpaths = (GfxSubpath **)
  739.            grealloc(subpaths, size * sizeof(GfxSubpath *));
  740.     }
  741.     subpaths[n] = new GfxSubpath(firstX, firstY);
  742.     ++n;
  743.     justMoved = gFalse;
  744.   }
  745.   subpaths[n-1]->curveTo(x1, y1, x2, y2, x3, y3);
  746. }
  747.  
  748.  
  749. //------------------------------------------------------------------------
  750. // GfxState
  751. //------------------------------------------------------------------------
  752.  
  753. GfxState::GfxState(int dpi, double px1a, double py1a, double px2a, double py2a,
  754.            int rotate, GBool upsideDown) {
  755.   double k;
  756.  
  757.   px1 = px1a;
  758.   py1 = py1a;
  759.   px2 = px2a;
  760.   py2 = py2a;
  761.   k = (double)dpi / 72.0;
  762.   if (rotate == 90) {
  763.     ctm[0] = 0;
  764.     ctm[1] = upsideDown ? k : -k;
  765.     ctm[2] = k;
  766.     ctm[3] = 0;
  767.     ctm[4] = -k * py1;
  768.     ctm[5] = k * (upsideDown ? -px1 : px2);
  769.     pageWidth = (int)(k * (py2 - py1));
  770.     pageHeight = (int)(k * (px2 - px1));
  771.   } else if (rotate == 180) {
  772.     ctm[0] = -k;
  773.     ctm[1] = 0;
  774.     ctm[2] = 0;
  775.     ctm[3] = upsideDown ? k : -k;
  776.     ctm[4] = k * px2;
  777.     ctm[5] = k * (upsideDown ? -py1 : py2);
  778.     pageWidth = (int)(k * (px2 - px1));
  779.     pageHeight = (int)(k * (py2 - py1));
  780.   } else if (rotate == 270) {
  781.     ctm[0] = 0;
  782.     ctm[1] = upsideDown ? -k : k;
  783.     ctm[2] = -k;
  784.     ctm[3] = 0;
  785.     ctm[4] = k * py2;
  786.     ctm[5] = k * (upsideDown ? px2 : -px1);
  787.     pageWidth = (int)(k * (py2 - py1));
  788.     pageHeight = (int)(k * (px2 - px1));
  789.   } else {
  790.     ctm[0] = k;
  791.     ctm[1] = 0;
  792.     ctm[2] = 0;
  793.     ctm[3] = upsideDown ? -k : k;
  794.     ctm[4] = -k * px1;
  795.     ctm[5] = k * (upsideDown ? py2 : -py1);
  796.     pageWidth = (int)(k * (px2 - px1));
  797.     pageHeight = (int)(k * (py2 - py1));
  798.   }
  799.  
  800.   fillColorSpace = new GfxColorSpace(colorGray);
  801.   strokeColorSpace = new GfxColorSpace(colorGray);
  802.   fillColor.setGray(0);
  803.   strokeColor.setGray(0);
  804.  
  805.   lineWidth = 1;
  806.   lineDash = NULL;
  807.   lineDashLength = 0;
  808.   lineDashStart = 0;
  809.   flatness = 0;
  810.   lineJoin = 0;
  811.   lineCap = 0;
  812.   miterLimit = 10;
  813.  
  814.   font = NULL;
  815.   fontSize = 0;
  816.   textMat[0] = 1; textMat[1] = 0;
  817.   textMat[2] = 0; textMat[3] = 1;
  818.   textMat[4] = 0; textMat[5] = 0;
  819.   charSpace = 0;
  820.   wordSpace = 0;
  821.   horizScaling = 1;
  822.   leading = 0;
  823.   rise = 0;
  824.   render = 0;
  825.  
  826.   path = new GfxPath();
  827.   curX = curY = 0;
  828.   lineX = lineY = 0;
  829.  
  830.   saved = NULL;
  831. }
  832.  
  833. GfxState::~GfxState() {
  834.   if (fillColorSpace)
  835.     delete fillColorSpace;
  836.   if (strokeColorSpace)
  837.     delete strokeColorSpace;
  838.   gfree(lineDash);
  839.   delete path;
  840.   if (saved)
  841.     delete saved;
  842. }
  843.  
  844. // Used for copy();
  845. GfxState::GfxState(GfxState *state) {
  846.   memcpy(this, state, sizeof(GfxState));
  847.   if (fillColorSpace)
  848.     fillColorSpace = state->fillColorSpace->copy();
  849.   if (strokeColorSpace)
  850.     strokeColorSpace = state->strokeColorSpace->copy();
  851.   if (lineDashLength > 0) {
  852.     lineDash = (double *)gmalloc(lineDashLength * sizeof(double));
  853.     memcpy(lineDash, state->lineDash, lineDashLength * sizeof(double));
  854.   }
  855.   path = state->path->copy();
  856.   saved = NULL;
  857. }
  858.  
  859. double GfxState::transformWidth(double w) {
  860.   double x, y;
  861.  
  862.   x = ctm[0] + ctm[2];
  863.   y = ctm[1] + ctm[3];
  864.   return w * sqrt(0.5 * (x * x + y * y));
  865. }
  866.  
  867. double GfxState::getTransformedFontSize() {
  868.   double x1, y1, x2, y2;
  869.  
  870.   x1 = textMat[2] * fontSize;
  871.   y1 = textMat[3] * fontSize;
  872.   x2 = ctm[0] * x1 + ctm[2] * y1;
  873.   y2 = ctm[1] * x1 + ctm[3] * y1;
  874.   return sqrt(x2 * x2 + y2 * y2);
  875. }
  876.  
  877. void GfxState::getFontTransMat(double *m11, double *m12,
  878.                    double *m21, double *m22) {
  879.   *m11 = (textMat[0] * ctm[0] + textMat[1] * ctm[2]) * fontSize;
  880.   *m12 = (textMat[0] * ctm[1] + textMat[1] * ctm[3]) * fontSize;
  881.   *m21 = (textMat[2] * ctm[0] + textMat[3] * ctm[2]) * fontSize;
  882.   *m22 = (textMat[2] * ctm[1] + textMat[3] * ctm[3]) * fontSize;
  883. }
  884.  
  885. void GfxState::concatCTM(double a, double b, double c,
  886.              double d, double e, double f) {
  887.   double a1 = ctm[0];
  888.   double b1 = ctm[1];
  889.   double c1 = ctm[2];
  890.   double d1 = ctm[3];
  891.  
  892.   ctm[0] = a * a1 + b * c1;
  893.   ctm[1] = a * b1 + b * d1;
  894.   ctm[2] = c * a1 + d * c1;
  895.   ctm[3] = c * b1 + d * d1;
  896.   ctm[4] = e * a1 + f * c1 + ctm[4];
  897.   ctm[5] = e * b1 + f * d1 + ctm[5];
  898. }
  899.  
  900. void GfxState::setFillColorSpace(GfxColorSpace *colorSpace) {
  901.   if (fillColorSpace)
  902.     delete fillColorSpace;
  903.   fillColorSpace = colorSpace;
  904. }
  905.  
  906. void GfxState::setStrokeColorSpace(GfxColorSpace *colorSpace) {
  907.   if (strokeColorSpace)
  908.     delete strokeColorSpace;
  909.   strokeColorSpace = colorSpace;
  910. }
  911.  
  912. void GfxState::setLineDash(double *dash, int length, double start) {
  913.   if (lineDash)
  914.     gfree(lineDash);
  915.   lineDash = dash;
  916.   lineDashLength = length;
  917.   lineDashStart = start;
  918. }
  919.  
  920. void GfxState::clearPath() {
  921.   delete path;
  922.   path = new GfxPath();
  923. }
  924.  
  925. void GfxState::textShift(double tx) {
  926.   double dx, dy;
  927.  
  928.   textTransformDelta(tx, 0, &dx, &dy);
  929.   curX += dx;
  930.   curY += dy;
  931. }
  932.  
  933. GfxState *GfxState::save() {
  934.   GfxState *newState;
  935.  
  936.   newState = copy();
  937.   newState->saved = this;
  938.   return newState;
  939. }
  940.  
  941. GfxState *GfxState::restore() {
  942.   GfxState *oldState;
  943.  
  944.   if (saved) {
  945.     oldState = saved;
  946.     saved = NULL;
  947.     delete this;
  948.   } else {
  949.     oldState = this;
  950.   }
  951.   return oldState;
  952. }
  953.