def set_clip(self, rect): """ set_clip(rect) -> None set the current clipping area of the Surface """ self.check_surface() if rect: sdlrect = ffi.new('SDL_Rect*') sdlrect.x, sdlrect.y, sdlrect.w, sdlrect.h = \ rect_vals_from_obj(rect) res = sdl.SDL_SetClipRect(self._c_surface, sdlrect) else: res = sdl.SDL_SetClipRect(self._c_surface, ffi.NULL) if res == -1: raise SDLError.from_sdl_error()
def blit(self, source, dest, area=None, special_flags=0): """ blit(source, dest, area=None, special_flags = 0) -> Rect draw one image onto another """ if not self._c_surface or not source._c_surface: raise SDLError("display Surface quit") if self.is_pure_opengl(): raise SDLError("Cannot blit to OPENGL Surfaces (OPENGLBLIT is ok)") srcrect = ffi.new('SDL_Rect*') destrect = ffi.new('SDL_Rect*') if area is not None: srcrect.x, srcrect.y, srcrect.w, srcrect.h = \ rect_vals_from_obj(area) else: srcrect.w = source._w srcrect.h = source._h if isinstance(dest, tuple) and len(dest) == 2: destrect.x = int(dest[0]) destrect.y = int(dest[1]) destrect.w = source._w destrect.h = source._h else: destrect.x, destrect.y, destrect.w, destrect.h = \ rect_vals_from_obj(dest) c_dest = self._c_surface c_src = source._c_surface c_subsurface = None flags = special_flags if self.subsurfacedata: owner = self.subsurfacedata.owner c_subsurface = owner._c_surface suboffsetx = self.subsurfacedata.xoffset suboffsety = self.subsurfacedata.yoffset while owner.subsurfacedata: subdata = owner.subsurfacedata owner = subdata.owner c_subsurface = owner._c_surface suboffsetx += subdata.xoffset suboffsety += subdata.yoffset orig_clip = ffi.new('SDL_Rect*') sub_clip = ffi.new('SDL_Rect*') sdl.SDL_GetClipRect(c_subsurface, orig_clip) sdl.SDL_GetClipRect(self._c_surface, sub_clip) sub_clip[0].x += suboffsetx sub_clip[0].y += suboffsety sdl.SDL_SetClipRect(c_subsurface, sub_clip) destrect.x += suboffsetx destrect.y += suboffsety c_dest = c_subsurface # TODO: implement special blend flags # these checks come straight from pygame - copied comments if (c_dest.format.Amask and (c_dest.flags & sdl.SDL_SRCALPHA) and not (c_src.format.Amask and not (c_src.flags & sdl.SDL_SRCALPHA)) and (c_dest.format.BytesPerPixel == 2 or c_dest.format.BytesPerPixel == 4)): # SDL works for 2 and 4 bytes res = sdl.pygame_Blit(c_src, srcrect, c_dest, destrect, flags) elif flags or (c_src.flags & (sdl.SDL_SRCALPHA | sdl.SDL_SRCCOLORKEY) and c_dest.pixels == c_src.pixels and check_surface_overlap(c_src, srcrect, c_dest, destrect)): ''' This simplification is possible because a source subsurface is converted to its owner with a clip rect and a dst subsurface cannot be blitted to its owner because the owner is locked. ''' res = sdl.pygame_Blit(c_src, srcrect, c_dest, destrect, flags) # can't blit alpha to 8bit, crashes SDL elif (c_dest.format.BytesPerPixel == 1 and (c_src.format.Amask or c_src.flags & sdl.SDL_SRCALPHA)): if c_src.format.BytesPerPixel == 1: res = sdl.pygame_Blit(c_src, srcrect, c_dest, destrect, 0) elif sdl.SDL_WasInit(sdl.SDL_INIT_VIDEO): # TODO: SDL_DisplayFormat segfaults c_src = sdl.SDL_DisplayFormat(c_src) if c_src: res = sdl.SDL_BlitSurface(c_src, srcrect, c_dest, destrect) sdl.SDL_FreeSurface(c_src) else: res = -1 else: raise NotImplementedError() else: res = sdl.SDL_BlitSurface(c_src, srcrect, c_dest, destrect) if c_subsurface: sdl.SDL_SetClipRect(c_subsurface, orig_clip) destrect.x -= suboffsetx destrect.y -= suboffsety else: # TODO: prep/unprep pass if res == -1: raise SDLError.from_sdl_error() elif res == -2: raise SDLError("Surface was lost") return Rect._from4(destrect.x, destrect.y, destrect.w, destrect.h)