~ubuntu-branches/ubuntu/precise/fofix-dfsg/precise

« back to all changes in this revision

Viewing changes to src/Svg.py

  • Committer: Bazaar Package Importer
  • Author(s): Christian Hammers
  • Date: 2010-02-21 12:09:32 UTC
  • Revision ID: james.westby@ubuntu.com-20100221120932-6bh992d2u8dtj9gr
Tags: upstream-3.121
ImportĀ upstreamĀ versionĀ 3.121

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#####################################################################
 
2
# -*- coding: iso-8859-1 -*-                                        #
 
3
#                                                                   #
 
4
# Frets on Fire                                                     #
 
5
# Copyright (C) 2006 Sami Kyļæ½stilļæ½                                  #
 
6
#               2008 myfingershurt                                  #
 
7
#               2008 evilynux <evilynux@gmail.com>                  #
 
8
#                                                                   #
 
9
# This program is free software; you can redistribute it and/or     #
 
10
# modify it under the terms of the GNU General Public License       #
 
11
# as published by the Free Software Foundation; either version 2    #
 
12
# of the License, or (at your option) any later version.            #
 
13
#                                                                   #
 
14
# This program is distributed in the hope that it will be useful,   #
 
15
# but WITHOUT ANY WARRANTY; without even the implied warranty of    #
 
16
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     #
 
17
# GNU General Public License for more details.                      #
 
18
#                                                                   #
 
19
# You should have received a copy of the GNU General Public License #
 
20
# along with this program; if not, write to the Free Software       #
 
21
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,        #
 
22
# MA  02110-1301, USA.                                              #
 
23
#####################################################################
 
24
 
 
25
import re
 
26
import os
 
27
from xml import sax
 
28
from OpenGL.GL import *
 
29
from numpy import reshape, dot, transpose, identity, zeros, array, float32
 
30
from math import sin, cos
 
31
 
 
32
import Log
 
33
import Config
 
34
from Texture import Texture, TextureException
 
35
from PIL import Image
 
36
 
 
37
import DummyAmanith as amanith
 
38
haveAmanith = True
 
39
 
 
40
# Add support for 'foo in attributes' syntax
 
41
if not hasattr(sax.xmlreader.AttributesImpl, '__contains__'):
 
42
  sax.xmlreader.AttributesImpl.__contains__ = sax.xmlreader.AttributesImpl.has_key
 
43
 
 
44
#
 
45
#  Bugs and limitations:
 
46
#
 
47
#  - only the translate() and matrix() transforms are supported
 
48
#  - only paths are supported
 
49
#  - only constant color, linear gradient and radial gradient fill supported
 
50
#
 
51
 
 
52
Config.define("opengl",  "svgshaders",   bool,  False, text = "Use OpenGL SVG shaders",   options = {False: "No", True: "Yes"})
 
53
 
 
54
class SvgGradient:
 
55
  def __init__(self, gradientDesc, transform):
 
56
    self.gradientDesc = gradientDesc
 
57
    self.transform = transform
 
58
 
 
59
  def applyTransform(self, transform):
 
60
    m = dot(transform.matrix, self.transform.matrix)
 
61
    self.gradientDesc.SetMatrix(transform.getGMatrix(m))
 
62
 
 
63
class SvgContext:
 
64
  def __init__(self, geometry):
 
65
    self.kernel = amanith.GKernel()
 
66
    self.geometry = geometry
 
67
    self.drawBoard = amanith.GOpenGLBoard(geometry[0], geometry[0] + geometry[2],
 
68
                                          geometry[1], geometry[1] + geometry[3])
 
69
    self.drawBoard.SetShadersEnabled(Config.get("opengl", "svgshaders"))
 
70
    self.transform = SvgTransform()
 
71
    self.setGeometry(geometry)
 
72
    self.setProjection(geometry)
 
73
  
 
74
    # eat any possible OpenGL errors -- we can't handle them anyway
 
