Merge branch 'master' of github.com:andreasgal/pdf.js

This commit is contained in:
Chris Jones 2011-06-15 12:42:48 -07:00
commit 470f0e49dd

235
pdf.js
View File

@ -617,6 +617,19 @@ function IsRef(v) {
return v instanceof Ref;
}
function IsPDFFunction(v) {
var fnDict;
if (typeof v != "object")
return false;
else if (IsDict(v))
fnDict = v;
else if (IsStream(v))
fnDict = v.dict;
else
return false;
return fnDict.has("FunctionType");
}
var EOF = {};
function IsEOF(v) {
@ -2055,16 +2068,16 @@ var CanvasGraphics = (function() {
// Shading
shadingFill: function(entryRef) {
var shadingRes = this.res.get("Shading");
var xref = this.xref;
var res = this.res;
var shadingRes = xref.fetchIfRef(res.get("Shading"));
if (!shadingRes)
return;
shadingRes = this.xref.fetchIfRef(shadingRes);
var shading = shadingRes.get(entryRef.name);
error("No shading resource found");
var shading = xref.fetchIfRef(shadingRes.get(entryRef.name));
if (!shading)
return;
shading = this.xref.fetchIfRef(shading);
if (!shading)
return;
error("No shading object found");
this.save();
@ -2075,27 +2088,25 @@ var CanvasGraphics = (function() {
this.endPath();
}
var cs = shading.get2("ColorSpace", "CS");
TODO("shading-fill color space");
var type = shading.get("ShadingType");
switch (type) {
case 1:
this.fillFunctionShading(shading);
break;
case 2:
this.fillAxialShading(shading);
break;
case 3:
this.fillRadialShading(shading);
break;
case 4: case 5: case 6: case 7:
TODO("shading fill type "+ type);
default:
malformed("Unknown shading type "+ type);
}
var background = shading.get("Background");
if (background)
TODO("handle background colors");
const types = [null, this.fillFunctionShading,
this.fillAxialShading, this.fillRadialShading];
var typeNum = shading.get("ShadingType");
var fillFn = types[typeNum];
if (!fillFn)
error("Unknown type of shading");
fillFn.apply(this, [shading]);
this.restore();
},
fillAxialShading: function(sh) {
var coordsArr = sh.get("Coords");
var x0 = coordsArr[0], y0 = coordsArr[1],
@ -2111,19 +2122,30 @@ var CanvasGraphics = (function() {
if (sh.has("Extend")) {
var extendArr = sh.get("Extend");
extendStart = extendArr[0], extendEnd = extendArr[1];
TODO("Support extend");
}
var fn = sh.get("Function");
fn = this.xref.fetchIfRef(fn);
var fnObj = sh.get("Function");
fnObj = this.xref.fetchIfRef(fnObj);
if (IsArray(fnObj))
error("No support for array of functions");
else if (!IsPDFFunction(fnObj))
error("Invalid function");
fn = new PDFFunction(this.xref, fnObj);
var gradient = this.ctx.createLinearGradient(x0, y0, x1, y1);
var step = (t1 - t0) / 10;
gradient.addColorStop(0, 'rgb(0,0,255)');
gradient.addColorStop(1, 'rgb(0,255,0)');
for (var i = t0; i <= t1; i += step) {
var c = fn.func([i]);
gradient.addColorStop(i, this.makeCssRgb.apply(this, c));
}
this.ctx.fillStyle = gradient;
this.ctx.fill();
this.consumePath();
// HACK to draw the gradient onto an infinite rectangle.
// PDF gradients are drawn across the entire image while
// Canvas only allows gradients to be drawn in a rectangle
this.ctx.fillRect(-1e10, -1e10, 2e10, 2e10);
},
// Images
@ -2471,3 +2493,154 @@ var ColorSpace = (function() {
return constructor;
})();
var PDFFunction = (function() {
function constructor(xref, fn) {
var dict = fn.dict;
if (!dict)
dict = fn;
const types = [this.constructSampled, null,
this.constructInterpolated, this.constructStiched,
this.constructPostScript];
var typeNum = dict.get("FunctionType");
var typeFn = types[typeNum];
if (!typeFn)
error("Unknown type of function");
typeFn.apply(this, [fn, dict]);
};
constructor.prototype = {
constructSampled: function(str, dict) {
var domain = dict.get("Domain");
var range = dict.get("Range");
if (!domain || !range)
error("No domain or range");
var inputSize = domain.length / 2;
var outputSize = range.length / 2;
if (inputSize != 1)
error("No support for multi-variable inputs to functions");
var size = dict.get("Size");
var bps = dict.get("BitsPerSample");
var order = dict.get("Order");
if (!order)
order = 1;
if (order !== 1)
error ("No support for cubic spline interpolation");
var encode = dict.get("Encode");
if (!encode) {
encode = [];
for (var i = 0; i < inputSize; ++i) {
encode.push(0);
encode.push(size[i] - 1);
}
}
var decode = dict.get("Decode");
if (!decode)
decode = range;
var samples = this.getSampleArray(size, outputSize, bps, str);
this.func = function(args) {
var clip = function(v, min, max) {
if (v > max)
v = max;
else if (v < min)
v = min
return v;
}
if (inputSize != args.length)
error("Incorrect number of arguments");
for (var i = 0; i < inputSize; i++) {
var i2 = i * 2;
// clip to the domain
var v = clip(args[i], domain[i2], domain[i2 + 1]);
// encode
v = encode[i2] + ((v - domain[i2]) *
(encode[i2 + 1] - encode[i2]) /
(domain[i2 + 1] - domain[i2]));
// clip to the size
args[i] = clip(v, 0, size[i] - 1);
}
// interpolate to table
TODO("Multi-dimensional interpolation");
var floor = Math.floor(args[0]);
var ceil = Math.ceil(args[0]);
var scale = args[0] - floor;
floor *= outputSize;
ceil *= outputSize;
var output = [];
for (var i = 0; i < outputSize; ++i) {
if (ceil == floor) {
var v = samples[ceil + i];
} else {
var low = samples[floor + i];
var high = samples[ceil + i];
var v = low * scale + high * (1 - scale);
}
var i2 = i * 2;
// decode
v = decode[i2] + (v * (decode[i2 + 1] - decode[i2]) /
((1 << bps) - 1));
// clip to the domain
output.push(clip(v, range[i2], range[i2 + 1]));
}
return output;
}
},
getSampleArray: function(size, outputSize, bps, str) {
var length = 1;
for (var i = 0; i < size.length; i++)
length *= size[i];
length *= outputSize;
var array = [];
var codeSize = 0;
var codeBuf = 0;
var strBytes = str.getBytes((length * bps + 7) / 8);
var strIdx = 0;
for (var i = 0; i < length; i++) {
var b;
while (codeSize < bps) {
codeBuf <<= 8;
codeBuf |= strBytes[strIdx++];
codeSize += 8;
}
codeSize -= bps
array.push(codeBuf >> codeSize);
codeBuf &= (1 << codeSize) - 1;
}
return array;
},
constructInterpolated: function() {
error("unhandled type of function");
},
constructStiched: function() {
error("unhandled type of function");
},
constructPostScript: function() {
error("unhandled type of function");
}
};
return constructor;
})();