# HG changeset patch # User Radek Brich # Date 1318407087 -7200 # Node ID feee783d4fc520aa0dd5b8372bb5e60ad1187e09 # Parent 139d1241b4c56408bdc0bd0c035aebb1dcfae7a6 DriverPygame: output to character buffer, draw whole screen at once. diff -r 139d1241b4c5 -r feee783d4fc5 demo_window.py --- a/demo_window.py Wed Oct 12 00:58:46 2011 +0200 +++ b/demo_window.py Wed Oct 12 10:11:27 2011 +0200 @@ -1,11 +1,11 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- +import cProfile, pstats import locale import os from tuikit.application import Application -from tuikit.editfield import EditField from tuikit.window import Window from tuikit.button import Button @@ -46,5 +46,9 @@ locale.setlocale(locale.LC_ALL, '') os.environ['ESCDELAY'] = '25' # do not wait 1 second after pressing Escape key app = MyApplication() - app.start() + #app.start() + + cProfile.run('app.start()', 'appstats') + p = pstats.Stats('appstats') + p.sort_stats('time', 'cumulative').print_stats(20) diff -r 139d1241b4c5 -r feee783d4fc5 tuikit/driver_pygame.py --- a/tuikit/driver_pygame.py Wed Oct 12 00:58:46 2011 +0200 +++ b/tuikit/driver_pygame.py Wed Oct 12 10:11:27 2011 +0200 @@ -8,11 +8,11 @@ from tuikit.common import Coords, Size, MouseEvent -class CharCache: +class TerminalScreen: - '''CharCache should implement character cache, as the name suggests. + '''Provide character-level output to screen SDL surface. - Currently it does not, characters ale rendered directly from TTF. + This is performance bottleneck and should be optimized as much as possible. ''' @@ -32,7 +32,7 @@ else: self.render = self.render_noglyph - def render_glyph(self, screen, x, y, c, fgcolor, bgcolor, attr): + def render_glyph(self, screen, x, y, c, fgcolor, bgcolor, defcolor, attr): '''Render using render_glyph and metrics. This is the correct way, but the output seems same as of render_noglyph @@ -40,12 +40,21 @@ This implements render() method. See render_noglyph for other implementation. - ''' + ''' + # draw background + dest = Coords(x * self.charsize.w, y * self.charsize.h) + if bgcolor != defcolor: + screen.fill(bgcolor, pygame.Rect(dest.x, dest.y, self.charsize.w, self.charsize.h)) + + if not c: + return + + # choose font if attr == 'bold': font = self.font_bold else: font = self.font - + # render character, get metrics surface = font.render_glyph(c, True, fgcolor, bgcolor) metrics = font.metrics(c)[0] @@ -65,10 +74,6 @@ if maxx > advance: maxx = advance - # draw background - dest = Coords(x * self.charsize.w, y * self.charsize.h) - screen.fill(bgcolor, pygame.Rect(dest.x, dest.y, self.charsize.w, self.charsize.h)) - # draw character dest.x += minx dest.y += ascent - maxy @@ -164,7 +169,7 @@ self.log = logging.getLogger('tuikit') self.screen = None self.size.w, self.size.h = 120, 40 # screen size in characters - self.charcache = None + self.term = None self.charsize = Size(16, 8) # character size in pixels self.last_keypress = None self.last_key = None @@ -175,12 +180,17 @@ def start(self, mainfunc): pygame.init() - self.charcache = CharCache() - self.charsize = self.charcache.charsize + self.term = TerminalScreen() + self.charsize = self.term.charsize + self.resize_screen() + mainfunc() + + def resize_screen(self): mode = self.size.w * self.charsize.w, self.size.h * self.charsize.h self.screen = pygame.display.set_mode(mode, pygame.RESIZABLE) - mainfunc() - + numchars = self.size.w * self.size.h + self.screenchars = [' '] * numchars + self.screencolors = [self.default_color] * numchars ## input ## @@ -218,8 +228,7 @@ neww, newh = ev.w // self.charsize.w, ev.h // self.charsize.h if neww != self.size.w or newh != self.size.h: self.size.w, self.size.h = neww, newh - mode = self.size.w * self.charsize.w, self.size.h * self.charsize.h - self.screen = pygame.display.set_mode(mode, pygame.RESIZABLE) + self.resize_screen() events.append(('resize',)) elif ev.type == pygame.QUIT: events.append(('quit',)) @@ -242,16 +251,31 @@ def erase(self): '''Clear screen.''' - self.screen.fill(self.colormap['black']) + numchars = self.size.w * self.size.h + for pos in range(numchars): + self.screenchars[pos] = ' ' + self.screencolors[pos] = self.default_color + self.screen.fill(self.default_color[1]) def putch(self, x, y, c): if not self.clipstack.test(x, y): return - fgcolor, bgcolor, attr = self.current_color - self.charcache.render(self.screen, x, y, c, fgcolor, bgcolor, attr) + pos = y*self.size.w+x + self.screencolors[pos] = self.current_color + self.screenchars[pos] = c def commit(self): '''Commit changes to the screen.''' + pos = 0 + for y in range(self.size.h): + for x in range(self.size.w): + fgcolor, bgcolor, attr = self.screencolors[pos] + c = self.screenchars[pos] + if c == ' ': + c = None + self.term.render(self.screen, x, y, c, + fgcolor, bgcolor, self.default_color[1], attr) + pos += 1 pygame.display.flip()