75
    try:
 
76
      glMatrixMode(GL_MODELVIEW)
 
77
    except:
 
78
      Log.warn("SVG renderer initialization failed; expect corrupted graphics. " +
 
79
               "To fix this, upgrade your OpenGL drivers and set your display " +
 
80
               "to 32 bit color precision.")
 
81
 
 
82
  def setGeometry(self, geometry = None):
 
83
    self.drawBoard.SetViewport(geometry[0], geometry[1],
 
84
                               geometry[2], geometry[3])
 
85
    self.transform.reset()
 
86
    self.transform.scale(geometry[2] / 640.0, geometry[3] / 480.0)
 
87
 
 
88
  def setProjection(self, geometry = None):
 
89
    geometry = geometry or self.geometry
 
90
    self.drawBoard.SetProjection(geometry[0], geometry[0] + geometry[2],
 
91
                                 geometry[1], geometry[1] + geometry[3])
 
92
    self.geometry = geometry
 
93
 
 
94
  def clear(self, r = 0, g = 0, b = 0, a = 0):
 
95
    self.drawBoard.Clear(r, g, b, a)
 
96
 
 
97
class SvgRenderStyle:
 
98
  def __init__(self, baseStyle = None):
 
99
    self.strokeColor = None
 
100
    self.strokeWidth = None
 
101
    self.fillColor = None
 
102
    self.strokeLineJoin = None
 
103
    self.strokeOpacity = None
 
104
    self.fillOpacity = None
 
105
    
 
106
    if baseStyle:
 
107
      self.__dict__.update(baseStyle.__dict__)
 
108
 
 
109
  def parseStyle(self, style):
 
110
    s = {}
 
111
    for m in re.finditer(r"(.+?):\s*(.+?)(;|$)\s*", style):
 
112
      s[m.group(1)] = m.group(2)
 
113
    return s
 
114
 
 
115
  def parseColor(self, color, defs = None):
 
116
    if color.lower() == "none":
 
117
      return None
 
118
 
 
119
    try:
 
120
      return SvgColors.colors[color.lower()]
 
121
    except KeyError:
 
122
      pass
 
123
      
 
124
    if color[0] == "#":
 
125
      color = color[1:]
 
126
      if len(color) == 3:
 
127
        return (int(color[0], 16) / 15.0, int(color[1], 16) / 15.0, int(color[2], 16) / 15.0, 1.0)
 
128
      return (int(color[0:2], 16) / 255.0, int(color[2:4], 16) / 255.0, int(color[4:6], 16) / 255.0, 1.0)
 
129
    else:
 
130
      if not defs:
 
131
        Log.warn("No patterns or gradients defined.")
 
132
        return None
 
133
      m = re.match("url\(#(.+)\)", color)
 
134
      if m:
 
135
        id = m.group(1)
 
136
        if not id in defs:
 
137
          Log.warn("Pattern/gradient %s has not been defined." % id)
 
138
        return defs.get(id)
 
139
 
 
140
  def __cmp__(self, s):
 
141
    if s:
 
142
      for k, v in self.__dict__.items():
 
143
        if v != getattr(s, k):
 
144
          return 1
 
145
      return 0
 
146
    return 1
 
147
 
 
148
  def __repr__(self):
 
149
    return "<SvgRenderStyle " + " ".join(["%s:%s" % (k, v) for k, v in self.__dict__.items()]) + ">"
 
150
 
 
151
  def applyAttributes(self, attrs, defs):
 
152
    style = attrs.get("style")
 
153
    if style:
 
154
      style = self.parseStyle(style)
 
155
      #print style
 
156
      if "stroke" in style:
 
157
        self.strokeColor = self.parseColor(style["stroke"], defs)
 
158
      if "fill" in style:
 
159
        self.fillColor = self.parseColor(style["fill"], defs)
 
160
      if "stroke-width" in style:
 
