summaryrefslogtreecommitdiff
path: root/unrpyc/renpy/display/imagemap.py
diff options
context:
space:
mode:
authorAlex Xu <alex_y_xu@yahoo.ca>2013-08-22 22:45:26 -0400
committerAlex Xu <alex_y_xu@yahoo.ca>2013-08-22 22:45:26 -0400
commit718936110b9511631fa1f4396be992752bf8b719 (patch)
treea871768c06adc2959f8f0d69869532d36a95ffab /unrpyc/renpy/display/imagemap.py
parentece6cf9fbfdba9dac8d7bf98516a840c955a4853 (diff)
downloadhtml5ks-718936110b9511631fa1f4396be992752bf8b719.tar.xz
html5ks-718936110b9511631fa1f4396be992752bf8b719.zip
include renpy
Diffstat (limited to 'unrpyc/renpy/display/imagemap.py')
-rw-r--r--unrpyc/renpy/display/imagemap.py233
1 files changed, 233 insertions, 0 deletions
diff --git a/unrpyc/renpy/display/imagemap.py b/unrpyc/renpy/display/imagemap.py
new file mode 100644
index 0000000..380bf80
--- /dev/null
+++ b/unrpyc/renpy/display/imagemap.py
@@ -0,0 +1,233 @@
+# Copyright 2004-2013 Tom Rothamel <pytom@bishoujo.us>
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation files
+# (the "Software"), to deal in the Software without restriction,
+# including without limitation the rights to use, copy, modify, merge,
+# publish, distribute, sublicense, and/or sell copies of the Software,
+# and to permit persons to whom the Software is furnished to do so,
+# subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+# This file handles imagemap caching.
+
+import pygame
+import renpy.display
+
+from renpy.display.render import render
+
+import hashlib
+import os
+
+# A list of cache images we've already written.
+cached = set()
+
+class ImageMapCrop(renpy.display.core.Displayable):
+ """
+ This handles the cropping of uncached imagemap components.
+ """
+
+ def __init__(self, child, rect):
+ super(ImageMapCrop, self).__init__()
+
+ self.child = child
+ self.rect = rect
+
+ def visit(self):
+ return [ self.child ]
+
+ def render(self, width, height, st, at):
+ cr = render(self.child, width, height, st, at)
+ return cr.subsurface(self.rect)
+
+
+class ImageCacheCrop(renpy.display.core.Displayable):
+ """
+ This handles the cropping of an imagemap component.
+ """
+
+ def __init__(self, cache, index):
+ super(ImageCacheCrop, self).__init__()
+
+ # The cache object we're associated with.
+ self.cache = cache
+
+ # The index of
+ self.index = index
+
+ def visit(self):
+ return self.cache.visit(self.index)
+
+ def render(self, width, height, st, at):
+ return self.cache.render(self.index, width, height, st, at)
+
+class ImageMapCache(renpy.object.Object):
+
+ def __init__(self, enable):
+ self.md5 = hashlib.md5()
+
+ # A list of (image, rect) tuples. The index in this list is used
+ # as a unique identifier for an ImageCacheCrop object.
+ self.imagerect = [ ]
+
+ # A map from (image, rect) to ImageCacheCrop object.
+ self.hotspots = { }
+
+ # A list of (width, height, index) tuples.
+ self.areas = [ ]
+
+ # The image containing our children.
+ self.cache = None
+
+ # A list that, for each hotspot, gives the rectangle in the cache
+ # image corresponding to that hotspot.
+ self.cache_rect = None
+
+ # The size of the cache.
+ self.cache_width = None
+ self.cache_height = None
+
+ self.enable = enable
+
+ def visit(self, index):
+ if self.cache is not None:
+ return [ self.cache ]
+ else:
+ return [ self.imagerect[index][0] ]
+
+ def crop(self, d, rect):
+ if not isinstance(d, renpy.display.im.ImageBase) or \
+ not renpy.config.imagemap_cache or \
+ not self.enable:
+ return ImageMapCrop(d, rect)
+
+ key = (d, rect)
+ rv = self.hotspots.get(key, None)
+ if rv is not None:
+ return rv
+
+ self.md5.update(repr(d.identity))
+ self.md5.update(repr(d.identity))
+
+ index = len(self.imagerect)
+ rv = ImageCacheCrop(self, index)
+
+ self.imagerect.append(key)
+ self.hotspots[key] = rv
+ self.areas.append((rect[2] + 2, rect[3] + 2, index))
+
+ return rv
+
+ def layout(self):
+ self.areas.sort()
+ self.areas.reverse()
+ self.cache_rect = [ None ] * len(self.areas)
+
+ # The width of the cache image.
+ width = self.areas[0][0]
+
+ x = 0
+ y = 0
+ line_height = 0
+
+ for w, h, i in self.areas:
+
+ if x + w > width:
+ y += line_height
+ line_height = 0
+ x = 0
+
+ self.cache_rect[i] = (x+1, y+1, w-2, h-2)
+
+ x += w
+ if line_height < h:
+ line_height = h
+
+ self.cache_width = width
+ self.cache_height = y + line_height
+
+ def write_cache(self, filename):
+
+ if filename in cached:
+ return
+
+ cached.add(filename)
+
+ # If all of our dependencies are of the same age or less,
+ # we don't need to rebuild the cache.
+
+ if renpy.loader.loadable(filename):
+ d_set = set()
+ mtime = 0
+
+ for i, rect in self.imagerect:
+ if i in d_set:
+ continue
+
+ d_set.add(i)
+ mtime = max(i.get_mtime(), mtime)
+
+ if renpy.loader.get_mtime(filename) >= mtime:
+ return
+
+ fn = os.path.join(renpy.config.gamedir, filename)
+ dir = os.path.dirname(fn) #@ReservedAssignment
+
+ if not os.path.exists(dir):
+ os.makedirs(dir)
+
+ cache = pygame.Surface((self.cache_width, self.cache_height), pygame.SRCALPHA, 32)
+
+ for i, (d, rect) in enumerate(self.imagerect):
+ x, y, _w, _h = self.cache_rect[i]
+
+ surf = renpy.display.im.cache.get(d).subsurface(rect)
+ cache.blit(surf, (x, y))
+
+ pygame.image.save(cache, renpy.exports.fsencode(fn))
+
+ def finish(self):
+ if not self.areas:
+ return
+
+ filename = "im-%s.png" % (self.md5.hexdigest())
+
+ if renpy.game.preferences.language:
+ filename = renpy.game.preferences.language + "-" + filename
+
+ filename = "cache/" + filename
+
+ self.md5 = None
+
+ self.layout()
+
+ if renpy.config.developer:
+ try:
+ self.write_cache(filename)
+ except:
+ pass
+
+ if renpy.loader.loadable(filename):
+ self.cache = renpy.display.im.Image(filename)
+
+
+ def render(self, index, width, height, st, at):
+ if self.cache is None:
+ d, rect = self.imagerect[index]
+ return render(d, width, height, st, at).subsurface(rect)
+
+ return render(self.cache, width, height, st, at).subsurface(self.cache_rect[index])
+
+
+
+