Commit 0f49234e4d2fbc1df888643eb2f9b3f4b0a79b03

Authored by Edmar Moretti
1 parent 6b7c1751

$1

admin/admin.db
No preview for this file type
classesjs/dicionario_ajuda.js
... ... @@ -693,7 +693,7 @@ g_traducao_ajuda = {
693 693 },
694 694 "84": {
695 695 titulo: "Gráfico interativo",
696   - diretorio:"i3geo/ferramentas/graficointerativo",
  696 + diretorio:"i3geo/ferramentas/graficointerativo1",
697 697 categoria:"3",
698 698 pt:"Gerador de representação gráfica de dados tabulares. Abre uma janela flutuante onde o usuário pode escolher os dados e o tipo de gráfico desejado. Os dados são baseados em um dos temas existentes no mapa.",
699 699 complemento:"Existem várias opções de tratamento dos dados que permitem, por exemplo, mostrar os percentuais ou os dados brutos. Pode-se ainda ativar a navegação dinâmica, o que permite atualizar o gráfico conforme é feita a navegação sobre o mapa.",
... ...
documentacao/manual-i3geo-5_0-pt.odt
No preview for this file type
documentacao/manual-i3geo-5_0-pt.pdf
No preview for this file type
ferramentas/graficointerativo1/dicionario.js
... ... @@ -67,7 +67,7 @@ i3GEOF.graficointerativo1.dicionario = {
67 67 it:""
68 68 }],
69 69 12: [{
70   - pt:"Escolha os dados que comporão o gráfico",
  70 + pt:"Configuração do gráfico",
71 71 en:"",
72 72 es:"",
73 73 it:""
... ... @@ -128,7 +128,8 @@ i3GEOF.graficointerativo1.dicionario = {
128 128 }],
129 129 22: [{
130 130 pt:"Utiliza valores acumulados",
131   - en:"",
  131 + en:"",titleFont: 'bold 14px sans-serif',
  132 + titlePosition: "top",
132 133 es:"",
133 134 it:""
134 135 }],
... ... @@ -193,7 +194,7 @@ i3GEOF.graficointerativo1.dicionario = {
193 194 it:""
194 195 }],
195 196 33: [{
196   - pt:"Digite o título",
  197 + pt:"Digite o título para legenda",
197 198 en:"",
198 199 es:"",
199 200 it:""
... ... @@ -295,7 +296,19 @@ i3GEOF.graficointerativo1.dicionario = {
295 296 it:""
296 297 }],
297 298 50: [{
298   - pt:"",
  299 + pt:"Título",
  300 + en:"",
  301 + es:"",
  302 + it:""
  303 + }],
  304 + 51: [{
  305 + pt:"Título do eixo X",
  306 + en:"",
  307 + es:"",
  308 + it:""
  309 + }],
  310 + 52: [{
  311 + pt:"Título do eixo Y",
299 312 en:"",
300 313 es:"",
301 314 it:""
... ...
ferramentas/graficointerativo1/index.js
... ... @@ -45,199 +45,230 @@ if (typeof (i3GEOF) === 'undefined') {
45 45 *
46 46 */
47 47 i3GEOF.graficointerativo1 = {
48   - /*
49   - * Variavel: aguarde
50   - *
51   - * Estilo do objeto DOM com a imagem de aguarde existente no
52   - * cabeçalho da janela.
53   - */
54   - aguarde : "",
55   - /*
56   - * Propriedade: dados
57   - *
58   - * Dados que serao utilizados. Pode ser passado como parametro.
59   - *
60   - * Default: {false}
61   - */
62   - dados : false,
63   - /*
64   - * Propriedade: titulo
65   - *
66   - * Título do gráfico. Se for vazio, será obtido do nome
67   - * do tema selecionado
68   - */
69   - titulo : "",
70   - /*
71   - * Propriedade: tipo
72   - *
73   - * Tipo de gráfico escolhido pelo usuário.
74   - */
75   - tipo : "",
76   - /*
77   - * Propriedade: acumula
78   - *
79   - * Acumula os valores ao gerar o gráfico
80   - *
81   - * Type: {boolean}
82   - *
83   - * Default: {false}
84   - */
85   - acumula : false,
86   - /*
87   - * Propriedade: relativa
88   - *
89   - * Utiliza valores relativos ao criar o gráfico
90   - *
91   - * Type: {boolean}
92   - *
93   - * Default: {false}
94   - */
95   - relativa : false,
96   - /*
97   - * Propriedade: dadospuros
98   - *
99   - * Não faz nenhum tipo de processamento nos dados antes de gerar o
100   - * gráfico
101   - *
102   - * Type: {boolean}
103   - *
104   - * Default: {false}
105   - */
106   - dadospuros : false,
107   - /*
108   - * Propriedade: navegacao
109   - *
110   - * Ativa ou não a navegação dinâmica do mapa
111   - *
112   - * Type: {boolean}
113   - *
114   - * Default: {false}
115   - */
116   - navegacao : false,
  48 + /*
  49 + * Variavel: aguarde
  50 + *
  51 + * Estilo do objeto DOM com a imagem de aguarde existente no
  52 + * cabeçalho da janela.
  53 + */
  54 + aguarde : "",
  55 + /*
  56 + * Propriedade: dados
  57 + *
  58 + * Dados que serao utilizados. Pode ser passado como parametro.
  59 + *
  60 + * Default: {false}
  61 + */
  62 + dados : false,
  63 + /*
  64 + * Propriedade: titulo
  65 + *
  66 + * Título do gráfico. Se for vazio, será obtido do nome
  67 + * do tema selecionado
  68 + */
  69 + titulo : "",
  70 + /*
  71 + * Propriedade: tipo
  72 + *
  73 + * Tipo de gráfico escolhido pelo usuário.
  74 + */
  75 + tipo : "",
  76 + /*
  77 + * Propriedade: acumula
  78 + *
  79 + * Acumula os valores ao gerar o gráfico
  80 + *
  81 + * Type: {boolean}
  82 + *
  83 + * Default: {false}
  84 + */
  85 + acumula : false,
  86 + /*
  87 + * Propriedade: relativa
  88 + *
  89 + * Utiliza valores relativos ao criar o gráfico
  90 + *
  91 + * Type: {boolean}
  92 + *
  93 + * Default: {false}
  94 + */
  95 + relativa : false,
  96 + /*
  97 + * Propriedade: dadospuros
  98 + *
  99 + * Não faz nenhum tipo de processamento nos dados antes de gerar o
  100 + * gráfico
  101 + *
  102 + * Type: {boolean}
  103 + *
  104 + * Default: {false}
  105 + */
  106 + dadospuros : false,
  107 + /*
  108 + * Propriedade: navegacao
  109 + *
  110 + * Ativa ou não a navegação dinâmica do mapa
  111 + *
  112 + * Type: {boolean}
  113 + *
  114 + * Default: {false}
  115 + */
  116 + navegacao : false,
117 117  
118   - /*
119   - * Para efeitos de compatibilidade antes da versão 4.7 que não
120   - * tinha dicionário
121   - */
122   - criaJanelaFlutuante : function(dados) {
123   - if (dados) {
124   - i3GEOF.graficointerativo1.dados = dados;
125   - }
126   - i3GEOF.graficointerativo1.iniciaDicionario();
127   - },
128   - /*
129   - * Function: iniciaDicionario
130   - *
131   - * Carrega o dicionário e chama a função que inicia a
132   - * ferramenta
133   - *
134   - * O Javascript é carregado com o id
135   - * i3GEOF.nomedaferramenta.dicionario_script
136   - */
137   - iniciaDicionario : function(dados) {
138   - if (dados) {
139   - i3GEOF.graficointerativo1.dados = dados;
140   - }
141   - if (typeof (i3GEOF.graficointerativo1.dicionario) === 'undefined') {
142   - i3GEO.util.scriptTag(i3GEO.configura.locaplic
143   - + "/ferramentas/graficointerativo1/dependencias.php",
144   - "i3GEOF.graficointerativo1.iniciaJanelaFlutuante()",
145   - "i3GEOF.graficointerativo1.dicionario_script");
146   - } else {
147   - i3GEOF.graficointerativo1.iniciaJanelaFlutuante(dados);
148   - }
149   - },
150   - /*
151   - * Function: inicia
152   - *
153   - * Inicia a ferramenta. É chamado por criaJanelaFlutuante
154   - *
155   - * Parametros:
156   - *
157   - * iddiv {String} - id do div que receberá o conteudo HTML da
158   - * ferramenta
159   - *
160   - * dados {JSON} - dados para o gráfico (opcional) exemplo
161   - * ["n;x","'Argentina';33796870","'Paraguay';4773464","'Brazil';151525400","'Chile';13772710"]
162   - */
163   - inicia : function(iddiv) {
164   - // try{
165   - $i(iddiv).innerHTML += i3GEOF.graficointerativo1.html();
166   - $i("i3GEOgraficointerativo1Acumula").checked = i3GEOF.graficointerativo1.acumula;
167   - $i("i3GEOgraficointerativo1Relativa").checked = i3GEOF.graficointerativo1.relativa;
168   - $i("i3GEOgraficointerativo1DadosPuros").checked = i3GEOF.graficointerativo1.dadospuros;
169   - if (i3GEOF.graficointerativo1.navegacao === true) {
170   - i3GEOF.graficointerativo1.ativaNavegacao(true);
171   - }
172   - // eventos das guias
173   - $i("i3GEOgraficointerativo1guia1").onclick = function() {
174   - i3GEO.guias.mostraGuiaFerramenta("i3GEOgraficointerativo1guia1",
175   - "i3GEOgraficointerativo1guia");
176   - $i("i3GEOgraficointerativo1Grafico").style.display = "none";
177   - };
178   - $i("i3GEOgraficointerativo1guia2").onclick = function() {
179   - i3GEO.guias.mostraGuiaFerramenta("i3GEOgraficointerativo1guia2",
180   - "i3GEOgraficointerativo1guia");
181   - i3GEOF.graficointerativo1.configuraDados();
182   - $i("i3GEOgraficointerativo1Grafico").style.display = "none";
183   - };
184   - $i("i3GEOgraficointerativo1guia3").onclick = function() {
185   - i3GEO.guias.mostraGuiaFerramenta("i3GEOgraficointerativo1guia3",
186   - "i3GEOgraficointerativo1guia");
187   - $i("i3GEOgraficointerativo1Grafico").style.display = "none";
188   - };
189   - $i("i3GEOgraficointerativo1guia4").onclick = function() {
190   - i3GEO.guias.mostraGuiaFerramenta("i3GEOgraficointerativo1guia4",
191   - "i3GEOgraficointerativo1guia");
192   - var t = $i("i3GEOgraficointerativo1Grafico");
193   - t.style.display = "block";
194   - t.style.position = "relative";
195   - t.style.top = "-5px";
196   - t.visibility = "visible";
197   - i3GEOF.graficointerativo1.tabela2dados();
198   - };
199   - $i("i3GEOgraficointerativo1guia5").onclick = function() {
200   - i3GEO.guias.mostraGuiaFerramenta("i3GEOgraficointerativo1guia5",
201   - "i3GEOgraficointerativo1guia");
202   - $i("i3GEOgraficointerativo1Grafico").style.display = "none";
203   - $i("i3GEOgraficointerativo1guia5obj").innerHTML = "<textarea rows='20' cols='52' >"
  118 + /*
  119 + * Para efeitos de compatibilidade antes da vers&atilde;o 4.7 que n&atilde;o
  120 + * tinha dicion&aacute;rio
  121 + */
  122 + criaJanelaFlutuante : function(dados) {
  123 + if (dados) {
  124 + i3GEOF.graficointerativo1.dados = dados;
  125 + }
  126 + i3GEOF.graficointerativo1.iniciaDicionario();
  127 + },
  128 + /*
  129 + * Function: iniciaDicionario
  130 + *
  131 + * Carrega o dicion&aacute;rio e chama a fun&ccedil;&atilde;o que inicia a
  132 + * ferramenta
  133 + *
  134 + * O Javascript &eacute; carregado com o id
  135 + * i3GEOF.nomedaferramenta.dicionario_script
  136 + */
  137 + iniciaDicionario : function(dados) {
  138 + if (dados) {
  139 + i3GEOF.graficointerativo1.dados = dados;
  140 + }
  141 + if (typeof (i3GEOF.graficointerativo1.dicionario) === 'undefined') {
  142 + i3GEO.util.scriptTag(i3GEO.configura.locaplic
  143 + + "/ferramentas/graficointerativo1/dependencias.php",
  144 + "i3GEOF.graficointerativo1.iniciaJanelaFlutuante()",
  145 + "i3GEOF.graficointerativo1.dicionario_script");
  146 + } else {
  147 + i3GEOF.graficointerativo1.iniciaJanelaFlutuante(dados);
  148 + }
  149 + },
  150 + /*
  151 + * Function: inicia
  152 + *
  153 + * Inicia a ferramenta. &Eacute; chamado por criaJanelaFlutuante
  154 + *
  155 + * Parametros:
  156 + *
  157 + * iddiv {String} - id do div que receber&aacute; o conteudo HTML da
  158 + * ferramenta
  159 + *
  160 + * dados {JSON} - dados para o gr&aacute;fico (opcional) exemplo
  161 + * ["n;x","'Argentina';33796870","'Paraguay';4773464","'Brazil';151525400","'Chile';13772710"]
  162 + */
  163 + inicia : function(iddiv) {
  164 + // try{
  165 + $i(iddiv).innerHTML += i3GEOF.graficointerativo1.html();
  166 + $i("i3GEOgraficointerativo1Acumula").checked = i3GEOF.graficointerativo1.acumula;
  167 + $i("i3GEOgraficointerativo1Relativa").checked = i3GEOF.graficointerativo1.relativa;
  168 + $i("i3GEOgraficointerativo1DadosPuros").checked = i3GEOF.graficointerativo1.dadospuros;
  169 + if (i3GEOF.graficointerativo1.navegacao === true) {
  170 + i3GEOF.graficointerativo1.ativaNavegacao(true);
  171 + }
  172 + // eventos das guias
  173 + $i("i3GEOgraficointerativo1guia1").onclick = function() {
  174 + i3GEO.guias.mostraGuiaFerramenta("i3GEOgraficointerativo1guia1",
  175 + "i3GEOgraficointerativo1guia");
  176 + $i("i3GEOgraficointerativo1Grafico").style.display = "none";
  177 + };
  178 + $i("i3GEOgraficointerativo1guia2").onclick = function() {
  179 + if(i3GEOF.graficointerativo1.tipo === ""){
  180 + alert($trad(4, i3GEOF.graficointerativo1.dicionario));
  181 + return;
  182 + }
  183 + i3GEO.guias.mostraGuiaFerramenta("i3GEOgraficointerativo1guia2","i3GEOgraficointerativo1guia");
  184 + i3GEOF.graficointerativo1.configuraDados();
  185 + $i("i3GEOgraficointerativo1Grafico").style.display = "none";
  186 + };
  187 + $i("i3GEOgraficointerativo1guia3").onclick = function() {
  188 + i3GEO.guias.mostraGuiaFerramenta("i3GEOgraficointerativo1guia3",
  189 + "i3GEOgraficointerativo1guia");
  190 + $i("i3GEOgraficointerativo1Grafico").style.display = "none";
  191 + };
  192 + $i("i3GEOgraficointerativo1guia4").onclick = function() {
  193 + if(i3GEOF.graficointerativo1.tipo === ""){
  194 + alert($trad(4, i3GEOF.graficointerativo1.dicionario));
  195 + return;
  196 + }
  197 + if($i("i3GEOgraficointerativo1Dados").innerHTML === ""){
  198 + return;
  199 + }
  200 + i3GEO.guias.mostraGuiaFerramenta("i3GEOgraficointerativo1guia4","i3GEOgraficointerativo1guia");
  201 + var t = $i("i3GEOgraficointerativo1Grafico");
  202 + t.style.display = "block";
  203 + t.style.position = "relative";
  204 + t.style.top = "-5px";
  205 + t.visibility = "visible";
  206 + i3GEOF.graficointerativo1.tabela2dados();
  207 + };
  208 + $i("i3GEOgraficointerativo1guia5").onclick = function() {
  209 + if(i3GEOF.graficointerativo1.tipo === ""){
  210 + alert($trad(4, i3GEOF.graficointerativo1.dicionario));
  211 + return;
  212 + }
  213 + if($i("i3GEOgraficointerativo1Dados").innerHTML === ""){
  214 + return;
  215 + }
  216 + i3GEO.guias.mostraGuiaFerramenta("i3GEOgraficointerativo1guia5","i3GEOgraficointerativo1guia");
  217 + $i("i3GEOgraficointerativo1Grafico").style.display = "none";
  218 + $i("i3GEOgraficointerativo1guia5obj").innerHTML = "<textarea rows='20' cols='52' >"
204 219 + (i3GEOF.graficointerativo1.tabela2csv()).join("\n")
205 220 + "</textarea>";
206   - };
207   -
208   - i3GEOF.graficointerativo1.ativaFoco();
209   - i3GEOF.graficointerativo1.comboTemas();
210   - new YAHOO.widget.Button("i3GEOgraficointerativo1botao1", {
211   - onclick : {
212   - fn : i3GEOF.graficointerativo1.obterDados
  221 + };
  222 + $i("i3GEOgraficointerativo1guia6").onclick = function() {
  223 + if(i3GEOF.graficointerativo1.tipo === ""){
  224 + alert($trad(4, i3GEOF.graficointerativo1.dicionario));
  225 + return;
  226 + }
  227 + if($i("i3GEOgraficointerativo1Dados").innerHTML === ""){
  228 + return;
  229 + }
  230 + var w,h,form = $i("i3GEOgraficointerativo1PNG"),
  231 + isvg = form.getElementsByTagName("input")[0],
  232 + svg = $i("i3GEOgraficointerativo1guia4objCanvas").firstChild;
  233 + h = svg.getAttributeNS(null, 'height');
  234 + w = svg.getAttributeNS(null, 'width');
  235 + if (typeof XMLSerializer != "undefined"){
  236 + svg = (new XMLSerializer()).serializeToString(svg);
  237 + } else {
  238 + svg = svg.html();
  239 + }
  240 + isvg.value = svg;
  241 + form.action = form.action+"?"+"w="+w+"&h="+h;
  242 + form.submit();
  243 + };
  244 + i3GEOF.graficointerativo1.ativaFoco();
  245 + i3GEOF.graficointerativo1.comboTemas();
  246 + new YAHOO.widget.Button("i3GEOgraficointerativo1botao1", {
  247 + onclick : {
  248 + fn : i3GEOF.graficointerativo1.obterDados
  249 + }
  250 + });
  251 + if (i3GEOF.graficointerativo1.dados
  252 + && i3GEOF.graficointerativo1.dados != "undefined") {
  253 + i3GEOF.graficointerativo1
  254 + .montaTabelaDados(i3GEOF.graficointerativo1.dados);
  255 + $i("i3GEOgraficointerativo1guia4").onclick.call();
213 256 }
214   - });
215   - if (i3GEOF.graficointerativo1.dados
216   - && i3GEOF.graficointerativo1.dados != "undefined") {
217   - // i3GEOF.graficointerativo1.tipo = "pizza2d";
218   - // var retorno =
219   - // {"attributes":{"id":""},"data":{"dados":["n;x","'4';3839572","'8';81710320","'7';24631314","'2';10967753","'1';24496400","'3';18752482","'5';13574480","'6';216507515"]}};
220   - i3GEOF.graficointerativo1
221   - .montaTabelaDados(i3GEOF.graficointerativo1.dados);
222   - $i("i3GEOgraficointerativo1guia4").onclick.call();
223   - }
224   - i3GEO.guias.mostraGuiaFerramenta("i3GEOgraficointerativo1guia1",
225   - "i3GEOgraficointerativo1guia");
226   - // }
227   - // catch(erro){i3GEO.janela.tempoMsg(erro);}
228   - },
229   - /*
230   - * Function: html
231   - *
232   - * Gera o c&oacute;digo html para apresenta&ccedil;&atilde;o das
233   - * op&ccedil;&otilde;es da ferramenta
234   - *
235   - * Retorno:
236   - *
237   - * String com o c&oacute;digo html
238   - */
239   - html : function() {
240   - var locaplic = i3GEO.configura.locaplic, ins = ''
  257 + i3GEO.guias.mostraGuiaFerramenta("i3GEOgraficointerativo1guia1",
  258 + "i3GEOgraficointerativo1guia");
  259 + },
  260 + /*
  261 + * Function: html
  262 + *
  263 + * Gera o c&oacute;digo html para apresenta&ccedil;&atilde;o das
  264 + * op&ccedil;&otilde;es da ferramenta
  265 + *
  266 + * Retorno:
  267 + *
  268 + * String com o c&oacute;digo html
  269 + */
  270 + html : function() {
  271 + var locaplic = i3GEO.configura.locaplic, ins = ''
241 272 + '<div id=i3GEOgraficointerativo1guiasYUI class="yui-navset" style="top:0px;cursor:pointer;left:0px;">'
242 273 + ' <ul class="yui-nav" style="border-width:0pt 0pt 0px;border-color:rgb(240,240,240);border-bottom-color:white;">'
243 274 + ' <li><a href="#ancora"><em><div id="i3GEOgraficointerativo1guia3" style="text-align:center;left:0px;" ><img class="ticPropriedades2" style="height:14px" title="'
... ... @@ -254,9 +285,13 @@ i3GEOF.graficointerativo1 = {
254 285 + ' <li><a href="#ancora"><em><div id="i3GEOgraficointerativo1guia4" style="text-align:center;left:0px;" >'
255 286 + $trad(3, i3GEOF.graficointerativo1.dicionario)
256 287 + '</div></em></a></li>'
257   - + ' <li><a href="#ancora"><em><div id="i3GEOgraficointerativo1guia5" style="text-align:center;left:0px;" >CSV</div></em></a></li>'
  288 + + ' <li><a href="#ancora"><em><div id="i3GEOgraficointerativo1guia5" style="text-align:center;left:0px;" >CSV'
  289 + + '</div></em></a></li>'
  290 + + ' <li><a href="#ancora"><em><div id="i3GEOgraficointerativo1guia6" style="text-align:center;left:0px;" >PNG'
  291 + + '</div></em></a></li>'
258 292 + ' </ul>'
259 293 + '</div><br>'
  294 + //tipos de grafico
260 295 + '<div class=guiaobj id="i3GEOgraficointerativo1guia1obj" style="left:1px;display:none;">'
261 296 + ' <p class=paragrafo >'
262 297 + $trad(4, i3GEOF.graficointerativo1.dicionario)
... ... @@ -305,6 +340,7 @@ i3GEOF.graficointerativo1 = {
305 340 + '</td></tr>'
306 341 + ' </table>'
307 342 + '</div> '
  343 + //obtencao dos dados e parametros
308 344 + '<div class=guiaobj id="i3GEOgraficointerativo1guia2obj" style="left:1px;display:none;top:-5px">'
309 345 + ' <p class=paragrafo >'
310 346 + $trad(12, i3GEOF.graficointerativo1.dicionario)
... ... @@ -313,6 +349,19 @@ i3GEOF.graficointerativo1 = {
313 349 + $trad(13, i3GEOF.graficointerativo1.dicionario)
314 350 + ':</p>'
315 351 + ' <div class=paragrafo id=i3GEOgraficointerativo1ComboTemas ></div>'
  352 + + ' <p class=paragrafo >'
  353 + + $trad(50, i3GEOF.graficointerativo1.dicionario)
  354 + + ':<br>'
  355 + + $inputText("", "", "i3GEOgraficointerativo1Titulo", "", 40,"")
  356 + + ' <p class=paragrafo >'
  357 + + $trad(51, i3GEOF.graficointerativo1.dicionario)
  358 + + ':<br>'
  359 + + $inputText("", "", "i3GEOgraficointerativo1TituloX", "", 40,"")
  360 + + ' <p class=paragrafo >'
  361 + + $trad(52, i3GEOF.graficointerativo1.dicionario)
  362 + + ':<br>'
  363 + + $inputText("", "", "i3GEOgraficointerativo1TituloY", "", 40,"")
  364 +
316 365 + ' <div class=paragrafo id=i3GEOgraficointerativo1ComboXlinha >'
317 366 + ' <p class=paragrafo >'
318 367 + $trad(14, i3GEOF.graficointerativo1.dicionario)
... ... @@ -329,7 +378,7 @@ i3GEOF.graficointerativo1 = {
329 378 + $trad(16, i3GEOF.graficointerativo1.dicionario)
330 379 + ': '
331 380 + $inputText("", "", "i3GEOgraficointerativo1excluir", "", 3,
332   - "")
  381 + "")
333 382 + ' <p class=paragrafo ><input type=checkbox style="cursor:pointer;top:3px;position:relative;" id=i3GEOgraficointerativo1CoresA /> '
334 383 + $trad(17, i3GEOF.graficointerativo1.dicionario)
335 384 + '</p>'
... ... @@ -341,6 +390,7 @@ i3GEOF.graficointerativo1 = {
341 390 + $trad(19, i3GEOF.graficointerativo1.dicionario)
342 391 + '</div>'
343 392 + '</div>'
  393 + //propriedades adicionais
344 394 + '<div class=guiaobj id="i3GEOgraficointerativo1guia3obj" style="left:1px;display:none;top:-5px">'
345 395 + ' <p class=paragrafo ><input style=cursor:pointer type=checkbox id=i3GEOgraficointerativo1xInclinado checked /> '
346 396 + $trad(20, i3GEOF.graficointerativo1.dicionario)
... ... @@ -369,7 +419,6 @@ i3GEOF.graficointerativo1 = {
369 419 + ' <p class=paragrafo ><input style=cursor:pointer type=checkbox id=i3GEOFgraficointerativo1ativaRowsInColumns /> '
370 420 + $trad(49, i3GEOF.graficointerativo1.dicionario)
371 421 + '</p>'
372   -
373 422 + ' <p class=paragrafo ><select onchange="i3GEOF.graficointerativo1.obterDados()" id="i3GEOgraficointerativo1TipoAgregacao" ><option value="soma">'
374 423 + $trad(26, i3GEOF.graficointerativo1.dicionario)
375 424 + '</option><option value="media">'
... ... @@ -379,360 +428,390 @@ i3GEOF.graficointerativo1 = {
379 428 + '</p>'
380 429 + ' <p class=paragrafo ><input style=cursor:pointer;width:50px; value=40 type=text id=i3GEOgraficointerativo1FatorTamanho /> '
381 430 + $trad(29, i3GEOF.graficointerativo1.dicionario)
382   - + '.</p>'
383   - +
384   -
385   - '</div>'
  431 + + '</p>'
  432 + + '</div>'
  433 + //aqui vai o grafico
386 434 + '<div class=guiaobj id="i3GEOgraficointerativo1guia4obj" style="left:1px;display:none;top:-10px">'
387 435 + ' <a href="#" onclick="i3GEOF.graficointerativo1.novaJanela()" >'
388 436 + $trad(30, i3GEOF.graficointerativo1.dicionario)
389 437 + '</a>'
390 438 + ' <div id=i3GEOgraficointerativo1guia4objCanvas ></div>'
391 439 + '</div>'
  440 + //csv
392 441 + '<div class=guiaobj id="i3GEOgraficointerativo1guia5obj" style="font-size:10px;left:10px;display:none;top:-0px">'
393 442 + '</div>'
  443 + //png
  444 + + '<div class=guiaobj id="i3GEOgraficointerativo1guia6obj" style="font-size:10px;left:10px;display:none;top:-0px">'
  445 + + ' <form method=post action="'+i3GEO.configura.locaplic+'/pacotes/svg2img.php" id="i3GEOgraficointerativo1PNG" target="_blank" >'
  446 + + ' <input type=hidden name="svg" value="" />'
  447 + + ' </form>'
  448 + + '</div>'
394 449 + '<div id="i3GEOgraficointerativo1Grafico" style="position:relative;top:-5px;display:none"></div>';
395   - return ins;
396   - },
397   - /*
398   - * Function: iniciaJanelaFlutuante
399   - *
400   - * Cria a janela flutuante para controle da ferramenta.
401   - *
402   - * Parametro
403   - *
404   - * dados {JSON} - dados para o gr&aacute;fico
405   - */
406   - iniciaJanelaFlutuante : function(dados) {
407   - if (dados) {
408   - i3GEOF.graficointerativo1.dados = dados;
409   - }
410   - var minimiza, cabecalho, janela, divid, temp, titulo;
411   - // cria a janela flutuante
412   - cabecalho = function() {
413   - i3GEOF.graficointerativo1.ativaFoco();
414   - };
415   - minimiza = function() {
416   - i3GEO.janela.minimiza("i3GEOF.graficointerativo1");
417   - };
418   - titulo = "&nbsp;&nbsp;&nbsp;"
  450 + return ins;
  451 + },
  452 + /*
  453 + * Function: iniciaJanelaFlutuante
  454 + *
  455 + * Cria a janela flutuante para controle da ferramenta.
  456 + *
  457 + * Parametro
  458 + *
  459 + * dados {JSON} - dados para o gr&aacute;fico
  460 + */
  461 + iniciaJanelaFlutuante : function(dados) {
  462 + if (dados) {
  463 + i3GEOF.graficointerativo1.dados = dados;
  464 + }
  465 + var minimiza, cabecalho, janela, divid, temp, titulo;
  466 + // cria a janela flutuante
  467 + cabecalho = function() {
  468 + i3GEOF.graficointerativo1.ativaFoco();
  469 + };
  470 + minimiza = function() {
  471 + i3GEO.janela.minimiza("i3GEOF.graficointerativo1");
  472 + };
  473 + titulo = "&nbsp;&nbsp;&nbsp;"
419 474 + $trad("t37b")
420 475 + " <a class=ajuda_usuario target=_blank href='"
421 476 + i3GEO.configura.locaplic
422 477 + "/ajuda_usuario.php?idcategoria=3&idajuda=84' >&nbsp;&nbsp;&nbsp;</a>";
423   - janela = i3GEO.janela.cria("380px", "310px", "", "", "", titulo,
424   - "i3GEOF.graficointerativo1", false, "hd", cabecalho, minimiza);
425   - divid = janela[2].id;
426   - i3GEOF.graficointerativo1.aguarde = $i("i3GEOF.graficointerativo1_imagemCabecalho").style;
427   - $i("i3GEOF.graficointerativo1_corpo").style.backgroundColor = "white";
428   - $i("i3GEOF.graficointerativo1_corpo").style.overflow = "auto";
429   - i3GEOF.graficointerativo1.inicia(divid);
430   - if (i3GEO.Interface) {
431   - temp = function() {
432   - if (i3GEO.Interface.ATUAL !== "googlemaps"
  478 + janela = i3GEO.janela.cria("480px", "450px", "", "", "", titulo,
  479 + "i3GEOF.graficointerativo1", false, "hd", cabecalho, minimiza);
  480 + divid = janela[2].id;
  481 + i3GEOF.graficointerativo1.aguarde = $i("i3GEOF.graficointerativo1_imagemCabecalho").style;
  482 + $i("i3GEOF.graficointerativo1_corpo").style.backgroundColor = "white";
  483 + $i("i3GEOF.graficointerativo1_corpo").style.overflow = "auto";
  484 + i3GEOF.graficointerativo1.inicia(divid);
  485 + if (i3GEO.Interface) {
  486 + temp = function() {
  487 + if (i3GEO.Interface.ATUAL !== "googlemaps"
433 488 && i3GEO.Interface.ATUAL !== "googleearth") {
434   - i3GEO.eventos.NAVEGAMAPA
435   - .remove("i3GEOF.graficointerativo1.obterDados()");
436   - }
437   - if (i3GEO.Interface.ATUAL == "googlemaps") {
438   - google.maps.event.removeListener(graficointerativo1Dragend);
439   - google.maps.event.removeListener(graficointerativo1Zoomend);
440   - }
441   - if (i3GEO.Interface.ATUAL === "googleearth") {
442   - google.earth.removeEventListener(graficointerativo1Dragend);
443   - }
  489 + i3GEO.eventos.NAVEGAMAPA
  490 + .remove("i3GEOF.graficointerativo1.obterDados()");
  491 + }
  492 + if (i3GEO.Interface.ATUAL == "googlemaps") {
  493 + google.maps.event.removeListener(graficointerativo1Dragend);
  494 + google.maps.event.removeListener(graficointerativo1Zoomend);
  495 + }
  496 + if (i3GEO.Interface.ATUAL === "googleearth") {
  497 + google.earth.removeEventListener(graficointerativo1Dragend);
  498 + }
  499 + if (i3GEO.eventos.ATUALIZAARVORECAMADAS.toString().search(
  500 + "i3GEOF.graficointerativo1.comboTemas()") > 0) {
  501 + i3GEO.eventos.ATUALIZAARVORECAMADAS
  502 + .remove("i3GEOF.graficointerativo1.comboTemas()");
  503 + }
  504 + };
  505 + YAHOO.util.Event.addListener(janela[0].close, "click", temp);
444 506 if (i3GEO.eventos.ATUALIZAARVORECAMADAS.toString().search(
445   - "i3GEOF.graficointerativo1.comboTemas()") > 0) {
  507 + "i3GEOF.graficointerativo1.comboTemas()") < 0) {
446 508 i3GEO.eventos.ATUALIZAARVORECAMADAS
447   - .remove("i3GEOF.graficointerativo1.comboTemas()");
  509 + .push("i3GEOF.graficointerativo1.comboTemas()");
448 510 }
449   - };
450   - YAHOO.util.Event.addListener(janela[0].close, "click", temp);
451   - if (i3GEO.eventos.ATUALIZAARVORECAMADAS.toString().search(
452   - "i3GEOF.graficointerativo1.comboTemas()") < 0) {
453   - i3GEO.eventos.ATUALIZAARVORECAMADAS
454   - .push("i3GEOF.graficointerativo1.comboTemas()");
455 511 }
456   - }
457   - },
458   - /*
459   - * Function: ativaFoco
460   - *
461   - * Refaz a interface da ferramenta quando a janela flutuante tem seu foco
462   - * ativado
463   - */
464   - ativaFoco : function() {
465   - if (i3GEO.Interface) {
466   - i3GEO.barraDeBotoes.ativaIcone("graficointerativo1");
467   - }
468   - var i = $i("i3GEOF.graficointerativo1_c").style;
469   - i3GEO.janela.ULTIMOZINDEX++;
470   - i.zIndex = i3GEO.janela.ULTIMOZINDEX;
471   - },
472   - novaJanela : function() {
473   - var janela = "", divid, g = $i("i3GEOgraficointerativo1guia4objCanvas"), v = g
474   - .cloneNode(true), cabecalho = function() {
475   - }, id = YAHOO.util.Dom.generateId(), minimiza = function() {
476   - i3GEO.janela.minimiza(id);
477   - }, titulo = "&nbsp;&nbsp;&nbsp;" + i3GEOF.graficointerativo1.titulo;
478   - janela = i3GEO.janela.cria("380px", "280px", "", "", "", titulo, id,
479   - false, "hd", cabecalho, minimiza);
480   - divid = janela[2].id;
481   - $i(divid).style.marginTop = "0px";
482   - v.id = id + "ngrafico";
483   - v.style.marginTop = "0px";
484   - $i(divid).appendChild(v);
485   - },
486   - /*
487   - * Function: comboTemas
488   - *
489   - * Monta o combo para escolha do tema que ser&aacute; utilizado no
490   - * gr&aacute;fico
491   - */
492   - comboTemas : function() {
493   - if (!i3GEO.Interface) {
494   - return;
495   - }
496   - i3GEO.util
497   - .comboTemas(
498   - "i3GEOgraficointerativo1ComboTemasId",
499   - function(retorno) {
500   - $i("i3GEOgraficointerativo1ComboTemas").innerHTML = retorno.dados;
501   - $i("i3GEOgraficointerativo1ComboTemas").style.display = "block";
502   - if ($i("i3GEOgraficointerativo1ComboTemasId")) {
503   - $i("i3GEOgraficointerativo1ComboTemasId").onchange = function() {
504   - i3GEO.mapa
505   - .ativaTema($i("i3GEOgraficointerativo1ComboTemasId").value);
506   - i3GEOF.graficointerativo1.comboItensSel();
507   - };
508   - }
509   - if (i3GEO.temaAtivo !== "") {
510   - $i("i3GEOgraficointerativo1ComboTemasId").value = i3GEO.temaAtivo;
511   - $i("i3GEOgraficointerativo1ComboTemasId").onchange
512   - .call();
513   - }
514   - }, "i3GEOgraficointerativo1ComboTemas", "", false,
515   - "ligados", "font-size:12px;width:350px");
516   - },
517   - /*
518   - * Function: ativaTipo
519   - *
520   - * Define a vari&aacute;vel com o tipo de gr&aacute;fico e mostra a guia 2
521   - */
522   - ativaTipo : function(obj) {
523   - i3GEOF.graficointerativo1.tipo = obj.value;
524   - if ($i("i3GEOgraficointerativo1Grafico").innerHTML === ""
  512 + },
  513 + /*
  514 + * Function: ativaFoco
  515 + *
  516 + * Refaz a interface da ferramenta quando a janela flutuante tem seu foco
  517 + * ativado
  518 + */
  519 + ativaFoco : function() {
  520 + if (i3GEO.Interface) {
  521 + i3GEO.barraDeBotoes.ativaIcone("graficointerativo1");
  522 + }
  523 + var i = $i("i3GEOF.graficointerativo1_c").style;
  524 + i3GEO.janela.ULTIMOZINDEX++;
  525 + i.zIndex = i3GEO.janela.ULTIMOZINDEX;
  526 + },
  527 + novaJanela : function() {
  528 + var janela = "", divid, g = $i("i3GEOgraficointerativo1guia4objCanvas"), v = g
  529 + .cloneNode(true), cabecalho = function() {
  530 + }, id = YAHOO.util.Dom.generateId(), minimiza = function() {
  531 + i3GEO.janela.minimiza(id);
  532 + }, titulo = "&nbsp;&nbsp;&nbsp;" + i3GEOF.graficointerativo1.titulo;
  533 + janela = i3GEO.janela.cria("380px", "280px", "", "", "", titulo, id,
  534 + false, "hd", cabecalho, minimiza);
  535 + divid = janela[2].id;
  536 + $i(divid).style.marginTop = "0px";
  537 + v.id = id + "ngrafico";
  538 + v.style.marginTop = "0px";
  539 + $i(divid).appendChild(v);
  540 + },
  541 + /*
  542 + * Function: comboTemas
  543 + *
  544 + * Monta o combo para escolha do tema que ser&aacute; utilizado no
  545 + * gr&aacute;fico
  546 + */
  547 + comboTemas : function() {
  548 + if (!i3GEO.Interface) {
  549 + return;
  550 + }
  551 + i3GEO.util
  552 + .comboTemas(
  553 + "i3GEOgraficointerativo1ComboTemasId",
  554 + function(retorno) {
  555 + $i("i3GEOgraficointerativo1ComboTemas").innerHTML = retorno.dados;
  556 + $i("i3GEOgraficointerativo1ComboTemas").style.display = "block";
  557 + if ($i("i3GEOgraficointerativo1ComboTemasId")) {
  558 + $i("i3GEOgraficointerativo1ComboTemasId").onchange = function() {
  559 + i3GEO.mapa
  560 + .ativaTema($i("i3GEOgraficointerativo1ComboTemasId").value);
  561 + i3GEOF.graficointerativo1.comboItensSel();
  562 + };
  563 + }
  564 + if (i3GEO.temaAtivo !== "") {
  565 + $i("i3GEOgraficointerativo1ComboTemasId").value = i3GEO.temaAtivo;
  566 + $i("i3GEOgraficointerativo1ComboTemasId").onchange
  567 + .call();
  568 + }
  569 + }, "i3GEOgraficointerativo1ComboTemas", "", false,
  570 + "ligados", "font-size:12px;width:350px");
  571 + },
  572 + /*
  573 + * Function: ativaTipo
  574 + *
  575 + * Define a vari&aacute;vel com o tipo de gr&aacute;fico e mostra a guia 2
  576 + */
  577 + ativaTipo : function(obj) {
  578 + i3GEOF.graficointerativo1.tipo = obj.value;
  579 + if ($i("i3GEOgraficointerativo1Grafico").innerHTML === ""
525 580 || $i("i3GEOgraficointerativo1tabeladados").innerHTML == "") {
526   - $i("i3GEOgraficointerativo1guia2").onclick.call();
527   - } else {
528   - $i("i3GEOgraficointerativo1guia4").onclick.call();
529   - }
530   - },
531   - /*
532   - * Function: configuraDados
533   - *
534   - * Configura o formul&aacute;rio para obten&ccedil;&atilde;o dos dados para
535   - * cada tipo de gr&aacute;fico
536   - */
537   - configuraDados : function() {
538   - var ativa = function(comboxlinha, comboylinha, ajudapizza) {
539   - try {
540   - $i("i3GEOgraficointerativo1ComboXlinha").style.display = comboxlinha;
541   - $i("i3GEOgraficointerativo1ComboYlinha").style.display = comboylinha;
542   - $i("i3GEOgraficointerativo1AjudaPizza").style.display = ajudapizza;
543   - } catch (e) {
  581 + $i("i3GEOgraficointerativo1guia2").onclick.call();
  582 + } else {
  583 + $i("i3GEOgraficointerativo1guia4").onclick.call();
544 584 }
545   - };
546   - if (i3GEOF.graficointerativo1.tipo === "") {
547   - i3GEO.janela.tempoMsg($trad(31,
548   - i3GEOF.graficointerativo1.dicionario));
549   - i3GEO.guias.mostraGuiaFerramenta("i3GEOgraficointerativo1guia1",
550   - "i3GEOgraficointerativo1guia");
551   - return;
552   - }
553   - if (i3GEOF.graficointerativo1.tipo === "pizza2d") {
554   - ativa.call("block", "block", "block");
555   - }
556   - },
557   - /*
558   - * Function: comboItensSel
559   - *
560   - * Cria um combo para selecionar os itens do tema escolhido
561   - *
562   - * Veja:
563   - *
564   - * <i3GEO.util.comboItens>
565   - */
566   - comboItensSel : function() {
567   - var tema = $i("i3GEOgraficointerativo1ComboTemasId").value;
568   - i3GEO.util
569   - .comboItens(
570   - "i3GEOgraficointerativo1ComboXid",
571   - tema,
572   - function(retorno) {
573   - if (retorno.tipo === "erro") {
574   - $i("i3GEOgraficointerativo1ComboX").innerHTML = "<br><br><span style='color:red'>"
575   - + $trad(
576   - 32,
577   - i3GEOF.graficointerativo1.dicionario)
  585 + },
  586 + /*
  587 + * Function: configuraDados
  588 + *
  589 + * Configura o formul&aacute;rio para obten&ccedil;&atilde;o dos dados para
  590 + * cada tipo de gr&aacute;fico
  591 + */
  592 + configuraDados : function() {
  593 + var ativa = function(comboxlinha, comboylinha, ajudapizza) {
  594 + try {
  595 + $i("i3GEOgraficointerativo1ComboXlinha").style.display = comboxlinha;
  596 + $i("i3GEOgraficointerativo1ComboYlinha").style.display = comboylinha;
  597 + $i("i3GEOgraficointerativo1AjudaPizza").style.display = ajudapizza;
  598 + } catch (e) {
  599 + }
  600 + };
  601 + if (i3GEOF.graficointerativo1.tipo === "") {
  602 + i3GEO.janela.tempoMsg($trad(31,
  603 + i3GEOF.graficointerativo1.dicionario));
  604 + i3GEO.guias.mostraGuiaFerramenta("i3GEOgraficointerativo1guia1",
  605 + "i3GEOgraficointerativo1guia");
  606 + return;
  607 + }
  608 + if (i3GEOF.graficointerativo1.tipo === "pizza2d") {
  609 + ativa.call("block", "block", "block");
  610 + }
  611 + },
  612 + /*
  613 + * Function: comboItensSel
  614 + *
  615 + * Cria um combo para selecionar os itens do tema escolhido
  616 + *
  617 + * Veja:
  618 + *
  619 + * <i3GEO.util.comboItens>
  620 + */
  621 + comboItensSel : function() {
  622 + var tema = $i("i3GEOgraficointerativo1ComboTemasId").value;
  623 + i3GEO.util
  624 + .comboItens(
  625 + "i3GEOgraficointerativo1ComboXid",
  626 + tema,
  627 + function(retorno) {
  628 + if (retorno.tipo === "erro") {
  629 + $i("i3GEOgraficointerativo1ComboX").innerHTML = "<br><br><span style='color:red'>"
  630 + + $trad(
  631 + 32,
  632 + i3GEOF.graficointerativo1.dicionario)
578 633 + "</span><br><br>";
579   - $i("i3GEOgraficointerativo1ComboY").innerHTML = "<br><br><span style='color:red'>"
580   - + $trad(
581   - 32,
582   - i3GEOF.graficointerativo1.dicionario)
  634 + $i("i3GEOgraficointerativo1ComboY").innerHTML = "<br><br><span style='color:red'>"
  635 + + $trad(
  636 + 32,
  637 + i3GEOF.graficointerativo1.dicionario)
583 638 + "</span><br><br>";
584   - } else {
585   - $i("i3GEOgraficointerativo1ComboY").innerHTML = "<div>"
586   - + retorno.dados
587   - + "&nbsp;<input title='"
588   - + $trad(
589   - 33,
590   - i3GEOF.graficointerativo1.dicionario)
591   - + "' class=digitar type=text size=20 id=i3GEOgraficointerativo1ComboYidTitulo value='' /></div>";
592   - $i("i3GEOgraficointerativo1ComboXid").id = "i3GEOgraficointerativo1ComboYid";
593   - $i("i3GEOgraficointerativo1ComboX").innerHTML = "<div>"
594   - + retorno.dados
595   - + "&nbsp;<input title='"
596   - + $trad(
597   - 33,
598   - i3GEOF.graficointerativo1.dicionario)
599   - + "' class=digitar type=text size=20 id=i3GEOgraficointerativo1ComboXidTitulo value='' /></div>";
600   - $i("i3GEOgraficointerativo1ComboXid").style.width = "160px";
601   - $i("i3GEOgraficointerativo1ComboYid").style.width = "160px";
  639 + } else {
  640 + $i("i3GEOgraficointerativo1ComboY").innerHTML = "<div>"
  641 + + retorno.dados
  642 + + "&nbsp;<input title='"
  643 + + $trad(33,i3GEOF.graficointerativo1.dicionario)
  644 + + "' class=digitar type=text size=20 id=i3GEOgraficointerativo1ComboYidTitulo value='' />"
  645 + + "&nbsp;<input id='i3GEOgraficointerativo1ComboYidcor' class=digitar type=text size=8 value='' />"
  646 + + "<img alt='aquarela.gif' style=position:relative;top:3px;left:3px;cursor:pointer src='"
  647 + + i3GEO.configura.locaplic
  648 + + "/imagens/aquarela.gif' onclick='i3GEOF.graficointerativo1.corj(\"i3GEOgraficointerativo1ComboYidcor\")' /></div>";
602 649  
603   - $i("i3GEOgraficointerativo1ComboXid").onchange = function() {
604   - $i(this.id + "Titulo").value = this.options[this.selectedIndex].label;
605   - };
606   - var adicionaFilho = function() {
607   - var no = document.createElement("div"), tit = $i(this.id
608   - + "Titulo"), novoselect;
609   - if (tit) {
610   - tit.value = this.options[this.selectedIndex].label;
611   - }
612   - no.innerHTML = retorno.dados + "<br>";
613   - novoselect = no.getElementsByTagName("select")[0];
614   - novoselect.id = "";
615   - novoselect.onchange = adicionaFilho;
616   - novoselect.style.width = "160px";
617   - $i("i3GEOgraficointerativo1ComboY").appendChild(no);
618   - };
619   - $i("i3GEOgraficointerativo1ComboYid").onchange = adicionaFilho;
620   - }
621   - }, "i3GEOgraficointerativo1ComboX", "");
622   - },
623   - /*
624   - * Function: obterDados
625   - *
626   - * Obt&eacute;m os dados que ser&atilde;o utilizados no gr&aacute;fico
627   - *
628   - * Veja:
629   - *
630   - * <GRAFICOSELECAO>
631   - */
632   - obterDados : function() {
633   - if (!i3GEO.Interface) {
634   - return;
635   - }
636   - if (i3GEOF.graficointerativo1.aguarde.visibility === "visible") {
637   - return;
638   - }
639   - var tema = $i("i3GEOgraficointerativo1ComboTemasId").value, excluir = $i("i3GEOgraficointerativo1excluir").value, cp = new cpaint(), tipo = $i("i3GEOgraficointerativo1TipoAgregacao").value, ordenax = "sim", monta, p, x, y, i, n, temp;
  650 + $i("i3GEOgraficointerativo1ComboXid").id = "i3GEOgraficointerativo1ComboYid";
  651 + $i("i3GEOgraficointerativo1ComboX").innerHTML = "<div>"
  652 + + retorno.dados
  653 + + "&nbsp;<input title='"
  654 + + $trad(33, i3GEOF.graficointerativo1.dicionario)
  655 + + "' class=digitar type=text size=20 id=i3GEOgraficointerativo1ComboXidTitulo value='' /></div>";
  656 + $i("i3GEOgraficointerativo1ComboXid").style.width = "160px";
  657 + $i("i3GEOgraficointerativo1ComboYid").style.width = "160px";
  658 +
  659 + var adicionaFilho = function() {
  660 + var no = document.createElement("div"),
  661 + id = "CorG"+parseInt(Math.random()*100000,10),
  662 + novoselect;
  663 + no.innerHTML = retorno.dados
  664 + + "&nbsp;<input title='"
  665 + + $trad(33, i3GEOF.graficointerativo1.dicionario)
  666 + + "' class=digitar type=text size=20 value='' />"
  667 + + "&nbsp;<input id='"
  668 + + id
  669 + + "' class=digitar type=text size=8 value='' />"
  670 + + "<img alt='aquarela.gif' style=position:relative;top:3px;left:3px;cursor:pointer src='"
  671 + + i3GEO.configura.locaplic
  672 + + "/imagens/aquarela.gif' onclick='i3GEOF.graficointerativo1.corj(\""
  673 + + id
  674 + + "\")' /><br>";
  675 + novoselect = no.getElementsByTagName("select")[0];
  676 + novoselect.id = "";
  677 + novoselect.onchange = adicionaFilho;
  678 + novoselect.style.width = "160px";
  679 + $i("i3GEOgraficointerativo1ComboY").appendChild(no);
  680 + };
  681 + $i("i3GEOgraficointerativo1ComboYid").onchange = adicionaFilho;
  682 + }
  683 + }, "i3GEOgraficointerativo1ComboX", "");
  684 + },
  685 + /*
  686 + * Function: obterDados
  687 + *
  688 + * Obt&eacute;m os dados que ser&atilde;o utilizados no gr&aacute;fico
  689 + *
  690 + * Veja:
  691 + *
  692 + * <GRAFICOSELECAO>
  693 + */
  694 + obterDados : function() {
  695 + if (!i3GEO.Interface) {
  696 + return;
  697 + }
  698 + if (i3GEOF.graficointerativo1.aguarde.visibility === "visible") {
  699 + return;
  700 + }
  701 + var tema = $i("i3GEOgraficointerativo1ComboTemasId").value, excluir = $i("i3GEOgraficointerativo1excluir").value, cp = new cpaint(), tipo = $i("i3GEOgraficointerativo1TipoAgregacao").value, ordenax = "sim", monta, p, x, y, i, n, temp;
640 702  
641   - // pega os itens
642   - temp = $i("i3GEOgraficointerativo1ComboX");
643   - x = temp.getElementsByTagName("select")[0].value;
644   - temp = $i("i3GEOgraficointerativo1ComboY");
645   - temp = temp.getElementsByTagName("select");
646   - n = temp.length;
647   - if (n === 1) {
648   - y = temp[0].value;
649   - } else {
650   - y = [];
651   - for (i = 0; i < n; i++) {
652   - if (temp[i].value != "") {
653   - y.push(temp[i].value);
  703 + // pega os itens
  704 + temp = $i("i3GEOgraficointerativo1ComboX");
  705 + x = temp.getElementsByTagName("select")[0].value;
  706 + temp = $i("i3GEOgraficointerativo1ComboY");
  707 + temp = temp.getElementsByTagName("select");
  708 + n = temp.length;
  709 + if (n === 1) {
  710 + y = temp[0].value;
  711 + } else {
  712 + y = [];
  713 + for (i = 0; i < n; i++) {
  714 + if (temp[i].value != "") {
  715 + y.push(temp[i].value);
  716 + }
654 717 }
  718 + y = y.join(",");
655 719 }
656   - y = y.join(",");
657   - }
658   - p = i3GEO.configura.locaplic
659   - + "/ferramentas/graficointerativo1/exec.php?g_sid="
660   - + i3GEO.configura.sid + "&funcao=graficoSelecao&tema=" + tema
661   - + "&itemclasses=" + x + "&itemvalores=" + y + "&exclui="
662   - + excluir + "&ext=" + i3GEO.parametros.mapexten;
  720 + p = i3GEO.configura.locaplic
  721 + + "/ferramentas/graficointerativo1/exec.php?g_sid="
  722 + + i3GEO.configura.sid + "&funcao=graficoSelecao&tema=" + tema
  723 + + "&itemclasses=" + x + "&itemvalores=" + y + "&exclui="
  724 + + excluir + "&ext=" + i3GEO.parametros.mapexten;
663 725  
664   - if ($i("i3GEOgraficointerativo1DadosPuros").checked) {
665   - tipo = "nenhum";
666   - } else {
667   - if (x === y) {
668   - tipo = "conta";
  726 + if ($i("i3GEOgraficointerativo1DadosPuros").checked) {
  727 + tipo = "nenhum";
  728 + } else {
  729 + if (x === y) {
  730 + tipo = "conta";
  731 + }
  732 + }
  733 + if (!$i("i3GEOgraficointerativo1OrdenaX").checked) {
  734 + ordenax = "nao";
669 735 }
670   - }
671   - if (!$i("i3GEOgraficointerativo1OrdenaX").checked) {
672   - ordenax = "nao";
673   - }
674 736  
675   - if (tema === "") {
676   - i3GEO.janela.tempoMsg($trad(34,
677   - i3GEOF.graficointerativo1.dicionario));
678   - return;
679   - }
680   - if (x === "") {
681   - i3GEO.janela.tempoMsg($trad(35,
682   - i3GEOF.graficointerativo1.dicionario));
683   - return;
684   - }
685   - if (y === "") {
686   - i3GEO.janela.tempoMsg($trad(36,
687   - i3GEOF.graficointerativo1.dicionario));
688   - return;
689   - }
690   - monta = function(retorno) {
691   - i3GEOF.graficointerativo1.aguarde.visibility = "hidden";
692   - i3GEOF.graficointerativo1.montaTabelaDados(retorno);
693   - $i("i3GEOgraficointerativo1guia4").onclick.call();
694   - // verifica para nao ficar mostrando a janela toda vez que redesenha
695   - // o mapa
696   - if ($i("i3GEOFgraficointerativo1ativaNavegacao").checked == false) {
697   - i3GEO.janela.tempoMsg($trad(37,
  737 + if (tema === "") {
  738 + i3GEO.janela.tempoMsg($trad(34,
698 739 i3GEOF.graficointerativo1.dicionario));
  740 + return;
699 741 }
700   - };
701   - i3GEOF.graficointerativo1.aguarde.visibility = "visible";
702   - cp.set_response_type("JSON");
703   - cp.call(p + "&tipo=" + tipo + "&ordenax=" + ordenax, "graficoSelecao",
704   - monta);
705   - },
706   - /*
707   - * Pega os nomes das colunas
708   - */
709   - nomesColunas: function(){
710   - //pega os nomes das clunas
711   - var i,n,
  742 + if (x === "") {
  743 + i3GEO.janela.tempoMsg($trad(35,
  744 + i3GEOF.graficointerativo1.dicionario));
  745 + return;
  746 + }
  747 + if (y === "") {
  748 + i3GEO.janela.tempoMsg($trad(36,
  749 + i3GEOF.graficointerativo1.dicionario));
  750 + return;
  751 + }
  752 + monta = function(retorno) {
  753 + i3GEOF.graficointerativo1.aguarde.visibility = "hidden";
  754 + i3GEOF.graficointerativo1.montaTabelaDados(retorno);
  755 + $i("i3GEOgraficointerativo1guia4").onclick.call();
  756 + // verifica para nao ficar mostrando a janela toda vez que redesenha
  757 + // o mapa
  758 + if ($i("i3GEOFgraficointerativo1ativaNavegacao").checked == false) {
  759 + i3GEO.janela.tempoMsg($trad(37,
  760 + i3GEOF.graficointerativo1.dicionario));
  761 + }
  762 + };
  763 + i3GEOF.graficointerativo1.aguarde.visibility = "visible";
  764 + cp.set_response_type("JSON");
  765 + cp.call(p + "&tipo=" + tipo + "&ordenax=" + ordenax, "graficoSelecao",
  766 + monta);
  767 + },
  768 + /*
  769 + * Pega os nomes das colunas
  770 + */
  771 + nomesColunas: function(){
  772 + //pega os nomes das clunas
  773 + var i,n,p,
712 774 temp = $i("i3GEOgraficointerativo1ComboX"),
713   - colunas = [];
714   - colunas.push(temp.getElementsByTagName("select")[0].value);
715   - temp = $i("i3GEOgraficointerativo1ComboY");
716   - temp = temp.getElementsByTagName("select");
717   - n = temp.length;
718   - for(i=0;i<n;i++){
719   - if(temp[i].value != ""){
720   - colunas.push(temp[i].value);
  775 + colunas = [],
  776 + cores = [],
  777 + alias = [];
  778 + colunas.push(temp.getElementsByTagName("select")[0].value);
  779 + alias.push(temp.getElementsByTagName("input")[0].value);
  780 + temp = $i("i3GEOgraficointerativo1ComboY");
  781 + temp = temp.getElementsByTagName("select");
  782 + n = temp.length;
  783 + for(i=0;i<n;i++){
  784 + if(temp[i].value != ""){
  785 + colunas.push(temp[i].value);
  786 + //pega o alias
  787 + p = temp[i].parentNode.getElementsByTagName("input");
  788 + if(p[0].value != ""){
  789 + alias.push(p[0].value);
  790 + }
  791 + else{
  792 + alias.push(temp[i].value);
  793 + }
  794 + if(p[1].value != ""){
  795 + cores.push(p[1].value);
  796 + }
  797 + else{
  798 + cores.push("#29C152");
  799 + }
  800 + }
721 801 }
722   - }
723   - return colunas;
724   - },
725   - /*
726   - * Function: montaTabelaDados
727   - *
728   - * Monta a tabela com os dados que ser&atilde;o utilizados no gr&aacute;fico
729   - *
730   - * Parametro:
731   - *
732   - * retorno {JSON} - dados no formato JSON
733   - */
734   - montaTabelaDados : function(retorno) {
735   - var colunas = [],
  802 + return [colunas,alias,cores];
  803 + },
  804 + /*
  805 + * Function: montaTabelaDados
  806 + *
  807 + * Monta a tabela com os dados que ser&atilde;o utilizados no gr&aacute;fico
  808 + *
  809 + * Parametro:
  810 + *
  811 + * retorno {JSON} - dados no formato JSON
  812 + */
  813 + montaTabelaDados : function(retorno) {
  814 + var colunas = [],
736 815 ncolunas,
737 816 dados,
738 817 n,
... ... @@ -742,105 +821,105 @@ i3GEOF.graficointerativo1 = {
742 821 j,
743 822 id,
744 823 cor = "#C11515";
745   - if (!retorno.dados && retorno.data != undefined) {
746   - dados = retorno.data.dados;
747   - } else {
748   - dados = retorno;
749   - }
750   - ins.push("<p class=paragrafo >"
751   - + $trad(38, i3GEOF.graficointerativo1.dicionario)
752   - + "</p><table class=lista4 id=i3GEOgraficointerativo1tabeladados ><tr><td></td>");
753   - //pega os nomes das clunas
754   - colunas = i3GEOF.graficointerativo1.nomesColunas();
755   - ncolunas = colunas.length;
756   - for(i=0;i<ncolunas;i++){
757   - ins.push("<td style=background-color:yellow >&nbsp;<img style=cursor:pointer onclick='i3GEOF.graficointerativo1.ordenaColuna(this,1)' src='"
758   - + i3GEO.configura.locaplic
759   - + "/imagens/ordena1.gif' title='ordena' /> "
760   - + colunas[i]
761   - + "</td>");
762   - }
763   - ins.push("<td style=background-color:yellow >"
764   - + $trad(41, i3GEOF.graficointerativo1.dicionario)
765   - + "</td><td></td></tr>");
766   - n = dados.length;
767   - for (i = 1; i < n; i++) {
768   - v = dados[i].split(";");
769   - // ins += v[0]+" "+v[1];
770   - id = "i3GEOgraficointerativo1Dados" + i; // layer+indice da classe
771   - ins.push("<tr><td>");
772   - ins.push("<img style='cursor:pointer' onclick='i3GEOF.graficointerativo1.excluilinha(this)' src='"
773   - + i3GEO.configura.locaplic
774   - + "/imagens/x.gif' title='"
775   - + $trad(42, i3GEOF.graficointerativo1.dicionario)
776   - + "' /></td>");
777   - ins.push("</td>");
778   - for(j=0;j<ncolunas;j++){
779   - v[j] = v[j].replace("'", "");
780   - v[j] = v[j].replace("'", "");
781   - ins.push("<td>");
782   - ins.push($inputText("", "", id + colunas[j], $trad(43,
783   - i3GEOF.graficointerativo1.dicionario), 20, v[j], colunas[j]));
  824 + if (!retorno.dados && retorno.data != undefined) {
  825 + dados = retorno.data.dados;
  826 + } else {
  827 + dados = retorno;
  828 + }
  829 + ins.push("<p class=paragrafo >"
  830 + + $trad(38, i3GEOF.graficointerativo1.dicionario)
  831 + + "</p><table class=lista4 id=i3GEOgraficointerativo1tabeladados ><tr><td></td>");
  832 + //pega os nomes das clunas
  833 + colunas = i3GEOF.graficointerativo1.nomesColunas()[0];
  834 + ncolunas = colunas.length;
  835 + for(i=0;i<ncolunas;i++){
  836 + ins.push("<td style=background-color:yellow >&nbsp;<img style=cursor:pointer onclick='i3GEOF.graficointerativo1.ordenaColuna(this,1)' src='"
  837 + + i3GEO.configura.locaplic
  838 + + "/imagens/ordena1.gif' title='ordena' /> "
  839 + + colunas[i]
  840 + + "</td>");
  841 + }
  842 + ins.push("<td style=background-color:yellow >"
  843 + + $trad(41, i3GEOF.graficointerativo1.dicionario)
  844 + + "</td><td></td></tr>");
  845 + n = dados.length;
  846 + for (i = 1; i < n; i++) {
  847 + v = dados[i].split(";");
  848 + // ins += v[0]+" "+v[1];
  849 + id = "i3GEOgraficointerativo1Dados" + i; // layer+indice da classe
  850 + ins.push("<tr><td>");
  851 + ins.push("<img style='cursor:pointer' onclick='i3GEOF.graficointerativo1.excluilinha(this)' src='"
  852 + + i3GEO.configura.locaplic
  853 + + "/imagens/x.gif' title='"
  854 + + $trad(42, i3GEOF.graficointerativo1.dicionario)
  855 + + "' /></td>");
784 856 ins.push("</td>");
  857 + for(j=0;j<ncolunas;j++){
  858 + v[j] = v[j].replace("'", "");
  859 + v[j] = v[j].replace("'", "");
  860 + ins.push("<td>");
  861 + ins.push($inputText("", "", id + colunas[j], $trad(43,
  862 + i3GEOF.graficointerativo1.dicionario), 20, v[j], colunas[j]));
  863 + ins.push("</td>");
  864 + }
  865 +
  866 + ins.push("<td>");
  867 + if ($i("i3GEOgraficointerativo1CoresA").checked) {
  868 + cor = i3GEO.util.rgb2hex(i3GEO.util.randomRGB());
  869 + }
  870 + // verifica se no objeto com os dados existe um terceiro valor com
  871 + // as cores
  872 + if (v[ncolunas + 1]) {
  873 + cor = i3GEO.util.rgb2hex(v[ncolunas + 1]);
  874 + }
  875 + ins.push($inputText("", "", id + "_cor", "", 12, cor, $trad(41,
  876 + i3GEOF.graficointerativo1.dicionario)));
  877 + ins.push("</td><td>");
  878 + ins.push("<img alt='aquarela.gif' style=cursor:pointer src='"
  879 + + i3GEO.configura.locaplic
  880 + + "/imagens/aquarela.gif' onclick='i3GEOF.graficointerativo1.corj(\""
  881 + + id + "_cor\")' />");
  882 + ins.push("</td></tr>");
785 883 }
  884 + ins.push("</table><br>");
  885 + $i("i3GEOgraficointerativo1Dados").innerHTML = ins.join("");
  886 + },
  887 + /*
  888 + * Function: tabela2csv
  889 + *
  890 + * Obt&eacute;m os dados da tabela em CSV
  891 + */
  892 + tabela2csv : function() {
  893 + var colunas = i3GEOF.graficointerativo1.nomesColunas(),
  894 + ncolunas = colunas[0].length,
  895 + inputs = $i("i3GEOgraficointerativo1Dados").getElementsByTagName("input"),
  896 + ninputs = inputs.length,
  897 + i,j,
  898 + temp,
  899 + csv = [];
786 900  
787   - ins.push("<td>");
788   - if ($i("i3GEOgraficointerativo1CoresA").checked) {
789   - cor = i3GEO.util.rgb2hex(i3GEO.util.randomRGB());
  901 + csv.push(colunas[0].join(";"));
  902 + for (i = 0; i < ninputs; i = (i + 1 + ncolunas)){
  903 + temp = [];
  904 + for(j=0;j<ncolunas;j++){
  905 + temp.push(inputs[i + j].value);
  906 + }
  907 + csv.push(temp.join(";"));
790 908 }
791   - // verifica se no objeto com os dados existe um terceiro valor com
792   - // as cores
793   - if (v[ncolunas + 1]) {
794   - cor = i3GEO.util.rgb2hex(v[ncolunas + 1]);
  909 + return csv;
  910 + },
  911 + /*
  912 + * Function: tabela2dados
  913 + *
  914 + * Obt&eacute;m os dados da tabela para compor o gr&aacute;fico
  915 + */
  916 + tabela2dados : function() {
  917 + if (i3GEOF.graficointerativo1.aguarde.visibility === "visible") {
  918 + return;
795 919 }
796   - ins.push($inputText("", "", id + "_cor", "", 12, cor, $trad(41,
797   - i3GEOF.graficointerativo1.dicionario)));
798   - ins.push("</td><td>");
799   - ins.push("<img alt='aquarela.gif' style=cursor:pointer src='"
800   - + i3GEO.configura.locaplic
801   - + "/imagens/aquarela.gif' onclick='i3GEOF.graficointerativo1.corj(\""
802   - + id + "_cor\")' />");
803   - ins.push("</td></tr>");
804   - }
805   - ins.push("</table><br>");
806   - $i("i3GEOgraficointerativo1Dados").innerHTML = ins.join("");
807   - },
808   - /*
809   - * Function: tabela2csv
810   - *
811   - * Obt&eacute;m os dados da tabela em CSV
812   - */
813   - tabela2csv : function() {
814   - var inputs = $i("i3GEOgraficointerativo1Dados").getElementsByTagName("input"),
815   - ninputs = inputs.length,
816   - i,
817   - legendaX = "",
818   - legendaY = "",
819   - csv = [];
820   - if ($i("i3GEOgraficointerativo1ComboXid")) {
821   - legendaX = $i("i3GEOgraficointerativo1ComboXid").value;
822   - }
823   - if ($i("i3GEOgraficointerativo1ComboYid")) {
824   - legendaY = $i("i3GEOgraficointerativo1ComboYid").value;
825   - }
826   - csv.push(legendaX + ";" + legendaY);
827   - for (i = 0; i < ninputs; i = i + 3) {
828   - csv.push(inputs[i].value + ";" + inputs[i + 1].value * 1);
829   - }
830   - return csv;
831   - },
832   - /*
833   - * Function: tabela2dados
834   - *
835   - * Obt&eacute;m os dados da tabela para compor o gr&aacute;fico
836   - */
837   - tabela2dados : function() {
838   - if (i3GEOF.graficointerativo1.aguarde.visibility === "visible") {
839   - return;
840   - }
841   - i3GEOF.graficointerativo1.aguarde.visibility = "visible";
842   - var colunas = i3GEOF.graficointerativo1.nomesColunas(),
843   - ncolunas = colunas.length,
  920 + i3GEOF.graficointerativo1.aguarde.visibility = "visible";
  921 + var colunas = i3GEOF.graficointerativo1.nomesColunas(),
  922 + ncolunas = colunas[0].length,
844 923 temp = 0,
845 924 ultimo = 0,
846 925 inputs = $i("i3GEOgraficointerativo1Dados").getElementsByTagName("input"),
... ... @@ -849,465 +928,479 @@ i3GEOF.graficointerativo1 = {
849 928 metadados = [],
850 929 i,j,
851 930 acumulado = [], acum, cores = [], par = [], total = 0, menor = inputs[1].value * 1, maior = 0, legendaX = "", legendaY = "", dados = {}, xInclinado = $i("i3GEOgraficointerativo1xInclinado").checked;
852   - if ($i("i3GEOgraficointerativo1ComboTemasId")) {
853   - titulo = $i("i3GEOgraficointerativo1ComboTemasId").options[$i("i3GEOgraficointerativo1ComboTemasId").options.selectedIndex].text;
854   - }
855   - if (i3GEOF.graficointerativo1.titulo != "") {
856   - titulo = i3GEOF.graficointerativo1.titulo;
857   - }
858   - if ($i("i3GEOgraficointerativo1ComboXid")) {
859   - legendaX = $i("i3GEOgraficointerativo1ComboXidTitulo").value;
860   - }
861   - if ($i("i3GEOgraficointerativo1ComboYid")) {
862   - legendaY = $i("i3GEOgraficointerativo1ComboYidTitulo").value;
863   - }
864   - if(ncolunas === 2){
865   - for (i = 0; i < ninputs; i = i + 3) {
866   - temp = inputs[i + 1].value * 1;
867   - total += temp;
868   - cores.push(inputs[i + 2].value);
  931 + if ($i("i3GEOgraficointerativo1ComboTemasId")) {
  932 + titulo = $i("i3GEOgraficointerativo1ComboTemasId").options[$i("i3GEOgraficointerativo1ComboTemasId").options.selectedIndex].text;
  933 + }
  934 + if (i3GEOF.graficointerativo1.titulo != "") {
  935 + titulo = i3GEOF.graficointerativo1.titulo;
869 936 }
870   - for (i = 0; i < ninputs; i = (i + 1 + ncolunas)) {
871   - temp = inputs[i + 1].value * 1;
872   - acum = ultimo + temp;
873   - acumulado.push(acum);
874   - ultimo = ultimo + temp;
875   - if (temp > maior) {
876   - maior = temp;
  937 + if ($i("i3GEOgraficointerativo1ComboXid")) {
  938 + legendaX = $i("i3GEOgraficointerativo1ComboXidTitulo").value;
  939 + }
  940 + if ($i("i3GEOgraficointerativo1ComboYid")) {
  941 + legendaY = $i("i3GEOgraficointerativo1ComboYidTitulo").value;
  942 + }
  943 + if(ncolunas === 2){
  944 + for (i = 0; i < ninputs; i = i + 3) {
  945 + temp = inputs[i + 1].value * 1;
  946 + total += temp;
  947 + cores.push(inputs[i + 2].value);
877 948 }
878   - if (temp < menor) {
879   - menor = temp;
  949 + for (i = 0; i < ninputs; i = (i + 1 + ncolunas)) {
  950 + temp = inputs[i + 1].value * 1;
  951 + acum = ultimo + temp;
  952 + acumulado.push(acum);
  953 + ultimo = ultimo + temp;
  954 + if (temp > maior) {
  955 + maior = temp;
  956 + }
  957 + if (temp < menor) {
  958 + menor = temp;
  959 + }
  960 + temp = inputs[i + 1].value * 1;
  961 + if ($i("i3GEOgraficointerativo1Acumula").checked) {
  962 + temp = acum;
  963 + }
  964 + if ($i("i3GEOgraficointerativo1Relativa").checked) {
  965 + temp = (temp * 100) / total;
  966 + }
  967 + par.push([ inputs[i].value + " ", temp ]);
880 968 }
881   - temp = inputs[i + 1].value * 1;
882 969 if ($i("i3GEOgraficointerativo1Acumula").checked) {
883   - temp = acum;
884   - }
885   - if ($i("i3GEOgraficointerativo1Relativa").checked) {
886   - temp = (temp * 100) / total;
  970 + maior = 0;
887 971 }
888   - par.push([ inputs[i].value + " ", temp ]);
889 972 }
890   - if ($i("i3GEOgraficointerativo1Acumula").checked) {
891   - maior = 0;
892   - }
893   - }
894   - else{
895   - total = 0;
896   - for (i = 0; i < ninputs; i = (i + 1 + ncolunas)){
897   - temp = [];
898   - for(j=0;j<ncolunas;j++){
899   - temp.push(inputs[i + j].value);
  973 + else{
  974 + total = 0;
  975 + for (i = 0; i < ninputs; i = (i + 1 + ncolunas)){
  976 + temp = [];
  977 + for(j=0;j<ncolunas;j++){
  978 + temp.push(inputs[i + j].value);
  979 + }
  980 + par.push(temp);
900 981 }
901   - //cores.push(inputs[j].value);
902   - par.push(temp);
  982 + cores = colunas[2];
  983 + }
  984 + if (legendaX == legendaY) {
  985 + menor = 0;
  986 + legendaX += " (" + $trad(45, i3GEOF.graficointerativo1.dicionario)
  987 + + ")";
  988 + legendaY += " (" + $trad(46, i3GEOF.graficointerativo1.dicionario)
  989 + + ")";
903 990 }
904   - cores = "";
905   - }
906   - if (legendaX == legendaY) {
907   - menor = 0;
908   - legendaX += " (" + $trad(45, i3GEOF.graficointerativo1.dicionario)
909   - + ")";
910   - legendaY += " (" + $trad(46, i3GEOF.graficointerativo1.dicionario)
911   - + ")";
912   - }
913 991  
914   - for(j=0;j<ncolunas;j++){
915   - metadados.push({
916   - "colIndex" : j,
917   - "colType" : tipoColuna,
918   - "colName" : colunas[j]
919   - });
920   - tipoColuna = "Numeric";
921   - }
922   - dados = {
923   - "resultset" : par,
924   - "metadata" : metadados
925   - };
926   - switch (i3GEOF.graficointerativo1.tipo) {
927   - case "bar_1":
928   - legendaX = "";
929   - i3GEOF.graficointerativo1.barras(dados, maior, cores, legendaY,
930   - legendaX, xInclinado, "vertical");
931   - break;
932   - case "bar_2":
933   - legendaX = "";
934   - i3GEOF.graficointerativo1.barras(dados, maior, cores, legendaY,
935   - legendaX, xInclinado, "horizontal");
936   - break;
937   - case "linha_1":
938   - legendaX = "";
939   - i3GEOF.graficointerativo1.linhas(dados, maior, cores, legendaY,
940   - legendaX, xInclinado);
941   - break;
942   - case "pizza_1":
943   - legendaX = "";
944   - i3GEOF.graficointerativo1.pizzas(dados, maior, cores, legendaY,
945   - legendaX);
946   - break;
947   - case "ponto_1":
948   - i3GEOF.graficointerativo1.pontos(dados, maior, cores, legendaY,
949   - legendaX);
950   - break;
951   - case "area_1":
952   - legendaX = "";
953   - i3GEOF.graficointerativo1.areas(dados, maior, cores, legendaY,
954   - legendaX, xInclinado);
955   - break;
956   - case "arvore_1":
957   - i3GEOF.graficointerativo1.arvores(dados, maior, cores, legendaY,
958   - legendaX);
959   - break;
960   - default:
961   - alert($trad(4, i3GEOF.graficointerativo1.dicionario));
962   - }
963   - },
964   - /*
965   - * Function: excluilinha
966   - *
967   - * Exclui uma linha da tabela de dados
968   - */
969   - excluilinha : function(celula) {
970   - var p = celula.parentNode.parentNode;
971   - do {
972   - p.removeChild(p.childNodes[0]);
973   - } while (p.childNodes.length > 0);
974   - p.parentNode.removeChild(p);
975   - },
976   - /*
977   - * Function: corj
978   - *
979   - * Abre a janela para o usu&aacute;rio selecionar uma cor interativamente
980   - */
981   - corj : function(obj) {
982   - i3GEO.util.abreCor("", obj, "hex");
983   - },
984   - /*
985   - * Function: ordenaColuna
986   - *
987   - * Ordena uma coluna da tabela
988   - */
989   - ordenaColuna : function(coluna, cid) {
990   - var tabela = $i("i3GEOgraficointerativo1Dados").getElementsByTagName(
991   - "table")[0], trs, ntrs = 0, psort = [], t = 0, ins = "", p = 0, e, temp, chaves = [], numero = false;
  992 + for(j=0;j<ncolunas;j++){
  993 + metadados.push({
  994 + "colIndex" : j,
  995 + "colType" : tipoColuna,
  996 + "colName" : colunas[1][j]
  997 + });
  998 + tipoColuna = "Numeric";
  999 + }
  1000 + dados = {
  1001 + "resultset" : par,
  1002 + "metadata" : metadados
  1003 + };
  1004 + switch (i3GEOF.graficointerativo1.tipo) {
  1005 + case "bar_1":
  1006 + legendaX = "";
  1007 + i3GEOF.graficointerativo1.barras(dados, maior, cores, legendaY,
  1008 + legendaX, xInclinado, "vertical");
  1009 + break;
  1010 + case "bar_2":
  1011 + legendaX = "";
  1012 + i3GEOF.graficointerativo1.barras(dados, maior, cores, legendaY,
  1013 + legendaX, xInclinado, "horizontal");
  1014 + break;
  1015 + case "linha_1":
  1016 + legendaX = "";
  1017 + i3GEOF.graficointerativo1.linhas(dados, maior, cores, legendaY,
  1018 + legendaX, xInclinado);
  1019 + break;
  1020 + case "pizza_1":
  1021 + legendaX = "";
  1022 + i3GEOF.graficointerativo1.pizzas(dados, maior, cores, legendaY,
  1023 + legendaX);
  1024 + break;
  1025 + case "ponto_1":
  1026 + i3GEOF.graficointerativo1.pontos(dados, maior, cores, legendaY,
  1027 + legendaX);
  1028 + break;
  1029 + case "area_1":
  1030 + legendaX = "";
  1031 + i3GEOF.graficointerativo1.areas(dados, maior, cores, legendaY,
  1032 + legendaX, xInclinado);
  1033 + break;
  1034 + case "arvore_1":
  1035 + i3GEOF.graficointerativo1.arvores(dados, maior, cores, legendaY,
  1036 + legendaX);
  1037 + break;
  1038 + default:
  1039 + alert($trad(4, i3GEOF.graficointerativo1.dicionario));
  1040 + }
  1041 + },
  1042 + /*
  1043 + * Function: excluilinha
  1044 + *
  1045 + * Exclui uma linha da tabela de dados
  1046 + */
  1047 + excluilinha : function(celula) {
  1048 + var p = celula.parentNode.parentNode;
  1049 + do {
  1050 + p.removeChild(p.childNodes[0]);
  1051 + } while (p.childNodes.length > 0);
  1052 + p.parentNode.removeChild(p);
  1053 + },
  1054 + /*
  1055 + * Function: corj
  1056 + *
  1057 + * Abre a janela para o usu&aacute;rio selecionar uma cor interativamente
  1058 + */
  1059 + corj : function(obj) {
  1060 + i3GEO.util.abreCor("", obj, "hex");
  1061 + },
  1062 + /*
  1063 + * Function: ordenaColuna
  1064 + *
  1065 + * Ordena uma coluna da tabela
  1066 + */
  1067 + ordenaColuna : function(coluna, cid) {
  1068 + var tabela = $i("i3GEOgraficointerativo1Dados").getElementsByTagName(
  1069 + "table")[0], trs, ntrs = 0, psort = [], t = 0, ins = "", p = 0, e, temp, chaves = [], numero = false;
992 1070  
993   - trs = tabela.getElementsByTagName("tr");
994   - ntrs = trs.length;
  1071 + trs = tabela.getElementsByTagName("tr");
  1072 + ntrs = trs.length;
995 1073  
996   - function sortNumber(a, b) {
997   - return a - b;
998   - }
999   - for (t = 1; t < ntrs; t++) {
1000   - temp = trs[t].childNodes[cid];
1001   - if (temp) {
1002   - psort.push(temp.childNodes[0].value);
1003   - chaves[temp.childNodes[0].value] = t;
1004   - if (temp.childNodes[0].value * 1) {
1005   - numero = true;
1006   - }
  1074 + function sortNumber(a, b) {
  1075 + return a - b;
1007 1076 }
1008   - }
1009   - // recosntroi a tabela
1010   - if (numero === true) {
1011   - psort = psort.sort(sortNumber);
1012   - } else {
1013   - psort = psort.sort();
1014   - }
1015   - ins = "<tr>" + trs[0].innerHTML + "</tr>";
1016   - for (p = 0; p < psort; p++) {
1017   - e = chaves[psort[p]];
1018   - if (trs[e] !== undefined) {
1019   - ins += "<tr>" + trs[e].innerHTML + "</tr>";
  1077 + for (t = 1; t < ntrs; t++) {
  1078 + temp = trs[t].childNodes[cid];
  1079 + if (temp) {
  1080 + psort.push(temp.childNodes[0].value);
  1081 + chaves[temp.childNodes[0].value] = t;
  1082 + if (temp.childNodes[0].value * 1) {
  1083 + numero = true;
  1084 + }
  1085 + }
1020 1086 }
1021   - }
1022   - tabela.innerHTML = ins;
1023   - },
1024   - /*
1025   - * Function: ativaNavegacao
1026   - *
1027   - * Ativa ou desativa a atualiza&ccedil;&atilde;o autom&aacute;tica ao
1028   - * navegar no mapa
1029   - */
1030   - ativaNavegacao : function(obj) {
1031   - if (!i3GEO.Interface) {
1032   - return;
1033   - }
1034   - if (obj === true) {
1035   - if (i3GEO.Interface.ATUAL !== "googlemaps"
1036   - && i3GEO.Interface.ATUAL !== "googleearth") {
1037   - i3GEO.eventos.NAVEGAMAPA
1038   - .push("i3GEOF.graficointerativo1.obterDados()");
  1087 + // recosntroi a tabela
  1088 + if (numero === true) {
  1089 + psort = psort.sort(sortNumber);
  1090 + } else {
  1091 + psort = psort.sort();
1039 1092 }
1040   - if (i3GEO.Interface.ATUAL === "googlemaps") {
1041   - graficointerativo1Dragend = GEvent.addListener(i3GeoMap,
1042   - "dragend", function() {
1043   - i3GEOF.graficointerativo1.obterDados();
1044   - });
1045   - graficointerativo1Zoomend = GEvent.addListener(i3GeoMap,
1046   - "zoomend", function() {
1047   - i3GEOF.graficointerativo1.obterDados();
1048   - });
  1093 + ins = "<tr>" + trs[0].innerHTML + "</tr>";
  1094 + for (p = 0; p < psort; p++) {
  1095 + e = chaves[psort[p]];
  1096 + if (trs[e] !== undefined) {
  1097 + ins += "<tr>" + trs[e].innerHTML + "</tr>";
  1098 + }
1049 1099 }
1050   - if (i3GEO.Interface.ATUAL === "googleearth") {
1051   - graficointerativo1Dragend = google.earth.addEventListener(
1052   - i3GeoMap.getView(), "viewchangeend", function() {
1053   - i3GEOF.graficointerativo1.obterDados();
1054   - });
  1100 + tabela.innerHTML = ins;
  1101 + },
  1102 + /*
  1103 + * Function: ativaNavegacao
  1104 + *
  1105 + * Ativa ou desativa a atualiza&ccedil;&atilde;o autom&aacute;tica ao
  1106 + * navegar no mapa
  1107 + */
  1108 + ativaNavegacao : function(obj) {
  1109 + if (!i3GEO.Interface) {
  1110 + return;
1055 1111 }
1056   - } else {
1057   - if (i3GEO.Interface.ATUAL !== "googlemaps"
  1112 + if (obj === true) {
  1113 + if (i3GEO.Interface.ATUAL !== "googlemaps"
1058 1114 && i3GEO.Interface.ATUAL !== "googleearth") {
1059   - i3GEO.eventos.NAVEGAMAPA
1060   - .remove("i3GEOF.graficointerativo1.obterDados()");
  1115 + i3GEO.eventos.NAVEGAMAPA
  1116 + .push("i3GEOF.graficointerativo1.obterDados()");
  1117 + }
  1118 + if (i3GEO.Interface.ATUAL === "googlemaps") {
  1119 + graficointerativo1Dragend = GEvent.addListener(i3GeoMap,
  1120 + "dragend", function() {
  1121 + i3GEOF.graficointerativo1.obterDados();
  1122 + });
  1123 + graficointerativo1Zoomend = GEvent.addListener(i3GeoMap,
  1124 + "zoomend", function() {
  1125 + i3GEOF.graficointerativo1.obterDados();
  1126 + });
  1127 + }
  1128 + if (i3GEO.Interface.ATUAL === "googleearth") {
  1129 + graficointerativo1Dragend = google.earth.addEventListener(
  1130 + i3GeoMap.getView(), "viewchangeend", function() {
  1131 + i3GEOF.graficointerativo1.obterDados();
  1132 + });
  1133 + }
  1134 + } else {
  1135 + if (i3GEO.Interface.ATUAL !== "googlemaps"
  1136 + && i3GEO.Interface.ATUAL !== "googleearth") {
  1137 + i3GEO.eventos.NAVEGAMAPA
  1138 + .remove("i3GEOF.graficointerativo1.obterDados()");
  1139 + }
  1140 + if (i3GEO.Interface.ATUAL === "googlemaps") {
  1141 + GEvent.removeListener(graficointerativo1Dragend);
  1142 + GEvent.removeListener(graficointerativo1Zoomend);
  1143 + }
  1144 + if (i3GEO.Interface.ATUAL === "googleearth") {
  1145 + google.earth.removeEventListener(graficointerativo1Dragend);
  1146 + }
1061 1147 }
1062   - if (i3GEO.Interface.ATUAL === "googlemaps") {
1063   - GEvent.removeListener(graficointerativo1Dragend);
1064   - GEvent.removeListener(graficointerativo1Zoomend);
  1148 + },
  1149 + configDefault : function(dados, maior, cores, legendaY, legendaX) {
  1150 + var config = {
  1151 + canvas : "i3GEOgraficointerativo1guia4objCanvas",
  1152 + width : dados.resultset.length * $i("i3GEOgraficointerativo1FatorTamanho").value,
  1153 + height : parseInt($i("i3GEOF.graficointerativo1_corpo").style.height, 10) - 80,
  1154 + orthoAxisTitle : legendaY,
  1155 + valuesFont : 'normal 9px sans-serif ',
  1156 + baseAxisTitle : legendaX,
  1157 + baseAxisTitleAlign : 'center',
  1158 + tooltipEnabled : true,
  1159 + tooltipArrowVisible : true,
  1160 + tooltipFade : false,
  1161 + tooltipFollowMouse : false,
  1162 + tooltipFormat : function(scene) {
  1163 + var cat = this.scene.datum.atoms['category'].value, val = this.scene.datum.atoms['value'].value;
  1164 + return "<span style=color:yellow >" + cat + "</span><br>"
  1165 + + format("#.###,", val);
  1166 + },
  1167 + baseAxisTitleFont : '9px sans-serif',
  1168 + yAxisTickFormatter : function(valor) {
  1169 + valor = valor + "";
  1170 + valor = format("#.###,", valor);
  1171 + return valor;
  1172 + },
  1173 + valueFormat : function(valor) {
  1174 + valor = valor + "";
  1175 + valor = format("#.###,", valor);
  1176 + return valor;
  1177 + },
  1178 + valuesAnchor : 'top',
  1179 + valuesVisible : false,
  1180 + orthoAxisOriginIsZero : false,
  1181 + titleAlign : 'center',
  1182 + titleFont: 'bold 14px sans-serif',
  1183 + baseAxisTitleFont : '12px sans-serif',
  1184 + orthoAxisTitleFont : '12px sans-serif',
  1185 + titlePosition: "top",
  1186 + orientation : 'vertical',
  1187 + baseAxisTicks : true,
  1188 + stacked : false,
  1189 + animate : true,
  1190 + hoverable : false,
  1191 + axisGrid : true,
  1192 + contentMargins : 5,
  1193 + axisOffset : 0.02,
  1194 + panelSizeRatio : 0.8,
  1195 + orthoAxisLabelSpacingMin : 2,
  1196 + selectable : false,
  1197 + extensionPoints : {
  1198 + continuousAxisTicks_strokeStyle : 'gray',
  1199 + axisGrid_strokeStyle : 'lightgray',
  1200 + xAxisLabel_textStyle : 'black',
  1201 + label_textBaseline : "bottom",
  1202 + xAxisLabel_font : 'normal 10px sans-serif'
  1203 + }
  1204 + };
  1205 + if(maior > 0){
  1206 + config.orthoAxisFixedMax = maior;
1065 1207 }
1066   - if (i3GEO.Interface.ATUAL === "googleearth") {
1067   - google.earth.removeEventListener(graficointerativo1Dragend);
  1208 + if($i("i3GEOgraficointerativo1Titulo").value != ""){
  1209 + config.title = $i("i3GEOgraficointerativo1Titulo").value;
1068 1210 }
1069   - }
1070   - },
1071   - configDefault : function(dados, maior, cores, legendaY, legendaX) {
1072   - var config = {
1073   - canvas : "i3GEOgraficointerativo1guia4objCanvas",
1074   - width : dados.resultset.length
1075   - * $i("i3GEOgraficointerativo1FatorTamanho").value,
1076   - height : parseInt(
1077   - $i("i3GEOF.graficointerativo1_corpo").style.height, 10) - 80,
1078   - orthoAxisTitle : legendaY,
1079   - valuesFont : 'normal 9px sans-serif ',
1080   - baseAxisTitle : legendaX,
1081   - baseAxisTitleAlign : 'left',
1082   - tooltipEnabled : true,
1083   - tooltipArrowVisible : true,
1084   - tooltipFade : false,
1085   - tooltipFollowMouse : false,
1086   - tooltipFormat : function(scene) {
1087   - var cat = this.scene.datum.atoms['category'].value, val = this.scene.datum.atoms['value'].value;
1088   - return "<span style=color:yellow >" + cat + "</span><br>"
1089   - + format("#.###,", val);
1090   - },
1091   - baseAxisTitleFont : '9px sans-serif',
1092   - yAxisTickFormatter : function(valor) {
1093   - valor = valor + "";
1094   - valor = format("#.###,", valor);
1095   - return valor;
1096   - },
1097   - valueFormat : function(valor) {
1098   - valor = valor + "";
1099   - valor = format("#.###,", valor);
1100   - return valor;
1101   - },
1102   - valuesAnchor : 'top',
1103   - valuesVisible : false,
1104   - orthoAxisOriginIsZero : false,
1105   - titleAlign : 'center',
1106   - orientation : 'vertical',
1107   - baseAxisTicks : true,
1108   - stacked : false,
1109   - animate : true,
1110   - hoverable : false,
1111   - axisGrid : true,
1112   - contentMargins : 5,
1113   - axisOffset : 0.02,
1114   - panelSizeRatio : 0.8,
1115   - orthoAxisLabelSpacingMin : 2,
1116   - selectable : false,
1117   - extensionPoints : {
1118   - continuousAxisTicks_strokeStyle : 'gray',
1119   - axisGrid_strokeStyle : 'lightgray',
1120   - xAxisLabel_textStyle : 'black',
1121   - label_textBaseline : "bottom",
1122   - xAxisLabel_font : 'normal 10px sans-serif'
  1211 + if($i("i3GEOgraficointerativo1TituloX").value != ""){
  1212 + config.baseAxisTitle = $i("i3GEOgraficointerativo1TituloX").value;
1123 1213 }
1124   - };
1125   - if(maior > 0){
1126   - config.orthoAxisFixedMax = maior;
1127   - }
1128   - return config;
1129   - },
1130   - barras : function(dados, maior, cores, legendaY, legendaX, xInclinado, tipo) {
1131   - var ct = true,
  1214 + if($i("i3GEOgraficointerativo1TituloY").value != ""){
  1215 + config.orthoAxisTitle = $i("i3GEOgraficointerativo1TituloY").value;
  1216 + }
  1217 + return config;
  1218 + },
  1219 + barras : function(dados, maior, cores, legendaY, legendaX, xInclinado, tipo) {
  1220 + var ct = true,
1132 1221 sr = false,
1133   - config = i3GEOF.graficointerativo1.configDefault(dados, maior, cores,
1134   - legendaY, legendaX);
1135   - if(cores != ""){
1136   - config.extensionPoints.bar_fillStyle = function(d) {
1137   - return cores[this.index];
1138   - };
1139   - }
1140   - if (tipo === "horizontal") {
1141   - config.orientation = 'horizontal';
1142   - }
1143   - if (xInclinado == true) {
1144   - config.extensionPoints.xAxisLabel_textAngle = -Math.PI / 3;
1145   - config.extensionPoints.xAxisLabel_textBaseline = 'top';
1146   - config.extensionPoints.xAxisLabel_textAlign = 'right';
1147   - }
1148   - if(dados.resultset[0].length > 2){
1149   - config.stacked = $i("i3GEOFgraficointerativo1ativaStacked").checked;
1150   - config.legend = true;
1151   - ct = true;
1152   - sr = $i("i3GEOFgraficointerativo1ativaRowsInColumns").checked;
1153   - }
1154   - new pvc.BarChart(config).setData(dados, {
1155   - crosstabMode : ct,
1156   - seriesInRows: sr
1157   - }).render();
1158   - i3GEOF.graficointerativo1.aguarde.visibility = "hidden";
1159   - },
1160   - linhas : function(dados, maior, cores, legendaY, legendaX, xInclinado, tipo) {
1161   - var ct = false,
  1222 + config = i3GEOF.graficointerativo1.configDefault(dados, maior, cores,legendaY, legendaX);
  1223 + if (tipo === "horizontal") {
  1224 + config.orientation = 'horizontal';
  1225 + }
  1226 + if (xInclinado == true) {
  1227 + config.extensionPoints.xAxisLabel_textAngle = -Math.PI / 3;
  1228 + config.extensionPoints.xAxisLabel_textBaseline = 'top';
  1229 + config.extensionPoints.xAxisLabel_textAlign = 'right';
  1230 + }
  1231 + if(dados.resultset[0].length > 2){
  1232 + config.stacked = $i("i3GEOFgraficointerativo1ativaStacked").checked;
  1233 + config.legend = true;
  1234 + ct = true;
  1235 + sr = $i("i3GEOFgraficointerativo1ativaRowsInColumns").checked;
  1236 + config.colors = cores;
  1237 + }
  1238 + else{
  1239 + if(cores != ""){
  1240 + config.extensionPoints.bar_fillStyle = function(d) {
  1241 + return cores[this.index];
  1242 + };
  1243 + }
  1244 + }
  1245 + new pvc.BarChart(config).setData(dados, {
  1246 + crosstabMode : ct,
  1247 + seriesInRows: sr
  1248 + }).render();
  1249 + i3GEOF.graficointerativo1.aguarde.visibility = "hidden";
  1250 + },
  1251 + linhas : function(dados, maior, cores, legendaY, legendaX, xInclinado, tipo) {
  1252 + var ct = false,
1162 1253 sr = false,
1163 1254 config = i3GEOF.graficointerativo1.configDefault(dados, maior, cores,
1164   - legendaY, legendaX);
1165   - if (xInclinado == true) {
1166   - config.extensionPoints.xAxisLabel_textAngle = -Math.PI / 3;
1167   - config.extensionPoints.xAxisLabel_textBaseline = 'top';
1168   - config.extensionPoints.xAxisLabel_textAlign = 'right';
1169   - }
1170   - config.dotsVisible = true;
  1255 + legendaY, legendaX);
  1256 + if (xInclinado == true) {
  1257 + config.extensionPoints.xAxisLabel_textAngle = -Math.PI / 3;
  1258 + config.extensionPoints.xAxisLabel_textBaseline = 'top';
  1259 + config.extensionPoints.xAxisLabel_textAlign = 'right';
  1260 + }
  1261 + config.dotsVisible = true;
1171 1262  
1172   - if(dados.resultset[0].length > 2){
1173   - config.stacked = $i("i3GEOFgraficointerativo1ativaStacked").checked;
1174   - config.legend = true;
1175   - ct = true;
1176   - sr = $i("i3GEOFgraficointerativo1ativaRowsInColumns").checked;
1177   - }
1178   - new pvc.LineChart(config).setData(dados, {
1179   - crosstabMode : ct,
1180   - seriesInRows: sr
1181   - }).render();
1182   - i3GEOF.graficointerativo1.aguarde.visibility = "hidden";
1183   - },
1184   - areas : function(dados, maior, cores, legendaY, legendaX, xInclinado, tipo) {
1185   - var ct = false,
  1263 + if(dados.resultset[0].length > 2){
  1264 + config.stacked = $i("i3GEOFgraficointerativo1ativaStacked").checked;
  1265 + config.legend = true;
  1266 + ct = true;
  1267 + sr = $i("i3GEOFgraficointerativo1ativaRowsInColumns").checked;
  1268 + config.colors = cores;
  1269 + }
  1270 + new pvc.LineChart(config).setData(dados, {
  1271 + crosstabMode : ct,
  1272 + seriesInRows: sr
  1273 + }).render();
  1274 + i3GEOF.graficointerativo1.aguarde.visibility = "hidden";
  1275 + },
  1276 + areas : function(dados, maior, cores, legendaY, legendaX, xInclinado, tipo) {
  1277 + var ct = false,
1186 1278 sr = false,
1187 1279 config = i3GEOF.graficointerativo1.configDefault(dados, maior, cores,
1188   - legendaY, legendaX);
1189   - if (xInclinado == true) {
1190   - config.extensionPoints.xAxisLabel_textAngle = -Math.PI / 3;
1191   - config.extensionPoints.xAxisLabel_textBaseline = 'top';
1192   - config.extensionPoints.xAxisLabel_textAlign = 'right';
1193   - }
1194   - config.dotsVisible = true;
1195   - config.areasVisible = true;
  1280 + legendaY, legendaX);
  1281 + if (xInclinado == true) {
  1282 + config.extensionPoints.xAxisLabel_textAngle = -Math.PI / 3;
  1283 + config.extensionPoints.xAxisLabel_textBaseline = 'top';
  1284 + config.extensionPoints.xAxisLabel_textAlign = 'right';
  1285 + }
  1286 + config.dotsVisible = true;
  1287 + config.areasVisible = true;
1196 1288  
1197   - if(dados.resultset[0].length > 2){
1198   - config.stacked = $i("i3GEOFgraficointerativo1ativaStacked").checked;
1199   - config.legend = true;
1200   - ct = true;
1201   - sr = $i("i3GEOFgraficointerativo1ativaRowsInColumns").checked;
1202   - }
1203   - new pvc.LineChart(config).setData(dados, {
1204   - crosstabMode : ct,
1205   - seriesInRows: sr
1206   - }).render();
1207   - i3GEOF.graficointerativo1.aguarde.visibility = "hidden";
1208   - },
1209   - arvores : function(dados, maior, cores, legendaY, legendaX, tipo) {
1210   - // config =
1211   - // i3GEOF.graficointerativo1.configDefault(dados,maior,cores,legendaY,legendaX);
1212   - // config.rootCategoryLabel = legendaX;
1213   - config = {
1214   - canvas : "i3GEOgraficointerativo1guia4objCanvas",
1215   - width : dados.resultset.length
  1289 + if(dados.resultset[0].length > 2){
  1290 + config.stacked = $i("i3GEOFgraficointerativo1ativaStacked").checked;
  1291 + config.legend = true;
  1292 + ct = true;
  1293 + sr = $i("i3GEOFgraficointerativo1ativaRowsInColumns").checked;
  1294 + config.colors = cores;
  1295 + }
  1296 + new pvc.LineChart(config).setData(dados, {
  1297 + crosstabMode : ct,
  1298 + seriesInRows: sr
  1299 + }).render();
  1300 + i3GEOF.graficointerativo1.aguarde.visibility = "hidden";
  1301 + },
  1302 + arvores : function(dados, maior, cores, legendaY, legendaX, tipo) {
  1303 + // config =
  1304 + // i3GEOF.graficointerativo1.configDefault(dados,maior,cores,legendaY,legendaX);
  1305 + // config.rootCategoryLabel = legendaX;
  1306 + config = {
  1307 + canvas : "i3GEOgraficointerativo1guia4objCanvas",
  1308 + width : dados.resultset.length
1216 1309 * $i("i3GEOgraficointerativo1FatorTamanho").value,
1217   - height : parseInt(
1218   - $i("i3GEOF.graficointerativo1_corpo").style.height, 10) - 80,
1219   - title : legendaY,
1220   - titleFont : 'italic 14px sans-serif',
1221   - selectable : true,
1222   - hoverable : true,
1223   - legend : false,
1224   - tooltipEnabled : true,
1225   - legendPosition : 'right',
1226   - rootCategoryLabel : legendaX,
1227   - tooltipFormat : function(scene) {
1228   - var cat = this.scene.datum.atoms['category'].value, val = this.scene.datum.atoms.size.value;
1229   - return "<span style=color:yellow >" + cat + "</span><br>"
1230   - + format("#.###,", val);
  1310 + height : parseInt(
  1311 + $i("i3GEOF.graficointerativo1_corpo").style.height, 10) - 80,
  1312 + title : legendaY,
  1313 + titleFont : 'italic 14px sans-serif',
  1314 + selectable : true,
  1315 + hoverable : true,
  1316 + legend : false,
  1317 + tooltipEnabled : true,
  1318 + legendPosition : 'right',
  1319 + rootCategoryLabel : legendaX,
  1320 + tooltipFormat : function(scene) {
  1321 + var cat = this.scene.datum.atoms['category'].value, val = this.scene.datum.atoms.size.value;
  1322 + return "<span style=color:yellow >" + cat + "</span><br>"
  1323 + + format("#.###,", val);
  1324 + }
  1325 + };
  1326 + if(cores != ""){
  1327 + config.colors = cores;
1231 1328 }
1232   - };
1233   - if(cores != ""){
1234   - config.colors = cores;
1235   - }
1236   - new pvc.TreemapChart(config).setData(dados, {
1237   - crosstabMode : false
1238   - }).render();
1239   - i3GEOF.graficointerativo1.aguarde.visibility = "hidden";
1240   - },
1241   - pizzas : function(dados, maior, cores, legendaY, legendaX, tipo) {
1242   - config = i3GEOF.graficointerativo1.configDefault(dados, maior, cores,
1243   - legendaY, legendaX);
1244   - var config = {
1245   - canvas : "i3GEOgraficointerativo1guia4objCanvas",
1246   - width : dados.resultset.length
  1329 + new pvc.TreemapChart(config).setData(dados, {
  1330 + crosstabMode : false
  1331 + }).render();
  1332 + i3GEOF.graficointerativo1.aguarde.visibility = "hidden";
  1333 + },
  1334 + pizzas : function(dados, maior, cores, legendaY, legendaX, tipo) {
  1335 + config = i3GEOF.graficointerativo1.configDefault(dados, maior, cores,
  1336 + legendaY, legendaX);
  1337 + var config = {
  1338 + canvas : "i3GEOgraficointerativo1guia4objCanvas",
  1339 + width : dados.resultset.length
1247 1340 * $i("i3GEOgraficointerativo1FatorTamanho").value,
1248   - height : parseInt(
1249   - $i("i3GEOF.graficointerativo1_corpo").style.height, 10) - 80,
1250   - animate : true,
1251   - selectable : true,
1252   - hoverable : true,
1253   - valuesVisible : true,
1254   - valuesLabelStyle : 'inside',
1255   - valuesMask : "{category}",
1256   - tooltipFormat : function(scene) {
1257   - var cat = this.scene.datum.atoms['category'].value, val = this.scene.datum.atoms['value'].value;
1258   - return "<span style=color:yellow >" + cat + "</span><br>"
1259   - + format("#.###,", val);
1260   - },
1261   - extensionPoints : {
1262   - slice_strokeStyle : 'white'
  1341 + height : parseInt(
  1342 + $i("i3GEOF.graficointerativo1_corpo").style.height, 10) - 80,
  1343 + animate : true,
  1344 + selectable : true,
  1345 + hoverable : true,
  1346 + valuesVisible : true,
  1347 + valuesLabelStyle : 'inside',
  1348 + valuesMask : "{category}",
  1349 + tooltipFormat : function(scene) {
  1350 + var cat = this.scene.datum.atoms['category'].value, val = this.scene.datum.atoms['value'].value;
  1351 + return "<span style=color:yellow >" + cat + "</span><br>"
  1352 + + format("#.###,", val);
  1353 + },
  1354 + extensionPoints : {
  1355 + slice_strokeStyle : 'white'
  1356 + }
  1357 + };
  1358 + if(cores != ""){
  1359 + config.colors = cores;
1263 1360 }
1264   - };
1265   - if(cores != ""){
1266   - config.colors = cores;
1267   - }
1268   - new pvc.PieChart(config).setData(dados, {
1269   - crosstabMode : false
1270   - }).render();
1271   - i3GEOF.graficointerativo1.aguarde.visibility = "hidden";
1272   - },
1273   - pontos : function(dados, maior, cores, legendaY, legendaX, tipo) {
1274   - config = i3GEOF.graficointerativo1.configDefault(dados, maior, cores,
1275   - legendaY, legendaX);
1276   - var config = {
1277   - canvas : "i3GEOgraficointerativo1guia4objCanvas",
1278   - width : dados.resultset.length
  1361 + new pvc.PieChart(config).setData(dados, {
  1362 + crosstabMode : false
  1363 + }).render();
  1364 + i3GEOF.graficointerativo1.aguarde.visibility = "hidden";
  1365 + },
  1366 + pontos : function(dados, maior, cores, legendaY, legendaX, tipo) {
  1367 + config = i3GEOF.graficointerativo1.configDefault(dados, maior, cores,
  1368 + legendaY, legendaX);
  1369 + var config = {
  1370 + canvas : "i3GEOgraficointerativo1guia4objCanvas",
  1371 + width : dados.resultset.length
1279 1372 * $i("i3GEOgraficointerativo1FatorTamanho").value,
1280   - height : parseInt(
1281   - $i("i3GEOF.graficointerativo1_corpo").style.height, 10) - 80,
1282   - animate : true,
1283   - selectable : true,
1284   - hoverable : true,
1285   - valuesVisible : false,
1286   - orthoAxisTitle : legendaY,
1287   - valuesFont : 'normal 9px sans-serif ',
1288   - baseAxisTitle : legendaX,
1289   - yAxisTickFormatter : function(valor) {
1290   - valor = valor + "";
1291   - valor = format("#.###,", valor);
1292   - return valor;
1293   - },
1294   - valueFormat : function(valor) {
1295   - valor = valor + "";
1296   - valor = format("#.###,", valor);
1297   - return valor;
1298   - },
1299   - tooltipFormat : function(scene) {
1300   - var cat = this.scene.datum.atoms['category'].value, val = this.scene.datum.atoms['value'].value;
1301   - return "<span style=color:yellow >X: " + cat + "</span><br>Y: "
1302   - + format("#.###,", val);
  1373 + height : parseInt(
  1374 + $i("i3GEOF.graficointerativo1_corpo").style.height, 10) - 80,
  1375 + animate : true,
  1376 + selectable : true,
  1377 + hoverable : true,
  1378 + valuesVisible : false,
  1379 + orthoAxisTitle : legendaY,
  1380 + valuesFont : 'normal 9px sans-serif ',
  1381 + baseAxisTitle : legendaX,
  1382 + yAxisTickFormatter : function(valor) {
  1383 + valor = valor + "";
  1384 + valor = format("#.###,", valor);
  1385 + return valor;
  1386 + },
  1387 + valueFormat : function(valor) {
  1388 + valor = valor + "";
  1389 + valor = format("#.###,", valor);
  1390 + return valor;
  1391 + },
  1392 + tooltipFormat : function(scene) {
  1393 + var cat = this.scene.datum.atoms['category'].value, val = this.scene.datum.atoms['value'].value;
  1394 + return "<span style=color:yellow >X: " + cat + "</span><br>Y: "
  1395 + + format("#.###,", val);
  1396 + }
  1397 + };
  1398 + if(cores != ""){
  1399 + config.colors = cores;
1303 1400 }
1304   - };
1305   - if(cores != ""){
1306   - config.colors = cores;
  1401 + new pvc.DotChart(config).setData(dados, {
  1402 + crosstabMode : false
  1403 + }).render();
  1404 + i3GEOF.graficointerativo1.aguarde.visibility = "hidden";
1307 1405 }
1308   - new pvc.DotChart(config).setData(dados, {
1309   - crosstabMode : false
1310   - }).render();
1311   - i3GEOF.graficointerativo1.aguarde.visibility = "hidden";
1312   - }
1313 1406 };
... ...
pacotes/base64.js 0 → 100755
... ... @@ -0,0 +1,113 @@
  1 +/* Copyright (C) 1999 Masanao Izumo <iz@onicos.co.jp>
  2 + * Version: 1.0
  3 + * LastModified: Dec 25 1999
  4 + * This library is free. You can redistribute it and/or modify it.
  5 + */
  6 +
  7 +/*
  8 + * Interfaces:
  9 + * b64 = base64encode(data);
  10 + * data = base64decode(b64);
  11 + */
  12 +
  13 +(function() {
  14 +
  15 +var base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  16 +var base64DecodeChars = new Array(
  17 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  18 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  19 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
  20 + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
  21 + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
  22 + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
  23 + -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
  24 + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1);
  25 +
  26 +function base64encode(str) {
  27 + var out, i, len;
  28 + var c1, c2, c3;
  29 +
  30 + len = str.length;
  31 + i = 0;
  32 + out = "";
  33 + while(i < len) {
  34 + c1 = str.charCodeAt(i++) & 0xff;
  35 + if(i == len)
  36 + {
  37 + out += base64EncodeChars.charAt(c1 >> 2);
  38 + out += base64EncodeChars.charAt((c1 & 0x3) << 4);
  39 + out += "==";
  40 + break;
  41 + }
  42 + c2 = str.charCodeAt(i++);
  43 + if(i == len)
  44 + {
  45 + out += base64EncodeChars.charAt(c1 >> 2);
  46 + out += base64EncodeChars.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4));
  47 + out += base64EncodeChars.charAt((c2 & 0xF) << 2);
  48 + out += "=";
  49 + break;
  50 + }
  51 + c3 = str.charCodeAt(i++);
  52 + out += base64EncodeChars.charAt(c1 >> 2);
  53 + out += base64EncodeChars.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4));
  54 + out += base64EncodeChars.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6));
  55 + out += base64EncodeChars.charAt(c3 & 0x3F);
  56 + }
  57 + return out;
  58 +}
  59 +
  60 +function base64decode(str) {
  61 + var c1, c2, c3, c4;
  62 + var i, len, out;
  63 +
  64 + len = str.length;
  65 + i = 0;
  66 + out = "";
  67 + while(i < len) {
  68 + /* c1 */
  69 + do {
  70 + c1 = base64DecodeChars[str.charCodeAt(i++) & 0xff];
  71 + } while(i < len && c1 == -1);
  72 + if(c1 == -1)
  73 + break;
  74 +
  75 + /* c2 */
  76 + do {
  77 + c2 = base64DecodeChars[str.charCodeAt(i++) & 0xff];
  78 + } while(i < len && c2 == -1);
  79 + if(c2 == -1)
  80 + break;
  81 +
  82 + out += String.fromCharCode((c1 << 2) | ((c2 & 0x30) >> 4));
  83 +
  84 + /* c3 */
  85 + do {
  86 + c3 = str.charCodeAt(i++) & 0xff;
  87 + if(c3 == 61)
  88 + return out;
  89 + c3 = base64DecodeChars[c3];
  90 + } while(i < len && c3 == -1);
  91 + if(c3 == -1)
  92 + break;
  93 +
  94 + out += String.fromCharCode(((c2 & 0XF) << 4) | ((c3 & 0x3C) >> 2));
  95 +
  96 + /* c4 */
  97 + do {
  98 + c4 = str.charCodeAt(i++) & 0xff;
  99 + if(c4 == 61)
  100 + return out;
  101 + c4 = base64DecodeChars[c4];
  102 + } while(i < len && c4 == -1);
  103 + if(c4 == -1)
  104 + break;
  105 + out += String.fromCharCode(((c3 & 0x03) << 6) | c4);
  106 + }
  107 + return out;
  108 +}
  109 +
  110 +if (!window.btoa) window.btoa = base64encode;
  111 +if (!window.atob) window.atob = base64decode;
  112 +
  113 +})();
0 114 \ No newline at end of file
... ...
pacotes/canvas2image.js 0 → 100755
... ... @@ -0,0 +1,235 @@
  1 +/*
  2 + * Canvas2Image v0.1
  3 + * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk
  4 + * MIT License [http://www.opensource.org/licenses/mit-license.php]
  5 + */
  6 +
  7 +var Canvas2Image = (function() {
  8 +
  9 + // check if we have canvas support
  10 + var bHasCanvas = false;
  11 + var oCanvas = document.createElement("canvas");
  12 + if (oCanvas.getContext("2d")) {
  13 + bHasCanvas = true;
  14 + }
  15 +
  16 + // no canvas, bail out.
  17 + if (!bHasCanvas) {
  18 + return {
  19 + saveAsBMP : function(){},
  20 + saveAsPNG : function(){},
  21 + saveAsJPEG : function(){}
  22 + }
  23 + }
  24 +
  25 + var bHasImageData = !!(oCanvas.getContext("2d").getImageData);
  26 + var bHasDataURL = !!(oCanvas.toDataURL);
  27 + var bHasBase64 = !!(window.btoa);
  28 +
  29 + var strDownloadMime = "image/octet-stream";
  30 +
  31 + // ok, we're good
  32 + var readCanvasData = function(oCanvas) {
  33 + var iWidth = parseInt(oCanvas.width);
  34 + var iHeight = parseInt(oCanvas.height);
  35 + return oCanvas.getContext("2d").getImageData(0,0,iWidth,iHeight);
  36 + }
  37 +
  38 + // base64 encodes either a string or an array of charcodes
  39 + var encodeData = function(data) {
  40 + var strData = "";
  41 + if (typeof data == "string") {
  42 + strData = data;
  43 + } else {
  44 + var aData = data;
  45 + for (var i=0;i<aData.length;i++) {
  46 + strData += String.fromCharCode(aData[i]);
  47 + }
  48 + }
  49 + return btoa(strData);
  50 + }
  51 +
  52 + // creates a base64 encoded string containing BMP data
  53 + // takes an imagedata object as argument
  54 + var createBMP = function(oData) {
  55 + var aHeader = [];
  56 +
  57 + var iWidth = oData.width;
  58 + var iHeight = oData.height;
  59 +
  60 + aHeader.push(0x42); // magic 1
  61 + aHeader.push(0x4D);
  62 +
  63 + var iFileSize = iWidth*iHeight*3 + 54; // total header size = 54 bytes
  64 + aHeader.push(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256);
  65 + aHeader.push(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256);
  66 + aHeader.push(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256);
  67 + aHeader.push(iFileSize % 256);
  68 +
  69 + aHeader.push(0); // reserved
  70 + aHeader.push(0);
  71 + aHeader.push(0); // reserved
  72 + aHeader.push(0);
  73 +
  74 + aHeader.push(54); // dataoffset
  75 + aHeader.push(0);
  76 + aHeader.push(0);
  77 + aHeader.push(0);
  78 +
  79 + var aInfoHeader = [];
  80 + aInfoHeader.push(40); // info header size
  81 + aInfoHeader.push(0);
  82 + aInfoHeader.push(0);
  83 + aInfoHeader.push(0);
  84 +
  85 + var iImageWidth = iWidth;
  86 + aInfoHeader.push(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256);
  87 + aInfoHeader.push(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256);
  88 + aInfoHeader.push(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256);
  89 + aInfoHeader.push(iImageWidth % 256);
  90 +
  91 + var iImageHeight = iHeight;
  92 + aInfoHeader.push(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256);
  93 + aInfoHeader.push(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256);
  94 + aInfoHeader.push(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256);
  95 + aInfoHeader.push(iImageHeight % 256);
  96 +
  97 + aInfoHeader.push(1); // num of planes
  98 + aInfoHeader.push(0);
  99 +
  100 + aInfoHeader.push(24); // num of bits per pixel
  101 + aInfoHeader.push(0);
  102 +
  103 + aInfoHeader.push(0); // compression = none
  104 + aInfoHeader.push(0);
  105 + aInfoHeader.push(0);
  106 + aInfoHeader.push(0);
  107 +
  108 + var iDataSize = iWidth*iHeight*3;
  109 + aInfoHeader.push(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256);
  110 + aInfoHeader.push(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256);
  111 + aInfoHeader.push(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256);
  112 + aInfoHeader.push(iDataSize % 256);
  113 +
  114 + for (var i=0;i<16;i++) {
  115 + aInfoHeader.push(0); // these bytes not used
  116 + }
  117 +
  118 + var iPadding = (4 - ((iWidth * 3) % 4)) % 4;
  119 +
  120 + var aImgData = oData.data;
  121 +
  122 + var strPixelData = "";
  123 + var y = iHeight;
  124 + do {
  125 + var iOffsetY = iWidth*(y-1)*4;
  126 + var strPixelRow = "";
  127 + for (var x=0;x<iWidth;x++) {
  128 + var iOffsetX = 4*x;
  129 +
  130 + strPixelRow += String.fromCharCode(aImgData[iOffsetY+iOffsetX+2]);
  131 + strPixelRow += String.fromCharCode(aImgData[iOffsetY+iOffsetX+1]);
  132 + strPixelRow += String.fromCharCode(aImgData[iOffsetY+iOffsetX]);
  133 + }
  134 + for (var c=0;c<iPadding;c++) {
  135 + strPixelRow += String.fromCharCode(0);
  136 + }
  137 + strPixelData += strPixelRow;
  138 + } while (--y);
  139 +
  140 + var strEncoded = encodeData(aHeader.concat(aInfoHeader)) + encodeData(strPixelData);
  141 +
  142 + return strEncoded;
  143 + }
  144 +
  145 +
  146 + // sends the generated file to the client
  147 + var saveFile = function(strData) {
  148 + document.location.href = strData;
  149 + }
  150 +
  151 + var makeDataURI = function(strData, strMime) {
  152 + return "data:" + strMime + ";base64," + strData;
  153 + }
  154 +
  155 + // generates a <img> object containing the imagedata
  156 + var makeImageObject = function(strSource) {
  157 + var oImgElement = document.createElement("img");
  158 + oImgElement.src = strSource;
  159 + return oImgElement;
  160 + }
  161 +
  162 + var scaleCanvas = function(oCanvas, iWidth, iHeight) {
  163 + if (iWidth && iHeight) {
  164 + var oSaveCanvas = document.createElement("canvas");
  165 + oSaveCanvas.width = iWidth;
  166 + oSaveCanvas.height = iHeight;
  167 + oSaveCanvas.style.width = iWidth+"px";
  168 + oSaveCanvas.style.height = iHeight+"px";
  169 +
  170 + var oSaveCtx = oSaveCanvas.getContext("2d");
  171 +
  172 + oSaveCtx.drawImage(oCanvas, 0, 0, oCanvas.width, oCanvas.height, 0, 0, iWidth, iHeight);
  173 + return oSaveCanvas;
  174 + }
  175 + return oCanvas;
  176 + }
  177 +
  178 + return {
  179 +
  180 + saveAsPNG : function(oCanvas, bReturnImg, iWidth, iHeight) {
  181 + if (!bHasDataURL) {
  182 + return false;
  183 + }
  184 + var oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight);
  185 + var strData = oScaledCanvas.toDataURL("image/png");
  186 + if (bReturnImg) {
  187 + return makeImageObject(strData);
  188 + } else {
  189 + saveFile(strData.replace("image/png", strDownloadMime));
  190 + }
  191 + return true;
  192 + },
  193 +
  194 + saveAsJPEG : function(oCanvas, bReturnImg, iWidth, iHeight) {
  195 + if (!bHasDataURL) {
  196 + return false;
  197 + }
  198 +
  199 + var oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight);
  200 + var strMime = "image/jpeg";
  201 + var strData = oScaledCanvas.toDataURL(strMime);
  202 +
  203 + // check if browser actually supports jpeg by looking for the mime type in the data uri.
  204 + // if not, return false
  205 + if (strData.indexOf(strMime) != 5) {
  206 + return false;
  207 + }
  208 +
  209 + if (bReturnImg) {
  210 + return makeImageObject(strData);
  211 + } else {
  212 + saveFile(strData.replace(strMime, strDownloadMime));
  213 + }
  214 + return true;
  215 + },
  216 +
  217 + saveAsBMP : function(oCanvas, bReturnImg, iWidth, iHeight) {
  218 + if (!(bHasImageData && bHasBase64)) {
  219 + return false;
  220 + }
  221 +
  222 + var oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight);
  223 +
  224 + var oData = readCanvasData(oScaledCanvas);
  225 + var strImgData = createBMP(oData);
  226 + if (bReturnImg) {
  227 + return makeImageObject(makeDataURI(strImgData, "image/bmp"));
  228 + } else {
  229 + saveFile(makeDataURI(strImgData, strDownloadMime));
  230 + }
  231 + return true;
  232 + }
  233 + };
  234 +
  235 +})();
0 236 \ No newline at end of file
... ...
pacotes/canvg.js 0 → 100755
... ... @@ -0,0 +1,2886 @@
  1 +/*
  2 + * canvg.js - Javascript SVG parser and renderer on Canvas
  3 + * MIT Licensed
  4 + * Gabe Lerner (gabelerner@gmail.com)
  5 + * http://code.google.com/p/canvg/
  6 + *
  7 + * Requires: rgbcolor.js - http://www.phpied.com/rgb-color-parser-in-javascript/
  8 + */
  9 +(function(){
  10 + // canvg(target, s)
  11 + // empty parameters: replace all 'svg' elements on page with 'canvas' elements
  12 + // target: canvas element or the id of a canvas element
  13 + // s: svg string, url to svg file, or xml document
  14 + // opts: optional hash of options
  15 + // ignoreMouse: true => ignore mouse events
  16 + // ignoreAnimation: true => ignore animations
  17 + // ignoreDimensions: true => does not try to resize canvas
  18 + // ignoreClear: true => does not clear canvas
  19 + // offsetX: int => draws at a x offset
  20 + // offsetY: int => draws at a y offset
  21 + // scaleWidth: int => scales horizontally to width
  22 + // scaleHeight: int => scales vertically to height
  23 + // renderCallback: function => will call the function after the first render is completed
  24 + // forceRedraw: function => will call the function on every frame, if it returns true, will redraw
  25 + this.canvg = function (target, s, opts) {
  26 + // no parameters
  27 + if (target == null && s == null && opts == null) {
  28 + var svgTags = document.getElementsByTagName('svg');
  29 + for (var i=0; i<svgTags.length; i++) {
  30 + var svgTag = svgTags[i];
  31 + var c = document.createElement('canvas');
  32 + c.width = svgTag.clientWidth;
  33 + c.height = svgTag.clientHeight;
  34 + svgTag.parentNode.insertBefore(c, svgTag);
  35 + svgTag.parentNode.removeChild(svgTag);
  36 + var div = document.createElement('div');
  37 + div.appendChild(svgTag);
  38 + canvg(c, div.innerHTML);
  39 + }
  40 + return;
  41 + }
  42 + opts = opts || {};
  43 +
  44 + if (typeof target == 'string') {
  45 + target = document.getElementById(target);
  46 + }
  47 +
  48 + // store class on canvas
  49 + if (target.svg != null) target.svg.stop();
  50 + var svg = build();
  51 + // on i.e. 8 for flash canvas, we can't assign the property so check for it
  52 + if (!(target.childNodes.length == 1 && target.childNodes[0].nodeName == 'OBJECT')) target.svg = svg;
  53 + svg.opts = opts;
  54 +
  55 + var ctx = target.getContext('2d');
  56 + if (typeof(s.documentElement) != 'undefined') {
  57 + // load from xml doc
  58 + svg.loadXmlDoc(ctx, s);
  59 + }
  60 + else if (s.substr(0,1) == '<') {
  61 + // load from xml string
  62 + svg.loadXml(ctx, s);
  63 + }
  64 + else {
  65 + // load from url
  66 + svg.load(ctx, s);
  67 + }
  68 + }
  69 +
  70 + function build() {
  71 + var svg = { };
  72 +
  73 + svg.FRAMERATE = 30;
  74 + svg.MAX_VIRTUAL_PIXELS = 30000;
  75 +
  76 + // globals
  77 + svg.init = function(ctx) {
  78 + var uniqueId = 0;
  79 + svg.UniqueId = function () { uniqueId++; return 'canvg' + uniqueId; };
  80 + svg.Definitions = {};
  81 + svg.Styles = {};
  82 + svg.Animations = [];
  83 + svg.Images = [];
  84 + svg.ctx = ctx;
  85 + svg.ViewPort = new (function () {
  86 + this.viewPorts = [];
  87 + this.Clear = function() { this.viewPorts = []; }
  88 + this.SetCurrent = function(width, height) { this.viewPorts.push({ width: width, height: height }); }
  89 + this.RemoveCurrent = function() { this.viewPorts.pop(); }
  90 + this.Current = function() { return this.viewPorts[this.viewPorts.length - 1]; }
  91 + this.width = function() { return this.Current().width; }
  92 + this.height = function() { return this.Current().height; }
  93 + this.ComputeSize = function(d) {
  94 + if (d != null && typeof(d) == 'number') return d;
  95 + if (d == 'x') return this.width();
  96 + if (d == 'y') return this.height();
  97 + return Math.sqrt(Math.pow(this.width(), 2) + Math.pow(this.height(), 2)) / Math.sqrt(2);
  98 + }
  99 + });
  100 + }
  101 + svg.init();
  102 +
  103 + // images loaded
  104 + svg.ImagesLoaded = function() {
  105 + for (var i=0; i<svg.Images.length; i++) {
  106 + if (!svg.Images[i].loaded) return false;
  107 + }
  108 + return true;
  109 + }
  110 +
  111 + // trim
  112 + svg.trim = function(s) { return s.replace(/^\s+|\s+$/g, ''); }
  113 +
  114 + // compress spaces
  115 + svg.compressSpaces = function(s) { return s.replace(/[\s\r\t\n]+/gm,' '); }
  116 +
  117 + // ajax
  118 + svg.ajax = function(url) {
  119 + var AJAX;
  120 + if(window.XMLHttpRequest){AJAX=new XMLHttpRequest();}
  121 + else{AJAX=new ActiveXObject('Microsoft.XMLHTTP');}
  122 + if(AJAX){
  123 + AJAX.open('GET',url,false);
  124 + AJAX.send(null);
  125 + return AJAX.responseText;
  126 + }
  127 + return null;
  128 + }
  129 +
  130 + // parse xml
  131 + svg.parseXml = function(xml) {
  132 + if (window.DOMParser)
  133 + {
  134 + var parser = new DOMParser();
  135 + return parser.parseFromString(xml, 'text/xml');
  136 + }
  137 + else
  138 + {
  139 + xml = xml.replace(/<!DOCTYPE svg[^>]*>/, '');
  140 + var xmlDoc = new ActiveXObject('Microsoft.XMLDOM');
  141 + xmlDoc.async = 'false';
  142 + xmlDoc.loadXML(xml);
  143 + return xmlDoc;
  144 + }
  145 + }
  146 +
  147 + svg.Property = function(name, value) {
  148 + this.name = name;
  149 + this.value = value;
  150 + }
  151 + svg.Property.prototype.getValue = function() {
  152 + return this.value;
  153 + }
  154 +
  155 + svg.Property.prototype.hasValue = function() {
  156 + return (this.value != null && this.value !== '');
  157 + }
  158 +
  159 + // return the numerical value of the property
  160 + svg.Property.prototype.numValue = function() {
  161 + if (!this.hasValue()) return 0;
  162 +
  163 + var n = parseFloat(this.value);
  164 + if ((this.value + '').match(/%$/)) {
  165 + n = n / 100.0;
  166 + }
  167 + return n;
  168 + }
  169 +
  170 + svg.Property.prototype.valueOrDefault = function(def) {
  171 + if (this.hasValue()) return this.value;
  172 + return def;
  173 + }
  174 +
  175 + svg.Property.prototype.numValueOrDefault = function(def) {
  176 + if (this.hasValue()) return this.numValue();
  177 + return def;
  178 + }
  179 +
  180 + // color extensions
  181 + // augment the current color value with the opacity
  182 + svg.Property.prototype.addOpacity = function(opacity) {
  183 + var newValue = this.value;
  184 + if (opacity != null && opacity != '' && typeof(this.value)=='string') { // can only add opacity to colors, not patterns
  185 + var color = new RGBColor(this.value);
  186 + if (color.ok) {
  187 + newValue = 'rgba(' + color.r + ', ' + color.g + ', ' + color.b + ', ' + opacity + ')';
  188 + }
  189 + }
  190 + return new svg.Property(this.name, newValue);
  191 + }
  192 +
  193 + // definition extensions
  194 + // get the definition from the definitions table
  195 + svg.Property.prototype.getDefinition = function() {
  196 + var name = this.value.match(/#([^\)'"]+)/);
  197 + if (name) { name = name[1]; }
  198 + if (!name) { name = this.value; }
  199 + return svg.Definitions[name];
  200 + }
  201 +
  202 + svg.Property.prototype.isUrlDefinition = function() {
  203 + return this.value.indexOf('url(') == 0
  204 + }
  205 +
  206 + svg.Property.prototype.getFillStyleDefinition = function(e, opacityProp) {
  207 + var def = this.getDefinition();
  208 +
  209 + // gradient
  210 + if (def != null && def.createGradient) {
  211 + return def.createGradient(svg.ctx, e, opacityProp);
  212 + }
  213 +
  214 + // pattern
  215 + if (def != null && def.createPattern) {
  216 + if (def.getHrefAttribute().hasValue()) {
  217 + var pt = def.attribute('patternTransform');
  218 + def = def.getHrefAttribute().getDefinition();
  219 + if (pt.hasValue()) { def.attribute('patternTransform', true).value = pt.value; }
  220 + }
  221 + return def.createPattern(svg.ctx, e);
  222 + }
  223 +
  224 + return null;
  225 + }
  226 +
  227 + // length extensions
  228 + svg.Property.prototype.getDPI = function(viewPort) {
  229 + return 96.0; // TODO: compute?
  230 + }
  231 +
  232 + svg.Property.prototype.getEM = function(viewPort) {
  233 + var em = 12;
  234 +
  235 + var fontSize = new svg.Property('fontSize', svg.Font.Parse(svg.ctx.font).fontSize);
  236 + if (fontSize.hasValue()) em = fontSize.toPixels(viewPort);
  237 +
  238 + return em;
  239 + }
  240 +
  241 + svg.Property.prototype.getUnits = function() {
  242 + var s = this.value+'';
  243 + return s.replace(/[0-9\.\-]/g,'');
  244 + }
  245 +
  246 + // get the length as pixels
  247 + svg.Property.prototype.toPixels = function(viewPort, processPercent) {
  248 + if (!this.hasValue()) return 0;
  249 + var s = this.value+'';
  250 + if (s.match(/em$/)) return this.numValue() * this.getEM(viewPort);
  251 + if (s.match(/ex$/)) return this.numValue() * this.getEM(viewPort) / 2.0;
  252 + if (s.match(/px$/)) return this.numValue();
  253 + if (s.match(/pt$/)) return this.numValue() * this.getDPI(viewPort) * (1.0 / 72.0);
  254 + if (s.match(/pc$/)) return this.numValue() * 15;
  255 + if (s.match(/cm$/)) return this.numValue() * this.getDPI(viewPort) / 2.54;
  256 + if (s.match(/mm$/)) return this.numValue() * this.getDPI(viewPort) / 25.4;
  257 + if (s.match(/in$/)) return this.numValue() * this.getDPI(viewPort);
  258 + if (s.match(/%$/)) return this.numValue() * svg.ViewPort.ComputeSize(viewPort);
  259 + var n = this.numValue();
  260 + if (processPercent && n < 1.0) return n * svg.ViewPort.ComputeSize(viewPort);
  261 + return n;
  262 + }
  263 +
  264 + // time extensions
  265 + // get the time as milliseconds
  266 + svg.Property.prototype.toMilliseconds = function() {
  267 + if (!this.hasValue()) return 0;
  268 + var s = this.value+'';
  269 + if (s.match(/s$/)) return this.numValue() * 1000;
  270 + if (s.match(/ms$/)) return this.numValue();
  271 + return this.numValue();
  272 + }
  273 +
  274 + // angle extensions
  275 + // get the angle as radians
  276 + svg.Property.prototype.toRadians = function() {
  277 + if (!this.hasValue()) return 0;
  278 + var s = this.value+'';
  279 + if (s.match(/deg$/)) return this.numValue() * (Math.PI / 180.0);
  280 + if (s.match(/grad$/)) return this.numValue() * (Math.PI / 200.0);
  281 + if (s.match(/rad$/)) return this.numValue();
  282 + return this.numValue() * (Math.PI / 180.0);
  283 + }
  284 +
  285 + // fonts
  286 + svg.Font = new (function() {
  287 + this.Styles = 'normal|italic|oblique|inherit';
  288 + this.Variants = 'normal|small-caps|inherit';
  289 + this.Weights = 'normal|bold|bolder|lighter|100|200|300|400|500|600|700|800|900|inherit';
  290 +
  291 + this.CreateFont = function(fontStyle, fontVariant, fontWeight, fontSize, fontFamily, inherit) {
  292 + var f = inherit != null ? this.Parse(inherit) : this.CreateFont('', '', '', '', '', svg.ctx.font);
  293 + return {
  294 + fontFamily: fontFamily || f.fontFamily,
  295 + fontSize: fontSize || f.fontSize,
  296 + fontStyle: fontStyle || f.fontStyle,
  297 + fontWeight: fontWeight || f.fontWeight,
  298 + fontVariant: fontVariant || f.fontVariant,
  299 + toString: function () { return [this.fontStyle, this.fontVariant, this.fontWeight, this.fontSize, this.fontFamily].join(' ') }
  300 + }
  301 + }
  302 +
  303 + var that = this;
  304 + this.Parse = function(s) {
  305 + var f = {};
  306 + var d = svg.trim(svg.compressSpaces(s || '')).split(' ');
  307 + var set = { fontSize: false, fontStyle: false, fontWeight: false, fontVariant: false }
  308 + var ff = '';
  309 + for (var i=0; i<d.length; i++) {
  310 + if (!set.fontStyle && that.Styles.indexOf(d[i]) != -1) { if (d[i] != 'inherit') f.fontStyle = d[i]; set.fontStyle = true; }
  311 + else if (!set.fontVariant && that.Variants.indexOf(d[i]) != -1) { if (d[i] != 'inherit') f.fontVariant = d[i]; set.fontStyle = set.fontVariant = true; }
  312 + else if (!set.fontWeight && that.Weights.indexOf(d[i]) != -1) { if (d[i] != 'inherit') f.fontWeight = d[i]; set.fontStyle = set.fontVariant = set.fontWeight = true; }
  313 + else if (!set.fontSize) { if (d[i] != 'inherit') f.fontSize = d[i].split('/')[0]; set.fontStyle = set.fontVariant = set.fontWeight = set.fontSize = true; }
  314 + else { if (d[i] != 'inherit') ff += d[i]; }
  315 + } if (ff != '') f.fontFamily = ff;
  316 + return f;
  317 + }
  318 + });
  319 +
  320 + // points and paths
  321 + svg.ToNumberArray = function(s) {
  322 + var a = svg.trim(svg.compressSpaces((s || '').replace(/,/g, ' '))).split(' ');
  323 + for (var i=0; i<a.length; i++) {
  324 + a[i] = parseFloat(a[i]);
  325 + }
  326 + return a;
  327 + }
  328 + svg.Point = function(x, y) {
  329 + this.x = x;
  330 + this.y = y;
  331 + }
  332 + svg.Point.prototype.angleTo = function(p) {
  333 + return Math.atan2(p.y - this.y, p.x - this.x);
  334 + }
  335 +
  336 + svg.Point.prototype.applyTransform = function(v) {
  337 + var xp = this.x * v[0] + this.y * v[2] + v[4];
  338 + var yp = this.x * v[1] + this.y * v[3] + v[5];
  339 + this.x = xp;
  340 + this.y = yp;
  341 + }
  342 +
  343 + svg.CreatePoint = function(s) {
  344 + var a = svg.ToNumberArray(s);
  345 + return new svg.Point(a[0], a[1]);
  346 + }
  347 + svg.CreatePath = function(s) {
  348 + var a = svg.ToNumberArray(s);
  349 + var path = [];
  350 + for (var i=0; i<a.length; i+=2) {
  351 + path.push(new svg.Point(a[i], a[i+1]));
  352 + }
  353 + return path;
  354 + }
  355 +
  356 + // bounding box
  357 + svg.BoundingBox = function(x1, y1, x2, y2) { // pass in initial points if you want
  358 + this.x1 = Number.NaN;
  359 + this.y1 = Number.NaN;
  360 + this.x2 = Number.NaN;
  361 + this.y2 = Number.NaN;
  362 +
  363 + this.x = function() { return this.x1; }
  364 + this.y = function() { return this.y1; }
  365 + this.width = function() { return this.x2 - this.x1; }
  366 + this.height = function() { return this.y2 - this.y1; }
  367 +
  368 + this.addPoint = function(x, y) {
  369 + if (x != null) {
  370 + if (isNaN(this.x1) || isNaN(this.x2)) {
  371 + this.x1 = x;
  372 + this.x2 = x;
  373 + }
  374 + if (x < this.x1) this.x1 = x;
  375 + if (x > this.x2) this.x2 = x;
  376 + }
  377 +
  378 + if (y != null) {
  379 + if (isNaN(this.y1) || isNaN(this.y2)) {
  380 + this.y1 = y;
  381 + this.y2 = y;
  382 + }
  383 + if (y < this.y1) this.y1 = y;
  384 + if (y > this.y2) this.y2 = y;
  385 + }
  386 + }
  387 + this.addX = function(x) { this.addPoint(x, null); }
  388 + this.addY = function(y) { this.addPoint(null, y); }
  389 +
  390 + this.addBoundingBox = function(bb) {
  391 + this.addPoint(bb.x1, bb.y1);
  392 + this.addPoint(bb.x2, bb.y2);
  393 + }
  394 +
  395 + this.addQuadraticCurve = function(p0x, p0y, p1x, p1y, p2x, p2y) {
  396 + var cp1x = p0x + 2/3 * (p1x - p0x); // CP1 = QP0 + 2/3 *(QP1-QP0)
  397 + var cp1y = p0y + 2/3 * (p1y - p0y); // CP1 = QP0 + 2/3 *(QP1-QP0)
  398 + var cp2x = cp1x + 1/3 * (p2x - p0x); // CP2 = CP1 + 1/3 *(QP2-QP0)
  399 + var cp2y = cp1y + 1/3 * (p2y - p0y); // CP2 = CP1 + 1/3 *(QP2-QP0)
  400 + this.addBezierCurve(p0x, p0y, cp1x, cp2x, cp1y, cp2y, p2x, p2y);
  401 + }
  402 +
  403 + this.addBezierCurve = function(p0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y) {
  404 + // from http://blog.hackers-cafe.net/2009/06/how-to-calculate-bezier-curves-bounding.html
  405 + var p0 = [p0x, p0y], p1 = [p1x, p1y], p2 = [p2x, p2y], p3 = [p3x, p3y];
  406 + this.addPoint(p0[0], p0[1]);
  407 + this.addPoint(p3[0], p3[1]);
  408 +
  409 + for (i=0; i<=1; i++) {
  410 + var f = function(t) {
  411 + return Math.pow(1-t, 3) * p0[i]
  412 + + 3 * Math.pow(1-t, 2) * t * p1[i]
  413 + + 3 * (1-t) * Math.pow(t, 2) * p2[i]
  414 + + Math.pow(t, 3) * p3[i];
  415 + }
  416 +
  417 + var b = 6 * p0[i] - 12 * p1[i] + 6 * p2[i];
  418 + var a = -3 * p0[i] + 9 * p1[i] - 9 * p2[i] + 3 * p3[i];
  419 + var c = 3 * p1[i] - 3 * p0[i];
  420 +
  421 + if (a == 0) {
  422 + if (b == 0) continue;
  423 + var t = -c / b;
  424 + if (0 < t && t < 1) {
  425 + if (i == 0) this.addX(f(t));
  426 + if (i == 1) this.addY(f(t));
  427 + }
  428 + continue;
  429 + }
  430 +
  431 + var b2ac = Math.pow(b, 2) - 4 * c * a;
  432 + if (b2ac < 0) continue;
  433 + var t1 = (-b + Math.sqrt(b2ac)) / (2 * a);
  434 + if (0 < t1 && t1 < 1) {
  435 + if (i == 0) this.addX(f(t1));
  436 + if (i == 1) this.addY(f(t1));
  437 + }
  438 + var t2 = (-b - Math.sqrt(b2ac)) / (2 * a);
  439 + if (0 < t2 && t2 < 1) {
  440 + if (i == 0) this.addX(f(t2));
  441 + if (i == 1) this.addY(f(t2));
  442 + }
  443 + }
  444 + }
  445 +
  446 + this.isPointInBox = function(x, y) {
  447 + return (this.x1 <= x && x <= this.x2 && this.y1 <= y && y <= this.y2);
  448 + }
  449 +
  450 + this.addPoint(x1, y1);
  451 + this.addPoint(x2, y2);
  452 + }
  453 +
  454 + // transforms
  455 + svg.Transform = function(v) {
  456 + var that = this;
  457 + this.Type = {}
  458 +
  459 + // translate
  460 + this.Type.translate = function(s) {
  461 + this.p = svg.CreatePoint(s);
  462 + this.apply = function(ctx) {
  463 + ctx.translate(this.p.x || 0.0, this.p.y || 0.0);
  464 + }
  465 + this.unapply = function(ctx) {
  466 + ctx.translate(-1.0 * this.p.x || 0.0, -1.0 * this.p.y || 0.0);
  467 + }
  468 + this.applyToPoint = function(p) {
  469 + p.applyTransform([1, 0, 0, 1, this.p.x || 0.0, this.p.y || 0.0]);
  470 + }
  471 + }
  472 +
  473 + // rotate
  474 + this.Type.rotate = function(s) {
  475 + var a = svg.ToNumberArray(s);
  476 + this.angle = new svg.Property('angle', a[0]);
  477 + this.cx = a[1] || 0;
  478 + this.cy = a[2] || 0;
  479 + this.apply = function(ctx) {
  480 + ctx.translate(this.cx, this.cy);
  481 + ctx.rotate(this.angle.toRadians());
  482 + ctx.translate(-this.cx, -this.cy);
  483 + }
  484 + this.unapply = function(ctx) {
  485 + ctx.translate(this.cx, this.cy);
  486 + ctx.rotate(-1.0 * this.angle.toRadians());
  487 + ctx.translate(-this.cx, -this.cy);
  488 + }
  489 + this.applyToPoint = function(p) {
  490 + var a = this.angle.toRadians();
  491 + p.applyTransform([1, 0, 0, 1, this.p.x || 0.0, this.p.y || 0.0]);
  492 + p.applyTransform([Math.cos(a), Math.sin(a), -Math.sin(a), Math.cos(a), 0, 0]);
  493 + p.applyTransform([1, 0, 0, 1, -this.p.x || 0.0, -this.p.y || 0.0]);
  494 + }
  495 + }
  496 +
  497 + this.Type.scale = function(s) {
  498 + this.p = svg.CreatePoint(s);
  499 + this.apply = function(ctx) {
  500 + ctx.scale(this.p.x || 1.0, this.p.y || this.p.x || 1.0);
  501 + }
  502 + this.unapply = function(ctx) {
  503 + ctx.scale(1.0 / this.p.x || 1.0, 1.0 / this.p.y || this.p.x || 1.0);
  504 + }
  505 + this.applyToPoint = function(p) {
  506 + p.applyTransform([this.p.x || 0.0, 0, 0, this.p.y || 0.0, 0, 0]);
  507 + }
  508 + }
  509 +
  510 + this.Type.matrix = function(s) {
  511 + this.m = svg.ToNumberArray(s);
  512 + this.apply = function(ctx) {
  513 + ctx.transform(this.m[0], this.m[1], this.m[2], this.m[3], this.m[4], this.m[5]);
  514 + }
  515 + this.applyToPoint = function(p) {
  516 + p.applyTransform(this.m);
  517 + }
  518 + }
  519 +
  520 + this.Type.SkewBase = function(s) {
  521 + this.base = that.Type.matrix;
  522 + this.base(s);
  523 + this.angle = new svg.Property('angle', s);
  524 + }
  525 + this.Type.SkewBase.prototype = new this.Type.matrix;
  526 +
  527 + this.Type.skewX = function(s) {
  528 + this.base = that.Type.SkewBase;
  529 + this.base(s);
  530 + this.m = [1, 0, Math.tan(this.angle.toRadians()), 1, 0, 0];
  531 + }
  532 + this.Type.skewX.prototype = new this.Type.SkewBase;
  533 +
  534 + this.Type.skewY = function(s) {
  535 + this.base = that.Type.SkewBase;
  536 + this.base(s);
  537 + this.m = [1, Math.tan(this.angle.toRadians()), 0, 1, 0, 0];
  538 + }
  539 + this.Type.skewY.prototype = new this.Type.SkewBase;
  540 +
  541 + this.transforms = [];
  542 +
  543 + this.apply = function(ctx) {
  544 + for (var i=0; i<this.transforms.length; i++) {
  545 + this.transforms[i].apply(ctx);
  546 + }
  547 + }
  548 +
  549 + this.unapply = function(ctx) {
  550 + for (var i=this.transforms.length-1; i>=0; i--) {
  551 + this.transforms[i].unapply(ctx);
  552 + }
  553 + }
  554 +
  555 + this.applyToPoint = function(p) {
  556 + for (var i=0; i<this.transforms.length; i++) {
  557 + this.transforms[i].applyToPoint(p);
  558 + }
  559 + }
  560 +
  561 + var data = svg.trim(svg.compressSpaces(v)).replace(/\)(\s?,\s?)/g,') ').split(/\s(?=[a-z])/);
  562 + for (var i=0; i<data.length; i++) {
  563 + var type = svg.trim(data[i].split('(')[0]);
  564 + var s = data[i].split('(')[1].replace(')','');
  565 + var transform = new this.Type[type](s);
  566 + transform.type = type;
  567 + this.transforms.push(transform);
  568 + }
  569 + }
  570 +
  571 + // aspect ratio
  572 + svg.AspectRatio = function(ctx, aspectRatio, width, desiredWidth, height, desiredHeight, minX, minY, refX, refY) {
  573 + // aspect ratio - http://www.w3.org/TR/SVG/coords.html#PreserveAspectRatioAttribute
  574 + aspectRatio = svg.compressSpaces(aspectRatio);
  575 + aspectRatio = aspectRatio.replace(/^defer\s/,''); // ignore defer
  576 + var align = aspectRatio.split(' ')[0] || 'xMidYMid';
  577 + var meetOrSlice = aspectRatio.split(' ')[1] || 'meet';
  578 +
  579 + // calculate scale
  580 + var scaleX = width / desiredWidth;
  581 + var scaleY = height / desiredHeight;
  582 + var scaleMin = Math.min(scaleX, scaleY);
  583 + var scaleMax = Math.max(scaleX, scaleY);
  584 + if (meetOrSlice == 'meet') { desiredWidth *= scaleMin; desiredHeight *= scaleMin; }
  585 + if (meetOrSlice == 'slice') { desiredWidth *= scaleMax; desiredHeight *= scaleMax; }
  586 +
  587 + refX = new svg.Property('refX', refX);
  588 + refY = new svg.Property('refY', refY);
  589 + if (refX.hasValue() && refY.hasValue()) {
  590 + ctx.translate(-scaleMin * refX.toPixels('x'), -scaleMin * refY.toPixels('y'));
  591 + }
  592 + else {
  593 + // align
  594 + if (align.match(/^xMid/) && ((meetOrSlice == 'meet' && scaleMin == scaleY) || (meetOrSlice == 'slice' && scaleMax == scaleY))) ctx.translate(width / 2.0 - desiredWidth / 2.0, 0);
  595 + if (align.match(/YMid$/) && ((meetOrSlice == 'meet' && scaleMin == scaleX) || (meetOrSlice == 'slice' && scaleMax == scaleX))) ctx.translate(0, height / 2.0 - desiredHeight / 2.0);
  596 + if (align.match(/^xMax/) && ((meetOrSlice == 'meet' && scaleMin == scaleY) || (meetOrSlice == 'slice' && scaleMax == scaleY))) ctx.translate(width - desiredWidth, 0);
  597 + if (align.match(/YMax$/) && ((meetOrSlice == 'meet' && scaleMin == scaleX) || (meetOrSlice == 'slice' && scaleMax == scaleX))) ctx.translate(0, height - desiredHeight);
  598 + }
  599 +
  600 + // scale
  601 + if (align == 'none') ctx.scale(scaleX, scaleY);
  602 + else if (meetOrSlice == 'meet') ctx.scale(scaleMin, scaleMin);
  603 + else if (meetOrSlice == 'slice') ctx.scale(scaleMax, scaleMax);
  604 +
  605 + // translate
  606 + ctx.translate(minX == null ? 0 : -minX, minY == null ? 0 : -minY);
  607 + }
  608 +
  609 + // elements
  610 + svg.Element = {}
  611 +
  612 + svg.EmptyProperty = new svg.Property('EMPTY', '');
  613 +
  614 + svg.Element.ElementBase = function(node) {
  615 + this.attributes = {};
  616 + this.styles = {};
  617 + this.children = [];
  618 +
  619 + // get or create attribute
  620 + this.attribute = function(name, createIfNotExists) {
  621 + var a = this.attributes[name];
  622 + if (a != null) return a;
  623 +
  624 + if (createIfNotExists == true) { a = new svg.Property(name, ''); this.attributes[name] = a; }
  625 + return a || svg.EmptyProperty;
  626 + }
  627 +
  628 + this.getHrefAttribute = function() {
  629 + for (var a in this.attributes) {
  630 + if (a.match(/:href$/)) {
  631 + return this.attributes[a];
  632 + }
  633 + }
  634 + return svg.EmptyProperty;
  635 + }
  636 +
  637 + // get or create style, crawls up node tree
  638 + this.style = function(name, createIfNotExists) {
  639 + var s = this.styles[name];
  640 + if (s != null) return s;
  641 +
  642 + var a = this.attribute(name);
  643 + if (a != null && a.hasValue()) {
  644 + this.styles[name] = a; // move up to me to cache
  645 + return a;
  646 + }
  647 +
  648 + var p = this.parent;
  649 + if (p != null) {
  650 + var ps = p.style(name);
  651 + if (ps != null && ps.hasValue()) {
  652 + return ps;
  653 + }
  654 + }
  655 +
  656 + if (createIfNotExists == true) { s = new svg.Property(name, ''); this.styles[name] = s; }
  657 + return s || svg.EmptyProperty;
  658 + }
  659 +
  660 + // base render
  661 + this.render = function(ctx) {
  662 + // don't render display=none
  663 + if (this.style('display').value == 'none') return;
  664 +
  665 + // don't render visibility=hidden
  666 + if (this.attribute('visibility').value == 'hidden') return;
  667 +
  668 + ctx.save();
  669 + if (this.attribute('mask').hasValue()) { // mask
  670 + var mask = this.attribute('mask').getDefinition();
  671 + if (mask != null) mask.apply(ctx, this);
  672 + }
  673 + else if (this.style('filter').hasValue()) { // filter
  674 + var filter = this.style('filter').getDefinition();
  675 + if (filter != null) filter.apply(ctx, this);
  676 + }
  677 + else {
  678 + this.setContext(ctx);
  679 + this.renderChildren(ctx);
  680 + this.clearContext(ctx);
  681 + }
  682 + ctx.restore();
  683 + }
  684 +
  685 + // base set context
  686 + this.setContext = function(ctx) {
  687 + // OVERRIDE ME!
  688 + }
  689 +
  690 + // base clear context
  691 + this.clearContext = function(ctx) {
  692 + // OVERRIDE ME!
  693 + }
  694 +
  695 + // base render children
  696 + this.renderChildren = function(ctx) {
  697 + for (var i=0; i<this.children.length; i++) {
  698 + this.children[i].render(ctx);
  699 + }
  700 + }
  701 +
  702 + this.addChild = function(childNode, create) {
  703 + var child = childNode;
  704 + if (create) child = svg.CreateElement(childNode);
  705 + child.parent = this;
  706 + this.children.push(child);
  707 + }
  708 +
  709 + if (node != null && node.nodeType == 1) { //ELEMENT_NODE
  710 + // add children
  711 + for (var i=0; i<node.childNodes.length; i++) {
  712 + var childNode = node.childNodes[i];
  713 + if (childNode.nodeType == 1) this.addChild(childNode, true); //ELEMENT_NODE
  714 + if (this.captureTextNodes && childNode.nodeType == 3) {
  715 + var text = childNode.nodeValue || childNode.text || '';
  716 + if (svg.trim(svg.compressSpaces(text)) != '') {
  717 + this.addChild(new svg.Element.tspan(childNode), false); // TEXT_NODE
  718 + }
  719 + }
  720 + }
  721 +
  722 + // add attributes
  723 + for (var i=0; i<node.attributes.length; i++) {
  724 + var attribute = node.attributes[i];
  725 + this.attributes[attribute.nodeName] = new svg.Property(attribute.nodeName, attribute.nodeValue);
  726 + }
  727 +
  728 + // add tag styles
  729 + var styles = svg.Styles[node.nodeName];
  730 + if (styles != null) {
  731 + for (var name in styles) {
  732 + this.styles[name] = styles[name];
  733 + }
  734 + }
  735 +
  736 + // add class styles
  737 + if (this.attribute('class').hasValue()) {
  738 + var classes = svg.compressSpaces(this.attribute('class').value).split(' ');
  739 + for (var j=0; j<classes.length; j++) {
  740 + styles = svg.Styles['.'+classes[j]];
  741 + if (styles != null) {
  742 + for (var name in styles) {
  743 + this.styles[name] = styles[name];
  744 + }
  745 + }
  746 + styles = svg.Styles[node.nodeName+'.'+classes[j]];
  747 + if (styles != null) {
  748 + for (var name in styles) {
  749 + this.styles[name] = styles[name];
  750 + }
  751 + }
  752 + }
  753 + }
  754 +
  755 + // add id styles
  756 + if (this.attribute('id').hasValue()) {
  757 + var styles = svg.Styles['#' + this.attribute('id').value];
  758 + if (styles != null) {
  759 + for (var name in styles) {
  760 + this.styles[name] = styles[name];
  761 + }
  762 + }
  763 + }
  764 +
  765 + // add inline styles
  766 + if (this.attribute('style').hasValue()) {
  767 + var styles = this.attribute('style').value.split(';');
  768 + for (var i=0; i<styles.length; i++) {
  769 + if (svg.trim(styles[i]) != '') {
  770 + var style = styles[i].split(':');
  771 + var name = svg.trim(style[0]);
  772 + var value = svg.trim(style[1]);
  773 + this.styles[name] = new svg.Property(name, value);
  774 + }
  775 + }
  776 + }
  777 +
  778 + // add id
  779 + if (this.attribute('id').hasValue()) {
  780 + if (svg.Definitions[this.attribute('id').value] == null) {
  781 + svg.Definitions[this.attribute('id').value] = this;
  782 + }
  783 + }
  784 + }
  785 + }
  786 +
  787 + svg.Element.RenderedElementBase = function(node) {
  788 + this.base = svg.Element.ElementBase;
  789 + this.base(node);
  790 +
  791 + this.setContext = function(ctx) {
  792 + // fill
  793 + if (this.style('fill').isUrlDefinition()) {
  794 + var fs = this.style('fill').getFillStyleDefinition(this, this.style('fill-opacity'));
  795 + if (fs != null) ctx.fillStyle = fs;
  796 + }
  797 + else if (this.style('fill').hasValue()) {
  798 + var fillStyle = this.style('fill');
  799 + if (fillStyle.value == 'currentColor') fillStyle.value = this.style('color').value;
  800 + ctx.fillStyle = (fillStyle.value == 'none' ? 'rgba(0,0,0,0)' : fillStyle.value);
  801 + }
  802 + if (this.style('fill-opacity').hasValue()) {
  803 + var fillStyle = new svg.Property('fill', ctx.fillStyle);
  804 + fillStyle = fillStyle.addOpacity(this.style('fill-opacity').value);
  805 + ctx.fillStyle = fillStyle.value;
  806 + }
  807 +
  808 + // stroke
  809 + if (this.style('stroke').isUrlDefinition()) {
  810 + var fs = this.style('stroke').getFillStyleDefinition(this, this.style('stroke-opacity'));
  811 + if (fs != null) ctx.strokeStyle = fs;
  812 + }
  813 + else if (this.style('stroke').hasValue()) {
  814 + var strokeStyle = this.style('stroke');
  815 + if (strokeStyle.value == 'currentColor') strokeStyle.value = this.style('color').value;
  816 + ctx.strokeStyle = (strokeStyle.value == 'none' ? 'rgba(0,0,0,0)' : strokeStyle.value);
  817 + }
  818 + if (this.style('stroke-opacity').hasValue()) {
  819 + var strokeStyle = new svg.Property('stroke', ctx.strokeStyle);
  820 + strokeStyle = strokeStyle.addOpacity(this.style('stroke-opacity').value);
  821 + ctx.strokeStyle = strokeStyle.value;
  822 + }
  823 + if (this.style('stroke-width').hasValue()) {
  824 + var newLineWidth = this.style('stroke-width').toPixels();
  825 + ctx.lineWidth = newLineWidth == 0 ? 0.001 : newLineWidth; // browsers don't respect 0
  826 + }
  827 + if (this.style('stroke-linecap').hasValue()) ctx.lineCap = this.style('stroke-linecap').value;
  828 + if (this.style('stroke-linejoin').hasValue()) ctx.lineJoin = this.style('stroke-linejoin').value;
  829 + if (this.style('stroke-miterlimit').hasValue()) ctx.miterLimit = this.style('stroke-miterlimit').value;
  830 + if (this.style('stroke-dasharray').hasValue() && this.style('stroke-dasharray').value != 'none') {
  831 + var gaps = svg.ToNumberArray(this.style('stroke-dasharray').value);
  832 + if (typeof(ctx.setLineDash) != 'undefined') { ctx.setLineDash(gaps); }
  833 + else if (typeof(ctx.webkitLineDash) != 'undefined') { ctx.webkitLineDash = gaps; }
  834 + else if (typeof(ctx.mozDash ) != 'undefined') { ctx.mozDash = gaps; }
  835 +
  836 + var offset = this.style('stroke-dashoffset').numValueOrDefault(1);
  837 + if (typeof(ctx.lineDashOffset) != 'undefined') { ctx.lineDashOffset = offset; }
  838 + else if (typeof(ctx.webkitLineDashOffset) != 'undefined') { ctx.webkitLineDashOffset = offset; }
  839 + else if (typeof(ctx.mozDashOffset) != 'undefined') { ctx.mozDashOffset = offset; }
  840 + }
  841 +
  842 + // font
  843 + if (typeof(ctx.font) != 'undefined') {
  844 + ctx.font = svg.Font.CreateFont(
  845 + this.style('font-style').value,
  846 + this.style('font-variant').value,
  847 + this.style('font-weight').value,
  848 + this.style('font-size').hasValue() ? this.style('font-size').toPixels() + 'px' : '',
  849 + this.style('font-family').value).toString();
  850 + }
  851 +
  852 + // transform
  853 + if (this.attribute('transform').hasValue()) {
  854 + var transform = new svg.Transform(this.attribute('transform').value);
  855 + transform.apply(ctx);
  856 + }
  857 +
  858 + // clip
  859 + if (this.style('clip-path').hasValue()) {
  860 + var clip = this.style('clip-path').getDefinition();
  861 + if (clip != null) clip.apply(ctx);
  862 + }
  863 +
  864 + // opacity
  865 + if (this.style('opacity').hasValue()) {
  866 + ctx.globalAlpha = this.style('opacity').numValue();
  867 + }
  868 + }
  869 + }
  870 + svg.Element.RenderedElementBase.prototype = new svg.Element.ElementBase;
  871 +
  872 + svg.Element.PathElementBase = function(node) {
  873 + this.base = svg.Element.RenderedElementBase;
  874 + this.base(node);
  875 +
  876 + this.path = function(ctx) {
  877 + if (ctx != null) ctx.beginPath();
  878 + return new svg.BoundingBox();
  879 + }
  880 +
  881 + this.renderChildren = function(ctx) {
  882 + this.path(ctx);
  883 + svg.Mouse.checkPath(this, ctx);
  884 + if (ctx.fillStyle != '') {
  885 + if (this.attribute('fill-rule').valueOrDefault('inherit') != 'inherit') { ctx.fill(this.attribute('fill-rule').value); }
  886 + else { ctx.fill(); }
  887 + }
  888 + if (ctx.strokeStyle != '') ctx.stroke();
  889 +
  890 + var markers = this.getMarkers();
  891 + if (markers != null) {
  892 + if (this.style('marker-start').isUrlDefinition()) {
  893 + var marker = this.style('marker-start').getDefinition();
  894 + marker.render(ctx, markers[0][0], markers[0][1]);
  895 + }
  896 + if (this.style('marker-mid').isUrlDefinition()) {
  897 + var marker = this.style('marker-mid').getDefinition();
  898 + for (var i=1;i<markers.length-1;i++) {
  899 + marker.render(ctx, markers[i][0], markers[i][1]);
  900 + }
  901 + }
  902 + if (this.style('marker-end').isUrlDefinition()) {
  903 + var marker = this.style('marker-end').getDefinition();
  904 + marker.render(ctx, markers[markers.length-1][0], markers[markers.length-1][1]);
  905 + }
  906 + }
  907 + }
  908 +
  909 + this.getBoundingBox = function() {
  910 + return this.path();
  911 + }
  912 +
  913 + this.getMarkers = function() {
  914 + return null;
  915 + }
  916 + }
  917 + svg.Element.PathElementBase.prototype = new svg.Element.RenderedElementBase;
  918 +
  919 + // svg element
  920 + svg.Element.svg = function(node) {
  921 + this.base = svg.Element.RenderedElementBase;
  922 + this.base(node);
  923 +
  924 + this.baseClearContext = this.clearContext;
  925 + this.clearContext = function(ctx) {
  926 + this.baseClearContext(ctx);
  927 + svg.ViewPort.RemoveCurrent();
  928 + }
  929 +
  930 + this.baseSetContext = this.setContext;
  931 + this.setContext = function(ctx) {
  932 + // initial values
  933 + ctx.strokeStyle = 'rgba(0,0,0,0)';
  934 + ctx.lineCap = 'butt';
  935 + ctx.lineJoin = 'miter';
  936 + ctx.miterLimit = 4;
  937 +
  938 + this.baseSetContext(ctx);
  939 +
  940 + // create new view port
  941 + if (!this.attribute('x').hasValue()) this.attribute('x', true).value = 0;
  942 + if (!this.attribute('y').hasValue()) this.attribute('y', true).value = 0;
  943 + ctx.translate(this.attribute('x').toPixels('x'), this.attribute('y').toPixels('y'));
  944 +
  945 + var width = svg.ViewPort.width();
  946 + var height = svg.ViewPort.height();
  947 +
  948 + if (!this.attribute('width').hasValue()) this.attribute('width', true).value = '100%';
  949 + if (!this.attribute('height').hasValue()) this.attribute('height', true).value = '100%';
  950 + if (typeof(this.root) == 'undefined') {
  951 + width = this.attribute('width').toPixels('x');
  952 + height = this.attribute('height').toPixels('y');
  953 +
  954 + var x = 0;
  955 + var y = 0;
  956 + if (this.attribute('refX').hasValue() && this.attribute('refY').hasValue()) {
  957 + x = -this.attribute('refX').toPixels('x');
  958 + y = -this.attribute('refY').toPixels('y');
  959 + }
  960 +
  961 + ctx.beginPath();
  962 + ctx.moveTo(x, y);
  963 + ctx.lineTo(width, y);
  964 + ctx.lineTo(width, height);
  965 + ctx.lineTo(x, height);
  966 + ctx.closePath();
  967 + ctx.clip();
  968 + }
  969 + svg.ViewPort.SetCurrent(width, height);
  970 +
  971 + // viewbox
  972 + if (this.attribute('viewBox').hasValue()) {
  973 + var viewBox = svg.ToNumberArray(this.attribute('viewBox').value);
  974 + var minX = viewBox[0];
  975 + var minY = viewBox[1];
  976 + width = viewBox[2];
  977 + height = viewBox[3];
  978 +
  979 + svg.AspectRatio(ctx,
  980 + this.attribute('preserveAspectRatio').value,
  981 + svg.ViewPort.width(),
  982 + width,
  983 + svg.ViewPort.height(),
  984 + height,
  985 + minX,
  986 + minY,
  987 + this.attribute('refX').value,
  988 + this.attribute('refY').value);
  989 +
  990 + svg.ViewPort.RemoveCurrent();
  991 + svg.ViewPort.SetCurrent(viewBox[2], viewBox[3]);
  992 + }
  993 + }
  994 + }
  995 + svg.Element.svg.prototype = new svg.Element.RenderedElementBase;
  996 +
  997 + // rect element
  998 + svg.Element.rect = function(node) {
  999 + this.base = svg.Element.PathElementBase;
  1000 + this.base(node);
  1001 +
  1002 + this.path = function(ctx) {
  1003 + var x = this.attribute('x').toPixels('x');
  1004 + var y = this.attribute('y').toPixels('y');
  1005 + var width = this.attribute('width').toPixels('x');
  1006 + var height = this.attribute('height').toPixels('y');
  1007 + var rx = this.attribute('rx').toPixels('x');
  1008 + var ry = this.attribute('ry').toPixels('y');
  1009 + if (this.attribute('rx').hasValue() && !this.attribute('ry').hasValue()) ry = rx;
  1010 + if (this.attribute('ry').hasValue() && !this.attribute('rx').hasValue()) rx = ry;
  1011 + rx = Math.min(rx, width / 2.0);
  1012 + ry = Math.min(ry, height / 2.0);
  1013 + if (ctx != null) {
  1014 + ctx.beginPath();
  1015 + ctx.moveTo(x + rx, y);
  1016 + ctx.lineTo(x + width - rx, y);
  1017 + ctx.quadraticCurveTo(x + width, y, x + width, y + ry)
  1018 + ctx.lineTo(x + width, y + height - ry);
  1019 + ctx.quadraticCurveTo(x + width, y + height, x + width - rx, y + height)
  1020 + ctx.lineTo(x + rx, y + height);
  1021 + ctx.quadraticCurveTo(x, y + height, x, y + height - ry)
  1022 + ctx.lineTo(x, y + ry);
  1023 + ctx.quadraticCurveTo(x, y, x + rx, y)
  1024 + ctx.closePath();
  1025 + }
  1026 +
  1027 + return new svg.BoundingBox(x, y, x + width, y + height);
  1028 + }
  1029 + }
  1030 + svg.Element.rect.prototype = new svg.Element.PathElementBase;
  1031 +
  1032 + // circle element
  1033 + svg.Element.circle = function(node) {
  1034 + this.base = svg.Element.PathElementBase;
  1035 + this.base(node);
  1036 +
  1037 + this.path = function(ctx) {
  1038 + var cx = this.attribute('cx').toPixels('x');
  1039 + var cy = this.attribute('cy').toPixels('y');
  1040 + var r = this.attribute('r').toPixels();
  1041 +
  1042 + if (ctx != null) {
  1043 + ctx.beginPath();
  1044 + ctx.arc(cx, cy, r, 0, Math.PI * 2, true);
  1045 + ctx.closePath();
  1046 + }
  1047 +
  1048 + return new svg.BoundingBox(cx - r, cy - r, cx + r, cy + r);
  1049 + }
  1050 + }
  1051 + svg.Element.circle.prototype = new svg.Element.PathElementBase;
  1052 +
  1053 + // ellipse element
  1054 + svg.Element.ellipse = function(node) {
  1055 + this.base = svg.Element.PathElementBase;
  1056 + this.base(node);
  1057 +
  1058 + this.path = function(ctx) {
  1059 + var KAPPA = 4 * ((Math.sqrt(2) - 1) / 3);
  1060 + var rx = this.attribute('rx').toPixels('x');
  1061 + var ry = this.attribute('ry').toPixels('y');
  1062 + var cx = this.attribute('cx').toPixels('x');
  1063 + var cy = this.attribute('cy').toPixels('y');
  1064 +
  1065 + if (ctx != null) {
  1066 + ctx.beginPath();
  1067 + ctx.moveTo(cx, cy - ry);
  1068 + ctx.bezierCurveTo(cx + (KAPPA * rx), cy - ry, cx + rx, cy - (KAPPA * ry), cx + rx, cy);
  1069 + ctx.bezierCurveTo(cx + rx, cy + (KAPPA * ry), cx + (KAPPA * rx), cy + ry, cx, cy + ry);
  1070 + ctx.bezierCurveTo(cx - (KAPPA * rx), cy + ry, cx - rx, cy + (KAPPA * ry), cx - rx, cy);
  1071 + ctx.bezierCurveTo(cx - rx, cy - (KAPPA * ry), cx - (KAPPA * rx), cy - ry, cx, cy - ry);
  1072 + ctx.closePath();
  1073 + }
  1074 +
  1075 + return new svg.BoundingBox(cx - rx, cy - ry, cx + rx, cy + ry);
  1076 + }
  1077 + }
  1078 + svg.Element.ellipse.prototype = new svg.Element.PathElementBase;
  1079 +
  1080 + // line element
  1081 + svg.Element.line = function(node) {
  1082 + this.base = svg.Element.PathElementBase;
  1083 + this.base(node);
  1084 +
  1085 + this.getPoints = function() {
  1086 + return [
  1087 + new svg.Point(this.attribute('x1').toPixels('x'), this.attribute('y1').toPixels('y')),
  1088 + new svg.Point(this.attribute('x2').toPixels('x'), this.attribute('y2').toPixels('y'))];
  1089 + }
  1090 +
  1091 + this.path = function(ctx) {
  1092 + var points = this.getPoints();
  1093 +
  1094 + if (ctx != null) {
  1095 + ctx.beginPath();
  1096 + ctx.moveTo(points[0].x, points[0].y);
  1097 + ctx.lineTo(points[1].x, points[1].y);
  1098 + }
  1099 +
  1100 + return new svg.BoundingBox(points[0].x, points[0].y, points[1].x, points[1].y);
  1101 + }
  1102 +
  1103 + this.getMarkers = function() {
  1104 + var points = this.getPoints();
  1105 + var a = points[0].angleTo(points[1]);
  1106 + return [[points[0], a], [points[1], a]];
  1107 + }
  1108 + }
  1109 + svg.Element.line.prototype = new svg.Element.PathElementBase;
  1110 +
  1111 + // polyline element
  1112 + svg.Element.polyline = function(node) {
  1113 + this.base = svg.Element.PathElementBase;
  1114 + this.base(node);
  1115 +
  1116 + this.points = svg.CreatePath(this.attribute('points').value);
  1117 + this.path = function(ctx) {
  1118 + var bb = new svg.BoundingBox(this.points[0].x, this.points[0].y);
  1119 + if (ctx != null) {
  1120 + ctx.beginPath();
  1121 + ctx.moveTo(this.points[0].x, this.points[0].y);
  1122 + }
  1123 + for (var i=1; i<this.points.length; i++) {
  1124 + bb.addPoint(this.points[i].x, this.points[i].y);
  1125 + if (ctx != null) ctx.lineTo(this.points[i].x, this.points[i].y);
  1126 + }
  1127 + return bb;
  1128 + }
  1129 +
  1130 + this.getMarkers = function() {
  1131 + var markers = [];
  1132 + for (var i=0; i<this.points.length - 1; i++) {
  1133 + markers.push([this.points[i], this.points[i].angleTo(this.points[i+1])]);
  1134 + }
  1135 + markers.push([this.points[this.points.length-1], markers[markers.length-1][1]]);
  1136 + return markers;
  1137 + }
  1138 + }
  1139 + svg.Element.polyline.prototype = new svg.Element.PathElementBase;
  1140 +
  1141 + // polygon element
  1142 + svg.Element.polygon = function(node) {
  1143 + this.base = svg.Element.polyline;
  1144 + this.base(node);
  1145 +
  1146 + this.basePath = this.path;
  1147 + this.path = function(ctx) {
  1148 + var bb = this.basePath(ctx);
  1149 + if (ctx != null) {
  1150 + ctx.lineTo(this.points[0].x, this.points[0].y);
  1151 + ctx.closePath();
  1152 + }
  1153 + return bb;
  1154 + }
  1155 + }
  1156 + svg.Element.polygon.prototype = new svg.Element.polyline;
  1157 +
  1158 + // path element
  1159 + svg.Element.path = function(node) {
  1160 + this.base = svg.Element.PathElementBase;
  1161 + this.base(node);
  1162 +
  1163 + var d = this.attribute('d').value;
  1164 + // TODO: convert to real lexer based on http://www.w3.org/TR/SVG11/paths.html#PathDataBNF
  1165 + d = d.replace(/,/gm,' '); // get rid of all commas
  1166 + d = d.replace(/([MmZzLlHhVvCcSsQqTtAa])([MmZzLlHhVvCcSsQqTtAa])/gm,'$1 $2'); // separate commands from commands
  1167 + d = d.replace(/([MmZzLlHhVvCcSsQqTtAa])([MmZzLlHhVvCcSsQqTtAa])/gm,'$1 $2'); // separate commands from commands
  1168 + d = d.replace(/([MmZzLlHhVvCcSsQqTtAa])([^\s])/gm,'$1 $2'); // separate commands from points
  1169 + d = d.replace(/([^\s])([MmZzLlHhVvCcSsQqTtAa])/gm,'$1 $2'); // separate commands from points
  1170 + d = d.replace(/([0-9])([+\-])/gm,'$1 $2'); // separate digits when no comma
  1171 + d = d.replace(/(\.[0-9]*)(\.)/gm,'$1 $2'); // separate digits when no comma
  1172 + d = d.replace(/([Aa](\s+[0-9]+){3})\s+([01])\s*([01])/gm,'$1 $3 $4 '); // shorthand elliptical arc path syntax
  1173 + d = svg.compressSpaces(d); // compress multiple spaces
  1174 + d = svg.trim(d);
  1175 + this.PathParser = new (function(d) {
  1176 + this.tokens = d.split(' ');
  1177 +
  1178 + this.reset = function() {
  1179 + this.i = -1;
  1180 + this.command = '';
  1181 + this.previousCommand = '';
  1182 + this.start = new svg.Point(0, 0);
  1183 + this.control = new svg.Point(0, 0);
  1184 + this.current = new svg.Point(0, 0);
  1185 + this.points = [];
  1186 + this.angles = [];
  1187 + }
  1188 +
  1189 + this.isEnd = function() {
  1190 + return this.i >= this.tokens.length - 1;
  1191 + }
  1192 +
  1193 + this.isCommandOrEnd = function() {
  1194 + if (this.isEnd()) return true;
  1195 + return this.tokens[this.i + 1].match(/^[A-Za-z]$/) != null;
  1196 + }
  1197 +
  1198 + this.isRelativeCommand = function() {
  1199 + switch(this.command)
  1200 + {
  1201 + case 'm':
  1202 + case 'l':
  1203 + case 'h':
  1204 + case 'v':
  1205 + case 'c':
  1206 + case 's':
  1207 + case 'q':
  1208 + case 't':
  1209 + case 'a':
  1210 + case 'z':
  1211 + return true;
  1212 + break;
  1213 + }
  1214 + return false;
  1215 + }
  1216 +
  1217 + this.getToken = function() {
  1218 + this.i++;
  1219 + return this.tokens[this.i];
  1220 + }
  1221 +
  1222 + this.getScalar = function() {
  1223 + return parseFloat(this.getToken());
  1224 + }
  1225 +
  1226 + this.nextCommand = function() {
  1227 + this.previousCommand = this.command;
  1228 + this.command = this.getToken();
  1229 + }
  1230 +
  1231 + this.getPoint = function() {
  1232 + var p = new svg.Point(this.getScalar(), this.getScalar());
  1233 + return this.makeAbsolute(p);
  1234 + }
  1235 +
  1236 + this.getAsControlPoint = function() {
  1237 + var p = this.getPoint();
  1238 + this.control = p;
  1239 + return p;
  1240 + }
  1241 +
  1242 + this.getAsCurrentPoint = function() {
  1243 + var p = this.getPoint();
  1244 + this.current = p;
  1245 + return p;
  1246 + }
  1247 +
  1248 + this.getReflectedControlPoint = function() {
  1249 + if (this.previousCommand.toLowerCase() != 'c' &&
  1250 + this.previousCommand.toLowerCase() != 's' &&
  1251 + this.previousCommand.toLowerCase() != 'q' &&
  1252 + this.previousCommand.toLowerCase() != 't' ){
  1253 + return this.current;
  1254 + }
  1255 +
  1256 + // reflect point
  1257 + var p = new svg.Point(2 * this.current.x - this.control.x, 2 * this.current.y - this.control.y);
  1258 + return p;
  1259 + }
  1260 +
  1261 + this.makeAbsolute = function(p) {
  1262 + if (this.isRelativeCommand()) {
  1263 + p.x += this.current.x;
  1264 + p.y += this.current.y;
  1265 + }
  1266 + return p;
  1267 + }
  1268 +
  1269 + this.addMarker = function(p, from, priorTo) {
  1270 + // if the last angle isn't filled in because we didn't have this point yet ...
  1271 + if (priorTo != null && this.angles.length > 0 && this.angles[this.angles.length-1] == null) {
  1272 + this.angles[this.angles.length-1] = this.points[this.points.length-1].angleTo(priorTo);
  1273 + }
  1274 + this.addMarkerAngle(p, from == null ? null : from.angleTo(p));
  1275 + }
  1276 +
  1277 + this.addMarkerAngle = function(p, a) {
  1278 + this.points.push(p);
  1279 + this.angles.push(a);
  1280 + }
  1281 +
  1282 + this.getMarkerPoints = function() { return this.points; }
  1283 + this.getMarkerAngles = function() {
  1284 + for (var i=0; i<this.angles.length; i++) {
  1285 + if (this.angles[i] == null) {
  1286 + for (var j=i+1; j<this.angles.length; j++) {
  1287 + if (this.angles[j] != null) {
  1288 + this.angles[i] = this.angles[j];
  1289 + break;
  1290 + }
  1291 + }
  1292 + }
  1293 + }
  1294 + return this.angles;
  1295 + }
  1296 + })(d);
  1297 +
  1298 + this.path = function(ctx) {
  1299 + var pp = this.PathParser;
  1300 + pp.reset();
  1301 +
  1302 + var bb = new svg.BoundingBox();
  1303 + if (ctx != null) ctx.beginPath();
  1304 + while (!pp.isEnd()) {
  1305 + pp.nextCommand();
  1306 + switch (pp.command) {
  1307 + case 'M':
  1308 + case 'm':
  1309 + var p = pp.getAsCurrentPoint();
  1310 + pp.addMarker(p);
  1311 + bb.addPoint(p.x, p.y);
  1312 + if (ctx != null) ctx.moveTo(p.x, p.y);
  1313 + pp.start = pp.current;
  1314 + while (!pp.isCommandOrEnd()) {
  1315 + var p = pp.getAsCurrentPoint();
  1316 + pp.addMarker(p, pp.start);
  1317 + bb.addPoint(p.x, p.y);
  1318 + if (ctx != null) ctx.lineTo(p.x, p.y);
  1319 + }
  1320 + break;
  1321 + case 'L':
  1322 + case 'l':
  1323 + while (!pp.isCommandOrEnd()) {
  1324 + var c = pp.current;
  1325 + var p = pp.getAsCurrentPoint();
  1326 + pp.addMarker(p, c);
  1327 + bb.addPoint(p.x, p.y);
  1328 + if (ctx != null) ctx.lineTo(p.x, p.y);
  1329 + }
  1330 + break;
  1331 + case 'H':
  1332 + case 'h':
  1333 + while (!pp.isCommandOrEnd()) {
  1334 + var newP = new svg.Point((pp.isRelativeCommand() ? pp.current.x : 0) + pp.getScalar(), pp.current.y);
  1335 + pp.addMarker(newP, pp.current);
  1336 + pp.current = newP;
  1337 + bb.addPoint(pp.current.x, pp.current.y);
  1338 + if (ctx != null) ctx.lineTo(pp.current.x, pp.current.y);
  1339 + }
  1340 + break;
  1341 + case 'V':
  1342 + case 'v':
  1343 + while (!pp.isCommandOrEnd()) {
  1344 + var newP = new svg.Point(pp.current.x, (pp.isRelativeCommand() ? pp.current.y : 0) + pp.getScalar());
  1345 + pp.addMarker(newP, pp.current);
  1346 + pp.current = newP;
  1347 + bb.addPoint(pp.current.x, pp.current.y);
  1348 + if (ctx != null) ctx.lineTo(pp.current.x, pp.current.y);
  1349 + }
  1350 + break;
  1351 + case 'C':
  1352 + case 'c':
  1353 + while (!pp.isCommandOrEnd()) {
  1354 + var curr = pp.current;
  1355 + var p1 = pp.getPoint();
  1356 + var cntrl = pp.getAsControlPoint();
  1357 + var cp = pp.getAsCurrentPoint();
  1358 + pp.addMarker(cp, cntrl, p1);
  1359 + bb.addBezierCurve(curr.x, curr.y, p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y);
  1360 + if (ctx != null) ctx.bezierCurveTo(p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y);
  1361 + }
  1362 + break;
  1363 + case 'S':
  1364 + case 's':
  1365 + while (!pp.isCommandOrEnd()) {
  1366 + var curr = pp.current;
  1367 + var p1 = pp.getReflectedControlPoint();
  1368 + var cntrl = pp.getAsControlPoint();
  1369 + var cp = pp.getAsCurrentPoint();
  1370 + pp.addMarker(cp, cntrl, p1);
  1371 + bb.addBezierCurve(curr.x, curr.y, p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y);
  1372 + if (ctx != null) ctx.bezierCurveTo(p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y);
  1373 + }
  1374 + break;
  1375 + case 'Q':
  1376 + case 'q':
  1377 + while (!pp.isCommandOrEnd()) {
  1378 + var curr = pp.current;
  1379 + var cntrl = pp.getAsControlPoint();
  1380 + var cp = pp.getAsCurrentPoint();
  1381 + pp.addMarker(cp, cntrl, cntrl);
  1382 + bb.addQuadraticCurve(curr.x, curr.y, cntrl.x, cntrl.y, cp.x, cp.y);
  1383 + if (ctx != null) ctx.quadraticCurveTo(cntrl.x, cntrl.y, cp.x, cp.y);
  1384 + }
  1385 + break;
  1386 + case 'T':
  1387 + case 't':
  1388 + while (!pp.isCommandOrEnd()) {
  1389 + var curr = pp.current;
  1390 + var cntrl = pp.getReflectedControlPoint();
  1391 + pp.control = cntrl;
  1392 + var cp = pp.getAsCurrentPoint();
  1393 + pp.addMarker(cp, cntrl, cntrl);
  1394 + bb.addQuadraticCurve(curr.x, curr.y, cntrl.x, cntrl.y, cp.x, cp.y);
  1395 + if (ctx != null) ctx.quadraticCurveTo(cntrl.x, cntrl.y, cp.x, cp.y);
  1396 + }
  1397 + break;
  1398 + case 'A':
  1399 + case 'a':
  1400 + while (!pp.isCommandOrEnd()) {
  1401 + var curr = pp.current;
  1402 + var rx = pp.getScalar();
  1403 + var ry = pp.getScalar();
  1404 + var xAxisRotation = pp.getScalar() * (Math.PI / 180.0);
  1405 + var largeArcFlag = pp.getScalar();
  1406 + var sweepFlag = pp.getScalar();
  1407 + var cp = pp.getAsCurrentPoint();
  1408 +
  1409 + // Conversion from endpoint to center parameterization
  1410 + // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
  1411 + // x1', y1'
  1412 + var currp = new svg.Point(
  1413 + Math.cos(xAxisRotation) * (curr.x - cp.x) / 2.0 + Math.sin(xAxisRotation) * (curr.y - cp.y) / 2.0,
  1414 + -Math.sin(xAxisRotation) * (curr.x - cp.x) / 2.0 + Math.cos(xAxisRotation) * (curr.y - cp.y) / 2.0
  1415 + );
  1416 + // adjust radii
  1417 + var l = Math.pow(currp.x,2)/Math.pow(rx,2)+Math.pow(currp.y,2)/Math.pow(ry,2);
  1418 + if (l > 1) {
  1419 + rx *= Math.sqrt(l);
  1420 + ry *= Math.sqrt(l);
  1421 + }
  1422 + // cx', cy'
  1423 + var s = (largeArcFlag == sweepFlag ? -1 : 1) * Math.sqrt(
  1424 + ((Math.pow(rx,2)*Math.pow(ry,2))-(Math.pow(rx,2)*Math.pow(currp.y,2))-(Math.pow(ry,2)*Math.pow(currp.x,2))) /
  1425 + (Math.pow(rx,2)*Math.pow(currp.y,2)+Math.pow(ry,2)*Math.pow(currp.x,2))
  1426 + );
  1427 + if (isNaN(s)) s = 0;
  1428 + var cpp = new svg.Point(s * rx * currp.y / ry, s * -ry * currp.x / rx);
  1429 + // cx, cy
  1430 + var centp = new svg.Point(
  1431 + (curr.x + cp.x) / 2.0 + Math.cos(xAxisRotation) * cpp.x - Math.sin(xAxisRotation) * cpp.y,
  1432 + (curr.y + cp.y) / 2.0 + Math.sin(xAxisRotation) * cpp.x + Math.cos(xAxisRotation) * cpp.y
  1433 + );
  1434 + // vector magnitude
  1435 + var m = function(v) { return Math.sqrt(Math.pow(v[0],2) + Math.pow(v[1],2)); }
  1436 + // ratio between two vectors
  1437 + var r = function(u, v) { return (u[0]*v[0]+u[1]*v[1]) / (m(u)*m(v)) }
  1438 + // angle between two vectors
  1439 + var a = function(u, v) { return (u[0]*v[1] < u[1]*v[0] ? -1 : 1) * Math.acos(r(u,v)); }
  1440 + // initial angle
  1441 + var a1 = a([1,0], [(currp.x-cpp.x)/rx,(currp.y-cpp.y)/ry]);
  1442 + // angle delta
  1443 + var u = [(currp.x-cpp.x)/rx,(currp.y-cpp.y)/ry];
  1444 + var v = [(-currp.x-cpp.x)/rx,(-currp.y-cpp.y)/ry];
  1445 + var ad = a(u, v);
  1446 + if (r(u,v) <= -1) ad = Math.PI;
  1447 + if (r(u,v) >= 1) ad = 0;
  1448 +
  1449 + // for markers
  1450 + var dir = 1 - sweepFlag ? 1.0 : -1.0;
  1451 + var ah = a1 + dir * (ad / 2.0);
  1452 + var halfWay = new svg.Point(
  1453 + centp.x + rx * Math.cos(ah),
  1454 + centp.y + ry * Math.sin(ah)
  1455 + );
  1456 + pp.addMarkerAngle(halfWay, ah - dir * Math.PI / 2);
  1457 + pp.addMarkerAngle(cp, ah - dir * Math.PI);
  1458 +
  1459 + bb.addPoint(cp.x, cp.y); // TODO: this is too naive, make it better
  1460 + if (ctx != null) {
  1461 + var r = rx > ry ? rx : ry;
  1462 + var sx = rx > ry ? 1 : rx / ry;
  1463 + var sy = rx > ry ? ry / rx : 1;
  1464 +
  1465 + ctx.translate(centp.x, centp.y);
  1466 + ctx.rotate(xAxisRotation);
  1467 + ctx.scale(sx, sy);
  1468 + ctx.arc(0, 0, r, a1, a1 + ad, 1 - sweepFlag);
  1469 + ctx.scale(1/sx, 1/sy);
  1470 + ctx.rotate(-xAxisRotation);
  1471 + ctx.translate(-centp.x, -centp.y);
  1472 + }
  1473 + }
  1474 + break;
  1475 + case 'Z':
  1476 + case 'z':
  1477 + if (ctx != null) ctx.closePath();
  1478 + pp.current = pp.start;
  1479 + }
  1480 + }
  1481 +
  1482 + return bb;
  1483 + }
  1484 +
  1485 + this.getMarkers = function() {
  1486 + var points = this.PathParser.getMarkerPoints();
  1487 + var angles = this.PathParser.getMarkerAngles();
  1488 +
  1489 + var markers = [];
  1490 + for (var i=0; i<points.length; i++) {
  1491 + markers.push([points[i], angles[i]]);
  1492 + }
  1493 + return markers;
  1494 + }
  1495 + }
  1496 + svg.Element.path.prototype = new svg.Element.PathElementBase;
  1497 +
  1498 + // pattern element
  1499 + svg.Element.pattern = function(node) {
  1500 + this.base = svg.Element.ElementBase;
  1501 + this.base(node);
  1502 +
  1503 + this.createPattern = function(ctx, element) {
  1504 + var width = this.attribute('width').toPixels('x', true);
  1505 + var height = this.attribute('height').toPixels('y', true);
  1506 +
  1507 + // render me using a temporary svg element
  1508 + var tempSvg = new svg.Element.svg();
  1509 + tempSvg.attributes['viewBox'] = new svg.Property('viewBox', this.attribute('viewBox').value);
  1510 + tempSvg.attributes['width'] = new svg.Property('width', width + 'px');
  1511 + tempSvg.attributes['height'] = new svg.Property('height', height + 'px');
  1512 + tempSvg.attributes['transform'] = new svg.Property('transform', this.attribute('patternTransform').value);
  1513 + tempSvg.children = this.children;
  1514 +
  1515 + var c = document.createElement('canvas');
  1516 + c.width = width;
  1517 + c.height = height;
  1518 + var cctx = c.getContext('2d');
  1519 + if (this.attribute('x').hasValue() && this.attribute('y').hasValue()) {
  1520 + cctx.translate(this.attribute('x').toPixels('x', true), this.attribute('y').toPixels('y', true));
  1521 + }
  1522 + // render 3x3 grid so when we transform there's no white space on edges
  1523 + for (var x=-1; x<=1; x++) {
  1524 + for (var y=-1; y<=1; y++) {
  1525 + cctx.save();
  1526 + cctx.translate(x * c.width, y * c.height);
  1527 + tempSvg.render(cctx);
  1528 + cctx.restore();
  1529 + }
  1530 + }
  1531 + var pattern = ctx.createPattern(c, 'repeat');
  1532 + return pattern;
  1533 + }
  1534 + }
  1535 + svg.Element.pattern.prototype = new svg.Element.ElementBase;
  1536 +
  1537 + // marker element
  1538 + svg.Element.marker = function(node) {
  1539 + this.base = svg.Element.ElementBase;
  1540 + this.base(node);
  1541 +
  1542 + this.baseRender = this.render;
  1543 + this.render = function(ctx, point, angle) {
  1544 + ctx.translate(point.x, point.y);
  1545 + if (this.attribute('orient').valueOrDefault('auto') == 'auto') ctx.rotate(angle);
  1546 + if (this.attribute('markerUnits').valueOrDefault('strokeWidth') == 'strokeWidth') ctx.scale(ctx.lineWidth, ctx.lineWidth);
  1547 + ctx.save();
  1548 +
  1549 + // render me using a temporary svg element
  1550 + var tempSvg = new svg.Element.svg();
  1551 + tempSvg.attributes['viewBox'] = new svg.Property('viewBox', this.attribute('viewBox').value);
  1552 + tempSvg.attributes['refX'] = new svg.Property('refX', this.attribute('refX').value);
  1553 + tempSvg.attributes['refY'] = new svg.Property('refY', this.attribute('refY').value);
  1554 + tempSvg.attributes['width'] = new svg.Property('width', this.attribute('markerWidth').value);
  1555 + tempSvg.attributes['height'] = new svg.Property('height', this.attribute('markerHeight').value);
  1556 + tempSvg.attributes['fill'] = new svg.Property('fill', this.attribute('fill').valueOrDefault('black'));
  1557 + tempSvg.attributes['stroke'] = new svg.Property('stroke', this.attribute('stroke').valueOrDefault('none'));
  1558 + tempSvg.children = this.children;
  1559 + tempSvg.render(ctx);
  1560 +
  1561 + ctx.restore();
  1562 + if (this.attribute('markerUnits').valueOrDefault('strokeWidth') == 'strokeWidth') ctx.scale(1/ctx.lineWidth, 1/ctx.lineWidth);
  1563 + if (this.attribute('orient').valueOrDefault('auto') == 'auto') ctx.rotate(-angle);
  1564 + ctx.translate(-point.x, -point.y);
  1565 + }
  1566 + }
  1567 + svg.Element.marker.prototype = new svg.Element.ElementBase;
  1568 +
  1569 + // definitions element
  1570 + svg.Element.defs = function(node) {
  1571 + this.base = svg.Element.ElementBase;
  1572 + this.base(node);
  1573 +
  1574 + this.render = function(ctx) {
  1575 + // NOOP
  1576 + }
  1577 + }
  1578 + svg.Element.defs.prototype = new svg.Element.ElementBase;
  1579 +
  1580 + // base for gradients
  1581 + svg.Element.GradientBase = function(node) {
  1582 + this.base = svg.Element.ElementBase;
  1583 + this.base(node);
  1584 +
  1585 + this.gradientUnits = this.attribute('gradientUnits').valueOrDefault('objectBoundingBox');
  1586 +
  1587 + this.stops = [];
  1588 + for (var i=0; i<this.children.length; i++) {
  1589 + var child = this.children[i];
  1590 + if (child.type == 'stop') this.stops.push(child);
  1591 + }
  1592 +
  1593 + this.getGradient = function() {
  1594 + // OVERRIDE ME!
  1595 + }
  1596 +
  1597 + this.createGradient = function(ctx, element, parentOpacityProp) {
  1598 + var stopsContainer = this;
  1599 + if (this.getHrefAttribute().hasValue()) {
  1600 + stopsContainer = this.getHrefAttribute().getDefinition();
  1601 + }
  1602 +
  1603 + var addParentOpacity = function (color) {
  1604 + if (parentOpacityProp.hasValue()) {
  1605 + var p = new svg.Property('color', color);
  1606 + return p.addOpacity(parentOpacityProp.value).value;
  1607 + }
  1608 + return color;
  1609 + };
  1610 +
  1611 + var g = this.getGradient(ctx, element);
  1612 + if (g == null) return addParentOpacity(stopsContainer.stops[stopsContainer.stops.length - 1].color);
  1613 + for (var i=0; i<stopsContainer.stops.length; i++) {
  1614 + g.addColorStop(stopsContainer.stops[i].offset, addParentOpacity(stopsContainer.stops[i].color));
  1615 + }
  1616 +
  1617 + if (this.attribute('gradientTransform').hasValue()) {
  1618 + // render as transformed pattern on temporary canvas
  1619 + var rootView = svg.ViewPort.viewPorts[0];
  1620 +
  1621 + var rect = new svg.Element.rect();
  1622 + rect.attributes['x'] = new svg.Property('x', -svg.MAX_VIRTUAL_PIXELS/3.0);
  1623 + rect.attributes['y'] = new svg.Property('y', -svg.MAX_VIRTUAL_PIXELS/3.0);
  1624 + rect.attributes['width'] = new svg.Property('width', svg.MAX_VIRTUAL_PIXELS);
  1625 + rect.attributes['height'] = new svg.Property('height', svg.MAX_VIRTUAL_PIXELS);
  1626 +
  1627 + var group = new svg.Element.g();
  1628 + group.attributes['transform'] = new svg.Property('transform', this.attribute('gradientTransform').value);
  1629 + group.children = [ rect ];
  1630 +
  1631 + var tempSvg = new svg.Element.svg();
  1632 + tempSvg.attributes['x'] = new svg.Property('x', 0);
  1633 + tempSvg.attributes['y'] = new svg.Property('y', 0);
  1634 + tempSvg.attributes['width'] = new svg.Property('width', rootView.width);
  1635 + tempSvg.attributes['height'] = new svg.Property('height', rootView.height);
  1636 + tempSvg.children = [ group ];
  1637 +
  1638 + var c = document.createElement('canvas');
  1639 + c.width = rootView.width;
  1640 + c.height = rootView.height;
  1641 + var tempCtx = c.getContext('2d');
  1642 + tempCtx.fillStyle = g;
  1643 + tempSvg.render(tempCtx);
  1644 + return tempCtx.createPattern(c, 'no-repeat');
  1645 + }
  1646 +
  1647 + return g;
  1648 + }
  1649 + }
  1650 + svg.Element.GradientBase.prototype = new svg.Element.ElementBase;
  1651 +
  1652 + // linear gradient element
  1653 + svg.Element.linearGradient = function(node) {
  1654 + this.base = svg.Element.GradientBase;
  1655 + this.base(node);
  1656 +
  1657 + this.getGradient = function(ctx, element) {
  1658 + var bb = this.gradientUnits == 'objectBoundingBox' ? element.getBoundingBox() : null;
  1659 +
  1660 + if (!this.attribute('x1').hasValue()
  1661 + && !this.attribute('y1').hasValue()
  1662 + && !this.attribute('x2').hasValue()
  1663 + && !this.attribute('y2').hasValue()) {
  1664 + this.attribute('x1', true).value = 0;
  1665 + this.attribute('y1', true).value = 0;
  1666 + this.attribute('x2', true).value = 1;
  1667 + this.attribute('y2', true).value = 0;
  1668 + }
  1669 +
  1670 + var x1 = (this.gradientUnits == 'objectBoundingBox'
  1671 + ? bb.x() + bb.width() * this.attribute('x1').numValue()
  1672 + : this.attribute('x1').toPixels('x'));
  1673 + var y1 = (this.gradientUnits == 'objectBoundingBox'
  1674 + ? bb.y() + bb.height() * this.attribute('y1').numValue()
  1675 + : this.attribute('y1').toPixels('y'));
  1676 + var x2 = (this.gradientUnits == 'objectBoundingBox'
  1677 + ? bb.x() + bb.width() * this.attribute('x2').numValue()
  1678 + : this.attribute('x2').toPixels('x'));
  1679 + var y2 = (this.gradientUnits == 'objectBoundingBox'
  1680 + ? bb.y() + bb.height() * this.attribute('y2').numValue()
  1681 + : this.attribute('y2').toPixels('y'));
  1682 +
  1683 + if (x1 == x2 && y1 == y2) return null;
  1684 + return ctx.createLinearGradient(x1, y1, x2, y2);
  1685 + }
  1686 + }
  1687 + svg.Element.linearGradient.prototype = new svg.Element.GradientBase;
  1688 +
  1689 + // radial gradient element
  1690 + svg.Element.radialGradient = function(node) {
  1691 + this.base = svg.Element.GradientBase;
  1692 + this.base(node);
  1693 +
  1694 + this.getGradient = function(ctx, element) {
  1695 + var bb = element.getBoundingBox();
  1696 +
  1697 + if (!this.attribute('cx').hasValue()) this.attribute('cx', true).value = '50%';
  1698 + if (!this.attribute('cy').hasValue()) this.attribute('cy', true).value = '50%';
  1699 + if (!this.attribute('r').hasValue()) this.attribute('r', true).value = '50%';
  1700 +
  1701 + var cx = (this.gradientUnits == 'objectBoundingBox'
  1702 + ? bb.x() + bb.width() * this.attribute('cx').numValue()
  1703 + : this.attribute('cx').toPixels('x'));
  1704 + var cy = (this.gradientUnits == 'objectBoundingBox'
  1705 + ? bb.y() + bb.height() * this.attribute('cy').numValue()
  1706 + : this.attribute('cy').toPixels('y'));
  1707 +
  1708 + var fx = cx;
  1709 + var fy = cy;
  1710 + if (this.attribute('fx').hasValue()) {
  1711 + fx = (this.gradientUnits == 'objectBoundingBox'
  1712 + ? bb.x() + bb.width() * this.attribute('fx').numValue()
  1713 + : this.attribute('fx').toPixels('x'));
  1714 + }
  1715 + if (this.attribute('fy').hasValue()) {
  1716 + fy = (this.gradientUnits == 'objectBoundingBox'
  1717 + ? bb.y() + bb.height() * this.attribute('fy').numValue()
  1718 + : this.attribute('fy').toPixels('y'));
  1719 + }
  1720 +
  1721 + var r = (this.gradientUnits == 'objectBoundingBox'
  1722 + ? (bb.width() + bb.height()) / 2.0 * this.attribute('r').numValue()
  1723 + : this.attribute('r').toPixels());
  1724 +
  1725 + return ctx.createRadialGradient(fx, fy, 0, cx, cy, r);
  1726 + }
  1727 + }
  1728 + svg.Element.radialGradient.prototype = new svg.Element.GradientBase;
  1729 +
  1730 + // gradient stop element
  1731 + svg.Element.stop = function(node) {
  1732 + this.base = svg.Element.ElementBase;
  1733 + this.base(node);
  1734 +
  1735 + this.offset = this.attribute('offset').numValue();
  1736 + if (this.offset < 0) this.offset = 0;
  1737 + if (this.offset > 1) this.offset = 1;
  1738 +
  1739 + var stopColor = this.style('stop-color');
  1740 + if (this.style('stop-opacity').hasValue()) stopColor = stopColor.addOpacity(this.style('stop-opacity').value);
  1741 + this.color = stopColor.value;
  1742 + }
  1743 + svg.Element.stop.prototype = new svg.Element.ElementBase;
  1744 +
  1745 + // animation base element
  1746 + svg.Element.AnimateBase = function(node) {
  1747 + this.base = svg.Element.ElementBase;
  1748 + this.base(node);
  1749 +
  1750 + svg.Animations.push(this);
  1751 +
  1752 + this.duration = 0.0;
  1753 + this.begin = this.attribute('begin').toMilliseconds();
  1754 + this.maxDuration = this.begin + this.attribute('dur').toMilliseconds();
  1755 +
  1756 + this.getProperty = function() {
  1757 + var attributeType = this.attribute('attributeType').value;
  1758 + var attributeName = this.attribute('attributeName').value;
  1759 +
  1760 + if (attributeType == 'CSS') {
  1761 + return this.parent.style(attributeName, true);
  1762 + }
  1763 + return this.parent.attribute(attributeName, true);
  1764 + };
  1765 +
  1766 + this.initialValue = null;
  1767 + this.initialUnits = '';
  1768 + this.removed = false;
  1769 +
  1770 + this.calcValue = function() {
  1771 + // OVERRIDE ME!
  1772 + return '';
  1773 + }
  1774 +
  1775 + this.update = function(delta) {
  1776 + // set initial value
  1777 + if (this.initialValue == null) {
  1778 + this.initialValue = this.getProperty().value;
  1779 + this.initialUnits = this.getProperty().getUnits();
  1780 + }
  1781 +
  1782 + // if we're past the end time
  1783 + if (this.duration > this.maxDuration) {
  1784 + // loop for indefinitely repeating animations
  1785 + if (this.attribute('repeatCount').value == 'indefinite'
  1786 + || this.attribute('repeatDur').value == 'indefinite') {
  1787 + this.duration = 0.0
  1788 + }
  1789 + else if (this.attribute('fill').valueOrDefault('remove') == 'remove' && !this.removed) {
  1790 + this.removed = true;
  1791 + this.getProperty().value = this.initialValue;
  1792 + return true;
  1793 + }
  1794 + else {
  1795 + return false; // no updates made
  1796 + }
  1797 + }
  1798 + this.duration = this.duration + delta;
  1799 +
  1800 + // if we're past the begin time
  1801 + var updated = false;
  1802 + if (this.begin < this.duration) {
  1803 + var newValue = this.calcValue(); // tween
  1804 +
  1805 + if (this.attribute('type').hasValue()) {
  1806 + // for transform, etc.
  1807 + var type = this.attribute('type').value;
  1808 + newValue = type + '(' + newValue + ')';
  1809 + }
  1810 +
  1811 + this.getProperty().value = newValue;
  1812 + updated = true;
  1813 + }
  1814 +
  1815 + return updated;
  1816 + }
  1817 +
  1818 + this.from = this.attribute('from');
  1819 + this.to = this.attribute('to');
  1820 + this.values = this.attribute('values');
  1821 + if (this.values.hasValue()) this.values.value = this.values.value.split(';');
  1822 +
  1823 + // fraction of duration we've covered
  1824 + this.progress = function() {
  1825 + var ret = { progress: (this.duration - this.begin) / (this.maxDuration - this.begin) };
  1826 + if (this.values.hasValue()) {
  1827 + var p = ret.progress * (this.values.value.length - 1);
  1828 + var lb = Math.floor(p), ub = Math.ceil(p);
  1829 + ret.from = new svg.Property('from', parseFloat(this.values.value[lb]));
  1830 + ret.to = new svg.Property('to', parseFloat(this.values.value[ub]));
  1831 + ret.progress = (p - lb) / (ub - lb);
  1832 + }
  1833 + else {
  1834 + ret.from = this.from;
  1835 + ret.to = this.to;
  1836 + }
  1837 + return ret;
  1838 + }
  1839 + }
  1840 + svg.Element.AnimateBase.prototype = new svg.Element.ElementBase;
  1841 +
  1842 + // animate element
  1843 + svg.Element.animate = function(node) {
  1844 + this.base = svg.Element.AnimateBase;
  1845 + this.base(node);
  1846 +
  1847 + this.calcValue = function() {
  1848 + var p = this.progress();
  1849 +
  1850 + // tween value linearly
  1851 + var newValue = p.from.numValue() + (p.to.numValue() - p.from.numValue()) * p.progress;
  1852 + return newValue + this.initialUnits;
  1853 + };
  1854 + }
  1855 + svg.Element.animate.prototype = new svg.Element.AnimateBase;
  1856 +
  1857 + // animate color element
  1858 + svg.Element.animateColor = function(node) {
  1859 + this.base = svg.Element.AnimateBase;
  1860 + this.base(node);
  1861 +
  1862 + this.calcValue = function() {
  1863 + var p = this.progress();
  1864 + var from = new RGBColor(p.from.value);
  1865 + var to = new RGBColor(p.to.value);
  1866 +
  1867 + if (from.ok && to.ok) {
  1868 + // tween color linearly
  1869 + var r = from.r + (to.r - from.r) * p.progress;
  1870 + var g = from.g + (to.g - from.g) * p.progress;
  1871 + var b = from.b + (to.b - from.b) * p.progress;
  1872 + return 'rgb('+parseInt(r,10)+','+parseInt(g,10)+','+parseInt(b,10)+')';
  1873 + }
  1874 + return this.attribute('from').value;
  1875 + };
  1876 + }
  1877 + svg.Element.animateColor.prototype = new svg.Element.AnimateBase;
  1878 +
  1879 + // animate transform element
  1880 + svg.Element.animateTransform = function(node) {
  1881 + this.base = svg.Element.AnimateBase;
  1882 + this.base(node);
  1883 +
  1884 + this.calcValue = function() {
  1885 + var p = this.progress();
  1886 +
  1887 + // tween value linearly
  1888 + var from = svg.ToNumberArray(p.from.value);
  1889 + var to = svg.ToNumberArray(p.to.value);
  1890 + var newValue = '';
  1891 + for (var i=0; i<from.length; i++) {
  1892 + newValue += from[i] + (to[i] - from[i]) * p.progress + ' ';
  1893 + }
  1894 + return newValue;
  1895 + };
  1896 + }
  1897 + svg.Element.animateTransform.prototype = new svg.Element.animate;
  1898 +
  1899 + // font element
  1900 + svg.Element.font = function(node) {
  1901 + this.base = svg.Element.ElementBase;
  1902 + this.base(node);
  1903 +
  1904 + this.horizAdvX = this.attribute('horiz-adv-x').numValue();
  1905 +
  1906 + this.isRTL = false;
  1907 + this.isArabic = false;
  1908 + this.fontFace = null;
  1909 + this.missingGlyph = null;
  1910 + this.glyphs = [];
  1911 + for (var i=0; i<this.children.length; i++) {
  1912 + var child = this.children[i];
  1913 + if (child.type == 'font-face') {
  1914 + this.fontFace = child;
  1915 + if (child.style('font-family').hasValue()) {
  1916 + svg.Definitions[child.style('font-family').value] = this;
  1917 + }
  1918 + }
  1919 + else if (child.type == 'missing-glyph') this.missingGlyph = child;
  1920 + else if (child.type == 'glyph') {
  1921 + if (child.arabicForm != '') {
  1922 + this.isRTL = true;
  1923 + this.isArabic = true;
  1924 + if (typeof(this.glyphs[child.unicode]) == 'undefined') this.glyphs[child.unicode] = [];
  1925 + this.glyphs[child.unicode][child.arabicForm] = child;
  1926 + }
  1927 + else {
  1928 + this.glyphs[child.unicode] = child;
  1929 + }
  1930 + }
  1931 + }
  1932 + }
  1933 + svg.Element.font.prototype = new svg.Element.ElementBase;
  1934 +
  1935 + // font-face element
  1936 + svg.Element.fontface = function(node) {
  1937 + this.base = svg.Element.ElementBase;
  1938 + this.base(node);
  1939 +
  1940 + this.ascent = this.attribute('ascent').value;
  1941 + this.descent = this.attribute('descent').value;
  1942 + this.unitsPerEm = this.attribute('units-per-em').numValue();
  1943 + }
  1944 + svg.Element.fontface.prototype = new svg.Element.ElementBase;
  1945 +
  1946 + // missing-glyph element
  1947 + svg.Element.missingglyph = function(node) {
  1948 + this.base = svg.Element.path;
  1949 + this.base(node);
  1950 +
  1951 + this.horizAdvX = 0;
  1952 + }
  1953 + svg.Element.missingglyph.prototype = new svg.Element.path;
  1954 +
  1955 + // glyph element
  1956 + svg.Element.glyph = function(node) {
  1957 + this.base = svg.Element.path;
  1958 + this.base(node);
  1959 +
  1960 + this.horizAdvX = this.attribute('horiz-adv-x').numValue();
  1961 + this.unicode = this.attribute('unicode').value;
  1962 + this.arabicForm = this.attribute('arabic-form').value;
  1963 + }
  1964 + svg.Element.glyph.prototype = new svg.Element.path;
  1965 +
  1966 + // text element
  1967 + svg.Element.text = function(node) {
  1968 + this.captureTextNodes = true;
  1969 + this.base = svg.Element.RenderedElementBase;
  1970 + this.base(node);
  1971 +
  1972 + this.baseSetContext = this.setContext;
  1973 + this.setContext = function(ctx) {
  1974 + this.baseSetContext(ctx);
  1975 + if (this.style('dominant-baseline').hasValue()) ctx.textBaseline = this.style('dominant-baseline').value;
  1976 + if (this.style('alignment-baseline').hasValue()) ctx.textBaseline = this.style('alignment-baseline').value;
  1977 + }
  1978 +
  1979 + this.getBoundingBox = function () {
  1980 + var x = this.attribute('x').toPixels('x');
  1981 + var y = this.attribute('y').toPixels('y');
  1982 + var fontSize = this.parent.style('font-size').numValueOrDefault(svg.Font.Parse(svg.ctx.font).fontSize);
  1983 + return new svg.BoundingBox(x, y - fontSize, x + Math.floor(fontSize * 2.0 / 3.0) * this.children[0].getText().length, y);
  1984 + }
  1985 +
  1986 + this.renderChildren = function(ctx) {
  1987 + this.x = this.attribute('x').toPixels('x');
  1988 + this.y = this.attribute('y').toPixels('y');
  1989 + this.x += this.getAnchorDelta(ctx, this, 0);
  1990 + for (var i=0; i<this.children.length; i++) {
  1991 + this.renderChild(ctx, this, i);
  1992 + }
  1993 + }
  1994 +
  1995 + this.getAnchorDelta = function (ctx, parent, startI) {
  1996 + var textAnchor = this.style('text-anchor').valueOrDefault('start');
  1997 + if (textAnchor != 'start') {
  1998 + var width = 0;
  1999 + for (var i=startI; i<parent.children.length; i++) {
  2000 + var child = parent.children[i];
  2001 + if (i > startI && child.attribute('x').hasValue()) break; // new group
  2002 + width += child.measureTextRecursive(ctx);
  2003 + }
  2004 + return -1 * (textAnchor == 'end' ? width : width / 2.0);
  2005 + }
  2006 + return 0;
  2007 + }
  2008 +
  2009 + this.renderChild = function(ctx, parent, i) {
  2010 + var child = parent.children[i];
  2011 + if (child.attribute('x').hasValue()) {
  2012 + child.x = child.attribute('x').toPixels('x') + this.getAnchorDelta(ctx, parent, i);
  2013 + }
  2014 + else {
  2015 + if (this.attribute('dx').hasValue()) this.x += this.attribute('dx').toPixels('x');
  2016 + if (child.attribute('dx').hasValue()) this.x += child.attribute('dx').toPixels('x');
  2017 + child.x = this.x;
  2018 + }
  2019 + this.x = child.x + child.measureText(ctx);
  2020 +
  2021 + if (child.attribute('y').hasValue()) {
  2022 + child.y = child.attribute('y').toPixels('y');
  2023 + }
  2024 + else {
  2025 + if (this.attribute('dy').hasValue()) this.y += this.attribute('dy').toPixels('y');
  2026 + if (child.attribute('dy').hasValue()) this.y += child.attribute('dy').toPixels('y');
  2027 + child.y = this.y;
  2028 + }
  2029 + this.y = child.y;
  2030 +
  2031 + child.render(ctx);
  2032 +
  2033 + for (var i=0; i<child.children.length; i++) {
  2034 + this.renderChild(ctx, child, i);
  2035 + }
  2036 + }
  2037 + }
  2038 + svg.Element.text.prototype = new svg.Element.RenderedElementBase;
  2039 +
  2040 + // text base
  2041 + svg.Element.TextElementBase = function(node) {
  2042 + this.base = svg.Element.RenderedElementBase;
  2043 + this.base(node);
  2044 +
  2045 + this.getGlyph = function(font, text, i) {
  2046 + var c = text[i];
  2047 + var glyph = null;
  2048 + if (font.isArabic) {
  2049 + var arabicForm = 'isolated';
  2050 + if ((i==0 || text[i-1]==' ') && i<text.length-2 && text[i+1]!=' ') arabicForm = 'terminal';
  2051 + if (i>0 && text[i-1]!=' ' && i<text.length-2 && text[i+1]!=' ') arabicForm = 'medial';
  2052 + if (i>0 && text[i-1]!=' ' && (i == text.length-1 || text[i+1]==' ')) arabicForm = 'initial';
  2053 + if (typeof(font.glyphs[c]) != 'undefined') {
  2054 + glyph = font.glyphs[c][arabicForm];
  2055 + if (glyph == null && font.glyphs[c].type == 'glyph') glyph = font.glyphs[c];
  2056 + }
  2057 + }
  2058 + else {
  2059 + glyph = font.glyphs[c];
  2060 + }
  2061 + if (glyph == null) glyph = font.missingGlyph;
  2062 + return glyph;
  2063 + }
  2064 +
  2065 + this.renderChildren = function(ctx) {
  2066 + var customFont = this.parent.style('font-family').getDefinition();
  2067 + if (customFont != null) {
  2068 + var fontSize = this.parent.style('font-size').numValueOrDefault(svg.Font.Parse(svg.ctx.font).fontSize);
  2069 + var fontStyle = this.parent.style('font-style').valueOrDefault(svg.Font.Parse(svg.ctx.font).fontStyle);
  2070 + var text = this.getText();
  2071 + if (customFont.isRTL) text = text.split("").reverse().join("");
  2072 +
  2073 + var dx = svg.ToNumberArray(this.parent.attribute('dx').value);
  2074 + for (var i=0; i<text.length; i++) {
  2075 + var glyph = this.getGlyph(customFont, text, i);
  2076 + var scale = fontSize / customFont.fontFace.unitsPerEm;
  2077 + ctx.translate(this.x, this.y);
  2078 + ctx.scale(scale, -scale);
  2079 + var lw = ctx.lineWidth;
  2080 + ctx.lineWidth = ctx.lineWidth * customFont.fontFace.unitsPerEm / fontSize;
  2081 + if (fontStyle == 'italic') ctx.transform(1, 0, .4, 1, 0, 0);
  2082 + glyph.render(ctx);
  2083 + if (fontStyle == 'italic') ctx.transform(1, 0, -.4, 1, 0, 0);
  2084 + ctx.lineWidth = lw;
  2085 + ctx.scale(1/scale, -1/scale);
  2086 + ctx.translate(-this.x, -this.y);
  2087 +
  2088 + this.x += fontSize * (glyph.horizAdvX || customFont.horizAdvX) / customFont.fontFace.unitsPerEm;
  2089 + if (typeof(dx[i]) != 'undefined' && !isNaN(dx[i])) {
  2090 + this.x += dx[i];
  2091 + }
  2092 + }
  2093 + return;
  2094 + }
  2095 +
  2096 + if (ctx.fillStyle != '') ctx.fillText(svg.compressSpaces(this.getText()), this.x, this.y);
  2097 + if (ctx.strokeStyle != '') ctx.strokeText(svg.compressSpaces(this.getText()), this.x, this.y);
  2098 + }
  2099 +
  2100 + this.getText = function() {
  2101 + // OVERRIDE ME
  2102 + }
  2103 +
  2104 + this.measureTextRecursive = function(ctx) {
  2105 + var width = this.measureText(ctx);
  2106 + for (var i=0; i<this.children.length; i++) {
  2107 + width += this.children[i].measureTextRecursive(ctx);
  2108 + }
  2109 + return width;
  2110 + }
  2111 +
  2112 + this.measureText = function(ctx) {
  2113 + var customFont = this.parent.style('font-family').getDefinition();
  2114 + if (customFont != null) {
  2115 + var fontSize = this.parent.style('font-size').numValueOrDefault(svg.Font.Parse(svg.ctx.font).fontSize);
  2116 + var measure = 0;
  2117 + var text = this.getText();
  2118 + if (customFont.isRTL) text = text.split("").reverse().join("");
  2119 + var dx = svg.ToNumberArray(this.parent.attribute('dx').value);
  2120 + for (var i=0; i<text.length; i++) {
  2121 + var glyph = this.getGlyph(customFont, text, i);
  2122 + measure += (glyph.horizAdvX || customFont.horizAdvX) * fontSize / customFont.fontFace.unitsPerEm;
  2123 + if (typeof(dx[i]) != 'undefined' && !isNaN(dx[i])) {
  2124 + measure += dx[i];
  2125 + }
  2126 + }
  2127 + return measure;
  2128 + }
  2129 +
  2130 + var textToMeasure = svg.compressSpaces(this.getText());
  2131 + if (!ctx.measureText) return textToMeasure.length * 10;
  2132 +
  2133 + ctx.save();
  2134 + this.setContext(ctx);
  2135 + var width = ctx.measureText(textToMeasure).width;
  2136 + ctx.restore();
  2137 + return width;
  2138 + }
  2139 + }
  2140 + svg.Element.TextElementBase.prototype = new svg.Element.RenderedElementBase;
  2141 +
  2142 + // tspan
  2143 + svg.Element.tspan = function(node) {
  2144 + this.captureTextNodes = true;
  2145 + this.base = svg.Element.TextElementBase;
  2146 + this.base(node);
  2147 +
  2148 + this.text = node.nodeValue || node.text || '';
  2149 + this.getText = function() {
  2150 + return this.text;
  2151 + }
  2152 + }
  2153 + svg.Element.tspan.prototype = new svg.Element.TextElementBase;
  2154 +
  2155 + // tref
  2156 + svg.Element.tref = function(node) {
  2157 + this.base = svg.Element.TextElementBase;
  2158 + this.base(node);
  2159 +
  2160 + this.getText = function() {
  2161 + var element = this.getHrefAttribute().getDefinition();
  2162 + if (element != null) return element.children[0].getText();
  2163 + }
  2164 + }
  2165 + svg.Element.tref.prototype = new svg.Element.TextElementBase;
  2166 +
  2167 + // a element
  2168 + svg.Element.a = function(node) {
  2169 + this.base = svg.Element.TextElementBase;
  2170 + this.base(node);
  2171 +
  2172 + this.hasText = true;
  2173 + for (var i=0; i<node.childNodes.length; i++) {
  2174 + if (node.childNodes[i].nodeType != 3) this.hasText = false;
  2175 + }
  2176 +
  2177 + // this might contain text
  2178 + this.text = this.hasText ? node.childNodes[0].nodeValue : '';
  2179 + this.getText = function() {
  2180 + return this.text;
  2181 + }
  2182 +
  2183 + this.baseRenderChildren = this.renderChildren;
  2184 + this.renderChildren = function(ctx) {
  2185 + if (this.hasText) {
  2186 + // render as text element
  2187 + this.baseRenderChildren(ctx);
  2188 + var fontSize = new svg.Property('fontSize', svg.Font.Parse(svg.ctx.font).fontSize);
  2189 + svg.Mouse.checkBoundingBox(this, new svg.BoundingBox(this.x, this.y - fontSize.toPixels('y'), this.x + this.measureText(ctx), this.y));
  2190 + }
  2191 + else {
  2192 + // render as temporary group
  2193 + var g = new svg.Element.g();
  2194 + g.children = this.children;
  2195 + g.parent = this;
  2196 + g.render(ctx);
  2197 + }
  2198 + }
  2199 +
  2200 + this.onclick = function() {
  2201 + window.open(this.getHrefAttribute().value);
  2202 + }
  2203 +
  2204 + this.onmousemove = function() {
  2205 + svg.ctx.canvas.style.cursor = 'pointer';
  2206 + }
  2207 + }
  2208 + svg.Element.a.prototype = new svg.Element.TextElementBase;
  2209 +
  2210 + // image element
  2211 + svg.Element.image = function(node) {
  2212 + this.base = svg.Element.RenderedElementBase;
  2213 + this.base(node);
  2214 +
  2215 + var href = this.getHrefAttribute().value;
  2216 + var isSvg = href.match(/\.svg$/)
  2217 +
  2218 + svg.Images.push(this);
  2219 + this.loaded = false;
  2220 + if (!isSvg) {
  2221 + this.img = document.createElement('img');
  2222 + var self = this;
  2223 + this.img.onload = function() { self.loaded = true; }
  2224 + this.img.onerror = function() { if (typeof(console) != 'undefined') { console.log('ERROR: image "' + href + '" not found'); self.loaded = true; } }
  2225 + this.img.src = href;
  2226 + }
  2227 + else {
  2228 + this.img = svg.ajax(href);
  2229 + this.loaded = true;
  2230 + }
  2231 +
  2232 + this.renderChildren = function(ctx) {
  2233 + var x = this.attribute('x').toPixels('x');
  2234 + var y = this.attribute('y').toPixels('y');
  2235 +
  2236 + var width = this.attribute('width').toPixels('x');
  2237 + var height = this.attribute('height').toPixels('y');
  2238 + if (width == 0 || height == 0) return;
  2239 +
  2240 + ctx.save();
  2241 + if (isSvg) {
  2242 + ctx.drawSvg(this.img, x, y, width, height);
  2243 + }
  2244 + else {
  2245 + ctx.translate(x, y);
  2246 + svg.AspectRatio(ctx,
  2247 + this.attribute('preserveAspectRatio').value,
  2248 + width,
  2249 + this.img.width,
  2250 + height,
  2251 + this.img.height,
  2252 + 0,
  2253 + 0);
  2254 + ctx.drawImage(this.img, 0, 0);
  2255 + }
  2256 + ctx.restore();
  2257 + }
  2258 +
  2259 + this.getBoundingBox = function() {
  2260 + var x = this.attribute('x').toPixels('x');
  2261 + var y = this.attribute('y').toPixels('y');
  2262 + var width = this.attribute('width').toPixels('x');
  2263 + var height = this.attribute('height').toPixels('y');
  2264 + return new svg.BoundingBox(x, y, x + width, y + height);
  2265 + }
  2266 + }
  2267 + svg.Element.image.prototype = new svg.Element.RenderedElementBase;
  2268 +
  2269 + // group element
  2270 + svg.Element.g = function(node) {
  2271 + this.base = svg.Element.RenderedElementBase;
  2272 + this.base(node);
  2273 +
  2274 + this.getBoundingBox = function() {
  2275 + var bb = new svg.BoundingBox();
  2276 + for (var i=0; i<this.children.length; i++) {
  2277 + bb.addBoundingBox(this.children[i].getBoundingBox());
  2278 + }
  2279 + return bb;
  2280 + };
  2281 + }
  2282 + svg.Element.g.prototype = new svg.Element.RenderedElementBase;
  2283 +
  2284 + // symbol element
  2285 + svg.Element.symbol = function(node) {
  2286 + this.base = svg.Element.RenderedElementBase;
  2287 + this.base(node);
  2288 +
  2289 + this.baseSetContext = this.setContext;
  2290 + this.setContext = function(ctx) {
  2291 + this.baseSetContext(ctx);
  2292 +
  2293 + // viewbox
  2294 + if (this.attribute('viewBox').hasValue()) {
  2295 + var viewBox = svg.ToNumberArray(this.attribute('viewBox').value);
  2296 + var minX = viewBox[0];
  2297 + var minY = viewBox[1];
  2298 + width = viewBox[2];
  2299 + height = viewBox[3];
  2300 +
  2301 + svg.AspectRatio(ctx,
  2302 + this.attribute('preserveAspectRatio').value,
  2303 + this.attribute('width').toPixels('x'),
  2304 + width,
  2305 + this.attribute('height').toPixels('y'),
  2306 + height,
  2307 + minX,
  2308 + minY);
  2309 +
  2310 + svg.ViewPort.SetCurrent(viewBox[2], viewBox[3]);
  2311 + }
  2312 + }
  2313 + }
  2314 + svg.Element.symbol.prototype = new svg.Element.RenderedElementBase;
  2315 +
  2316 + // style element
  2317 + svg.Element.style = function(node) {
  2318 + this.base = svg.Element.ElementBase;
  2319 + this.base(node);
  2320 +
  2321 + // text, or spaces then CDATA
  2322 + var css = ''
  2323 + for (var i=0; i<node.childNodes.length; i++) {
  2324 + css += node.childNodes[i].nodeValue;
  2325 + }
  2326 + css = css.replace(/(\/\*([^*]|[\r\n]|(\*+([^*\/]|[\r\n])))*\*+\/)|(^[\s]*\/\/.*)/gm, ''); // remove comments
  2327 + css = svg.compressSpaces(css); // replace whitespace
  2328 + var cssDefs = css.split('}');
  2329 + for (var i=0; i<cssDefs.length; i++) {
  2330 + if (svg.trim(cssDefs[i]) != '') {
  2331 + var cssDef = cssDefs[i].split('{');
  2332 + var cssClasses = cssDef[0].split(',');
  2333 + var cssProps = cssDef[1].split(';');
  2334 + for (var j=0; j<cssClasses.length; j++) {
  2335 + var cssClass = svg.trim(cssClasses[j]);
  2336 + if (cssClass != '') {
  2337 + var props = {};
  2338 + for (var k=0; k<cssProps.length; k++) {
  2339 + var prop = cssProps[k].indexOf(':');
  2340 + var name = cssProps[k].substr(0, prop);
  2341 + var value = cssProps[k].substr(prop + 1, cssProps[k].length - prop);
  2342 + if (name != null && value != null) {
  2343 + props[svg.trim(name)] = new svg.Property(svg.trim(name), svg.trim(value));
  2344 + }
  2345 + }
  2346 + svg.Styles[cssClass] = props;
  2347 + if (cssClass == '@font-face') {
  2348 + var fontFamily = props['font-family'].value.replace(/"/g,'');
  2349 + var srcs = props['src'].value.split(',');
  2350 + for (var s=0; s<srcs.length; s++) {
  2351 + if (srcs[s].indexOf('format("svg")') > 0) {
  2352 + var urlStart = srcs[s].indexOf('url');
  2353 + var urlEnd = srcs[s].indexOf(')', urlStart);
  2354 + var url = srcs[s].substr(urlStart + 5, urlEnd - urlStart - 6);
  2355 + var doc = svg.parseXml(svg.ajax(url));
  2356 + var fonts = doc.getElementsByTagName('font');
  2357 + for (var f=0; f<fonts.length; f++) {
  2358 + var font = svg.CreateElement(fonts[f]);
  2359 + svg.Definitions[fontFamily] = font;
  2360 + }
  2361 + }
  2362 + }
  2363 + }
  2364 + }
  2365 + }
  2366 + }
  2367 + }
  2368 + }
  2369 + svg.Element.style.prototype = new svg.Element.ElementBase;
  2370 +
  2371 + // use element
  2372 + svg.Element.use = function(node) {
  2373 + this.base = svg.Element.RenderedElementBase;
  2374 + this.base(node);
  2375 +
  2376 + this.baseSetContext = this.setContext;
  2377 + this.setContext = function(ctx) {
  2378 + this.baseSetContext(ctx);
  2379 + if (this.attribute('x').hasValue()) ctx.translate(this.attribute('x').toPixels('x'), 0);
  2380 + if (this.attribute('y').hasValue()) ctx.translate(0, this.attribute('y').toPixels('y'));
  2381 + }
  2382 +
  2383 + this.getDefinition = function() {
  2384 + var element = this.getHrefAttribute().getDefinition();
  2385 + if (this.attribute('width').hasValue()) element.attribute('width', true).value = this.attribute('width').value;
  2386 + if (this.attribute('height').hasValue()) element.attribute('height', true).value = this.attribute('height').value;
  2387 + return element;
  2388 + }
  2389 +
  2390 + this.path = function(ctx) {
  2391 + var element = this.getDefinition();
  2392 + if (element != null) element.path(ctx);
  2393 + }
  2394 +
  2395 + this.getBoundingBox = function() {
  2396 + var element = this.getDefinition();
  2397 + if (element != null) return element.getBoundingBox();
  2398 + }
  2399 +
  2400 + this.renderChildren = function(ctx) {
  2401 + var element = this.getDefinition();
  2402 + if (element != null) {
  2403 + // temporarily detach from parent and render
  2404 + var oldParent = element.parent;
  2405 + element.parent = null;
  2406 + element.render(ctx);
  2407 + element.parent = oldParent;
  2408 + }
  2409 + }
  2410 + }
  2411 + svg.Element.use.prototype = new svg.Element.RenderedElementBase;
  2412 +
  2413 + // mask element
  2414 + svg.Element.mask = function(node) {
  2415 + this.base = svg.Element.ElementBase;
  2416 + this.base(node);
  2417 +
  2418 + this.apply = function(ctx, element) {
  2419 + // render as temp svg
  2420 + var x = this.attribute('x').toPixels('x');
  2421 + var y = this.attribute('y').toPixels('y');
  2422 + var width = this.attribute('width').toPixels('x');
  2423 + var height = this.attribute('height').toPixels('y');
  2424 +
  2425 + if (width == 0 && height == 0) {
  2426 + var bb = new svg.BoundingBox();
  2427 + for (var i=0; i<this.children.length; i++) {
  2428 + bb.addBoundingBox(this.children[i].getBoundingBox());
  2429 + }
  2430 + var x = Math.floor(bb.x1);
  2431 + var y = Math.floor(bb.y1);
  2432 + var width = Math.floor(bb.width());
  2433 + var height = Math.floor(bb.height());
  2434 + }
  2435 +
  2436 + // temporarily remove mask to avoid recursion
  2437 + var mask = element.attribute('mask').value;
  2438 + element.attribute('mask').value = '';
  2439 +
  2440 + var cMask = document.createElement('canvas');
  2441 + cMask.width = x + width;
  2442 + cMask.height = y + height;
  2443 + var maskCtx = cMask.getContext('2d');
  2444 + this.renderChildren(maskCtx);
  2445 +
  2446 + var c = document.createElement('canvas');
  2447 + c.width = x + width;
  2448 + c.height = y + height;
  2449 + var tempCtx = c.getContext('2d');
  2450 + element.render(tempCtx);
  2451 + tempCtx.globalCompositeOperation = 'destination-in';
  2452 + tempCtx.fillStyle = maskCtx.createPattern(cMask, 'no-repeat');
  2453 + tempCtx.fillRect(0, 0, x + width, y + height);
  2454 +
  2455 + ctx.fillStyle = tempCtx.createPattern(c, 'no-repeat');
  2456 + ctx.fillRect(0, 0, x + width, y + height);
  2457 +
  2458 + // reassign mask
  2459 + element.attribute('mask').value = mask;
  2460 + }
  2461 +
  2462 + this.render = function(ctx) {
  2463 + // NO RENDER
  2464 + }
  2465 + }
  2466 + svg.Element.mask.prototype = new svg.Element.ElementBase;
  2467 +
  2468 + // clip element
  2469 + svg.Element.clipPath = function(node) {
  2470 + this.base = svg.Element.ElementBase;
  2471 + this.base(node);
  2472 +
  2473 + this.apply = function(ctx) {
  2474 + for (var i=0; i<this.children.length; i++) {
  2475 + var child = this.children[i];
  2476 + if (typeof(child.path) != 'undefined') {
  2477 + var transform = null;
  2478 + if (child.attribute('transform').hasValue()) {
  2479 + transform = new svg.Transform(child.attribute('transform').value);
  2480 + transform.apply(ctx);
  2481 + }
  2482 + child.path(ctx);
  2483 + ctx.clip();
  2484 + if (transform) { transform.unapply(ctx); }
  2485 + }
  2486 + }
  2487 + }
  2488 +
  2489 + this.render = function(ctx) {
  2490 + // NO RENDER
  2491 + }
  2492 + }
  2493 + svg.Element.clipPath.prototype = new svg.Element.ElementBase;
  2494 +
  2495 + // filters
  2496 + svg.Element.filter = function(node) {
  2497 + this.base = svg.Element.ElementBase;
  2498 + this.base(node);
  2499 +
  2500 + this.apply = function(ctx, element) {
  2501 + // render as temp svg
  2502 + var bb = element.getBoundingBox();
  2503 + var x = Math.floor(bb.x1);
  2504 + var y = Math.floor(bb.y1);
  2505 + var width = Math.floor(bb.width());
  2506 + var height = Math.floor(bb.height());
  2507 +
  2508 + // temporarily remove filter to avoid recursion
  2509 + var filter = element.style('filter').value;
  2510 + element.style('filter').value = '';
  2511 +
  2512 + var px = 0, py = 0;
  2513 + for (var i=0; i<this.children.length; i++) {
  2514 + var efd = this.children[i].extraFilterDistance || 0;
  2515 + px = Math.max(px, efd);
  2516 + py = Math.max(py, efd);
  2517 + }
  2518 +
  2519 + var c = document.createElement('canvas');
  2520 + c.width = width + 2*px;
  2521 + c.height = height + 2*py;
  2522 + var tempCtx = c.getContext('2d');
  2523 + tempCtx.translate(-x + px, -y + py);
  2524 + element.render(tempCtx);
  2525 +
  2526 + // apply filters
  2527 + for (var i=0; i<this.children.length; i++) {
  2528 + this.children[i].apply(tempCtx, 0, 0, width + 2*px, height + 2*py);
  2529 + }
  2530 +
  2531 + // render on me
  2532 + ctx.drawImage(c, 0, 0, width + 2*px, height + 2*py, x - px, y - py, width + 2*px, height + 2*py);
  2533 +
  2534 + // reassign filter
  2535 + element.style('filter', true).value = filter;
  2536 + }
  2537 +
  2538 + this.render = function(ctx) {
  2539 + // NO RENDER
  2540 + }
  2541 + }
  2542 + svg.Element.filter.prototype = new svg.Element.ElementBase;
  2543 +
  2544 + svg.Element.feMorphology = function(node) {
  2545 + this.base = svg.Element.ElementBase;
  2546 + this.base(node);
  2547 +
  2548 + this.apply = function(ctx, x, y, width, height) {
  2549 + // TODO: implement
  2550 + }
  2551 + }
  2552 + svg.Element.feMorphology.prototype = new svg.Element.ElementBase;
  2553 +
  2554 + svg.Element.feComposite = function(node) {
  2555 + this.base = svg.Element.ElementBase;
  2556 + this.base(node);
  2557 +
  2558 + this.apply = function(ctx, x, y, width, height) {
  2559 + // TODO: implement
  2560 + }
  2561 + }
  2562 + svg.Element.feComposite.prototype = new svg.Element.ElementBase;
  2563 +
  2564 + svg.Element.feColorMatrix = function(node) {
  2565 + this.base = svg.Element.ElementBase;
  2566 + this.base(node);
  2567 +
  2568 + var matrix = svg.ToNumberArray(this.attribute('values').value);
  2569 + switch (this.attribute('type').valueOrDefault('matrix')) { // http://www.w3.org/TR/SVG/filters.html#feColorMatrixElement
  2570 + case 'saturate':
  2571 + var s = matrix[0];
  2572 + matrix = [0.213+0.787*s,0.715-0.715*s,0.072-0.072*s,0,0,
  2573 + 0.213-0.213*s,0.715+0.285*s,0.072-0.072*s,0,0,
  2574 + 0.213-0.213*s,0.715-0.715*s,0.072+0.928*s,0,0,
  2575 + 0,0,0,1,0,
  2576 + 0,0,0,0,1];
  2577 + break;
  2578 + case 'hueRotate':
  2579 + var a = matrix[0] * Math.PI / 180.0;
  2580 + var c = function (m1,m2,m3) { return m1 + Math.cos(a)*m2 + Math.sin(a)*m3; };
  2581 + matrix = [c(0.213,0.787,-0.213),c(0.715,-0.715,-0.715),c(0.072,-0.072,0.928),0,0,
  2582 + c(0.213,-0.213,0.143),c(0.715,0.285,0.140),c(0.072,-0.072,-0.283),0,0,
  2583 + c(0.213,-0.213,-0.787),c(0.715,-0.715,0.715),c(0.072,0.928,0.072),0,0,
  2584 + 0,0,0,1,0,
  2585 + 0,0,0,0,1];
  2586 + break;
  2587 + case 'luminanceToAlpha':
  2588 + matrix = [0,0,0,0,0,
  2589 + 0,0,0,0,0,
  2590 + 0,0,0,0,0,
  2591 + 0.2125,0.7154,0.0721,0,0,
  2592 + 0,0,0,0,1];
  2593 + break;
  2594 + }
  2595 +
  2596 + function imGet(img, x, y, width, height, rgba) {
  2597 + return img[y*width*4 + x*4 + rgba];
  2598 + }
  2599 +
  2600 + function imSet(img, x, y, width, height, rgba, val) {
  2601 + img[y*width*4 + x*4 + rgba] = val;
  2602 + }
  2603 +
  2604 + function m(i, v) {
  2605 + var mi = matrix[i];
  2606 + return mi * (mi < 0 ? v - 255 : v);
  2607 + }
  2608 +
  2609 + this.apply = function(ctx, x, y, width, height) {
  2610 + // assuming x==0 && y==0 for now
  2611 + var srcData = ctx.getImageData(0, 0, width, height);
  2612 + for (var y = 0; y < height; y++) {
  2613 + for (var x = 0; x < width; x++) {
  2614 + var r = imGet(srcData.data, x, y, width, height, 0);
  2615 + var g = imGet(srcData.data, x, y, width, height, 1);
  2616 + var b = imGet(srcData.data, x, y, width, height, 2);
  2617 + var a = imGet(srcData.data, x, y, width, height, 3);
  2618 + imSet(srcData.data, x, y, width, height, 0, m(0,r)+m(1,g)+m(2,b)+m(3,a)+m(4,1));
  2619 + imSet(srcData.data, x, y, width, height, 1, m(5,r)+m(6,g)+m(7,b)+m(8,a)+m(9,1));
  2620 + imSet(srcData.data, x, y, width, height, 2, m(10,r)+m(11,g)+m(12,b)+m(13,a)+m(14,1));
  2621 + imSet(srcData.data, x, y, width, height, 3, m(15,r)+m(16,g)+m(17,b)+m(18,a)+m(19,1));
  2622 + }
  2623 + }
  2624 + ctx.clearRect(0, 0, width, height);
  2625 + ctx.putImageData(srcData, 0, 0);
  2626 + }
  2627 + }
  2628 + svg.Element.feColorMatrix.prototype = new svg.Element.ElementBase;
  2629 +
  2630 + svg.Element.feGaussianBlur = function(node) {
  2631 + this.base = svg.Element.ElementBase;
  2632 + this.base(node);
  2633 +
  2634 + this.blurRadius = Math.floor(this.attribute('stdDeviation').numValue());
  2635 + this.extraFilterDistance = this.blurRadius;
  2636 +
  2637 + this.apply = function(ctx, x, y, width, height) {
  2638 + if (typeof(stackBlurCanvasRGBA) == 'undefined') {
  2639 + if (typeof(console) != 'undefined') { console.log('ERROR: StackBlur.js must be included for blur to work'); }
  2640 + return;
  2641 + }
  2642 +
  2643 + // StackBlur requires canvas be on document
  2644 + ctx.canvas.id = svg.UniqueId();
  2645 + ctx.canvas.style.display = 'none';
  2646 + document.body.appendChild(ctx.canvas);
  2647 + stackBlurCanvasRGBA(ctx.canvas.id, x, y, width, height, this.blurRadius);
  2648 + document.body.removeChild(ctx.canvas);
  2649 + }
  2650 + }
  2651 + svg.Element.feGaussianBlur.prototype = new svg.Element.ElementBase;
  2652 +
  2653 + // title element, do nothing
  2654 + svg.Element.title = function(node) {
  2655 + }
  2656 + svg.Element.title.prototype = new svg.Element.ElementBase;
  2657 +
  2658 + // desc element, do nothing
  2659 + svg.Element.desc = function(node) {
  2660 + }
  2661 + svg.Element.desc.prototype = new svg.Element.ElementBase;
  2662 +
  2663 + svg.Element.MISSING = function(node) {
  2664 + if (typeof(console) != 'undefined') { console.log('ERROR: Element \'' + node.nodeName + '\' not yet implemented.'); }
  2665 + }
  2666 + svg.Element.MISSING.prototype = new svg.Element.ElementBase;
  2667 +
  2668 + // element factory
  2669 + svg.CreateElement = function(node) {
  2670 + var className = node.nodeName.replace(/^[^:]+:/,''); // remove namespace
  2671 + className = className.replace(/\-/g,''); // remove dashes
  2672 + var e = null;
  2673 + if (typeof(svg.Element[className]) != 'undefined') {
  2674 + e = new svg.Element[className](node);
  2675 + }
  2676 + else {
  2677 + e = new svg.Element.MISSING(node);
  2678 + }
  2679 +
  2680 + e.type = node.nodeName;
  2681 + return e;
  2682 + }
  2683 +
  2684 + // load from url
  2685 + svg.load = function(ctx, url) {
  2686 + svg.loadXml(ctx, svg.ajax(url));
  2687 + }
  2688 +
  2689 + // load from xml
  2690 + svg.loadXml = function(ctx, xml) {
  2691 + svg.loadXmlDoc(ctx, svg.parseXml(xml));
  2692 + }
  2693 +
  2694 + svg.loadXmlDoc = function(ctx, dom) {
  2695 + svg.init(ctx);
  2696 +
  2697 + var mapXY = function(p) {
  2698 + var e = ctx.canvas;
  2699 + while (e) {
  2700 + p.x -= e.offsetLeft;
  2701 + p.y -= e.offsetTop;
  2702 + e = e.offsetParent;
  2703 + }
  2704 + if (window.scrollX) p.x += window.scrollX;
  2705 + if (window.scrollY) p.y += window.scrollY;
  2706 + return p;
  2707 + }
  2708 +
  2709 + // bind mouse
  2710 + if (svg.opts['ignoreMouse'] != true) {
  2711 + ctx.canvas.onclick = function(e) {
  2712 + var p = mapXY(new svg.Point(e != null ? e.clientX : event.clientX, e != null ? e.clientY : event.clientY));
  2713 + svg.Mouse.onclick(p.x, p.y);
  2714 + };
  2715 + ctx.canvas.onmousemove = function(e) {
  2716 + var p = mapXY(new svg.Point(e != null ? e.clientX : event.clientX, e != null ? e.clientY : event.clientY));
  2717 + svg.Mouse.onmousemove(p.x, p.y);
  2718 + };
  2719 + }
  2720 +
  2721 + var e = svg.CreateElement(dom.documentElement);
  2722 + e.root = true;
  2723 +
  2724 + // render loop
  2725 + var isFirstRender = true;
  2726 + var draw = function() {
  2727 + svg.ViewPort.Clear();
  2728 + if (ctx.canvas.parentNode) svg.ViewPort.SetCurrent(ctx.canvas.parentNode.clientWidth, ctx.canvas.parentNode.clientHeight);
  2729 +
  2730 + if (svg.opts['ignoreDimensions'] != true) {
  2731 + // set canvas size
  2732 + if (e.style('width').hasValue()) {
  2733 + ctx.canvas.width = e.style('width').toPixels('x');
  2734 + ctx.canvas.style.width = ctx.canvas.width + 'px';
  2735 + }
  2736 + if (e.style('height').hasValue()) {
  2737 + ctx.canvas.height = e.style('height').toPixels('y');
  2738 + ctx.canvas.style.height = ctx.canvas.height + 'px';
  2739 + }
  2740 + }
  2741 + var cWidth = ctx.canvas.clientWidth || ctx.canvas.width;
  2742 + var cHeight = ctx.canvas.clientHeight || ctx.canvas.height;
  2743 + if (svg.opts['ignoreDimensions'] == true && e.style('width').hasValue() && e.style('height').hasValue()) {
  2744 + cWidth = e.style('width').toPixels('x');
  2745 + cHeight = e.style('height').toPixels('y');
  2746 + }
  2747 + svg.ViewPort.SetCurrent(cWidth, cHeight);
  2748 +
  2749 + if (svg.opts['offsetX'] != null) e.attribute('x', true).value = svg.opts['offsetX'];
  2750 + if (svg.opts['offsetY'] != null) e.attribute('y', true).value = svg.opts['offsetY'];
  2751 + if (svg.opts['scaleWidth'] != null && svg.opts['scaleHeight'] != null) {
  2752 + var xRatio = 1, yRatio = 1, viewBox = svg.ToNumberArray(e.attribute('viewBox').value);
  2753 + if (e.attribute('width').hasValue()) xRatio = e.attribute('width').toPixels('x') / svg.opts['scaleWidth'];
  2754 + else if (!isNaN(viewBox[2])) xRatio = viewBox[2] / svg.opts['scaleWidth'];
  2755 + if (e.attribute('height').hasValue()) yRatio = e.attribute('height').toPixels('y') / svg.opts['scaleHeight'];
  2756 + else if (!isNaN(viewBox[3])) yRatio = viewBox[3] / svg.opts['scaleHeight'];
  2757 +
  2758 + e.attribute('width', true).value = svg.opts['scaleWidth'];
  2759 + e.attribute('height', true).value = svg.opts['scaleHeight'];
  2760 + e.attribute('viewBox', true).value = '0 0 ' + (cWidth * xRatio) + ' ' + (cHeight * yRatio);
  2761 + e.attribute('preserveAspectRatio', true).value = 'none';
  2762 + }
  2763 +
  2764 + // clear and render
  2765 + if (svg.opts['ignoreClear'] != true) {
  2766 + ctx.clearRect(0, 0, cWidth, cHeight);
  2767 + }
  2768 + e.render(ctx);
  2769 + if (isFirstRender) {
  2770 + isFirstRender = false;
  2771 + if (typeof(svg.opts['renderCallback']) == 'function') svg.opts['renderCallback'](dom);
  2772 + }
  2773 + }
  2774 +
  2775 + var waitingForImages = true;
  2776 + if (svg.ImagesLoaded()) {
  2777 + waitingForImages = false;
  2778 + draw();
  2779 + }
  2780 + svg.intervalID = setInterval(function() {
  2781 + var needUpdate = false;
  2782 +
  2783 + if (waitingForImages && svg.ImagesLoaded()) {
  2784 + waitingForImages = false;
  2785 + needUpdate = true;
  2786 + }
  2787 +
  2788 + // need update from mouse events?
  2789 + if (svg.opts['ignoreMouse'] != true) {
  2790 + needUpdate = needUpdate | svg.Mouse.hasEvents();
  2791 + }
  2792 +
  2793 + // need update from animations?
  2794 + if (svg.opts['ignoreAnimation'] != true) {
  2795 + for (var i=0; i<svg.Animations.length; i++) {
  2796 + needUpdate = needUpdate | svg.Animations[i].update(1000 / svg.FRAMERATE);
  2797 + }
  2798 + }
  2799 +
  2800 + // need update from redraw?
  2801 + if (typeof(svg.opts['forceRedraw']) == 'function') {
  2802 + if (svg.opts['forceRedraw']() == true) needUpdate = true;
  2803 + }
  2804 +
  2805 + // render if needed
  2806 + if (needUpdate) {
  2807 + draw();
  2808 + svg.Mouse.runEvents(); // run and clear our events
  2809 + }
  2810 + }, 1000 / svg.FRAMERATE);
  2811 + }
  2812 +
  2813 + svg.stop = function() {
  2814 + if (svg.intervalID) {
  2815 + clearInterval(svg.intervalID);
  2816 + }
  2817 + }
  2818 +
  2819 + svg.Mouse = new (function() {
  2820 + this.events = [];
  2821 + this.hasEvents = function() { return this.events.length != 0; }
  2822 +
  2823 + this.onclick = function(x, y) {
  2824 + this.events.push({ type: 'onclick', x: x, y: y,
  2825 + run: function(e) { if (e.onclick) e.onclick(); }
  2826 + });
  2827 + }
  2828 +
  2829 + this.onmousemove = function(x, y) {
  2830 + this.events.push({ type: 'onmousemove', x: x, y: y,
  2831 + run: function(e) { if (e.onmousemove) e.onmousemove(); }
  2832 + });
  2833 + }
  2834 +
  2835 + this.eventElements = [];
  2836 +
  2837 + this.checkPath = function(element, ctx) {
  2838 + for (var i=0; i<this.events.length; i++) {
  2839 + var e = this.events[i];
  2840 + if (ctx.isPointInPath && ctx.isPointInPath(e.x, e.y)) this.eventElements[i] = element;
  2841 + }
  2842 + }
  2843 +
  2844 + this.checkBoundingBox = function(element, bb) {
  2845 + for (var i=0; i<this.events.length; i++) {
  2846 + var e = this.events[i];
  2847 + if (bb.isPointInBox(e.x, e.y)) this.eventElements[i] = element;
  2848 + }
  2849 + }
  2850 +
  2851 + this.runEvents = function() {
  2852 + svg.ctx.canvas.style.cursor = '';
  2853 +
  2854 + for (var i=0; i<this.events.length; i++) {
  2855 + var e = this.events[i];
  2856 + var element = this.eventElements[i];
  2857 + while (element) {
  2858 + e.run(element);
  2859 + element = element.parent;
  2860 + }
  2861 + }
  2862 +
  2863 + // done running, clear
  2864 + this.events = [];
  2865 + this.eventElements = [];
  2866 + }
  2867 + });
  2868 +
  2869 + return svg;
  2870 + }
  2871 +})();
  2872 +
  2873 +if (typeof(CanvasRenderingContext2D) != 'undefined') {
  2874 + CanvasRenderingContext2D.prototype.drawSvg = function(s, dx, dy, dw, dh) {
  2875 + canvg(this.canvas, s, {
  2876 + ignoreMouse: true,
  2877 + ignoreAnimation: true,
  2878 + ignoreDimensions: true,
  2879 + ignoreClear: true,
  2880 + offsetX: dx,
  2881 + offsetY: dy,
  2882 + scaleWidth: dw,
  2883 + scaleHeight: dh
  2884 + });
  2885 + }
  2886 +}
0 2887 \ No newline at end of file
... ...
pacotes/rgbcolor.js 0 → 100755
... ... @@ -0,0 +1,288 @@
  1 +/**
  2 + * A class to parse color values
  3 + * @author Stoyan Stefanov <sstoo@gmail.com>
  4 + * @link http://www.phpied.com/rgb-color-parser-in-javascript/
  5 + * @license Use it if you like it
  6 + */
  7 +function RGBColor(color_string)
  8 +{
  9 + this.ok = false;
  10 +
  11 + // strip any leading #
  12 + if (color_string.charAt(0) == '#') { // remove # if any
  13 + color_string = color_string.substr(1,6);
  14 + }
  15 +
  16 + color_string = color_string.replace(/ /g,'');
  17 + color_string = color_string.toLowerCase();
  18 +
  19 + // before getting into regexps, try simple matches
  20 + // and overwrite the input
  21 + var simple_colors = {
  22 + aliceblue: 'f0f8ff',
  23 + antiquewhite: 'faebd7',
  24 + aqua: '00ffff',
  25 + aquamarine: '7fffd4',
  26 + azure: 'f0ffff',
  27 + beige: 'f5f5dc',
  28 + bisque: 'ffe4c4',
  29 + black: '000000',
  30 + blanchedalmond: 'ffebcd',
  31 + blue: '0000ff',
  32 + blueviolet: '8a2be2',
  33 + brown: 'a52a2a',
  34 + burlywood: 'deb887',
  35 + cadetblue: '5f9ea0',
  36 + chartreuse: '7fff00',
  37 + chocolate: 'd2691e',
  38 + coral: 'ff7f50',
  39 + cornflowerblue: '6495ed',
  40 + cornsilk: 'fff8dc',
  41 + crimson: 'dc143c',
  42 + cyan: '00ffff',
  43 + darkblue: '00008b',
  44 + darkcyan: '008b8b',
  45 + darkgoldenrod: 'b8860b',
  46 + darkgray: 'a9a9a9',
  47 + darkgreen: '006400',
  48 + darkkhaki: 'bdb76b',
  49 + darkmagenta: '8b008b',
  50 + darkolivegreen: '556b2f',
  51 + darkorange: 'ff8c00',
  52 + darkorchid: '9932cc',
  53 + darkred: '8b0000',
  54 + darksalmon: 'e9967a',
  55 + darkseagreen: '8fbc8f',
  56 + darkslateblue: '483d8b',
  57 + darkslategray: '2f4f4f',
  58 + darkturquoise: '00ced1',
  59 + darkviolet: '9400d3',
  60 + deeppink: 'ff1493',
  61 + deepskyblue: '00bfff',
  62 + dimgray: '696969',
  63 + dodgerblue: '1e90ff',
  64 + feldspar: 'd19275',
  65 + firebrick: 'b22222',
  66 + floralwhite: 'fffaf0',
  67 + forestgreen: '228b22',
  68 + fuchsia: 'ff00ff',
  69 + gainsboro: 'dcdcdc',
  70 + ghostwhite: 'f8f8ff',
  71 + gold: 'ffd700',
  72 + goldenrod: 'daa520',
  73 + gray: '808080',
  74 + green: '008000',
  75 + greenyellow: 'adff2f',
  76 + honeydew: 'f0fff0',
  77 + hotpink: 'ff69b4',
  78 + indianred : 'cd5c5c',
  79 + indigo : '4b0082',
  80 + ivory: 'fffff0',
  81 + khaki: 'f0e68c',
  82 + lavender: 'e6e6fa',
  83 + lavenderblush: 'fff0f5',
  84 + lawngreen: '7cfc00',
  85 + lemonchiffon: 'fffacd',
  86 + lightblue: 'add8e6',
  87 + lightcoral: 'f08080',
  88 + lightcyan: 'e0ffff',
  89 + lightgoldenrodyellow: 'fafad2',
  90 + lightgrey: 'd3d3d3',
  91 + lightgreen: '90ee90',
  92 + lightpink: 'ffb6c1',
  93 + lightsalmon: 'ffa07a',
  94 + lightseagreen: '20b2aa',
  95 + lightskyblue: '87cefa',
  96 + lightslateblue: '8470ff',
  97 + lightslategray: '778899',
  98 + lightsteelblue: 'b0c4de',
  99 + lightyellow: 'ffffe0',
  100 + lime: '00ff00',
  101 + limegreen: '32cd32',
  102 + linen: 'faf0e6',
  103 + magenta: 'ff00ff',
  104 + maroon: '800000',
  105 + mediumaquamarine: '66cdaa',
  106 + mediumblue: '0000cd',
  107 + mediumorchid: 'ba55d3',
  108 + mediumpurple: '9370d8',
  109 + mediumseagreen: '3cb371',
  110 + mediumslateblue: '7b68ee',
  111 + mediumspringgreen: '00fa9a',
  112 + mediumturquoise: '48d1cc',
  113 + mediumvioletred: 'c71585',
  114 + midnightblue: '191970',
  115 + mintcream: 'f5fffa',
  116 + mistyrose: 'ffe4e1',
  117 + moccasin: 'ffe4b5',
  118 + navajowhite: 'ffdead',
  119 + navy: '000080',
  120 + oldlace: 'fdf5e6',
  121 + olive: '808000',
  122 + olivedrab: '6b8e23',
  123 + orange: 'ffa500',
  124 + orangered: 'ff4500',
  125 + orchid: 'da70d6',
  126 + palegoldenrod: 'eee8aa',
  127 + palegreen: '98fb98',
  128 + paleturquoise: 'afeeee',
  129 + palevioletred: 'd87093',
  130 + papayawhip: 'ffefd5',
  131 + peachpuff: 'ffdab9',
  132 + peru: 'cd853f',
  133 + pink: 'ffc0cb',
  134 + plum: 'dda0dd',
  135 + powderblue: 'b0e0e6',
  136 + purple: '800080',
  137 + red: 'ff0000',
  138 + rosybrown: 'bc8f8f',
  139 + royalblue: '4169e1',
  140 + saddlebrown: '8b4513',
  141 + salmon: 'fa8072',
  142 + sandybrown: 'f4a460',
  143 + seagreen: '2e8b57',
  144 + seashell: 'fff5ee',
  145 + sienna: 'a0522d',
  146 + silver: 'c0c0c0',
  147 + skyblue: '87ceeb',
  148 + slateblue: '6a5acd',
  149 + slategray: '708090',
  150 + snow: 'fffafa',
  151 + springgreen: '00ff7f',
  152 + steelblue: '4682b4',
  153 + tan: 'd2b48c',
  154 + teal: '008080',
  155 + thistle: 'd8bfd8',
  156 + tomato: 'ff6347',
  157 + turquoise: '40e0d0',
  158 + violet: 'ee82ee',
  159 + violetred: 'd02090',
  160 + wheat: 'f5deb3',
  161 + white: 'ffffff',
  162 + whitesmoke: 'f5f5f5',
  163 + yellow: 'ffff00',
  164 + yellowgreen: '9acd32'
  165 + };
  166 + for (var key in simple_colors) {
  167 + if (color_string == key) {
  168 + color_string = simple_colors[key];
  169 + }
  170 + }
  171 + // emd of simple type-in colors
  172 +
  173 + // array of color definition objects
  174 + var color_defs = [
  175 + {
  176 + re: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/,
  177 + example: ['rgb(123, 234, 45)', 'rgb(255,234,245)'],
  178 + process: function (bits){
  179 + return [
  180 + parseInt(bits[1]),
  181 + parseInt(bits[2]),
  182 + parseInt(bits[3])
  183 + ];
  184 + }
  185 + },
  186 + {
  187 + re: /^(\w{2})(\w{2})(\w{2})$/,
  188 + example: ['#00ff00', '336699'],
  189 + process: function (bits){
  190 + return [
  191 + parseInt(bits[1], 16),
  192 + parseInt(bits[2], 16),
  193 + parseInt(bits[3], 16)
  194 + ];
  195 + }
  196 + },
  197 + {
  198 + re: /^(\w{1})(\w{1})(\w{1})$/,
  199 + example: ['#fb0', 'f0f'],
  200 + process: function (bits){
  201 + return [
  202 + parseInt(bits[1] + bits[1], 16),
  203 + parseInt(bits[2] + bits[2], 16),
  204 + parseInt(bits[3] + bits[3], 16)
  205 + ];
  206 + }
  207 + }
  208 + ];
  209 +
  210 + // search through the definitions to find a match
  211 + for (var i = 0; i < color_defs.length; i++) {
  212 + var re = color_defs[i].re;
  213 + var processor = color_defs[i].process;
  214 + var bits = re.exec(color_string);
  215 + if (bits) {
  216 + channels = processor(bits);
  217 + this.r = channels[0];
  218 + this.g = channels[1];
  219 + this.b = channels[2];
  220 + this.ok = true;
  221 + }
  222 +
  223 + }
  224 +
  225 + // validate/cleanup values
  226 + this.r = (this.r < 0 || isNaN(this.r)) ? 0 : ((this.r > 255) ? 255 : this.r);
  227 + this.g = (this.g < 0 || isNaN(this.g)) ? 0 : ((this.g > 255) ? 255 : this.g);
  228 + this.b = (this.b < 0 || isNaN(this.b)) ? 0 : ((this.b > 255) ? 255 : this.b);
  229 +
  230 + // some getters
  231 + this.toRGB = function () {
  232 + return 'rgb(' + this.r + ', ' + this.g + ', ' + this.b + ')';
  233 + }
  234 + this.toHex = function () {
  235 + var r = this.r.toString(16);
  236 + var g = this.g.toString(16);
  237 + var b = this.b.toString(16);
  238 + if (r.length == 1) r = '0' + r;
  239 + if (g.length == 1) g = '0' + g;
  240 + if (b.length == 1) b = '0' + b;
  241 + return '#' + r + g + b;
  242 + }
  243 +
  244 + // help
  245 + this.getHelpXML = function () {
  246 +
  247 + var examples = new Array();
  248 + // add regexps
  249 + for (var i = 0; i < color_defs.length; i++) {
  250 + var example = color_defs[i].example;
  251 + for (var j = 0; j < example.length; j++) {
  252 + examples[examples.length] = example[j];
  253 + }
  254 + }
  255 + // add type-in colors
  256 + for (var sc in simple_colors) {
  257 + examples[examples.length] = sc;
  258 + }
  259 +
  260 + var xml = document.createElement('ul');
  261 + xml.setAttribute('id', 'rgbcolor-examples');
  262 + for (var i = 0; i < examples.length; i++) {
  263 + try {
  264 + var list_item = document.createElement('li');
  265 + var list_color = new RGBColor(examples[i]);
  266 + var example_div = document.createElement('div');
  267 + example_div.style.cssText =
  268 + 'margin: 3px; '
  269 + + 'border: 1px solid black; '
  270 + + 'background:' + list_color.toHex() + '; '
  271 + + 'color:' + list_color.toHex()
  272 + ;
  273 + example_div.appendChild(document.createTextNode('test'));
  274 + var list_item_value = document.createTextNode(
  275 + ' ' + examples[i] + ' -> ' + list_color.toRGB() + ' -> ' + list_color.toHex()
  276 + );
  277 + list_item.appendChild(example_div);
  278 + list_item.appendChild(list_item_value);
  279 + xml.appendChild(list_item);
  280 +
  281 + } catch(e){}
  282 + }
  283 + return xml;
  284 +
  285 + }
  286 +
  287 +}
  288 +
... ...
pacotes/svg2img.php 0 → 100755
... ... @@ -0,0 +1,31 @@
  1 +<html>
  2 +<head>
  3 +<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>
  4 +<script type='text/javascript' src='rgbcolor.js'></script>
  5 +<script type='text/javascript' src='canvg.js'></script>
  6 +<script type='text/javascript' src='canvas2image.js'></script>
  7 +<script type='text/javascript' src='base64.js'></script>
  8 +</head>
  9 +<body>
  10 +<div id=canvas ></div>
  11 +</body>
  12 +<script>
  13 +function render(svg, w, h) {
  14 + document.createElement('canvas')
  15 + var c = document.createElement('canvas');
  16 + c.id = "svgcancas";
  17 + c.width = w || 500;
  18 + c.height = h || 500;
  19 + document.getElementById('canvas').innerHTML = '';
  20 + document.getElementById('canvas').appendChild(c);
  21 + if (typeof FlashCanvas != "undefined") {
  22 + FlashCanvas.initElement(c);
  23 + }
  24 + canvg(c, svg, { renderCallback: function () {
  25 + oCanvas = document.getElementById("svgcancas");
  26 + Canvas2Image.saveAsPNG(oCanvas,false,w,h);
  27 + }});
  28 +}
  29 +render('<?php echo $_POST["svg"];?>',<?php echo $_GET["w"];?>,<?php echo $_GET["h"];?>);
  30 +</script>
  31 +</html>
0 32 \ No newline at end of file
... ...