Package pyjamas :: Package Canvas :: Module GWTCanvasImplIE6
[hide private]
[frames] | no frames]

Source Code for Module pyjamas.Canvas.GWTCanvasImplIE6

  1  """ 
  2  * Copyright 2008 Google Inc. 
  3  * 
  4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not 
  5  * use this file except in compliance with the License. You may obtain a copy of 
  6  * the License at 
  7  * 
  8  * http:#www.apache.org/licenses/LICENSE-2.0 
  9  * 
 10  * Unless required by applicable law or agreed to in writing, software 
 11  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 
 12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 
 13  * License for the specific language governing permissions and limitations under 
 14  * the License. 
 15  """ 
 16   
 17  import math 
 18   
 19  from pyjamas import DOM 
 20  from __pyjamas__ import JS, doc 
 21  from pyjamas.ui.Widget import Widget 
 22   
 23   
 24   
 25  from pyjamas.Canvas.GWTCanvasImplIEConsts import BUTT, DESTINATION_OVER, SOURCE_OVER 
 26  from pyjamas.Canvas import GWTCanvasConsts  
 27  from pyjamas.Canvas.JSOStack import JSOStack  
 28  from pyjamas.Canvas import PathElement  
 29  from pyjamas.Canvas.VMLContext import VMLContext 
 30   
