Merge pull request #4464 from bthorben/issue#4461

Fixes pages without Resources in their dictionary
This commit is contained in:
Yury Delendik 2014-03-18 13:00:21 -05:00
commit 329d0ec30b
4 changed files with 86 additions and 19 deletions

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
/* globals assertWellFormed, calculateMD5, Catalog, error, info, isArray, /* globals assertWellFormed, calculateMD5, Catalog, Dict, error, info, isArray,
isArrayBuffer, isName, isStream, isString, LegacyPromise, isArrayBuffer, isName, isStream, isString, LegacyPromise,
Linearization, NullStream, PartialEvaluator, shadow, Stream, Lexer, Linearization, NullStream, PartialEvaluator, shadow, Stream, Lexer,
StreamsSequenceStream, stringToPDFString, stringToBytes, Util, XRef, StreamsSequenceStream, stringToPDFString, stringToBytes, Util, XRef,
@ -25,6 +25,8 @@
var Page = (function PageClosure() { var Page = (function PageClosure() {
var LETTER_SIZE_MEDIABOX = [0, 0, 612, 792];
function Page(pdfManager, xref, pageIndex, pageDict, ref, fontCache) { function Page(pdfManager, xref, pageIndex, pageDict, ref, fontCache) {
this.pdfManager = pdfManager; this.pdfManager = pdfManager;
this.pageIndex = pageIndex; this.pageIndex = pageIndex;
@ -42,51 +44,69 @@ var Page = (function PageClosure() {
getPageProp: function Page_getPageProp(key) { getPageProp: function Page_getPageProp(key) {
return this.pageDict.get(key); return this.pageDict.get(key);
}, },
inheritPageProp: function Page_inheritPageProp(key) {
getInheritedPageProp: function Page_inheritPageProp(key) {
var dict = this.pageDict; var dict = this.pageDict;
var obj = dict.get(key); var value = dict.get(key);
while (obj === undefined) { while (value === undefined) {
dict = dict.get('Parent'); dict = dict.get('Parent');
if (!dict) if (!dict) {
break; break;
obj = dict.get(key); }
value = dict.get(key);
} }
return obj; return value;
}, },
get content() { get content() {
return this.getPageProp('Contents'); return this.getPageProp('Contents');
}, },
get resources() { get resources() {
return shadow(this, 'resources', this.inheritPageProp('Resources')); var value = this.getInheritedPageProp('Resources');
// For robustness: The spec states that a \Resources entry has to be
// present, but can be empty. Some document omit it still. In this case
// return an empty dictionary:
if (value === undefined) {
value = new Dict();
}
return shadow(this, 'resources', value);
}, },
get mediaBox() { get mediaBox() {
var obj = this.inheritPageProp('MediaBox'); var obj = this.getInheritedPageProp('MediaBox');
// Reset invalid media box to letter size. // Reset invalid media box to letter size.
if (!isArray(obj) || obj.length !== 4) if (!isArray(obj) || obj.length !== 4) {
obj = [0, 0, 612, 792]; obj = LETTER_SIZE_MEDIABOX;
}
return shadow(this, 'mediaBox', obj); return shadow(this, 'mediaBox', obj);
}, },
get view() { get view() {
var mediaBox = this.mediaBox; var mediaBox = this.mediaBox;
var cropBox = this.inheritPageProp('CropBox'); var cropBox = this.getInheritedPageProp('CropBox');
if (!isArray(cropBox) || cropBox.length !== 4) if (!isArray(cropBox) || cropBox.length !== 4) {
return shadow(this, 'view', mediaBox); return shadow(this, 'view', mediaBox);
}
// From the spec, 6th ed., p.963: // From the spec, 6th ed., p.963:
// "The crop, bleed, trim, and art boxes should not ordinarily // "The crop, bleed, trim, and art boxes should not ordinarily
// extend beyond the boundaries of the media box. If they do, they are // extend beyond the boundaries of the media box. If they do, they are
// effectively reduced to their intersection with the media box." // effectively reduced to their intersection with the media box."
cropBox = Util.intersect(cropBox, mediaBox); cropBox = Util.intersect(cropBox, mediaBox);
if (!cropBox) if (!cropBox) {
return shadow(this, 'view', mediaBox); return shadow(this, 'view', mediaBox);
}
return shadow(this, 'view', cropBox); return shadow(this, 'view', cropBox);
}, },
get annotationRefs() { get annotationRefs() {
return shadow(this, 'annotationRefs', this.inheritPageProp('Annots')); return shadow(this, 'annotationRefs',
this.getInheritedPageProp('Annots'));
}, },
get rotate() { get rotate() {
var rotate = this.inheritPageProp('Rotate') || 0; var rotate = this.getInheritedPageProp('Rotate') || 0;
// Normalize rotation so it's a multiple of 90 and between 0 and 270 // Normalize rotation so it's a multiple of 90 and between 0 and 270
if (rotate % 90 !== 0) { if (rotate % 90 !== 0) {
rotate = 0; rotate = 0;
@ -99,6 +119,7 @@ var Page = (function PageClosure() {
} }
return shadow(this, 'rotate', rotate); return shadow(this, 'rotate', rotate);
}, },
getContentStream: function Page_getContentStream() { getContentStream: function Page_getContentStream() {
var content = this.content; var content = this.content;
var stream; var stream;
@ -118,9 +139,10 @@ var Page = (function PageClosure() {
} }
return stream; return stream;
}, },
loadResources: function(keys) { loadResources: function(keys) {
if (!this.resourcesPromise) { if (!this.resourcesPromise) {
// TODO: add async inheritPageProp and remove this. // TODO: add async getInheritedPageProp and remove this.
this.resourcesPromise = this.pdfManager.ensure(this, 'resources'); this.resourcesPromise = this.pdfManager.ensure(this, 'resources');
} }
var promise = new LegacyPromise(); var promise = new LegacyPromise();
@ -134,6 +156,7 @@ var Page = (function PageClosure() {
}.bind(this)); }.bind(this));
return promise; return promise;
}, },
getOperatorList: function Page_getOperatorList(handler, intent) { getOperatorList: function Page_getOperatorList(handler, intent) {
var self = this; var self = this;
var promise = new LegacyPromise(); var promise = new LegacyPromise();
@ -153,7 +176,7 @@ var Page = (function PageClosure() {
'Pattern', 'Pattern',
'Shading', 'Shading',
'XObject', 'XObject',
'Font', 'Font'
// ProcSet // ProcSet
// Properties // Properties
]); ]);
@ -201,6 +224,7 @@ var Page = (function PageClosure() {
return promise; return promise;
}, },
extractTextContent: function Page_extractTextContent() { extractTextContent: function Page_extractTextContent() {
var handler = { var handler = {
on: function nullHandlerOn() {}, on: function nullHandlerOn() {},

View File

@ -67,3 +67,4 @@
!issue3885.pdf !issue3885.pdf
!bug859204.pdf !bug859204.pdf
!issue4246.pdf !issue4246.pdf
!issue4461.pdf

35
test/pdfs/issue4461.pdf Normal file
View File

@ -0,0 +1,35 @@
%PDF-1.4
%μῦ
1 0 obj
<</Parent 2 0 R/MediaBox[0 0 30 20]/Type/Page/Contents 3 0 R>>
endobj
2 0 obj
<</Kids[1 0 R]/Type/Pages/Count 1>>
endobj
3 0 obj
<</Length 0>>
stream
endstream
endobj
4 0 obj
<</Pages 2 0 R/Type/Catalog>>
endobj
xref
0 5
0000000000 65536 f
0000000017 00000 n
0000000096 00000 n
0000000148 00000 n
0000000195 00000 n
trailer
<</Size 5/Root 4 0 R/ID[<1861E1AD51AD0FE751FE9A71F1C854F5><1861E1AD51AD0FE751FE9A71F1C854F5>]>>
startxref
241
%%EOF

View File

@ -709,6 +709,13 @@
"link": true, "link": true,
"type": "eq" "type": "eq"
}, },
{ "id": "issue4461-load",
"file": "pdfs/issue4461.pdf",
"md5": "9df4ecaae429adb5dc93d9342a53159d",
"rounds": 1,
"type": "load",
"about": "Document without /Resources entry in page dictionary"
},
{ "id": "issue1249-load", { "id": "issue1249-load",
"file": "pdfs/issue1249.pdf", "file": "pdfs/issue1249.pdf",
"md5": "4f81339fa09422a7db980f34ea963609", "md5": "4f81339fa09422a7db980f34ea963609",