The branch, master has been updated via 551cc9a465269ab1208438d81fc0d492ce797366 (commit) via ba8e434a99e88ff84db5e391004b13df3de6f063 (commit) via 0d7c2195ffed20f90f516fd0662d2e166f55aba6 (commit) via 6faabf70f4c95cc0733c6f7abe43701f6b04ae48 (commit) via 1f6f14a4ef1603ddc9c724d29a32b55f2ed40f7d (commit) via e122e5ac70e939febb457d2445dcd1c7d0942340 (commit) via 7ff287e1e045fabd9eb504d90de02634807d3424 (commit) via 2b949e99d7aebe454280c4fab445afceee30ce39 (commit) via 95c60e193d8a431712844871fa54edfeaedf8536 (commit) via 60a2f965929ec35e82f4183265bd2f82e3a6a1af (commit) via 2ad26bcc604daa46104952f57a3bf4a6a59d8ba2 (commit) via 45330faa592c05fd6a20a90ea898baf580f9d84d (commit) via bd731759a7339c7c5256630511da9f9dc1ad20c0 (commit) via 139ac496c181950dea2ef2b032d718098a6e8db6 (commit) via 11b8a407f35888c4a1f6b4f4bbef889ea868a5f7 (commit) via 75bc5fc24a13d7743f8853265c94b10c044d01d1 (commit) via 7d4841df4951193fd75e1d92df6c8b182f426d97 (commit) via c4992e568cdc06c1a543a916bc3f021ebe884413 (commit) via 6544f5f9e78db8b4364589b8cdbe2a80df609bc3 (commit) via 50ae4412950b96b86562a02c4c8552611453dabd (commit) via 3a2fd218fcd8c942a7b11188ad147d2e45a4ac0c (commit) via 7cb695d5020d9b555b19fea60b0f92c2b880ccf0 (commit) via 972be216dd261f2bc4ccf9a5fd2304936a9fff92 (commit) via 9179fde0a587b5c722edcbea3a2c35ce60f56a95 (commit) via 8c0a294dc5acc3fc2926b97706d518504d54b205 (commit) via e8b26f8e5d11a56e5805c5d48fa79bfb368fce6d (commit) via 4a09e17af3f1220a36dac61c3b578f9a925bb1b7 (commit) via 60ad158b0451c3347e5a8813cc39099b40e78b1f (commit) via fb91a17704339395c51d2027eef6b6ef5de7fc04 (commit) via 9943ef0275b2f0e880680c4c166fd33f5048b874 (commit) via 22e8102e3212045c0ab1718d52e69be0fdeebe34 (commit) via f8dd706ad38113afe6291524f01b8b5e4cd9e8c5 (commit) via 05235672e67e5856aa688adaeabc97b3780c02ae (commit) via 2216824c900d18b5f39058c1e97a9b56d4309c99 (commit) via a3510734b18cf12a77cedabceb76258539565e75 (commit) via 9409b76db65fd5ab13a71e2d765cbf13c44b49c1 (commit) from 25dc50a5dd8a69f435272d37f7febafffc1d0ff0 (commit)
- Log ----------------------------------------------------------------- commit 551cc9a465269ab1208438d81fc0d492ce797366 Merge: ba8e434a99e88ff84db5e391004b13df3de6f063 0d7c2195ffed20f90f516fd0662d2e166f55aba6 Author: Michal Čihař mcihar@suse.cz Date: Wed Jun 15 07:50:05 2011 +0200
Merge remote-tracking branch 'pootle/master'
commit ba8e434a99e88ff84db5e391004b13df3de6f063 Merge: 25dc50a5dd8a69f435272d37f7febafffc1d0ff0 2216824c900d18b5f39058c1e97a9b56d4309c99 Author: Michal Čihař mcihar@suse.cz Date: Wed Jun 15 07:49:56 2011 +0200
Merge remote-tracking branch 'tyron/master'
Conflicts: server_status.php
commit 0d7c2195ffed20f90f516fd0662d2e166f55aba6 Author: Marc Delisle marc@infomarc.info Date: Wed Jun 15 02:35:52 2011 +0200
Translation update done using Pootle.
commit 6faabf70f4c95cc0733c6f7abe43701f6b04ae48 Author: Marc Delisle marc@infomarc.info Date: Wed Jun 15 02:35:44 2011 +0200
Translation update done using Pootle.
commit 1f6f14a4ef1603ddc9c724d29a32b55f2ed40f7d Author: Marc Delisle marc@infomarc.info Date: Wed Jun 15 02:35:36 2011 +0200
Translation update done using Pootle.
commit e122e5ac70e939febb457d2445dcd1c7d0942340 Author: Marc Delisle marc@infomarc.info Date: Wed Jun 15 02:35:22 2011 +0200
Translation update done using Pootle.
commit 7ff287e1e045fabd9eb504d90de02634807d3424 Author: Marc Delisle marc@infomarc.info Date: Wed Jun 15 02:35:12 2011 +0200
Translation update done using Pootle.
commit 2b949e99d7aebe454280c4fab445afceee30ce39 Author: Marc Delisle marc@infomarc.info Date: Wed Jun 15 02:35:04 2011 +0200
Translation update done using Pootle.
commit 95c60e193d8a431712844871fa54edfeaedf8536 Author: Marc Delisle marc@infomarc.info Date: Wed Jun 15 02:34:55 2011 +0200
Translation update done using Pootle.
commit 60a2f965929ec35e82f4183265bd2f82e3a6a1af Author: Marc Delisle marc@infomarc.info Date: Wed Jun 15 02:34:49 2011 +0200
Translation update done using Pootle.
commit 2ad26bcc604daa46104952f57a3bf4a6a59d8ba2 Author: Marc Delisle marc@infomarc.info Date: Wed Jun 15 02:34:40 2011 +0200
Translation update done using Pootle.
commit 45330faa592c05fd6a20a90ea898baf580f9d84d Author: Marc Delisle marc@infomarc.info Date: Wed Jun 15 02:34:31 2011 +0200
Translation update done using Pootle.
commit bd731759a7339c7c5256630511da9f9dc1ad20c0 Author: Marc Delisle marc@infomarc.info Date: Wed Jun 15 02:34:20 2011 +0200
Translation update done using Pootle.
commit 139ac496c181950dea2ef2b032d718098a6e8db6 Author: Marc Delisle marc@infomarc.info Date: Wed Jun 15 02:34:10 2011 +0200
Translation update done using Pootle.
commit 11b8a407f35888c4a1f6b4f4bbef889ea868a5f7 Author: Marc Delisle marc@infomarc.info Date: Wed Jun 15 02:33:58 2011 +0200
Translation update done using Pootle.
commit 75bc5fc24a13d7743f8853265c94b10c044d01d1 Author: Marc Delisle marc@infomarc.info Date: Wed Jun 15 02:33:46 2011 +0200
Translation update done using Pootle.
commit 7d4841df4951193fd75e1d92df6c8b182f426d97 Author: Marc Delisle marc@infomarc.info Date: Wed Jun 15 02:33:37 2011 +0200
Translation update done using Pootle.
commit c4992e568cdc06c1a543a916bc3f021ebe884413 Author: Marc Delisle marc@infomarc.info Date: Wed Jun 15 02:33:28 2011 +0200
Translation update done using Pootle.
commit 6544f5f9e78db8b4364589b8cdbe2a80df609bc3 Author: Marc Delisle marc@infomarc.info Date: Wed Jun 15 02:33:15 2011 +0200
Translation update done using Pootle.
commit 50ae4412950b96b86562a02c4c8552611453dabd Author: Marc Delisle marc@infomarc.info Date: Wed Jun 15 02:33:06 2011 +0200
Translation update done using Pootle.
commit 3a2fd218fcd8c942a7b11188ad147d2e45a4ac0c Author: Marc Delisle marc@infomarc.info Date: Wed Jun 15 02:32:52 2011 +0200
Translation update done using Pootle.
commit 7cb695d5020d9b555b19fea60b0f92c2b880ccf0 Author: Marc Delisle marc@infomarc.info Date: Wed Jun 15 02:32:40 2011 +0200
Translation update done using Pootle.
commit 972be216dd261f2bc4ccf9a5fd2304936a9fff92 Author: Marc Delisle marc@infomarc.info Date: Wed Jun 15 02:32:26 2011 +0200
Translation update done using Pootle.
commit 9179fde0a587b5c722edcbea3a2c35ce60f56a95 Author: Marc Delisle marc@infomarc.info Date: Wed Jun 15 02:32:18 2011 +0200
Translation update done using Pootle.
commit 8c0a294dc5acc3fc2926b97706d518504d54b205 Author: Marc Delisle marc@infomarc.info Date: Wed Jun 15 02:32:07 2011 +0200
Translation update done using Pootle.
commit e8b26f8e5d11a56e5805c5d48fa79bfb368fce6d Author: Marc Delisle marc@infomarc.info Date: Wed Jun 15 02:31:57 2011 +0200
Translation update done using Pootle.
commit 4a09e17af3f1220a36dac61c3b578f9a925bb1b7 Author: Marc Delisle marc@infomarc.info Date: Wed Jun 15 02:31:46 2011 +0200
Translation update done using Pootle.
commit 60ad158b0451c3347e5a8813cc39099b40e78b1f Author: Marc Delisle marc@infomarc.info Date: Wed Jun 15 02:31:38 2011 +0200
Translation update done using Pootle.
commit fb91a17704339395c51d2027eef6b6ef5de7fc04 Author: Marc Delisle marc@infomarc.info Date: Wed Jun 15 02:31:23 2011 +0200
Translation update done using Pootle.
commit 9943ef0275b2f0e880680c4c166fd33f5048b874 Author: Marc Delisle marc@infomarc.info Date: Wed Jun 15 02:31:16 2011 +0200
Translation update done using Pootle.
commit 22e8102e3212045c0ab1718d52e69be0fdeebe34 Author: Marc Delisle marc@infomarc.info Date: Wed Jun 15 02:31:06 2011 +0200
Translation update done using Pootle.
commit f8dd706ad38113afe6291524f01b8b5e4cd9e8c5 Author: Marc Delisle marc@infomarc.info Date: Wed Jun 15 02:30:54 2011 +0200
Translation update done using Pootle.
commit 05235672e67e5856aa688adaeabc97b3780c02ae Author: Marc Delisle marc@infomarc.info Date: Wed Jun 15 02:30:40 2011 +0200
Translation update done using Pootle.
commit 2216824c900d18b5f39058c1e97a9b56d4309c99 Author: Tyron Madlener tyronx@gmail.com Date: Tue Jun 14 20:55:37 2011 +0200
- Newest canvg version from trunk fixing display of hidden elements - Some attempts to get png export working for IE8 (needs flashcanvas)
commit a3510734b18cf12a77cedabceb76258539565e75 Author: Tyron Madlener tyronx@gmail.com Date: Tue Jun 14 17:19:40 2011 +0200
merge conflicts
commit 9409b76db65fd5ab13a71e2d765cbf13c44b49c1 Merge: d7fc94529cef1f3bbdb1ec302c2d22dcfd039112 4b73c39775b8234b66fd375aa3ac7387e945d704 Author: Tyron Madlener tyronx@gmail.com Date: Tue Jun 14 17:16:26 2011 +0200
Merge remote-tracking branch 'origin/master'
Conflicts: server_status.php
-----------------------------------------------------------------------
Summary of changes: js/canvg/canvg.js | 304 ++++++++++--- js/canvg/flashcanvas.js | 1093 +++++++++++++++++++++++++++++++++++++++++++ js/canvg/flashcanvas.swf | Bin 0 -> 21235 bytes js/highcharts/exporting.js | 4 + js/highcharts/highcharts.js | 2 +- po/en_GB.po | 85 ++-- server_status.php | 6 + 7 files changed, 1389 insertions(+), 105 deletions(-) create mode 100644 js/canvg/flashcanvas.js create mode 100644 js/canvg/flashcanvas.swf
diff --git a/js/canvg/canvg.js b/js/canvg/canvg.js index 83c91b4..7b7e963 100644 --- a/js/canvg/canvg.js +++ b/js/canvg/canvg.js @@ -12,7 +12,6 @@ if(!window.console) { window.console.dir = function(str) {}; }
-// <3 IE if(!Array.indexOf){ Array.prototype.indexOf = function(obj){ for(var i=0; i<this.length; i++){ @@ -28,7 +27,7 @@ if(!Array.indexOf){ // canvg(target, s) // empty parameters: replace all 'svg' elements on page with 'canvas' elements // target: canvas element or the id of a canvas element - // s: svg string or url to svg file + // s: svg string, url to svg file, or xml document // opts: optional hash of options // ignoreMouse: true => ignore mouse events // ignoreAnimation: true => ignore animations @@ -75,7 +74,11 @@ if(!Array.indexOf){ svg.opts = opts; var ctx = target.getContext('2d'); - if (s.substr(0,1) == '<') { + if (typeof(s.documentElement) != 'undefined') { + // load from xml doc + svg.loadXmlDoc(ctx, s); + } + else if (s.substr(0,1) == '<') { // load from xml string svg.loadXml(ctx, s); } @@ -89,6 +92,7 @@ if(!Array.indexOf){ var svg = { }; svg.FRAMERATE = 30; + svg.MAX_VIRTUAL_PIXELS = 30000; // globals svg.init = function(ctx) { @@ -99,6 +103,7 @@ if(!Array.indexOf){ svg.ctx = ctx; svg.ViewPort = new (function () { this.viewPorts = []; + this.Clear = function() { this.viewPorts = []; } this.SetCurrent = function(width, height) { this.viewPorts.push({ width: width, height: height }); } this.RemoveCurrent = function() { this.viewPorts.pop(); } this.Current = function() { return this.viewPorts[this.viewPorts.length - 1]; } @@ -551,7 +556,7 @@ if(!Array.indexOf){ } } - var data = v.split(/\s(?=[a-z])/); + var data = svg.trim(svg.compressSpaces(v)).split(/\s(?=[a-z])/); for (var i=0; i<data.length; i++) { var type = data[i].split('(')[0]; var s = data[i].split('(')[1].replace(')',''); @@ -616,7 +621,7 @@ if(!Array.indexOf){ return a; } - // get or create style + // get or create style, crawls up node tree this.style = function(name, createIfNotExists) { var s = this.styles[name]; if (s != null) return s; @@ -625,6 +630,14 @@ if(!Array.indexOf){ if (a != null && a.hasValue()) { return a; } + + var p = this.parent; + if (p != null) { + var ps = p.style(name); + if (ps != null && ps.hasValue()) { + return ps; + } + } s = new svg.Property(name, ''); if (createIfNotExists == true) this.styles[name] = s; @@ -635,6 +648,9 @@ if(!Array.indexOf){ this.render = function(ctx) { // don't render display=none if (this.attribute('display').value == 'none') return; + + // don't render visibility=hidden + if (this.attribute('visibility').value == 'hidden') return; ctx.save(); this.setContext(ctx); @@ -681,7 +697,7 @@ if(!Array.indexOf){ } // add tag styles - var styles = svg.Styles[this.type]; + var styles = svg.Styles[node.nodeName]; if (styles != null) { for (var name in styles) { this.styles[name] = styles[name]; @@ -698,6 +714,12 @@ if(!Array.indexOf){ this.styles[name] = styles[name]; } } + styles = svg.Styles[node.nodeName+'.'+classes[j]]; + if (styles != null) { + for (var name in styles) { + this.styles[name] = styles[name]; + } + } } } @@ -856,7 +878,7 @@ if(!Array.indexOf){ var width = svg.ViewPort.width(); var height = svg.ViewPort.height(); - if (this.attribute('width').hasValue() && this.attribute('height').hasValue()) { + if (typeof(this.root) == 'undefined' && this.attribute('width').hasValue() && this.attribute('height').hasValue()) { width = this.attribute('width').Length.toPixels('x'); height = this.attribute('height').Length.toPixels('y'); @@ -1186,9 +1208,6 @@ if(!Array.indexOf){ pp.reset();
var bb = new svg.BoundingBox(); - - if(this.attribute('visibility').value=='hidden') return; - if (ctx != null) ctx.beginPath(); while (!pp.isEnd()) { pp.nextCommand(); @@ -1469,6 +1488,37 @@ if(!Array.indexOf){ for (var i=0; i<stopsContainer.stops.length; i++) { g.addColorStop(stopsContainer.stops[i].offset, stopsContainer.stops[i].color); } + + if (this.attribute('gradientTransform').hasValue()) { + // render as transformed pattern on temporary canvas + var rootView = svg.ViewPort.viewPorts[0]; + + var rect = new svg.Element.rect(); + rect.attributes['x'] = new svg.Property('x', -svg.MAX_VIRTUAL_PIXELS/3.0); + rect.attributes['y'] = new svg.Property('y', -svg.MAX_VIRTUAL_PIXELS/3.0); + rect.attributes['width'] = new svg.Property('width', svg.MAX_VIRTUAL_PIXELS); + rect.attributes['height'] = new svg.Property('height', svg.MAX_VIRTUAL_PIXELS); + + var group = new svg.Element.g(); + group.attributes['transform'] = new svg.Property('transform', this.attribute('gradientTransform').value); + group.children = [ rect ]; + + var tempSvg = new svg.Element.svg(); + tempSvg.attributes['x'] = new svg.Property('x', 0); + tempSvg.attributes['y'] = new svg.Property('y', 0); + tempSvg.attributes['width'] = new svg.Property('width', rootView.width); + tempSvg.attributes['height'] = new svg.Property('height', rootView.height); + tempSvg.children = [ group ]; + + var c = document.createElement('canvas'); + c.width = rootView.width; + c.height = rootView.height; + var tempCtx = c.getContext('2d'); + tempCtx.fillStyle = g; + tempSvg.render(tempCtx); + return tempCtx.createPattern(c, 'no-repeat'); + } + return g; } } @@ -1494,16 +1544,8 @@ if(!Array.indexOf){ var y2 = (this.gradientUnits == 'objectBoundingBox' ? bb.y() + bb.height() * this.attribute('y2').numValue() : this.attribute('y2').Length.toPixels('y')); - - var p1 = new svg.Point(x1, y1); - var p2 = new svg.Point(x2, y2); - if (this.attribute('gradientTransform').hasValue()) { - var transform = new svg.Transform(this.attribute('gradientTransform').value); - transform.applyToPoint(p1); - transform.applyToPoint(p2); - } - - return ctx.createLinearGradient(p1.x, p1.y, p2.x, p2.y); + + return ctx.createLinearGradient(x1, y1, x2, y2); } } svg.Element.linearGradient.prototype = new svg.Element.GradientBase; @@ -1540,22 +1582,7 @@ if(!Array.indexOf){ ? (bb.width() + bb.height()) / 2.0 * this.attribute('r').numValue() : this.attribute('r').Length.toPixels()); - var c = new svg.Point(cx, cy); - var f = new svg.Point(fx, fy); - if (this.attribute('gradientTransform').hasValue()) { - var transform = new svg.Transform(this.attribute('gradientTransform').value); - transform.applyToPoint(c); - transform.applyToPoint(f); - - for (var i=0; i<transform.transforms.length; i++) { - // average the scaling part of the transform, apply to radius - var scale1 = transform.transforms[i].m[0]; - var scale2 = transform.transforms[i].m[3]; - r = r * ((scale1 + scale2) / 2.0); - } - } - - return ctx.createRadialGradient(f.x, f.y, 0, c.x, c.y, r); + return ctx.createRadialGradient(fx, fy, 0, cx, cy, r); } } svg.Element.radialGradient.prototype = new svg.Element.GradientBase; @@ -1693,6 +1720,73 @@ if(!Array.indexOf){ } svg.Element.animateTransform.prototype = new svg.Element.animate; + // font element + svg.Element.font = function(node) { + this.base = svg.Element.ElementBase; + this.base(node); + + this.horizAdvX = this.attribute('horiz-adv-x').numValue(); + + this.isRTL = false; + this.isArabic = false; + this.fontFace = null; + this.missingGlyph = null; + this.glyphs = []; + for (var i=0; i<this.children.length; i++) { + var child = this.children[i]; + if (child.type == 'font-face') { + this.fontFace = child; + if (child.style('font-family').hasValue()) { + svg.Definitions[child.style('font-family').value] = this; + } + } + else if (child.type == 'missing-glyph') this.missingGlyph = child; + else if (child.type == 'glyph') { + if (child.arabicForm != '') { + this.isRTL = true; + this.isArabic = true; + if (typeof(this.glyphs[child.unicode]) == 'undefined') this.glyphs[child.unicode] = []; + this.glyphs[child.unicode][child.arabicForm] = child; + } + else { + this.glyphs[child.unicode] = child; + } + } + } + } + svg.Element.font.prototype = new svg.Element.ElementBase; + + // font-face element + svg.Element.fontface = function(node) { + this.base = svg.Element.ElementBase; + this.base(node); + + this.ascent = this.attribute('ascent').value; + this.descent = this.attribute('descent').value; + this.unitsPerEm = this.attribute('units-per-em').numValue(); + } + svg.Element.fontface.prototype = new svg.Element.ElementBase; + + // missing-glyph element + svg.Element.missingglyph = function(node) { + this.base = svg.Element.path; + this.base(node); + + this.horizAdvX = 0; + } + svg.Element.missingglyph.prototype = new svg.Element.path; + + // glyph element + svg.Element.glyph = function(node) { + this.base = svg.Element.path; + this.base(node); + + this.horizAdvX = this.attribute('horiz-adv-x').numValue(); + this.unicode = this.attribute('unicode').value; + this.arabicForm = this.attribute('arabic-form').value; + } + svg.Element.glyph.prototype = new svg.Element.path; + // text element svg.Element.text = function(node) { this.base = svg.Element.RenderedElementBase; @@ -1715,19 +1809,16 @@ if(!Array.indexOf){ this.baseSetContext = this.setContext; this.setContext = function(ctx) { this.baseSetContext(ctx); - if (this.attribute('text-anchor').hasValue()) { - var textAnchor = this.attribute('text-anchor').value; + if (this.style('text-anchor').hasValue()) { + var textAnchor = this.style('text-anchor').value; ctx.textAlign = textAnchor == 'middle' ? 'center' : textAnchor; } if (this.attribute('alignment-baseline').hasValue()) ctx.textBaseline = this.attribute('alignment-baseline').value; } this.renderChildren = function(ctx) { - if(this.attribute('visibility').value=='hidden') return; - var x = this.attribute('x').Length.toPixels('x'); var y = this.attribute('y').Length.toPixels('y'); - for (var i=0; i<this.children.length; i++) { var child = this.children[i]; @@ -1759,8 +1850,63 @@ if(!Array.indexOf){ this.base = svg.Element.RenderedElementBase; this.base(node); + this.getGlyph = function(font, text, i) { + var c = text[i]; + var glyph = null; + if (font.isArabic) { + var arabicForm = 'isolated'; + if ((i==0 || text[i-1]==' ') && i<text.length-2 && text[i+1]!=' ') arabicForm = 'terminal'; + if (i>0 && text[i-1]!=' ' && i<text.length-2 && text[i+1]!=' ') arabicForm = 'medial'; + if (i>0 && text[i-1]!=' ' && (i == text.length-1 || text[i+1]==' ')) arabicForm = 'initial'; + if (typeof(font.glyphs[c]) != 'undefined') { + glyph = font.glyphs[c][arabicForm]; + if (glyph == null && font.glyphs[c].type == 'glyph') glyph = font.glyphs[c]; + } + } + else { + glyph = font.glyphs[c]; + } + if (glyph == null) glyph = font.missingGlyph; + return glyph; + } + this.renderChildren = function(ctx) { - ctx.fillText(svg.compressSpaces(this.getText()), this.x, this.y); + var customFont = this.parent.style('font-family').Definition.getDefinition(); + if (customFont != null) { + var fontSize = this.parent.style('font-size').numValueOrDefault(svg.Font.Parse(svg.ctx.font).fontSize); + var fontStyle = this.parent.style('font-style').valueOrDefault(svg.Font.Parse(svg.ctx.font).fontStyle); + var text = this.getText(); + if (customFont.isRTL) text = text.split("").reverse().join(""); + + if (this.parent.style('text-anchor').value == 'middle') { + this.x = this.x - this.measureText(ctx) / 2.0; + } + + var dx = svg.ToNumberArray(this.parent.attribute('dx').value); + for (var i=0; i<text.length; i++) { + var glyph = this.getGlyph(customFont, text, i); + var scale = fontSize / customFont.fontFace.unitsPerEm; + ctx.translate(this.x, this.y); + ctx.scale(scale, -scale); + var lw = ctx.lineWidth; + ctx.lineWidth = ctx.lineWidth * customFont.fontFace.unitsPerEm / fontSize; + if (fontStyle == 'italic') ctx.transform(1, 0, .4, 1, 0, 0); + glyph.render(ctx); + if (fontStyle == 'italic') ctx.transform(1, 0, -.4, 1, 0, 0); + ctx.lineWidth = lw; + ctx.scale(1/scale, -1/scale); + ctx.translate(-this.x, -this.y); + + this.x += fontSize * (glyph.horizAdvX || customFont.horizAdvX) / customFont.fontFace.unitsPerEm; + if (typeof(dx[i]) != 'undefined' && !isNaN(dx[i])) { + this.x += dx[i]; + } + } + return; + } + + if (ctx.strokeStyle != '') ctx.strokeText(svg.compressSpaces(this.getText()), this.x, this.y); + if (ctx.fillStyle != '') ctx.fillText(svg.compressSpaces(this.getText()), this.x, this.y); } this.getText = function() { @@ -1768,6 +1914,23 @@ if(!Array.indexOf){ } this.measureText = function(ctx) { + var customFont = this.parent.style('font-family').Definition.getDefinition(); + if (customFont != null) { + var fontSize = this.parent.style('font-size').numValueOrDefault(svg.Font.Parse(svg.ctx.font).fontSize); + var measure = 0; + var text = this.getText(); + if (customFont.isRTL) text = text.split("").reverse().join(""); + var dx = svg.ToNumberArray(this.parent.attribute('dx').value); + for (var i=0; i<text.length; i++) { + var glyph = this.getGlyph(customFont, text, i); + measure += (glyph.horizAdvX || customFont.horizAdvX) * fontSize / customFont.fontFace.unitsPerEm; + if (typeof(dx[i]) != 'undefined' && !isNaN(dx[i])) { + measure += dx[i]; + } + } + return measure; + } + var textToMeasure = svg.compressSpaces(this.getText()); if (!ctx.measureText) return textToMeasure.length * 10; return ctx.measureText(textToMeasure).width; @@ -1780,8 +1943,9 @@ if(!Array.indexOf){ this.base = svg.Element.TextElementBase; this.base(node); - // TEXT ELEMENT - this.text = node.nodeType == 3 ? node.nodeValue : node.childNodes[0].nodeValue; + this.text = node.nodeType == 3 ? node.nodeValue : // text + node.childNodes.length > 0 ? node.childNodes[0].nodeValue : // element + node.text; this.getText = function() { return this.text; } @@ -1931,8 +2095,9 @@ if(!Array.indexOf){ this.base = svg.Element.ElementBase; this.base(node); - var css = node.childNodes[0].nodeValue; - css = css.replace(/(/*([^*]|[\r\n]|(*+([^*/]|[\r\n])))**+/)|(//.*)/gm, ''); // remove comments + // text, or spaces then CDATA + var css = node.childNodes[0].nodeValue + (node.childNodes.length > 1 ? node.childNodes[1].nodeValue : ''); + css = css.replace(/(/*([^*]|[\r\n]|(*+([^*/]|[\r\n])))**+/)|(^[\s]*//.*)/gm, ''); // remove comments css = svg.compressSpaces(css); // replace whitespace var cssDefs = css.split('}'); for (var i=0; i<cssDefs.length; i++) { @@ -1945,14 +2110,31 @@ if(!Array.indexOf){ if (cssClass != '') { var props = {}; for (var k=0; k<cssProps.length; k++) { - var prop = cssProps[k].split(':'); - var name = prop[0]; - var value = prop[1]; + var prop = cssProps[k].indexOf(':'); + var name = cssProps[k].substr(0, prop); + var value = cssProps[k].substr(prop + 1, cssProps[k].length - prop); if (name != null && value != null) { - props[svg.trim(prop[0])] = new svg.Property(svg.trim(prop[0]), svg.trim(prop[1])); + props[svg.trim(name)] = new svg.Property(svg.trim(name), svg.trim(value)); } } svg.Styles[cssClass] = props; + if (cssClass == '@font-face') { + var fontFamily = props['font-family'].value.replace(/"/g,''); + var srcs = props['src'].value.split(','); + for (var s=0; s<srcs.length; s++) { + if (srcs[s].indexOf('format("svg")') > 0) { + var urlStart = srcs[s].indexOf('url'); + var urlEnd = srcs[s].indexOf(')', urlStart); + var url = srcs[s].substr(urlStart + 5, urlEnd - urlStart - 6); + var doc = svg.parseXml(svg.ajax(url)); + var fonts = doc.getElementsByTagName('font'); + for (var f=0; f<fonts.length; f++) { + var font = svg.CreateElement(fonts[f]); + svg.Definitions[fontFamily] = font; + } + } + } + } } } } @@ -2004,6 +2186,10 @@ if(!Array.indexOf){ } } } + + this.render = function(ctx) { + // NO RENDER + } } svg.Element.clipPath.prototype = new svg.Element.ElementBase;
@@ -2024,7 +2210,8 @@ if(!Array.indexOf){ // element factory svg.CreateElement = function(node) { - var className = node.nodeName.replace(/^[^:]+:/,''); + var className = node.nodeName.replace(/^[^:]+:/,''); // remove namespace + className = className.replace(/-/g,''); // remove dashes var e = null; if (typeof(svg.Element[className]) != 'undefined') { e = new svg.Element[className](node); @@ -2044,6 +2231,10 @@ if(!Array.indexOf){ // load from xml svg.loadXml = function(ctx, xml) { + svg.loadXmlDoc(ctx, svg.parseXml(xml)); + } + + svg.loadXmlDoc = function(ctx, dom) { svg.init(ctx); var mapXY = function(p) { @@ -2070,19 +2261,24 @@ if(!Array.indexOf){ }; } - var dom = svg.parseXml(xml); var e = svg.CreateElement(dom.documentElement); + e.root = true; // render loop var isFirstRender = true; var draw = function() { + svg.ViewPort.Clear(); + if (ctx.canvas.parentNode) svg.ViewPort.SetCurrent(ctx.canvas.parentNode.clientWidth, ctx.canvas.parentNode.clientHeight); + if (svg.opts == null || svg.opts['ignoreDimensions'] != true) { // set canvas size if (e.style('width').hasValue()) { - ctx.canvas.width = e.style('width').Length.toPixels(ctx.canvas.parentNode.clientWidth); + ctx.canvas.width = e.style('width').Length.toPixels('x'); + ctx.canvas.style.width = ctx.canvas.width + 'px'; } if (e.style('height').hasValue()) { - ctx.canvas.height = e.style('height').Length.toPixels(ctx.canvas.parentNode.clientHeight); + ctx.canvas.height = e.style('height').Length.toPixels('y'); + ctx.canvas.style.height = ctx.canvas.height + 'px'; } } svg.ViewPort.SetCurrent(ctx.canvas.clientWidth, ctx.canvas.clientHeight); diff --git a/js/canvg/flashcanvas.js b/js/canvg/flashcanvas.js new file mode 100644 index 0000000..6ecaa94 --- /dev/null +++ b/js/canvg/flashcanvas.js @@ -0,0 +1,1093 @@ +/* + * FlashCanvas + * + * Copyright (c) 2009 Tim Cameron Ryan + * Copyright (c) 2009-2011 FlashCanvas Project + * Released under the MIT/X License + */ + +// Reference: +// http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-eleme... +// http://dev.w3.org/html5/spec/the-canvas-element.html + +// If the browser is IE and does not support HTML5 Canvas +if (window["ActiveXObject"] && !window["CanvasRenderingContext2D"]) { + +(function(window, document, undefined) { + +/* + * Constant + */ + +var NULL = null; +var CANVAS = "canvas"; +var CANVAS_RENDERING_CONTEXT_2D = "CanvasRenderingContext2D"; +var CANVAS_GRADIENT = "CanvasGradient"; +var CANVAS_PATTERN = "CanvasPattern"; +var FLASH_CANVAS = "FlashCanvas"; +var G_VML_CANVAS_MANAGER = "G_vmlCanvasManager"; +var OBJECT_ID_PREFIX = "external"; +var ON_FOCUS = "onfocus"; +var ON_PROPERTY_CHANGE = "onpropertychange"; +var ON_READY_STATE_CHANGE = "onreadystatechange"; +var ON_UNLOAD = "onunload"; + +var config = window[FLASH_CANVAS + "Options"] || {}; +var BASE_URL = config["swfPath"] || getScriptUrl().replace(/[^/]+$/, ""); +var SWF_URL = BASE_URL + "flashcanvas.swf"; + +// DOMException code +var INDEX_SIZE_ERR = 1; +var NOT_SUPPORTED_ERR = 9; +var INVALID_STATE_ERR = 11; +var SYNTAX_ERR = 12; +var TYPE_MISMATCH_ERR = 17; +var SECURITY_ERR = 18; + +/** + * @constructor + */ +function Lookup(array) { + for (var i = 0, n = array.length; i < n; i++) + this[array[i]] = i; +} + +var properties = new Lookup([ + // Canvas element + "toDataURL", + + // CanvasRenderingContext2D + "save", + "restore", + "scale", + "rotate", + "translate", + "transform", + "setTransform", + "globalAlpha", + "globalCompositeOperation", + "strokeStyle", + "fillStyle", + "createLinearGradient", + "createRadialGradient", + "createPattern", + "lineWidth", + "lineCap", + "lineJoin", + "miterLimit", + "shadowOffsetX", + "shadowOffsetY", + "shadowBlur", + "shadowColor", + "clearRect", + "fillRect", + "strokeRect", + "beginPath", + "closePath", + "moveTo", + "lineTo", + "quadraticCurveTo", + "bezierCurveTo", + "arcTo", + "rect", + "arc", + "fill", + "stroke", + "clip", + "isPointInPath", +// "drawFocusRing", + "font", + "textAlign", + "textBaseline", + "fillText", + "strokeText", + "measureText", + "drawImage", + "createImageData", + "getImageData", + "putImageData", + + // CanvasGradient + "addColorStop", + + // Internal use + "direction", + "resize" +]); + +// Whether swf is ready for use +var isReady = {}; + +// Monitor the number of loading files +var lock = {}; + +// Canvas elements +var canvases = {}; + +// SPAN element embedded in the canvas +var spans = {}; + +/** + * 2D context + * @constructor + */ +var CanvasRenderingContext2D = function(canvas, swf) { + // back-reference to the canvas + this.canvas = canvas; + + // back-reference to the swf + this._swf = swf; + + // unique ID of canvas + this._canvasId = swf.id.slice(8); + + // initialize drawing states + this._initialize(); + + // Count CanvasGradient and CanvasPattern objects + this._gradientPatternId = 0; + + // Directionality of the canvas element + this._direction = ""; + + // frame update interval + var self = this; + setInterval(function() { + if (lock[self._canvasId] === 0) { + self._executeCommand(); + } + }, 30); +}; + +CanvasRenderingContext2D.prototype = { + /* + * state + */ + + save: function() { + // write all properties + this._setCompositing(); + this._setShadows(); + this._setStrokeStyle(); + this._setFillStyle(); + this._setLineStyles(); + this._setFontStyles(); + + // push state + this._stateStack.push([ + this._globalAlpha, + this._globalCompositeOperation, + this._strokeStyle, + this._fillStyle, + this._lineWidth, + this._lineCap, + this._lineJoin, + this._miterLimit, + this._shadowOffsetX, + this._shadowOffsetY, + this._shadowBlur, + this._shadowColor, + this._font, + this._textAlign, + this._textBaseline + ]); + + this._queue.push(properties.save); + }, + + restore: function() { + // pop state + var stateStack = this._stateStack; + if (stateStack.length) { + var state = stateStack.pop(); + this.globalAlpha = state[0]; + this.globalCompositeOperation = state[1]; + this.strokeStyle = state[2]; + this.fillStyle = state[3]; + this.lineWidth = state[4]; + this.lineCap = state[5]; + this.lineJoin = state[6]; + this.miterLimit = state[7]; + this.shadowOffsetX = state[8]; + this.shadowOffsetY = state[9]; + this.shadowBlur = state[10]; + this.shadowColor = state[11]; + this.font = state[12]; + this.textAlign = state[13]; + this.textBaseline = state[14]; + } + + this._queue.push(properties.restore); + }, + + /* + * transformations + */ + + scale: function(x, y) { + this._queue.push(properties.scale, x, y); + }, + + rotate: function(angle) { + this._queue.push(properties.rotate, angle); + }, + + translate: function(x, y) { + this._queue.push(properties.translate, x, y); + }, + + transform: function(m11, m12, m21, m22, dx, dy) { + this._queue.push(properties.transform, m11, m12, m21, m22, dx, dy); + }, + + setTransform: function(m11, m12, m21, m22, dx, dy) { + this._queue.push(properties.setTransform, m11, m12, m21, m22, dx, dy); + }, + + /* + * compositing + */ + + _setCompositing: function() { + var queue = this._queue; + if (this._globalAlpha !== this.globalAlpha) { + this._globalAlpha = this.globalAlpha; + queue.push(properties.globalAlpha, this._globalAlpha); + } + if (this._globalCompositeOperation !== this.globalCompositeOperation) { + this._globalCompositeOperation = this.globalCompositeOperation; + queue.push(properties.globalCompositeOperation, this._globalCompositeOperation); + } + }, + + /* + * colors and styles + */ + + _setStrokeStyle: function() { + if (this._strokeStyle !== this.strokeStyle) { + var style = this._strokeStyle = this.strokeStyle; + this._queue.push(properties.strokeStyle, (typeof style === "object") ? style.id : style); + } + }, + + _setFillStyle: function() { + if (this._fillStyle !== this.fillStyle) { + var style = this._fillStyle = this.fillStyle; + this._queue.push(properties.fillStyle, (typeof style === "object") ? style.id : style); + } + }, + + createLinearGradient: function(x0, y0, x1, y1) { + // If any of the arguments are not finite numbers, throws a + // NOT_SUPPORTED_ERR exception. + if (!(isFinite(x0) && isFinite(y0) && isFinite(x1) && isFinite(y1))) { + throwException(NOT_SUPPORTED_ERR); + } + + this._queue.push(properties.createLinearGradient, x0, y0, x1, y1); + return new CanvasGradient(this); + }, + + createRadialGradient: function(x0, y0, r0, x1, y1, r1) { + // If any of the arguments are not finite numbers, throws a + // NOT_SUPPORTED_ERR exception. + if (!(isFinite(x0) && isFinite(y0) && isFinite(r0) && + isFinite(x1) && isFinite(y1) && isFinite(r1))) { + throwException(NOT_SUPPORTED_ERR); + } + + // If either of the radii are negative, throws an INDEX_SIZE_ERR + // exception. + if (r0 < 0 || r1 < 0) { + throwException(INDEX_SIZE_ERR); + } + + this._queue.push(properties.createRadialGradient, x0, y0, r0, x1, y1, r1); + return new CanvasGradient(this); + }, + + createPattern: function(image, repetition) { + // If the image is null, the implementation must raise a + // TYPE_MISMATCH_ERR exception. + if (!image) { + throwException(TYPE_MISMATCH_ERR); + } + + var tagName = image.tagName, src; + var canvasId = this._canvasId; + + // If the first argument isn't an img, canvas, or video element, + // throws a TYPE_MISMATCH_ERR exception. + if (tagName) { + tagName = tagName.toLowerCase(); + if (tagName === "img") { + src = image.getAttribute("src", 2); + } else if (tagName === CANVAS || tagName === "video") { + // For now, only HTMLImageElement is supported. + return; + } else { + throwException(TYPE_MISMATCH_ERR); + } + } + + // Additionally, we accept any object that has a src property. + // This is useful when you'd like to specify a long data URI. + else if (image.src) { + src = image.src; + } else { + throwException(TYPE_MISMATCH_ERR); + } + + // If the second argument isn't one of the allowed values, throws a + // SYNTAX_ERR exception. + if (!(repetition === "repeat" || repetition === "no-repeat" || + repetition === "repeat-x" || repetition === "repeat-y" || + repetition === "" || repetition === NULL)) { + throwException(SYNTAX_ERR); + } + + // Special characters in the filename need escaping. + this._queue.push(properties.createPattern, encodeXML(src), repetition); + + if (isReady[canvasId]) { + this._executeCommand(); + ++lock[canvasId]; + } + + return new CanvasPattern(this); + }, + + /* + * line caps/joins + */ + + _setLineStyles: function() { + var queue = this._queue; + if (this._lineWidth !== this.lineWidth) { + this._lineWidth = this.lineWidth; + queue.push(properties.lineWidth, this._lineWidth); + } + if (this._lineCap !== this.lineCap) { + this._lineCap = this.lineCap; + queue.push(properties.lineCap, this._lineCap); + } + if (this._lineJoin !== this.lineJoin) { + this._lineJoin = this.lineJoin; + queue.push(properties.lineJoin, this._lineJoin); + } + if (this._miterLimit !== this.miterLimit) { + this._miterLimit = this.miterLimit; + queue.push(properties.miterLimit, this._miterLimit); + } + }, + + /* + * shadows + */ + + _setShadows: function() { + var queue = this._queue; + if (this._shadowOffsetX !== this.shadowOffsetX) { + this._shadowOffsetX = this.shadowOffsetX; + queue.push(properties.shadowOffsetX, this._shadowOffsetX); + } + if (this._shadowOffsetY !== this.shadowOffsetY) { + this._shadowOffsetY = this.shadowOffsetY; + queue.push(properties.shadowOffsetY, this._shadowOffsetY); + } + if (this._shadowBlur !== this.shadowBlur) { + this._shadowBlur = this.shadowBlur; + queue.push(properties.shadowBlur, this._shadowBlur); + } + if (this._shadowColor !== this.shadowColor) { + this._shadowColor = this.shadowColor; + queue.push(properties.shadowColor, this._shadowColor); + } + }, + + /* + * rects + */ + + clearRect: function(x, y, w, h) { + this._queue.push(properties.clearRect, x, y, w, h); + }, + + fillRect: function(x, y, w, h) { + this._setCompositing(); + this._setShadows(); + this._setFillStyle(); + this._queue.push(properties.fillRect, x, y, w, h); + }, + + strokeRect: function(x, y, w, h) { + this._setCompositing(); + this._setShadows(); + this._setStrokeStyle(); + this._setLineStyles(); + this._queue.push(properties.strokeRect, x, y, w, h); + }, + + /* + * path API + */ + + beginPath: function() { + this._queue.push(properties.beginPath); + }, + + closePath: function() { + this._queue.push(properties.closePath); + }, + + moveTo: function(x, y) { + this._queue.push(properties.moveTo, x, y); + }, + + lineTo: function(x, y) { + this._queue.push(properties.lineTo, x, y); + }, + + quadraticCurveTo: function(cpx, cpy, x, y) { + this._queue.push(properties.quadraticCurveTo, cpx, cpy, x, y); + }, + + bezierCurveTo: function(cp1x, cp1y, cp2x, cp2y, x, y) { + this._queue.push(properties.bezierCurveTo, cp1x, cp1y, cp2x, cp2y, x, y); + }, + + arcTo: function(x1, y1, x2, y2, radius) { + // Throws an INDEX_SIZE_ERR exception if the given radius is negative. + if (radius < 0 && isFinite(radius)) { + throwException(INDEX_SIZE_ERR); + } + + this._queue.push(properties.arcTo, x1, y1, x2, y2, radius); + }, + + rect: function(x, y, w, h) { + this._queue.push(properties.rect, x, y, w, h); + }, + + arc: function(x, y, radius, startAngle, endAngle, anticlockwise) { + // Throws an INDEX_SIZE_ERR exception if the given radius is negative. + if (radius < 0 && isFinite(radius)) { + throwException(INDEX_SIZE_ERR); + } + + this._queue.push(properties.arc, x, y, radius, startAngle, endAngle, anticlockwise ? 1 : 0); + }, + + fill: function() { + this._setCompositing(); + this._setShadows(); + this._setFillStyle(); + this._queue.push(properties.fill); + }, + + stroke: function() { + this._setCompositing(); + this._setShadows(); + this._setStrokeStyle(); + this._setLineStyles(); + this._queue.push(properties.stroke); + }, + + clip: function() { + this._queue.push(properties.clip); + }, + + isPointInPath: function(x, y) { + // TODO: Implement + }, + + /* + * text + */ + + _setFontStyles: function() { + var queue = this._queue; + if (this._font !== this.font) { + try { + var span = spans[this._canvasId]; + span.style.font = this._font = this.font; + + var style = span.currentStyle; + var fontSize = span.offsetHeight; + var font = [style.fontStyle, style.fontWeight, fontSize, style.fontFamily].join(" "); + queue.push(properties.font, font); + } catch(e) { + // If this.font cannot be parsed as a CSS font value, then it + // must be ignored. + } + } + if (this._textAlign !== this.textAlign) { + this._textAlign = this.textAlign; + queue.push(properties.textAlign, this._textAlign); + } + if (this._textBaseline !== this.textBaseline) { + this._textBaseline = this.textBaseline; + queue.push(properties.textBaseline, this._textBaseline); + } + if (this._direction !== this.canvas.currentStyle.direction) { + this._direction = this.canvas.currentStyle.direction; + queue.push(properties.direction, this._direction); + } + }, + + fillText: function(text, x, y, maxWidth) { + this._setCompositing(); + this._setFillStyle(); + this._setShadows(); + this._setFontStyles(); + this._queue.push(properties.fillText, encodeXML(text), x, y, + maxWidth === undefined ? Infinity : maxWidth); + }, + + strokeText: function(text, x, y, maxWidth) { + this._setCompositing(); + this._setStrokeStyle(); + this._setShadows(); + this._setFontStyles(); + this._queue.push(properties.strokeText, encodeXML(text), x, y, + maxWidth === undefined ? Infinity : maxWidth); + }, + + measureText: function(text) { + var span = spans[this._canvasId]; + try { + span.style.font = this.font; + } catch(e) { + // If this.font cannot be parsed as a CSS font value, then it must + // be ignored. + } + + // Replace space characters with tab characters because innerText + // removes trailing white spaces. + span.innerText = text.replace(/[ \n\f\r]/g, "\t"); + + return new TextMetrics(span.offsetWidth); + }, + + /* + * drawing images + */ + + drawImage: function(image, x1, y1, w1, h1, x2, y2, w2, h2) { + // If the image is null, the implementation must raise a + // TYPE_MISMATCH_ERR exception. + if (!image) { + throwException(TYPE_MISMATCH_ERR); + } + + var tagName = image.tagName, src, argc = arguments.length; + var canvasId = this._canvasId; + + // If the first argument isn't an img, canvas, or video element, + // throws a TYPE_MISMATCH_ERR exception. + if (tagName) { + tagName = tagName.toLowerCase(); + if (tagName === "img") { + src = image.getAttribute("src", 2); + } else if (tagName === CANVAS || tagName === "video") { + // For now, only HTMLImageElement is supported. + return; + } else { + throwException(TYPE_MISMATCH_ERR); + } + } + + // Additionally, we accept any object that has a src property. + // This is useful when you'd like to specify a long data URI. + else if (image.src) { + src = image.src; + } else { + throwException(TYPE_MISMATCH_ERR); + } + + this._setCompositing(); + this._setShadows(); + + // Special characters in the filename need escaping. + src = encodeXML(src); + + if (argc === 3) { + this._queue.push(properties.drawImage, argc, src, x1, y1); + } else if (argc === 5) { + this._queue.push(properties.drawImage, argc, src, x1, y1, w1, h1); + } else if (argc === 9) { + // If one of the sw or sh arguments is zero, the implementation + // must raise an INDEX_SIZE_ERR exception. + if (w1 === 0 || h1 === 0) { + throwException(INDEX_SIZE_ERR); + } + + this._queue.push(properties.drawImage, argc, src, x1, y1, w1, h1, x2, y2, w2, h2); + } else { + return; + } + + if (isReady[canvasId]) { + this._executeCommand(); + ++lock[canvasId]; + } + }, + + /* + * pixel manipulation + */ + + // ImageData createImageData(in float sw, in float sh); + // ImageData createImageData(in ImageData imagedata); + createImageData: function() { + // TODO: Implement + }, + + // ImageData getImageData(in float sx, in float sy, in float sw, in float sh); + getImageData: function(sx, sy, sw, sh) { + // TODO: Implement + }, + + // void putImageData(in ImageData imagedata, in float dx, in float dy, [Optional] in float dirtyX, in float dirtyY, in float dirtyWidth, in float dirtyHeight); + putImageData: function(imagedata, dx, dy, dirtyX, dirtyY, dirtyWidth, dirtyHeight) { + // TODO: Implement + }, + + /* + * private methods + */ + + _initialize: function() { + // compositing + this.globalAlpha = this._globalAlpha = 1.0; + this.globalCompositeOperation = this._globalCompositeOperation = "source-over"; + + // colors and styles + this.strokeStyle = this._strokeStyle = "#000000"; + this.fillStyle = this._fillStyle = "#000000"; + + // line caps/joins + this.lineWidth = this._lineWidth = 1.0; + this.lineCap = this._lineCap = "butt"; + this.lineJoin = this._lineJoin = "miter"; + this.miterLimit = this._miterLimit = 10.0; + + // shadows + this.shadowOffsetX = this._shadowOffsetX = 0; + this.shadowOffsetY = this._shadowOffsetY = 0; + this.shadowBlur = this._shadowBlur = 0; + this.shadowColor = this._shadowColor = "rgba(0, 0, 0, 0.0)"; + + // text + this.font = this._font = "10px sans-serif"; + this.textAlign = this._textAlign = "start"; + this.textBaseline = this._textBaseline = "alphabetic"; + + // command queue + this._queue = []; + + // stack of drawing states + this._stateStack = []; + }, + + _flush: function() { + var queue = this._queue; + this._queue = []; + return queue; + }, + + _executeCommand: function() { + // execute commands + var commands = this._flush(); + if (commands.length > 0) { + return eval(this._swf.CallFunction( + '<invoke name="executeCommand" returntype="javascript"><arguments><string>' + + commands.join("�") + "</string></arguments></invoke>" + )); + } + }, + + _resize: function(width, height) { + // Flush commands in the queue + this._executeCommand(); + + // Clear back to the initial state + this._initialize(); + + // Adjust the size of Flash to that of the canvas + if (width > 0) { + this._swf.width = width; + } + if (height > 0) { + this._swf.height = height; + } + + // Execute a resize command at the start of the next frame + this._queue.push(properties.resize, width, height); + } +}; + +/** + * CanvasGradient stub + * @constructor + */ +var CanvasGradient = function(ctx) { + this._ctx = ctx; + this.id = ctx._gradientPatternId++; +}; + +CanvasGradient.prototype = { + addColorStop: function(offset, color) { + // Throws an INDEX_SIZE_ERR exception if the offset is out of range. + if (isNaN(offset) || offset < 0 || offset > 1) { + throwException(INDEX_SIZE_ERR); + } + + this._ctx._queue.push(properties.addColorStop, this.id, offset, color); + } +}; + +/** + * CanvasPattern stub + * @constructor + */ +var CanvasPattern = function(ctx) { + this.id = ctx._gradientPatternId++; +}; + +/** + * TextMetrics stub + * @constructor + */ +var TextMetrics = function(width) { + this.width = width; +}; + +/** + * DOMException + * @constructor + */ +var DOMException = function(code) { + this.code = code; + this.message = DOMExceptionNames[code]; +}; + +DOMException.prototype = new Error; + +var DOMExceptionNames = { + 1: "INDEX_SIZE_ERR", + 9: "NOT_SUPPORTED_ERR", + 11: "INVALID_STATE_ERR", + 12: "SYNTAX_ERR", + 17: "TYPE_MISMATCH_ERR", + 18: "SECURITY_ERR" +}; + +/* + * Event handlers + */ + +function onReadyStateChange() { + if (document.readyState === "complete") { + document.detachEvent(ON_READY_STATE_CHANGE, onReadyStateChange); + + var canvases = document.getElementsByTagName(CANVAS); + for (var i = 0, n = canvases.length; i < n; ++i) { + FlashCanvas.initElement(canvases[i]); + } + } +} + +function onFocus() { + // forward the event to the parent + var swf = event.srcElement, canvas = swf.parentNode; + swf.blur(); + canvas.focus(); +} + +function onPropertyChange() { + var prop = event.propertyName; + if (prop === "width" || prop === "height") { + var canvas = event.srcElement; + var value = canvas[prop]; + var number = parseInt(value, 10); + + if (isNaN(number) || number < 0) { + number = (prop === "width") ? 300 : 150; + } + + if (value === number) { + canvas.style[prop] = number + "px"; + canvas.getContext("2d")._resize(canvas.width, canvas.height); + } else { + canvas[prop] = number; + } + } +} + +function onUnload() { + window.detachEvent(ON_UNLOAD, onUnload); + + for (var canvasId in canvases) { + var canvas = canvases[canvasId], swf = canvas.firstChild, prop; + + // clean up the references of swf.executeCommand and swf.resize + for (prop in swf) { + if (typeof swf[prop] === "function") { + swf[prop] = NULL; + } + } + + // clean up the references of canvas.getContext and canvas.toDataURL + for (prop in canvas) { + if (typeof canvas[prop] === "function") { + canvas[prop] = NULL; + } + } + + // remove event listeners + swf.detachEvent(ON_FOCUS, onFocus); + canvas.detachEvent(ON_PROPERTY_CHANGE, onPropertyChange); + } + + // delete exported symbols + window[CANVAS_RENDERING_CONTEXT_2D] = NULL; + window[CANVAS_GRADIENT] = NULL; + window[CANVAS_PATTERN] = NULL; + window[FLASH_CANVAS] = NULL; + window[G_VML_CANVAS_MANAGER] = NULL; +} + +/* + * FlashCanvas API + */ + +var FlashCanvas = { + initElement: function(canvas) { + // Check whether the initialization is required or not. + if (canvas.getContext) { + return canvas; + } + + // initialize lock + var canvasId = getUniqueId(); + var objectId = OBJECT_ID_PREFIX + canvasId; + isReady[canvasId] = false; + lock[canvasId] = 1; + + // Set the width and height attributes. + setCanvasSize(canvas); + + // embed swf and SPAN element + canvas.innerHTML = + '<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"' + + ' codebase="' + location.protocol + '//fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0"' + + ' width="100%" height="100%" id="' + objectId + '">' + + '<param name="allowScriptAccess" value="always">' + + '<param name="flashvars" value="id=' + objectId + '">' + + '<param name="wmode" value="transparent">' + + '</object>' + + '<span style="margin:0;padding:0;border:0;display:inline-block;position:static;height:1em;overflow:visible;white-space:nowrap">' + + '</span>'; + + canvases[canvasId] = canvas; + var swf = canvas.firstChild; + spans[canvasId] = canvas.lastChild; + + // Check whether the canvas element is in the DOM tree + var documentContains = document.body.contains; + if (documentContains(canvas)) { + // Load swf file immediately + swf["movie"] = SWF_URL; + } else { + // Wait until the element is added to the DOM tree + var intervalId = setInterval(function() { + if (documentContains(canvas)) { + clearInterval(intervalId); + swf["movie"] = SWF_URL; + } + }, 0); + } + + // If the browser is IE6 or in quirks mode + if (document.compatMode === "BackCompat" || !window.XMLHttpRequest) { + spans[canvasId].style.overflow = "hidden"; + } + + // initialize context + var ctx = new CanvasRenderingContext2D(canvas, swf); + + // canvas API + canvas.getContext = function(contextId) { + return contextId === "2d" ? ctx : NULL; + }; + + canvas.toDataURL = function(type, quality) { + if (("" + type).replace(/[A-Z]+/g, toLowerCase) === "image/jpeg") { + ctx._queue.push(properties.toDataURL, type, + typeof quality === "number" ? quality : ""); + } else { + ctx._queue.push(properties.toDataURL, type); + } + return ctx._executeCommand(); + }; + + // add event listener + swf.attachEvent(ON_FOCUS, onFocus); + + return canvas; + }, + + saveImage: function(canvas) { + var swf = canvas.firstChild; + swf.saveImage(); + }, + + setOptions: function(options) { + // TODO: Implement + }, + + trigger: function(canvasId, type) { + var canvas = canvases[canvasId]; + canvas.fireEvent("on" + type); + }, + + unlock: function(canvasId, ready) { + if (lock[canvasId]) { + --lock[canvasId]; + } + if (ready) { + var canvas = canvases[canvasId]; + var swf = canvas.firstChild; + var width; + var height; + + // Set the width and height attributes of the canvas element. + setCanvasSize(canvas); + width = canvas.width; + height = canvas.height; + + canvas.style.width = width + "px"; + canvas.style.height = height + "px"; + + // Adjust the size of Flash to that of the canvas + if (width > 0) { + swf.width = width; + } + if (height > 0) { + swf.height = height; + } + swf.resize(width, height); + + // Add event listener + canvas.attachEvent(ON_PROPERTY_CHANGE, onPropertyChange); + + // ExternalInterface is now ready for use + isReady[canvasId] = true; + } + } +}; + +/* + * Utility methods + */ + +// Get the absolute URL of flashcanvas.js +function getScriptUrl() { + var scripts = document.getElementsByTagName("script"); + var script = scripts[scripts.length - 1]; + + // @see http://msdn.microsoft.com/en-us/library/ms536429(VS.85).aspx + if (document.documentMode >= 8) { + return script.src; + } else { + return script.getAttribute("src", 4); + } +} + +// Get a unique ID composed of alphanumeric characters. +function getUniqueId() { + return Math.random().toString(36).slice(2) || "0"; +} + +// Escape characters not permitted in XML. +function encodeXML(str) { + return ("" + str).replace(/&/g, "&").replace(/</g, "<"); +} + +function toLowerCase(str) { + return str.toLowerCase(); +} + +function throwException(code) { + throw new DOMException(code); +} + +// The width and height attributes of a canvas element must have values that +// are valid non-negative integers. +function setCanvasSize(canvas) { + var width = parseInt(canvas.width, 10); + var height = parseInt(canvas.height, 10); + + if (isNaN(width) || width < 0) { + width = 300; + } + if (isNaN(height) || height < 0) { + height = 150; + } + + canvas.width = width; + canvas.height = height; +} + +/* + * initialization + */ + +// IE HTML5 shiv +document.createElement(CANVAS); + +// setup default CSS +document.createStyleSheet().cssText = + CANVAS + "{display:inline-block;overflow:hidden;width:300px;height:150px}"; + +// initialize canvas elements +if (document.readyState === "complete") { + onReadyStateChange(); +} else { + document.attachEvent(ON_READY_STATE_CHANGE, onReadyStateChange); +} + +// prevent IE6 memory leaks +window.attachEvent(ON_UNLOAD, onUnload); + +// preload SWF file if it's in the same domain +if (SWF_URL.indexOf(location.protocol + "//" + location.host + "/") === 0) { + var req = new ActiveXObject("Microsoft.XMLHTTP"); + req.open("GET", SWF_URL, false); + req.send(NULL); +} + +/* + * public API + */ + +window[CANVAS_RENDERING_CONTEXT_2D] = CanvasRenderingContext2D; +window[CANVAS_GRADIENT] = CanvasGradient; +window[CANVAS_PATTERN] = CanvasPattern; +window[FLASH_CANVAS] = FlashCanvas; + +// ExplorerCanvas-compatible APIs for convenience +window[G_VML_CANVAS_MANAGER] = { + init: function(){}, + init_: function(){}, + initElement: FlashCanvas.initElement +}; + +// Prevent Closure Compiler from removing the function. +keep = CanvasRenderingContext2D.measureText; + +})(window, document); + +} diff --git a/js/canvg/flashcanvas.swf b/js/canvg/flashcanvas.swf new file mode 100644 index 0000000..66ff213 Binary files /dev/null and b/js/canvg/flashcanvas.swf differ diff --git a/js/highcharts/exporting.js b/js/highcharts/exporting.js index 4f134d5..036c6ae 100644 --- a/js/highcharts/exporting.js +++ b/js/highcharts/exporting.js @@ -308,6 +308,10 @@ extend(Chart.prototype, { chart = this, canvas=createElement('canvas');
+ if (typeof FlashCanvas != "undefined") { + FlashCanvas.initElement(canvas); + } + $('body').append(canvas); $(canvas).hide();
diff --git a/js/highcharts/highcharts.js b/js/highcharts/highcharts.js index c15862b..4ad0c6c 100644 --- a/js/highcharts/highcharts.js +++ b/js/highcharts/highcharts.js @@ -2210,7 +2210,7 @@ SVGRenderer.prototype = { if (lineNo) { // Webkit and opera sometimes return 'normal' as the line height. In that // case, webkit uses offsetHeight, while Opera falls back to 18 - lineHeight = pInt(window.getComputedStyle(lastLine, null).getPropertyValue('line-height')); + if(window.getComputedStyle) lineHeight = pInt(window.getComputedStyle(lastLine, null).getPropertyValue('line-height')); if (isNaN(lineHeight)) { lineHeight = textLineHeight || lastLine.offsetHeight || 18; } diff --git a/po/en_GB.po b/po/en_GB.po index ec6b80a..2c6d439 100644 --- a/po/en_GB.po +++ b/po/en_GB.po @@ -4,7 +4,7 @@ msgstr "" "Project-Id-Version: phpMyAdmin 3.5.0-dev\n" "Report-Msgid-Bugs-To: phpmyadmin-devel@lists.sourceforge.net\n" "POT-Creation-Date: 2011-06-14 17:22+0200\n" -"PO-Revision-Date: 2011-06-09 22:12+0200\n" +"PO-Revision-Date: 2011-06-15 02:35+0200\n" "Last-Translator: Marc Delisle marc@infomarc.info\n" "Language-Team: english-gb en_GB@li.org\n" "Language: en_GB\n" @@ -1005,10 +1005,9 @@ msgstr "This is not a number!"
#. l10n: Default description for the y-Axis of Charts #: js/messages.php:51 -#, fuzzy #| msgid "Log file count" msgid "Total count" -msgstr "Log file count" +msgstr "Total count"
#: js/messages.php:54 msgid "The host name is empty!" @@ -1045,24 +1044,22 @@ msgid "Close" msgstr "Close"
#: js/messages.php:64 server_status.php:393 -#, fuzzy #| msgid "Server Choice" msgid "Live traffic chart" -msgstr "Server Choice" +msgstr "Live traffic chart"
#: js/messages.php:65 server_status.php:396 msgid "Live conn./process chart" -msgstr "" +msgstr "Live conn./process chart"
#: js/messages.php:66 server_status.php:423 -#, fuzzy #| msgid "Show query chart" msgid "Live query chart" -msgstr "Show query chart" +msgstr "Live query chart"
#: js/messages.php:68 msgid "Static data" -msgstr "" +msgstr "Static data"
#. l10n: Total number of queries #: js/messages.php:70 libraries/build_html_for_db.lib.php:45 @@ -1075,7 +1072,7 @@ msgstr "Total" #. l10n: Other, small valued, queries #: js/messages.php:72 server_status.php:586 msgid "Other" -msgstr "" +msgstr "Other"
#. l10n: Thousands separator #: js/messages.php:74 libraries/common.lib.php:1359 @@ -8212,71 +8209,62 @@ msgid "Runtime Information" msgstr "Runtime Information"
#: server_status.php:367 -#, fuzzy #| msgid "Server Choice" msgid "Server traffic" -msgstr "Server Choice" +msgstr "Server traffic"
#: server_status.php:368 msgid "Query statistics" msgstr "Query statistics"
#: server_status.php:369 -#, fuzzy #| msgid "See slave status table" msgid "All status variables" -msgstr "See slave status table" +msgstr "All status variables"
#: server_status.php:379 server_status.php:410 -#, fuzzy #| msgid "Refresh" msgid "Refresh rate" -msgstr "Refresh" +msgstr "Refresh rate"
#: server_status.php:380 server_status.php:411 -#, fuzzy #| msgid "Second" msgid "second" -msgstr "Second" +msgstr "second"
#: server_status.php:381 server_status.php:382 server_status.php:383 #: server_status.php:384 server_status.php:385 server_status.php:412 #: server_status.php:413 server_status.php:414 server_status.php:415 #: server_status.php:416 -#, fuzzy #| msgid "Second" msgid "seconds" -msgstr "Second" +msgstr "seconds"
#: server_status.php:386 server_status.php:387 server_status.php:388 #: server_status.php:389 server_status.php:417 server_status.php:418 #: server_status.php:419 server_status.php:420 -#, fuzzy #| msgid "Minute" msgid "minutes" -msgstr "Minute" +msgstr "minutes"
#: server_status.php:440 -#, fuzzy #| msgid "Do not change the password" msgid "Containing the word:" -msgstr "Do not change the password" +msgstr "Containing the word:"
#: server_status.php:445 -#, fuzzy #| msgid "Show open tables" msgid "Show only alert values" -msgstr "Show open tables" +msgstr "Show only alert values"
#: server_status.php:449 msgid "Filter by category..." -msgstr "" +msgstr "Filter by category..."
#: server_status.php:462 -#, fuzzy #| msgid "Related Links" msgid "Related links:" -msgstr "Related Links" +msgstr "Related links:"
#: server_status.php:507 server_status.php:539 server_status.php:660 #: server_status.php:705 @@ -8298,12 +8286,12 @@ msgstr "Query type" #. l10n: # = Amount of queries #: server_status.php:537 msgid "#" -msgstr "" +msgstr "#"
#: server_status.php:609 #, php-format msgid "Network traffic since startup: %s" -msgstr "" +msgstr "Network traffic since startup: %s"
#: server_status.php:617 #, php-format @@ -8384,10 +8372,9 @@ msgid "ID" msgstr "ID"
#: server_status.php:840 -#, fuzzy #| msgid "Whether to enable SSL for connection to MySQL server." msgid "The number of failed attempts to connect to the MySQL server." -msgstr "Whether to enable SSL for connection to MySQL server." +msgstr "The number of failed attempts to connect to the MySQL server."
#: server_status.php:841 msgid "" @@ -8407,6 +8394,7 @@ msgstr "The number of transactions that used the temporary binary log cache." msgid "" "The number of connection attempts (successful or not) to the MySQL server." msgstr "" +"The number of connection attempts (successful or not) to the MySQL server."
#: server_status.php:844 msgid "" @@ -8826,6 +8814,8 @@ msgid "" "The maximum number of connections that have been in use simultaneously since " "the server started." msgstr "" +"The maximum number of connections that have been in use simultaneously since " +"the server started."
#: server_status.php:915 msgid "The number of rows waiting to be written in INSERT DELAYED queues." @@ -8857,6 +8847,9 @@ msgid "" "fragmentation issues, which may be solved by issuing a FLUSH QUERY CACHE " "statement." msgstr "" +"The number of free memory blocks in query cache. High numbers can indicate " +"fragmentation issues, which may be solved by issuing a FLUSH QUERY CACHE " +"statement."
#: server_status.php:921 msgid "The amount of free memory for query cache." @@ -9583,10 +9576,9 @@ msgid "Line" msgstr "Line"
#: tbl_chart.php:88 -#, fuzzy #| msgid "Inline" msgid "Spline" -msgstr "Inline" +msgstr "Spline"
#: tbl_chart.php:89 msgid "Pie" @@ -9597,50 +9589,43 @@ msgid "Stacked" msgstr "Stacked"
#: tbl_chart.php:94 -#, fuzzy #| msgid "Report title:" msgid "Chart title" -msgstr "Report title:" +msgstr "Chart title"
#: tbl_chart.php:99 msgid "X-Axis:" -msgstr "" +msgstr "X-Axis:"
#: tbl_chart.php:113 -#, fuzzy #| msgid "SQL queries" msgid "Series:" -msgstr "SQL queries" +msgstr "Series:"
#: tbl_chart.php:115 -#, fuzzy #| msgid "Textarea columns" msgid "The remaining columns" -msgstr "Textarea columns" +msgstr "The remaining columns"
#: tbl_chart.php:128 -#, fuzzy #| msgid "X Axis label" msgid "X-Axis label:" -msgstr "X Axis label" +msgstr "X-Axis label:"
#: tbl_chart.php:128 -#, fuzzy #| msgid "Value" msgid "X Values" -msgstr "Value" +msgstr "X Values"
#: tbl_chart.php:129 -#, fuzzy #| msgid "Y Axis label" msgid "Y-Axis label:" -msgstr "Y Axis label" +msgstr "Y-Axis label:"
#: tbl_chart.php:129 -#, fuzzy #| msgid "Value" msgid "Y Values" -msgstr "Value" +msgstr "Y Values"
#: tbl_create.php:56 #, php-format diff --git a/server_status.php b/server_status.php index cba7266..c56eb70 100644 --- a/server_status.php +++ b/server_status.php @@ -44,13 +44,16 @@ if (isset($_REQUEST['ajax_request'])) { cleanDeprecated($queries); // admin commands are not queries unset($queries['Com_admin_commands']); + $sum=array_sum($queries); $ret = Array('x'=>(microtime(true)*1000),'y'=>$sum,'pointInfo'=>$queries); exit(json_encode($ret)); case 'traffic': $traffic = PMA_DBI_fetch_result('SHOW GLOBAL STATUS WHERE Variable_name="Bytes_received" OR Variable_name="Bytes_sent"', 0, 1); + $ret = Array('x'=>(microtime(true)*1000),'y_sent'=>$traffic['Bytes_sent'],'y_received'=>$traffic['Bytes_received']); exit(json_encode($ret)); + } } } @@ -73,6 +76,7 @@ $GLOBALS['js_include'][] = 'jquery/jquery.cookie.js'; // For tab persistence $GLOBALS['js_include'][] = 'highcharts/highcharts.js'; /* Files required for chart exporting */ $GLOBALS['js_include'][] = 'highcharts/exporting.js'; +$GLOBALS['js_include'][] = 'canvg/flashcanvas.js'; $GLOBALS['js_include'][] = 'canvg/canvg.js'; $GLOBALS['js_include'][] = 'canvg/rgbcolor.js';
@@ -394,6 +398,8 @@ echo __('Runtime Information'); </a> <a class="tabChart liveconnectionsLink" href="#"> <?php echo __('Live conn./process chart'); ?> + + </a> </div> <div class="tabInnerContent">
hooks/post-receive