161
        self.strokeWidth = float(style["stroke-width"].replace("px", ""))
 
162
      if "stroke-opacity" in style:
 
163
        self.strokeOpacity = float(style["stroke-opacity"])
 
164
      if "fill-opacity" in style:
 
165
        self.fillOpacity = float(style["fill-opacity"])
 
166
      if "stroke-linejoin" in style:
 
167
        j = style["stroke-linejoin"].lower()
 
168
        if j == "miter":
 
169
          self.strokeLineJoin = amanith.G_MITER_JOIN
 
170
        elif j == "round":
 
171
          self.strokeLineJoin = amanith.G_ROUND_JOIN
 
172
        elif j == "bevel":
 
173
          self.strokeLineJoin = amanith.G_BEVEL_JOIN
 
174
 
 
175
  def apply(self, drawBoard, transform):
 
176
    if self.strokeColor is not None:
 
177
      if isinstance(self.strokeColor, SvgGradient):
 
178
        self.strokeColor.applyTransform(transform)
 
179
        drawBoard.SetStrokePaintType(amanith.G_GRADIENT_PAINT_TYPE)
 
180
        drawBoard.SetStrokeGradient(self.strokeColor.gradientDesc)
 
181
      else:
 
182
        drawBoard.SetStrokePaintType(amanith.G_COLOR_PAINT_TYPE)
 
183
        drawBoard.SetStrokeColor(*self.strokeColor)
 
184
      drawBoard.SetStrokeEnabled(True)
 
185
    else:
 
186
      drawBoard.SetStrokeEnabled(False)
 
187
    
 
188
    if self.fillColor is not None:
 
189
      if isinstance(self.fillColor, SvgGradient):
 
190
        self.fillColor.applyTransform(transform)
 
191
        drawBoard.SetFillPaintType(amanith.G_GRADIENT_PAINT_TYPE)
 
192
        drawBoard.SetFillGradient(self.fillColor.gradientDesc)
 
193
      else:
 
194
        drawBoard.SetFillPaintType(amanith.G_COLOR_PAINT_TYPE)
 
195
        drawBoard.SetFillColor(*self.fillColor)
 
196
      drawBoard.SetFillEnabled(True)
 
197
    else:
 
198
      drawBoard.SetFillEnabled(False)
 
199
 
 
200
    if self.strokeWidth is not None:
 
201
      drawBoard.SetStrokeWidth(self.strokeWidth)
 
202
    
 
203
    if self.strokeOpacity is not None:
 
204
      drawBoard.SetStrokeOpacity(self.strokeOpacity)
 
205
      
 
206
    if self.fillOpacity is not None:
 
207
      drawBoard.SetFillOpacity(self.fillOpacity)
 
208
 
 
209
    if self.strokeLineJoin is not None:
 
210
      drawBoard.SetStrokeJoinStyle(self.strokeLineJoin)
 
211
 
 
212
class SvgTransform:
 
213
  def __init__(self, baseTransform = None):
 
214
    self._gmatrix = amanith.GMatrix33()
 
215
    self.reset()
 
216
    
 
217
    if baseTransform:
 
218
      self.matrix = baseTransform.matrix.copy()
 
219
 
 
220
  def applyAttributes(self, attrs, key = "transform"):
 
221
    transform = attrs.get(key)
 
222
    if transform:
 
223
      m = re.match(r"translate\(\s*(.+?)\s*,(.+?)\s*\)", transform)
 
224
      if m:
 
225
        dx, dy = [float(c) for c in m.groups()]
 
226
        self.matrix[0, 2] += dx
 
227
        self.matrix[1, 2] += dy
 
228
      m = re.match(r"matrix\(\s*" + "\s*,\s*".join(["(.+?)"] * 6) + r"\s*\)", transform)
 
229
      if m:
 
230
        e = [float(c) for c in m.groups()]
 