31 -def addNamespace():
32 JS(""" 33 if (!$doc.namespaces["v"]) { 34 $doc.namespaces.add("v", "urn:schemas-microsoft-com:vml"); 35 $doc.createStyleSheet().cssText = "v\\:*{behavior:url(#default#VML);}"; 36 } 37 """)
38 39 40 """* 41 * Deferred binding implementation of GWTCanvas for IE6. It is an implementation 42 * of canvas on top of VML. 43 """
44 -class GWTCanvasImplIE6:
45
46 - def __init__(self):
47 try: 48 ns = doc().namespaces.item("v") 49 except: 50 doc().namespaces.add("v", "urn:schemas-microsoft-com:vml") 51 doc().createStyleSheet().cssText = "v\\:*{behavior:url(#default#VML);}" 52 53 54 55 """* 56 * This will be used for an array join. Currently a bit faster than 57 * StringBuilder.append() & toString() because of the extra collections 58 * overhead. 59 """ 60 self.pathStr = JSOStack() 61 62 """* 63 * Stack uses preallocated arrays which makes push() slightly faster than 64 * [].push() since each push is simply an indexed setter. 65 """ 66 self.contextStack = [] 67 68 self.currentX = 0 69 70 self.currentY = 0 71 72 self.parentElement = None 73 74 self.parentHeight = 0 75 76 self.parentWidth = 0
77 78 79
80 - def arc(self, x, y, radius, startAngle, endAngle, anticlockwise):
81 self.pathStr.append(PathElement.arc(x, y, radius, startAngle, endAngle, 82 anticlockwise, self))
83 84
85 - def beginPath(self):
86 self.pathStr.clear()
87 88
89 - def clear(self, width=0, height=0):
90 self.pathStr.clear() 91 DOM.setInnerHTML(self.parentElement, "")
92
93 - def closePath(self):
94 self.pathStr.append(PathElement.closePath())
95 96
97 - def createElement(self):
98 self.context = VMLContext() 99 self.matrix = self.context.matrix 100 return self.createParentElement()
101 102
103 - def createParentElement(self):
104 self.parentElement = DOM.createElement("div") 105 DOM.setStyleAttribute(self.parentElement, "overflow", "hidden") 106 return self.parentElement
107 108
109 - def cubicCurveTo(self, cp1x, cp1y, cp2x, cp2y, x, y):
110 self.pathStr.append(PathElement.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y, self)) 111 self.currentX = x 112 self.currentY = y
113 114
115 - def drawImage(self, img, *args):
116 117 if isinstance(img, Widget): 118 img = img.getElement() 119 fullWidth = img.width 120 fullHeight = img.height 121 122 if len(args) == 8: 123 sourceX = args[0] 124 sourceY = args[1] 125 sourceWidth = args[2] 126 sourceHeight = args[3] 127 destX = args[4] 128 destY = args[5] 129 destWidth = args[6] 130 destHeight = args[7] 131 elif len(args) == 4: 132 sourceX = 0 133 sourceY = 0 134 sourceWidth = fullWidth 135 sourceHeight = fullHeight 136 destX = args[0] 137 destY = args[1] 138 destWidth = args[2] 139 destHeight = args[3] 140 elif len(args) == 2: 141 sourceX = 0 142 sourceY = 0 143 sourceWidth = fullWidth 144 sourceHeight = fullHeight 145 destX = args[0] 146 destY = args[1] 147 destWidth = fullWidth 148 destHeight = fullHeight 149 150 vmlStr = [] # JSOStack.getScratchArray() 151 152 vmlStr.append("<v:group style=\"position:absolute;width:10;height:10;") 153 dX = self.getCoordX(self.matrix, destX, destY) 154 dY = self.getCoordY(self.matrix, destX, destY) 155 156 # If we have a transformation matrix with rotation/scale, we 157 # apply a filter 158 if self.context.matrix[0] != 1 or self.context.matrix[1] != 0: 159 160 # We create a padding bounding box to prevent clipping. 161 vmlStr.append("padding-right:") 162 vmlStr.append(str(self.parentWidth) + "px;") 163 vmlStr.append("padding-bottom:") 164 vmlStr.append(str(self.parentHeight) + "px;") 165 vmlStr.append("filter:progid:DXImageTransform.Microsoft.Matrix(M11='") 166 vmlStr.append("" + str(self.matrix[0])) 167 vmlStr.append("',") 168 vmlStr.append("M12='") 169 vmlStr.append("" + str(self.matrix[1])) 170 vmlStr.append("',") 171 vmlStr.append("M21='") 172 vmlStr.append(str(self.matrix[3])) 173 vmlStr.append("',") 174 vmlStr.append("M22='") 175 vmlStr.append(str(self.matrix[4])) 176 vmlStr.append("',") 177 vmlStr.append("Dx='") 178 vmlStr.append(str(math.floor(((dX / 10))))) 179 vmlStr.append("',") 180 vmlStr.append("Dy='") 181 vmlStr.append(str(math.floor(((dY / 10))))) 182 vmlStr.append("', SizingMethod='clip');") 183 184 else: 185 vmlStr.append("left:") 186 vmlStr.append("%dpx;" % int(dX / 10)) 187 vmlStr.append("top:") 188 vmlStr.append("%dpx" % int(dY / 10)) 189 190 191 vmlStr.append("\" coordsize=\"100,100\" coordorigin=\"0,0\"><v:image src=\"") 192 vmlStr.append(DOM.getAttribute(img, "src")) 193 vmlStr.append("\" style=\"") 194 195 vmlStr.append("width:") 196 vmlStr.append(str(int(destWidth * 10))) 197 vmlStr.append(";height:") 198 vmlStr.append(str(int(destHeight * 10))) 199 vmlStr.append(";\" cropleft=\"") 200 vmlStr.append(str(sourceX / fullWidth)) 201 vmlStr.append("\" croptop=\"") 202 vmlStr.append(str(sourceY / fullHeight)) 203 vmlStr.append("\" cropright=\"") 204 vmlStr.append(str((fullWidth - sourceX - sourceWidth) / fullWidth)) 205 vmlStr.append("\" cropbottom=\"") 206 vmlStr.append(str((fullHeight - sourceY - sourceHeight) / fullHeight)) 207 vmlStr.append("\"/></v:group>") 208 209 self.insert("BeforeEnd", ''.join(vmlStr))
210 211
212 - def fill(self):
213 if len(self.pathStr) == 0: 214 return 215 216 shapeStr = [] #JSOStack.getScratchArray() 217 shapeStr.append("<v:shape style=\"position:absolute;width:10;height:10;\" coordsize=\"100,100\" fillcolor=\"") 218 shapeStr.append(self.context.fillStyle) 219 shapeStr.append("\" stroked=\"f\" path=\"") 220 221 shapeStr.append(self.pathStr.join()) 222 223 shapeStr.append(" e\"><v:fill opacity=\"") 224 shapeStr.append(str(self.context.globalAlpha * self.context.fillAlpha)) 225 226 if (self.context.fillGradient is not None and 227 len(self.context.fillGradient.colorStops) > 0): 228 colorStops = self.context.fillGradient.colorStops 229 230 shapeStr.append("\" color=\"") 231 shapeStr.append(str(colorStops[0].color)) 232 shapeStr.append("\" color2=\"") 233 shapeStr.append(str(colorStops[colorStops.size() - 1].color)) 234 shapeStr.append("\" type=\"") 235 shapeStr.append(self.context.fillGradient.type) 236 237 minX = self.pathStr.getMinCoordX() 238 maxX = self.pathStr.getMaxCoordX() 239 minY = self.pathStr.getMinCoordY() 240 maxY = self.pathStr.getMaxCoordY() 241 242 dx = maxX - minX 243 dy = maxY - minY 244 245 fillLength = math.sqrt((dx * dx) + (dy * dy)) 246 gradLength = len(self.context.fillGradient) 247 248 # Now add all the color stops 249 colors = "" 250 for i in range(1, len(colorStops)): 251 cs = colorStops[i] 252 stopPosn = cs.offset * gradLength 253 # /(math.min(((stopPosn / fillLength) * 100), 100)) 254 colors += "%d%%" % (100 - int(((stopPosn / fillLength) * 100))) 255 colors += str(cs.color) + "," 256 if stopPosn > fillLength: 257 break 258 259 260 shapeStr.append("\" colors=\"") 261 # shapeStr.append(colors) 262 shapeStr.append("50% white,51% #0f0,100% #fff,") 263 shapeStr.append("\" angle=\"") 264 #shapeStr.append(str(self.context.fillGradient.angle)) 265 shapeStr.append("180" + "") 266 267 268 shapeStr.append("\"></v:fill></v:shape>") 269 daStr = ''.join(shapeStr) 270 # Window.alert(daStr) 271 self.insert(self.context.globalCompositeOperation, daStr)
272 273
274 - def fillRect(self, x, y, w, h):
275 w += x 276 h += y 277 self.beginPath() 278 self.moveTo(x, y) 279 self.lineTo(x, h) 280 self.lineTo(w, h) 281 self.lineTo(w, y) 282 self.closePath() 283 self.fill() 284 self.pathStr.clear()
285 286
287 - def getContext(self):
288 return self.context
289 290
291 - def getCoordX(self, matrix, x, y):
292 coordX = int(math.floor((math.floor(10 * (matrix[0] * x + matrix[1] 293 * y + matrix[2]) - 4.5)))) 294 # record current point to derive bounding box of current open path. 295 self.pathStr.logCoordX(coordX / 10) 296 return coordX
297 298
299 - def getCoordY(self, matrix, x, y):
300 coordY = int(math.floor((math.floor(10 * (matrix[3] * x + matrix[4] 301 * y + matrix[5]) - 4.5)))) 302 # record current point to derive bounding box of current open path. 303 self.pathStr.logCoordY(coordY / 10) 304 return coordY
305 306
307 - def getFillStyle(self):
308 return self.context.fillStyle
309 310
311 - def getGlobalAlpha(self):
312 return self.context.globalAlpha
313 314
316 if self.context.globalCompositeOperation == DESTINATION_OVER: 317 return GWTCanvasConsts.DESTINATION_OVER 318 else: 319 return GWTCanvasConsts.SOURCE_OVER
320 321 322
323 - def getLineCap(self):
324 if self.context.lineCap == BUTT: 325 return GWTCanvasConsts.BUTT 326 327 return self.context.lineCap
328 329
330 - def getLineJoin(self):
331 return self.context.lineJoin
332 333
334 - def getLineWidth(self):
335 return self.context.lineWidth
336 337
338 - def getMiterLimit(self):
339 return self.context.miterLimit
340 341
342 - def getStrokeStyle(self):
343 return self.context.strokeStyle
344 345
346 - def lineTo(self, x, y):
347 self.pathStr.append(PathElement.lineTo(x, y, self)) 348 self.currentX = x 349 self.currentY = y
350 351
352 - def moveTo(self, x, y):
353 self.pathStr.append(PathElement.moveTo(x, y, self)) 354 self.currentX = x 355 self.currentY = y
356 357
358 - def quadraticCurveTo(self, cpx, cpy, x, y):
359 cp1x = (self.currentX + 2.0 / 3.0 * (cpx - self.currentX)) 360 cp1y = (self.currentY + 2.0 / 3.0 * (cpy - self.currentY)) 361 cp2x = (cp1x + (x - self.currentX) / 3.0) 362 cp2y = (cp1y + (y - self.currentY) / 3.0) 363 self.pathStr.append(PathElement.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y, self)) 364 self.currentX = x 365 self.currentY = y
366 367
368 - def rect(self, x, y, w, h):
369 self.pathStr.append(PathElement.moveTo(x, y, self)) 370 self.pathStr.append(PathElement.lineTo(x + w, y, self)) 371 self.pathStr.append(PathElement.lineTo(x + w, y + h, self)) 372 self.pathStr.append(PathElement.lineTo(x, y + h, self)) 373 self.pathStr.append(PathElement.closePath()) 374 self.currentX = x 375 self.currentY = y + h
376 377
378 - def restoreContext(self):
379 if len(self.contextStack) > 0: 380 self.context = self.contextStack.pop() 381 self.matrix = self.context.matrix
382 383 384
385 - def rotate(self, angle):
386 s = math.sin(-angle) 387 c = math.cos(-angle) 388 a = self.matrix[0] 389 b = self.matrix[1] 390 m1 = a * c 391 m2 = b * s 392 self.matrix[0] = m1 - m2 393 m1 = a * s 394 m2 = b * c 395 self.matrix[1] = m1 + m2 396 a = self.matrix[3] 397 b = self.matrix[4] 398 m1 = a * c 399 m2 = b * s 400 self.matrix[3] = m1 - m2 401 m1 = a * s 402 m2 = b * c 403 self.matrix[4] = m1 + m2
404 405
406 - def saveContext(self):
407 self.contextStack.append(self.context) 408 self.context = VMLContext(self.context) 409 self.matrix = self.context.matrix
410 411
412 - def scale(self, x, y):
413 self.context.arcScaleX *= x 414 self.context.arcScaleY *= y 415 self.matrix[0] *= x 416 self.matrix[1] *= y 417 self.matrix[3] *= x 418 self.matrix[4] *= y
419 420
421 - def setBackgroundColor(self, element, color):
422 DOM.setStyleAttribute(element, "backgroundColor", color)
423 424
425 - def setCoordHeight(self, elem, height):
426 DOM.setElemAttribute(elem, "width", int(height)) 427 self.clear(0, 0)
428 429
430 - def setCoordWidth(self, elem, width):
431 DOM.setElemAttribute(elem, "width", int(width)) 432 self.clear(0, 0)
433 434
435 - def setCurrentX(self, currentX):
436 self.currentX = currentX
437 438
439 - def setCurrentY(self, currentY):
440 self.currentY = currentY
441 442
443 - def setFillStyle(self, gradient):
444 self.context.fillGradient = gradient
445 446
447 - def setFillStyle(self, fillStyle):
448 fillStyle = str(fillStyle).strip() 449 if fillStyle.startswith("rgba("): 450 end = fillStyle.find(")", 12) 451 if end > -1: 452 guts = fillStyle[5:end].split(",") 453 if len(guts) == 4: 454 self.context.fillAlpha = float(guts[3]) 455 self.context.fillStyle = "rgb(" + guts[0] + "," + guts[1] + "," + guts[2] + ")" 456 457 458 else: 459 self.context.fillAlpha = 1 460 self.context.fillStyle = fillStyle
461 462 463
464 - def setGlobalAlpha(self, globalAlpha):
465 self.context.globalAlpha = globalAlpha
466 467
468 - def setGlobalCompositeOperation(self, gco):
469 gco = gco.strip() 470 if gco.lower == GWTCanvasConsts.SOURCE_OVER: 471 self.context.globalCompositeOperation = SOURCE_OVER 472 elif gco.lower == GWTCanvasConsts.DESTINATION_OVER: 473 self.context.globalCompositeOperation = DESTINATION_OVER
474 475 476
477 - def setLineCap(self, lineCap):
478 if lineCap.strip().lower == GWTCanvasConsts.BUTT: 479 self.context.lineCap = BUTT 480 else: 481 self.context.lineCap = lineCap
482 483 484
485 - def setLineJoin(self, lineJoin):
486 self.context.lineJoin = lineJoin
487 488
489 - def setLineWidth(self, lineWidth):
490 self.context.lineWidth = lineWidth
491 492
493 - def setMiterLimit(self, miterLimit):
494 self.context.miterLimit = miterLimit
495
496 - def setParentElement(self, g):
497 self.parentElement = g
498 499
500 - def setPixelHeight(self, elem, height):
501 DOM.setStyleAttribute(elem, "height", str(height) + "px") 502 self.parentHeight = height
503 504
505 - def setPixelWidth(self, elem, width):
506 DOM.setStyleAttribute(elem, "width", str(width) + "px") 507 self.parentWidth = width
508 509
510 - def setStrokeStyle(self, gradient):
511 self.context.strokeGradient = gradient
512 513
514 - def setStrokeStyle(self, strokeStyle):
515 strokeStyle = str(strokeStyle).strip() 516 if strokeStyle.startswith("rgba("): 517 end = strokeStyle.find(")", 12) 518 if end > -1: 519 guts = strokeStyle[5:end].split(",") 520 if len(guts) == 4: 521 self.context.strokeAlpha = float(guts[3]) 522 self.context.strokeStyle = "rgb(" + guts[0] + "," + guts[1] + "," + guts[2] + ")" 523 524 525 else: 526 self.context.strokeAlpha = 1 527 self.context.strokeStyle = strokeStyle
528 529 530
531 - def stroke(self):
532 if len(self.pathStr) == 0: 533 return 534 535 shapeStr = [] #JSOStack.getScratchArray() 536 shapeStr.append("<v:shape style=\"position:absolute;width:10;height:10;\" coordsize=\"100,100\" filled=\"f\" strokecolor=\"") 537 shapeStr.append(str(self.context.strokeStyle)) 538 shapeStr.append("\" strokeweight=\"") 539 shapeStr.append(str(self.context.lineWidth)) 540 shapeStr.append("px\" path=\"") 541 542 shapeStr.append(self.pathStr.join()) 543 544 shapeStr.append(" e\"><v:stroke opacity=\"") 545 shapeStr.append(str(self.context.globalAlpha * self.context.strokeAlpha)) 546 shapeStr.append("\" miterlimit=\"") 547 shapeStr.append(str(self.context.miterLimit)) 548 shapeStr.append("\" joinstyle=\"") 549 shapeStr.append(self.context.lineJoin) 550 shapeStr.append("\" endcap=\"") 551 shapeStr.append(self.context.lineCap) 552 553 shapeStr.append("\"></v:stroke></v:shape>") 554 self.insert(self.context.globalCompositeOperation, ''.join(shapeStr))
555 556
557 - def strokeRect(self, x, y, w, h):
558 w += x 559 h += y 560 self.beginPath() 561 self.moveTo(x, y) 562 self.lineTo(x, h) 563 self.lineTo(w, h) 564 self.lineTo(w, y) 565 self.closePath() 566 self.stroke() 567 self.pathStr.clear()
568 569
570 - def transform(m11, m12, m21, m22, dx, dy):
571 a = self.matrix[0] 572 b = self.matrix[1] 573 self.matrix[0] = a * m11 + b * m21 574 self.matrix[1] = a * m12 + b * m22 575 self.matrix[2] += a * dx + b * dy 576 a = self.matrix[3] 577 b = self.matrix[4] 578 self.matrix[3] = a * m11 + b * m21 579 self.matrix[4] = a * m12 + b * m22 580 self.matrix[5] += a * dx + b * dy
581 582
583 - def translate(self, x, y):
584 self.matrix[2] += self.matrix[0] * x + self.matrix[1] * y 585 self.matrix[5] += self.matrix[3] * x + self.matrix[4] * y
586 587
588 - def insert(self, gco, html):
589 self.parentElement.insertAdjacentHTML(gco, html)
590