2.1 --- a/libxml2dom/events.py Sun Mar 25 01:57:53 2007 +0000
2.2 +++ b/libxml2dom/events.py Sun Mar 25 01:59:19 2007 +0000
2.3 @@ -1,7 +1,8 @@
2.4 #!/usr/bin/env python
2.5
2.6 """
2.7 -DOM events support.
2.8 +DOM Level 3 Events support, with SVG Tiny 1.2 implementation additions.
2.9 +See: http://www.w3.org/TR/DOM-Level-3-Events/events.html
2.10
2.11 Copyright (C) 2007 Paul Boddie <paul@boddie.org.uk>
2.12
2.13 @@ -20,39 +21,63 @@
2.14 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
2.15 """
2.16
2.17 +import time
2.18 +
2.19 +XML_EVENTS_NAMESPACE = "http://www.w3.org/2001/xml-events"
2.20 +
2.21 class EventException(Exception):
2.22
2.23 UNSPECIFIED_EVENT_TYPE_ERR = 0
2.24 DISPATCH_REQUEST_ERR = 1
2.25
2.26 +class DocumentEvent:
2.27 +
2.28 + "An event interface supportable by documents."
2.29 +
2.30 + def canDispatch(self, namespaceURI, type):
2.31 + raise NotImplementedError, "canDispatch"
2.32 +
2.33 + def createEvent(self, eventType):
2.34 + raise NotImplementedError, "createEvent"
2.35 +
2.36 class Event:
2.37
2.38 + "An event class."
2.39 +
2.40 CAPTURING_PHASE = 1
2.41 AT_TARGET = 2
2.42 BUBBLING_PHASE = 3
2.43
2.44 - def __init__(self):
2.45 - type
2.46 - target
2.47 - currentTarget
2.48 - eventPhase
2.49 - bubbles
2.50 - cancelable
2.51 - timeStamp
2.52 - namespaceURI
2.53 - defaultPrevented
2.54 + def __init__(self, target, currentTarget):
2.55 +
2.56 + "Initialise the event."
2.57 +
2.58 + self.target = target
2.59 + self.currentTarget = currentTarget
2.60 + self.defaultPrevented = 0
2.61 +
2.62 + # Initialised later:
2.63 +
2.64 + self.type = None
2.65 + self.namespaceURI = None
2.66 +
2.67 + # DOM Level 3 Events:
2.68 +
2.69 + self.bubbles = None
2.70 + self.eventPhase = self.CAPTURING_PHASE
2.71 + self.timeStamp = time.time()
2.72
2.73 def initEvent(self, eventTypeArg, canBubbleArg, cancelableArg):
2.74 - pass
2.75 -
2.76 - def initEvent(self, eventTypeArg, canBubbleArg, cancelableArg):
2.77 - pass
2.78 + self.initEventNS(None, eventTypeArg, canBubbleArg, cancelableArg)
2.79
2.80 def initEventNS(self, namespaceURIArg, eventTypeArg, canBubbleArg, cancelableArg):
2.81 - pass
2.82 + self.namespaceURI = namespaceURIArg
2.83 + self.type = eventTypeArg
2.84 + self.bubbles = canBubbleArg
2.85 + self.cancelable = cancelableArg
2.86
2.87 def preventDefault(self):
2.88 - pass
2.89 + self.defaultPrevented = 1
2.90
2.91 def stopPropagation(self):
2.92 pass
2.93 @@ -78,7 +103,10 @@
2.94 def dispatchEvent(self, evt):
2.95 if not evt.type:
2.96 raise EventException(EventException.UNSPECIFIED_EVENT_TYPE_ERR)
2.97 - # NOTE: Dispatch on namespaceURI, type...
2.98 + # Dispatch on namespaceURI, type.
2.99 + for listener in self.listeners.get((evt.namespaceURI, evt.type), []):
2.100 + listener.handleEvent(evt)
2.101 + return evt.defaultPrevented
2.102
2.103 def removeEventListener(self, type, listener, useCapture):
2.104 self.removeEventListenerNS(None, type, listener, useCapture)
3.1 --- a/libxml2dom/svg.py Sun Mar 25 01:57:53 2007 +0000
3.2 +++ b/libxml2dom/svg.py Sun Mar 25 01:59:19 2007 +0000
3.3 @@ -1,8 +1,9 @@
3.4 #!/usr/bin/env python
3.5
3.6 """
3.7 -SVG-specific document support. See:
3.8 -http://www.w3.org/TR/SVGMobile12/python-binding.html
3.9 +SVG-specific document support.
3.10 +See: http://www.w3.org/TR/SVGMobile12/python-binding.html
3.11 +See: http://www.w3.org/TR/SVGMobile12/svgudom.html
3.12
3.13 Copyright (C) 2007 Paul Boddie <paul@boddie.org.uk>
3.14
3.15 @@ -22,16 +23,38 @@
3.16 """
3.17
3.18 import libxml2dom
3.19 +from libxml2dom.events import *
3.20 from libxml2dom.macrolib import *
3.21 -from libxml2dom.macrolib import \
3.22 - createDocument as Node_createDocument, \
3.23 - parseString as Node_parseString, parseURI as Node_parseURI, \
3.24 - parseFile as Node_parseFile, \
3.25 - toString as Node_toString, toStream as Node_toStream, \
3.26 - toFile as Node_toFile
3.27 +import xml.dom
3.28 +import math
3.29
3.30 SVG_NAMESPACE = "http://www.w3.org/2000/svg"
3.31
3.32 +class _Exception(Exception):
3.33 +
3.34 + "A generic SVG exception."
3.35 +
3.36 + def __init__(self, code):
3.37 + Exception.__init__(self, code)
3.38 + self.code = code
3.39 +
3.40 +class SVGException(_Exception):
3.41 +
3.42 + "An SVG exception."
3.43 +
3.44 + SVG_WRONG_TYPE_ERR = 0
3.45 + SVG_INVALID_VALUE_ERR = 1
3.46 + SVG_MATRIX_NOT_INVERTABLE = 2
3.47 +
3.48 +class GlobalException(_Exception):
3.49 +
3.50 + "A global exception."
3.51 +
3.52 + NOT_CONNECTED_ERR = 1
3.53 + ENCODING_ERR = 2
3.54 + DENIED_ERR = 3
3.55 + UNKNOWN_ERR = 4
3.56 +
3.57 class SVGImplementation(libxml2dom.Implementation):
3.58
3.59 "Contains an SVG-specific implementation."
3.60 @@ -54,7 +77,257 @@
3.61 else:
3.62 return libxml2dom.Implementation.get_node(self, _node, context_node)
3.63
3.64 -class SVGElement(libxml2dom.Node): # Element, EventTarget, TraitAccess, ElementTraversal
3.65 +# Interfaces and helper classes.
3.66 +
3.67 +class AsyncStatusCallback:
3.68 +
3.69 + "An asynchronous callback interface."
3.70 +
3.71 + def operationComplete(self, status):
3.72 + pass
3.73 +
3.74 +class AsyncURLStatus:
3.75 +
3.76 + "The status of a URL retrieval operation."
3.77 +
3.78 + def __init__(self, success, contentType, content):
3.79 + self.success, self.contentType, self.content = success, contentType, content
3.80 +
3.81 +class SVGGlobal: # Global, EventListenerInitializer2
3.82 +
3.83 + "An SVG global."
3.84 +
3.85 + def __init__(self, document): # parent
3.86 +
3.87 + "Initialise the global with the given 'document'."
3.88 +
3.89 + self.document = document
3.90 +
3.91 + def createConnection(self):
3.92 + raise NotImplementedError, "createConnection"
3.93 +
3.94 + def createTimer(self, initialInterval, repeatInterval):
3.95 + raise NotImplementedError, "createTimer"
3.96 +
3.97 + def gotoLocation(self, newIRI):
3.98 + raise NotImplementedError, "gotoLocation"
3.99 +
3.100 + def binaryToString(self, octets, encoding):
3.101 + raise NotImplementedError, "binaryToString"
3.102 +
3.103 + def stringToBinary(self, data, encoding):
3.104 + raise NotImplementedError, "stringToBinary"
3.105 +
3.106 + def getURL(self, iri, callback):
3.107 +
3.108 + # NOTE: Not asynchronous.
3.109 + # NOTE: The urlopen function may not support IRIs.
3.110 + # No exceptions are supposed to be raised, which is a bit nasty.
3.111 +
3.112 + f = urllib.urlopen(iri)
3.113 + try:
3.114 + try:
3.115 + content = f.read()
3.116 + contentType = f.headers["Content-Type"]
3.117 + callback.operationComplete(AsyncURLStatus(1, contentType, content))
3.118 + except:
3.119 + callback.operationComplete(AsyncURLStatus(0, None, None))
3.120 + finally:
3.121 + f.close()
3.122 +
3.123 + def postURL(self, iri, data, callback, type, encoding):
3.124 + raise NotImplementedError, "postURL"
3.125 +
3.126 + def parseXML(self, data, contextDoc):
3.127 + doc = parseString(data)
3.128 + return contextDoc.importNode(doc.documentElement, 1)
3.129 +
3.130 +class SVGLocatable:
3.131 +
3.132 + "A locatable interface."
3.133 +
3.134 + pass
3.135 +
3.136 +class SVGMatrix:
3.137 +
3.138 + """
3.139 + A matrix.
3.140 + See: http://www.w3.org/TR/SVGMobile12/svgudom.html#svg__SVGMatrix
3.141 + """
3.142 +
3.143 + def __init__(self, a, b, c, d, e, f):
3.144 + self.matrix = a, b, c, d, e, f
3.145 +
3.146 + def getComponent(self, index):
3.147 +
3.148 + """
3.149 + Return the component with the given 'index' (starting at zero) from the
3.150 + sequence a, b, c, d, e, f where each element corresponds to the matrix
3.151 + as follows:
3.152 +
3.153 + [ a c e ]
3.154 + [ b d f ]
3.155 + [ 0 0 1 ]
3.156 + """
3.157 +
3.158 + try:
3.159 + return self.matrix[index]
3.160 + except IndexError:
3.161 + raise xml.dom.DOMException(xml.dom.INDEX_SIZE_ERR)
3.162 +
3.163 + def mMultiply(self, secondMatrix):
3.164 +
3.165 + """
3.166 + Multiply this matrix with 'secondMatrix' and update its contents to the
3.167 + result of the multiplication operation defined as follows:
3.168 +
3.169 + [ a c e ] [ A C E ]
3.170 + [ b d f ] [ B D F ]
3.171 + [ 0 0 1 ] [ 0 0 1 ]
3.172 +
3.173 + Return this object as a result.
3.174 + """
3.175 +
3.176 + a, b, c, d, e, f = self.matrix
3.177 + A, B, C, D, E, F = secondMatrix.matrix
3.178 + self.matrix = a*A + c*B, b*A + d*B, a*C + c*D, b*C + d*D, a*E + c*F + e, b*E + d*F + f
3.179 + return self
3.180 +
3.181 + def inverse(self):
3.182 +
3.183 + """
3.184 + det = ad - cb
3.185 +
3.186 + See (for example): http://mathworld.wolfram.com/MatrixInverse.html
3.187 + """
3.188 +
3.189 + det = a*d - c*b
3.190 + if det != 0:
3.191 + m = 1/det
3.192 + a, b, c, d, e, f = self.matrix
3.193 + self.matrix = m * d, m * -b, m * -c, m * a, m * (c*f - e*d), m * (e*b - a*f)
3.194 + return self
3.195 + else:
3.196 + raise SVGException(SVGException.SVG_MATRIX_NOT_INVERTABLE)
3.197 +
3.198 + def mTranslate(self, x, y):
3.199 +
3.200 + """
3.201 + [ 1 0 x ]
3.202 + [ 0 1 y ]
3.203 + [ 0 0 1 ]
3.204 + """
3.205 +
3.206 + return self.mMultiply(SVGMatrix(1, 0, 0, 1, x, y))
3.207 +
3.208 + def mScale(self, scaleFactor):
3.209 +
3.210 + """
3.211 + [ scaleFactor 0 0 ]
3.212 + [ 0 scaleFactor 0 ]
3.213 + [ 0 0 1 ]
3.214 + """
3.215 +
3.216 + return self.mMultiply(SVGMatrix(scaleFactor, 0, 0, scaleFactor, 0, 0))
3.217 +
3.218 + def mRotate(self, angle):
3.219 +
3.220 + """
3.221 + [ cos(angle) -sin(angle) 0 ]
3.222 + [ sin(angle) cos(angle) 0 ]
3.223 + [ 0 0 1 ]
3.224 + """
3.225 +
3.226 + return self.mMultiply(SVGMatrix(math.cos(angle), math.sin(angle), -math.sin(angle), math.cos(angle), 0, 0))
3.227 +
3.228 +class SVGPath:
3.229 +
3.230 + """
3.231 + A path.
3.232 + See: http://www.w3.org/TR/SVGMobile12/svgudom.html#svg__SVGPath
3.233 + See: http://www.w3.org/TR/SVGMobile12/paths.html
3.234 + """
3.235 +
3.236 + MOVE_TO = 77
3.237 + LINE_TO = 76
3.238 + CURVE_TO = 67
3.239 + QUAD_TO = 81
3.240 + CLOSE = 90
3.241 +
3.242 + def __init__(self):
3.243 + self.segments = []
3.244 +
3.245 + def _numberOfSegments(self):
3.246 + return len(self.segments)
3.247 +
3.248 + numberOfSegments = property(_numberOfSegments)
3.249 +
3.250 + def getSegment(self, cmdIndex):
3.251 + try:
3.252 + return self.segments[cmdIndex][0]
3.253 + except IndexError:
3.254 + raise xml.dom.DOMException(xml.dom.INDEX_SIZE_ERR)
3.255 +
3.256 + def getSegmentParam(self, cmdIndex, paramIndex):
3.257 + try:
3.258 + return self.segments[cmdIndex][1][paramIndex]
3.259 + except IndexError:
3.260 + raise xml.dom.DOMException(xml.dom.INDEX_SIZE_ERR)
3.261 +
3.262 + def moveTo(self, x, y):
3.263 + self.segments.append((self.MOVE_TO, (x, y)))
3.264 +
3.265 + def lineTo(self, x, y):
3.266 + self.segments.append((self.LINE_TO, (x, y)))
3.267 +
3.268 + def quadTo(self, x1, y1, x2, y2):
3.269 + self.segments.append((self.QUAD_TO, (x1, y1, x2, y2)))
3.270 +
3.271 + def curveTo(self, x1, y1, x2, y2, x3, y3):
3.272 + self.segments.append((self.CURVE_TO, (x1, y1, x2, y2, x3, y3)))
3.273 +
3.274 + def close(self):
3.275 + self.segments.append((self.CLOSE,))
3.276 +
3.277 +class SVGPoint:
3.278 +
3.279 + "A point."
3.280 +
3.281 + def __init__(self, x, y):
3.282 + self.x = x
3.283 + self.y = y
3.284 +
3.285 +class SVGRect:
3.286 +
3.287 + "A rectangle."
3.288 +
3.289 + def __init__(self, x, y, width, height):
3.290 + self.x, self.y, self.width, self.height = x, y, width, height
3.291 +
3.292 +class SVGRGBColor:
3.293 +
3.294 + "A colour."
3.295 +
3.296 + def __init__(self, red, green, blue):
3.297 + self.red, self.green, self.blue = red, green, blue
3.298 +
3.299 +# Node classes.
3.300 +
3.301 +class SVGDocument(libxml2dom.Document, DocumentEvent, EventTarget):
3.302 +
3.303 + "An SVG-specific document node."
3.304 +
3.305 + def __init__(self, node, impl):
3.306 +
3.307 + """
3.308 + Initialise the document with the given 'node', implementation 'impl',
3.309 + and global (SVGGlobal) details.
3.310 + """
3.311 +
3.312 + libxml2dom.Document.__init__(self, node, impl)
3.313 + self.global_ = SVGGlobal(self) # parent
3.314 +
3.315 +class SVGElement(libxml2dom.Node, EventTarget): # (Element), TraitAccess, ElementTraversal
3.316
3.317 "An SVG-specific element."
3.318
3.319 @@ -66,15 +339,34 @@
3.320
3.321 id = property(_id, _setId)
3.322
3.323 -class SVGLocatable:
3.324 -
3.325 - "A locatable interface."
3.326 -
3.327 class SVGLocatableElement(SVGElement, SVGLocatable):
3.328
3.329 "A locatable element."
3.330
3.331 -class SVGSVGElement(SVGLocatableElement): # SVGTimedElement
3.332 + pass
3.333 +
3.334 +class SVGTimedElement(SVGElement): # smil::ElementTimeControl
3.335 +
3.336 + "A timed element."
3.337 +
3.338 + def __init__(self, *args):
3.339 +
3.340 + "Initialise the element with the underlying 'args'."
3.341 +
3.342 + SVGElement.__init__(self, *args)
3.343 + self.document_time = 0
3.344 + self.paused = 0
3.345 +
3.346 + def _isPaused(self):
3.347 + return self.paused
3.348 +
3.349 + def pauseElement(self):
3.350 + self.paused = 1
3.351 +
3.352 + def resumeElement(self):
3.353 + self.paused = 0
3.354 +
3.355 +class SVGSVGElement(SVGLocatableElement, SVGTimedElement):
3.356
3.357 "An SVG-specific top-level element."
3.358
3.359 @@ -90,11 +382,62 @@
3.360 NAV_LEFT = 10
3.361 NAV_UP_LEFT = 11
3.362
3.363 -class SVGDocument(libxml2dom.Document):
3.364 + def __init__(self, *args):
3.365 +
3.366 + "Initialise the element with the underlying 'args'."
3.367 +
3.368 + SVGTimedElement.__init__(self, *args)
3.369 + self.scale = 1
3.370 + self.rotate = 0
3.371 + self.translate = SVGPoint(0, 0)
3.372 +
3.373 + def _currentScale(self):
3.374 + return self.scale
3.375 +
3.376 + def _currentRotate(self):
3.377 + return self.rotate
3.378 +
3.379 + def _currentTranslate(self):
3.380 + return self.translate
3.381 +
3.382 + def _viewport(self):
3.383 + attr = self.getAttribute("viewBox")
3.384 + if attr is None:
3.385 + return attr
3.386 + l = map(int, attr.split())
3.387 + return SVGRect(*l)
3.388 +
3.389 + def getCurrentTime(self):
3.390 + return self.document_time
3.391
3.392 - "An SVG-specific document node."
3.393 + def setCurrentTime(self, setCurrentTime):
3.394 + self.document_time = setCurrentTime
3.395 +
3.396 + def createSVGMatrixComponents(self, a, b, c, d, e, f):
3.397 + return SVGMatrix(a, b, c, d, e, f)
3.398 +
3.399 + def createSVGRect(self):
3.400 + return SVGRect(0, 0, 0, 0)
3.401 +
3.402 + def createSVGPath(self):
3.403 + return SVGPath()
3.404
3.405 - # NOTE: Define global (SVGGlobal).
3.406 + def createSVGRGBColor(self, red, green, blue):
3.407 + return SVGRGBColor(red, green, blue)
3.408 +
3.409 + def moveFocus(self, motionType):
3.410 + raise NotImplementedError, "moveFocus"
3.411 +
3.412 + def setFocus(self, object):
3.413 + raise NotImplementedError, "setFocus"
3.414 +
3.415 + def getCurrentFocusedObject(self):
3.416 + raise NotImplementedError, "getCurrentFocusedObject"
3.417 +
3.418 + currentScale = property(_currentScale)
3.419 + currentRotate = property(_currentRotate)
3.420 + currentTranslate = property(_currentTranslate)
3.421 + viewport = property(_viewport)
3.422
3.423 # Convenience functions.
3.424