Ignore:
Timestamp:
Dec 30, 2009, 7:13:45 PM (12 years ago)
Author:
rbri
Message:

PDF plugin: Poppler library updated to version 0.12.3

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/poppler/mypoppler/poppler/Gfx.cc

    r271 r277  
    1818// Copyright (C) 2006 Thorkild Stray <thorkild@ifi.uio.no>
    1919// Copyright (C) 2006 Kristian HÞgsberg <krh@redhat.com>
    20 // Copyright (C) 2006-2008 Carlos Garcia Campos <carlosgc@gnome.org>
     20// Copyright (C) 2006-2009 Carlos Garcia Campos <carlosgc@gnome.org>
    2121// Copyright (C) 2006, 2007 Jeff Muizelaar <jeff@infidigm.net>
    2222// Copyright (C) 2007, 2008 Brad Hards <bradh@kde.org>
     
    2727// Copyright (C) 2008 Pino Toscano <pino@kde.org>
    2828// Copyright (C) 2008 Michael Vrable <mvrable@cs.ucsd.edu>
     29// Copyright (C) 2008 Hib Eris <hib@hiberis.nl>
     30// Copyright (C) 2009 M Joonas Pihlaja <jpihlaja@cc.helsinki.fi>
     31// Copyright (C) 2009 Thomas Freitag <Thomas.Freitag@alfa.de>
     32// Copyright (C) 2009 William Bader <williambader@hotmail.com>
     33// Copyright (C) 2009 David Benjamin <davidben@mit.edu>
    2934//
    3035// To see a description of the changes please see the Changelog file that
     
    111116//------------------------------------------------------------------------
    112117
    113 #ifdef WIN32 // this works around a bug in the VC7 compiler
     118#ifdef _MSC_VER // this works around a bug in the VC7 compiler
    114119#  pragma optimize("",off)
    115120#endif
     
    284289};
    285290
    286 #ifdef WIN32 // this works around a bug in the VC7 compiler
     291#ifdef _MSC_VER // this works around a bug in the VC7 compiler
    287292#  pragma optimize("",on)
    288293#endif
    289294
    290295#define numOps (sizeof(opTab) / sizeof(Operator))
     296
     297static inline GBool isSameGfxColor(const GfxColor &colorA, const GfxColor &colorB, Guint nComps, double delta) {
     298  for (Guint k = 0; k < nComps; ++k) {
     299    if (abs(colorA.c[k] - colorB.c[k]) > delta) {
     300      return false;
     301    }
     302  }
     303  return true;
     304}
    291305
    292306//------------------------------------------------------------------------
     
    428442}
    429443
    430 GfxPattern *GfxResources::lookupPattern(char *name) {
     444GfxPattern *GfxResources::lookupPattern(char *name, Gfx *gfx) {
    431445  GfxResources *resPtr;
    432446  GfxPattern *pattern;
     
    436450    if (resPtr->patternDict.isDict()) {
    437451      if (!resPtr->patternDict.dictLookup(name, &obj)->isNull()) {
    438         pattern = GfxPattern::parse(&obj);
     452        pattern = GfxPattern::parse(&obj, gfx);
    439453        obj.free();
    440454        return pattern;
     
    447461}
    448462
    449 GfxShading *GfxResources::lookupShading(char *name) {
     463GfxShading *GfxResources::lookupShading(char *name, Gfx *gfx) {
    450464  GfxResources *resPtr;
    451465  GfxShading *shading;
     
    455469    if (resPtr->shadingDict.isDict()) {
    456470      if (!resPtr->shadingDict.dictLookup(name, &obj)->isNull()) {
    457         shading = GfxShading::parse(&obj);
     471        shading = GfxShading::parse(&obj, gfx);
    458472        obj.free();
    459473        return shading;
     
    489503         PDFRectangle *cropBox, int rotate,
    490504         GBool (*abortCheckCbkA)(void *data),
    491          void *abortCheckCbkDataA) {
     505         void *abortCheckCbkDataA)
     506#ifdef USE_CMS
     507 : iccColorSpaceCache(5)
     508#endif
     509{
    492510  int i;
    493511
     
    497515  printCommands = globalParams->getPrintCommands();
    498516  profileCommands = globalParams->getProfileCommands();
     517  textHaveCSPattern = gFalse;
     518  drawText = gFalse;
     519  maskHaveCSPattern = gFalse;
    499520  mcStack = NULL;
    500521
     
    534555         PDFRectangle *box, PDFRectangle *cropBox,
    535556         GBool (*abortCheckCbkA)(void *data),
    536          void *abortCheckCbkDataA) {
     557         void *abortCheckCbkDataA)
     558 #ifdef USE_CMS
     559 : iccColorSpaceCache(5)
     560#endif
     561{
    537562  int i;
    538563
     
    541566  subPage = gTrue;
    542567  printCommands = globalParams->getPrintCommands();
     568  profileCommands = globalParams->getProfileCommands();
     569  textHaveCSPattern = gFalse;
     570  drawText = gFalse;
     571  maskHaveCSPattern = gFalse;
    543572  mcStack = NULL;
    544573
     
    10391068          isolated = knockout = gFalse;
    10401069          if (!obj4.dictLookup("CS", &obj5)->isNull()) {
    1041             blendingColorSpace = GfxColorSpace::parse(&obj5);
     1070            blendingColorSpace = GfxColorSpace::parse(&obj5, this);
    10421071          }
    10431072          obj5.free();
     
    12291258  GfxColor color;
    12301259
    1231   state->setFillPattern(NULL);
    1232   state->setFillColorSpace(new GfxDeviceGrayColorSpace());
    1233   out->updateFillColorSpace(state);
    1234   color.c[0] = dblToCol(args[0].getNum());
    1235   state->setFillColor(&color);
    1236   out->updateFillColor(state);
     1260  if (textHaveCSPattern) {
     1261    GBool needFill = out->deviceHasTextClip(state);
     1262    out->endTextObject(state);
     1263    if (needFill) {
     1264      doPatternFill(gTrue);
     1265    }
     1266    out->restoreState(state);
     1267    state->setFillPattern(NULL);
     1268    state->setFillColorSpace(new GfxDeviceGrayColorSpace());
     1269    out->updateFillColorSpace(state);
     1270    color.c[0] = dblToCol(args[0].getNum());
     1271    state->setFillColor(&color);
     1272    out->updateFillColor(state);
     1273    out->beginTextObject(state);
     1274    out->updateRender(state);
     1275    out->updateTextMat(state);
     1276    out->updateTextPos(state);
     1277    textHaveCSPattern = gFalse;
     1278  } else {
     1279    state->setFillPattern(NULL);
     1280    state->setFillColorSpace(new GfxDeviceGrayColorSpace());
     1281    out->updateFillColorSpace(state);
     1282    color.c[0] = dblToCol(args[0].getNum());
     1283    state->setFillColor(&color);
     1284    out->updateFillColor(state);
     1285  }
    12371286}
    12381287
     
    12521301  int i;
    12531302
    1254   state->setFillPattern(NULL);
    1255   state->setFillColorSpace(new GfxDeviceCMYKColorSpace());
    1256   out->updateFillColorSpace(state);
    1257   for (i = 0; i < 4; ++i) {
    1258     color.c[i] = dblToCol(args[i].getNum());
    1259   }
    1260   state->setFillColor(&color);
    1261   out->updateFillColor(state);
     1303  if (textHaveCSPattern) {
     1304    colorSpaceText = new GfxDeviceCMYKColorSpace();
     1305    for (i = 0; i < 4; ++i) {
     1306      colorText.c[i] = dblToCol(args[i].getNum());
     1307    }
     1308  } else {
     1309    state->setFillPattern(NULL);
     1310    state->setFillColorSpace(new GfxDeviceCMYKColorSpace());
     1311    out->updateFillColorSpace(state);
     1312    for (i = 0; i < 4; ++i) {
     1313      color.c[i] = dblToCol(args[i].getNum());
     1314    }
     1315    state->setFillColor(&color);
     1316    out->updateFillColor(state);
     1317  }
    12621318}
    12631319
     
    12801336  int i;
    12811337
    1282   state->setFillPattern(NULL);
    1283   state->setFillColorSpace(new GfxDeviceRGBColorSpace());
    1284   out->updateFillColorSpace(state);
    1285   for (i = 0; i < 3; ++i) {
    1286     color.c[i] = dblToCol(args[i].getNum());
    1287   }
    1288   state->setFillColor(&color);
    1289   out->updateFillColor(state);
     1338  if (textHaveCSPattern) {
     1339    colorSpaceText = new GfxDeviceRGBColorSpace();
     1340    for (i = 0; i < 3; ++i) {
     1341      colorText.c[i] = dblToCol(args[i].getNum());
     1342    }
     1343  } else {
     1344    state->setFillPattern(NULL);
     1345    state->setFillColorSpace(new GfxDeviceRGBColorSpace());
     1346    out->updateFillColorSpace(state);
     1347    for (i = 0; i < 3; ++i) {
     1348      color.c[i] = dblToCol(args[i].getNum());
     1349    }
     1350    state->setFillColor(&color);
     1351    out->updateFillColor(state);
     1352  }
    12901353}
    12911354
     
    13121375  res->lookupColorSpace(args[0].getName(), &obj);
    13131376  if (obj.isNull()) {
    1314     colorSpace = GfxColorSpace::parse(&args[0]);
     1377    colorSpace = GfxColorSpace::parse(&args[0], this);
    13151378  } else {
    1316     colorSpace = GfxColorSpace::parse(&obj);
     1379    colorSpace = GfxColorSpace::parse(&obj, this);
    13171380  }
    13181381  obj.free();
     
    13231386    state->setFillColor(&color);
    13241387    out->updateFillColor(state);
     1388    if (drawText) {
     1389      if (colorSpace->getMode() == csPattern) {
     1390        colorSpaceText = NULL;
     1391        textHaveCSPattern = gTrue;
     1392        out->beginTextObject(state);
     1393      } else if (textHaveCSPattern) {
     1394        GBool needFill = out->deviceHasTextClip(state);
     1395        out->endTextObject(state);
     1396        if (needFill) {
     1397          doPatternFill(gTrue);
     1398        }
     1399        out->beginTextObject(state);
     1400        out->updateRender(state);
     1401        out->updateTextMat(state);
     1402        out->updateTextPos(state);
     1403        textHaveCSPattern = gFalse;
     1404      }
     1405    }
    13251406  } else {
    13261407    error(getPos(), "Bad color space (fill)");
     
    13361417  res->lookupColorSpace(args[0].getName(), &obj);
    13371418  if (obj.isNull()) {
    1338     colorSpace = GfxColorSpace::parse(&args[0]);
     1419    colorSpace = GfxColorSpace::parse(&args[0], this);
    13391420  } else {
    1340     colorSpace = GfxColorSpace::parse(&obj);
     1421    colorSpace = GfxColorSpace::parse(&obj, this);
    13411422  }
    13421423  obj.free();
     
    14061487    }
    14071488    if (args[numArgs-1].isName() &&
    1408         (pattern = res->lookupPattern(args[numArgs-1].getName()))) {
     1489        (pattern = res->lookupPattern(args[numArgs-1].getName(), this))) {
    14091490      state->setFillPattern(pattern);
    14101491    }
     
    14491530    }
    14501531    if (args[numArgs-1].isName() &&
    1451         (pattern = res->lookupPattern(args[numArgs-1].getName()))) {
     1532        (pattern = res->lookupPattern(args[numArgs-1].getName(), this))) {
    14521533      state->setStrokePattern(pattern);
    14531534    }
     
    17641845  GfxPatternColorSpace *patCS;
    17651846  GfxColorSpace *cs;
     1847  GfxColor color;
    17661848  GfxPath *savedPath;
    17671849  double xMin, yMin, xMax, yMax, x, y, x1, y1;
     
    18261908    state->setStrokeColorSpace(cs->copy());
    18271909    out->updateStrokeColorSpace(state);
    1828     state->setStrokeColor(state->getFillColor());
     1910    if (stroke) {
     1911        state->setFillColor(state->getStrokeColor());
     1912    } else {
     1913        state->setStrokeColor(state->getFillColor());
     1914    }
    18291915  } else {
    1830     state->setFillColorSpace(new GfxDeviceGrayColorSpace());
     1916    cs = new GfxDeviceGrayColorSpace();
     1917    state->setFillColorSpace(cs);
     1918    cs->getDefaultColor(&color);
     1919    state->setFillColor(&color);
    18311920    out->updateFillColorSpace(state);
    18321921    state->setStrokeColorSpace(new GfxDeviceGrayColorSpace());
     1922    state->setStrokeColor(&color);
    18331923    out->updateStrokeColorSpace(state);
    18341924  }
     
    18371927  state->setStrokePattern(NULL);
    18381928  out->updateStrokeColor(state);
    1839   if (!stroke) {
    1840     state->setLineWidth(0);
    1841     out->updateLineWidth(state);
    1842   }
    18431929
    18441930  // clip to current path
     
    18461932    state->clipToStrokePath();
    18471933    out->clipToStrokePath(state);
    1848   } else {
     1934  } else if (!textHaveCSPattern && !maskHaveCSPattern) {
    18491935    state->clip();
    18501936    if (eoFill) {
     
    18551941  }
    18561942  state->clearPath();
     1943  state->setLineWidth(0);
     1944  out->updateLineWidth(state);
    18571945
    18581946  // get the clip region, check for empty
    18591947  state->getClipBBox(&cxMin, &cyMin, &cxMax, &cyMax);
    18601948  if (cxMin > cxMax || cyMin > cyMax) {
    1861     goto err;
     1949    goto restore;
    18621950  }
    18631951
     
    19142002    m1[i] = m[i];
    19152003  }
    1916   if (out->useTilingPatternFill()) {
     2004  if (!contentIsHidden()) {
    19172005    m1[4] = m[4];
    19182006    m1[5] = m[5];
    1919     if (!contentIsHidden()) {
    1920       out->tilingPatternFill(state, tPat->getContentStream(),
    1921                              tPat->getPaintType(), tPat->getResDict(),
    1922                              m1, tPat->getBBox(),
    1923                              xi0, yi0, xi1, yi1, xstep, ystep);
    1924     }
    1925   } else {
    1926     for (yi = yi0; yi < yi1; ++yi) {
    1927       for (xi = xi0; xi < xi1; ++xi) {
    1928         x = xi * xstep;
    1929         y = yi * ystep;
    1930         m1[4] = x * m[0] + y * m[2] + m[4];
    1931         m1[5] = x * m[1] + y * m[3] + m[5];
    1932         doForm1(tPat->getContentStream(), tPat->getResDict(),
    1933                 m1, tPat->getBBox());
     2007    if (out->useTilingPatternFill() &&
     2008        out->tilingPatternFill(state, tPat->getContentStream(),
     2009                               tPat->getPaintType(), tPat->getResDict(),
     2010                               m1, tPat->getBBox(),
     2011                               xi0, yi0, xi1, yi1, xstep, ystep)) {
     2012            goto restore;
     2013    } else {
     2014      for (yi = yi0; yi < yi1; ++yi) {
     2015        for (xi = xi0; xi < xi1; ++xi) {
     2016          x = xi * xstep;
     2017          y = yi * ystep;
     2018          m1[4] = x * m[0] + y * m[2] + m[4];
     2019          m1[5] = x * m[1] + y * m[3] + m[5];
     2020          doForm1(tPat->getContentStream(), tPat->getResDict(),
     2021                  m1, tPat->getBBox());
     2022        }
    19342023      }
    19352024    }
     
    19372026
    19382027  // restore graphics state
    1939  err:
     2028 restore:
    19402029  restoreState();
    19412030  state->setPath(savedPath);
     
    19742063    state->clipToStrokePath();
    19752064    out->clipToStrokePath(state);
    1976   } else {
     2065  } else if (!textHaveCSPattern && !maskHaveCSPattern) {
    19772066    state->clip();
    19782067    if (eoFill) {
     
    20712160  double xMin, yMin, xMax, yMax;
    20722161
    2073   if (!(shading = res->lookupShading(args[0].getName()))) {
     2162  if (!(shading = res->lookupShading(args[0].getName(), this))) {
    20742163    return;
    20752164  }
     
    22632352}
    22642353
     2354static void bubbleSort(double array[])
     2355{
     2356  for (int j = 0; j < 3; ++j) {
     2357    int kk = j;
     2358    for (int k = j + 1; k < 4; ++k) {
     2359      if (array[k] < array[kk]) {
     2360        kk = k;
     2361      }
     2362    }
     2363    double tmp = array[j];
     2364    array[j] = array[kk];
     2365    array[kk] = tmp;
     2366  }
     2367}
     2368
    22652369void Gfx::doAxialShFill(GfxAxialShading *shading) {
    22662370  double xMin, yMin, xMax, yMax;
     
    22682372  double dx, dy, mul;
    22692373  GBool dxZero, dyZero;
    2270   double tMin, tMax, t, tx, ty;
     2374  double bboxIntersections[4];
     2375  double tMin, tMax, tx, ty;
    22712376  double s[4], sMin, sMax, tmp;
    22722377  double ux0, uy0, ux1, uy1, vx0, vy0, vx1, vy1;
     
    22762381  GfxColor color0, color1;
    22772382  int nComps;
    2278   int i, j, k, kk;
    2279 
    2280   if (out->useShadedFills() &&
    2281       out->axialShadedFill(state, shading)) {
    2282     return;
    2283   }
     2383  int i, j, k;
     2384  GBool needExtend = gTrue;
    22842385
    22852386  // get the clip region bbox
     
    22972398  } else {
    22982399    mul = 1 / (dx * dx + dy * dy);
    2299     tMin = tMax = ((xMin - x0) * dx + (yMin - y0) * dy) * mul;
    2300     t = ((xMin - x0) * dx + (yMax - y0) * dy) * mul;
    2301     if (t < tMin) {
    2302       tMin = t;
    2303     } else if (t > tMax) {
    2304       tMax = t;
    2305     }
    2306     t = ((xMax - x0) * dx + (yMin - y0) * dy) * mul;
    2307     if (t < tMin) {
    2308       tMin = t;
    2309     } else if (t > tMax) {
    2310       tMax = t;
    2311     }
    2312     t = ((xMax - x0) * dx + (yMax - y0) * dy) * mul;
    2313     if (t < tMin) {
    2314       tMin = t;
    2315     } else if (t > tMax) {
    2316       tMax = t;
    2317     }
     2400    bboxIntersections[0] = ((xMin - x0) * dx + (yMin - y0) * dy) * mul;
     2401    bboxIntersections[1] = ((xMin - x0) * dx + (yMax - y0) * dy) * mul;
     2402    bboxIntersections[2] = ((xMax - x0) * dx + (yMin - y0) * dy) * mul;
     2403    bboxIntersections[3] = ((xMax - x0) * dx + (yMax - y0) * dy) * mul;
     2404    bubbleSort(bboxIntersections);
     2405    tMin = bboxIntersections[0];
     2406    tMax = bboxIntersections[3];
    23182407    if (tMin < 0 && !shading->getExtend0()) {
    23192408      tMin = 0;
     
    23222411      tMax = 1;
    23232412    }
     2413  }
     2414
     2415  if (out->useShadedFills() &&
     2416      out->axialShadedFill(state, shading, tMin, tMax)) {
     2417          return;
    23242418  }
    23252419
     
    23762470  shading->getColor(tt, &color0);
    23772471
     2472  if (out->useFillColorStop()) {
     2473    // make sure we add stop color when t = tMin
     2474    state->setFillColor(&color0);
     2475    out->updateFillColorStop(state, (tt - tMin)/(tMax - tMin));
     2476  }
     2477
    23782478  // compute the coordinates of the point on the t axis at t = tMin;
    23792479  // then compute the intersection of the perpendicular line with the
     
    23962496    s[2] = (xMin - tx) / -dy;
    23972497    s[3] = (xMax - tx) / -dy;
    2398     for (j = 0; j < 3; ++j) {
    2399       kk = j;
    2400       for (k = j + 1; k < 4; ++k) {
    2401         if (s[k] < s[kk]) {
    2402           kk = k;
    2403         }
    2404       }
    2405       tmp = s[j]; s[j] = s[kk]; s[kk] = tmp;
    2406     }
     2498    bubbleSort(s);
    24072499    sMin = s[1];
    24082500    sMax = s[2];
     
    24142506
    24152507  i = 0;
     2508  bool doneBBox1, doneBBox2;
     2509  if (dxZero && dyZero) {
     2510    doneBBox1 = doneBBox2 = true;
     2511  } else {
     2512    doneBBox1 = bboxIntersections[1] < tMin;
     2513    doneBBox2 = bboxIntersections[2] > tMax;
     2514  }
     2515
     2516  // If output device doesn't support the extended mode required
     2517  // we have to do it here
     2518  needExtend = !out->axialShadedSupportExtend(state, shading);
     2519
    24162520  while (i < axialMaxSplits) {
    24172521
     
    24282532      }
    24292533      shading->getColor(tt, &color1);
    2430       for (k = 0; k < nComps; ++k) {
    2431         if (abs(color1.c[k] - color0.c[k]) > axialColorDelta) {
    2432           break;
    2433         }
    2434       }
    2435       if (k == nComps) {
    2436         break;
     2534      if (isSameGfxColor(color1, color0, nComps, axialColorDelta)) {
     2535         // in these two if what we guarantee is that if we are skipping lots of
     2536         // positions because the colors are the same, we still create a region
     2537         // with vertexs passing by bboxIntersections[1] and bboxIntersections[2]
     2538         // otherwise we can have empty regions that should really be painted
     2539         // like happened in bug 19896
     2540         // What we do to ensure that we pass a line through this points
     2541         // is making sure use the exact bboxIntersections[] value as one of the used ta[] values
     2542         if (!doneBBox1 && ta[i] < bboxIntersections[1] && ta[j] > bboxIntersections[1]) {
     2543           int teoricalj = (int) ((bboxIntersections[1] - tMin) * axialMaxSplits / (tMax - tMin));
     2544           if (teoricalj <= i) teoricalj = i + 1;
     2545           if (teoricalj < j) {
     2546             next[i] = teoricalj;
     2547             next[teoricalj] = j;
     2548           }
     2549           else {
     2550             teoricalj = j;
     2551           }
     2552           ta[teoricalj] = bboxIntersections[1];
     2553           j = teoricalj;
     2554           doneBBox1 = true;
     2555         }
     2556         if (!doneBBox2 && ta[i] < bboxIntersections[2] && ta[j] > bboxIntersections[2]) {
     2557           int teoricalj = (int) ((bboxIntersections[2] - tMin) * axialMaxSplits / (tMax - tMin));
     2558           if (teoricalj <= i) teoricalj = i + 1;
     2559           if (teoricalj < j) {
     2560             next[i] = teoricalj;
     2561             next[teoricalj] = j;
     2562           }
     2563           else {
     2564             teoricalj = j;
     2565           }
     2566           ta[teoricalj] = bboxIntersections[2];
     2567           j = teoricalj;
     2568           doneBBox2 = true;
     2569         }
     2570         break;
    24372571      }
    24382572      k = (i + j) / 2;
     
    24682602      s[2] = (xMin - tx) / -dy;
    24692603      s[3] = (xMax - tx) / -dy;
    2470       for (j = 0; j < 3; ++j) {
    2471         kk = j;
    2472         for (k = j + 1; k < 4; ++k) {
    2473           if (s[k] < s[kk]) {
    2474             kk = k;
    2475           }
    2476         }
    2477         tmp = s[j]; s[j] = s[kk]; s[kk] = tmp;
    2478       }
     2604      bubbleSort(s);
    24792605      sMin = s[1];
    24802606      sMax = s[2];
     
    24872613    // set the color
    24882614    state->setFillColor(&color0);
    2489     out->updateFillColor(state);
    2490 
    2491     // fill the region
    2492     state->moveTo(ux0, uy0);
    2493     state->lineTo(vx0, vy0);
    2494     state->lineTo(vx1, vy1);
    2495     state->lineTo(ux1, uy1);
    2496     state->closePath();
    2497     if (!contentIsHidden())
    2498       out->fill(state);
    2499     state->clearPath();
     2615    if (out->useFillColorStop())
     2616      out->updateFillColorStop(state, (ta[j] - tMin)/(tMax - tMin));
     2617    else
     2618      out->updateFillColor(state);
     2619
     2620    if (needExtend) {
     2621      // fill the region
     2622      state->moveTo(ux0, uy0);
     2623      state->lineTo(vx0, vy0);
     2624      state->lineTo(vx1, vy1);
     2625      state->lineTo(ux1, uy1);
     2626      state->closePath();
     2627    }
     2628
     2629    if (!out->useFillColorStop()) {
     2630      if (!contentIsHidden())
     2631        out->fill(state);
     2632      state->clearPath();
     2633    }
    25002634
    25012635    // set up for next region
     
    25062640    color0 = color1;
    25072641    i = next[i];
     2642  }
     2643
     2644  if (out->useFillColorStop()) {
     2645    if (!needExtend) {
     2646      state->moveTo(xMin, yMin);
     2647      state->lineTo(xMin, yMax);
     2648      state->lineTo(xMax, yMax);
     2649      state->lineTo(xMax, yMin);
     2650      state->closePath();
     2651    }
     2652    if (!contentIsHidden())
     2653      out->fill(state);
     2654    state->clearPath();
    25082655  }
    25092656}
     
    25212668  double *ctm;
    25222669  double theta, alpha, angle, t;
    2523 
    2524   if (out->useShadedFills() &&
    2525       out->radialShadedFill(state, shading)) {
    2526     return;
    2527   }
     2670  GBool needExtend = gTrue;
    25282671
    25292672  // get the shading info
     
    26222765  }
    26232766
     2767  if (out->useShadedFills() &&
     2768      out->radialShadedFill(state, shading, sMin, sMax)) {
     2769    return;
     2770  }
     2771
    26242772  // compute the number of steps into which circles must be divided to
    26252773  // achieve a curve flatness of 0.1 pixel in device space for the
     
    26672815    shading->getColor(ta, &colorA);
    26682816  }
     2817
     2818  needExtend = !out->radialShadedSupportExtend(state, shading);
    26692819
    26702820  // fill the circles
     
    26882838    }
    26892839    while (ib - ia > 1) {
    2690       for (k = 0; k < nComps; ++k) {
    2691         if (abs(colorB.c[k] - colorA.c[k]) > radialColorDelta) {
     2840      if (isSameGfxColor(colorB, colorA, nComps, radialColorDelta) && ib < radialMaxSplits) {
     2841        // The shading is not necessarily lineal so having two points with the
     2842        // same color does not mean all the areas in between have the same color too
     2843        // Do another bisection to be a bit more sure we are not doing something wrong
     2844        GfxColor colorC;
     2845        int ic = (ia + ib) / 2;
     2846        double sc = sMin + ((double)ic / (double)radialMaxSplits) * (sMax - sMin);
     2847        double tc = t0 + sc * (t1 - t0);
     2848        if (tc < t0) {
     2849          shading->getColor(t0, &colorC);
     2850        } else if (tc > t1) {
     2851          shading->getColor(t1, &colorC);
     2852        } else {
     2853          shading->getColor(tc, &colorC);
     2854        }
     2855        if (isSameGfxColor(colorC, colorA, nComps, radialColorDelta))
    26922856          break;
    2693         }
    2694       }
    2695       if (k == nComps && ib < radialMaxSplits) {
    2696         break;
    26972857      }
    26982858      ib = (ia + ib) / 2;
     
    27182878    }
    27192879    state->setFillColor(&colorA);
    2720     out->updateFillColor(state);
    2721 
    2722     if (enclosed) {
    2723 
    2724       // construct path for first circle (counterclockwise)
    2725       state->moveTo(xa + ra, ya);
    2726       for (k = 1; k < n; ++k) {
    2727         angle = ((double)k / (double)n) * 2 * M_PI;
    2728         state->lineTo(xa + ra * cos(angle), ya + ra * sin(angle));
    2729       }
    2730       state->closePath();
    2731 
    2732       // construct and append path for second circle (clockwise)
    2733       state->moveTo(xb + rb, yb);
    2734       for (k = 1; k < n; ++k) {
    2735         angle = -((double)k / (double)n) * 2 * M_PI;
    2736         state->lineTo(xb + rb * cos(angle), yb + rb * sin(angle));
    2737       }
    2738       state->closePath();
    2739 
    2740     } else {
    2741 
    2742       // construct the first subpath (clockwise)
    2743       state->moveTo(xa + ra * cos(alpha + theta + 0.5 * M_PI),
    2744                     ya + ra * sin(alpha + theta + 0.5 * M_PI));
    2745       for (k = 0; k < n; ++k) {
    2746         angle = alpha + theta + 0.5 * M_PI
    2747           - ((double)k / (double)n) * (2 * theta + M_PI);
    2748         state->lineTo(xb + rb * cos(angle), yb + rb * sin(angle));
    2749       }
    2750       for (k = 0; k < n; ++k) {
    2751         angle = alpha - theta - 0.5 * M_PI
    2752           + ((double)k / (double)n) * (2 * theta - M_PI);
    2753         state->lineTo(xa + ra * cos(angle), ya + ra * sin(angle));
    2754       }
    2755       state->closePath();
    2756 
    2757       // construct the second subpath (counterclockwise)
    2758       state->moveTo(xa + ra * cos(alpha + theta + 0.5 * M_PI),
    2759                     ya + ra * sin(alpha + theta + 0.5 * M_PI));
    2760       for (k = 0; k < n; ++k) {
    2761         angle = alpha + theta + 0.5 * M_PI
    2762                 + ((double)k / (double)n) * (-2 * theta + M_PI);
    2763         state->lineTo(xb + rb * cos(angle), yb + rb * sin(angle));
    2764       }
    2765       for (k = 0; k < n; ++k) {
    2766         angle = alpha - theta - 0.5 * M_PI
    2767                 + ((double)k / (double)n) * (2 * theta + M_PI);
    2768         state->lineTo(xa + ra * cos(angle), ya + ra * sin(angle));
    2769       }
    2770       state->closePath();
    2771     }
    2772 
    2773     // fill the path
    2774     if (!contentIsHidden())
    2775       out->fill(state);
    2776     state->clearPath();
     2880    if (out->useFillColorStop())
     2881      out->updateFillColorStop(state, (sa - sMin)/(sMax - sMin));
     2882    else
     2883      out->updateFillColor(state);
     2884
     2885    if (needExtend) {
     2886      if (enclosed) {
     2887        // construct path for first circle (counterclockwise)
     2888        state->moveTo(xa + ra, ya);
     2889        for (k = 1; k < n; ++k) {
     2890          angle = ((double)k / (double)n) * 2 * M_PI;
     2891          state->lineTo(xa + ra * cos(angle), ya + ra * sin(angle));
     2892        }
     2893        state->closePath();
     2894
     2895        // construct and append path for second circle (clockwise)
     2896        state->moveTo(xb + rb, yb);
     2897        for (k = 1; k < n; ++k) {
     2898          angle = -((double)k / (double)n) * 2 * M_PI;
     2899          state->lineTo(xb + rb * cos(angle), yb + rb * sin(angle));
     2900        }
     2901        state->closePath();
     2902      } else {
     2903        // construct the first subpath (clockwise)
     2904        state->moveTo(xa + ra * cos(alpha + theta + 0.5 * M_PI),
     2905                      ya + ra * sin(alpha + theta + 0.5 * M_PI));
     2906        for (k = 0; k < n; ++k) {
     2907          angle = alpha + theta + 0.5 * M_PI
     2908                  - ((double)k / (double)n) * (2 * theta + M_PI);
     2909          state->lineTo(xb + rb * cos(angle), yb + rb * sin(angle));
     2910        }
     2911        for (k = 0; k < n; ++k) {
     2912          angle = alpha - theta - 0.5 * M_PI
     2913                  + ((double)k / (double)n) * (2 * theta - M_PI);
     2914          state->lineTo(xa + ra * cos(angle), ya + ra * sin(angle));
     2915        }
     2916        state->closePath();
     2917
     2918        // construct the second subpath (counterclockwise)
     2919        state->moveTo(xa + ra * cos(alpha + theta + 0.5 * M_PI),
     2920                      ya + ra * sin(alpha + theta + 0.5 * M_PI));
     2921        for (k = 0; k < n; ++k) {
     2922          angle = alpha + theta + 0.5 * M_PI
     2923                  + ((double)k / (double)n) * (-2 * theta + M_PI);
     2924          state->lineTo(xb + rb * cos(angle), yb + rb * sin(angle));
     2925        }
     2926        for (k = 0; k < n; ++k) {
     2927          angle = alpha - theta - 0.5 * M_PI
     2928                  + ((double)k / (double)n) * (2 * theta + M_PI);
     2929          state->lineTo(xa + ra * cos(angle), ya + ra * sin(angle));
     2930        }
     2931        state->closePath();
     2932      }
     2933    }
     2934
     2935    if (!out->useFillColorStop()) {
     2936      // fill the path
     2937      if (!contentIsHidden())
     2938        out->fill(state);
     2939      state->clearPath();
     2940    }
    27772941
    27782942    // step to the next value of t
     
    27852949    colorA = colorB;
    27862950  }
     2951
     2952  if (out->useFillColorStop()) {
     2953    // make sure we add stop color when sb = sMax
     2954    state->setFillColor(&colorA);
     2955    out->updateFillColorStop(state, (sb - sMin)/(sMax - sMin));
     2956
     2957    // fill the path
     2958    state->moveTo(xMin, yMin);
     2959    state->lineTo(xMin, yMax);
     2960    state->lineTo(xMax, yMax);
     2961    state->lineTo(xMax, yMin);
     2962    state->closePath();
     2963
     2964    if (!contentIsHidden())
     2965      out->fill(state);
     2966    state->clearPath();
     2967  }
     2968
     2969  if (!needExtend)
     2970    return;
    27872971
    27882972  if (enclosed) {
     
    30903274
    30913275void Gfx::opBeginText(Object args[], int numArgs) {
     3276  out->beginTextObject(state);
     3277  drawText = gTrue;
    30923278  state->setTextMat(1, 0, 0, 1, 0, 0);
    30933279  state->textMoveTo(0, 0);
     
    30953281  out->updateTextPos(state);
    30963282  fontChanged = gTrue;
     3283  if (out->supportTextCSPattern(state)) {
     3284    colorSpaceText = NULL;
     3285    textHaveCSPattern = gTrue;
     3286  }
    30973287}
    30983288
    30993289void Gfx::opEndText(Object args[], int numArgs) {
     3290  GBool needFill = out->deviceHasTextClip(state);
    31003291  out->endTextObject(state);
     3292  drawText = gFalse;
     3293  if (out->supportTextCSPattern(state) && textHaveCSPattern) {
     3294    if (needFill) {
     3295      doPatternFill(gTrue);
     3296    }
     3297    out->restoreState(state);
     3298    if (colorSpaceText != NULL) {
     3299      state->setFillPattern(NULL);
     3300      state->setFillColorSpace(colorSpaceText);
     3301      out->updateFillColorSpace(state);
     3302      state->setFillColor(&colorText);
     3303      out->updateFillColor(state);
     3304      colorSpaceText = NULL;
     3305    }
     3306  }
     3307  textHaveCSPattern = gFalse;
    31013308}
    31023309
     
    31393346void Gfx::opSetTextRender(Object args[], int numArgs) {
    31403347  state->setRender(args[0].getInt());
     3348  if (args[0].getInt() == 7) {
     3349    textHaveCSPattern = gFalse;
     3350  }
    31413351  out->updateRender(state);
    31423352}
     
    35583768  int width, height;
    35593769  int bits, maskBits;
     3770  GBool interpolate;
    35603771  StreamColorSpaceMode csMode;
    35613772  GBool mask;
     
    35683779  int maskWidth, maskHeight;
    35693780  GBool maskInvert;
     3781  GBool maskInterpolate;
    35703782  Stream *maskStr;
    35713783  Object obj1, obj2;
     
    36093821    goto err1;
    36103822
     3823  // image interpolation
     3824  dict->lookup("Interpolate", &obj1);
     3825  if (obj1.isNull()) {
     3826    obj1.free();
     3827    dict->lookup("I", &obj1);
     3828  }
     3829  if (obj1.isBool())
     3830    interpolate = obj1.getBool();
     3831  else
     3832    interpolate = gFalse;
     3833  obj1.free();
     3834  maskInterpolate = gFalse;
     3835
    36113836  // image or mask?
    36123837  dict->lookup("ImageMask", &obj1);
     
    36533878    if (obj1.isArray()) {
    36543879      obj1.arrayGet(0, &obj2);
    3655       if (obj2.isInt() && obj2.getInt() == 1)
     3880      // Table 4.39 says /Decode must be [1 0] or [0 1]. Adobe
     3881      // accepts [1.0 0.0] as well.
     3882      if (obj2.isNum() && obj2.getNum() >= 0.9)
    36563883        invert = gTrue;
    36573884      obj2.free();
     
    36623889
    36633890    // draw it
    3664     if (!contentIsHidden())
    3665       out->drawImageMask(state, ref, str, width, height, invert, inlineImg);
    3666 
     3891    if (!contentIsHidden()) {
     3892        out->drawImageMask(state, ref, str, width, height, invert, interpolate, inlineImg);
     3893      if (out->fillMaskCSPattern(state)) {
     3894        maskHaveCSPattern = gTrue;
     3895        doPatternFill(gTrue);
     3896        out->endMaskClip(state);
     3897        maskHaveCSPattern = gFalse;
     3898      }
     3899    }
    36673900  } else {
    36683901
     
    36833916    }
    36843917    if (!obj1.isNull()) {
    3685       colorSpace = GfxColorSpace::parse(&obj1);
     3918      colorSpace = GfxColorSpace::parse(&obj1, this);
    36863919    } else if (csMode == streamCSDeviceGray) {
    36873920      colorSpace = new GfxDeviceGrayColorSpace();
     
    37443977      maskHeight = obj1.getInt();
    37453978      obj1.free();
     3979      maskDict->lookup("Interpolate", &obj1);
     3980      if (obj1.isNull()) {
     3981        obj1.free();
     3982        maskDict->lookup("I", &obj1);
     3983      }
     3984      if (obj1.isBool())
     3985        maskInterpolate = obj1.getBool();
     3986      else
     3987        maskInterpolate = gFalse;
     3988      obj1.free();
    37463989      maskDict->lookup("BitsPerComponent", &obj1);
    37473990      if (obj1.isNull()) {
     
    37684011        }
    37694012      }
    3770       maskColorSpace = GfxColorSpace::parse(&obj1);
     4013      maskColorSpace = GfxColorSpace::parse(&obj1, this);
    37714014      obj1.free();
    37724015      if (!maskColorSpace || maskColorSpace->getMode() != csDeviceGray) {
     
    37924035           ++i) {
    37934036        maskObj.arrayGet(i, &obj1);
    3794         maskColors[i] = obj1.getInt();
     4037        if (obj1.isInt()) {
     4038          maskColors[i] = obj1.getInt();
     4039        } else if (obj1.isReal()) {
     4040          error(-1, "Mask entry should be an integer but it's a real, trying to use it");
     4041          maskColors[i] = (int) obj1.getReal();
     4042        } else {
     4043          error(-1, "Mask entry should be an integer but it's of type %d", obj1.getType());
     4044          obj1.free();
     4045          goto err1;
     4046        }
    37954047        obj1.free();
    37964048      }
     
    38234075      maskHeight = obj1.getInt();
    38244076      obj1.free();
     4077      maskDict->lookup("Interpolate", &obj1);
     4078      if (obj1.isNull()) {
     4079        obj1.free();
     4080        maskDict->lookup("I", &obj1);
     4081      }
     4082      if (obj1.isBool())
     4083        maskInterpolate = obj1.getBool();
     4084      else
     4085        maskInterpolate = gFalse;
     4086      obj1.free();
    38254087      maskDict->lookup("ImageMask", &obj1);
    38264088      if (obj1.isNull()) {
     
    38404102      if (obj1.isArray()) {
    38414103        obj1.arrayGet(0, &obj2);
    3842         if (obj2.isInt() && obj2.getInt() == 1) {
     4104        // Table 4.39 says /Decode must be [1 0] or [0 1]. Adobe
     4105        // accepts [1.0 0.0] as well.
     4106        if (obj2.isNum() && obj2.getNum() >= 0.9) {
    38434107          maskInvert = gTrue;
    38444108        }
     
    38544118    if (haveSoftMask) {
    38554119      if (!contentIsHidden()) {
    3856         out->drawSoftMaskedImage(state, ref, str, width, height, colorMap,
    3857                                  maskStr, maskWidth, maskHeight, maskColorMap);
     4120        out->drawSoftMaskedImage(state, ref, str, width, height, colorMap, interpolate,
     4121                                 maskStr, maskWidth, maskHeight, maskColorMap, maskInterpolate);
    38584122      }
    38594123      delete maskColorMap;
    38604124    } else if (haveExplicitMask && !contentIsHidden ()) {
    3861       out->drawMaskedImage(state, ref, str, width, height, colorMap,
    3862                            maskStr, maskWidth, maskHeight, maskInvert);
     4125      out->drawMaskedImage(state, ref, str, width, height, colorMap, interpolate,
     4126                           maskStr, maskWidth, maskHeight, maskInvert, maskInterpolate);
    38634127    } else if (!contentIsHidden()) {
    3864       out->drawImage(state, ref, str, width, height, colorMap,
     4128      out->drawImage(state, ref, str, width, height, colorMap, interpolate,
    38654129                     haveColorKeyMask ? maskColors : (int *)NULL, inlineImg);
    38664130    }
     
    39504214      transpGroup = gTrue;
    39514215      if (!obj1.dictLookup("CS", &obj3)->isNull()) {
    3952         blendingColorSpace = GfxColorSpace::parse(&obj3);
     4216        blendingColorSpace = GfxColorSpace::parse(&obj3, this);
    39534217      }
    39544218      obj3.free();
     
    40404304  }
    40414305
     4306  GfxState *stateBefore = state;
     4307
    40424308  // draw the form
    40434309  display(str, gFalse);
     4310 
     4311  if (stateBefore != state) {
     4312    if (state->isParentState(stateBefore)) {
     4313      error(-1, "There's a form with more q than Q, trying to fix");
     4314      while (stateBefore != state) {
     4315        restoreState();
     4316      }
     4317    } else {
     4318      error(-1, "There's a form with more Q than q");
     4319    }
     4320  }
    40444321
    40454322  if (softMask || transpGroup) {
     
    41944471
    41954472GBool Gfx::contentIsHidden() {
    4196   return mcStack && mcStack->ocSuppressed;
     4473  MarkedContentStack *mc = mcStack;
     4474  bool hidden = mc && mc->ocSuppressed;
     4475  while (!hidden && mc && mc->next) {
     4476    mc = mc->next;
     4477    hidden = mc->ocSuppressed;
     4478  }
     4479  return hidden;
    41974480}
    41984481
     
    42344517  if(numArgs == 2 && args[1].isDict ()) {
    42354518    out->beginMarkedContent(args[0].getName(),args[1].getDict());
    4236   } else {
    4237     out->beginMarkedContent(args[0].getName());
    42384519  }
    42394520}
     
    43334614    // get the form matrix
    43344615    dict->lookup("Matrix", &matrixObj);
    4335     if (matrixObj.isArray()) {
     4616    if (matrixObj.isArray() && matrixObj.arrayGetLength() >= 6) {
    43364617      for (i = 0; i < 6; ++i) {
    43374618        matrixObj.arrayGet(i, &obj1);
     
    44614742  res = resPtr;
    44624743}
     4744
     4745#ifdef USE_CMS
     4746PopplerCache *Gfx::getIccColorSpaceCache()
     4747{
     4748  return &iccColorSpaceCache;
     4749}
     4750#endif
Note: See TracChangeset for help on using the changeset viewer.