diff --git a/examples/node/domstubs.js b/examples/node/domstubs.js index dafc75832..b0e422b8a 100644 --- a/examples/node/domstubs.js +++ b/examples/node/domstubs.js @@ -99,7 +99,7 @@ DOMElement.prototype = { attrList.push(i + '="' + xmlEncode(this.attributes[i]) + '"'); } - if (this.nodeName === 'svg:tspan') { + if (this.nodeName === 'svg:tspan' || this.nodeName === 'svg:style') { var encText = xmlEncode(this.textContent); return '<' + this.nodeName + ' ' + attrList.join(' ') + '>' + encText + ''; diff --git a/examples/node/pdf2svg.js b/examples/node/pdf2svg.js index 6da69b165..f5979cacc 100644 --- a/examples/node/pdf2svg.js +++ b/examples/node/pdf2svg.js @@ -65,8 +65,9 @@ PDFJS.getDocument(data).then(function (doc) { return page.getOperatorList().then(function (opList) { var svgGfx = new PDFJS.SVGGraphics(page.commonObjs, page.objs); - return svgGfx.loadDependencies(opList).then(function (values) { - var svgDump = svgGfx.getSVG(viewport, pageNum, opList).toString(); + svgGfx.embedFonts = true; + return svgGfx.getSVG(opList, viewport).then(function (svg) { + var svgDump = svg.toString(); writeToFile(svgDump, pageNum); }); }); diff --git a/examples/svgviewer/viewer.js b/examples/svgviewer/viewer.js index 90d8de3d0..ddbb6fa34 100644 --- a/examples/svgviewer/viewer.js +++ b/examples/svgviewer/viewer.js @@ -48,8 +48,8 @@ PDFJS.getDocument(url).then(function(pdf) { return page.getOperatorList().then(function (opList) { var svgGfx = new PDFJS.SVGGraphics(page.commonObjs, page.objs); - return svgGfx.loadDependencies(opList).then(function (values) { - container.appendChild(svgGfx.getSVG(viewport, pageNum, opList)); + return svgGfx.getSVG(opList, viewport).then(function (svg) { + container.appendChild(svg); }); }); }); diff --git a/make.js b/make.js index 4a3e6e0f9..55945af0b 100644 --- a/make.js +++ b/make.js @@ -380,6 +380,7 @@ target.bundle = function(args) { 'display/pattern_helper.js', 'display/font_loader.js', 'display/annotation_helper.js', + 'display/svg.js' ]); var srcFiles = builder.getWorkerSrcFiles('src/worker_loader.js'); diff --git a/src/display/svg.js b/src/display/svg.js index 124861a50..09ce2d9f9 100644 --- a/src/display/svg.js +++ b/src/display/svg.js @@ -19,16 +19,7 @@ 'use strict'; -function createScratchSVG(width, height) { - var NS = 'http://www.w3.org/2000/svg'; - var svg = document.createElementNS(NS, 'svg:svg'); - svg.setAttributeNS(null, 'version', '1.1'); - svg.setAttributeNS(null, 'width', width + 'px'); - svg.setAttributeNS(null, 'height', height + 'px'); - svg.setAttributeNS(null, 'viewBox', '0 0 ' + width + ' ' + height); - return svg; -} - +//#if (GENERIC || SINGLE_FILE) var convertImgDataToPng = (function convertImgDataToPngClosure() { var PNG_HEADER = new Uint8Array([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]); @@ -281,6 +272,16 @@ var SVGExtraState = (function SVGExtraStateClosure() { })(); var SVGGraphics = (function SVGGraphicsClosure() { + function createScratchSVG(width, height) { + var NS = 'http://www.w3.org/2000/svg'; + var svg = document.createElementNS(NS, 'svg:svg'); + svg.setAttributeNS(null, 'version', '1.1'); + svg.setAttributeNS(null, 'width', width + 'px'); + svg.setAttributeNS(null, 'height', height + 'px'); + svg.setAttributeNS(null, 'viewBox', '0 0 ' + width + ' ' + height); + return svg; + } + function opListToTree(opList) { var opTree = []; var tmp = []; @@ -360,6 +361,10 @@ var SVGGraphics = (function SVGGraphicsClosure() { this.commonObjs = commonObjs; this.objs = objs; this.pendingEOFill = false; + + this.embedFonts = false; + this.embeddedFonts = {}; + this.cssStyle = null; } var NS = 'http://www.w3.org/2000/svg'; @@ -431,21 +436,24 @@ var SVGGraphics = (function SVGGraphicsClosure() { this.tgrp.setAttributeNS(null, 'transform', pm(this.transformMatrix)); }, - getSVG: function SVGGraphics_getSVG(viewport, pageNum, operatorList) { + getSVG: function SVGGraphics_getSVG(operatorList, viewport) { this.svg = createScratchSVG(viewport.width, viewport.height); this.viewport = viewport; - this.transformMatrix = IDENTITY_MATRIX; - this.pgrp = document.createElementNS(NS, 'svg:g'); // Parent group - this.pgrp.setAttributeNS(null, 'transform', pm(viewport.transform)); - this.tgrp = document.createElementNS(NS, 'svg:g'); // Transform group - this.tgrp.setAttributeNS(null, 'transform', pm(this.transformMatrix)); - this.defs = document.createElementNS(NS, 'svg:defs'); - this.pgrp.appendChild(this.defs); - this.pgrp.appendChild(this.tgrp); - this.svg.appendChild(this.pgrp); - var opTree = this.convertOpList(operatorList); - this.executeOpTree(opTree); - return this.svg; + + return this.loadDependencies(operatorList).then(function () { + this.transformMatrix = IDENTITY_MATRIX; + this.pgrp = document.createElementNS(NS, 'svg:g'); // Parent group + this.pgrp.setAttributeNS(null, 'transform', pm(viewport.transform)); + this.tgrp = document.createElementNS(NS, 'svg:g'); // Transform group + this.tgrp.setAttributeNS(null, 'transform', pm(this.transformMatrix)); + this.defs = document.createElementNS(NS, 'svg:defs'); + this.pgrp.appendChild(this.defs); + this.pgrp.appendChild(this.tgrp); + this.svg.appendChild(this.pgrp); + var opTree = this.convertOpList(operatorList); + this.executeOpTree(opTree); + return this.svg; + }.bind(this)); }, convertOpList: function SVGGraphics_convertOpList(operatorList) { @@ -724,12 +732,31 @@ var SVGGraphics = (function SVGGraphicsClosure() { this.moveText(x, y); }, + addFontStyle: function SVGGraphics_addFontStyle(fontObj) { + if (!this.cssStyle) { + this.cssStyle = document.createElementNS(NS, 'svg:style'); + this.cssStyle.setAttributeNS(null, 'type', 'text/css'); + this.defs.appendChild(this.cssStyle); + } + + var url = PDFJS.createObjectURL(fontObj.data, fontObj.mimetype); + this.cssStyle.textContent += + '@font-face { font-family: "' + fontObj.loadedName + '";' + + ' src: url(' + url + '); }\n'; + }, + setFont: function SVGGraphics_setFont(details) { var current = this.current; var fontObj = this.commonObjs.get(details[0]); var size = details[1]; this.current.font = fontObj; + if (this.embedFonts && fontObj.data && + !this.embeddedFonts[fontObj.loadedName]) { + this.addFontStyle(fontObj); + this.embeddedFonts[fontObj.loadedName] = fontObj; + } + current.fontMatrix = (fontObj.fontMatrix ? fontObj.fontMatrix : FONT_IDENTITY_MATRIX); @@ -1024,7 +1051,7 @@ var SVGGraphics = (function SVGGraphicsClosure() { var current = this.current; var imgObj = this.objs.get(objId); var imgEl = document.createElementNS(NS, 'svg:image'); - imgEl.setAttributeNS(XLINK_NS, 'href', imgObj.src); + imgEl.setAttributeNS(XLINK_NS, 'xlink:href', imgObj.src); imgEl.setAttributeNS(null, 'width', imgObj.width + 'px'); imgEl.setAttributeNS(null, 'height', imgObj.height + 'px'); imgEl.setAttributeNS(null, 'x', '0'); @@ -1065,7 +1092,7 @@ var SVGGraphics = (function SVGGraphicsClosure() { current.element = cliprect; this.clip('nonzero'); var imgEl = document.createElementNS(NS, 'svg:image'); - imgEl.setAttributeNS(XLINK_NS, 'href', imgSrc); + imgEl.setAttributeNS(XLINK_NS, 'xlink:href', imgSrc); imgEl.setAttributeNS(null, 'x', '0'); imgEl.setAttributeNS(null, 'y', pf(-height)); imgEl.setAttributeNS(null, 'width', pf(width) + 'px'); @@ -1114,4 +1141,4 @@ var SVGGraphics = (function SVGGraphicsClosure() { })(); PDFJS.SVGGraphics = SVGGraphics; - +//#endif