Subversion-Projekte lars-tiefland.cienc

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
9 lars 1
/** @preserve
2
jsPDF Silly SVG plugin
3
Copyright (c) 2012 Willow Systems Corporation, willow-systems.com
4
*/
5
/**
6
 * Permission is hereby granted, free of charge, to any person obtaining
7
 * a copy of this software and associated documentation files (the
8
 * "Software"), to deal in the Software without restriction, including
9
 * without limitation the rights to use, copy, modify, merge, publish,
10
 * distribute, sublicense, and/or sell copies of the Software, and to
11
 * permit persons to whom the Software is furnished to do so, subject to
12
 * the following conditions:
13
 *
14
 * The above copyright notice and this permission notice shall be
15
 * included in all copies or substantial portions of the Software.
16
 *
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
 * ====================================================================
25
 */
26
 
27
;(function(jsPDFAPI) {
28
'use strict'
29
 
30
/**
31
Parses SVG XML and converts only some of the SVG elements into
32
PDF elements.
33
 
34
Supports:
35
 paths
36
 
37
@public
38
@function
39
@param
40
@returns {Type}
41
*/
42
jsPDFAPI.addSVG = function(svgtext, x, y, w, h) {
43
	// 'this' is _jsPDF object returned when jsPDF is inited (new jsPDF())
44
 
45
	var undef
46
 
47
	if (x === undef || x === undef) {
48
		throw new Error("addSVG needs values for 'x' and 'y'")
49
	}
50
 
51
    function InjectCSS(cssbody, document) {
52
        var styletag = document.createElement('style')
53
        styletag.type = 'text/css'
54
        if (styletag.styleSheet) {
55
        	// ie
56
            styletag.styleSheet.cssText = cssbody
57
        } else {
58
        	// others
59
            styletag.appendChild(document.createTextNode(cssbody))
60
        }
61
        document.getElementsByTagName("head")[0].appendChild(styletag)
62
    }
63
 
64
	function createWorkerNode(document){
65
 
66
		var frameID = 'childframe' // Date.now().toString() + '_' + (Math.random() * 100).toString()
67
		, frame = document.createElement('iframe')
68
 
69
		InjectCSS(
70
			'.jsPDF_sillysvg_iframe {display:none;position:absolute;}'
71
			, document
72
		)
73
 
74
		frame.name = frameID
75
		frame.setAttribute("width", 0)
76
		frame.setAttribute("height", 0)
77
		frame.setAttribute("frameborder", "0")
78
		frame.setAttribute("scrolling", "no")
79
		frame.setAttribute("seamless", "seamless")
80
		frame.setAttribute("class", "jsPDF_sillysvg_iframe")
81
 
82
		document.body.appendChild(frame)
83
 
84
		return frame
85
	}
86
 
87
	function attachSVGToWorkerNode(svgtext, frame){
88
		var framedoc = ( frame.contentWindow || frame.contentDocument ).document
89
		framedoc.write(svgtext)
90
		framedoc.close()
91
		return framedoc.getElementsByTagName('svg')[0]
92
	}
93
 
94
	function convertPathToPDFLinesArgs(path){
95
		'use strict'
96
		// we will use 'lines' method call. it needs:
97
		// - starting coordinate pair
98
		// - array of arrays of vector shifts (2-len for line, 6 len for bezier)
99
		// - scale array [horizontal, vertical] ratios
100
		// - style (stroke, fill, both)
101
 
102
		var x = parseFloat(path[1])
103
		, y = parseFloat(path[2])
104
		, vectors = []
105
		, position = 3
106
		, len = path.length
107
 
108
		while (position < len){
109
			if (path[position] === 'c'){
110
				vectors.push([
111
					parseFloat(path[position + 1])
112
					, parseFloat(path[position + 2])
113
					, parseFloat(path[position + 3])
114
					, parseFloat(path[position + 4])
115
					, parseFloat(path[position + 5])
116
					, parseFloat(path[position + 6])
117
				])
118
				position += 7
119
			} else if (path[position] === 'l') {
120
				vectors.push([
121
					parseFloat(path[position + 1])
122
					, parseFloat(path[position + 2])
123
				])
124
				position += 3
125
			} else {
126
				position += 1
127
			}
128
		}
129
		return [x,y,vectors]
130
	}
131
 
132
	var workernode = createWorkerNode(document)
133
	, svgnode = attachSVGToWorkerNode(svgtext, workernode)
134
	, scale = [1,1]
135
	, svgw = parseFloat(svgnode.getAttribute('width'))
136
	, svgh = parseFloat(svgnode.getAttribute('height'))
137
 
138
	if (svgw && svgh) {
139
		// setting both w and h makes image stretch to size.
140
		// this may distort the image, but fits your demanded size
141
		if (w && h) {
142
			scale = [w / svgw, h / svgh]
143
		}
144
		// if only one is set, that value is set as max and SVG
145
		// is scaled proportionately.
146
		else if (w) {
147
			scale = [w / svgw, w / svgw]
148
		} else if (h) {
149
			scale = [h / svgh, h / svgh]
150
		}
151
	}
152
 
153
	var i, l, tmp
154
	, linesargs
155
	, items = svgnode.childNodes
156
	for (i = 0, l = items.length; i < l; i++) {
157
		tmp = items[i]
158
		if (tmp.tagName && tmp.tagName.toUpperCase() === 'PATH') {
159
			linesargs = convertPathToPDFLinesArgs( tmp.getAttribute("d").split(' ') )
160
			// path start x coordinate
161
			linesargs[0] = linesargs[0] * scale[0] + x // where x is upper left X of image
162
			// path start y coordinate
163
			linesargs[1] = linesargs[1] * scale[1] + y // where y is upper left Y of image
164
			// the rest of lines are vectors. these will adjust with scale value auto.
165
			this.lines.call(
166
				this
167
				, linesargs[2] // lines
168
				, linesargs[0] // starting x
169
				, linesargs[1] // starting y
170
				, scale
171
			)
172
		}
173
	}
174
 
175
	// clean up
176
	// workernode.parentNode.removeChild(workernode)
177
 
178
	return this
179
}
180
 
181
})(jsPDF.API)