diff --git a/src/canvas.js b/src/canvas.js index 85e82aaa5..cc6d50ded 100644 --- a/src/canvas.js +++ b/src/canvas.js @@ -1097,6 +1097,40 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { } } } + function rescaleImage(pixels, widthScale, heightScale) { + var scaledWidth = Math.ceil(width / widthScale); + var scaledHeight = Math.ceil(height / heightScale); + + var itemsSum = new Uint32Array(scaledWidth * scaledHeight * 4); + var itemsCount = new Uint32Array(scaledWidth * scaledHeight); + for (var i = 0, position = 0; i < height; i++) { + var lineOffset = (0 | (i / heightScale)) * scaledWidth; + for (var j = 0; j < width; j++) { + var countOffset = lineOffset + (0 | (j / widthScale)); + var sumOffset = countOffset << 2; + itemsSum[sumOffset] += pixels[position]; + itemsSum[sumOffset + 1] += pixels[position + 1]; + itemsSum[sumOffset + 2] += pixels[position + 2]; + itemsSum[sumOffset + 3] += pixels[position + 3]; + itemsCount[countOffset]++; + position += 4; + } + } + var tmpCanvas = createScratchCanvas(scaledWidth, scaledHeight); + var tmpCtx = tmpCanvas.getContext('2d'); + var imgData = tmpCtx.getImageData(0, 0, scaledWidth, scaledHeight); + pixels = imgData.data; + for (var i = 0, j = 0, ii = scaledWidth * scaledHeight; i < ii; i++) { + var count = itemsCount[i]; + pixels[j] = itemsSum[j] / count; + pixels[j + 1] = itemsSum[j + 1] / count; + pixels[j + 2] = itemsSum[j + 2] / count; + pixels[j + 3] = itemsSum[j + 3] / count; + j += 4; + } + tmpCtx.putImageData(imgData, 0, 0); + return tmpCanvas; + } this.save(); @@ -1119,8 +1153,19 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { applyStencilMask(pixels, inverseDecode); - tmpCtx.putImageData(imgData, 0, 0); - ctx.drawImage(tmpCanvas, 0, -h); + var currentTransform = ctx.mozCurrentTransformInverse; + var widthScale = Math.max(Math.abs(currentTransform[0]), 1); + var heightScale = Math.max(Math.abs(currentTransform[3]), 1); + if (widthScale >= 2 || heightScale >= 2) { + // canvas does not resize well large images to small -- using simple + // algorithm to perform pre-scaling + tmpCanvas = rescaleImage(imgData.data, widthScale, heightScale); + ctx.scale(widthScale, heightScale); + ctx.drawImage(tmpCanvas, 0, -h / heightScale); + } else { + tmpCtx.putImageData(imgData, 0, 0); + ctx.drawImage(tmpCanvas, 0, -h); + } this.restore(); }, diff --git a/src/evaluator.js b/src/evaluator.js index 8849a994a..059ff113f 100644 --- a/src/evaluator.js +++ b/src/evaluator.js @@ -226,8 +226,10 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { insertDependency([objId]); args = [objId, w, h]; - var softMask = dict.get('SMask', 'IM') || false; - if (!softMask && image instanceof JpegStream && + var softMask = dict.get('SMask', 'SM') || false; + var mask = dict.get('Mask') || false; + + if (!softMask && !mask && image instanceof JpegStream && image.isNativelySupported(xref, resources)) { // These JPEGs don't need any more processing so we can just send it. fn = 'paintJpegXObject'; diff --git a/src/fonts.js b/src/fonts.js index 72bcecbce..f74ad4439 100644 --- a/src/fonts.js +++ b/src/fonts.js @@ -3104,9 +3104,13 @@ var Font = (function FontClosure() { window.btoa(data) + ');'); var rule = "@font-face { font-family:'" + fontName + "';src:" + url + '}'; - var styleElement = document.createElement('style'); - document.documentElement.getElementsByTagName('head')[0].appendChild( - styleElement); + var styleElement = document.getElementById('PDFJS_FONT_STYLE_TAG'); + if (!styleElement) { + styleElement = document.createElement('style'); + styleElement.id = 'PDFJS_FONT_STYLE_TAG'; + document.documentElement.getElementsByTagName('head')[0].appendChild( + styleElement); + } var styleSheet = styleElement.sheet; styleSheet.insertRule(rule, styleSheet.cssRules.length); diff --git a/src/image.js b/src/image.js index c8c19f9e5..3495483e7 100644 --- a/src/image.js +++ b/src/image.js @@ -33,7 +33,7 @@ var PDFImage = (function PDFImageClosure() { // Clamp the value to the range return value < 0 ? 0 : value > max ? max : value; } - function PDFImage(xref, res, image, inline, smask) { + function PDFImage(xref, res, image, inline, smask, mask) { this.image = image; if (image.getParams) { // JPX/JPEG2000 streams directly contain bits per component @@ -94,12 +94,10 @@ var PDFImage = (function PDFImageClosure() { } } - var mask = dict.get('Mask'); - - if (mask) { - TODO('masked images'); - } else if (smask) { + if (smask) { this.smask = new PDFImage(xref, res, smask, false); + } else if (mask) { + this.mask = new PDFImage(xref, res, mask, false); } } /** @@ -110,21 +108,36 @@ var PDFImage = (function PDFImageClosure() { res, image, inline) { var imageDataPromise = new Promise(); var smaskPromise = new Promise(); + var maskPromise = new Promise(); // The image data and smask data may not be ready yet, wait till both are // resolved. - Promise.all([imageDataPromise, smaskPromise]).then(function(results) { - var imageData = results[0], smaskData = results[1]; - var image = new PDFImage(xref, res, imageData, inline, smaskData); + Promise.all([imageDataPromise, smaskPromise, maskPromise]).then( + function(results) { + var imageData = results[0], smaskData = results[1], maskData = results[2]; + var image = new PDFImage(xref, res, imageData, inline, smaskData, + maskData); callback(image); }); handleImageData(handler, xref, res, image, imageDataPromise); var smask = image.dict.get('SMask'); - if (smask) + var mask = image.dict.get('Mask'); + + if (smask) { handleImageData(handler, xref, res, smask, smaskPromise); - else + maskPromise.resolve(null); + } else { smaskPromise.resolve(null); + if (mask && isStream(mask)) { + handleImageData(handler, xref, res, mask, maskPromise); + } else if (mask) { + TODO('handle color key masking'); + maskPromise.resolve(null); + } else { + maskPromise.resolve(null); + } + } }; /** @@ -268,6 +281,7 @@ var PDFImage = (function PDFImageClosure() { }, getOpacity: function PDFImage_getOpacity(width, height) { var smask = this.smask; + var mask = this.mask; var originalWidth = this.width; var originalHeight = this.height; var buf; @@ -278,7 +292,20 @@ var PDFImage = (function PDFImageClosure() { buf = new Uint8Array(sw * sh); smask.fillGrayBuffer(buf); if (sw != width || sh != height) - buf = PDFImage.resize(buf, smask.bps, 1, sw, sh, width, height); + buf = PDFImage.resize(buf, smask.bpc, 1, sw, sh, width, height); + } else if (mask) { + var sw = mask.width; + var sh = mask.height; + buf = new Uint8Array(sw * sh); + mask.numComps = 1; + mask.fillGrayBuffer(buf); + + // Need to invert values in buffer + for (var i = 0, ii = sw * sh; i < ii; ++i) + buf[i] = 255 - buf[i]; + + if (sw != width || sh != height) + buf = PDFImage.resize(buf, mask.bpc, 1, sw, sh, width, height); } else { buf = new Uint8Array(width * height); for (var i = 0, ii = width * height; i < ii; ++i) diff --git a/test/pdfs/issue1796.pdf.link b/test/pdfs/issue1796.pdf.link new file mode 100644 index 000000000..b6470b421 --- /dev/null +++ b/test/pdfs/issue1796.pdf.link @@ -0,0 +1 @@ +http://www.maxims6n.bget.ru/book3/viewer/t4.pdf diff --git a/test/test_manifest.json b/test/test_manifest.json index 25d2a2080..32bde988e 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -608,5 +608,13 @@ "md5": "cbc1988e4803f647fa83467a85f0e231", "rounds": 1, "type": "eq" + }, + { "id": "issue1796", + "file": "pdfs/issue1796.pdf", + "md5": "9b9b60dc2a4cc3ea05932785d71304fe", + "rounds": 1, + "pageLimit": 2, + "link": true, + "type": "eq" } ] diff --git a/web/viewer.css b/web/viewer.css index 7c7d4f684..b8e86f2c8 100644 --- a/web/viewer.css +++ b/web/viewer.css @@ -11,7 +11,13 @@ body { height: 100%; background-color: #404040; background-image: url(images/texture.png); - font-family: Segoe UI, Verdana, sans-serif; +} + +body, +input, +button, +select { + font: message-box; } .hidden { @@ -54,19 +60,31 @@ html[dir='rtl'] .innerCenter { bottom: 0; width: 200px; visibility: hidden; - -moz-transition-duration: 200ms; - -moz-transition-timing-function: ease; -webkit-transition-duration: 200ms; -webkit-transition-timing-function: ease; + -moz-transition-duration: 200ms; + -moz-transition-timing-function: ease; + -ms-transition-duration: 200ms; + -ms-transition-timing-function: ease; + -o-transition-duration: 200ms; + -o-transition-timing-function: ease; + transition-duration: 200ms; + transition-timing-function: ease; + } html[dir='ltr'] #sidebarContainer { - -moz-transition-property: left; -webkit-transition-property: left; + -moz-transition-property: left; + -ms-transition-property: left; + -o-transition-property: left; + transition-property: left; left: -200px; } html[dir='rtl'] #sidebarContainer { - -moz-transition-property: right; -webkit-transition-property: right; + -ms-transition-property: right; + -o-transition-property: right; + transition-property: right; right: -200px; } @@ -87,19 +105,31 @@ html[dir='rtl'] #outerContainer.sidebarOpen > #sidebarContainer { right: 0; bottom: 0; left: 0; - -moz-transition-duration: 200ms; - -moz-transition-timing-function: ease; -webkit-transition-duration: 200ms; -webkit-transition-timing-function: ease; + -moz-transition-duration: 200ms; + -moz-transition-timing-function: ease; + -ms-transition-duration: 200ms; + -ms-transition-timing-function: ease; + -o-transition-duration: 200ms; + -o-transition-timing-function: ease; + transition-duration: 200ms; + transition-timing-function: ease; } html[dir='ltr'] #outerContainer.sidebarOpen > #mainContainer { - -moz-transition-property: left; -webkit-transition-property: left; + -moz-transition-property: left; + -ms-transition-property: left; + -o-transition-property: left; + transition-property: left; left: 200px; } html[dir='rtl'] #outerContainer.sidebarOpen > #mainContainer { - -moz-transition-property: right; -webkit-transition-property: right; + -moz-transition-property: right; + -ms-transition-property: right; + -o-transition-property: right; + transition-property: right; right: 200px; } @@ -147,10 +177,16 @@ html[dir='rtl'] #sidebarContent { #toolbarSidebar { width: 200px; height: 29px; + background-image: url(images/texture.png), + -webkit-linear-gradient(hsla(0,0%,30%,.99), hsla(0,0%,25%,.95)); background-image: url(images/texture.png), -moz-linear-gradient(hsla(0,0%,30%,.99), hsla(0,0%,25%,.95)); background-image: url(images/texture.png), - -webkit-linear-gradient(hsla(0,0%,30%,.99), hsla(0,0%,25%,.95)); + -ms-linear-gradient(hsla(0,0%,30%,.99), hsla(0,0%,25%,.95)); + background-image: url(images/texture.png), + -o-linear-gradient(hsla(0,0%,30%,.99), hsla(0,0%,25%,.95)); + background-image: url(images/texture.png), + linear-gradient(hsla(0,0%,30%,.99), hsla(0,0%,25%,.95)); box-shadow: inset -2px 0 0 hsla(0,0%,100%,.08), inset 0 1px 1px hsla(0,0%,0%,.15), inset 0 -1px 0 hsla(0,0%,100%,.05), @@ -161,10 +197,16 @@ html[dir='rtl'] #sidebarContent { #toolbarViewer { position: relative; height: 32px; + background-image: url(images/texture.png), + -webkit-linear-gradient(hsla(0,0%,32%,.99), hsla(0,0%,27%,.95)); background-image: url(images/texture.png), -moz-linear-gradient(hsla(0,0%,32%,.99), hsla(0,0%,27%,.95)); background-image: url(images/texture.png), - -webkit-linear-gradient(hsla(0,0%,32%,.99), hsla(0,0%,27%,.95)); + -ms-linear-gradient(hsla(0,0%,32%,.99), hsla(0,0%,27%,.95)); + background-image: url(images/texture.png), + -o-linear-gradient(hsla(0,0%,32%,.99), hsla(0,0%,27%,.95)); + background-image: url(images/texture.png), + linear-gradient(hsla(0,0%,32%,.99), hsla(0,0%,27%,.95)); border-left: 1px solid hsla(0,0%,0%,.5); box-shadow: inset 1px 0 0 hsla(0,0%,100%,.08), inset 0 1px 1px hsla(0,0%,0%,.15), @@ -251,20 +293,33 @@ html[dir='rtl'] .splitToolbarButton > .toolbarButton { .splitToolbarButton.toggled > .toolbarButton, .toolbarButton.textButton { background-color: hsla(0,0%,0%,.12); - background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); background-image: -webkit-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); + background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); + background-image: -ms-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); + background-image: -o-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); + background-image: linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); background-clip: padding-box; border: 1px solid hsla(0,0%,0%,.35); border-color: hsla(0,0%,0%,.32) hsla(0,0%,0%,.38) hsla(0,0%,0%,.42); box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset, 0 0 1px hsla(0,0%,100%,.15) inset, 0 1px 0 hsla(0,0%,100%,.05); - -moz-transition-property: background-color, border-color, box-shadow; - -moz-transition-duration: 150ms; - -moz-transition-timing-function: ease; -webkit-transition-property: background-color, border-color, box-shadow; -webkit-transition-duration: 150ms; -webkit-transition-timing-function: ease; + -moz-transition-property: background-color, border-color, box-shadow; + -moz-transition-duration: 150ms; + -moz-transition-timing-function: ease; + -ms-transition-property: background-color, border-color, box-shadow; + -ms-transition-duration: 150ms; + -ms-transition-timing-function: ease; + -o-transition-property: background-color, border-color, box-shadow; + -o-transition-duration: 150ms; + -o-transition-timing-function: ease; + transition-property: background-color, border-color, box-shadow; + transition-duration: 150ms; + transition-timing-function: ease; + } .splitToolbarButton > .toolbarButton:hover, .splitToolbarButton > .toolbarButton:focus, @@ -315,12 +370,21 @@ html[dir='rtl'] .splitToolbarButtonSeparator { padding: 12px 0; margin: 0; box-shadow: 0 0 0 1px hsla(0,0%,100%,.03); - -moz-transition-property: padding; - -moz-transition-duration: 10ms; - -moz-transition-timing-function: ease; -webkit-transition-property: padding; -webkit-transition-duration: 10ms; -webkit-transition-timing-function: ease; + -moz-transition-property: padding; + -moz-transition-duration: 10ms; + -moz-transition-timing-function: ease; + -ms-transition-property: padding; + -ms-transition-duration: 10ms; + -ms-transition-timing-function: ease; + -o-transition-property: padding; + -o-transition-duration: 10ms; + -o-transition-timing-function: ease; + transition-property: padding; + transition-duration: 10ms; + transition-timing-function: ease; } .toolbarButton, @@ -332,15 +396,26 @@ html[dir='rtl'] .splitToolbarButtonSeparator { color: hsl(0,0%,95%); font-size: 12px; line-height: 14px; - -moz-user-select:none; -webkit-user-select:none; + -moz-user-select:none; + -ms-user-select:none; + /* Opera does not support user-select, use <... unselectable="on"> instead */ cursor: default; - -moz-transition-property: background-color, border-color, box-shadow; - -moz-transition-duration: 150ms; - -moz-transition-timing-function: ease; -webkit-transition-property: background-color, border-color, box-shadow; -webkit-transition-duration: 150ms; -webkit-transition-timing-function: ease; + -moz-transition-property: background-color, border-color, box-shadow; + -moz-transition-duration: 150ms; + -moz-transition-timing-function: ease; + -ms-transition-property: background-color, border-color, box-shadow; + -ms-transition-duration: 150ms; + -ms-transition-timing-function: ease; + -o-transition-property: background-color, border-color, box-shadow; + -o-transition-duration: 150ms; + -o-transition-timing-function: ease; + transition-property: background-color, border-color, box-shadow; + transition-duration: 150ms; + transition-timing-function: ease; } html[dir='ltr'] .toolbarButton, @@ -356,8 +431,11 @@ html[dir='rtl'] .dropdownToolbarButton { .toolbarButton:focus, .dropdownToolbarButton { background-color: hsla(0,0%,0%,.12); - background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); background-image: -webkit-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); + background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); + background-image: -ms-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); + background-image: -o-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); + background-image: linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); background-clip: padding-box; border: 1px solid hsla(0,0%,0%,.35); border-color: hsla(0,0%,0%,.32) hsla(0,0%,0%,.38) hsla(0,0%,0%,.42); @@ -369,35 +447,59 @@ html[dir='rtl'] .dropdownToolbarButton { .toolbarButton:hover:active, .dropdownToolbarButton:hover:active { background-color: hsla(0,0%,0%,.2); - background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); background-image: -webkit-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); + background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); + background-image: -ms-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); + background-image: -o-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); + background-image: linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); border-color: hsla(0,0%,0%,.35) hsla(0,0%,0%,.4) hsla(0,0%,0%,.45); box-shadow: 0 1px 1px hsla(0,0%,0%,.1) inset, 0 0 1px hsla(0,0%,0%,.2) inset, 0 1px 0 hsla(0,0%,100%,.05); - -moz-transition-property: background-color, border-color, box-shadow; - -moz-transition-duration: 10ms; - -moz-transition-timing-function: linear; -webkit-transition-property: background-color, border-color, box-shadow; -webkit-transition-duration: 10ms; -webkit-transition-timing-function: linear; + -moz-transition-property: background-color, border-color, box-shadow; + -moz-transition-duration: 10ms; + -moz-transition-timing-function: linear; + -ms-transition-property: background-color, border-color, box-shadow; + -ms-transition-duration: 10ms; + -ms-transition-timing-function: linear; + -o-transition-property: background-color, border-color, box-shadow; + -o-transition-duration: 10ms; + -o-transition-timing-function: linear; + transition-property: background-color, border-color, box-shadow; + transition-duration: 10ms; + transition-timing-function: linear; } .toolbarButton.toggled, .splitToolbarButton.toggled > .toolbarButton.toggled { background-color: hsla(0,0%,0%,.3); - background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); background-image: -webkit-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); + background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); + background-image: -ms-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); + background-image: -o-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); + background-image: linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); border-color: hsla(0,0%,0%,.4) hsla(0,0%,0%,.45) hsla(0,0%,0%,.5); box-shadow: 0 1px 1px hsla(0,0%,0%,.1) inset, 0 0 1px hsla(0,0%,0%,.2) inset, 0 1px 0 hsla(0,0%,100%,.05); - -moz-transition-property: background-color, border-color, box-shadow; - -moz-transition-duration: 10ms; - -moz-transition-timing-function: linear; -webkit-transition-property: background-color, border-color, box-shadow; -webkit-transition-duration: 10ms; -webkit-transition-timing-function: linear; + -moz-transition-property: background-color, border-color, box-shadow; + -moz-transition-duration: 10ms; + -moz-transition-timing-function: linear; + -ms-transition-property: background-color, border-color, box-shadow; + -ms-transition-duration: 10ms; + -ms-transition-timing-function: linear; + -o-transition-property: background-color, border-color, box-shadow; + -o-transition-duration: 10ms; + -o-transition-timing-function: linear; + transition-property: background-color, border-color, box-shadow; + transition-duration: 10ms; + transition-timing-function: linear; } .toolbarButton.toggled:hover:active, @@ -424,8 +526,8 @@ html[dir='rtl'] .dropdownToolbarButton { } .dropdownToolbarButton > select { - -moz-appearance: none; /* in the future this might matter, see bugzilla bug #649849 */ -webkit-appearance: none; + -moz-appearance: none; /* in the future this might matter, see bugzilla bug #649849 */ min-width: 140px; font-size: 12px; color: hsl(0,0%,95%); @@ -467,8 +569,8 @@ html[dir='rtl'] .toolbarButton:first-child { } .toolbarButtonFlexibleSpacer { - -moz-box-flex: 1; -webkit-box-flex: 1; + -moz-box-flex: 1; min-width: 30px; } @@ -523,8 +625,8 @@ html[dir='rtl'] .toolbarButton.pageDown::before { } .toolbarButton.bookmark { - -moz-box-sizing: border-box; -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; box-sizing: border-box; margin-top: 3px; padding-top: 4px; @@ -603,8 +705,8 @@ html[dir='rtl'] .toolbarButton.pageDown::before { font-size: 12px; line-height: 14px; text-align: left; - -moz-user-select:none; -webkit-user-select:none; + -moz-user-select:none; cursor: default; } @@ -680,8 +782,8 @@ a:focus > .thumbnail > .thumbnailSelectionRing, bottom: 0; padding: 4px 4px 0; overflow: auto; - -moz-user-select:none; -webkit-user-select:none; + -moz-user-select:none; } .outlineItem > .outlineItems { @@ -791,9 +893,9 @@ canvas { margin: 10px auto; position: relative; overflow: hidden; - box-shadow: 0px 4px 10px #000; - -moz-box-shadow: 0px 4px 10px #000; -webkit-box-shadow: 0px 4px 10px #000; + -moz-box-shadow: 0px 4px 10px #000; + box-shadow: 0px 4px 10px #000; background-color: white; } @@ -805,9 +907,9 @@ canvas { .page > a:hover { opacity: 0.2; background: #ff0; - box-shadow: 0px 2px 10px #ff0; - -moz-box-shadow: 0px 2px 10px #ff0; -webkit-box-shadow: 0px 2px 10px #ff0; + -moz-box-shadow: 0px 2px 10px #ff0; + box-shadow: 0px 2px 10px #ff0; } .loadingIcon { @@ -855,12 +957,13 @@ canvas { float: left; background: #666; - background: -moz-linear-gradient(top, #b2b2b2 0%, #898989 100%); background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#b2b2b2), color-stop(100%,#898989)); background: -webkit-linear-gradient(top, #b2b2b2 0%,#898989 100%); - background: -o-linear-gradient(top, #b2b2b2 0%,#898989 100%); + background: -moz-linear-gradient(top, #b2b2b2 0%,#898989 100%); background: -ms-linear-gradient(top, #b2b2b2 0%,#898989 100%); - background: linear-gradient(top, #b2b2b2 0%,#898989 100%); + background: -o-linear-gradient(top, #b2b2b2 0%,#898989 100%); + background: linear-gradient(top, #b2b2b2 0%,#898989 100%); + border-top-left-radius: 2px; border-bottom-left-radius: 2px; @@ -912,9 +1015,9 @@ canvas { padding: 0.2em; max-width: 20em; background-color: #F1E47B; - box-shadow: 0px 2px 10px #333; - -moz-box-shadow: 0px 2px 10px #333; -webkit-box-shadow: 0px 2px 10px #333; + -moz-box-shadow: 0px 2px 10px #333; + box-shadow: 0px 2px 10px #333; } .annotComment > div > h1 { @@ -1024,9 +1127,9 @@ canvas { .page { float: left; display: none; - box-shadow: none; - -moz-box-shadow: none; -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; } .page[data-loaded] { diff --git a/web/viewer.js b/web/viewer.js index 2078175e7..d371c3242 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -1846,6 +1846,18 @@ window.addEventListener('pagechange', function pagechange(evt) { document.getElementById('next').disabled = (page >= PDFView.pages.length); }, true); +// Firefox specific event, so that we can prevent browser from zooming +window.addEventListener('DOMMouseScroll', function(evt) { + if (evt.ctrlKey) { + evt.preventDefault(); + + var ticks = evt.detail; + var direction = (ticks > 0) ? 'zoomOut' : 'zoomIn'; + for (var i = 0, length = Math.abs(ticks); i < length; i++) + PDFView[direction](); + } +}, false); + window.addEventListener('keydown', function keydown(evt) { var handled = false; var cmd = (evt.ctrlKey ? 1 : 0) |