Diffstat (limited to 'noncore/unsupported/qpdf/xpdf/GfxState.cc') (more/less context) (ignore whitespace changes)
-rw-r--r-- | noncore/unsupported/qpdf/xpdf/GfxState.cc | 246 |
1 files changed, 235 insertions, 11 deletions
diff --git a/noncore/unsupported/qpdf/xpdf/GfxState.cc b/noncore/unsupported/qpdf/xpdf/GfxState.cc index af4e0d4..befd45a 100644 --- a/noncore/unsupported/qpdf/xpdf/GfxState.cc +++ b/noncore/unsupported/qpdf/xpdf/GfxState.cc | |||
@@ -1,9 +1,9 @@ | |||
1 | //======================================================================== | 1 | //======================================================================== |
2 | // | 2 | // |
3 | // GfxState.cc | 3 | // GfxState.cc |
4 | // | 4 | // |
5 | // Copyright 1996 Derek B. Noonburg | 5 | // Copyright 1996-2002 Glyph & Cog, LLC |
6 | // | 6 | // |
7 | //======================================================================== | 7 | //======================================================================== |
8 | 8 | ||
9 | #ifdef __GNUC__ | 9 | #ifdef __GNUC__ |
@@ -407,11 +407,24 @@ void GfxDeviceCMYKColorSpace::getGray(GfxColor *color, fouble *gray) { | |||
407 | - 0.114 * color->c[2]); | 407 | - 0.114 * color->c[2]); |
408 | } | 408 | } |
409 | 409 | ||
410 | void GfxDeviceCMYKColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) { | 410 | void GfxDeviceCMYKColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) { |
411 | rgb->r = clip01(1 - (color->c[0] + color->c[3])); | 411 | fouble c, m, y, aw, ac, am, ay, ar, ag, ab; |
412 | rgb->g = clip01(1 - (color->c[1] + color->c[3])); | 412 | |
413 | rgb->b = clip01(1 - (color->c[2] + color->c[3])); | 413 | c = clip01(color->c[0] + color->c[3]); |
414 | m = clip01(color->c[1] + color->c[3]); | ||
415 | y = clip01(color->c[2] + color->c[3]); | ||
416 | aw = (1-c) * (1-m) * (1-y); | ||
417 | ac = c * (1-m) * (1-y); | ||
418 | am = (1-c) * m * (1-y); | ||
419 | ay = (1-c) * (1-m) * y; | ||
420 | ar = (1-c) * m * y; | ||
421 | ag = c * (1-m) * y; | ||
422 | ab = c * m * (1-y); | ||
423 | rgb->r = clip01(aw + 0.9137*am + 0.9961*ay + 0.9882*ar); | ||
424 | rgb->g = clip01(aw + 0.6196*ac + ay + 0.5176*ag); | ||
425 | rgb->b = clip01(aw + 0.7804*ac + 0.5412*am + 0.0667*ar + 0.2118*ag + | ||
426 | 0.4863*ab); | ||
414 | } | 427 | } |
415 | 428 | ||
416 | void GfxDeviceCMYKColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) { | 429 | void GfxDeviceCMYKColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) { |
417 | cmyk->c = clip01(color->c[0]); | 430 | cmyk->c = clip01(color->c[0]); |
@@ -1267,12 +1280,8 @@ GfxShading *GfxShading::parse(Object *obj) { | |||
1267 | goto err1; | 1280 | goto err1; |
1268 | } | 1281 | } |
1269 | typeA = obj1.getInt(); | 1282 | typeA = obj1.getInt(); |
1270 | obj1.free(); | 1283 | obj1.free(); |
1271 | if (typeA != 2) { | ||
1272 | error(-1, "Unimplemented shading type %d", typeA); | ||
1273 | goto err1; | ||
1274 | } | ||
1275 | 1284 | ||
1276 | obj->dictLookup("ColorSpace", &obj1); | 1285 | obj->dictLookup("ColorSpace", &obj1); |
1277 | if (!(colorSpaceA = GfxColorSpace::parse(&obj1))) { | 1286 | if (!(colorSpaceA = GfxColorSpace::parse(&obj1))) { |
1278 | error(-1, "Bad color space in shading dictionary"); | 1287 | error(-1, "Bad color space in shading dictionary"); |
@@ -1316,9 +1325,19 @@ GfxShading *GfxShading::parse(Object *obj) { | |||
1316 | } | 1325 | } |
1317 | } | 1326 | } |
1318 | obj1.free(); | 1327 | obj1.free(); |
1319 | 1328 | ||
1320 | shading = GfxAxialShading::parse(obj->getDict()); | 1329 | switch (typeA) { |
1330 | case 2: | ||
1331 | shading = GfxAxialShading::parse(obj->getDict()); | ||
1332 | break; | ||
1333 | case 3: | ||
1334 | shading = GfxRadialShading::parse(obj->getDict()); | ||
1335 | break; | ||
1336 | default: | ||
1337 | error(-1, "Unimplemented shading type %d", typeA); | ||
1338 | goto err1; | ||
1339 | } | ||
1321 | 1340 | ||
1322 | if (shading) { | 1341 | if (shading) { |
1323 | shading->type = typeA; | 1342 | shading->type = typeA; |
1324 | shading->colorSpace = colorSpaceA; | 1343 | shading->colorSpace = colorSpaceA; |
@@ -1456,8 +1475,130 @@ void GfxAxialShading::getColor(fouble t, GfxColor *color) { | |||
1456 | } | 1475 | } |
1457 | } | 1476 | } |
1458 | 1477 | ||
1459 | //------------------------------------------------------------------------ | 1478 | //------------------------------------------------------------------------ |
1479 | // GfxRadialShading | ||
1480 | //------------------------------------------------------------------------ | ||
1481 | |||
1482 | GfxRadialShading::GfxRadialShading(fouble x0A, fouble y0A, fouble r0A, | ||
1483 | fouble x1A, fouble y1A, fouble r1A, | ||
1484 | fouble t0A, fouble t1A, | ||
1485 | Function **funcsA, int nFuncsA, | ||
1486 | GBool extend0A, GBool extend1A) { | ||
1487 | int i; | ||
1488 | |||
1489 | x0 = x0A; | ||
1490 | y0 = y0A; | ||
1491 | r0 = r0A; | ||
1492 | x1 = x1A; | ||
1493 | y1 = y1A; | ||
1494 | r1 = r1A; | ||
1495 | t0 = t0A; | ||
1496 | t1 = t1A; | ||
1497 | nFuncs = nFuncsA; | ||
1498 | for (i = 0; i < nFuncs; ++i) { | ||
1499 | funcs[i] = funcsA[i]; | ||
1500 | } | ||
1501 | extend0 = extend0A; | ||
1502 | extend1 = extend1A; | ||
1503 | } | ||
1504 | |||
1505 | GfxRadialShading::~GfxRadialShading() { | ||
1506 | int i; | ||
1507 | |||
1508 | for (i = 0; i < nFuncs; ++i) { | ||
1509 | delete funcs[i]; | ||
1510 | } | ||
1511 | } | ||
1512 | |||
1513 | GfxRadialShading *GfxRadialShading::parse(Dict *dict) { | ||
1514 | fouble x0A, y0A, r0A, x1A, y1A, r1A; | ||
1515 | fouble t0A, t1A; | ||
1516 | Function *funcsA[gfxColorMaxComps]; | ||
1517 | int nFuncsA; | ||
1518 | GBool extend0A, extend1A; | ||
1519 | Object obj1, obj2; | ||
1520 | int i; | ||
1521 | |||
1522 | x0A = y0A = r0A = x1A = y1A = r1A = 0; | ||
1523 | if (dict->lookup("Coords", &obj1)->isArray() && | ||
1524 | obj1.arrayGetLength() == 6) { | ||
1525 | x0A = obj1.arrayGet(0, &obj2)->getNum(); | ||
1526 | obj2.free(); | ||
1527 | y0A = obj1.arrayGet(1, &obj2)->getNum(); | ||
1528 | obj2.free(); | ||
1529 | r0A = obj1.arrayGet(2, &obj2)->getNum(); | ||
1530 | obj2.free(); | ||
1531 | x1A = obj1.arrayGet(3, &obj2)->getNum(); | ||
1532 | obj2.free(); | ||
1533 | y1A = obj1.arrayGet(4, &obj2)->getNum(); | ||
1534 | obj2.free(); | ||
1535 | r1A = obj1.arrayGet(5, &obj2)->getNum(); | ||
1536 | obj2.free(); | ||
1537 | } else { | ||
1538 | error(-1, "Missing or invalid Coords in shading dictionary"); | ||
1539 | goto err1; | ||
1540 | } | ||
1541 | obj1.free(); | ||
1542 | |||
1543 | t0A = 0; | ||
1544 | t1A = 1; | ||
1545 | if (dict->lookup("Domain", &obj1)->isArray() && | ||
1546 | obj1.arrayGetLength() == 2) { | ||
1547 | t0A = obj1.arrayGet(0, &obj2)->getNum(); | ||
1548 | obj2.free(); | ||
1549 | t1A = obj1.arrayGet(1, &obj2)->getNum(); | ||
1550 | obj2.free(); | ||
1551 | } | ||
1552 | obj1.free(); | ||
1553 | |||
1554 | dict->lookup("Function", &obj1); | ||
1555 | if (obj1.isArray()) { | ||
1556 | nFuncsA = obj1.arrayGetLength(); | ||
1557 | for (i = 0; i < nFuncsA; ++i) { | ||
1558 | obj1.arrayGet(i, &obj2); | ||
1559 | if (!(funcsA[i] = Function::parse(&obj2))) { | ||
1560 | obj1.free(); | ||
1561 | obj2.free(); | ||
1562 | goto err1; | ||
1563 | } | ||
1564 | obj2.free(); | ||
1565 | } | ||
1566 | } else { | ||
1567 | nFuncsA = 1; | ||
1568 | if (!(funcsA[0] = Function::parse(&obj1))) { | ||
1569 | obj1.free(); | ||
1570 | goto err1; | ||
1571 | } | ||
1572 | } | ||
1573 | obj1.free(); | ||
1574 | |||
1575 | extend0A = extend1A = gFalse; | ||
1576 | if (dict->lookup("Extend", &obj1)->isArray() && | ||
1577 | obj1.arrayGetLength() == 2) { | ||
1578 | extend0A = obj1.arrayGet(0, &obj2)->getBool(); | ||
1579 | obj2.free(); | ||
1580 | extend1A = obj1.arrayGet(1, &obj2)->getBool(); | ||
1581 | obj2.free(); | ||
1582 | } | ||
1583 | obj1.free(); | ||
1584 | |||
1585 | return new GfxRadialShading(x0A, y0A, r0A, x1A, y1A, r1A, t0A, t1A, | ||
1586 | funcsA, nFuncsA, extend0A, extend1A); | ||
1587 | |||
1588 | err1: | ||
1589 | return NULL; | ||
1590 | } | ||
1591 | |||
1592 | void GfxRadialShading::getColor(fouble t, GfxColor *color) { | ||
1593 | int i; | ||
1594 | |||
1595 | for (i = 0; i < nFuncs; ++i) { | ||
1596 | funcs[i]->transform(&t, &color->c[i]); | ||
1597 | } | ||
1598 | } | ||
1599 | |||
1600 | //------------------------------------------------------------------------ | ||
1460 | // GfxImageColorMap | 1601 | // GfxImageColorMap |
1461 | //------------------------------------------------------------------------ | 1602 | //------------------------------------------------------------------------ |
1462 | 1603 | ||
1463 | GfxImageColorMap::GfxImageColorMap(int bitsA, Object *decode, | 1604 | GfxImageColorMap::GfxImageColorMap(int bitsA, Object *decode, |
@@ -1917,8 +2058,69 @@ GfxState::GfxState(GfxState *state) { | |||
1917 | } | 2058 | } |
1918 | saved = NULL; | 2059 | saved = NULL; |
1919 | } | 2060 | } |
1920 | 2061 | ||
2062 | void GfxState::getUserClipBBox(fouble *xMin, fouble *yMin, | ||
2063 | fouble *xMax, fouble *yMax) { | ||
2064 | fouble ictm[6]; | ||
2065 | fouble xMin1, yMin1, xMax1, yMax1, det, tx, ty; | ||
2066 | |||
2067 | // invert the CTM | ||
2068 | det = 1 / (ctm[0] * ctm[3] - ctm[1] * ctm[2]); | ||
2069 | ictm[0] = ctm[3] * det; | ||
2070 | ictm[1] = -ctm[1] * det; | ||
2071 | ictm[2] = -ctm[2] * det; | ||
2072 | ictm[3] = ctm[0] * det; | ||
2073 | ictm[4] = (ctm[2] * ctm[5] - ctm[3] * ctm[4]) * det; | ||
2074 | ictm[5] = (ctm[1] * ctm[4] - ctm[0] * ctm[5]) * det; | ||
2075 | |||
2076 | // transform all four corners of the clip bbox; find the min and max | ||
2077 | // x and y values | ||
2078 | xMin1 = xMax1 = clipXMin * ictm[0] + clipYMin * ictm[2] + ictm[4]; | ||
2079 | yMin1 = yMax1 = clipXMin * ictm[1] + clipYMin * ictm[3] + ictm[5]; | ||
2080 | tx = clipXMin * ictm[0] + clipYMax * ictm[2] + ictm[4]; | ||
2081 | ty = clipXMin * ictm[1] + clipYMax * ictm[3] + ictm[5]; | ||
2082 | if (tx < xMin1) { | ||
2083 | xMin1 = tx; | ||
2084 | } else if (tx > xMax1) { | ||
2085 | xMax1 = tx; | ||
2086 | } | ||
2087 | if (ty < yMin1) { | ||
2088 | yMin1 = ty; | ||
2089 | } else if (ty > yMax1) { | ||
2090 | yMax1 = ty; | ||
2091 | } | ||
2092 | tx = clipXMax * ictm[0] + clipYMin * ictm[2] + ictm[4]; | ||
2093 | ty = clipXMax * ictm[1] + clipYMin * ictm[3] + ictm[5]; | ||
2094 | if (tx < xMin1) { | ||
2095 | xMin1 = tx; | ||
2096 | } else if (tx > xMax1) { | ||
2097 | xMax1 = tx; | ||
2098 | } | ||
2099 | if (ty < yMin1) { | ||
2100 | yMin1 = ty; | ||
2101 | } else if (ty > yMax1) { | ||
2102 | yMax1 = ty; | ||
2103 | } | ||
2104 | tx = clipXMax * ictm[0] + clipYMax * ictm[2] + ictm[4]; | ||
2105 | ty = clipXMax * ictm[1] + clipYMax * ictm[3] + ictm[5]; | ||
2106 | if (tx < xMin1) { | ||
2107 | xMin1 = tx; | ||
2108 | } else if (tx > xMax1) { | ||
2109 | xMax1 = tx; | ||
2110 | } | ||
2111 | if (ty < yMin1) { | ||
2112 | yMin1 = ty; | ||
2113 | } else if (ty > yMax1) { | ||
2114 | yMax1 = ty; | ||
2115 | } | ||
2116 | |||
2117 | *xMin = xMin1; | ||
2118 | *yMin = yMin1; | ||
2119 | *xMax = xMax1; | ||
2120 | *yMax = yMax1; | ||
2121 | } | ||
2122 | |||
1921 | fouble GfxState::transformWidth(fouble w) { | 2123 | fouble GfxState::transformWidth(fouble w) { |
1922 | fouble x, y; | 2124 | fouble x, y; |
1923 | 2125 | ||
1924 | x = ctm[0] + ctm[2]; | 2126 | x = ctm[0] + ctm[2]; |
@@ -1945,29 +2147,50 @@ void GfxState::getFontTransMat(fouble *m11, fouble *m12, | |||
1945 | } | 2147 | } |
1946 | 2148 | ||
1947 | void GfxState::setCTM(fouble a, fouble b, fouble c, | 2149 | void GfxState::setCTM(fouble a, fouble b, fouble c, |
1948 | fouble d, fouble e, fouble f) { | 2150 | fouble d, fouble e, fouble f) { |
2151 | int i; | ||
2152 | |||
1949 | ctm[0] = a; | 2153 | ctm[0] = a; |
1950 | ctm[1] = b; | 2154 | ctm[1] = b; |
1951 | ctm[2] = c; | 2155 | ctm[2] = c; |
1952 | ctm[3] = d; | 2156 | ctm[3] = d; |
1953 | ctm[4] = e; | 2157 | ctm[4] = e; |
1954 | ctm[5] = f; | 2158 | ctm[5] = f; |
2159 | |||
2160 | // avoid FP exceptions on badly messed up PDF files | ||
2161 | for (i = 0; i < 6; ++i) { | ||
2162 | if (ctm[i] > fouble(1e3)) { | ||
2163 | ctm[i] = fouble(1e3); | ||
2164 | } else if (ctm[i] < -fouble(1e3)) { | ||
2165 | ctm[i] = -fouble(1e3); | ||
2166 | } | ||
2167 | } | ||
1955 | } | 2168 | } |
1956 | 2169 | ||
1957 | void GfxState::concatCTM(fouble a, fouble b, fouble c, | 2170 | void GfxState::concatCTM(fouble a, fouble b, fouble c, |
1958 | fouble d, fouble e, fouble f) { | 2171 | fouble d, fouble e, fouble f) { |
1959 | fouble a1 = ctm[0]; | 2172 | fouble a1 = ctm[0]; |
1960 | fouble b1 = ctm[1]; | 2173 | fouble b1 = ctm[1]; |
1961 | fouble c1 = ctm[2]; | 2174 | fouble c1 = ctm[2]; |
1962 | fouble d1 = ctm[3]; | 2175 | fouble d1 = ctm[3]; |
2176 | int i; | ||
1963 | 2177 | ||
1964 | ctm[0] = a * a1 + b * c1; | 2178 | ctm[0] = a * a1 + b * c1; |
1965 | ctm[1] = a * b1 + b * d1; | 2179 | ctm[1] = a * b1 + b * d1; |
1966 | ctm[2] = c * a1 + d * c1; | 2180 | ctm[2] = c * a1 + d * c1; |
1967 | ctm[3] = c * b1 + d * d1; | 2181 | ctm[3] = c * b1 + d * d1; |
1968 | ctm[4] = e * a1 + f * c1 + ctm[4]; | 2182 | ctm[4] = e * a1 + f * c1 + ctm[4]; |
1969 | ctm[5] = e * b1 + f * d1 + ctm[5]; | 2183 | ctm[5] = e * b1 + f * d1 + ctm[5]; |
2184 | |||
2185 | // avoid FP exceptions on badly messed up PDF files | ||
2186 | for (i = 0; i < 6; ++i) { | ||
2187 | if (ctm[i] > fouble(1e3)) { | ||
2188 | ctm[i] = fouble(1e3); | ||
2189 | } else if (ctm[i] < -fouble(1e3)) { | ||
2190 | ctm[i] = -fouble(1e3); | ||
2191 | } | ||
2192 | } | ||
1970 | } | 2193 | } |
1971 | 2194 | ||
1972 | void GfxState::setFillColorSpace(GfxColorSpace *colorSpace) { | 2195 | void GfxState::setFillColorSpace(GfxColorSpace *colorSpace) { |
1973 | if (fillColorSpace) { | 2196 | if (fillColorSpace) { |
@@ -2050,12 +2273,12 @@ void GfxState::clip() { | |||
2050 | clipYMax = yMax; | 2273 | clipYMax = yMax; |
2051 | } | 2274 | } |
2052 | } | 2275 | } |
2053 | 2276 | ||
2054 | void GfxState::textShift(fouble tx) { | 2277 | void GfxState::textShift(fouble tx, fouble ty) { |
2055 | fouble dx, dy; | 2278 | fouble dx, dy; |
2056 | 2279 | ||
2057 | textTransformDelta(tx, 0, &dx, &dy); | 2280 | textTransformDelta(tx, ty, &dx, &dy); |
2058 | curX += dx; | 2281 | curX += dx; |
2059 | curY += dy; | 2282 | curY += dy; |
2060 | } | 2283 | } |
2061 | 2284 | ||
@@ -2094,4 +2317,5 @@ GfxState *GfxState::restore() { | |||
2094 | } | 2317 | } |
2095 | 2318 | ||
2096 | return oldState; | 2319 | return oldState; |
2097 | } | 2320 | } |
2321 | |||