1 /* 2 Copyright 2008,2009 3 Matthias Ehmann, 4 Michael Gerhaeuser, 5 Carsten Miller, 6 Bianca Valentin, 7 Alfred Wassermann, 8 Peter Wilfahrt 9 10 This file is part of JSXGraph. 11 12 JSXGraph is free software: you can redistribute it and/or modify 13 it under the terms of the GNU Lesser General Public License as published by 14 the Free Software Foundation, either version 3 of the License, or 15 (at your option) any later version. 16 17 JSXGraph is distributed in the hope that it will be useful, 18 but WITHOUT ANY WARRANTY; without even the implied warranty of 19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 GNU Lesser General Public License for more details. 21 22 You should have received a copy of the GNU Lesser General Public License 23 along with JSXGraph. If not, see <http://www.gnu.org/licenses/>. 24 */ 25 /* 26 -------------------------------------------------------------------- 27 von AbstractRenderer abgeleitete Zeichenklasse 28 fuer Browser mit VML-Elementen (Internet Explorer) 29 -------------------------------------------------------------------- 30 */ 31 32 JXG.VMLRenderer = function(container) { 33 this.constructor(); 34 35 /* 36 Enable easy test which renderer is used. 37 */ 38 this.type = 'vml'; 39 40 this.container = container; 41 this.container.style.overflow = 'hidden'; 42 this.container.onselectstart = function () { return false; }; 43 44 this.resolution = 10; // Paths are drawn with a a resolution of this.resolution/pixel. 45 46 // Add VML includes and namespace 47 // Original: IE <=7 48 //container.ownerDocument.createStyleSheet().addRule("v\\:*", "behavior: url(#default#VML);"); 49 if (JXG.vmlStylesheet==null) { 50 container.ownerDocument.namespaces.add("jxgvml", "urn:schemas-microsoft-com:vml"); 51 JXG.vmlStylesheet = this.container.ownerDocument.createStyleSheet(); 52 JXG.vmlStylesheet.addRule(".jxgvml", "behavior:url(#default#VML)"); 53 } 54 try { 55 !container.ownerDocument.namespaces.jxgvml && container.ownerDocument.namespaces.add("jxgvml", "urn:schemas-microsoft-com:vml"); 56 this.createNode = function (tagName) { 57 return container.ownerDocument.createElement('<jxgvml:' + tagName + ' class="jxgvml">'); 58 }; 59 } catch (e) { 60 this.createNode = function (tagName) { 61 return container.ownerDocument.createElement('<' + tagName + ' xmlns="urn:schemas-microsoft.com:vml" class="jxgvml">'); 62 }; 63 } 64 // um Dashes zu realisieren 65 this.dashArray = ['Solid', '1 1', 'ShortDash', 'Dash', 'LongDash', 'ShortDashDot', 'LongDashDot']; 66 }; 67 68 JXG.VMLRenderer.prototype = JXG.AbstractRenderer(); 69 70 JXG.VMLRenderer.prototype.setAttr = function(node, key, val, val2) { 71 try { 72 if (document.documentMode==8) { 73 node[key] = val; 74 } else { 75 node.setAttribute(key,val,val2); 76 } 77 } catch (e) { 78 //document.getElementById('debug').innerHTML += node.id+' '+key+' '+val+'<br>\n'; 79 } 80 }; 81 82 JXG.VMLRenderer.prototype.setShadow = function(el) { 83 var nodeShadow = el.rendNodeShadow; 84 85 if (!nodeShadow) return; // Added 29.9.09. A.W. 86 if (el.visPropOld['shadow']==el.visProp['shadow']) { 87 return; 88 } 89 if(el.visProp['shadow']) { 90 this.setAttr(nodeShadow, 'On', 'True'); 91 this.setAttr(nodeShadow, 'Offset', '3pt,3pt'); 92 this.setAttr(nodeShadow, 'Opacity', '60%'); 93 this.setAttr(nodeShadow, 'Color', '#aaaaaa'); 94 } 95 else { 96 this.setAttr(nodeShadow, 'On', 'False'); 97 } 98 el.visPropOld['shadow']=el.visProp['shadow']; 99 }; 100 101 JXG.VMLRenderer.prototype.setGradient = function(el) { 102 var nodeFill = el.rendNodeFill; 103 if(el.visProp['gradient'] == 'linear') { 104 this.setAttr(nodeFill, 'type', 'gradient'); 105 this.setAttr(nodeFill, 'color2', el.visProp['gradientSecondColor']); 106 this.setAttr(nodeFill, 'opacity2', el.visProp['gradientSecondOpacity']); 107 this.setAttr(nodeFill, 'angle', el.visProp['gradientAngle']); 108 } 109 else if (el.visProp['gradient'] == 'radial') { 110 this.setAttr(nodeFill, 'type','gradientradial'); 111 this.setAttr(nodeFill, 'color2',el.visProp['gradientSecondColor']); 112 this.setAttr(nodeFill, 'opacity2',el.visProp['gradientSecondOpacity']); 113 this.setAttr(nodeFill, 'focusposition', el.visProp['gradientPositionX']*100+'%,'+el.visProp['gradientPositionY']*100+'%'); 114 this.setAttr(nodeFill, 'focussize', '0,0'); 115 } 116 else { 117 this.setAttr(nodeFill, 'type','solid'); 118 } 119 }; 120 121 JXG.VMLRenderer.prototype.updateGradient = function(el) {}; // Not needed in VML; 122 123 JXG.VMLRenderer.prototype.addShadowToGroup = function(groupname, board) { 124 var el, pEl; 125 if(groupname == "lines") { 126 for(el in board.objects) { 127 pEl = board.objects[el]; 128 if(pEl.elementClass == JXG.OBJECT_CLASS_LINE) { 129 this.addShadowToElement(pEl); 130 } 131 } 132 } 133 else if(groupname == "points") { 134 for(el in board.objects) { 135 pEl = board.objects[el]; 136 if(pEl.elementClass == JXG.OBJECT_CLASS_POINT) { 137 this.addShadowToElement(pEl); 138 } 139 } 140 } 141 else if(groupname == "circles") { 142 for(el in board.objects) { 143 pEl = board.objects[el]; 144 if(pEl.elementClass == JXG.OBJECT_CLASS_CIRCLE) { 145 this.addShadowToElement(pEl); 146 } 147 } 148 } 149 board.fullUpdate(); 150 }; 151 152 JXG.VMLRenderer.prototype.displayCopyright = function(str,fontsize) { 153 var node, t; 154 155 //node = this.container.ownerDocument.createElement('v:textbox'); 156 node = this.createNode('textbox'); 157 node.style.position = 'absolute'; 158 this.setAttr(node,'id', this.container.id+'_'+'licenseText'); 159 160 node.style.left = 20; 161 node.style.top = (2); 162 node.style.fontSize = (fontsize); 163 node.style.color = '#356AA0'; 164 node.style.fontFamily = 'Arial,Helvetica,sans-serif'; 165 this.setAttr(node,'opacity','30%'); 166 node.style.filter = 'alpha(opacity = 30)'; 167 168 t = document.createTextNode(str); 169 node.appendChild(t); 170 this.appendChildPrim(node,0); 171 }; 172 173 JXG.VMLRenderer.prototype.drawInternalText = function(el) { 174 var node; 175 node = this.createNode('textbox'); 176 node.style.position = 'absolute'; 177 if (document.documentMode==8) { 178 node.setAttribute('class', 'JXGtext'); 179 } else { 180 node.setAttribute('className', 9); 181 } 182 el.rendNodeText = document.createTextNode(''); 183 node.appendChild(el.rendNodeText); 184 this.appendChildPrim(node,9); 185 return node; 186 }; 187 188 JXG.VMLRenderer.prototype.updateInternalText = function(/** JXG.Text */ el) { 189 el.rendNode.style.left = (el.coords.scrCoords[1])+'px'; 190 el.rendNode.style.top = (el.coords.scrCoords[2] - this.vOffsetText)+'px'; 191 el.updateText(); 192 if (el.htmlStr!= el.plaintextStr) { 193 el.rendNodeText.data = el.plaintextStr; 194 el.htmlStr = el.plaintextStr; 195 } 196 this.transformImage(el, el.transformations); 197 198 }; 199 200 JXG.VMLRenderer.prototype.drawTicks = function(ticks) { 201 var ticksNode = this.createPrim('path', ticks.id); 202 this.appendChildPrim(ticksNode,ticks.layer); 203 //ticks.rendNode = ticksNode; 204 this.appendNodesToElement(ticks, 'path'); 205 }; 206 207 JXG.VMLRenderer.prototype.updateTicks = function(axis,dxMaj,dyMaj,dxMin,dyMin) { 208 var tickArr = [], i, len, c, ticks, r = this.resolution; 209 210 len = axis.ticks.length; 211 for (i=0; i<len; i++) { 212 c = axis.ticks[i].scrCoords; 213 if(axis.ticks[i].major) { 214 if ((axis.board.needsFullUpdate||axis.needsRegularUpdate) && axis.labels[i].visProp['visible']) { 215 this.drawText(axis.labels[i]); 216 } 217 tickArr.push(' m ' + Math.round(r*(c[1]+dxMaj)) + 218 ', ' + Math.round(r*(c[2]-dyMaj)) + 219 ' l ' + Math.round(r*(c[1]-dxMaj)) + 220 ', ' + Math.round(r*(c[2]+dyMaj))+' '); 221 } 222 else 223 tickArr.push(' m ' + Math.round(r*(c[1]+dxMin)) + 224 ', ' + Math.round(r*(c[2]-dyMin)) + 225 ' l ' + Math.round(r*(c[1]-dxMin)) + 226 ', ' + Math.round(r*(c[2]+dyMin))+' '); 227 } 228 229 ticks = this.getElementById(axis.id); 230 if(ticks == null) { 231 ticks = this.createPrim('path', axis.id); 232 this.appendChildPrim(ticks,axis.layer); 233 this.appendNodesToElement(axis,'path'); 234 } 235 this.setAttr(ticks,'stroked', 'true'); 236 this.setAttr(ticks,'strokecolor', axis.visProp['strokeColor'], 1); 237 this.setAttr(ticks,'strokeweight', axis.visProp['strokeWidth']); 238 //ticks.setAttributeNS(null, 'stroke-opacity', axis.visProp['strokeOpacity']); 239 this.updatePathPrim(ticks, tickArr, axis.board); 240 }; 241 242 JXG.VMLRenderer.prototype.drawImage = function(el) { 243 // IE 8: Bilder ueber data URIs werden bis 32kB unterstuetzt. 244 var node; // url = el.url(); //'data:image/png;base64,' + el.imageBase64String; 245 246 node = this.container.ownerDocument.createElement('img'); 247 node.style.position = 'absolute'; 248 this.setAttr(node,'id', this.container.id+'_'+el.id); 249 250 //this.setAttr(node,'src',url); 251 this.container.appendChild(node); 252 this.appendChildPrim(node,el.layer); 253 // Adding the rotation filter. This is always filter item 0: 254 // node.filters.item(0), see transformImage 255 node.style.filter = node.style['-ms-filter'] = 256 "progid:DXImageTransform.Microsoft.Matrix(M11='1.0', sizingMethod='auto expand')"; 257 el.rendNode = node; 258 this.updateImage(el); 259 }; 260 261 JXG.VMLRenderer.prototype.updateImageURL = function(el) { 262 var url; 263 if (JXG.isFunction(el.url)) { 264 url = el.url(); 265 } else { 266 url = el.url; 267 } 268 this.setAttr(el.rendNode,'src',url); 269 }; 270 271 JXG.VMLRenderer.prototype.transformImage = function(el,t) { 272 var node = el.rendNode, 273 m, p = [], s, len = t.length, 274 maxX, maxY, minX, minY, i, h, w, 275 nt; 276 277 if (el.type==JXG.OBJECT_TYPE_TEXT) { 278 el.updateSize(); 279 } 280 if (len>0) { 281 nt = el.rendNode.style.filter.toString(); 282 if (!nt.match(/DXImageTransform/)) { 283 node.style.filter = node.style['-ms-filter'] = 284 "progid:DXImageTransform.Microsoft.Matrix(M11='1.0', sizingMethod='auto expand') " + nt; 285 } 286 287 m = this.joinTransforms(el,t); 288 p[0] = JXG.Math.matVecMult(m, el.coords.scrCoords); 289 p[0][1] /= p[0][0]; 290 p[0][2] /= p[0][0]; 291 p[1] = JXG.Math.matVecMult(m, [1, el.coords.scrCoords[1]+el.size[0], el.coords.scrCoords[2]]); 292 p[1][1] /= p[1][0]; 293 p[1][2] /= p[1][0]; 294 p[2] = JXG.Math.matVecMult(m, [1, el.coords.scrCoords[1]+el.size[0], el.coords.scrCoords[2]-el.size[1]]); 295 p[2][1] /= p[2][0]; 296 p[2][2] /= p[2][0]; 297 p[3] = JXG.Math.matVecMult(m, [1, el.coords.scrCoords[1], el.coords.scrCoords[2]-el.size[1]]); 298 p[3][1] /= p[3][0]; 299 p[3][2] /= p[3][0]; 300 maxX = p[0][1]; 301 minX = p[0][1]; 302 maxY = p[0][2]; 303 minY = p[0][2]; 304 for (i=1; i<4; i++) { 305 maxX = Math.max(maxX, p[i][1]); 306 minX = Math.min(minX, p[i][1]); 307 maxY = Math.max(maxY, p[i][2]); 308 minY = Math.min(minY, p[i][2]); 309 } 310 node.style.left = minX + 'px'; 311 node.style.top = minY + 'px'; 312 313 node.filters.item(0).M11 = m[1][1]; 314 node.filters.item(0).M12 = m[1][2]; 315 node.filters.item(0).M21 = m[2][1]; 316 node.filters.item(0).M22 = m[2][2]; 317 } 318 }; 319 320 /* 321 JXG.VMLRenderer.prototype.removeGrid = function(board) { 322 var c = this.getElementById('gridx'); 323 this.remove(c); 324 325 c = this.getElementById('gridy'); 326 this.remove(c); 327 328 board.hasGrid = false; 329 }; 330 */ 331 332 JXG.VMLRenderer.prototype.hide = function(el) { 333 var node; 334 335 if (!JXG.exists(el)) 336 return; 337 node = el.rendNode; 338 if(JXG.exists(node)) { 339 node.style.visibility = "hidden"; 340 } 341 }; 342 343 JXG.VMLRenderer.prototype.show = function(el) { 344 var node; 345 346 if (!JXG.exists(el)) 347 return; 348 node = el.rendNode; 349 if(JXG.exists(node)) { 350 node.style.visibility = "inherit"; 351 } 352 }; 353 354 JXG.VMLRenderer.prototype.setDashStyle = function(el,visProp) { 355 var node; 356 if(visProp['dash'] >= 0) { 357 node = el.rendNodeStroke; 358 this.setAttr(node,'dashstyle', this.dashArray[visProp['dash']]); 359 } 360 }; 361 362 JXG.VMLRenderer.prototype.setObjectStrokeColor = function(el, color, opacity) { 363 var c = this.evaluate(color), 364 o = this.evaluate(opacity), 365 node, nodeStroke; 366 367 o = (o>0)?o:0; 368 369 if (el.visPropOld['strokeColor']==c && el.visPropOld['strokeOpacity']==o) { 370 return; 371 } 372 if(el.type == JXG.OBJECT_TYPE_TEXT) { 373 el.rendNode.style.color = c; 374 } 375 else { 376 node = el.rendNode; 377 this.setAttr(node,'stroked', 'true'); 378 this.setAttr(node,'strokecolor', c); 379 380 if(el.id == 'gridx') { 381 nodeStroke = this.getElementById('gridx_stroke'); 382 } 383 else if(el.id == 'gridy') { 384 nodeStroke = this.getElementById('gridy_stroke'); 385 } 386 else { 387 nodeStroke = el.rendNodeStroke; 388 } 389 if (JXG.exists(o)) { 390 this.setAttr(nodeStroke,'opacity', (o*100)+'%'); 391 392 } 393 } 394 el.visPropOld['strokeColor'] = c; 395 el.visPropOld['strokeOpacity'] = o; 396 }; 397 398 JXG.VMLRenderer.prototype.setObjectFillColor = function(el, color, opacity) { 399 var c = this.evaluate(color), 400 o = this.evaluate(opacity), t; 401 402 o = (o>0)?o:0; 403 404 if (el.visPropOld['fillColor']==c && el.visPropOld['fillOpacity']==o) { 405 return; 406 } 407 if(c == 'none') { 408 this.setAttr(el.rendNode,'filled', 'false'); 409 } 410 else { 411 this.setAttr(el.rendNode,'filled', 'true'); 412 this.setAttr(el.rendNode,'fillcolor', c); 413 if (JXG.exists(o) && el.rendNodeFill) { // Added el.rendNodeFill 29.9.09 A.W. 414 this.setAttr(el.rendNodeFill,'opacity', (o*100)+'%'); 415 } 416 } 417 if (el.type==JXG.OBJECT_TYPE_IMAGE) { 418 t = el.rendNode.style.filter.toString(); 419 if (t.match(/alpha/)) { 420 el.rendNode.style.filter = t.replace(/alpha\(opacity *= *[0-9\.]+\)/, 421 'alpha(opacity = '+(o*100)+')'); 422 } else { 423 el.rendNode.style.filter += ' alpha(opacity = ' + (o*100) +')'; 424 } 425 } 426 el.visPropOld['fillColor'] = c; 427 el.visPropOld['fillOpacity'] = o; 428 }; 429 430 JXG.VMLRenderer.prototype.remove = function(node) { 431 if (node!=null) node.removeNode(true); 432 }; 433 434 JXG.VMLRenderer.prototype.suspendRedraw = function() { 435 this.container.style.display='none'; 436 }; 437 438 JXG.VMLRenderer.prototype.unsuspendRedraw = function() { 439 this.container.style.display=''; 440 }; 441 442 JXG.VMLRenderer.prototype.setAttributes = function(node,props,vmlprops,visProp) { 443 var val, i, p, 444 len = props.length; 445 446 for (i=0;i<len;i++) { 447 p = props[i]; 448 if (visProp[p]!=null) { 449 val = this.evaluate(visProp[p]); 450 val = (val>0)?val:0; 451 this.setAttr(node,vmlprops[i], val); 452 } 453 } 454 }; 455 456 JXG.VMLRenderer.prototype.setGridDash = function(id, node) { 457 var node = this.getElementById(id+'_stroke'); 458 this.setAttr(node,'dashstyle', 'Dash'); 459 }; 460 461 /** 462 * Sets an elements stroke width. 463 * @param {Object} el Reference to the geometry element. 464 * @param {int} width The new stroke width to be assigned to the element. 465 */ 466 JXG.VMLRenderer.prototype.setObjectStrokeWidth = function(el, width) { 467 var w = this.evaluate(width), 468 node; 469 //w = (w>0)?w:0; 470 471 if (el.visPropOld['strokeWidth']==w) { 472 return; 473 } 474 475 node = el.rendNode; 476 this.setPropertyPrim(node,'stroked', 'true'); 477 if (w!=null) { 478 this.setPropertyPrim(node,'stroke-width',w); 479 } 480 el.visPropOld['strokeWidth'] = w; 481 }; 482 483 JXG.VMLRenderer.prototype.createPrim = function(type, id) { 484 var node, 485 fillNode = this.createNode('fill'), 486 strokeNode = this.createNode('stroke'), 487 shadowNode = this.createNode('shadow'), 488 pathNode; 489 490 this.setAttr(fillNode, 'id', this.container.id+'_'+id+'_fill'); 491 this.setAttr(strokeNode, 'id', this.container.id+'_'+id+'_stroke'); 492 this.setAttr(shadowNode, 'id', this.container.id+'_'+id+'_shadow'); 493 494 if (type=='circle' || type=='ellipse' ) { 495 node = this.createNode('oval'); 496 node.appendChild(fillNode); 497 node.appendChild(strokeNode); 498 node.appendChild(shadowNode); 499 } else if (type == 'polygon' || type == 'path' || type == 'shape' || type == 'line') { 500 node = this.createNode('shape'); 501 node.appendChild(fillNode); 502 node.appendChild(strokeNode); 503 node.appendChild(shadowNode); 504 pathNode = this.createNode('path'); 505 this.setAttr(pathNode, 'id', this.container.id+'_'+id+'_path'); 506 node.appendChild(pathNode); 507 } else { 508 node = this.createNode(type); 509 node.appendChild(fillNode); 510 node.appendChild(strokeNode); 511 node.appendChild(shadowNode); 512 } 513 node.style.position = 'absolute'; 514 this.setAttr(node, 'id', this.container.id+'_'+id); 515 516 return node; 517 }; 518 519 JXG.VMLRenderer.prototype.appendNodesToElement = function(element, type) { 520 if(type == 'shape' || type == 'path' || type == 'polygon') { 521 element.rendNodePath = this.getElementById(element.id+'_path'); 522 } 523 element.rendNodeFill = this.getElementById(element.id+'_fill'); 524 element.rendNodeStroke = this.getElementById(element.id+'_stroke'); 525 element.rendNodeShadow = this.getElementById(element.id+'_shadow'); 526 element.rendNode = this.getElementById(element.id); 527 }; 528 529 /* 530 // seems to be unused 531 JXG.VMLRenderer.prototype.makeArrow = function(node,el,idAppendix) { 532 var nodeStroke = el.rendNodeStroke; 533 this.setAttr(nodeStroke, 'endarrow', 'block'); 534 this.setAttr(nodeStroke, 'endarrowlength', 'long'); 535 }; 536 */ 537 538 JXG.VMLRenderer.prototype.makeArrows = function(el) { 539 var nodeStroke; 540 541 if (el.visPropOld['firstArrow']==el.visProp['firstArrow'] && el.visPropOld['lastArrow']==el.visProp['lastArrow']) { 542 return; 543 } 544 545 if(el.visProp['firstArrow']) { 546 nodeStroke = el.rendNodeStroke; 547 this.setAttr(nodeStroke, 'startarrow', 'block'); 548 this.setAttr(nodeStroke, 'startarrowlength', 'long'); 549 } 550 else { 551 nodeStroke = el.rendNodeStroke; 552 if(nodeStroke != null) { 553 this.setAttr(nodeStroke, 'startarrow', 'none'); 554 } 555 } 556 if(el.visProp['lastArrow']) { 557 nodeStroke = el.rendNodeStroke; 558 this.setAttr(nodeStroke, 'id', this.container.id+'_'+el.id+"stroke"); 559 this.setAttr(nodeStroke, 'endarrow', 'block'); 560 this.setAttr(nodeStroke, 'endarrowlength', 'long'); 561 } 562 else { 563 nodeStroke = el.rendNodeStroke; 564 if(nodeStroke != null) { 565 this.setAttr(nodeStroke, 'endarrow', 'none'); 566 } 567 } 568 el.visPropOld['firstArrow'] = el.visProp['firstArrow']; 569 el.visPropOld['lastArrow'] = el.visProp['lastArrow']; 570 }; 571 572 JXG.VMLRenderer.prototype.updateLinePrim = function(node,p1x,p1y,p2x,p2y,board) { 573 /* 574 this.setAttr(node, 'from', [p1x,p1y].join(',')); 575 this.setAttr(node, 'to', [p2x,p2y].join(',')); 576 */ 577 var s, r = this.resolution; 578 s = ['m ',r*p1x,', ',r*p1y,' l ',r*p2x,', ',r*p2y]; 579 this.updatePathPrim(node,s,board); 580 }; 581 582 JXG.VMLRenderer.prototype.updateCirclePrim = function(node,x,y,r) { 583 //node.setAttribute('style','left:'+(x-r)+'px; top:'+(y-r)+'px; width:'+(r*2)+'px; height:'+ (r*2)+'px'); 584 node.style.left = (x-r)+'px'; 585 node.style.top = (y-r)+'px'; 586 node.style.width = (r*2)+'px'; 587 node.style.height = (r*2)+'px'; 588 }; 589 590 JXG.VMLRenderer.prototype.updateRectPrim = function(node,x,y,w,h) { 591 node.style.left = (x)+'px'; 592 node.style.top = (y)+'px'; 593 if (w>=0) node.style.width = (w)+'px'; 594 if (h>=0) node.style.height = (h)+'px'; 595 }; 596 597 JXG.VMLRenderer.prototype.updateEllipsePrim = function(node,x,y,rx,ry) { 598 node.style.left = (x-rx)+'px'; 599 node.style.top = (y-ry)+'px'; 600 node.style.width = (rx*2)+'px'; 601 node.style.height = (ry*2)+'px'; 602 }; 603 604 JXG.VMLRenderer.prototype.updatePathPrim = function(node,pointString,board) { 605 var x = board.canvasWidth, 606 y = board.canvasHeight; 607 node.style.width = x; 608 node.style.height = y; 609 this.setAttr(node, 'coordsize', [(this.resolution*x),(this.resolution*y)].join(',')); 610 this.setAttr(node, 'path',pointString.join("")); 611 }; 612 613 JXG.VMLRenderer.prototype.updatePathStringPrim = function(el) { 614 var pStr = [], 615 //h = 3*el.board.canvasHeight, 616 //w = 100*el.board.canvasWidth, 617 i, scr, 618 r = this.resolution, 619 mround = Math.round, 620 symbm = ' m ', 621 symbl = ' l ', 622 nextSymb = symbm, 623 isNoPlot = (el.curveType!='plot'), 624 //isFunctionGraph = (el.curveType=='functiongraph'), 625 len = Math.min(el.numberPoints,8192); // otherwise IE 7 crashes in hilbert.html 626 627 if (el.numberPoints<=0) { return ''; } 628 if (isNoPlot && el.board.options.curve.RDPsmoothing) { 629 el.points = this.RamenDouglasPeuker(el.points,1.0); 630 } 631 len = Math.min(len,el.points.length); 632 633 for (i=0; i<len; i++) { 634 scr = el.points[i].scrCoords; 635 if (isNaN(scr[1]) || isNaN(scr[2]) /* || Math.abs(scr[1])>w || (isFunctionGraph && (scr[2]>h || scr[2]<-0.5*h))*/ ) { // PenUp 636 nextSymb = symbm; 637 } else { 638 // IE has problems with values being too far away. 639 if (scr[1]>20000.0) { scr[1] = 20000.0; } 640 else if (scr[1]<-20000.0) { scr[1] = -20000.0; } 641 if (scr[2]>20000.0) { scr[2] = 20000.0; } 642 else if (scr[2]<-20000.0) { scr[2] = -20000.0; } 643 644 pStr.push([nextSymb,mround(r*scr[1]),', ',mround(r*scr[2])].join('')); 645 nextSymb = symbl; 646 } 647 } 648 pStr.push(' e'); 649 return pStr; 650 }; 651 652 JXG.VMLRenderer.prototype.updatePathStringPoint = function(el, size, type) { 653 var s = [], 654 scr = el.coords.scrCoords, 655 sqrt32 = size*Math.sqrt(3)*0.5, 656 s05 = size*0.5, 657 r = this.resolution; 658 659 if(type == 'x') { 660 s.push(['m ',(r*(scr[1]-size)),', ',(r*(scr[2]-size)),' l ', 661 (r*(scr[1]+size)),', ',(r*(scr[2]+size)),' m ', 662 (r*(scr[1]+size)),', ',(r*(scr[2]-size)),' l ', 663 (r*(scr[1]-size)),', ',(r*(scr[2]+size))].join('')); 664 } 665 else if(type == '+') { 666 s.push(['m ',(r*(scr[1]-size)),', ',(r*(scr[2])),' l ', 667 (r*(scr[1]+size)),', ',(r*(scr[2])),' m ', 668 (r*(scr[1])),', ',(r*(scr[2]-size)),' l ', 669 (r*(scr[1])),', ',(r*(scr[2]+size))].join('')); 670 } 671 else if(type == '<>') { 672 s.push(['m ',(r*(scr[1]-size)),', ',(r*(scr[2])),' l ', 673 (r*(scr[1])),', ',(r*(scr[2]+size)),' l ', 674 (r*(scr[1]+size)),', ',(r*(scr[2])),' l ', 675 (r*(scr[1])),', ',(r*(scr[2]-size)),' x e ' 676 ].join('')); 677 } 678 else if(type == '^') { 679 s.push(['m ',(r*(scr[1])),', ',(r*(scr[2]-size)),' l ', 680 Math.round(r*(scr[1]-sqrt32)),', ',(r*(scr[2]+s05)),' l ', 681 Math.round(r*(scr[1]+sqrt32)),', ',(r*(scr[2]+s05)),' x e ' 682 ].join('')); 683 } 684 else if(type == 'v') { 685 s.push(['m ',(r*(scr[1])),', ',(r*(scr[2]+size)),' l ', 686 Math.round(r*(scr[1]-sqrt32)),', ',(r*(scr[2]-s05)),' l ', 687 Math.round(r*(scr[1]+sqrt32)),', ',(r*(scr[2]-s05)),' x e ' 688 ].join('')); 689 } 690 else if(type == '>') { 691 s.push(['m ',(r*(scr[1]+size)),', ',(r*(scr[2])),' l ', 692 (r*(scr[1]-s05)),', ',Math.round(r*(scr[2]-sqrt32)),' l ', 693 (r*(scr[1]-s05)),', ',Math.round(r*(scr[2]+sqrt32)), 694 //' x e ' 695 ' l ',(r*(scr[1]+size)),', ',(r*(scr[2])) 696 ].join('')); 697 } 698 else if(type == '<') { 699 s.push(['m ',(r*(scr[1]-size)),', ',(r*(scr[2])),' l ', 700 (r*(scr[1]+s05)),', ',Math.round(r*(scr[2]-sqrt32)),' l ', 701 (r*(scr[1]+s05)),', ',Math.round(r*(scr[2]+sqrt32)),' x e ' 702 ].join('')); 703 } 704 return s; 705 } 706 707 JXG.VMLRenderer.prototype.updatePolygonPrim = function(node,el) { 708 var minX = el.vertices[0].coords.scrCoords[1], 709 maxX = el.vertices[0].coords.scrCoords[1], 710 minY = el.vertices[0].coords.scrCoords[2], 711 maxY = el.vertices[0].coords.scrCoords[2], 712 i, 713 len = el.vertices.length, 714 scr, x, y, 715 pStr = []; 716 717 this.setAttr(node, 'stroked', 'false'); 718 for(i=1; i<len-1; i++) { 719 scr = el.vertices[i].coords.scrCoords; 720 if(scr[1] < minX) { 721 minX = scr[1]; 722 } 723 else if(scr[1] > maxX) { 724 maxX = scr[1]; 725 } 726 if(scr[2] < minY) { 727 minY = scr[2]; 728 } 729 else if(scr[2] > maxY) { 730 maxY = scr[2]; 731 } 732 } 733 734 x = Math.round(maxX-minX); // Breite des umgebenden Rechtecks? 735 y = Math.round(maxY-minY); // Hoehe des umgebenden Rechtecks? 736 737 if (!isNaN(x) && !isNaN(y)) { 738 node.style.width = x; 739 node.style.height = y; 740 this.setAttr(node, 'coordsize', x+','+y); 741 } 742 743 scr = el.vertices[0].coords.scrCoords; 744 pStr.push(["m ",scr[1],",",scr[2]," l "].join('')); 745 746 for(i=1; i<len-1; i++) { 747 scr = el.vertices[i].coords.scrCoords; 748 pStr.push(scr[1] + "," + scr[2]); 749 if(i<len-2) { 750 pStr.push(", "); 751 } 752 } 753 pStr.push(" x e"); 754 755 this.setAttr(node, 'path',pStr.join("")); 756 }; 757 758 JXG.VMLRenderer.prototype.appendChildPrim = function(node,level) { 759 if (!JXG.exists(level)) level = 0; // For trace nodes 760 node.style.zIndex = level; 761 this.container.appendChild(node); 762 }; 763 764 JXG.VMLRenderer.prototype.setPropertyPrim = function(node,key,val) { 765 var keyVml = '', 766 node2, v; 767 768 switch (key) { 769 case 'stroke': keyVml = 'strokecolor'; break; 770 case 'stroke-width': keyVml = 'strokeweight'; break; 771 case 'stroke-dasharray': keyVml = 'dashstyle'; break; 772 } 773 if (keyVml!='') { 774 v = this.evaluate(val); 775 this.setAttr(node, keyVml, v); 776 } 777 }; 778 779 JXG.VMLRenderer.prototype.drawVerticalGrid = function(topLeft, bottomRight, gx, board) { 780 var node = this.createPrim('path', 'gridx'), 781 gridArr = []; 782 783 while(topLeft.scrCoords[1] < bottomRight.scrCoords[1] + gx - 1) { 784 gridArr.push(' m ' + (this.resolution*topLeft.scrCoords[1]) + 785 ', ' + 0 + 786 ' l ' + (this.resolution*topLeft.scrCoords[1]) + 787 ', ' + (this.resolution*board.canvasHeight)+' '); 788 topLeft.setCoordinates(JXG.COORDS_BY_SCREEN, [topLeft.scrCoords[1] + gx, topLeft.scrCoords[2]]); 789 } 790 this.updatePathPrim(node, gridArr, board); 791 return node; 792 }; 793 794 JXG.VMLRenderer.prototype.drawHorizontalGrid = function(topLeft, bottomRight, gy, board) { 795 var node = this.createPrim('path', 'gridy'), 796 gridArr = []; 797 while(topLeft.scrCoords[2] <= bottomRight.scrCoords[2] + gy - 1) { 798 gridArr.push(' m ' + 0 + 799 ', ' + (this.resolution*topLeft.scrCoords[2]) + 800 ' l ' + (this.resolution*board.canvasWidth) + 801 ', ' + (this.resolution*topLeft.scrCoords[2])+' '); 802 topLeft.setCoordinates(JXG.COORDS_BY_SCREEN, [topLeft.scrCoords[1], topLeft.scrCoords[2] + gy]); 803 } 804 this.updatePathPrim(node, gridArr, board); 805 return node; 806 }; 807