From 03f1de34035293bc8d8800459736a58c8fc28a8c Mon Sep 17 00:00:00 2001 From: pramodhkp Date: Thu, 3 Jul 2014 21:29:04 +0530 Subject: [PATCH 1/5] Added clip operator --- src/display/svg.js | 46 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/src/display/svg.js b/src/display/svg.js index efffc36a1..8c231c417 100644 --- a/src/display/svg.js +++ b/src/display/svg.js @@ -62,7 +62,10 @@ var SVGExtraState = (function SVGExtraStateClosure() { // Dependency this.dependencies = []; - this.count = 0; + + // Clipping + this.clipId = ''; + this.pendingClip = false; } SVGExtraState.prototype = { @@ -122,6 +125,7 @@ var SVGGraphics = (function SVGGraphicsClosure(ctx) { var LINE_JOIN_STYLES = ['miter', 'round', 'bevel']; var NORMAL_CLIP = {}; var EO_CLIP = {}; + var clipCount = 0; SVGGraphics.prototype = { save: function SVGGraphics_save() { @@ -199,6 +203,8 @@ var SVGGraphics = (function SVGGraphicsClosure(ctx) { this.tgrp = document.createElementNS(NS, 'svg:g'); // Transform group this.tgrp.setAttributeNS(null, 'transform', 'matrix(' + this.transformMatrix +')'); + this.defs = document.createElementNS(NS, 'svg:defs'); + this.pgrp.appendChild(this.defs); this.pgrp.appendChild(this.tgrp); this.svg.appendChild(this.pgrp); this.container.appendChild(this.svg); @@ -307,6 +313,12 @@ var SVGGraphics = (function SVGGraphicsClosure(ctx) { case OPS.fillStroke: this.fillStroke(); break; + case OPS.clip: + this.clip('nonzero'); + break; + case OPS.eoClip: + this.clip('evenodd'); + break; case OPS.paintSolidColorImageMask: this.paintSolidColorImageMask(); break; @@ -579,6 +591,9 @@ var SVGGraphics = (function SVGGraphicsClosure(ctx) { current.path.setAttributeNS(null, 'stroke-dasharray', current.dashArray); current.path.setAttributeNS(null, 'stroke-dashoffset', current.dashPhase + 'px'); + if (current.pendingClip) { + this.cgrp.appendChild(this.tgrp); + } current.path.setAttributeNS(null, 'fill', 'none'); this.tgrp.appendChild(current.path); // Saving a reference in current.element so that it can be addressed @@ -587,6 +602,30 @@ var SVGGraphics = (function SVGGraphicsClosure(ctx) { current.setCurrentPoint(x, y); }, + clip: function SVGGraphics_clip(type) { + var current = this.current; + // Add current path to clipping path + current.clipId = 'clippath' + clipCount; + clipCount++; + this.clippath = document.createElementNS(NS, 'svg:clipPath'); + this.clippath.setAttributeNS(null, 'id', current.clipId); + var clipElement = current.element.cloneNode(); + if (type == 'evenodd') { + clipElement.setAttributeNS(null, 'clip-rule', 'evenodd'); + } else { + clipElement.setAttributeNS(null, 'clip-rule', 'nonzero'); + } + this.clippath.appendChild(clipElement); + this.defs.appendChild(this.clippath); + + // Create a new group with that attribute + current.pendingClip = true; + this.cgrp = document.createElementNS(NS, 'svg:g'); + this.cgrp.setAttributeNS(null, 'clip-path', + 'url(#' + current.clipId + ')'); + this.pgrp.appendChild(this.cgrp); + }, + closePath: function SVGGraphics_closePath() { var current = this.current; var d = current.path.getAttributeNS(null, 'd'); @@ -650,14 +689,12 @@ var SVGGraphics = (function SVGGraphicsClosure(ctx) { fill: function SVGGraphics_fill() { var current = this.current; current.element.setAttributeNS(null, 'fill', current.fillColor); - this.tgrp.appendChild(current.element); }, stroke: function SVGGraphics_stroke() { var current = this.current; current.element.setAttributeNS(null, 'stroke', current.strokeColor); current.element.setAttributeNS(null, 'fill', 'none'); - this.tgrp.appendChild(current.element); }, eoFill: function SVGGraphics_eoFill() { @@ -705,6 +742,9 @@ var SVGGraphics = (function SVGGraphicsClosure(ctx) { imgEl.setAttributeNS(null, 'y', -h); imgEl.setAttributeNS(null, 'transform', 'scale(' + 1 / w + ' ' + -1 / h + ')'); + if (current.pendingClip) { + this.cgrp.appendChild(this.tgrp); + } this.tgrp.appendChild(imgEl); }, }; From 0688fd3d701335b9eb9971822ca7b526a15cc7f9 Mon Sep 17 00:00:00 2001 From: pramodhkp Date: Thu, 3 Jul 2014 21:33:31 +0530 Subject: [PATCH 2/5] Added fill, stroke, line-join & font attr --- src/display/svg.js | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/src/display/svg.js b/src/display/svg.js index 8c231c417..fcdb8d05b 100644 --- a/src/display/svg.js +++ b/src/display/svg.js @@ -33,8 +33,10 @@ function createScratchSVG(width, height) { var SVGExtraState = (function SVGExtraStateClosure() { function SVGExtraState(old) { // Are soft masks and alpha values shapes or opacities? - this.fontSize = 0; this.fontSizeScale = 1; + this.fontWeight = 'normal'; + this.fontSize = 'normal'; + this.textMatrix = IDENTITY_MATRIX; this.fontMatrix = FONT_IDENTITY_MATRIX; this.leading = 0; @@ -313,6 +315,9 @@ var SVGGraphics = (function SVGGraphicsClosure(ctx) { case OPS.fillStroke: this.fillStroke(); break; + case OPS.eoFillStroke: + this.eoFillStroke(); + break; case OPS.clip: this.clip('nonzero'); break; @@ -453,8 +458,13 @@ var SVGGraphics = (function SVGGraphicsClosure(ctx) { } current.tspan.setAttributeNS(null, 'x', current.xcoords.join(' ')); + current.tspan.setAttributeNS(null, 'y', -current.y); current.tspan.setAttributeNS(null, 'font-family', current.fontFamily); current.tspan.setAttributeNS(null, 'font-size', current.fontSize + 'px'); + current.tspan.setAttributeNS(null, 'font-style', current.fontStyle); + current.tspan.setAttributeNS(null, 'font-weight', current.fontWeight); + current.tspan.setAttributeNS(null, 'stroke', 'none'); + current.tspan.setAttributeNS(null, 'fill', current.fillColor); current.txtElement.setAttributeNS(null, 'transform', 'matrix(' + current.textMatrix + ') scale(1, -1)' ); @@ -485,10 +495,6 @@ var SVGGraphics = (function SVGGraphicsClosure(ctx) { var italic = fontObj.italic ? 'italic' : 'normal'; - current.font.style = (bold == 'normal' ? - (italic == 'normal' ? - '' : 'font-weight:' + italic) : - 'font-weight:' + bold); if (size < 0) { size = -size; @@ -498,6 +504,12 @@ var SVGGraphics = (function SVGGraphicsClosure(ctx) { } current.fontSize = size; current.fontFamily = fontObj.loadedName; + current.fontWeight = bold; + current.fontStyle = italic; + + current.tspan = document.createElementNS(NS, 'svg:tspan'); + current.tspan.setAttributeNS(null, 'y', -current.y); + current.xcoords = []; }, endText: function SVGGraphics_endText(args) { @@ -524,6 +536,8 @@ var SVGGraphics = (function SVGGraphicsClosure(ctx) { setFillRGBColor: function SVGGraphics_setFillRGBColor(r, g, b) { var color = Util.makeCssRgb(arguments); this.current.fillColor = color; + this.current.tspan = document.createElementNS(NS, 'svg:tspan'); + this.current.xcoords = []; }, setDash: function SVGGraphics_setDash(dashArray, dashPhase) { this.current.dashArray = dashArray; @@ -586,6 +600,7 @@ var SVGGraphics = (function SVGGraphicsClosure(ctx) { current.path.setAttributeNS(null, 'stroke-miterlimit', current.miterLimit); current.path.setAttributeNS(null, 'stroke-linecap', current.lineCap); + current.path.setAttributeNS(null, 'stroke-linejoin', current.lineJoin); current.path.setAttributeNS(null, 'stroke-width', current.lineWidth + 'px'); current.path.setAttributeNS(null, 'stroke-dasharray', current.dashArray); @@ -704,8 +719,15 @@ var SVGGraphics = (function SVGGraphicsClosure(ctx) { }, fillStroke: function SVGGraphics_fillStroke() { - this.fill(); + // Order is important since stroke wants fill to be none. + // First stroke, then if fill needed, it will be overwritten. this.stroke(); + this.fill(); + }, + + eoFillStroke: function SVGGraphics_eoFillStroke() { + this.current.element.setAttributeNS(null, 'fill-rule', 'evenodd'); + this.fillStroke(); }, closeStroke: function SVGGraphics_closeStroke() { From a55c9856e9e07148df97985eb90ea24c7461481b Mon Sep 17 00:00:00 2001 From: pramodhkp Date: Thu, 3 Jul 2014 21:37:05 +0530 Subject: [PATCH 3/5] Misc variable initialization --- src/display/svg.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/display/svg.js b/src/display/svg.js index fcdb8d05b..c253b4641 100644 --- a/src/display/svg.js +++ b/src/display/svg.js @@ -61,6 +61,9 @@ var SVGExtraState = (function SVGExtraStateClosure() { this.lineJoin = ''; this.lineCap = ''; this.miterLimit = 0; + + this.dashArray = []; + this.dashPhase = 0; // Dependency this.dependencies = []; From 2380b38b27ee0d06958055f4280f1dca84696a14 Mon Sep 17 00:00:00 2001 From: pramodhkp Date: Sat, 5 Jul 2014 14:18:11 +0530 Subject: [PATCH 4/5] Fixed setGState, viewport transform --- src/display/svg.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/display/svg.js b/src/display/svg.js index c253b4641..b5878e175 100644 --- a/src/display/svg.js +++ b/src/display/svg.js @@ -25,8 +25,7 @@ function createScratchSVG(width, height) { svg.setAttributeNS(null, 'version', '1.1'); svg.setAttributeNS(null, 'width', width + 'px'); svg.setAttributeNS(null, 'height', height + 'px'); - svg.setAttributeNS(null, 'viewBox', '0 ' + (-height) + ' ' + - width + ' ' + height); + svg.setAttributeNS(null, 'viewBox', '0 0 ' + width + ' ' + height); return svg; } @@ -203,8 +202,8 @@ var SVGGraphics = (function SVGGraphicsClosure(ctx) { this.viewport = viewport; this.transformMatrix = IDENTITY_MATRIX; this.pgrp = document.createElementNS(NS, 'svg:g'); // Parent group - this.pgrp.setAttributeNS(null, 'transform', 'scale(' + viewport.scale + - ',' + -viewport.scale + ')'); + this.pgrp.setAttributeNS(null, 'transform', + 'matrix(' + viewport.transform +')'); this.tgrp = document.createElementNS(NS, 'svg:g'); // Transform group this.tgrp.setAttributeNS(null, 'transform', 'matrix(' + this.transformMatrix +')'); @@ -304,7 +303,7 @@ var SVGGraphics = (function SVGGraphicsClosure(ctx) { this.setDash(args[0], args[1]); break; case OPS.setGState: - this.setGState(args); + this.setGState(args[0]); break; case OPS.fill: this.fill(); @@ -690,7 +689,7 @@ var SVGGraphics = (function SVGGraphicsClosure(ctx) { case 'FL': break; case 'Font': - this.setFont(value[0], value[1]); + this.setFont(value); break; case 'CA': break; From 6e4dd83a4d1729bf0af0470d29746a12f6ece3b7 Mon Sep 17 00:00:00 2001 From: pramodhkp Date: Fri, 25 Jul 2014 17:59:10 +0530 Subject: [PATCH 5/5] Added endPath, endText. fixes extra elements --- src/display/svg.js | 43 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/src/display/svg.js b/src/display/svg.js index b5878e175..6431ebf02 100644 --- a/src/display/svg.js +++ b/src/display/svg.js @@ -192,7 +192,6 @@ var SVGGraphics = (function SVGGraphicsClosure(ctx) { this.tgrp = document.createElementNS(NS, 'svg:g'); this.tgrp.setAttributeNS(null, 'transform', 'matrix(' + this.transformMatrix + ')'); - this.pgrp.appendChild(this.tgrp); }, beginDrawing: function SVGGraphics_beginDrawing(viewport, pageNum, @@ -266,7 +265,7 @@ var SVGGraphics = (function SVGGraphicsClosure(ctx) { this.showText(args[0]); break; case OPS.endText: - this.endText(args); + this.endText(); break; case OPS.moveText: this.moveText(args[0], args[1]); @@ -351,6 +350,9 @@ var SVGGraphics = (function SVGGraphicsClosure(ctx) { case OPS.constructPath: this.constructPath(args[0], args[1]); break; + case OPS.endPath: + this.endPath(); + break; case 92: this.group(opTree[x].items); break; @@ -477,7 +479,7 @@ var SVGGraphics = (function SVGGraphicsClosure(ctx) { this.tgrp.appendChild(current.txtElement); }, - + setLeadingMoveText: function SVGGraphics_setLeadingMoveText(x, y) { this.setLeading(-y); this.moveText(x, y); @@ -515,7 +517,14 @@ var SVGGraphics = (function SVGGraphicsClosure(ctx) { }, endText: function SVGGraphics_endText(args) { - // Empty for now. Not sure how to break showText into this. + if (this.current.pendingClip) { + this.pgrp.appendChild(this.cgrp); + } else { + this.pgrp.appendChild(this.tgrp); + } + this.tgrp = document.createElementNS(NS, 'svg:g'); + this.tgrp.setAttributeNS(null, 'transform', + 'matrix(' + this.transformMatrix + ')'); }, // Path properties @@ -608,17 +617,33 @@ var SVGGraphics = (function SVGGraphicsClosure(ctx) { current.path.setAttributeNS(null, 'stroke-dasharray', current.dashArray); current.path.setAttributeNS(null, 'stroke-dashoffset', current.dashPhase + 'px'); + current.path.setAttributeNS(null, 'fill', 'none'); + + this.tgrp.appendChild(current.path); if (current.pendingClip) { this.cgrp.appendChild(this.tgrp); + this.pgrp.appendChild(this.cgrp); + } else { + this.pgrp.appendChild(this.tgrp); } - current.path.setAttributeNS(null, 'fill', 'none'); - this.tgrp.appendChild(current.path); // Saving a reference in current.element so that it can be addressed // in 'fill' and 'stroke' current.element = current.path; current.setCurrentPoint(x, y); }, + endPath: function SVGGraphics_endPath() { + var current = this.current; + if (current.pendingClip) { + this.pgrp.appendChild(this.cgrp); + } else { + this.pgrp.appendChild(this.tgrp); + } + this.tgrp = document.createElementNS(NS, 'svg:g'); + this.tgrp.setAttributeNS(null, 'transform', + 'matrix(' + this.transformMatrix + ')'); + }, + clip: function SVGGraphics_clip(type) { var current = this.current; // Add current path to clipping path @@ -766,10 +791,14 @@ var SVGGraphics = (function SVGGraphicsClosure(ctx) { imgEl.setAttributeNS(null, 'y', -h); imgEl.setAttributeNS(null, 'transform', 'scale(' + 1 / w + ' ' + -1 / h + ')'); + + this.tgrp.appendChild(imgEl); if (current.pendingClip) { this.cgrp.appendChild(this.tgrp); + this.pgrp.appendChild(this.cgrp); + } else { + this.pgrp.appendChild(this.tgrp); } - this.tgrp.appendChild(imgEl); }, }; return SVGGraphics;