+ *val = x;
+ return gTrue;
+}
+
+void GfxShadingBitBuf::flushBits() {
+ bitBuf = 0;
+ nBits = 0;
+}
+
+//------------------------------------------------------------------------
+// GfxGouraudTriangleShading
+//------------------------------------------------------------------------
+
+GfxGouraudTriangleShading::GfxGouraudTriangleShading(
+ int typeA,
+ GfxGouraudVertex *verticesA, int nVerticesA,
+ int (*trianglesA)[3], int nTrianglesA,
+ Function **funcsA, int nFuncsA):
+ GfxShading(typeA)
+{
+ int i;
+
+ vertices = verticesA;
+ nVertices = nVerticesA;
+ triangles = trianglesA;
+ nTriangles = nTrianglesA;
+ nFuncs = nFuncsA;
+ for (i = 0; i < nFuncs; ++i) {
+ funcs[i] = funcsA[i];
+ }
+}
+
+GfxGouraudTriangleShading::GfxGouraudTriangleShading(
+ GfxGouraudTriangleShading *shading):
+ GfxShading(shading)
+{
+ int i;
+
+ nVertices = shading->nVertices;
+ vertices = (GfxGouraudVertex *)gmallocn(nVertices, sizeof(GfxGouraudVertex));
+ memcpy(vertices, shading->vertices, nVertices * sizeof(GfxGouraudVertex));
+ nTriangles = shading->nTriangles;
+ triangles = (int (*)[3])gmallocn(nTriangles * 3, sizeof(int));
+ memcpy(triangles, shading->triangles, nTriangles * 3 * sizeof(int));
+ nFuncs = shading->nFuncs;
+ for (i = 0; i < nFuncs; ++i) {
+ funcs[i] = shading->funcs[i]->copy();
+ }
+}
+
+GfxGouraudTriangleShading::~GfxGouraudTriangleShading() {
+ int i;
+
+ gfree(vertices);
+ gfree(triangles);
+ for (i = 0; i < nFuncs; ++i) {
+ delete funcs[i];
+ }
+}
+
+GfxGouraudTriangleShading *GfxGouraudTriangleShading::parse(int typeA,
+ Dict *dict,
+ Stream *str) {
+ GfxGouraudTriangleShading *shading;
+ Function *funcsA[gfxColorMaxComps];
+ int nFuncsA;
+ int coordBits, compBits, flagBits, vertsPerRow, nRows;
+ double xMin, xMax, yMin, yMax;
+ double cMin[gfxColorMaxComps], cMax[gfxColorMaxComps];
+ double xMul, yMul;
+ double cMul[gfxColorMaxComps];
+ GfxGouraudVertex *verticesA;
+ int (*trianglesA)[3];
+ int nComps, nVerticesA, nTrianglesA, vertSize, triSize;
+ Guint x, y, flag;
+ Guint c[gfxColorMaxComps];
+ GfxShadingBitBuf *bitBuf;
+ Object obj1, obj2;
+ int i, j, k, state;
+
+ if (dict->lookup("BitsPerCoordinate", &obj1)->isInt()) {
+ coordBits = obj1.getInt();
+ } else {
+ error(-1, "Missing or invalid BitsPerCoordinate in shading dictionary");
+ goto err2;
+ }
+ obj1.free();
+ if (dict->lookup("BitsPerComponent", &obj1)->isInt()) {
+ compBits = obj1.getInt();
+ } else {
+ error(-1, "Missing or invalid BitsPerComponent in shading dictionary");
+ goto err2;
+ }
+ obj1.free();
+ flagBits = vertsPerRow = 0; // make gcc happy
+ if (typeA == 4) {
+ if (dict->lookup("BitsPerFlag", &obj1)->isInt()) {
+ flagBits = obj1.getInt();
+ } else {
+ error(-1, "Missing or invalid BitsPerFlag in shading dictionary");
+ goto err2;
+ }
+ obj1.free();
+ } else {
+ if (dict->lookup("VerticesPerRow", &obj1)->isInt()) {
+ vertsPerRow = obj1.getInt();
+ } else {
+ error(-1, "Missing or invalid VerticesPerRow in shading dictionary");
+ goto err2;
+ }
+ obj1.free();
+ }
+ if (dict->lookup("Decode", &obj1)->isArray() &&
+ obj1.arrayGetLength() >= 6) {
+ xMin = obj1.arrayGet(0, &obj2)->getNum();
+ obj2.free();
+ xMax = obj1.arrayGet(1, &obj2)->getNum();
+ obj2.free();
+ xMul = (xMax - xMin) / (pow(2.0, coordBits) - 1);
+ yMin = obj1.arrayGet(2, &obj2)->getNum();
+ obj2.free();
+ yMax = obj1.arrayGet(3, &obj2)->getNum();
+ obj2.free();
+ yMul = (yMax - yMin) / (pow(2.0, coordBits) - 1);
+ for (i = 0; 5 + 2*i < obj1.arrayGetLength() && i < gfxColorMaxComps; ++i) {
+ cMin[i] = obj1.arrayGet(4 + 2*i, &obj2)->getNum();
+ obj2.free();
+ cMax[i] = obj1.arrayGet(5 + 2*i, &obj2)->getNum();
+ obj2.free();
+ cMul[i] = (cMax[i] - cMin[i]) / (double)((1 << compBits) - 1);
+ }
+ nComps = i;
+ } else {
+ error(-1, "Missing or invalid Decode array in shading dictionary");
+ goto err2;
+ }
+ obj1.free();
+
+ if (!dict->lookup("Function", &obj1)->isNull()) {
+ if (obj1.isArray()) {
+ nFuncsA = obj1.arrayGetLength();
+ if (nFuncsA > gfxColorMaxComps) {
+ error(-1, "Invalid Function array in shading dictionary");
+ goto err1;
+ }
+ for (i = 0; i < nFuncsA; ++i) {
+ obj1.arrayGet(i, &obj2);
+ if (!(funcsA[i] = Function::parse(&obj2))) {
+ obj1.free();
+ obj2.free();
+ goto err1;
+ }
+ obj2.free();
+ }
+ } else {
+ nFuncsA = 1;
+ if (!(funcsA[0] = Function::parse(&obj1))) {
+ obj1.free();
+ goto err1;
+ }
+ }
+ } else {
+ nFuncsA = 0;
+ }
+ obj1.free();
+
+ nVerticesA = nTrianglesA = 0;
+ verticesA = NULL;
+ trianglesA = NULL;
+ vertSize = triSize = 0;
+ state = 0;
+ flag = 0; // make gcc happy
+ bitBuf = new GfxShadingBitBuf(str);
+ while (1) {
+ if (typeA == 4) {
+ if (!bitBuf->getBits(flagBits, &flag)) {
+ break;
+ }
+ }
+ if (!bitBuf->getBits(coordBits, &x) ||
+ !bitBuf->getBits(coordBits, &y)) {
+ break;
+ }
+ for (i = 0; i < nComps; ++i) {
+ if (!bitBuf->getBits(compBits, &c[i])) {
+ break;
+ }
+ }
+ if (i < nComps) {
+ break;
+ }
+ if (nVerticesA == vertSize) {
+ vertSize = (vertSize == 0) ? 16 : 2 * vertSize;
+ verticesA = (GfxGouraudVertex *)
+ greallocn(verticesA, vertSize, sizeof(GfxGouraudVertex));
+ }
+ verticesA[nVerticesA].x = xMin + xMul * (double)x;
+ verticesA[nVerticesA].y = yMin + yMul * (double)y;
+ for (i = 0; i < nComps; ++i) {
+ verticesA[nVerticesA].color.c[i] =
+ dblToCol(cMin[i] + cMul[i] * (double)c[i]);
+ }
+ ++nVerticesA;
+ bitBuf->flushBits();
+ if (typeA == 4) {
+ if (state == 0 || state == 1) {
+ ++state;
+ } else if (state == 2 || flag > 0) {
+ if (nTrianglesA == triSize) {
+ triSize = (triSize == 0) ? 16 : 2 * triSize;
+ trianglesA = (int (*)[3])
+ greallocn(trianglesA, triSize * 3, sizeof(int));
+ }
+ if (state == 2) {
+ trianglesA[nTrianglesA][0] = nVerticesA - 3;
+ trianglesA[nTrianglesA][1] = nVerticesA - 2;
+ trianglesA[nTrianglesA][2] = nVerticesA - 1;
+ ++state;
+ } else if (flag == 1) {
+ trianglesA[nTrianglesA][0] = trianglesA[nTrianglesA - 1][1];
+ trianglesA[nTrianglesA][1] = trianglesA[nTrianglesA - 1][2];
+ trianglesA[nTrianglesA][2] = nVerticesA - 1;
+ } else { // flag == 2
+ trianglesA[nTrianglesA][0] = trianglesA[nTrianglesA - 1][0];
+ trianglesA[nTrianglesA][1] = trianglesA[nTrianglesA - 1][2];
+ trianglesA[nTrianglesA][2] = nVerticesA - 1;
+ }
+ ++nTrianglesA;
+ } else { // state == 3 && flag == 0
+ state = 1;
+ }
+ }
+ }
+ delete bitBuf;
+ if (typeA == 5) {
+ nRows = nVerticesA / vertsPerRow;
+ nTrianglesA = (nRows - 1) * 2 * (vertsPerRow - 1);
+ trianglesA = (int (*)[3])gmallocn(nTrianglesA * 3, sizeof(int));
+ k = 0;
+ for (i = 0; i < nRows - 1; ++i) {
+ for (j = 0; j < vertsPerRow - 1; ++j) {
+ trianglesA[k][0] = i * vertsPerRow + j;
+ trianglesA[k][1] = i * vertsPerRow + j+1;
+ trianglesA[k][2] = (i+1) * vertsPerRow + j;
+ ++k;
+ trianglesA[k][0] = i * vertsPerRow + j+1;
+ trianglesA[k][1] = (i+1) * vertsPerRow + j;
+ trianglesA[k][2] = (i+1) * vertsPerRow + j+1;
+ ++k;
+ }
+ }
+ }
+
+ shading = new GfxGouraudTriangleShading(typeA, verticesA, nVerticesA,
+ trianglesA, nTrianglesA,
+ funcsA, nFuncsA);
+ if (!shading->init(dict)) {
+ delete shading;
+ return NULL;
+ }
+ return shading;
+
+ err2:
+ obj1.free();
+ err1:
+ return NULL;
+}
+
+GfxShading *GfxGouraudTriangleShading::copy() {
+ return new GfxGouraudTriangleShading(this);
+}
+
+void GfxGouraudTriangleShading::getTriangle(
+ int i,
+ double *x0, double *y0, GfxColor *color0,
+ double *x1, double *y1, GfxColor *color1,
+ double *x2, double *y2, GfxColor *color2) {
+ double in;
+ double out[gfxColorMaxComps];
+ int v, j;
+
+ v = triangles[i][0];
+ *x0 = vertices[v].x;
+ *y0 = vertices[v].y;
+ if (nFuncs > 0) {
+ in = colToDbl(vertices[v].color.c[0]);
+ for (j = 0; j < nFuncs; ++j) {
+ funcs[j]->transform(&in, &out[j]);
+ }
+ for (j = 0; j < gfxColorMaxComps; ++j) {
+ color0->c[j] = dblToCol(out[j]);
+ }
+ } else {
+ *color0 = vertices[v].color;
+ }
+ v = triangles[i][1];
+ *x1 = vertices[v].x;
+ *y1 = vertices[v].y;
+ if (nFuncs > 0) {
+ in = colToDbl(vertices[v].color.c[0]);
+ for (j = 0; j < nFuncs; ++j) {
+ funcs[j]->transform(&in, &out[j]);
+ }
+ for (j = 0; j < gfxColorMaxComps; ++j) {
+ color1->c[j] = dblToCol(out[j]);
+ }
+ } else {
+ *color1 = vertices[v].color;
+ }
+ v = triangles[i][2];
+ *x2 = vertices[v].x;
+ *y2 = vertices[v].y;
+ if (nFuncs > 0) {
+ in = colToDbl(vertices[v].color.c[0]);
+ for (j = 0; j < nFuncs; ++j) {
+ funcs[j]->transform(&in, &out[j]);
+ }
+ for (j = 0; j < gfxColorMaxComps; ++j) {
+ color2->c[j] = dblToCol(out[j]);
+ }
+ } else {
+ *color2 = vertices[v].color;
+ }
+}
+
+//------------------------------------------------------------------------
+// GfxPatchMeshShading
+//------------------------------------------------------------------------
+
+GfxPatchMeshShading::GfxPatchMeshShading(int typeA,
+ GfxPatch *patchesA, int nPatchesA,
+ Function **funcsA, int nFuncsA):
+ GfxShading(typeA)
+{
+ int i;
+
+ patches = patchesA;
+ nPatches = nPatchesA;
+ nFuncs = nFuncsA;
+ for (i = 0; i < nFuncs; ++i) {
+ funcs[i] = funcsA[i];
+ }
+}
+
+GfxPatchMeshShading::GfxPatchMeshShading(GfxPatchMeshShading *shading):
+ GfxShading(shading)
+{
+ int i;
+
+ nPatches = shading->nPatches;
+ patches = (GfxPatch *)gmallocn(nPatches, sizeof(GfxPatch));
+ memcpy(patches, shading->patches, nPatches * sizeof(GfxPatch));
+ nFuncs = shading->nFuncs;
+ for (i = 0; i < nFuncs; ++i) {
+ funcs[i] = shading->funcs[i]->copy();
+ }
+}
+
+GfxPatchMeshShading::~GfxPatchMeshShading() {
+ int i;
+
+ gfree(patches);
+ for (i = 0; i < nFuncs; ++i) {
+ delete funcs[i];
+ }
+}
+
+GfxPatchMeshShading *GfxPatchMeshShading::parse(int typeA, Dict *dict,
+ Stream *str) {
+ GfxPatchMeshShading *shading;
+ Function *funcsA[gfxColorMaxComps];
+ int nFuncsA;
+ int coordBits, compBits, flagBits;
+ double xMin, xMax, yMin, yMax;
+ double cMin[gfxColorMaxComps], cMax[gfxColorMaxComps];
+ double xMul, yMul;
+ double cMul[gfxColorMaxComps];
+ GfxPatch *patchesA, *p;
+ int nComps, nPatchesA, patchesSize, nPts, nColors;
+ Guint flag;
+ double x[16], y[16];
+ Guint xi, yi;
+ GfxColorComp c[4][gfxColorMaxComps];
+ Guint ci[4];
+ GfxShadingBitBuf *bitBuf;
+ Object obj1, obj2;
+ int i, j;
+
+ if (dict->lookup("BitsPerCoordinate", &obj1)->isInt()) {
+ coordBits = obj1.getInt();
+ } else {
+ error(-1, "Missing or invalid BitsPerCoordinate in shading dictionary");
+ goto err2;
+ }
+ obj1.free();
+ if (dict->lookup("BitsPerComponent", &obj1)->isInt()) {
+ compBits = obj1.getInt();
+ } else {
+ error(-1, "Missing or invalid BitsPerComponent in shading dictionary");
+ goto err2;
+ }
+ obj1.free();
+ if (dict->lookup("BitsPerFlag", &obj1)->isInt()) {
+ flagBits = obj1.getInt();
+ } else {
+ error(-1, "Missing or invalid BitsPerFlag in shading dictionary");
+ goto err2;
+ }
+ obj1.free();
+ if (dict->lookup("Decode", &obj1)->isArray() &&
+ obj1.arrayGetLength() >= 6) {
+ xMin = obj1.arrayGet(0, &obj2)->getNum();
+ obj2.free();
+ xMax = obj1.arrayGet(1, &obj2)->getNum();
+ obj2.free();
+ xMul = (xMax - xMin) / (pow(2.0, coordBits) - 1);
+ yMin = obj1.arrayGet(2, &obj2)->getNum();
+ obj2.free();
+ yMax = obj1.arrayGet(3, &obj2)->getNum();
+ obj2.free();
+ yMul = (yMax - yMin) / (pow(2.0, coordBits) - 1);
+ for (i = 0; 5 + 2*i < obj1.arrayGetLength() && i < gfxColorMaxComps; ++i) {
+ cMin[i] = obj1.arrayGet(4 + 2*i, &obj2)->getNum();
+ obj2.free();
+ cMax[i] = obj1.arrayGet(5 + 2*i, &obj2)->getNum();
+ obj2.free();
+ cMul[i] = (cMax[i] - cMin[i]) / (double)((1 << compBits) - 1);
+ }
+ nComps = i;
+ } else {
+ error(-1, "Missing or invalid Decode array in shading dictionary");
+ goto err2;
+ }
+ obj1.free();
+
+ if (!dict->lookup("Function", &obj1)->isNull()) {
+ if (obj1.isArray()) {
+ nFuncsA = obj1.arrayGetLength();
+ if (nFuncsA > gfxColorMaxComps) {
+ error(-1, "Invalid Function array in shading dictionary");
+ goto err1;
+ }
+ for (i = 0; i < nFuncsA; ++i) {
+ obj1.arrayGet(i, &obj2);
+ if (!(funcsA[i] = Function::parse(&obj2))) {
+ obj1.free();
+ obj2.free();
+ goto err1;
+ }
+ obj2.free();
+ }
+ } else {
+ nFuncsA = 1;
+ if (!(funcsA[0] = Function::parse(&obj1))) {
+ obj1.free();
+ goto err1;
+ }
+ }
+ } else {
+ nFuncsA = 0;
+ }
+ obj1.free();
+
+ nPatchesA = 0;
+ patchesA = NULL;
+ patchesSize = 0;
+ bitBuf = new GfxShadingBitBuf(str);
+ while (1) {
+ if (!bitBuf->getBits(flagBits, &flag)) {
+ break;
+ }
+ if (typeA == 6) {
+ switch (flag) {
+ case 0: nPts = 12; nColors = 4; break;
+ case 1:
+ case 2:
+ case 3:
+ default: nPts = 8; nColors = 2; break;
+ }
+ } else {
+ switch (flag) {
+ case 0: nPts = 16; nColors = 4; break;
+ case 1:
+ case 2:
+ case 3:
+ default: nPts = 12; nColors = 2; break;
+ }
+ }
+ for (i = 0; i < nPts; ++i) {
+ if (!bitBuf->getBits(coordBits, &xi) ||
+ !bitBuf->getBits(coordBits, &yi)) {
+ break;
+ }
+ x[i] = xMin + xMul * (double)xi;
+ y[i] = yMin + yMul * (double)yi;
+ }
+ if (i < nPts) {
+ break;
+ }
+ for (i = 0; i < nColors; ++i) {
+ for (j = 0; j < nComps; ++j) {
+ if (!bitBuf->getBits(compBits, &ci[j])) {
+ break;
+ }
+ c[i][j] = dblToCol(cMin[j] + cMul[j] * (double)ci[j]);
+ }
+ if (j < nComps) {
+ break;
+ }
+ }
+ if (i < nColors) {
+ break;
+ }
+ if (nPatchesA == patchesSize) {
+ patchesSize = (patchesSize == 0) ? 16 : 2 * patchesSize;
+ patchesA = (GfxPatch *)greallocn(patchesA,
+ patchesSize, sizeof(GfxPatch));
+ }
+ p = &patchesA[nPatchesA];
+ if (typeA == 6) {
+ switch (flag) {
+ case 0:
+ p->x[0][0] = x[0];
+ p->y[0][0] = y[0];
+ p->x[0][1] = x[1];
+ p->y[0][1] = y[1];
+ p->x[0][2] = x[2];
+ p->y[0][2] = y[2];
+ p->x[0][3] = x[3];
+ p->y[0][3] = y[3];
+ p->x[1][3] = x[4];
+ p->y[1][3] = y[4];
+ p->x[2][3] = x[5];
+ p->y[2][3] = y[5];
+ p->x[3][3] = x[6];
+ p->y[3][3] = y[6];
+ p->x[3][2] = x[7];
+ p->y[3][2] = y[7];
+ p->x[3][1] = x[8];
+ p->y[3][1] = y[8];
+ p->x[3][0] = x[9];
+ p->y[3][0] = y[9];
+ p->x[2][0] = x[10];
+ p->y[2][0] = y[10];
+ p->x[1][0] = x[11];
+ p->y[1][0] = y[11];
+ for (j = 0; j < nComps; ++j) {
+ p->color[0][0].c[j] = c[0][j];
+ p->color[0][1].c[j] = c[1][j];
+ p->color[1][1].c[j] = c[2][j];
+ p->color[1][0].c[j] = c[3][j];
+ }
+ break;
+ case 1:
+ p->x[0][0] = patchesA[nPatchesA-1].x[0][3];
+ p->y[0][0] = patchesA[nPatchesA-1].y[0][3];
+ p->x[0][1] = patchesA[nPatchesA-1].x[1][3];
+ p->y[0][1] = patchesA[nPatchesA-1].y[1][3];
+ p->x[0][2] = patchesA[nPatchesA-1].x[2][3];
+ p->y[0][2] = patchesA[nPatchesA-1].y[2][3];
+ p->x[0][3] = patchesA[nPatchesA-1].x[3][3];
+ p->y[0][3] = patchesA[nPatchesA-1].y[3][3];
+ p->x[1][3] = x[0];
+ p->y[1][3] = y[0];
+ p->x[2][3] = x[1];
+ p->y[2][3] = y[1];
+ p->x[3][3] = x[2];
+ p->y[3][3] = y[2];
+ p->x[3][2] = x[3];
+ p->y[3][2] = y[3];
+ p->x[3][1] = x[4];
+ p->y[3][1] = y[4];
+ p->x[3][0] = x[5];
+ p->y[3][0] = y[5];
+ p->x[2][0] = x[6];
+ p->y[2][0] = y[6];
+ p->x[1][0] = x[7];
+ p->y[1][0] = y[7];
+ for (j = 0; j < nComps; ++j) {
+ p->color[0][0].c[j] = patchesA[nPatchesA-1].color[0][1].c[j];
+ p->color[0][1].c[j] = patchesA[nPatchesA-1].color[1][1].c[j];
+ p->color[1][1].c[j] = c[0][j];
+ p->color[1][0].c[j] = c[1][j];
+ }
+ break;
+ case 2:
+ p->x[0][0] = patchesA[nPatchesA-1].x[3][3];
+ p->y[0][0] = patchesA[nPatchesA-1].y[3][3];
+ p->x[0][1] = patchesA[nPatchesA-1].x[3][2];
+ p->y[0][1] = patchesA[nPatchesA-1].y[3][2];
+ p->x[0][2] = patchesA[nPatchesA-1].x[3][1];
+ p->y[0][2] = patchesA[nPatchesA-1].y[3][1];
+ p->x[0][3] = patchesA[nPatchesA-1].x[3][0];
+ p->y[0][3] = patchesA[nPatchesA-1].y[3][0];
+ p->x[1][3] = x[0];
+ p->y[1][3] = y[0];
+ p->x[2][3] = x[1];
+ p->y[2][3] = y[1];
+ p->x[3][3] = x[2];
+ p->y[3][3] = y[2];
+ p->x[3][2] = x[3];
+ p->y[3][2] = y[3];
+ p->x[3][1] = x[4];
+ p->y[3][1] = y[4];
+ p->x[3][0] = x[5];
+ p->y[3][0] = y[5];
+ p->x[2][0] = x[6];
+ p->y[2][0] = y[6];
+ p->x[1][0] = x[7];
+ p->y[1][0] = y[7];
+ for (j = 0; j < nComps; ++j) {
+ p->color[0][0].c[j] = patchesA[nPatchesA-1].color[1][1].c[j];
+ p->color[0][1].c[j] = patchesA[nPatchesA-1].color[1][0].c[j];
+ p->color[1][1].c[j] = c[0][j];
+ p->color[1][0].c[j] = c[1][j];
+ }
+ break;
+ case 3:
+ p->x[0][0] = patchesA[nPatchesA-1].x[3][0];
+ p->y[0][0] = patchesA[nPatchesA-1].y[3][0];
+ p->x[0][1] = patchesA[nPatchesA-1].x[2][0];
+ p->y[0][1] = patchesA[nPatchesA-1].y[2][0];
+ p->x[0][2] = patchesA[nPatchesA-1].x[1][0];
+ p->y[0][2] = patchesA[nPatchesA-1].y[1][0];
+ p->x[0][3] = patchesA[nPatchesA-1].x[0][0];
+ p->y[0][3] = patchesA[nPatchesA-1].y[0][0];
+ p->x[1][3] = x[0];
+ p->y[1][3] = y[0];
+ p->x[2][3] = x[1];
+ p->y[2][3] = y[1];
+ p->x[3][3] = x[2];
+ p->y[3][3] = y[2];
+ p->x[3][2] = x[3];
+ p->y[3][2] = y[3];
+ p->x[3][1] = x[4];
+ p->y[3][1] = y[4];
+ p->x[3][0] = x[5];
+ p->y[3][0] = y[5];
+ p->x[2][0] = x[6];
+ p->y[2][0] = y[6];
+ p->x[1][0] = x[7];
+ p->y[1][0] = y[7];
+ for (j = 0; j < nComps; ++j) {
+ p->color[0][1].c[j] = patchesA[nPatchesA-1].color[1][0].c[j];
+ p->color[0][1].c[j] = patchesA[nPatchesA-1].color[0][0].c[j];
+ p->color[1][1].c[j] = c[0][j];
+ p->color[1][0].c[j] = c[1][j];
+ }
+ break;
+ }
+ } else {
+ switch (flag) {
+ case 0:
+ p->x[0][0] = x[0];
+ p->y[0][0] = y[0];
+ p->x[0][1] = x[1];
+ p->y[0][1] = y[1];
+ p->x[0][2] = x[2];
+ p->y[0][2] = y[2];
+ p->x[0][3] = x[3];
+ p->y[0][3] = y[3];
+ p->x[1][3] = x[4];
+ p->y[1][3] = y[4];
+ p->x[2][3] = x[5];
+ p->y[2][3] = y[5];
+ p->x[3][3] = x[6];
+ p->y[3][3] = y[6];
+ p->x[3][2] = x[7];
+ p->y[3][2] = y[7];
+ p->x[3][1] = x[8];
+ p->y[3][1] = y[8];
+ p->x[3][0] = x[9];
+ p->y[3][0] = y[9];
+ p->x[2][0] = x[10];
+ p->y[2][0] = y[10];
+ p->x[1][0] = x[11];
+ p->y[1][0] = y[11];
+ p->x[1][1] = x[12];
+ p->y[1][1] = y[12];
+ p->x[1][2] = x[13];
+ p->y[1][2] = y[13];
+ p->x[2][2] = x[14];
+ p->y[2][2] = y[14];
+ p->x[2][1] = x[15];
+ p->y[2][1] = y[15];
+ for (j = 0; j < nComps; ++j) {
+ p->color[0][0].c[j] = c[0][j];
+ p->color[0][1].c[j] = c[1][j];
+ p->color[1][1].c[j] = c[2][j];
+ p->color[1][0].c[j] = c[3][j];
+ }
+ break;
+ case 1:
+ p->x[0][0] = patchesA[nPatchesA-1].x[0][3];
+ p->y[0][0] = patchesA[nPatchesA-1].y[0][3];
+ p->x[0][1] = patchesA[nPatchesA-1].x[1][3];
+ p->y[0][1] = patchesA[nPatchesA-1].y[1][3];
+ p->x[0][2] = patchesA[nPatchesA-1].x[2][3];
+ p->y[0][2] = patchesA[nPatchesA-1].y[2][3];
+ p->x[0][3] = patchesA[nPatchesA-1].x[3][3];
+ p->y[0][3] = patchesA[nPatchesA-1].y[3][3];
+ p->x[1][3] = x[0];
+ p->y[1][3] = y[0];
+ p->x[2][3] = x[1];
+ p->y[2][3] = y[1];
+ p->x[3][3] = x[2];
+ p->y[3][3] = y[2];
+ p->x[3][2] = x[3];
+ p->y[3][2] = y[3];
+ p->x[3][1] = x[4];
+ p->y[3][1] = y[4];
+ p->x[3][0] = x[5];
+ p->y[3][0] = y[5];
+ p->x[2][0] = x[6];
+ p->y[2][0] = y[6];
+ p->x[1][0] = x[7];
+ p->y[1][0] = y[7];
+ p->x[1][1] = x[8];
+ p->y[1][1] = y[8];
+ p->x[1][2] = x[9];
+ p->y[1][2] = y[9];
+ p->x[2][2] = x[10];
+ p->y[2][2] = y[10];
+ p->x[2][1] = x[11];
+ p->y[2][1] = y[11];
+ for (j = 0; j < nComps; ++j) {
+ p->color[0][0].c[j] = patchesA[nPatchesA-1].color[0][1].c[j];
+ p->color[0][1].c[j] = patchesA[nPatchesA-1].color[1][1].c[j];
+ p->color[1][1].c[j] = c[0][j];
+ p->color[1][0].c[j] = c[1][j];
+ }
+ break;
+ case 2:
+ p->x[0][0] = patchesA[nPatchesA-1].x[3][3];
+ p->y[0][0] = patchesA[nPatchesA-1].y[3][3];
+ p->x[0][1] = patchesA[nPatchesA-1].x[3][2];
+ p->y[0][1] = patchesA[nPatchesA-1].y[3][2];
+ p->x[0][2] = patchesA[nPatchesA-1].x[3][1];
+ p->y[0][2] = patchesA[nPatchesA-1].y[3][1];
+ p->x[0][3] = patchesA[nPatchesA-1].x[3][0];
+ p->y[0][3] = patchesA[nPatchesA-1].y[3][0];
+ p->x[1][3] = x[0];
+ p->y[1][3] = y[0];
+ p->x[2][3] = x[1];
+ p->y[2][3] = y[1];
+ p->x[3][3] = x[2];
+ p->y[3][3] = y[2];
+ p->x[3][2] = x[3];
+ p->y[3][2] = y[3];
+ p->x[3][1] = x[4];
+ p->y[3][1] = y[4];
+ p->x[3][0] = x[5];
+ p->y[3][0] = y[5];
+ p->x[2][0] = x[6];
+ p->y[2][0] = y[6];
+ p->x[1][0] = x[7];
+ p->y[1][0] = y[7];
+ p->x[1][1] = x[8];
+ p->y[1][1] = y[8];
+ p->x[1][2] = x[9];
+ p->y[1][2] = y[9];
+ p->x[2][2] = x[10];
+ p->y[2][2] = y[10];
+ p->x[2][1] = x[11];
+ p->y[2][1] = y[11];
+ for (j = 0; j < nComps; ++j) {
+ p->color[0][0].c[j] = patchesA[nPatchesA-1].color[1][1].c[j];
+ p->color[0][1].c[j] = patchesA[nPatchesA-1].color[1][0].c[j];
+ p->color[1][1].c[j] = c[0][j];
+ p->color[1][0].c[j] = c[1][j];
+ }
+ break;
+ case 3:
+ p->x[0][0] = patchesA[nPatchesA-1].x[3][0];
+ p->y[0][0] = patchesA[nPatchesA-1].y[3][0];
+ p->x[0][1] = patchesA[nPatchesA-1].x[2][0];
+ p->y[0][1] = patchesA[nPatchesA-1].y[2][0];
+ p->x[0][2] = patchesA[nPatchesA-1].x[1][0];
+ p->y[0][2] = patchesA[nPatchesA-1].y[1][0];
+ p->x[0][3] = patchesA[nPatchesA-1].x[0][0];
+ p->y[0][3] = patchesA[nPatchesA-1].y[0][0];
+ p->x[1][3] = x[0];
+ p->y[1][3] = y[0];
+ p->x[2][3] = x[1];
+ p->y[2][3] = y[1];
+ p->x[3][3] = x[2];
+ p->y[3][3] = y[2];
+ p->x[3][2] = x[3];
+ p->y[3][2] = y[3];
+ p->x[3][1] = x[4];
+ p->y[3][1] = y[4];
+ p->x[3][0] = x[5];
+ p->y[3][0] = y[5];
+ p->x[2][0] = x[6];
+ p->y[2][0] = y[6];
+ p->x[1][0] = x[7];
+ p->y[1][0] = y[7];
+ p->x[1][1] = x[8];
+ p->y[1][1] = y[8];
+ p->x[1][2] = x[9];
+ p->y[1][2] = y[9];
+ p->x[2][2] = x[10];
+ p->y[2][2] = y[10];
+ p->x[2][1] = x[11];
+ p->y[2][1] = y[11];
+ for (j = 0; j < nComps; ++j) {
+ p->color[0][0].c[j] = patchesA[nPatchesA-1].color[1][0].c[j];
+ p->color[0][1].c[j] = patchesA[nPatchesA-1].color[0][0].c[j];
+ p->color[1][1].c[j] = c[0][j];
+ p->color[1][0].c[j] = c[1][j];
+ }
+ break;
+ }
+ }
+ ++nPatchesA;
+ bitBuf->flushBits();
+ }
+ delete bitBuf;
+
+ if (typeA == 6) {
+ for (i = 0; i < nPatchesA; ++i) {
+ p = &patchesA[i];
+ p->x[1][1] = (-4 * p->x[0][0]
+ +6 * (p->x[0][1] + p->x[1][0])
+ -2 * (p->x[0][3] + p->x[3][0])
+ +3 * (p->x[3][1] + p->x[1][3])
+ - p->x[3][3]) / 9;
+ p->y[1][1] = (-4 * p->y[0][0]
+ +6 * (p->y[0][1] + p->y[1][0])
+ -2 * (p->y[0][3] + p->y[3][0])
+ +3 * (p->y[3][1] + p->y[1][3])
+ - p->y[3][3]) / 9;
+ p->x[1][2] = (-4 * p->x[0][3]
+ +6 * (p->x[0][2] + p->x[1][3])
+ -2 * (p->x[0][0] + p->x[3][3])
+ +3 * (p->x[3][2] + p->x[1][0])
+ - p->x[3][0]) / 9;
+ p->y[1][2] = (-4 * p->y[0][3]
+ +6 * (p->y[0][2] + p->y[1][3])
+ -2 * (p->y[0][0] + p->y[3][3])
+ +3 * (p->y[3][2] + p->y[1][0])
+ - p->y[3][0]) / 9;
+ p->x[2][1] = (-4 * p->x[3][0]
+ +6 * (p->x[3][1] + p->x[2][0])
+ -2 * (p->x[3][3] + p->x[0][0])
+ +3 * (p->x[0][1] + p->x[2][3])
+ - p->x[0][3]) / 9;
+ p->y[2][1] = (-4 * p->y[3][0]
+ +6 * (p->y[3][1] + p->y[2][0])
+ -2 * (p->y[3][3] + p->y[0][0])
+ +3 * (p->y[0][1] + p->y[2][3])
+ - p->y[0][3]) / 9;
+ p->x[2][2] = (-4 * p->x[3][3]
+ +6 * (p->x[3][2] + p->x[2][3])
+ -2 * (p->x[3][0] + p->x[0][3])
+ +3 * (p->x[0][2] + p->x[2][0])
+ - p->x[0][0]) / 9;
+ p->y[2][2] = (-4 * p->y[3][3]
+ +6 * (p->y[3][2] + p->y[2][3])
+ -2 * (p->y[3][0] + p->y[0][3])
+ +3 * (p->y[0][2] + p->y[2][0])
+ - p->y[0][0]) / 9;
+ }
+ }
+
+ shading = new GfxPatchMeshShading(typeA, patchesA, nPatchesA,
+ funcsA, nFuncsA);
+ if (!shading->init(dict)) {
+ delete shading;
+ return NULL;
+ }
+ return shading;
+
+ err2:
+ obj1.free();
+ err1:
+ return NULL;
+}
+
+GfxShading *GfxPatchMeshShading::copy() {
+ return new GfxPatchMeshShading(this);