+Tue April 10 2007 Shyouzou Sugitani <shy@users.sourceforge.jp>
+ * gdk-pixbufを使用している部分のメモリリーク対策をした.
+ * gdk-pixbuf関連のコードをSerikoからSurfaceクラスに移した.
+
Sat March 24 2007 Shyouzou Sugitani <shy@users.sourceforge.jp>
* メニューアイコンの管理を各ゴーストからApplicationクラスに移した.
#
import os
+import gc
if 'DISPLAY' in os.environ:
import gtk
self.clear_text()
def reset_pixbuf_cache(self):
+ self.pixbuf = None
+ gc.collect()
self.pixbuf = {}
for key, (path, config) in self.balloon.iteritems():
try:
w = pixbuf.get_width()
h = pixbuf.get_height()
self.images.append((pixbuf, (w, h), (x, y)))
+ del pixbuf
+ gc.collect()
self.redraw()
def draw_last_line(self, column=0):
import math
import time
import sys
+import gc
if 'DISPLAY' in os.environ:
if 'gtk' not in sys.modules:
balloon_pixbuf = balloon_pixbuf.scale_simple(
w, h, gtk.gdk.INTERP_BILINEAR)
balloon_pixmap, mask_pixmap = balloon_pixbuf.render_pixmap_and_mask(1)
+ del balloon_pixbuf
+ gc.collect()
if self.position == 'lefttop':
pass
elif self.position == 'leftbottom':
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
# PURPOSE. See the GNU General Public License for more details.
#
-# $Id: hanayu.py,v 1.32 2006/03/25 08:07:09 shy Exp $
+# $Id: hanayu.py,v 1.33 2007/04/10 14:38:59 shy Exp $
#
# TODO:
import os
import math
import time
+import gc
if 'DISPLAY' in os.environ:
if 'gtk' not in sys.modules:
0, 0, xoffset, yoffset,
width, height,
gtk.gdk.RGB_DITHER_NONE, 0, 0)
+ del pixbuf
+ gc.collect()
self.darea.window.draw_drawable(self.surface_gc, self.surface_pixmap,
0, 0, 0, 0, self.width, self.height)
# - 透明度の設定
import os
+import gc
if 'DISPLAY' in os.environ:
import gtk
class Skin:
def __init__(self, data, accelgroup, kinoko, scale):
+ self.frame_buffer = []
self.data = data
self.accelgroup = accelgroup
self.kinoko = kinoko
surface_pixbuf = self.pixbuf.scale_simple(
w, h, gtk.gdk.INTERP_BILINEAR)
image, mask = surface_pixbuf.render_pixmap_and_mask(255)
+ del surface_pixbuf
+ gc.collect()
except: ## FIXME
self.kinoko.close(None)
return
surface_pixbuf = self.pixbuf.copy()
return surface_pixbuf
- def update(self, cache=None):
- if cache is not None:
- surface_pixbuf = cache
+ def clear_frame_buffer(self):
+ self.frame_buffer = []
+
+ def update_frame_buffer(self, seriko, frame, move, dirty):
+ if dirty:
+ surface_pixbuf = self.create_surface_pixbuf(seriko.base_id)
+ if surface_pixbuf is not None:
+ # draw overlays
+ for pixbuf_id, x, y in seriko.iter_overlays():
+ try:
+ pixbuf = self.get_pixbuf(pixbuf_id)
+ w = pixbuf.get_width()
+ h = pixbuf.get_height()
+ except:
+ continue
+ # overlay surface pixbuf
+ sw = surface_pixbuf.get_width()
+ sh = surface_pixbuf.get_height()
+ if x + w > sw:
+ w = sw - x
+ if y + h > sh:
+ h = sh - y
+ if x < 0:
+ dest_x = 0
+ w += x
+ else:
+ dest_x = x
+ if y < 0:
+ dest_y = 0
+ h += y
+ else:
+ dest_y = y
+ pixbuf.composite(surface_pixbuf, dest_x, dest_y,
+ w, h, x, y, 1.0, 1.0,
+ gtk.gdk.INTERP_BILINEAR, 255)
+ else:
+ surface_pixbuf = None
+ self.frame_buffer.append((frame, move, surface_pixbuf, dirty))
+
+ def update(self):
+ if len(self.frame_buffer) > 0:
+ frame, move, surface_pixbuf, dirty = self.frame_buffer.pop(0)
+ if move is not None:
+ self.move_surface(*move)
+ if not dirty:
+ return
else:
surface_pixbuf = self.create_surface_pixbuf()
if self.__scale != 100:
surface_pixbuf = surface_pixbuf.scale_simple(
w, h, gtk.gdk.INTERP_BILINEAR)
image, mask = surface_pixbuf.render_pixmap_and_mask(255)
+ del surface_pixbuf
+ gc.collect()
self.w, self.h = self.surface_pixmap.get_size()
self.darea.window.set_back_pixmap(image, False)
self.window.shape_combine_mask(mask, 0, 0)
self.darea.queue_draw()
def terminate(self):
- self.seriko.terminate()
+ self.seriko.terminate(self)
def add_overlay(self, actor, surface_id, x, y):
- self.seriko.add_overlay(actor, surface_id, x, y)
+ self.seriko.add_overlay(self, actor, surface_id, x, y)
def remove_overlay(self, actor):
self.seriko.remove_overlay(actor)
self.kinoko.close(None)
def destroy(self): ## FIXME
- self.seriko.terminate()
+ self.seriko.terminate(self)
self.window.destroy()
def button_press(self, widget, event): ## FIXME
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
# PURPOSE. See the GNU General Public License for more details.
#
-# $Id: main.py,v 1.139 2007/03/24 03:51:08 shy Exp $
+# $Id: main.py,v 1.140 2007/04/10 14:38:59 shy Exp $
#
import getopt
import traceback
import cStringIO
import fcntl
+import gc
gettext.install('ninix')
pixbuf = None
if pixbuf is not None:
icon = pixbuf.scale_simple(16, 16, gtk.gdk.INTERP_BILINEAR)
+ del pixbuf
+ gc.collect()
else:
icon = None
else:
import os
import re
+import gc
if 'DISPLAY' in os.environ:
import gtk
1.0, 1.0, gtk.gdk.INTERP_BILINEAR, 255)
self.__sidebar_width = sidebar_width
pixmap, mask = new_pixbuf.render_pixmap_and_mask(255)
+ del pixbuf
+ del new_pixbuf
+ gc.collect()
else:
self.__sidebar_width = 0
self.__pixmap_with_sidebar = pixmap
0, 0,
1.0, 1.0, gtk.gdk.INTERP_BILINEAR, 255)
pixmap, mask = new_pixbuf.render_pixmap_and_mask(255)
+ del pixbuf
+ del new_pixbuf
+ del pixbuf_sidebar
+ gc.collect()
self.__pixmap_prelight_with_sidebar = pixmap
def __set_mayuna_menu(self, side):
import os
import random
+import gc
if 'DISPLAY' in os.environ:
import gtk
h = max(1, pixbuf.get_height() * self.__scale / 100)
pixbuf = pixbuf.scale_simple(w, h, gtk.gdk.INTERP_BILINEAR)
image, mask = pixbuf.render_pixmap_and_mask(255)
+ del pixbuf
+ gc.collect()
except:
self.nekoninni.finalize()
return
h = pixbuf.get_height() * self.__scale / 100
pixbuf = pixbuf.scale_simple(w, h, gtk.gdk.INTERP_BILINEAR)
image, mask = pixbuf.render_pixmap_and_mask(255)
+ del pixbuf
+ gc.collect()
except:
self.nekoninni.finalize()
return
import sys
import urllib
import time
+import gc
from xml.dom import pulldom
try:
pixbuf = ninix.pix.create_pixbuf_from_file(filename)
image, mask = pixbuf.render_pixmap_and_mask(255)
+ del pixbuf
+ gc.collect()
except:
darea.window.set_back_pixmap(None, False)
else:
import sys
import os
import md5
+import gc
if 'DISPLAY' in os.environ:
import gtk
loader.close()
return pixbuf
-def add_alpha_from_PNA_file(pixbuf, path):
- assert pixbuf.get_has_alpha()
- pna_pixbuf = gtk.gdk.pixbuf_new_from_file(path)
- pna_array = pna_pixbuf.get_pixels_array()
- assert pna_pixbuf.get_bits_per_sample() / 8 == 1 ## FIXME
- pixbuf_array = pixbuf.get_pixels_array()
- width = pixbuf.get_width()
- height = pixbuf.get_height()
- pixbuf_array[:,:,3] = pna_array[:,:,0]
-
def create_pixbuf_from_file(path, is_pnr=1, use_pna=0):
head, tail = os.path.split(path)
basename, suffix = os.path.splitext(tail)
if use_pna:
path = os.path.join(head, ''.join((basename, '.pna')))
if os.path.exists(path):
- add_alpha_from_PNA_file(pixbuf, path)
+ assert pixbuf.get_has_alpha()
+ pna_pixbuf = gtk.gdk.pixbuf_new_from_file(path)
+ pna_array = pna_pixbuf.get_pixels_array()
+ assert pna_pixbuf.get_bits_per_sample() / 8 == 1 ## FIXME
+ pixbuf_array = pixbuf.get_pixels_array()
+ pixbuf_array[:,:,3] = pna_array[:,:,0]
+ del pna_pixbuf
+ gc.collect()
return pixbuf
def create_pixmap_from_file(path):
pixbuf = create_pixbuf_from_file(path)
pixmap, mask = pixbuf.render_pixmap_and_mask(1)
+ del pixbuf
+ gc.collect()
return pixmap, mask
-
-def reduce_pixbuf(target_pixbuf, pixbuf, dest_x, dest_y):
- if pixbuf.get_has_alpha():
- dest_w = target_pixbuf.get_width()
- dest_h = target_pixbuf.get_height()
- target_array = target_pixbuf.get_pixels_array()
- array = pixbuf.get_pixels_array()
- w = pixbuf.get_width()
- h = pixbuf.get_height()
- for i in range(h):
- for j in range(w):
- if array[i][j][3] == 0: # alpha
- x = j + dest_x
- y = i + dest_y
- if 0 <= x < dest_w and 0 <= y < dest_h:
- target_array[y][x][3] = 0 # alpha
- return target_pixbuf
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
# PURPOSE. See the GNU General Public License for more details.
#
-# $Id: seriko.py,v 1.25 2006/10/05 15:16:44 shy Exp $
+# $Id: seriko.py,v 1.26 2007/04/10 14:38:59 shy Exp $
#
import re
self.frame = {'step': 0.033, # [sec]
'next': 0}
self.active = []
- self.__cache = []
self.__move = None
self.__dirty = 1
- def cache_is_empty(self):
- if self.__cache:
- return False
- else:
- return True
-
- def get_cache(self):
- assert self.__cache is not None
- return self.__cache[0][2]
-
def set_base_id(self, window, surface_id):
if surface_id == -2:
- self.terminate()
+ self.terminate(window)
self.base_id = window.surface_id
else:
self.base_id = surface_id
def move_surface(self, xoffset, yoffset):
self.__move = (xoffset, yoffset)
- def draw_overlays(self, window, surface_pixbuf):
- ##print 'draw_overlays()'
- if surface_pixbuf is None:
- return None
- for pixbuf_id, x, y in self.iter_overlays():
- try:
- pixbuf = window.get_pixbuf(pixbuf_id)
- w = pixbuf.get_width()
- h = pixbuf.get_height()
- except:
- continue
- # overlay surface pixbuf
- sw = surface_pixbuf.get_width()
- sh = surface_pixbuf.get_height()
- if x + w > sw:
- w = sw - x
- if y + h > sh:
- h = sh - y
- if x < 0:
- dest_x = 0
- w += x
- else:
- dest_x = x
- if y < 0:
- dest_y = 0
- h += y
- else:
- dest_y = y
- pixbuf.composite(surface_pixbuf, dest_x, dest_y,
- w, h, x, y, 1.0, 1.0,
- gtk.gdk.INTERP_BILINEAR, 255)
- return surface_pixbuf
-
def append_actor(self, frame, actor):
self.active.append((frame, actor))
def update_frame(self, window):
if self.terminate_flag:
return False
- if len(self.__cache) > 1.0 / self.frame['step']: # XXX
+ if len(window.frame_buffer) > 1.0 / self.frame['step']: # XXX
return True
self.frame['next'] += self.frame['step']
frame, actor = self.get_actor_next(window)
actor.update(window, frame)
last_actor = actor
frame, actor = self.get_actor_next(window)
- self.update_surface_cache(window)
+ self.update_surface_frame_buffer(window)
if last_actor is not None and last_actor.exclusive and \
last_actor.terminate_flag and self.exclusive_actor is None: # XXX
self.invoke_restart(window)
return self.active.pop(0)
return None, None
- def update_surface_cache(self, window):
- if self.__dirty:
- surface_pixbuf = window.create_surface_pixbuf(self.base_id)
- surface_pixbuf = self.draw_overlays(window, surface_pixbuf)
- else:
- surface_pixbuf = None
- self.__cache.append((self.frame['next'], self.__move, surface_pixbuf, self.__dirty))
+ def update_surface_frame_buffer(self, window):
+ window.update_frame_buffer(
+ self, self.frame['next'], self.__move, self.__dirty)
self.__dirty = 0
def update(self, window):
if self.terminate_flag:
return False
- if self.__cache:
- frame, move, surface, dirty = self.__cache.pop(0)
- if move is not None:
- window.move_surface(*move)
- if dirty:
- window.update(surface)
+ window.update()
self.timeout_id = gobject.timeout_add(int(self.frame['step'] * 1000), self.update, window)
return False
def lock_exclusive(self, window, actor):
assert self.exclusive_actor is None
- self.terminate()
+ self.terminate(window)
self.exclusive_actor = actor
actor.set_post_proc(self.unlock_exclusive, (window, actor))
self.update_frame(window) # XXX
pass
self.__dirty = 1
- def add_overlay(self, actor, pixbuf_id, x, y):
+ def add_overlay(self, window, actor, pixbuf_id, x, y):
if pixbuf_id == '-2':
- self.terminate()
+ self.terminate(window)
if pixbuf_id in ['-1', '-2']:
self.remove_overlay(actor)
return
def reset(self, window, surface_id):
self.queue = []
- self.terminate()
+ self.terminate(window)
self.frame['next'] = 0
self.set_base_id(window, window.surface_id)
if surface_id in self.seriko:
self.invoke_always(window)
self.timeout_id = gobject.timeout_add(int(self.frame['step'] * 1000), self.update, window)
- def terminate(self):
+ def terminate(self, window):
self.terminate_flag = 1
if self.timeout_id is not None:
gobject.source_remove(self.timeout_id)
self.active = []
self.__move = None
self.__dirty = 1
- self.__cache = []
+ window.clear_frame_buffer()
self.terminate_flag = 0
def iter_overlays(self):
import re
import urlparse
import random
+import gc
if 'DISPLAY' in os.environ:
import gtk
key, method, filename, x, y, w, h)
if error is not None:
print error
+ pixbuf_list = None
+ gc.collect()
pixbuf_list = []
return pixbuf_list
pixbuf = None
for window in self.window:
window.window.set_icon(pixbuf)
+ del pixbuf
+ gc.collect()
def __check_mikire_kasanari(self):
if not self.is_shown(0):
self.mayuna = mayuna
self.bind = bind
self.reset_pixbuf_cache()
+ self.frame_buffer = []
self.default_id = default_id
self.debug = debug
self.__shown = 0
if aliases:
surface_id = random.choice(aliases)
if surface_id == '-2':
- self.seriko.terminate()
+ self.seriko.terminate(self)
if surface_id in ['-1', '-2']:
pass
elif surface_id not in self.pixbuf:
self.set_position(x, y)
self.sakura.ghost.notify_surface_change(self.side) ## FIXME
- def compose_surface(self, surface_pixbuf, mayuna, done):
- for pattern in mayuna.patterns:
- surface, interval, method, args = pattern
+ def iter_mayuna(self, surface_width, surface_height, mayuna, done):
+ for surface, interval, method, args in mayuna.patterns:
if method in ['bind', 'add']:
if surface in self.pixbuf:
x, y = args
w = pixbuf.get_width()
h = pixbuf.get_height()
# overlay surface pixbuf
- sw = surface_pixbuf.get_width()
- sh = surface_pixbuf.get_height()
- if x + w > sw:
- w = sw - x
- if y + h > sh:
- h = sh - y
+ if x + w > surface_width:
+ w = surface_width - x
+ if y + h > surface_height:
+ h = surface_height - y
if x < 0:
dest_x = 0
w += x
h += y
else:
dest_y = y
- pixbuf.composite(surface_pixbuf, dest_x, dest_y,
- w, h, x, y, 1.0, 1.0,
- gtk.gdk.INTERP_BILINEAR, 255)
+ yield method, pixbuf, dest_x, dest_y, w, h, x, y
elif method == 'reduce':
if surface in self.pixbuf:
- x, y = args
+ dest_x, dest_y = args
pixbuf = self.get_pixbuf(surface)
w = pixbuf.get_width()
h = pixbuf.get_height()
- surface_pixbuf = pix.reduce_pixbuf(
- surface_pixbuf, pixbuf, x, y)
+ x = y = 0 # XXX
+ yield method, pixbuf, dest_x, dest_y, w, h, x, y
elif method == 'insert':
index = args[0]
for actor in self.mayuna[self.surface_id]:
if actor_id in self.bind and self.bind[actor_id][1] and \
actor_id not in done:
done.append(actor_id)
- surface_pixbuf = self.compose_surface(
- surface_pixbuf, actor, done)
+ for result in self.iter_mayuna(surface_width, surface_height, actor, done):
+ yield result
else:
break
else:
raise RuntimeError, 'should not reach here'
- return surface_pixbuf
def reset_pixbuf_cache(self):
+ self.pixbuf_cache = None
+ self.mayuna_cache = None
+ gc.collect()
self.pixbuf_cache = {}
self.mayuna_cache = {}
overlay.composite(pixbuf, dest_x, dest_y,
w, h, x, y, 1.0, 1.0,
gtk.gdk.INTERP_BILINEAR, 255)
+ del overlay
+ ##else:
+ ## gc.collect() # XXX
return pixbuf
def get_pixbuf(self, pixbuf_id):
if actor_id in self.bind and self.bind[actor_id][1] and \
actor_id not in done:
done.append(actor_id)
- surface_pixbuf = self.compose_surface(
- surface_pixbuf, actor, done)
+ #surface_pixbuf = self.compose_surface(
+ # surface_pixbuf, actor, done)
+ surface_width = surface_pixbuf.get_width()
+ surface_height = surface_pixbuf.get_height()
+ for method, pixbuf, dest_x, dest_y, w, h, x, y in self.iter_mayuna(surface_width, surface_height, actor, done):
+ if method in ['bind', 'add']:
+ pixbuf.composite(surface_pixbuf, dest_x, dest_y,
+ w, h, x, y, 1.0, 1.0,
+ gtk.gdk.INTERP_BILINEAR, 255)
+ elif method == 'reduce':
+ if pixbuf.get_has_alpha():
+ dest_w = surface_width
+ dest_h = surface_height
+ surface_array = surface_pixbuf.get_pixels_array()
+ array = pixbuf.get_pixels_array()
+ for i in range(h):
+ for j in range(w):
+ if array[i][j][3] == 0: # alpha
+ x = j + dest_x
+ y = i + dest_y
+ if 0 <= x < dest_w and 0 <= y < dest_h:
+ surface_array[y][x][3] = 0 # alpha
+ else:
+ raise RuntimeError, 'should not reach here'
self.mayuna_cache[surface_id] = surface_pixbuf.copy()
else:
surface_pixbuf =self.get_pixbuf(surface_id)
return surface_pixbuf
- def update(self, cache=None):
- if cache is not None:
- surface_pixbuf = cache
+ def clear_frame_buffer(self):
+ self.frame_buffer = []
+
+ def update_frame_buffer(self, seriko, frame, move, dirty):
+ if dirty:
+ surface_pixbuf = self.create_surface_pixbuf(seriko.base_id)
+ if surface_pixbuf is not None:
+ # draw overlays
+ for pixbuf_id, x, y in seriko.iter_overlays():
+ try:
+ pixbuf = self.get_pixbuf(pixbuf_id)
+ w = pixbuf.get_width()
+ h = pixbuf.get_height()
+ except:
+ continue
+ # overlay surface pixbuf
+ sw = surface_pixbuf.get_width()
+ sh = surface_pixbuf.get_height()
+ if x + w > sw:
+ w = sw - x
+ if y + h > sh:
+ h = sh - y
+ if x < 0:
+ dest_x = 0
+ w += x
+ else:
+ dest_x = x
+ if y < 0:
+ dest_y = 0
+ h += y
+ else:
+ dest_y = y
+ pixbuf.composite(surface_pixbuf, dest_x, dest_y,
+ w, h, x, y, 1.0, 1.0,
+ gtk.gdk.INTERP_BILINEAR, 255)
+ del pixbuf
+ ##gc.collect() # XXX
+ else:
+ surface_pixbuf = None
+ self.frame_buffer.append((frame, move, surface_pixbuf, dirty))
+
+ def update(self):
+ if len(self.frame_buffer) > 0:
+ frame, move, surface_pixbuf, dirty = self.frame_buffer.pop(0)
+ if move is not None:
+ self.move_surface(*move)
+ if not dirty:
+ return
else:
surface_pixbuf = self.create_surface_pixbuf()
if self.__scale != 100:
self.seriko.remove_overlay(actor)
def add_overlay(self, actor, pixbuf_id, x, y):
- self.seriko.add_overlay(actor, pixbuf_id, x, y)
+ self.seriko.add_overlay(self, actor, pixbuf_id, x, y)
def __move(self, xoffset=0, yoffset=0):
x, y = self.get_position()
self.reset_pixbuf_cache()
for tag in self.callbacks:
self.darea.disconnect(tag)
- self.seriko.terminate()
+ self.seriko.terminate(self)
self.window.remove(self.darea)
self.darea.destroy()
self.window.destroy()