231
        e = [e[0], e[2], e[4], e[1], e[3], e[5], 0, 0, 1]
 
232
        m = reshape(e, (3, 3))
 
233
        self.matrix = dot(self.matrix, m)
 
234
 
 
235
  def transform(self, transform):
 
236
    self.matrix = dot(self.matrix, transform.matrix)
 
237
 
 
238
  def reset(self):
 
239
    self.matrix = identity(3, dtype = float32)
 
240
 
 
241
  def translate(self, dx, dy):
 
242
    m = zeros((3, 3))
 
243
    m[0, 2] = dx
 
244
    m[1, 2] = dy
 
245
    self.matrix += m
 
246
 
 
247
  def rotate(self, angle):
 
248
    m = identity(3, dtype = float32)
 
249
    s = sin(angle)
 
250
    c = cos(angle)
 
251
    m[0, 0] =  c
 
252
    m[0, 1] = -s
 
253
    m[1, 0] =  s
 
254
    m[1, 1] =  c
 
255
    self.matrix = dot(self.matrix, m)
 
256
 
 
257
  def scale(self, sx, sy):
 
258
    m = identity(3, dtype = float32)
 
259
    m[0, 0] = sx
 
260
    m[1, 1] = sy
 
261
    self.matrix = dot(self.matrix, m)
 
262
 
 
263
  def applyGL(self):
 
264
    # Interpret the 2D matrix as 3D
 
265
    m = self.matrix
 
266
    m = [m[0, 0], m[1, 0], 0.0, 0.0,
 
267
         m[0, 1], m[1, 1], 0.0, 0.0,
 
268
             0.0,     0.0, 1.0, 0.0,
 
269
         m[0, 2], m[1, 2], 0.0, 1.0]
 
270
    glMultMatrixf(m)
 
271
 
 
272
  def getGMatrix(self, m):
 
273
    self._gmatrix.Set( \
 
274
      m[0, 0], m[0, 1], m[0, 2], \
 
275
      m[1, 0], m[1, 1], m[1, 2], \
 
276
      m[2, 0], m[2, 1], m[2, 2])
 
277
    return self._gmatrix
 
278
 
 
279
  def apply(self, drawBoard):
 
280
    drawBoard.SetModelViewMatrix(self.getGMatrix(self.matrix))
 
281
 
 
282
class SvgHandler(sax.ContentHandler):
 
283
  def __init__(self, drawBoard, cache):
 
284
    self.drawBoard = drawBoard
 
285
    self.styleStack = [SvgRenderStyle()]
 
286
    self.contextStack = [None]
 
287
    self.transformStack = [SvgTransform()]
 
288
    self.defs = {}
 
289
    self.cache = cache
 
290
  
 
291
  def startElement(self, name, attrs):
 
292
    style = SvgRenderStyle(self.style())
 
293
    style.applyAttributes(attrs, self.defs)
 
294
    self.styleStack.append(style)
 
295
    
 
296
    transform = SvgTransform(self.transform())
 
297
    transform.applyAttributes(attrs)
 
298
    self.transformStack.append(transform)
 
299
    
 
300
    try:
 
301
      f = "start" + name.capitalize()
 
302
      #print f, self.transformStack
 
303
      #print len(self.styleStack)
 
304
      f = getattr(self, f)
 
305
    except AttributeError:
 
306
      return
 
307
    f(attrs)
 
308
 
 
309
  def endElement(self, name):
 
310
    try:
 
311
      f = "end" + name.capitalize()
 
312
      #print f, self.contextStack
 
313
      getattr(self, f)()
 
314
    except AttributeError:
 
315
      pass
 
316
    self.styleStack.pop()
 
317
    self.transformStack.pop()
 
318
 
 
319
  def startG(self, attrs):
 
320
    self.contextStack.append("g")
 
321
 
 
322
  def endG(self):
 
323
    self.contextStack.pop()
 
324
 
 
325
  def startDefs(self, attrs):
 
