diff --git a/drawing.py b/drawing.py new file mode 100644 index 0000000..f92cda6 --- /dev/null +++ b/drawing.py @@ -0,0 +1,113 @@ +# fx-92 Scientifique Collège+ language interpreter: On-screen drawing + +from sdl2 import * + +class Window: + """ + An SDL window with pixel scaling. + """ + + BLACK = (0, 0, 0, 255) + WHITE = (255, 255, 255, 255) + + def __init__(self, width, height, scale): + self.width = width + self.height = height + self.scale = scale + + def __enter__(self): + """ + Enter window context: allocate and create a window. + """ + + if SDL_WasInit(SDL_INIT_VIDEO): + raise Exception("Cannot create two windows") + + if SDL_Init(SDL_INIT_VIDEO) < 0: + raise Exception("Failed to initialize SDL") + + # Create the window + self.w = SDL_CreateWindow("fx-92 Scientifique Collège+".encode(), + SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, + self.width*self.scale, self.height*self.scale, SDL_WINDOW_SHOWN) + if self.w is None: + raise Exception("Failed to create window") + + # Create the renderer + self.r = SDL_CreateRenderer(self.w, -1, SDL_RENDERER_ACCELERATED) + if self.r is None: + SDL_DestroyWindow(self.w) + raise Exception("Failed to create renderer") + + # Create the base texture where things will be rendered at scale 1 + self.t = SDL_CreateTexture(self.r, SDL_PIXELFORMAT_ARGB8888, + SDL_TEXTUREACCESS_TARGET, self.width, self.height) + if self.t is None: + SDL_DestroyRenderer(r) + SDL_DestroyWindow(w) + raise Exception("Failed to create texture") + + SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, b'0') + SDL_SetRenderTarget(self.r, self.t) + + self.clear(self.WHITE) + self.update() + + return self + + def __exit__(self, *args): + """ + Exit context: close and destroy window. + """ + + if self.t is not None: + SDL_SetRenderTarget(self.r, None) + SDL_DestroyTexture(self.t) + if self.r is not None: + SDL_DestroyRenderer(self.r) + if self.w is not None: + SDL_DestroyWindow(self.w) + + SDL_Quit() + + def clear(self, color): + """Clear screen in a uniform color.""" + + SDL_SetRenderDrawColor(self.r, *color) + SDL_RenderClear(self.r) + + def line(self, x1, x2, y1, y2, color): + """Draw a straight line.""" + + SDL_SetRenderDrawColor(self.r, *color) + SDL_RenderDrawLine(self.r, x1, x2, y1, y2) + + def wait(self): + """Wait for the window to be closed.""" + + event = SDL_Event() + while 1: + SDL_WaitEvent(event) + + if event.type == SDL_QUIT: + break + + if event.type == SDL_KEYDOWN: + key = event.key.keysym.sym + if key == SDLK_s: + print("Going to save the picture, probably") + + def update(self): + """Push window contents on-screen.""" + + # Target the window with scaling + SDL_SetRenderTarget(self.r, None) + SDL_RenderSetScale(self.r, self.scale, self.scale) + + # Push that to the screen + SDL_RenderCopy(self.r, self.t, None, None) + SDL_RenderPresent(self.r) + + # Go back to the texture + SDL_SetRenderTarget(self.r, self.t) + SDL_RenderSetScale(self.r, 1, 1) diff --git a/fx92.py b/fx92.py index 4f9e4bf..3e739b4 100755 --- a/fx92.py +++ b/fx92.py @@ -4,6 +4,7 @@ import sys from parser import UrlParser from printer import print_ast +from drawing import Window #--- # fx-92 SC+ interpreter @@ -39,5 +40,11 @@ def main(argv): print_ast(ast, lang="ast") + with Window(width=96, height=32, scale=8) as w: + w.clear(w.WHITE) + w.line(1, 1, 20, 20, w.BLACK) + w.update() + w.wait() + if __name__ == "__main__": main(sys.argv)