From bc574aa629b968107a8cc35ff08b0953731f10b6 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Thu, 14 Aug 2014 12:56:11 -0500 Subject: [PATCH 1/3] Refactors SVG api --- examples/node/pdf2svg.js | 4 +-- examples/svgviewer/viewer.js | 4 +-- src/display/svg.js | 49 +++++++++++++++++++----------------- 3 files changed, 30 insertions(+), 27 deletions(-) diff --git a/examples/node/pdf2svg.js b/examples/node/pdf2svg.js index 6da69b165..482714909 100644 --- a/examples/node/pdf2svg.js +++ b/examples/node/pdf2svg.js @@ -65,8 +65,8 @@ 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(); + 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/src/display/svg.js b/src/display/svg.js index 124861a50..3c8fd24b3 100644 --- a/src/display/svg.js +++ b/src/display/svg.js @@ -19,16 +19,6 @@ '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; -} - var convertImgDataToPng = (function convertImgDataToPngClosure() { var PNG_HEADER = new Uint8Array([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]); @@ -281,6 +271,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 = []; @@ -431,21 +431,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) { From 0f862e7eb3d9c854950d59faa81dc7c840f7b5fa Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Thu, 14 Aug 2014 13:02:30 -0500 Subject: [PATCH 2/3] Adds svg.js to the generic and singlefile builds --- make.js | 1 + src/display/svg.js | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) 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 3c8fd24b3..d84b6a1e6 100644 --- a/src/display/svg.js +++ b/src/display/svg.js @@ -19,6 +19,7 @@ 'use strict'; +//#if (GENERIC || SINGLE_FILE) var convertImgDataToPng = (function convertImgDataToPngClosure() { var PNG_HEADER = new Uint8Array([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]); @@ -1117,4 +1118,4 @@ var SVGGraphics = (function SVGGraphicsClosure() { })(); PDFJS.SVGGraphics = SVGGraphics; - +//#endif From de23d3791e53e651ab9c1a5fd79cbc85cce934cc Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Thu, 14 Aug 2014 15:11:27 -0500 Subject: [PATCH 3/3] Fixes image and font embedding --- examples/node/domstubs.js | 2 +- examples/node/pdf2svg.js | 1 + src/display/svg.js | 27 +++++++++++++++++++++++++-- 3 files changed, 27 insertions(+), 3 deletions(-) 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 482714909..f5979cacc 100644 --- a/examples/node/pdf2svg.js +++ b/examples/node/pdf2svg.js @@ -65,6 +65,7 @@ PDFJS.getDocument(data).then(function (doc) { return page.getOperatorList().then(function (opList) { var svgGfx = new PDFJS.SVGGraphics(page.commonObjs, page.objs); + svgGfx.embedFonts = true; return svgGfx.getSVG(opList, viewport).then(function (svg) { var svgDump = svg.toString(); writeToFile(svgDump, pageNum); diff --git a/src/display/svg.js b/src/display/svg.js index d84b6a1e6..09ce2d9f9 100644 --- a/src/display/svg.js +++ b/src/display/svg.js @@ -361,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'; @@ -728,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); @@ -1028,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'); @@ -1069,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');