326
    self.contextStack.append("defs")
 
327
 
 
328
  def endDefs(self):
 
329
    self.contextStack.pop()
 
330
 
 
331
  def startMarker(self, attrs):
 
332
    self.contextStack.append("marker")
 
333
 
 
334
  def endMarker(self):
 
335
    self.contextStack.pop()
 
336
 
 
337
  def context(self):
 
338
    return self.contextStack[-1]
 
339
 
 
340
  def style(self):
 
341
    return self.styleStack[-1]
 
342
 
 
343
  def transform(self):
 
344
    return self.transformStack[-1]
 
345
 
 
346
  def startPath(self, attrs):
 
347
    if self.context() in ["g", None]:
 
348
      if "d" in attrs:
 
349
        self.style().apply(self.drawBoard, self.transform())
 
350
        self.transform().apply(self.drawBoard)
 
351
        d = str(attrs["d"])
 
352
        self.cache.addStroke(self.style(), self.transform(), self.drawBoard.DrawPaths(d))
 
353
 
 
354
  def createLinearGradient(self, attrs, keys):
 
355
    a = dict(attrs)
 
356
    if not "x1" in a or not "x2" in a or not "y1" in a or not "y2" in a:
 
357
      a["x1"] = a["y1"] = 0.0
 
358
      a["x2"] = a["y2"] = 1.0
 
359
    if "id" in a and "x1" in a and "x2" in a and "y1" in a and "y2" in a:
 
360
      transform = SvgTransform()
 
361
      if "gradientTransform" in a:
 
362
        transform.applyAttributes(a, key = "gradientTransform")
 
363
      x1, y1, x2, y2 = [float(a[k]) for k in ["x1", "y1", "x2", "y2"]]
 
364
      return a["id"], self.drawBoard.CreateLinearGradient((x1, y1), (x2, y2), keys), transform
 
365
    return None, None, None
 
366
 
 
367
  def createRadialGradient(self, attrs, keys):
 
368
    a = dict(attrs)
 
369
    if not "cx" in a or not "cy" in a or not "fx" in a or not "fy" in a:
 
370
      a["cx"] = a["cy"] = 0.0
 
371
      a["fx"] = a["fy"] = 1.0
 
372
    if "id" in a and "cx" in a and "cy" in a and "fx" in a and "fy" in a and "r" in a:
 
373
      transform = SvgTransform()
 
374
      if "gradientTransform" in a:
 
375
        transform.applyAttributes(a, key = "gradientTransform")
 
376
      cx, cy, fx, fy, r = [float(a[k]) for k in ["cx", "cy", "fx", "fy", "r"]]
 
377
      return a["id"], self.drawBoard.CreateRadialGradient((cx, cy), (fx, fy), r, keys), transform
 
378
    return None, None, None
 
379
 
 
380
  def startLineargradient(self, attrs):
 
381
    if self.context() == "defs":
 
382
      if "xlink:href" in attrs:
 
383
        id = attrs["xlink:href"][1:]
 
384
        if not id in self.defs:
 
385
          Log.warn("Linear gradient %s has not been defined." % id)
 
386
        else:
 
387
          keys = self.defs[id].gradientDesc.ColorKeys()
 
388
          id, grad, trans = self.createLinearGradient(attrs, keys)
 
389
          self.defs[id] = SvgGradient(grad, trans)
 
390
      else:
 
391
        self.contextStack.append("gradient")
 
392
        self.stops = []
 
393
        self.gradientAttrs = attrs
 
394
    
 
395
  def startRadialgradient(self, attrs):
 
396
    if self.context() == "defs":
 
397
      if "xlink:href" in attrs:
 
398
        id = attrs["xlink:href"][1:]
 
399
        if not id in self.defs:
 
400
          Log.warn("Radial gradient %s has not been defined." % id)
 
401
        else:
 
