diff --git a/src/core/pattern.js b/src/core/pattern.js
index 5a1535ba9..f31da33ee 100644
--- a/src/core/pattern.js
+++ b/src/core/pattern.js
@@ -15,13 +15,18 @@
* limitations under the License.
*/
/* globals ColorSpace, PDFFunction, Util, error, warn, info, isArray, isStream,
- isPDFFunction, UnsupportedManager, UNSUPPORTED_FEATURES */
+ assert, isPDFFunction, UnsupportedManager, UNSUPPORTED_FEATURES */
'use strict';
var PatternType = {
+ FUNCTION_BASED: 1,
AXIAL: 2,
- RADIAL: 3
+ RADIAL: 3,
+ FREE_FORM_MESH: 4,
+ LATTICE_FORM_MESH: 5,
+ COONS_PATCH_MESH: 6,
+ TENSOR_PATCH_MESH: 7
};
var Pattern = (function PatternClosure() {
@@ -49,6 +54,11 @@ var Pattern = (function PatternClosure() {
case PatternType.RADIAL:
// Both radial and axial shadings are handled by RadialAxial shading.
return new Shadings.RadialAxial(dict, matrix, xref, res);
+ case PatternType.FREE_FORM_MESH:
+ case PatternType.LATTICE_FORM_MESH:
+ case PatternType.COONS_PATCH_MESH:
+ case PatternType.TENSOR_PATCH_MESH:
+ return new Shadings.Mesh(shading, matrix, xref, res);
default:
UnsupportedManager.notify(UNSUPPORTED_FEATURES.shadingPattern);
return new Shadings.Dummy();
@@ -213,6 +223,537 @@ Shadings.RadialAxial = (function RadialAxialClosure() {
return RadialAxial;
})();
+// All mesh shading. For now, they will be presented as set of the triangles
+// to be drawn on the canvas and rgb color for each vertex.
+Shadings.Mesh = (function MeshClosure() {
+ function MeshStreamReader(stream, context) {
+ this.stream = stream;
+ this.context = context;
+ this.buffer = 0;
+ this.bufferLength = 0;
+ }
+ MeshStreamReader.prototype = {
+ get hasData() {
+ if (this.stream.end) {
+ return this.stream.pos < this.stream.end;
+ }
+ if (this.bufferLength > 0) {
+ return true;
+ }
+ var nextByte = this.stream.getByte();
+ if (nextByte < 0) {
+ return false;
+ }
+ this.buffer = nextByte;
+ this.bufferLength = 8;
+ return true;
+ },
+ readBits: function MeshStreamReader_readBits(n) {
+ var buffer = this.buffer;
+ var bufferLength = this.bufferLength;
+ if (n === 32) {
+ if (bufferLength === 0) {
+ return ((this.stream.getByte() << 24) |
+ (this.stream.getByte() << 16) | (this.stream.getByte() << 8) |
+ this.stream.getByte()) >>> 0;
+ }
+ buffer = (buffer << 24) | (this.stream.getByte() << 16) |
+ (this.stream.getByte() << 8) | this.stream.getByte();
+ var nextByte = this.stream.getByte();
+ this.buffer = nextByte & ((1 << bufferLength) - 1);
+ return ((buffer << (8 - bufferLength)) |
+ ((nextByte & 0xFF) >> bufferLength)) >>> 0;
+ }
+ if (n === 8 && bufferLength === 0) {
+ return this.stream.getByte();
+ }
+ while (bufferLength < n) {
+ buffer = (buffer << 8) | this.stream.getByte();
+ bufferLength += 8;
+ }
+ bufferLength -= n;
+ this.bufferLength = bufferLength;
+ this.buffer = buffer & ((1 << bufferLength) - 1);
+ return buffer >> bufferLength;
+ },
+ align: function MeshStreamReader_align() {
+ this.buffer = 0;
+ this.bufferLength = 0;
+ },
+ readFlag: function MeshStreamReader_readFlag() {
+ return this.readBits(this.context.bitsPerFlag);
+ },
+ readCoordinate: function MeshStreamReader_readCoordinate() {
+ var bitsPerCoordinate = this.context.bitsPerCoordinate;
+ var xi = this.readBits(bitsPerCoordinate);
+ var yi = this.readBits(bitsPerCoordinate);
+ var decode = this.context.decode;
+ var scale = bitsPerCoordinate < 32 ? 1 / ((1 << bitsPerCoordinate) - 1) :
+ 2.3283064365386963e-10; // 2 ^ -32
+ return [
+ xi * scale * (decode[1] - decode[0]) + decode[0],
+ yi * scale * (decode[3] - decode[2]) + decode[2]
+ ];
+ },
+ readComponents: function MeshStreamReader_readComponents() {
+ var numComps = this.context.numComps;
+ var bitsPerComponent = this.context.bitsPerComponent;
+ var scale = bitsPerComponent < 32 ? 1 / ((1 << bitsPerComponent) - 1) :
+ 2.3283064365386963e-10; // 2 ^ -32
+ var decode = this.context.decode;
+ var components = [];
+ for (var i = 0, j = 4; i < numComps; i++, j += 2) {
+ var ci = this.readBits(bitsPerComponent);
+ components.push(ci * scale * (decode[j + 1] - decode[j]) + decode[j]);
+ }
+ if (this.context.colorFn) {
+ components = this.context.colorFn(components);
+ }
+ return this.context.colorSpace.getRgb(components, 0);
+ }
+ };
+
+ function decodeType4Shading(mesh, reader) {
+ var coords = mesh.coords;
+ var colors = mesh.colors;
+ var operators = [];
+ var ps = []; // not maintaining cs since that will match ps
+ var verticesLeft = 0; // assuming we have all data to start a new triangle
+ while (reader.hasData) {
+ var f = reader.readFlag();
+ var coord = reader.readCoordinate();
+ var color = reader.readComponents();
+ if (verticesLeft === 0) { // ignoring flags if we started a triangle
+ assert(0 <= f && f <= 2, 'Unknown type4 flag');
+ switch (f) {
+ case 0:
+ verticesLeft = 3;
+ break;
+ case 1:
+ ps.push(ps[ps.length - 2], ps[ps.length - 1]);
+ verticesLeft = 1;
+ break;
+ case 2:
+ ps.push(ps[ps.length - 3], ps[ps.length - 1]);
+ verticesLeft = 1;
+ break;
+ }
+ operators.push(f);
+ }
+ ps.push(coords.length);
+ coords.push(coord);
+ colors.push(color);
+ verticesLeft--;
+
+ reader.align();
+ }
+
+ var psPacked = new Int32Array(ps);
+
+ mesh.figures.push({
+ type: 'triangles',
+ coords: psPacked,
+ colors: psPacked
+ });
+ }
+
+ function decodeType5Shading(mesh, reader, verticesPerRow) {
+ var coords = mesh.coords;
+ var colors = mesh.colors;
+ var operators = [];
+ var ps = []; // not maintaining cs since that will match ps
+ while (reader.hasData) {
+ var coord = reader.readCoordinate();
+ var color = reader.readComponents();
+ ps.push(coords.length);
+ coords.push(coord);
+ colors.push(color);
+ }
+
+ var psPacked = new Int32Array(ps);
+
+ mesh.figures.push({
+ type: 'lattice',
+ coords: psPacked,
+ colors: psPacked,
+ verticesPerRow: verticesPerRow
+ });
+ }
+
+ var SPLIT_PATCH_CHUNKS_AMOUNT = 4;
+ var B = (function buildB() {
+ var lut = [];
+ for (var i = 0; i <= SPLIT_PATCH_CHUNKS_AMOUNT; i++) {
+ var t = i / SPLIT_PATCH_CHUNKS_AMOUNT, t_ = 1 - t;
+ lut.push(new Float32Array([t_ * t_ * t_, 3 * t * t_ * t_,
+ 3 * t * t * t_, t * t * t]));
+ }
+ return lut;
+ })();
+
+ function buildFigureFromPatch(mesh, pi, ci) {
+ if (SPLIT_PATCH_CHUNKS_AMOUNT < 3) {
+ mesh.figures.push({
+ type: 'lattice',
+ coords: new Int32Array([pi[0], pi[3], pi[12], pi[15]]),
+ colors: new Int32Array(ci),
+ verticesPerRow: 2
+ });
+ return;
+ }
+
+ var coords = mesh.coords, colors = mesh.colors;
+ var verticesPerRow = SPLIT_PATCH_CHUNKS_AMOUNT + 1;
+ var figureCoords = new Int32Array((SPLIT_PATCH_CHUNKS_AMOUNT + 1) *
+ verticesPerRow);
+ var figureColors = new Int32Array((SPLIT_PATCH_CHUNKS_AMOUNT + 1) *
+ verticesPerRow);
+ var k = 0;
+ var cl = new Uint8Array(3), cr = new Uint8Array(3);
+ var c0 = colors[ci[0]], c1 = colors[ci[1]],
+ c2 = colors[ci[2]], c3 = colors[ci[3]];
+ for (var row = 0; row <= SPLIT_PATCH_CHUNKS_AMOUNT; row++) {
+ cl[0] = ((c0[0] * (SPLIT_PATCH_CHUNKS_AMOUNT - row) +
+ c2[0] * row) / SPLIT_PATCH_CHUNKS_AMOUNT) | 0;
+ cl[1] = ((c0[1] * (SPLIT_PATCH_CHUNKS_AMOUNT - row) +
+ c2[1] * row) / SPLIT_PATCH_CHUNKS_AMOUNT) | 0;
+ cl[2] = ((c0[2] * (SPLIT_PATCH_CHUNKS_AMOUNT - row) +
+ c2[2] * row) / SPLIT_PATCH_CHUNKS_AMOUNT) | 0;
+
+ cr[0] = ((c1[0] * (SPLIT_PATCH_CHUNKS_AMOUNT - row) +
+ c3[0] * row) / SPLIT_PATCH_CHUNKS_AMOUNT) | 0;
+ cr[1] = ((c1[1] * (SPLIT_PATCH_CHUNKS_AMOUNT - row) +
+ c3[1] * row) / SPLIT_PATCH_CHUNKS_AMOUNT) | 0;
+ cr[2] = ((c1[2] * (SPLIT_PATCH_CHUNKS_AMOUNT - row) +
+ c3[2] * row) / SPLIT_PATCH_CHUNKS_AMOUNT) | 0;
+
+ for (var col = 0; col <= SPLIT_PATCH_CHUNKS_AMOUNT; col++, k++) {
+ if ((row === 0 || row === SPLIT_PATCH_CHUNKS_AMOUNT) &&
+ (col === 0 || col === SPLIT_PATCH_CHUNKS_AMOUNT)) {
+ continue;
+ }
+ var x = 0, y = 0;
+ var q = 0;
+ for (var i = 0; i <= 3; i++) {
+ for (var j = 0; j <= 3; j++, q++) {
+ var m = B[row][i] * B[col][j];
+ x += coords[pi[q]][0] * m;
+ y += coords[pi[q]][1] * m;
+ }
+ }
+ figureCoords[k] = coords.length;
+ coords.push([x, y]);
+ figureColors[k] = colors.length;
+ var newColor = new Uint8Array(3);
+ newColor[0] = ((cl[0] * (SPLIT_PATCH_CHUNKS_AMOUNT - col) +
+ cr[0] * col) / SPLIT_PATCH_CHUNKS_AMOUNT) | 0;
+ newColor[1] = ((cl[1] * (SPLIT_PATCH_CHUNKS_AMOUNT - col) +
+ cr[1] * col) / SPLIT_PATCH_CHUNKS_AMOUNT) | 0;
+ newColor[2] = ((cl[2] * (SPLIT_PATCH_CHUNKS_AMOUNT - col) +
+ cr[2] * col) / SPLIT_PATCH_CHUNKS_AMOUNT) | 0;
+ colors.push(newColor);
+ }
+ }
+ figureCoords[0] = pi[0];
+ figureColors[0] = ci[0];
+ figureCoords[SPLIT_PATCH_CHUNKS_AMOUNT] = pi[3];
+ figureColors[SPLIT_PATCH_CHUNKS_AMOUNT] = ci[1];
+ figureCoords[verticesPerRow * SPLIT_PATCH_CHUNKS_AMOUNT] = pi[12];
+ figureColors[verticesPerRow * SPLIT_PATCH_CHUNKS_AMOUNT] = ci[2];
+ figureCoords[verticesPerRow * verticesPerRow - 1] = pi[15];
+ figureColors[verticesPerRow * verticesPerRow - 1] = ci[3];
+
+ mesh.figures.push({
+ type: 'lattice',
+ coords: figureCoords,
+ colors: figureColors,
+ verticesPerRow: verticesPerRow
+ });
+ }
+
+ function decodeType6Shading(mesh, reader) {
+ // A special case of Type 7. The p11, p12, p21, p22 automatically filled
+ var coords = mesh.coords;
+ var colors = mesh.colors;
+ var ps = new Int32Array(16); // p00, p10, ..., p30, p01, ..., p33
+ var cs = new Int32Array(4); // c00, c30, c03, c33
+ while (reader.hasData) {
+ var f = reader.readFlag();
+ assert(0 <= f && f <= 3, 'Unknown type6 flag');
+ var i, ii;
+ var pi = coords.length;
+ for (i = 0, ii = (f !== 0 ? 8 : 12); i < ii; i++) {
+ coords.push(reader.readCoordinate());
+ }
+ var ci = colors.length;
+ for (i = 0, ii = (f !== 0 ? 2 : 4); i < ii; i++) {
+ colors.push(reader.readComponents());
+ }
+ var tmp1, tmp2, tmp3, tmp4;
+ switch (f) {
+ case 0:
+ ps[12] = pi + 3; ps[13] = pi + 4; ps[14] = pi + 5; ps[15] = pi + 6;
+ ps[ 8] = pi + 2; /* values for 5, 6, 9, 10 are */ ps[11] = pi + 7;
+ ps[ 4] = pi + 1; /* calculated below */ ps[ 7] = pi + 8;
+ ps[ 0] = pi; ps[ 1] = pi + 11; ps[ 2] = pi + 10; ps[ 3] = pi + 9;
+ cs[2] = ci + 1; cs[3] = ci + 2;
+ cs[0] = ci; cs[1] = ci + 3;
+ break;
+ case 1:
+ tmp1 = ps[12]; tmp2 = ps[13]; tmp3 = ps[14]; tmp4 = ps[15];
+ ps[12] = pi + 5; ps[13] = pi + 4; ps[14] = pi + 3; ps[15] = pi + 2;
+ ps[ 8] = pi + 6; /* values for 5, 6, 9, 10 are */ ps[11] = pi + 1;
+ ps[ 4] = pi + 7; /* calculated below */ ps[ 7] = pi;
+ ps[ 0] = tmp1; ps[ 1] = tmp2; ps[ 2] = tmp3; ps[ 3] = tmp4;
+ tmp1 = cs[2]; tmp2 = cs[3];
+ cs[2] = ci + 1; cs[3] = ci;
+ cs[0] = tmp1; cs[1] = tmp2;
+ break;
+ case 2:
+ ps[12] = ps[15]; ps[13] = pi + 7; ps[14] = pi + 6; ps[15] = pi + 5;
+ ps[ 8] = ps[11]; /* values for 5, 6, 9, 10 are */ ps[11] = pi + 4;
+ ps[ 4] = ps[7]; /* calculated below */ ps[ 7] = pi + 3;
+ ps[ 0] = ps[3]; ps[ 1] = pi; ps[ 2] = pi + 1; ps[ 3] = pi + 2;
+ cs[2] = cs[3]; cs[3] = ci + 1;
+ cs[0] = cs[1]; cs[1] = ci;
+ break;
+ case 3:
+ ps[12] = ps[0]; ps[13] = ps[1]; ps[14] = ps[2]; ps[15] = ps[3];
+ ps[ 8] = pi; /* values for 5, 6, 9, 10 are */ ps[11] = pi + 7;
+ ps[ 4] = pi + 1; /* calculated below */ ps[ 7] = pi + 6;
+ ps[ 0] = pi + 2; ps[ 1] = pi + 3; ps[ 2] = pi + 4; ps[ 3] = pi + 5;
+ cs[2] = cs[0]; cs[3] = cs[1];
+ cs[0] = ci; cs[1] = ci + 1;
+ break;
+ }
+ // set p11, p12, p21, p22
+ ps[5] = coords.length;
+ coords.push([
+ (-4 * coords[ps[0]][0] - coords[ps[15]][0] +
+ 6 * (coords[ps[4]][0] + coords[ps[1]][0]) -
+ 2 * (coords[ps[12]][0] + coords[ps[3]][0]) +
+ 3 * (coords[ps[13]][0] + coords[ps[7]][0])) / 9,
+ (-4 * coords[ps[0]][1] - coords[ps[15]][1] +
+ 6 * (coords[ps[4]][1] + coords[ps[1]][1]) -
+ 2 * (coords[ps[12]][1] + coords[ps[3]][1]) +
+ 3 * (coords[ps[13]][1] + coords[ps[7]][1])) / 9
+ ]);
+ ps[6] = coords.length;
+ coords.push([
+ (-4 * coords[ps[3]][0] - coords[ps[12]][0] +
+ 6 * (coords[ps[2]][0] + coords[ps[7]][0]) -
+ 2 * (coords[ps[0]][0] + coords[ps[15]][0]) +
+ 3 * (coords[ps[4]][0] + coords[ps[14]][0])) / 9,
+ (-4 * coords[ps[3]][1] - coords[ps[12]][1] +
+ 6 * (coords[ps[2]][1] + coords[ps[7]][1]) -
+ 2 * (coords[ps[0]][1] + coords[ps[15]][1]) +
+ 3 * (coords[ps[4]][1] + coords[ps[14]][1])) / 9
+ ]);
+ ps[9] = coords.length;
+ coords.push([
+ (-4 * coords[ps[12]][0] - coords[ps[3]][0] +
+ 6 * (coords[ps[8]][0] + coords[ps[13]][0]) -
+ 2 * (coords[ps[0]][0] + coords[ps[15]][0]) +
+ 3 * (coords[ps[11]][0] + coords[ps[1]][0])) / 9,
+ (-4 * coords[ps[12]][1] - coords[ps[3]][1] +
+ 6 * (coords[ps[8]][1] + coords[ps[13]][1]) -
+ 2 * (coords[ps[0]][1] + coords[ps[15]][1]) +
+ 3 * (coords[ps[11]][1] + coords[ps[1]][1])) / 9
+ ]);
+ ps[10] = coords.length;
+ coords.push([
+ (-4 * coords[ps[15]][0] - coords[ps[0]][0] +
+ 6 * (coords[ps[11]][0] + coords[ps[14]][0]) -
+ 2 * (coords[ps[12]][0] + coords[ps[3]][0]) +
+ 3 * (coords[ps[2]][0] + coords[ps[8]][0])) / 9,
+ (-4 * coords[ps[15]][1] - coords[ps[0]][1] +
+ 6 * (coords[ps[11]][1] + coords[ps[14]][1]) -
+ 2 * (coords[ps[12]][1] + coords[ps[3]][1]) +
+ 3 * (coords[ps[2]][1] + coords[ps[8]][1])) / 9
+ ]);
+ buildFigureFromPatch(mesh, ps, cs);
+ }
+ }
+
+ function decodeType7Shading(mesh, reader) {
+ var coords = mesh.coords;
+ var colors = mesh.colors;
+ var ps = new Int32Array(16); // p00, p10, ..., p30, p01, ..., p33
+ var cs = new Int32Array(4); // c00, c30, c03, c33
+ while (reader.hasData) {
+ var f = reader.readFlag();
+ assert(0 <= f && f <= 3, 'Unknown type7 flag');
+ var i, ii;
+ var pi = coords.length;
+ for (i = 0, ii = (f !== 0 ? 12 : 16); i < ii; i++) {
+ coords.push(reader.readCoordinate());
+ }
+ var ci = colors.length;
+ for (i = 0, ii = (f !== 0 ? 2 : 4); i < ii; i++) {
+ colors.push(reader.readComponents());
+ }
+ var tmp1, tmp2, tmp3, tmp4;
+ switch (f) {
+ case 0:
+ ps[12] = pi + 3; ps[13] = pi + 4; ps[14] = pi + 5; ps[15] = pi + 6;
+ ps[ 8] = pi + 2; ps[ 9] = pi + 13; ps[10] = pi + 14; ps[11] = pi + 7;
+ ps[ 4] = pi + 1; ps[ 5] = pi + 12; ps[ 6] = pi + 15; ps[ 7] = pi + 8;
+ ps[ 0] = pi; ps[ 1] = pi + 11; ps[ 2] = pi + 10; ps[ 3] = pi + 9;
+ cs[2] = ci + 1; cs[3] = ci + 2;
+ cs[0] = ci; cs[1] = ci + 3;
+ break;
+ case 1:
+ tmp1 = ps[12]; tmp2 = ps[13]; tmp3 = ps[14]; tmp4 = ps[15];
+ ps[12] = pi + 5; ps[13] = pi + 4; ps[14] = pi + 3; ps[15] = pi + 2;
+ ps[ 8] = pi + 6; ps[ 9] = pi + 11; ps[10] = pi + 10; ps[11] = pi + 1;
+ ps[ 4] = pi + 7; ps[ 5] = pi + 8; ps[ 6] = pi + 9; ps[ 7] = pi;
+ ps[ 0] = tmp1; ps[ 1] = tmp2; ps[ 2] = tmp3; ps[ 3] = tmp4;
+ tmp1 = cs[2]; tmp2 = cs[3];
+ cs[2] = ci + 1; cs[3] = ci;
+ cs[0] = tmp1; cs[1] = tmp2;
+ break;
+ case 2:
+ ps[12] = ps[15]; ps[13] = pi + 7; ps[14] = pi + 6; ps[15] = pi + 5;
+ ps[ 8] = ps[11]; ps[ 9] = pi + 8; ps[10] = pi + 11; ps[11] = pi + 4;
+ ps[ 4] = ps[7]; ps[ 5] = pi + 9; ps[ 6] = pi + 10; ps[ 7] = pi + 3;
+ ps[ 0] = ps[3]; ps[ 1] = pi; ps[ 2] = pi + 1; ps[ 3] = pi + 2;
+ cs[2] = cs[3]; cs[3] = ci + 1;
+ cs[0] = cs[1]; cs[1] = ci;
+ break;
+ case 3:
+ ps[12] = ps[0]; ps[13] = ps[1]; ps[14] = ps[2]; ps[15] = ps[3];
+ ps[ 8] = pi; ps[ 9] = pi + 9; ps[10] = pi + 8; ps[11] = pi + 7;
+ ps[ 4] = pi + 1; ps[ 5] = pi + 10; ps[ 6] = pi + 11; ps[ 7] = pi + 6;
+ ps[ 0] = pi + 2; ps[ 1] = pi + 3; ps[ 2] = pi + 4; ps[ 3] = pi + 5;
+ cs[2] = cs[0]; cs[3] = cs[1];
+ cs[0] = ci; cs[1] = ci + 1;
+ break;
+ }
+ buildFigureFromPatch(mesh, ps, cs);
+ }
+ }
+
+ function Mesh(stream, matrix, xref, res) {
+ assert(isStream(stream), 'Mesh data is not a stream');
+ var dict = stream.dict;
+ this.matrix = matrix;
+ this.shadingType = dict.get('ShadingType');
+ this.type = 'Pattern';
+ this.bbox = dict.get('BBox');
+ var cs = dict.get('ColorSpace', 'CS');
+ cs = ColorSpace.parse(cs, xref, res);
+ this.cs = cs;
+ this.background = dict.has('Background') ?
+ cs.getRgb(dict.get('Background'), 0) : null;
+
+ var fnObj = dict.get('Function');
+ var fn;
+ if (!fnObj) {
+ fn = null;
+ } else if (isArray(fnObj)) {
+ var fnArray = [];
+ for (var j = 0, jj = fnObj.length; j < jj; j++) {
+ var obj = xref.fetchIfRef(fnObj[j]);
+ if (!isPDFFunction(obj)) {
+ error('Invalid function');
+ }
+ fnArray.push(PDFFunction.parse(xref, obj));
+ }
+ fn = function radialAxialColorFunction(arg) {
+ var out = [];
+ for (var i = 0, ii = fnArray.length; i < ii; i++) {
+ out.push(fnArray[i](arg)[0]);
+ }
+ return out;
+ };
+ } else {
+ if (!isPDFFunction(fnObj)) {
+ error('Invalid function');
+ }
+ fn = PDFFunction.parse(xref, fnObj);
+ }
+
+ this.coords = [];
+ this.colors = [];
+ this.figures = [];
+
+ var decodeContext = {
+ bitsPerCoordinate: dict.get('BitsPerCoordinate'),
+ bitsPerComponent: dict.get('BitsPerComponent'),
+ bitsPerFlag: dict.get('BitsPerFlag'),
+ decode: dict.get('Decode'),
+ colorFn: fn,
+ colorSpace: cs,
+ numComps: fn ? 1 : cs.numComps
+ };
+ var reader = new MeshStreamReader(stream, decodeContext);
+
+ switch (this.shadingType) {
+ case PatternType.FREE_FORM_MESH:
+ decodeType4Shading(this, reader);
+ break;
+ case PatternType.LATTICE_FORM_MESH:
+ var verticesPerRow = dict.get('VerticesPerRow') | 0;
+ assert(verticesPerRow >= 2, 'Invalid VerticesPerRow');
+ decodeType5Shading(this, reader, verticesPerRow);
+ break;
+ case PatternType.COONS_PATCH_MESH:
+ decodeType6Shading(this, reader);
+ break;
+ case PatternType.TENSOR_PATCH_MESH:
+ decodeType7Shading(this, reader);
+ break;
+ default:
+ error('Unsupported mesh type.');
+ break;
+ }
+
+ // calculate bounds
+ var minX = this.coords[0][0], minY = this.coords[0][1],
+ maxX = minX, maxY = minY;
+ for (var i = 1, ii = this.coords.length; i < ii; i++) {
+ var x = this.coords[i][0], y = this.coords[i][1];
+ minX = minX > x ? x : minX;
+ minY = minY > y ? y : minY;
+ maxX = maxX < x ? x : maxX;
+ maxY = maxY < y ? y : maxY;
+ }
+ this.bounds = [minX, minY, maxX, maxY];
+ }
+
+ Mesh.prototype = {
+ getIR: function Mesh_getIR() {
+ var type = this.shadingType;
+ var i, ii, j;
+ var coords = this.coords;
+ var coordsPacked = new Float32Array(coords.length * 2);
+ for (i = 0, j = 0, ii = coords.length; i < ii; i++) {
+ var xy = coords[i];
+ coordsPacked[j++] = xy[0];
+ coordsPacked[j++] = xy[1];
+ }
+ var colors = this.colors;
+ var colorsPacked = new Uint8Array(colors.length * 3);
+ for (i = 0, j = 0, ii = colors.length; i < ii; i++) {
+ var c = colors[i];
+ colorsPacked[j++] = c[0];
+ colorsPacked[j++] = c[1];
+ colorsPacked[j++] = c[2];
+ }
+ var figures = this.figures;
+ var bbox = this.bbox;
+ var bounds = this.bounds;
+ var matrix = this.matrix;
+ var background = this.background;
+
+ return ['Mesh', type, coordsPacked, colorsPacked, figures, bounds,
+ matrix, bbox, background];
+ }
+ };
+
+ return Mesh;
+})();
+
Shadings.Dummy = (function DummyClosure() {
function Dummy() {
this.type = 'Pattern';
diff --git a/src/display/canvas.js b/src/display/canvas.js
index d5ddb496a..581aa7baf 100644
--- a/src/display/canvas.js
+++ b/src/display/canvas.js
@@ -619,10 +619,12 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
}
var transform = viewport.transform;
- this.baseTransform = transform.slice();
+
this.ctx.save();
this.ctx.transform.apply(this.ctx, transform);
+ this.baseTransform = this.ctx.mozCurrentTransform.slice();
+
if (this.textLayer) {
this.textLayer.beginLayout();
}
@@ -1498,10 +1500,8 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
}
var pattern = new TilingPattern(IR, color, this.ctx, this.objs,
this.commonObjs, this.baseTransform);
- } else if (IR[0] == 'RadialAxial' || IR[0] == 'Dummy') {
- var pattern = getShadingPatternFromIR(IR);
} else {
- error('Unkown IR type ' + IR[0]);
+ var pattern = getShadingPatternFromIR(IR);
}
return pattern;
},
@@ -1582,7 +1582,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
this.save();
var pattern = getShadingPatternFromIR(patternIR);
- ctx.fillStyle = pattern.getPattern(ctx, this);
+ ctx.fillStyle = pattern.getPattern(ctx, this, true);
var inv = ctx.mozCurrentTransformInverse;
if (inv) {
diff --git a/src/display/pattern_helper.js b/src/display/pattern_helper.js
index ee20fa130..4c1dc9539 100644
--- a/src/display/pattern_helper.js
+++ b/src/display/pattern_helper.js
@@ -15,7 +15,7 @@
* limitations under the License.
*/
/* globals CanvasGraphics, CachedCanvases, ColorSpace, Util, error, info,
- isArray */
+ isArray, makeCssRgb */
'use strict';
@@ -49,6 +49,186 @@ ShadingIRs.RadialAxial = {
}
};
+var createMeshCanvas = (function createMeshCanvasClosure() {
+ function drawTriangle(data, context, p1, p2, p3, c1, c2, c3) {
+ // Very basic Gouraud-shaded triangle rasterization algorithm.
+ var coords = context.coords, colors = context.colors;
+ var bytes = data.data, rowSize = data.width * 4;
+ var tmp;
+ if (coords[p1 * 2 + 1] > coords[p2 * 2 + 1]) {
+ tmp = p1; p1 = p2; p2 = tmp; tmp = c1; c1 = c2; c2 = tmp;
+ }
+ if (coords[p2 * 2 + 1] > coords[p3 * 2 + 1]) {
+ tmp = p2; p2 = p3; p3 = tmp; tmp = c2; c2 = c3; c3 = tmp;
+ }
+ if (coords[p1 * 2 + 1] > coords[p2 * 2 + 1]) {
+ tmp = p1; p1 = p2; p2 = tmp; tmp = c1; c1 = c2; c2 = tmp;
+ }
+ var x1 = (coords[p1 * 2] + context.offsetX) * context.scaleX;
+ var y1 = (coords[p1 * 2 + 1] + context.offsetY) * context.scaleY;
+ var x2 = (coords[p2 * 2] + context.offsetX) * context.scaleX;
+ var y2 = (coords[p2 * 2 + 1] + context.offsetY) * context.scaleY;
+ var x3 = (coords[p3 * 2] + context.offsetX) * context.scaleX;
+ var y3 = (coords[p3 * 2 + 1] + context.offsetY) * context.scaleY;
+ if (y1 >= y3) {
+ return;
+ }
+ var c1i = c1 * 3, c2i = c2 * 3, c3i = c3 * 3;
+ var c1r = colors[c1i], c1g = colors[c1i + 1], c1b = colors[c1i + 2];
+ var c2r = colors[c2i], c2g = colors[c2i + 1], c2b = colors[c2i + 2];
+ var c3r = colors[c3i], c3g = colors[c3i + 1], c3b = colors[c3i + 2];
+
+ var minY = Math.round(y1), maxY = Math.round(y3);
+ var xa, car, cag, cab;
+ var xb, cbr, cbg, cbb;
+ var k;
+ for (var y = minY; y <= maxY; y++) {
+ if (y < y2) {
+ k = y < y1 ? 0 : y1 === y2 ? 1 : (y1 - y) / (y1 - y2);
+ xa = x1 - (x1 - x2) * k;
+ car = c1r - (c1r - c2r) * k;
+ cag = c1g - (c1g - c2g) * k;
+ cab = c1b - (c1b - c2b) * k;
+ } else {
+ k = y > y3 ? 1 : y2 === y3 ? 0 : (y2 - y) / (y2 - y3);
+ xa = x2 - (x2 - x3) * k;
+ car = c2r - (c2r - c3r) * k;
+ cag = c2g - (c2g - c3g) * k;
+ cab = c2b - (c2b - c3b) * k;
+ }
+ k = y < y1 ? 0 : y > y3 ? 1 : (y1 - y) / (y1 - y3);
+ xb = x1 - (x1 - x3) * k;
+ cbr = c1r - (c1r - c3r) * k;
+ cbg = c1g - (c1g - c3g) * k;
+ cbb = c1b - (c1b - c3b) * k;
+ var x1_ = Math.round(Math.min(xa, xb));
+ var x2_ = Math.round(Math.max(xa, xb));
+ var j = rowSize * y + x1_ * 4;
+ for (var x = x1_; x <= x2_; x++) {
+ k = (xa - x) / (xa - xb);
+ k = k < 0 ? 0 : k > 1 ? 1 : k;
+ bytes[j++] = (car - (car - cbr) * k) | 0;
+ bytes[j++] = (cag - (cag - cbg) * k) | 0;
+ bytes[j++] = (cab - (cab - cbb) * k) | 0;
+ bytes[j++] = 255;
+ }
+ }
+ }
+
+ function drawFigure(data, figure, context) {
+ var ps = figure.coords;
+ var cs = figure.colors;
+ switch (figure.type) {
+ case 'lattice':
+ var verticesPerRow = figure.verticesPerRow;
+ var rows = Math.floor(ps.length / verticesPerRow) - 1;
+ var cols = verticesPerRow - 1;
+ for (var i = 0; i < rows; i++) {
+ var q = i * verticesPerRow;
+ for (var j = 0; j < cols; j++, q++) {
+ drawTriangle(data, context,
+ ps[q], ps[q + 1], ps[q + verticesPerRow],
+ cs[q], cs[q + 1], cs[q + verticesPerRow]);
+ drawTriangle(data, context,
+ ps[q + verticesPerRow + 1], ps[q + 1], ps[q + verticesPerRow],
+ cs[q + verticesPerRow + 1], cs[q + 1], cs[q + verticesPerRow]);
+ }
+ }
+ break;
+ case 'triangles':
+ for (var i = 0, ii = ps.length; i < ii; i += 3) {
+ drawTriangle(data, context,
+ ps[i], ps[i + 1], ps[i + 2],
+ cs[i], cs[i + 1], cs[i + 2]);
+ }
+ break;
+ default:
+ error('illigal figure');
+ break;
+ }
+ }
+
+ function createMeshCanvas(owner, bounds, coords, colors, figures,
+ backgroundColor) {
+ // we will increase scale on some weird factor to let antialiasing take
+ // care of "rough" edges
+ var EXPECTED_SCALE = 1.5;
+ // MAX_PATTERN_SIZE is used to avoid OOM situation.
+ var MAX_PATTERN_SIZE = 3000; // 10in @ 300dpi shall be enough
+
+ var boundsWidth = bounds[2] - bounds[0];
+ var boundsHeight = bounds[3] - bounds[1];
+
+ var width = Math.min(Math.ceil(Math.abs(boundsWidth * EXPECTED_SCALE)),
+ MAX_PATTERN_SIZE);
+ var height = Math.min(Math.ceil(Math.abs(boundsHeight * EXPECTED_SCALE)),
+ MAX_PATTERN_SIZE);
+ var scaleX = width / boundsWidth;
+ var scaleY = height / boundsHeight;
+
+ var tmpCanvas = CachedCanvases.getCanvas('mesh', width, height, false);
+ var tmpCtx = tmpCanvas.context;
+ if (backgroundColor) {
+ tmpCtx.fillStyle = makeCssRgb(backgroundColor);
+ tmpCtx.fillRect(0, 0, width, height);
+ }
+
+ var context = {
+ coords: coords,
+ colors: colors,
+ offsetX: -bounds[0],
+ offsetY: -bounds[1],
+ scaleX: scaleX,
+ scaleY: scaleY
+ };
+
+ var data = tmpCtx.getImageData(0, 0, width, height);
+ for (var i = 0; i < figures.length; i++) {
+ drawFigure(data, figures[i], context);
+ }
+ tmpCtx.putImageData(data, 0, 0);
+
+ return {canvas: tmpCanvas.canvas, scaleX: 1 / scaleX, scaleY: 1 / scaleY};
+ }
+ return createMeshCanvas;
+})();
+
+ShadingIRs.Mesh = {
+ fromIR: function Mesh_fromIR(raw) {
+ var type = raw[1];
+ var coords = raw[2];
+ var colors = raw[3];
+ var figures = raw[4];
+ var bounds = raw[5];
+ var matrix = raw[6];
+ var bbox = raw[7];
+ var background = raw[8];
+ return {
+ type: 'Pattern',
+ getPattern: function Mesh_getPattern(ctx, owner, shadingFill) {
+ // Rasterizing on the main thread since sending/queue large canvases
+ // might cause OOM.
+ // TODO consider using WebGL or asm.js to perform rasterization
+ var temporaryPatternCanvas = createMeshCanvas(owner, bounds,
+ coords, colors, figures, shadingFill ? null : background);
+
+ if (!shadingFill) {
+ ctx.setTransform.apply(ctx, owner.baseTransform);
+ if (matrix) {
+ ctx.transform.apply(ctx, matrix);
+ }
+ }
+
+ ctx.translate(bounds[0], bounds[1]);
+ ctx.scale(temporaryPatternCanvas.scaleX,
+ temporaryPatternCanvas.scaleY);
+
+ return ctx.createPattern(temporaryPatternCanvas.canvas, 'no-repeat');
+ }
+ };
+ }
+};
+
ShadingIRs.Dummy = {
fromIR: function Dummy_fromIR() {
return {
@@ -61,7 +241,11 @@ ShadingIRs.Dummy = {
};
function getShadingPatternFromIR(raw) {
- return ShadingIRs[raw[0]].fromIR(raw);
+ var shadingIR = ShadingIRs[raw[0]];
+ if (!shadingIR) {
+ error('Unknown IR type: ' + raw[0]);
+ }
+ return shadingIR.fromIR(raw);
}
var TilingPattern = (function TilingPatternClosure() {
diff --git a/test/pdfs/.gitignore b/test/pdfs/.gitignore
index 2d5aa76a7..0489087bf 100644
--- a/test/pdfs/.gitignore
+++ b/test/pdfs/.gitignore
@@ -41,6 +41,7 @@
!type4psfunc.pdf
!issue1350.pdf
!S2.pdf
+!personwithdog.pdf
!helloworld-bad.pdf
!zerowidthline.pdf
!bug868745.pdf
diff --git a/test/pdfs/personwithdog.pdf b/test/pdfs/personwithdog.pdf
new file mode 100755
index 000000000..11fca9aaa
--- /dev/null
+++ b/test/pdfs/personwithdog.pdf
@@ -0,0 +1,2846 @@
+%PDF-1.5
%
+1 0 obj
<>/OCGs[5 0 R]>>/Pages 3 0 R/Type/Catalog>>
endobj
2 0 obj
<>stream
+
+
+
+
+ application/pdf
+
+
+ personwithdog
+
+
+
+
+ 2013-06-13T09:42:13-05:00
+ 2013-06-13T09:42:13-05:00
+ 2013-06-13T09:42:13-05:00
+ Adobe Illustrator CS6 (Macintosh)
+
+
+
+ 216
+ 256
+ JPEG
+ /9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA
AQBIAAAAAQAB/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoK
DBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8f
Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgBAADYAwER
AAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAA
AQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPB
UtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE
1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZ
qbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEy
obHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp
0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo
+DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8A9U4q7FXYq7FXYq7FXYq7
FXYq7FXYq7FXYq7FVC+vrPT7Oa9vZktrS2QyTzyEKiIoqWYnCBavmvz7/wA5H+YdZuZdO8kodO0x
SV/Ssig3MoFQTGrVWJD22L96r0zMx6cD6mBk86fRta16f61rF9PqFyxFZbqR7hjQUA5OSdu2Xihy
Yo238h3lqwns3ltJx/dyRMYmFPBweQ+g4k2tsy8u/nL+Ynky5SLXvU8xaENpfVJN3GvQvHO1S9K7
iStexGVTwRly2LISfRflbzTofmjRYNZ0W5W5srgbEbMjj7Uci9Vde4OYUomJos02yKuxV2KuxV2K
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
+
+
+
+
+
+ uuid:cd506565-a895-dd46-89c1-85e7ef227c3d
+ xmp.did:0280117407206811822AE0A975F682F6
+ uuid:5D20892493BFDB11914A8590D31508C8
+ proof:pdf
+
+ uuid:ba5dc92b-6d0a-484a-ab90-b9370a4a0965
+ xmp.did:0980117407206811822A897E387FE54C
+ uuid:5D20892493BFDB11914A8590D31508C8
+ proof:pdf
+
+
+
+
+ saved
+ xmp.iid:0280117407206811822AE0A975F682F6
+ 2013-06-13T09:42:12-05:00
+ Adobe Illustrator CS6 (Macintosh)
+ /
+
+
+
+
+
+ Print
+
+
+ False
+ True
+ 1
+
+ 612.000000
+ 792.000000
+ Points
+
+
+
+ Cyan
+ Magenta
+ Yellow
+ Black
+
+
+
+
+
+ Default Swatch Group
+ 0
+
+
+
+ White
+ CMYK
+ PROCESS
+ 0.000000
+ 0.000000
+ 0.000000
+ 0.000000
+
+
+ Black
+ CMYK
+ PROCESS
+ 0.000000
+ 0.000000
+ 0.000000
+ 100.000000
+
+
+ CMYK Red
+ CMYK
+ PROCESS
+ 0.000000
+ 100.000000
+ 100.000000
+ 0.000000
+
+
+ CMYK Yellow
+ CMYK
+ PROCESS
+ 0.000000
+ 0.000000
+ 100.000000
+ 0.000000
+
+
+ CMYK Green
+ CMYK
+ PROCESS
+ 100.000000
+ 0.000000
+ 100.000000
+ 0.000000
+
+
+ CMYK Cyan
+ CMYK
+ PROCESS
+ 100.000000
+ 0.000000
+ 0.000000
+ 0.000000
+
+
+ CMYK Blue
+ CMYK
+ PROCESS
+ 100.000000
+ 100.000000
+ 0.000000
+ 0.000000
+
+
+ CMYK Magenta
+ CMYK
+ PROCESS
+ 0.000000
+ 100.000000
+ 0.000000
+ 0.000000
+
+
+ C=15 M=100 Y=90 K=10
+ CMYK
+ PROCESS
+ 14.999998
+ 100.000000
+ 90.000000
+ 10.000002
+
+
+ C=0 M=90 Y=85 K=0
+ CMYK
+ PROCESS
+ 0.000000
+ 90.000000
+ 85.000000
+ 0.000000
+
+
+ C=0 M=80 Y=95 K=0
+ CMYK
+ PROCESS
+ 0.000000
+ 80.000000
+ 95.000000
+ 0.000000
+
+
+ C=0 M=50 Y=100 K=0
+ CMYK
+ PROCESS
+ 0.000000
+ 50.000000
+ 100.000000
+ 0.000000
+
+
+ C=0 M=35 Y=85 K=0
+ CMYK
+ PROCESS
+ 0.000000
+ 35.000004
+ 85.000000
+ 0.000000
+
+
+ C=5 M=0 Y=90 K=0
+ CMYK
+ PROCESS
+ 5.000001
+ 0.000000
+ 90.000000
+ 0.000000
+
+
+ C=20 M=0 Y=100 K=0
+ CMYK
+ PROCESS
+ 19.999998
+ 0.000000
+ 100.000000
+ 0.000000
+
+
+ C=50 M=0 Y=100 K=0
+ CMYK
+ PROCESS
+ 50.000000
+ 0.000000
+ 100.000000
+ 0.000000
+
+
+ C=75 M=0 Y=100 K=0
+ CMYK
+ PROCESS
+ 75.000000
+ 0.000000
+ 100.000000
+ 0.000000
+
+
+ C=85 M=10 Y=100 K=10
+ CMYK
+ PROCESS
+ 85.000000
+ 10.000002
+ 100.000000
+ 10.000002
+
+
+ C=90 M=30 Y=95 K=30
+ CMYK
+ PROCESS
+ 90.000000
+ 30.000002
+ 95.000000
+ 30.000002
+
+
+ C=75 M=0 Y=75 K=0
+ CMYK
+ PROCESS
+ 75.000000
+ 0.000000
+ 75.000000
+ 0.000000
+
+
+ C=80 M=10 Y=45 K=0
+ CMYK
+ PROCESS
+ 80.000000
+ 10.000002
+ 45.000000
+ 0.000000
+
+
+ C=70 M=15 Y=0 K=0
+ CMYK
+ PROCESS
+ 70.000000
+ 14.999998
+ 0.000000
+ 0.000000
+
+
+ C=85 M=50 Y=0 K=0
+ CMYK
+ PROCESS
+ 85.000000
+ 50.000000
+ 0.000000
+ 0.000000
+
+
+ C=100 M=95 Y=5 K=0
+ CMYK
+ PROCESS
+ 100.000000
+ 95.000000
+ 5.000001
+ 0.000000
+
+
+ C=100 M=100 Y=25 K=25
+ CMYK
+ PROCESS
+ 100.000000
+ 100.000000
+ 25.000000
+ 25.000000
+
+
+ C=75 M=100 Y=0 K=0
+ CMYK
+ PROCESS
+ 75.000000
+ 100.000000
+ 0.000000
+ 0.000000
+
+
+ C=50 M=100 Y=0 K=0
+ CMYK
+ PROCESS
+ 50.000000
+ 100.000000
+ 0.000000
+ 0.000000
+
+
+ C=35 M=100 Y=35 K=10
+ CMYK
+ PROCESS
+ 35.000004
+ 100.000000
+ 35.000004
+ 10.000002
+
+
+ C=10 M=100 Y=50 K=0
+ CMYK
+ PROCESS
+ 10.000002
+ 100.000000
+ 50.000000
+ 0.000000
+
+
+ C=0 M=95 Y=20 K=0
+ CMYK
+ PROCESS
+ 0.000000
+ 95.000000
+ 19.999998
+ 0.000000
+
+
+ C=25 M=25 Y=40 K=0
+ CMYK
+ PROCESS
+ 25.000000
+ 25.000000
+ 39.999996
+ 0.000000
+
+
+ C=40 M=45 Y=50 K=5
+ CMYK
+ PROCESS
+ 39.999996
+ 45.000000
+ 50.000000
+ 5.000001
+
+
+ C=50 M=50 Y=60 K=25
+ CMYK
+ PROCESS
+ 50.000000
+ 50.000000
+ 60.000004
+ 25.000000
+
+
+ C=55 M=60 Y=65 K=40
+ CMYK
+ PROCESS
+ 55.000000
+ 60.000004
+ 65.000000
+ 39.999996
+
+
+ C=25 M=40 Y=65 K=0
+ CMYK
+ PROCESS
+ 25.000000
+ 39.999996
+ 65.000000
+ 0.000000
+
+
+ C=30 M=50 Y=75 K=10
+ CMYK
+ PROCESS
+ 30.000002
+ 50.000000
+ 75.000000
+ 10.000002
+
+
+ C=35 M=60 Y=80 K=25
+ CMYK
+ PROCESS
+ 35.000004
+ 60.000004
+ 80.000000
+ 25.000000
+
+
+ C=40 M=65 Y=90 K=35
+ CMYK
+ PROCESS
+ 39.999996
+ 65.000000
+ 90.000000
+ 35.000004
+
+
+ C=40 M=70 Y=100 K=50
+ CMYK
+ PROCESS
+ 39.999996
+ 70.000000
+ 100.000000
+ 50.000000
+
+
+ C=50 M=70 Y=80 K=70
+ CMYK
+ PROCESS
+ 50.000000
+ 70.000000
+ 80.000000
+ 70.000000
+
+
+ C=100 M=96 Y=35 K=47
+ CMYK
+ PROCESS
+ 100.000000
+ 96.041801
+ 34.717323
+ 47.113754
+
+
+ C=25 M=17 Y=0 K=0
+ CMYK
+ PROCESS
+ 25.461203
+ 16.729992
+ 0.115967
+ 0.000000
+
+
+
+
+
+ Grays
+ 1
+
+
+
+ C=0 M=0 Y=0 K=100
+ CMYK
+ PROCESS
+ 0.000000
+ 0.000000
+ 0.000000
+ 100.000000
+
+
+ C=0 M=0 Y=0 K=90
+ CMYK
+ PROCESS
+ 0.000000
+ 0.000000
+ 0.000000
+ 89.999405
+
+
+ C=0 M=0 Y=0 K=80
+ CMYK
+ PROCESS
+ 0.000000
+ 0.000000
+ 0.000000
+ 79.998795
+
+
+ C=0 M=0 Y=0 K=70
+ CMYK
+ PROCESS
+ 0.000000
+ 0.000000
+ 0.000000
+ 69.999702
+
+
+ C=0 M=0 Y=0 K=60
+ CMYK
+ PROCESS
+ 0.000000
+ 0.000000
+ 0.000000
+ 59.999104
+
+
+ C=0 M=0 Y=0 K=50
+ CMYK
+ PROCESS
+ 0.000000
+ 0.000000
+ 0.000000
+ 50.000000
+
+
+ C=0 M=0 Y=0 K=40
+ CMYK
+ PROCESS
+ 0.000000
+ 0.000000
+ 0.000000
+ 39.999401
+
+
+ C=0 M=0 Y=0 K=30
+ CMYK
+ PROCESS
+ 0.000000
+ 0.000000
+ 0.000000
+ 29.998802
+
+
+ C=0 M=0 Y=0 K=20
+ CMYK
+ PROCESS
+ 0.000000
+ 0.000000
+ 0.000000
+ 19.999701
+
+
+ C=0 M=0 Y=0 K=10
+ CMYK
+ PROCESS
+ 0.000000
+ 0.000000
+ 0.000000
+ 9.999103
+
+
+ C=0 M=0 Y=0 K=5
+ CMYK
+ PROCESS
+ 0.000000
+ 0.000000
+ 0.000000
+ 4.998803
+
+
+
+
+
+ Brights
+ 1
+
+
+
+ C=0 M=100 Y=100 K=0
+ CMYK
+ PROCESS
+ 0.000000
+ 100.000000
+ 100.000000
+ 0.000000
+
+
+ C=0 M=75 Y=100 K=0
+ CMYK
+ PROCESS
+ 0.000000
+ 75.000000
+ 100.000000
+ 0.000000
+
+
+ C=0 M=10 Y=95 K=0
+ CMYK
+ PROCESS
+ 0.000000
+ 10.000002
+ 95.000000
+ 0.000000
+
+
+ C=85 M=10 Y=100 K=0
+ CMYK
+ PROCESS
+ 85.000000
+ 10.000002
+ 100.000000
+ 0.000000
+
+
+ C=100 M=90 Y=0 K=0
+ CMYK
+ PROCESS
+ 100.000000
+ 90.000000
+ 0.000000
+ 0.000000
+
+
+ C=60 M=90 Y=0 K=0
+ CMYK
+ PROCESS
+ 60.000004
+ 90.000000
+ 0.003099
+ 0.003099
+
+
+
+
+
+
+
+
+ Adobe PDF library 10.01
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
endstream
endobj
3 0 obj
<>
endobj
7 0 obj
<>/Resources<>/ExtGState<>/Properties<>/Shading<>/XObject<>>>/Thumb 33 0 R/TrimBox[0.0 0.0 612.0 792.0]/Type/Page>>
endobj
8 0 obj
<>stream
+H-
v*I$8A-J[pqpCq$r\_~t?xL3WMgGZӇppF).)kG,I}b:^\"113|,b9C `o;[aN;pݏeLl%峄l̲%fw?[O C=YMq=K\ggԛ|s|-w䦵#c^nX@
_S;>oǿɭoƿ~g~s?#礣HĘYsAQjO_g scΎg_zq93Ux3kBPY\:r O
gv=9T 9s$vɮ^)x/)=#e\ń<}pX:p@v̮:$BSPi|MGҠ%~3|>3^%C5+H4t6b}$.makXEηbG|('A*
2
+ω]5B@p5#u46aT',6xU2TN2$@n;LE[vei{٥lطV;(qhV
7CCb('8U Bgw
F#9%Ғb|4YI|
K}$}N#.Gw '-!f?S跄q%M;ra$xYUw{7
Gt`&I]t/yaא'.~hQ4F[liʅ쥑\SǐȔ[SsPe#6pgDn#PW}!e5cݯQrşEX)߹(;Yii,)y`j$w~E{]W=VTMƷiCW&8Uש%*
L?1EMNE$l_؛F@q"3w8dveiKFJ$W)CϱCؼi54r{B`!kJD7pɉI[@vw;
Կ<[iX4x=,ˣʅBa˰©7z-+&jG$)G$2z[84PƩb5DR^ujcǮ^A# ŒdӛcPw36kSpBS/3l@ R)ϥ#HtYi82nEjre`zz%ʭfG|jtf/&3
+TcF(75!P劜G>K]5O6
Ghɺ&dfC2U%ZWHJ3wWrHcu+,7XƟ(KK4%=3512ZЦQ>@ B3!1+sӌ34T-ɶxYJX
+#44Dw5p#)WLg5 h;ntQg}G-CVj3Ww.]]#l8 v1IL~nה۽?Na'niibʼn>6L)igC#gd6әj=!{2[>*
ί`>kbEOҳy`j㋱b&5`nWJC6\5$
+nn]Ǩm#A*qȷmSja{p`ZM \ j>5 9:BYCYKa1^>aN%<_ˍz1,OPB&je,\5EVӪJ,)WexW_#)xQKFB0˾./Ԧ
+6-٭lfjUdK
+TÛf̛nM6`tMiT_BT|]hCku5QI3\QL^=܌X~3o`>LvJW "u$~>Ռn%sl),nWvuFD1U̼ɳ=5e5Dܯfia7X;56hM9ڹ=
}I.AO#= ,"8pNAH>v5'\L9ArWզ%L %d2د־V#bn$5),U6.̊zh?/l;G&0yHA_Fu͛R̽
+^1bM%y֦C'v(QS=aæO r\o\agXzf4zNUZvLOHxhM)1*Ⱦ g<ؘo@A@$BFRJ8@)|r%]3XK" 3/
endstream
endobj
9 0 obj
<>
endobj
33 0 obj
<>stream
+8;Z\796/c@$luKq(ilIj!%T&o=Re*+We^+eq>eZuj2qgFC!i=USg5@t`no:muR$^kSG+@+",.4d-LV\R&W*3sM3pNM.8L^c@3JEfU
+C/I!BQS[)j1EGVCLb+a[F#qIe$J"F"!-Sq>Q9pAMa6O,WJlOu7O$h`@0r0>l1SAX5
+6;M7(\5aB:d+V^cWufS2%.toETG&coUJT%*[*ln`H)SE_eU:J8[@4;X5k0Jj[?&o0
+X)a;%;>_NU%BLBZ@JZgSA$@c:8>FUhWgYM5$*K^a+k_
+`3Wj]#cLp#$4To(-B"_F(0f!g9cX4`e_4]+8QF4JZQ+Z2-0973ARkd7ZGK>,Lfs0;
+#ICJ+4U&A4&b0n(]FcHCtpO&p\`J#^+o]L;A^
+1J6j"B)^V3X\eor++)n/m^gcC2DVfQ^^'mm7)_W8oj[Dc=
+/m\q$T64N?(7FBS`0r]nJ]6j?CK!7h2;8-R*-/5:]].76?*13c!/X9LC,8TZ
+C2SC61)>1`j2p,6ct?%Qm4QJN(WsVgeY,^SSnt.eML[G/Zp%K8?[ZWfPd)`K,P?Fe
+]83QSZ]iepAd8:1M%'fEie?"69"s]_9]g9\(>$ZhNcpNT@1$O_;PSDA%jW0uA[
+5L/Gb[VIr5p:ATi=[+3p3W\>D
+]%Pgc-tjPoJ_csU?]U+FWn^D(0J@r*pM9WE!N4K,Fim9db?39_=[Pg2:WJ%S@(#8m
+NHn+&aeH<3ZHFlt&+0)k"8!rM~>
endstream
endobj
34 0 obj
[/Indexed/DeviceRGB 255 35 0 R]
endobj
35 0 obj
<>stream
+8;X]O>EqN@%''O_@%e@?J;%+8(9e>X=MR6S?i^YgA3=].HDXF.R$lIL@"pJ+EP(%0
+b]6ajmNZn*!='OQZeQ^Y*,=]?C.B+\Ulg9dhD*"iC[;*=3`oP1[!S^)?1)IZ4dup`
+E1r!/,*0[*9.aFIR2&b-C#soRZ7Dl%MLY\.?d>Mn
+6%Q2oYfNRF$$+ON<+]RUJmC0InDZ4OTs0S!saG>GGKUlQ*Q?45:CI&4J'_2j$XKrcYp0n+Xl_nU*O(
+l[$6Nn+Z_Nq0]s7hs]`XX1nZ8&94a\~>
endstream
endobj
25 0 obj
<>>>/Subtype/Form>>stream
+0 0 0 0.05 k
+/GS0 gs
+q 1 0 0 1 385.3555 638.0166 cm
+0 0 m
+0 -2.771 -2.245 -5.017 -5.016 -5.017 c
+-7.786 -5.017 -10.032 -2.771 -10.032 0 c
+-10.032 2.77 -7.786 5.016 -5.016 5.016 c
+-2.245 5.016 0 2.77 0 0 c
+f
+Q
+
endstream
endobj
26 0 obj
<>>>/Subtype/Form>>stream
+0 0 0 0.05 k
+/GS0 gs
+q 1 0 0 1 396.3555 620.5 cm
+0 0 m
+0 -3.038 -2.463 -5.5 -5.5 -5.5 c
+-8.537 -5.5 -11 -3.038 -11 0 c
+-11 3.038 -8.537 5.5 -5.5 5.5 c
+-2.463 5.5 0 3.038 0 0 c
+f
+Q
+
endstream
endobj
27 0 obj
<>>>/Subtype/Form>>stream
+0 0 0 0.05 k
+/GS0 gs
+q 1 0 0 1 367.3447 523.5029 cm
+0 0 m
+0 -3.589 2.909 -6.498 6.497 -6.498 c
+10.086 -6.498 12.995 -3.589 12.995 0 c
+12.995 3.588 10.086 6.497 6.497 6.497 c
+2.909 6.497 0 3.588 0 0 c
+f
+Q
+
endstream
endobj
28 0 obj
<>>>/Subtype/Form>>stream
+0 0 0 0.05 k
+/GS0 gs
+q 1 0 0 1 393.7207 500.3096 cm
+0 0 m
+0 -3.695 -2.996 -6.69 -6.691 -6.69 c
+-10.386 -6.69 -13.381 -3.695 -13.381 0 c
+-13.381 3.695 -10.386 6.69 -6.691 6.69 c
+-2.996 6.69 0 3.695 0 0 c
+f
+Q
+
endstream
endobj
29 0 obj
<>>>/Subtype/Form>>stream
+0 0 0 0.05 k
+/GS0 gs
+q 1 0 0 1 306 496.9644 cm
+0 0 m
+0 -1.848 -3.134 -3.345 -7 -3.345 c
+-10.866 -3.345 -14 -1.848 -14 0 c
+-14 1.848 -10.866 3.345 -7 3.345 c
+-3.134 3.345 0 1.848 0 0 c
+f
+Q
+
endstream
endobj
30 0 obj
<>>>/Subtype/Form>>stream
+0 0 0 0.05 k
+/GS0 gs
+q 1 0 0 1 292 475 cm
+0 0 m
+0 5.523 -7.611 10 -17 10 c
+-26.389 10 -34 5.523 -34 0 c
+-34 -5.523 -26.389 -10 -17 -10 c
+-7.611 -10 0 -5.523 0 0 c
+f
+Q
+
endstream
endobj
31 0 obj
<>>>/Subtype/Form>>stream
+0 0 0 0.05 k
+/GS0 gs
+q 1 0 0 1 234 304 cm
+0 0 m
+0 -3.866 -7.387 -7 -16.5 -7 c
+-25.613 -7 -33 -3.866 -33 0 c
+-33 3.866 -25.613 7 -16.5 7 c
+-7.387 7 0 3.866 0 0 c
+f
+Q
+
endstream
endobj
32 0 obj
<>>>/Subtype/Form>>stream
+0 0 0 0.05 k
+/GS0 gs
+q 1 0 0 1 189 304 cm
+0 0 m
+0 -3.866 -3.358 -7 -7.5 -7 c
+-11.642 -7 -15 -3.866 -15 0 c
+-15 3.866 -11.642 7 -7.5 7 c
+-3.358 7 0 3.866 0 0 c
+f
+Q
+
endstream
endobj
43 0 obj
<>
endobj
12 0 obj
<>
endobj
42 0 obj
<>
endobj
41 0 obj
<>
endobj
40 0 obj
<>
endobj
39 0 obj
<>
endobj
38 0 obj
<>
endobj
37 0 obj
<>
endobj
36 0 obj
<>
endobj
15 0 obj
<>stream
+ {ʽͭU7x[Lr
\zeI?WwX)u?u1ϋ>غ2c%7S$cLk_p9zYxYxQnYx ϋ>غ2)u?u1WwXI?C2J:j4ZЇtPg3dJ&<0<PF25g)YxQnGaYx Lr"hFmc[8@FO
'! ;a('I?ze
\m?%"iqXYxYxG`Qn I?;a('! 'X7k5)9%Tzews7j4C2J:+x}9BLiWv4^JwQnG`5HGa Pg3dtZЇj43Ip>0I^u[ K XMia C 'kl/O?7Xǯf$ YxGaĶ=SYx XMia / p UO Iv&l Ih~ } w( pM Ut v F
+ YxYxF_Ke Ih~l v&I[ѭG[ooɴooBd"ѥ1cI^u[%S|
4Uq: -;[ѭuksYɌKeF_5HĶ=S j4ews79%Tz5)ypdݾ$r{ GXeI^u[p>03IM;n2?J0FGa5H&3Ķ=S I^u["ѥ1cooBdoɴi7P_ɴ!}!}_T2dYSǟT
ajm@|2R:ikaP_e}
+SĶ=S5H'51B SǟT
2dY!}_T!}}7֢\ڙI7E8H`Gʡ^dݾ$r 6.EFE>$פ_}7Xn,ڙPWʸR1B'5zh$&3 [8xCE>wc˪e~H/1]Tz;Y([q5/,34'
@FO@kB4'oUh3eYxYxĶ=SG` ',34[q5/;Y("&TI(s6˖&F%5)kX74v:
J]ACCyG`Ķ=S'45H c˪e~H/1]Tz;Y(}kwLσA].9hzpJZiL G
+v/V3FTY:"}YxĶ=S:OYx L GpJZihz].951n,cU,csM7&w?JGr?
usbr+w6Yx:O9MYx ;Y("&TI(s*az0t{mnvG].9A}kwLσbn=QE5sӳ(($UMcĶ=S'4x".:O ].9Gmnvbi[YPY9ueQ&U,cn,c51+oy*b:iv]:Ox".u!,9M 5)ypdݾ$rQqx+L:)^Fn@j6aKМTe4w7GaS]/oF*5H&3}k&-= n@)^F+L:xԶޭ0vrt<_
qK\%sE4T+
$06F6"dqk-=}k&n['4 dݾ$rGʡ^8H`7ERК9mQWobQ0/_>xQqԗ̍@jp8 LԒ&3zh$eQ}k&