def set_mode(self, mode_info): """Initialise a given text or graphics mode.""" self.text_mode = mode_info.is_text_mode # unpack mode info struct self.font_height = mode_info.font_height self.font_width = mode_info.font_width # prebuilt glyphs # NOTE: [x][y] format - change this if we change pixels2d self.glyph_dict = { u'\0': numpy.zeros((self.font_width, self.font_height)) } self.num_pages = mode_info.num_pages self.mode_has_blink = mode_info.has_blink self.mode_has_artifacts = False if not self.text_mode: self.bitsperpixel = mode_info.bitsperpixel self.mode_has_artifacts = mode_info.supports_artifacts # logical size self.size = (mode_info.pixel_width, mode_info.pixel_height) self._resize_display(*self._find_display_size( self.size[0], self.size[1], self.border_width)) # set standard cursor self.set_cursor_shape(self.font_width, self.font_height, 0, self.font_height) # screen pages canvas_width, canvas_height = self.size self.canvas = [ sdl2.SDL_CreateRGBSurface(0, canvas_width, canvas_height, 8, 0, 0, 0, 0) for _ in range(self.num_pages) ] self.pixels = [pixels2d(canvas.contents) for canvas in self.canvas] # create work surface for border and composite self.border_x = int(canvas_width * self.border_width // 200) self.border_y = int(canvas_height * self.border_width // 200) work_width = canvas_width + 2 * self.border_x work_height = canvas_height + 2 * self.border_y sdl2.SDL_FreeSurface(self.work_surface) self.work_surface = sdl2.SDL_CreateRGBSurface(0, work_width, work_height, 8, 0, 0, 0, 0) self.work_pixels = pixels2d( self.work_surface.contents)[self.border_x:work_width - self.border_x, self.border_y:work_height - self.border_y] # create overlay for clipboard selection feedback # use convertsurface to create a copy of the display surface format pixelformat = self.display_surface.contents.format self.overlay = sdl2.SDL_ConvertSurface(self.work_surface, pixelformat, 0) sdl2.SDL_SetSurfaceBlendMode(self.overlay, sdl2.SDL_BLENDMODE_ADD) # initialise clipboard self.clipboard = video_graphical.ClipboardInterface( self, mode_info.width, mode_info.height) self.screen_changed = True self._has_window = True
def _do_flip(self): """Draw the canvas to the screen.""" sdl2.SDL_FillRect(self.work_surface, None, self.border_attr) if self.composite_artifacts: self.work_pixels[:] = video_graphical.apply_composite_artifacts( self.pixels[self.vpagenum], 4 // self.bitsperpixel) sdl2.SDL_SetSurfacePalette(self.work_surface, self.composite_palette) else: self.work_pixels[:] = self.pixels[self.vpagenum] sdl2.SDL_SetSurfacePalette(self.work_surface, self.show_palette[self.blink_state]) # apply cursor to work surface self._show_cursor(True) # convert 8-bit work surface to (usually) 32-bit display surface format pixelformat = self.display_surface.contents.format conv = sdl2.SDL_ConvertSurface(self.work_surface, pixelformat, 0) # scale converted surface and blit onto display if not self.smooth: sdl2.SDL_BlitScaled(conv, None, self.display_surface, None) else: # smooth-scale converted surface w, h = self.window_width, self.window_height zoomx = ctypes.c_double(w / (self.size[0] + 2.0 * self.border_x)) zoomy = ctypes.c_double(h / (self.size[1] + 2.0 * self.border_y)) # only free the surface just before zoomSurface needs to re-allocate # so that the memory block is highly likely to be easily available # this seems to avoid unpredictable delays sdl2.SDL_FreeSurface(self.zoomed) self.zoomed = sdl2.sdlgfx.zoomSurface(conv, zoomx, zoomy, sdl2.sdlgfx.SMOOTHING_ON) # blit onto display sdl2.SDL_BlitSurface(self.zoomed, None, self.display_surface, None) # create clipboard feedback if self.clipboard.active(): rects = (sdl2.SDL_Rect(r[0] + self.border_x, r[1] + self.border_y, r[2], r[3]) for r in self.clipboard.selection_rect) sdl_rects = (sdl2.SDL_Rect * len(self.clipboard.selection_rect))(*rects) sdl2.SDL_FillRect( self.overlay, None, sdl2.SDL_MapRGBA(self.overlay.contents.format, 0, 0, 0, 0)) sdl2.SDL_FillRects( self.overlay, sdl_rects, len(sdl_rects), sdl2.SDL_MapRGBA(self.overlay.contents.format, 128, 0, 128, 0)) sdl2.SDL_BlitScaled(self.overlay, None, self.display_surface, None) # flip the display sdl2.SDL_UpdateWindowSurface(self.display) # destroy the temporary surface sdl2.SDL_FreeSurface(conv)