402
          keys = self.defs[id].gradientDesc.ColorKeys()
 
403
          id, grad, trans = self.createRadialGradient(attrs, keys)
 
404
          self.defs[id] = SvgGradient(grad, trans)
 
405
      else:
 
406
        self.contextStack.append("gradient")
 
407
        self.stops = []
 
408
        self.gradientAttrs = attrs
 
409
 
 
410
  def parseKeys(self, stops):
 
411
    keys = []
 
412
    for stop in self.stops:
 
413
      color, opacity, offset = None, None, None
 
414
      if "style" in stop:
 
415
        style =  self.style().parseStyle(stop["style"])
 
416
        if "stop-color" in style:
 
417
          color = self.style().parseColor(style["stop-color"])
 
418
        if "stop-opacity" in style:
 
419
          opacity = float(style["stop-opacity"])
 
420
      if "offset" in stop:
 
421
        offset = float(stop["offset"])
 
422
      if offset is not None and (color is not None or opacity is not None):
 
423
        if opacity is None: opacity = 1.0
 
424
        k = amanith.GKeyValue(offset, (color[0], color[1], color[2], opacity))
 
425
        keys.append(k)
 
426
    return keys
 
427
    
 
428
  def endLineargradient(self):
 
429
    if self.context() == "gradient":
 
430
      keys = self.parseKeys(self.stops)
 
431
      id, grad, trans = self.createLinearGradient(self.gradientAttrs, keys)
 
432
      del self.stops
 
433
      del self.gradientAttrs
 
434
      if id and grad:
 
435
        self.defs[id] = SvgGradient(grad, trans)
 
436
      self.contextStack.pop()
 
437
    
 
438
  def endRadialgradient(self):
 
439
    if self.context() == "gradient":
 
440
      keys = self.parseKeys(self.stops)
 
441
      id, grad, trans = self.createRadialGradient(self.gradientAttrs, keys)
 
442
      del self.stops
 
443
      del self.gradientAttrs
 
444
      if id and grad:
 
445
        self.defs[id] = SvgGradient(grad, trans)
 
446
      self.contextStack.pop()
 
447
    
 
448
  def startStop(self, attrs):
 
449
    if self.context() == "gradient":
 
450
      self.stops.append(attrs)
 
451
    
 
452
class SvgCache:
 
453
  def __init__(self, drawBoard):
 
454
    self.drawBoard = drawBoard
 
455
    self.displayList = []
 
456
    self.transforms = {}
 
457
    self.bank = drawBoard.CreateCacheBank()
 
458
 
 
459
  def beginCaching(self):
 
460
    self.drawBoard.SetCacheBank(self.bank)
 
461
    self.drawBoard.SetTargetMode(amanith.G_CACHE_MODE)
 
462
 
 
463
  def endCaching(self):
 
464
    self.drawBoard.SetTargetMode(amanith.G_COLOR_MODE)
 
465
    self.drawBoard.SetCacheBank(None)
 
466
 
 
467
  def addStroke(self, style, transform, slot):
 
468
    if self.displayList:
 
469
      lastStyle = self.displayList[-1][0]
 
470
    else:
 
471
      lastStyle = None
 
472
 
 
473
    self.transforms[slot] = transform
 
474
    
 
475
    if lastStyle == style:
 
476
      lastSlotStart, lastSlotEnd = self.displayList[-1][1][-1]
 
477
      if lastSlotEnd == slot - 1:
 
478
        self.displayList[-1][1][-1] = (lastSlotStart, slot)
 
479
      else:
 
480
        self.displayList[-1][1].append((slot, slot))
 
481
    else:
 
482
      self.displayList.append((style, [(slot, slot)]))
 
483
 
 
484
  def draw(self, baseTransform):
 
485
    self.drawBoard.SetCacheBank(self.bank)
 
486
    for style, slotList in self.displayList:
 
487
      transform = SvgTransform(baseTransform)
 
