From 1bb440670210c7e52413928e6c28b6220642db55 Mon Sep 17 00:00:00 2001 From: sbarman Date: Wed, 22 Jun 2011 17:55:47 -0700 Subject: [PATCH 01/10] work in progress --- pdf.js | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/pdf.js b/pdf.js index ec8f74a3b..8b9fefb2c 100644 --- a/pdf.js +++ b/pdf.js @@ -2042,7 +2042,8 @@ var CanvasExtraState = (function() { this.fontSize = 0.0; this.textMatrix = IDENTITY_MATRIX; this.leading = 0.0; - this.colorSpace = null; + this.fillColorSpace = null; + this.strokeColorSpace = null; // Current point (in user coordinates) this.x = 0.0; this.y = 0.0; @@ -2823,9 +2824,9 @@ var CanvasGraphics = (function() { setFillColorSpace: function(space) { // TODO real impl if (space.name === "Pattern") - this.current.colorSpace = "Pattern"; + this.current.fillColorSpace = "Pattern"; else - this.current.colorSpace = "DeviceRGB"; + this.current.fillColorSpace = "DeviceRGB"; }, setStrokeColor: function(/*...*/) { // TODO real impl @@ -2849,7 +2850,7 @@ var CanvasGraphics = (function() { }, setFillColorN: function(/*...*/) { // TODO real impl - var colorSpace = this.current.colorSpace; + var colorSpace = this.current.fillColorSpace; if (!colorSpace) { var stateStack = this.stateStack; var i = stateStack.length - 1; @@ -2858,7 +2859,7 @@ var CanvasGraphics = (function() { } } - if (this.current.colorSpace == "Pattern") { + if (this.current.fillColorSpace == "Pattern") { var patternName = arguments[0]; if (IsName(patternName)) { var xref = this.xref; @@ -3372,6 +3373,15 @@ var CanvasGraphics = (function() { makeCssRgb: function(r, g, b) { var ri = (255 * r) | 0, gi = (255 * g) | 0, bi = (255 * b) | 0; return "rgb("+ ri +","+ gi +","+ bi +")"; + }, + getColorSpaceObj(colorSpace) { + if (IsName(colorSpace)) { + var name = colorSpace.name; + } else if (IsArray(colorSpace)) { + var name = colorSpace[0]; + } + } + }, // We generally keep the canvas context set for // nonzero-winding, and just set evenodd for the operations From a5be9c46481cc4d02bc9380c2c7a0a1aae734470 Mon Sep 17 00:00:00 2001 From: sbarman Date: Tue, 28 Jun 2011 19:25:36 -0700 Subject: [PATCH 02/10] refactored colorspace into own class --- pdf.js | 245 ++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 181 insertions(+), 64 deletions(-) diff --git a/pdf.js b/pdf.js index bdb88a4a4..731fa0116 100644 --- a/pdf.js +++ b/pdf.js @@ -3266,7 +3266,6 @@ var CanvasExtraState = (function() { this.fontSize = 0; this.textMatrix = IDENTITY_MATRIX; this.leading = 0; - this.colorSpace = null; // Current point (in user coordinates) this.x = 0; this.y = 0; @@ -3906,51 +3905,32 @@ var CanvasGraphics = (function() { // Color setStrokeColorSpace: function(space) { - // TODO real impl + this.current.strokeColorSpace = + ColorSpace.parse(space, this.xref, this.res); }, setFillColorSpace: function(space) { - // TODO real impl - if (space.name === "Pattern") - this.current.fillColorSpace = "Pattern"; - else - this.current.fillColorSpace = "DeviceRGB"; + this.current.fillColorSpace = + ColorSpace.parse(space, this.xref, this.res); }, setStrokeColor: function(/*...*/) { - // TODO real impl - if (1 === arguments.length) { - this.setStrokeGray.apply(this, arguments); - } else if (3 === arguments.length) { - this.setStrokeRGBColor.apply(this, arguments); - } else if (4 === arguments.length) { - this.setStrokeCMYKColor.apply(this, arguments); - } + var cs = this.getStrokeColorSpace(); + var color = cs.getRgb(arguments); + this.setStrokeRGBColor.apply(this, color); }, setStrokeColorN: function(/*...*/) { // TODO real impl + TODO("check for special color spaces"); this.setStrokeColor.apply(this, arguments); }, setFillColor: function(/*...*/) { - // TODO real impl - if (1 === arguments.length) { - this.setFillGray.apply(this, arguments); - } else if (3 === arguments.length) { - this.setFillRGBColor.apply(this, arguments); - } else if (4 === arguments.length) { - this.setFillCMYKColor.apply(this, arguments); - } + var cs = this.getFillColorSpace(); + var color = cs.getRgb(arguments); + this.setFillRGBColor.apply(this, color); }, setFillColorN: function(/*...*/) { - // TODO real impl - var colorSpace = this.current.fillColorSpace; - if (!colorSpace) { - var stateStack = this.stateStack; - var i = stateStack.length - 1; - while (!colorSpace && i >= 0) { - colorSpace = stateStack[i--].colorSpace; - } - } + var cs = this.getStrokeColorSpace(); - if (this.current.fillColorSpace == "Pattern") { + if (cs.name == "Pattern") { var patternName = arguments[0]; if (IsName(patternName)) { var xref = this.xref; @@ -4328,12 +4308,35 @@ var CanvasGraphics = (function() { var bi = (255 * (1 - Math.min(1, y * (1 - k) + k))) | 0; return "rgb("+ ri +","+ gi +","+ bi +")"; }, - getColorSpaceObj(colorSpace) { - if (IsName(colorSpace)) { - var name = colorSpace.name; - } else if (IsArray(colorSpace)) { - var name = colorSpace[0]; - } + getFillColorSpace: function() { + var cs = this.current.fillColorSpace; + if (cs) + return cs; + + var states = this.stateStack; + var i = states.length - 1; + while (i >= 0 && !(cs = states[i].fillColorSpace)) + --i; + + if (cs) + return cs; + else + return new DeviceRgbCS(); + }, + getStrokeColorSpace: function() { + var cs = this.current.strokeColorSpace; + if (cs) + return cs; + + var states = this.stateStack; + var i = states.length - 1; + while (i >= 0 && !(cs = states[i].strokeColorSpace)) + --i; + + if (cs) + return cs; + else + return new DeviceRgbCS(); }, // We generally keep the canvas context set for // nonzero-winding, and just set evenodd for the operations @@ -4352,20 +4355,43 @@ var CanvasGraphics = (function() { })(); var ColorSpace = (function() { - function constructor(xref, cs) { + function constructor() { + error("should not call ColorSpace constructor"); + }; + + constructor.parse = function colorspace_parse(cs, xref, res) { + if (IsName(cs)) { + var colorSpaces = res.get("ColorSpace"); + var refcs = colorSpaces.get(cs.name); + if (refcs) + cs = refcs; + } + + cs = xref.fetchIfRef(cs); + if (IsName(cs)) { var mode = cs.name; this.mode = mode; + switch(mode) { case "DeviceGray": case "G": - this.numComps = 1; + return new DeviceGrayCS(); break; case "DeviceRGB": - this.numComps = 3; + case "RGB": + return new DeviceRgbCS(); + break; + case "DeviceCMYK": + case "CMYK": + return new DeviceCmykCS(); break; + case "Pattern": + return new PatternCS(null); + break; + default: + error("unrecognized colorspace " + mode); } - TODO("fill in color space constructor"); } else if (IsArray(cs)) { var mode = cs[0].name; this.mode = mode; @@ -4376,27 +4402,49 @@ var ColorSpace = (function() { switch (mode) { case "DeviceGray": case "G": - this.stream = stream; - this.dict = stream.dict; - this.numComps = 1; + return new DeviceGrayCS(); + break; + case "DeviceRGB": + case "RGB": + return new DeviceRgbCS(); + break; + case "DeviceCMYK": + case "CMYK": + return new DeviceCmykCS(); + break; + case "CalGray": + return new DeviceGrayCS(stream); + break; + case "CalRGB": + return new DeviceRgbCS(stream); break; case "ICCBased": var dict = stream.dict; - - this.stream = stream; - this.dict = dict; - this.numComps = dict.get("N"); + var numComps = dict.get("N"); + if (numComps == 1) + return new DeviceGrayCS(); + else if (numComps == 3) + return new DeviceRgbCS(); + else if (numComps == 4) + return new DeviceCmykCS(); break; + case "Pattern": + return new PatternCS(); case "Indexed": - this.stream = stream; - this.dict = stream.dict; - var base = cs[1]; - var hival = cs[2]; - assertWellFormed(0 <= hival && hival <= 255, "hival in range"); - var lookupTable = cs[3]; - TODO("implement 'Indexed' color space"); - this.numComps = 3; // HACK - break; + /*return new IndexedCS(stream); + this.stream = stream; + this.dict = stream.dict; + var base = cs[1]; + var hival = cs[2]; + assertWellFormed(0 <= hival && hival <= 255, "hival in range"); + var lookupTable = cs[3]; + TODO("implement 'Indexed' color space"); + this.numComps = 3; // HACK + break; + */ + case "Lab": + case "Seperation": + case "DeviceN": default: error("unrecognized color space object '"+ mode +"'"); } @@ -4405,9 +4453,81 @@ var ColorSpace = (function() { } }; + return constructor; +})(); + +var PatternCS = (function() { + function constructor() { + this.name = "Pattern"; + } + constructor.prototype = {}; + + return constructor; +})(); + +var DeviceGrayCS = (function() { + function constructor() { + this.name = "DeviceGray"; + this.numComps = 1; + this.defaultColor = [0]; + }; + + constructor.prototype = { + getRgb: function graycs_getRgb(color) { + var c = color[0]; + return [c, c, c]; + }, + getRgbBuffer: function graycs_getRgbBuffer(input) { + var length = colorBuf.length; + var rgbBuf = new Uint8Array(length); + for (var i = 0, j = 0; i < length; ++i) { + var c = input[i]; + rgbBuf[j++] = c; + rgbBuf[j++] = c; + rgbBuf[j++] = c; + } + return rgbBuf; + } + }; + return constructor; +})(); + +var DeviceRgbCS = (function() { + function constructor() { + this.name = "DeviceRGB"; + this.numComps = 3; + this.defaultColor = [0, 0, 0]; + } constructor.prototype = { + getRgb: function graycs_getRgb(color) { + return color; + }, + getRgbBuffer: function graycs_getRgbBuffer(input) { + return input; + } }; + return constructor; +})(); +var DeviceCmykCS = (function() { + function constructor() { + this.name = "DeviceCMYK"; + this.numComps = 4; + this.defaultColor = [0, 0, 0, 1]; + } + constructor.prototype = { + getRgb: function graycs_getRgb(color) { + var c = color[0], y = color[1], m = color[2], k = color[3]; + var ri = (1 - Math.min(1, c * (1 - k) + k)) | 0; + var gi = (1 - Math.min(1, m * (1 - k) + k)) | 0; + var bi = (1 - Math.min(1, y * (1 - k) + k)) | 0; + return [ri, gi, bi]; + }, + getRgbBuffer: function graycs_getRgbBuffer(colorBuf) { + error("conversion from rgb to cmyk not implemented for images"); + return colorBuf; + } + }; return constructor; })(); @@ -4445,11 +4565,8 @@ var PDFImage = (function() { } this.bpc = bitsPerComponent; - var colorSpaces = res.get("ColorSpace"); - var csStream = xref.fetchIfRef(dict.get2("ColorSpace", "CS")); - if (IsName(csStream) && inline) - csStream = colorSpaces.get(csStream); - this.colorSpace = new ColorSpace(xref, csStream); + var colorSpace = dict.get2("ColorSpace", "CS"); + this.colorSpace = ColorSpace.parse(colorSpace, xref, res); this.numComps = this.colorSpace.numComps; this.decode = dict.get2("Decode", "D"); From 08e7b9a8585461904e3fc794ae2d9dcaad096a1c Mon Sep 17 00:00:00 2001 From: sbarman Date: Wed, 29 Jun 2011 10:15:16 -0700 Subject: [PATCH 03/10] Working version of indexed color space --- pdf.js | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 67 insertions(+), 7 deletions(-) diff --git a/pdf.js b/pdf.js index 731fa0116..c979b7684 100644 --- a/pdf.js +++ b/pdf.js @@ -4396,9 +4396,6 @@ var ColorSpace = (function() { var mode = cs[0].name; this.mode = mode; - var stream = cs[1]; - stream = xref.fetchIfRef(stream); - switch (mode) { case "DeviceGray": case "G": @@ -4413,12 +4410,13 @@ var ColorSpace = (function() { return new DeviceCmykCS(); break; case "CalGray": - return new DeviceGrayCS(stream); + return new DeviceGrayCS(); break; case "CalRGB": - return new DeviceRgbCS(stream); + return new DeviceRgbCS(); break; case "ICCBased": + var stream = xref.fetchIfRef(cs[1]); var dict = stream.dict; var numComps = dict.get("N"); if (numComps == 1) @@ -4430,7 +4428,13 @@ var ColorSpace = (function() { break; case "Pattern": return new PatternCS(); + break; case "Indexed": + var base = ColorSpace.parse(cs[1], xref, res); + var hiVal = cs[2]; + var lookup = xref.fetchIfRef(cs[3]); + return new IndexedCS(base, hiVal, lookup); + /*return new IndexedCS(stream); this.stream = stream; this.dict = stream.dict; @@ -4465,6 +4469,62 @@ var PatternCS = (function() { return constructor; })(); +var IndexedCS = (function() { + function constructor(base, highVal, lookup) { + this.name = "Indexed"; + this.numComps = 1; + this.defaultColor = [0]; + + this.base = base; + var baseNumComps = base.numComps; + this.highVal = highVal; + + var length = baseNumComps * highVal; + var lookupArray = new Uint8Array(length); + if (IsStream(lookup)) { + var bytes = lookup.getBytes(length); + lookupArray.set(bytes); + } else if (IsString(lookup)) { + for (var i = 0; i < length; ++i) + lookupArray[i] = lookup.charCodeAt(i); + } else { + error("Unrecognized lookup table"); + } + this.lookup = lookupArray; + } + + constructor.prototype = { + getRgb: function graycs_getRgb(color) { + var lookup = this.lookup; + var base = this.base; + var numComps = base.numComps; + + var c = []; + for (var i = 0; i < numComps; ++i) + c.push(lookup[i]) + return this.base.getRgb(c); + }, + getRgbBuffer: function graycs_getRgbBuffer(input) { + var base = this.base; + var numComps = base.numComps; + var lookup = this.lookup; + var length = input.length; + + var baseBuf = new Uint8Array(length * numComps); + var baseBufPos = 0; + for (var i = 0; i < length; ++i) { + var lookupPos = input[i]; + for (var j = 0; j < numComps ; ++j) { + baseBuf[baseBufPos++] = lookup[lookupPos + j]; + } + } + + return base.getRgbBuffer(baseBuf); + } + }; + return constructor; +})(); + var DeviceGrayCS = (function() { function constructor() { this.name = "DeviceGray"; @@ -4478,7 +4538,7 @@ var DeviceGrayCS = (function() { return [c, c, c]; }, getRgbBuffer: function graycs_getRgbBuffer(input) { - var length = colorBuf.length; + var length = input.length; var rgbBuf = new Uint8Array(length); for (var i = 0, j = 0; i < length; ++i) { var c = input[i]; @@ -4642,7 +4702,7 @@ var PDFImage = (function() { output[i] = Math.round(255 * ret / ((1 << bpc) - 1)); } } - return output; + return this.colorSpace.getRbaBuffer(output); }, getOpacity: function getOpacity() { var smask = this.smask; From ed7e18f730ac9198db81146f4e8c17bf050dcd64 Mon Sep 17 00:00:00 2001 From: sbarman Date: Wed, 29 Jun 2011 10:27:00 -0700 Subject: [PATCH 04/10] clean up --- pdf.js | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/pdf.js b/pdf.js index a6681a687..a9d350555 100644 --- a/pdf.js +++ b/pdf.js @@ -3409,6 +3409,7 @@ var CanvasGraphics = (function() { translateFont: function(fontDict, xref, resources) { var fd = fontDict.get("FontDescriptor"); + return; if (!fd) // XXX deprecated "special treatment" for standard // fonts? What do we need to do here? @@ -4440,18 +4441,6 @@ var ColorSpace = (function() { var hiVal = cs[2]; var lookup = xref.fetchIfRef(cs[3]); return new IndexedCS(base, hiVal, lookup); - - /*return new IndexedCS(stream); - this.stream = stream; - this.dict = stream.dict; - var base = cs[1]; - var hival = cs[2]; - assertWellFormed(0 <= hival && hival <= 255, "hival in range"); - var lookupTable = cs[3]; - TODO("implement 'Indexed' color space"); - this.numComps = 3; // HACK - break; - */ case "Lab": case "Seperation": case "DeviceN": From a013e803a2b68935dd03404a0e156830ce988257 Mon Sep 17 00:00:00 2001 From: sbarman Date: Wed, 29 Jun 2011 10:30:28 -0700 Subject: [PATCH 05/10] cleanup --- pdf.js | 1 - 1 file changed, 1 deletion(-) diff --git a/pdf.js b/pdf.js index a9d350555..c5eceb854 100644 --- a/pdf.js +++ b/pdf.js @@ -3409,7 +3409,6 @@ var CanvasGraphics = (function() { translateFont: function(fontDict, xref, resources) { var fd = fontDict.get("FontDescriptor"); - return; if (!fd) // XXX deprecated "special treatment" for standard // fonts? What do we need to do here? From eedaa159a921a26608bcc6011559478f2c7dc101 Mon Sep 17 00:00:00 2001 From: notmasteryet Date: Thu, 30 Jun 2011 21:12:42 -0500 Subject: [PATCH 06/10] Real page distance between two pages is 10 --- multi_page_viewer.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/multi_page_viewer.js b/multi_page_viewer.js index 180e715eb..2f5f47b69 100644 --- a/multi_page_viewer.js +++ b/multi_page_viewer.js @@ -43,12 +43,12 @@ var PDFViewer = { lastPagesDrawn: [], visiblePages: function() { - const pageBottomMargin = 20; + const pageBottomMargin = 10; var windowTop = window.pageYOffset; var windowBottom = window.pageYOffset + window.innerHeight; var pageHeight, page; - var i, n = PDFViewer.numberOfPages, currentHeight = 0; + var i, n = PDFViewer.numberOfPages, currentHeight = pageBottomMargin; for (i = 1; i <= n; i++) { var page = PDFViewer.pdf.getPage(i); pageHeight = PDFViewer.pageHeight(page) + pageBottomMargin; From 40afbc725bcb585f83e0275b61d0b3e2c9c8e327 Mon Sep 17 00:00:00 2001 From: Andreas Gal Date: Sat, 2 Jul 2011 01:11:55 -0700 Subject: [PATCH 07/10] work-around for issue #158 --- pdf.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pdf.js b/pdf.js index b52d196a9..8f869a48a 100644 --- a/pdf.js +++ b/pdf.js @@ -3938,6 +3938,10 @@ var CanvasGraphics = (function() { }, setFillColor: function(/*...*/) { var cs = this.getFillColorSpace(); + if (cs.name == "Pattern") { + TODO("implement Pattern fill"); + return; + } var color = cs.getRgb(arguments); this.setFillRGBColor.apply(this, color); }, From 6c26a6023e32f771ee8d02db0798c3b48ec025cf Mon Sep 17 00:00:00 2001 From: sayrer Date: Sat, 2 Jul 2011 09:28:13 -0700 Subject: [PATCH 08/10] The "read more" links were on the same line. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index b6ff6c19f..7f9f8d914 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ PDF reader extension powered by pdf.js. You can read more about pdf.js here: http://andreasgal.com/2011/06/15/pdf-js/ + http://blog.mozilla.com/cjones/2011/06/15/overview-of-pdf-js-guts/ follow us on twitter: @pdfjs From 10a31bbd38fee52f95636df03920390a2ad73c30 Mon Sep 17 00:00:00 2001 From: sayrer Date: Sat, 2 Jul 2011 09:30:46 -0700 Subject: [PATCH 09/10] Edited README.md via GitHub --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 7f9f8d914..0d439b139 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,10 @@ yet to integrate it into Firefox. We will explore that possibility once pdf.js is production ready. Until then we aim to publish a Firefox PDF reader extension powered by pdf.js. +Our demo site is here: + + http://andreasgal.github.com/pdf.js/ + You can read more about pdf.js here: http://andreasgal.com/2011/06/15/pdf-js/ From 8d196a96d067d71808d1aed03259cdabdab3fd03 Mon Sep 17 00:00:00 2001 From: sbarman Date: Sun, 3 Jul 2011 01:20:30 -0500 Subject: [PATCH 10/10] fix for colorspaces --- pdf.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pdf.js b/pdf.js index 8f869a48a..7e47a3c57 100644 --- a/pdf.js +++ b/pdf.js @@ -4380,9 +4380,11 @@ var ColorSpace = (function() { constructor.parse = function colorspace_parse(cs, xref, res) { if (IsName(cs)) { var colorSpaces = res.get("ColorSpace"); - var refcs = colorSpaces.get(cs.name); - if (refcs) - cs = refcs; + if (colorSpaces) { + var refcs = colorSpaces.get(cs.name); + if (refcs) + cs = refcs; + } } cs = xref.fetchIfRef(cs);