488
      transform.transform(self.transforms[slotList[0][0]])
 
489
      transform.apply(self.drawBoard)
 
490
      style.apply(self.drawBoard, transform)
 
491
      for firstSlot, lastSlot in slotList:
 
492
        self.drawBoard.DrawCacheSlots(firstSlot, lastSlot)
 
493
    self.drawBoard.SetCacheBank(None)
 
494
 
 
495
    # eat any possible OpenGL errors -- we can't handle them anyway
 
496
    try:
 
497
      glMatrixMode(GL_MODELVIEW)
 
498
    except:
 
499
      pass
 
500
 
 
501
class ImgDrawing:
 
502
  def __init__(self, context, ImgData):
 
503
    self.ImgData = None
 
504
    self.texture = None
 
505
    self.context = context
 
506
    self.cache = None
 
507
    self.transform = SvgTransform()
 
508
 
 
509
    # Detect the type of data passed in
 
510
    if type(ImgData) == file:
 
511
      self.ImgData = ImgData.read()
 
512
    elif type(ImgData) == str:
 
513
      bitmapFile = ImgData.replace(".svg", ".png")
 
514
      # Load PNG files directly
 
515
      if ImgData.endswith(".png"):
 
516
        self.texture = Texture(ImgData)
 
517
      elif ImgData.endswith(".jpg"):
 
518
        self.texture = Texture(ImgData)
 
519
      elif ImgData.endswith(".jpeg"):
 
520
        self.texture = Texture(ImgData)
 
521
      # Check whether we have a prerendered bitmap version of the SVG file
 
522
      elif ImgData.endswith(".svg") and os.path.exists(bitmapFile):
 
523
        Log.debug("Loading cached bitmap '%s' instead of '%s'." % (bitmapFile, ImgData))
 
524
        self.texture = Texture(bitmapFile)
 
525
      else:
 
526
        if not haveAmanith:
 
527
          e = "PyAmanith support is deprecated and you are trying to load an SVG file."
 
528
          Log.error(e)
 
529
          raise RuntimeError(e)
 
530
        Log.debug("Loading SVG file '%s'." % (ImgData))
 
531
        self.ImgData = open(ImgData).read()
 
532
    elif isinstance(ImgData, Image.Image): #stump: let a PIL image be passed in
 
533
      self.texture = Texture()
 
534
      self.texture.loadImage(ImgData)
 
535
 
 
536
    # Make sure we have a valid texture
 
537
    if not self.texture:
 
538
      if type(ImgData) == str:
 
539
        e = "Unable to load texture for %s." % ImgData
 
540
      else:
 
541
        e = "Unable to load texture for SVG file."
 
542
      Log.error(e)
 
543
      raise RuntimeError(e)
 
544
 
 
545
  def _cacheDrawing(self, drawBoard):
 
546
    self.cache.beginCaching()
 
547
    parser = sax.make_parser()
 
548
    sax.parseString(self.ImgData, SvgHandler(drawBoard, self.cache))
 
549
    self.cache.endCaching()
 
550
    del self.ImgData
 
551
 
 
552
  def convertToTexture(self, width, height):
 
553
    if self.texture:
 
554
      return
 
555
 
 
556
    e = "SVG drawing does not have a valid texture image."
 
557
    Log.error(e)
 
558
    raise RuntimeError(e)
 
559
 
 
560
  def _getEffectiveTransform(self):
 
561
    transform = SvgTransform(self.transform)
 
562
    transform.transform(self.context.transform)
 
563
    return transform
 
564
 
 
565
  def width1(self):
 
566
    width = self.texture.pixelSize[0]
 
567
    if not width == None:
 
568
      return width
 
569
    else:
 
570
      return 0
 
571
 
 
572
  #myfingershurt:
 
573
  def height1(self):
 
574
    height = self.texture.pixelSize[1]
 
575
    if not height == None:
 
576
      return height
 
577
    else:
 
578
      return 0
 
579
 
 
580
 
 
581
  def widthf(self, pixelw):
 
582
    width = self.texture.pixelSize[0]
 
583
    wfactor = pixelw/width
 
584
    if not width == None:
 
585
      return wfactor
 
586
    else:
 
587
      return 0    
 
588
 
 
589
  def _render(self, transform):
 
590
    glMatrixMode(GL_TEXTURE)
 
591
    glPushMatrix()
 
592
    glMatrixMode(GL_MODELVIEW)
 
593
    
 
594
    glPushAttrib(GL_ENABLE_BIT | GL_TEXTURE_BIT | GL_STENCIL_BUFFER_BIT | GL_TRANSFORM_BIT | GL_COLOR_BUFFER_BIT | GL_POLYGON_BIT | GL_CURRENT_BIT | GL_DEPTH_BUFFER_BIT)
 
595
    if not self.cache:
 
596
      self.cache = SvgCache(self.context.drawBoard)
 
597
      self._cacheDrawing(self.context.drawBoard)
 
598
    self.cache.draw(transform)
 
599
    glPopAttrib()
 
600
 
 
601
    glMatrixMode(GL_TEXTURE)
 
602
    glPopMatrix()
 
603
    glMatrixMode(GL_MODELVIEW)
 
604
 
 
605
  def draw(self, color = (1, 1, 1, 1), rect = (0,1,0,1), lOffset = 0.0, rOffset = 0.0):
 
606
    glMatrixMode(GL_TEXTURE)
 
607
    glPushMatrix()
 
608
    glMatrixMode(GL_PROJECTION)
 
609
    glPushMatrix()
 
610
    self.context.setProjection()
 
611
    glMatrixMode(GL_MODELVIEW)
 
612
    glPushMatrix()
 
613
 
 
614
    transform = self._getEffectiveTransform()
 
615
    if self.texture:
 
616
      glLoadIdentity()
 
617
      transform.applyGL()
 
618
 
 
619
      glScalef(self.texture.pixelSize[0], self.texture.pixelSize[1], 1)
 
620
      glTranslatef(-.5, -.5, 0)
 
621
      glColor4f(*color)
 
622
      
 
623
 
 
624
      glEnable(GL_TEXTURE_2D)
 
625
      self.texture.bind()
 
626
      
 
627
      triangVtx = array(
 
628
        [[0.0-lOffset, 1.0],
 
629
         [1.0-rOffset, 1.0],
 
630
         [0.0+lOffset, 0.0],
 
631
         [1.0+rOffset, 0.0]], dtype=float32)
 
632
 
 
633
      textriangVtx = array(
 
634
        [[rect[0], rect[3]],
 
635
         [rect[1], rect[3]],
 
636
         [rect[0], rect[2]],
 
637
         [rect[1], rect[2]]], dtype=float32)
 
638
 
 
639
      glEnableClientState(GL_TEXTURE_COORD_ARRAY)    
 
640
      glEnableClientState(GL_VERTEX_ARRAY)
 
641
      glTexCoordPointerf(textriangVtx)
 
642
      glVertexPointerf(triangVtx)
 
643
      glDrawArrays(GL_TRIANGLE_STRIP, 0, triangVtx.shape[0])
 
644
      glDisableClientState(GL_VERTEX_ARRAY)
 
645
      glDisableClientState(GL_TEXTURE_COORD_ARRAY)
 
646
 
 
647
      glDisable(GL_TEXTURE_2D)
 
648
    else:
 
649
      self._render(transform)
 
650
    glMatrixMode(GL_TEXTURE)
 
651
    glPopMatrix()
 
652
    glMatrixMode(GL_MODELVIEW)
 
653
    glPopMatrix()
 
654
    glMatrixMode(GL_PROJECTION)
 
655
    glPopMatrix()
 
656
    glMatrixMode(GL_MODELVIEW)