def _set_at(self, x, y, c_color): bpp = self._format.BytesPerPixel if bpp == 1: pixels = ffi.cast("uint8_t*", self._c_surface.pixels) pixels[y * self._c_surface.pitch // bpp + x] = c_color elif bpp == 2: pixels = ffi.cast("uint16_t*", self._c_surface.pixels) pixels[y * self._c_surface.pitch // bpp + x] = c_color elif bpp == 3: pixels = ffi.cast("uint8_t*", self._c_surface.pixels) base = y * self._c_surface.pitch + x * 3 fmt = self._format if get_sdl_byteorder() == sdl.SDL_LIL_ENDIAN: pixels[base + (fmt.Rshift >> 3)] = ffi.cast('uint8_t', c_color >> 16) pixels[base + (fmt.Gshift >> 3)] = ffi.cast('uint8_t', c_color >> 8) pixels[base + (fmt.Bshift >> 3)] = ffi.cast('uint8_t', c_color) else: pixels[base + 2 - (fmt.Rshift >> 3)] = ffi.cast('uint8_t', c_color >> 16) pixels[base + 2 - (fmt.Gshift >> 3)] = ffi.cast('uint8_t', c_color >> 8) pixels[base + 2 - (fmt.Bshift >> 3)] = ffi.cast('uint8_t', c_color) elif bpp == 4: pixels = ffi.cast("uint32_t*", self._c_surface.pixels) pixels[y * (self._c_surface.pitch // bpp) + x] = c_color else: raise RuntimeError("invalid color depth for surface")
def _drawvertline(surface, c_color, start_y, end_y, x): """Draw a vertical line using SDL_FillRect""" sdlrect = ffi.new('SDL_Rect*') if start_y > end_y: end_y, start_y = start_y, end_y sdlrect.x = ffi.cast("int16_t", x) sdlrect.y = ffi.cast("int16_t", start_y) sdlrect.w = 1 sdlrect.h = ffi.cast("uint16_t", end_y - start_y + 1) sdl.SDL_FillRect(surface._c_surface, sdlrect, c_color)
def _drawhorizline(surface, c_color, start_x, end_x, y): """Draw a horizontal line using SDL_FillRect""" sdlrect = ffi.new('SDL_Rect*') if start_x > end_x: end_x, start_x = start_x, end_x sdlrect.x = ffi.cast("int16_t", start_x) sdlrect.y = ffi.cast("int16_t", y) sdlrect.w = ffi.cast("uint16_t", end_x - start_x + 1) sdlrect.h = 1 sdl.SDL_FillRect(surface._c_surface, sdlrect, c_color)
def check_surface_overlap(c_src, srcrect, c_dest, destrect): srcx, srcy, destx, desty, w, h = (srcrect.x, srcrect.y, destrect.x, destrect.y, srcrect.w, srcrect.h) if srcx < 0: w += srcx destx -= srcx srcx = 0 maxw = c_src.w - srcx if maxw < w: w = maxw if srcy < 0: h += srcy desty -= srcy srcy = 0 maxh = c_src.h - srcy if maxh < h: h = maxh clip = c_dest.clip_rect x = clip.x - destx if x > 0: w -= x destx += x srcx += x x = destx + w - clip.x - clip.w if x > 0: w -= x y = clip.y - desty if y > 0: h -= y desty += y srcy += y y = desty + h - clip.y - clip.h if y > 0: h -= y if w <= 0 or h <= 0: return None srcpixels = ffi.cast("uint8_t*", c_src.pixels) srcpixels += c_src.offset + srcy * c_src.pitch + \ srcx * c_src.format.BytesPerPixel destpixels = ffi.cast("uint8_t*", c_dest.pixels) destpixels += c_src.offset + desty * c_dest.pitch + \ destx * c_dest.format.BytesPerPixel if destpixels <= srcpixels: return False span = w * c_src.format.BytesPerPixel if destpixels >= (srcpixels + (h - 1) * c_src.pitch + span): return False destoffset = (destpixels - srcpixels) % c_src.pitch return (destoffset < span) or (destoffset > c_src.pitch - span)
def save_jpg(surf, filename): if (surf.format.BytesPerPixel == 3 and not (surf.flags & sdl.SDL_SRCALPHA) and surf.format.Rshift == 0): ss_surf = surf else: if get_sdl_byteorder() == sdl.SDL_LIL_ENDIAN: rmask, gmask, bmask, amask = 0xff, 0xff00, 0xff0000, 0xff000000 else: rmask, gmask, bmask, amask = 0xff00, 0xff, 0xff0000, 0xff000000 ss_surf = sdl.SDL_CreateRGBSurface(sdl.SDL_SWSURFACE, surf.w, surf.h, 24, rmask, gmask, bmask, amask) if not ss_surf: return -1 rect = ffi.new('SDL_Rect*') rect.w = surf.w rect.h = surf.h sdl.SDL_BlitSurface(surf, rect, ss_surf, ffi.NULL) ss_rows = ffi.new('unsigned char*[]', surf.h) ss_pixels = ffi.cast('unsigned char*', ss_surf.pixels) for i in range(surf.h): ss_rows[i] = ss_pixels + i * ss_surf.pitch err_msg = ffi.new('char**') result = jpglib.write_jpeg(filename, ss_rows, surf.w, surf.h, 85, err_msg) if ss_surf is not surf: sdl.SDL_FreeSurface(ss_surf) if result == -1: raise IOError("JPGError: %s" % ffi.string(err_msg[0])) return result
def save_png(surf, filename): alpha = bool(surf.format.Amask) if get_sdl_byteorder() == sdl.SDL_LIL_ENDIAN: rmask, gmask, bmask, amask = 0xff, 0xff00, 0xff0000, 0xff000000 else: rmask, gmask, bmask, amask = 0xff00, 0xff0000, 0xff, 0x000000ff ss_surf = sdl.SDL_CreateRGBSurface(sdl.SDL_SWSURFACE | sdl.SDL_SRCALPHA, surf.w, surf.h, 32 if alpha else 24, rmask, gmask, bmask, amask) if not ss_surf: return -1 with opaque(surf): rect = ffi.new('SDL_Rect*') rect.w = surf.w rect.h = surf.h sdl.SDL_BlitSurface(surf, rect, ss_surf, ffi.NULL) ss_rows = ffi.new('unsigned char*[]', surf.h) ss_pixels = ffi.cast('unsigned char*', ss_surf.pixels) for i in range(surf.h): ss_rows[i] = ss_pixels + i * ss_surf.pitch err_msg = ffi.new('char**') result = pnglib.write_png(filename, ss_rows, surf.w, surf.h, (pnglib.PNG_COLOR_TYPE_RGB_ALPHA if alpha else pnglib.PNG_COLOR_TYPE_RGB), 8, err_msg) sdl.SDL_FreeSurface(ss_surf) if result == -1: raise IOError("PNGError: %s" % ffi.string(err_msg[0])) return result
def get_raw(self): """ get_raw() -> bytes return a bytestring copy of the Sound samples. """ check_mixer() return ffi.buffer(ffi.cast('char*', self.chunk.abuf), self.chunk.alen)[:]
def _get_at(self, x, y): bpp = self._format.BytesPerPixel if bpp == 1: pixels = ffi.cast("uint8_t*", self._c_surface.pixels) return pixels[y * self._c_surface.pitch // bpp + x] elif bpp == 2: pixels = ffi.cast("uint16_t*", self._c_surface.pixels) return pixels[y * self._c_surface.pitch // bpp + x] elif bpp == 3: pixels = ffi.cast("uint8_t*", self._c_surface.pixels) base = y * self._c_surface.pitch + x * 3 return (pixels[base + BYTE0] + (pixels[base + BYTE1] << 8) + (pixels[base + BYTE2] << 16)) elif bpp == 4: pixels = ffi.cast("uint32_t*", self._c_surface.pixels) return pixels[y * self._c_surface.pitch // bpp + x]
def _timer_callback(interval, param): if sdl.SDL_WasInit(sdl.SDL_INIT_VIDEO): event = ffi.new("SDL_Event*") event.type = ffi.cast("intptr_t", param) # SDL will make a copy of the event while handling SDL_PushEvent, # so we don't need to hold the allocated memory after this call. sdl.SDL_PushEvent(event) return interval
def smoothscale(surface, size, dest_surface=None): """ smoothscale(Surface, (width, height), DestSurface = None) -> Surface scale a surface to an arbitrary size smoothly """ width, height = size if width < 0 or height < 0: raise ValueError("Cannot scale to negative size") c_surf = surface._c_surface bpp = c_surf.format.BytesPerPixel if bpp < 3 or bpp > 4: raise ValueError("Only 24-bit or 32-bit surfaces can be" " smoothly scaled") if dest_surface is None: new_surf = new_surface_from_surface(c_surf, width, height) else: new_surf = dest_surface._c_surface if new_surf.w != width or new_surf.h != height: raise ValueError("Destination surface not the given width or height.") if (width * bpp + 3) // 4 > new_surf.pitch: raise ValueError("SDL Error: destination surface pitch not" " 4-byte aligned.") if width and height: with locked(new_surf): with locked(c_surf): if c_surf.w == width and c_surf.h == height: # Non-scaling case, so just copy the correct pixels c_pitch = c_surf.pitch n_pitch = new_surf.pitch srcpixels = ffi.cast('uint8_t*', c_surf.pixels) destpixels = ffi.cast('uint8_t*', new_surf.pixels) step = width * bpp for y in range(0, height): offset_n = y * n_pitch offset_c = y * c_pitch destpixels[offset_n:offset_n + step] = srcpixels[offset_c:offset_c + step] else: sdl.scalesmooth(c_surf, new_surf) if dest_surface: return dest_surface return Surface._from_sdl_surface(new_surf)
def unmap_rgb(self, mapped_int): """ unmap_rgb(mapped_int) -> Color convert a mapped integer color value into a Color """ self.check_surface() mapped_int = ffi.cast('uint32_t', mapped_int) r, g, b, a = [ffi.new('uint8_t*') for i in range(4)] sdl.SDL_GetRGBA(mapped_int, self._format, r, g, b, a) return Color(r[0], g[0], b[0], a[0])
def scroll(self, dx=0, dy=0): """ scroll(dx=0, dy=0) -> None Shift the surface image in place """ self.check_surface() if self.is_pure_opengl(): raise SDLError("Cannot scroll an OPENGL Surfaces (OPENGLBLIT is ok)") if not (dx or dy): return None clip_rect = self._c_surface.clip_rect w = clip_rect.w h = clip_rect.h if dx >= w or dx <= -w or dy >= h or dy <= -h: return None with locked(self._c_surface): bpp = self._c_surface.format.BytesPerPixel pitch = self._c_surface.pitch pixels = ffi.cast("uint8_t*", self._c_surface.pixels) src = dst = pixels + clip_rect.y * pitch + clip_rect.x * bpp if dx >= 0: w -= dx if dy > 0: h -= dy dst += dy * pitch + dx * bpp else: h += dy src -= dy * pitch dst += dx * bpp else: w += dx if dy > 0: h -= dy src -= dx * bpp dst += dy * pitch else: h += dy src -= dy * pitch + dx * bpp if src < dst: src += (h - 1) * pitch dst += (h - 1) * pitch pitch = -pitch span = w * bpp for _ in range(h): sdl.memmove(dst, src, span) src += pitch dst += pitch return None
def smoothscale(surface, size, dest_surface=None): """ smoothscale(Surface, (width, height), DestSurface = None) -> Surface scale a surface to an arbitrary size smoothly """ width, height = size if width < 0 or height < 0: raise ValueError("Cannot scale to negative size") c_surf = surface._c_surface bpp = c_surf.format.BytesPerPixel if bpp < 3 or bpp > 4: raise ValueError("Only 24-bit or 32-bit surfaces can be" " smoothly scaled") if dest_surface is None: new_surf = new_surface_from_surface(c_surf, width, height) else: new_surf = dest_surface._c_surface if new_surf.w != width or new_surf.h != height: raise ValueError("Destination surface not the given width or height.") if (width * bpp + 3) // 4 > new_surf.pitch: raise ValueError("SDL Error: destination surface pitch not" " 4-byte aligned.") if width and height: with locked(new_surf): with locked(c_surf): if c_surf.w == width and c_surf.h == height: pitch = c_surf.pitch # Trivial case srcpixels = ffi.cast('uint8_t*', c_surf.pixels) destpixels = ffi.cast('uint8_t*', new_surf.pixels) destpixels[0:height * pitch] = srcpixels[0:height * pitch] else: sdl.scalesmooth(c_surf, new_surf) if dest_surface: return dest_surface return Surface._from_sdl_surface(new_surf)
def set_masks(self, masks): """ set_masks((r,g,b,a)) -> None set the bitmasks needed to convert between a color and a mapped integer """ self.check_surface() try: r, g, b, a = [ffi.cast('uint32_t', m) for m in masks] format = self._format format.Rmask = r format.Gmask = g format.Bmask = b format.Amask = a except (ValueError, TypeError): raise TypeError("invalid argument for masks")
def set_shifts(self, shifts): """ set_shifts((r,g,b,a)) -> None sets the bit shifts needed to convert between a color and a mapped integer """ self.check_surface() try: r, g, b, a = [ffi.cast('uint8_t', s) for s in shifts] format = self._format format.Rshift = r format.Gshift = g format.Bshift = b format.Ashift = a except (ValueError, TypeError): raise TypeError("invalid argument for shifts")
def flip(surface, xaxis, yaxis): c_surf = surface._c_surface w, h = c_surf.w, c_surf.h new_surf = new_surface_from_surface(c_surf, w, h) bpp = c_surf.format.BytesPerPixel pitch = c_surf.pitch with locked(new_surf): with locked(surface._c_surface): # only have to deal with rows if not xaxis: srcpixels = ffi.cast('uint8_t*', c_surf.pixels) destpixels = ffi.cast('uint8_t*', new_surf.pixels) if not yaxis: # no changes - just copy pixels destpixels[0:h * pitch] = srcpixels[0:h * pitch] else: for y in range(h): dest_start = (h - y - 1) * pitch src_start = y * pitch destpixels[dest_start:dest_start + pitch] = \ srcpixels[src_start:src_start + pitch] # have to calculate position for individual pixels else: if not yaxis: def get_y(y): return y else: def get_y(y): return h - y - 1 if bpp in (1, 2, 4): ptr_type = 'uint%s_t*' % c_surf.format.BitsPerPixel srcpixels = ffi.cast(ptr_type, c_surf.pixels) destpixels = ffi.cast(ptr_type, new_surf.pixels) for y in range(h): dest_row_start = get_y(y) * w src_row_start = y * w for x in range(w): destpixels[dest_row_start + (w - x - 1)] = \ srcpixels[src_row_start + x] else: srcpixels = ffi.cast('uint8_t*', c_surf.pixels) destpixels = ffi.cast('uint8_t*', new_surf.pixels) for y in range(h): dest_row_start = get_y(y) * pitch src_row_start = y * pitch for x in range(0, pitch, 3): dest_pix_start = dest_row_start + (pitch - x - 3) src_pix_start = src_row_start + x destpixels[dest_pix_start:dest_pix_start + 3] = \ srcpixels[src_pix_start:src_pix_start + 3] return Surface._from_sdl_surface(new_surf)
def post(event): """post(Event): return None place a new event on the queue""" # SDL requires video to be initialised before PushEvent does the right thing check_video() is_blocked = sdl.SDL_EventState(event.type, sdl.SDL_QUERY) == sdl.SDL_IGNORE if is_blocked: raise RuntimeError("event post blocked for %s" % event_name(event.type)) sdl_event = ffi.new("SDL_Event *") sdl_event.type = event.type sdl_event.user.code = _USEROBJECT_CHECK1 sdl_event.user.data1 = _USEROBJECT_CHECK2 sdl_event.user.data2 = ffi.cast("void*", sdl_event) _user_events[sdl_event] = event if sdl.SDL_PushEvent(sdl_event) == -1: raise SDLError.from_sdl_error()
def post(event): """post(Event): return None place a new event on the queue""" # SDL requires video to be initialised before PushEvent does the right thing check_video() is_blocked = sdl.SDL_EventState(event.type, sdl.SDL_QUERY) == sdl.SDL_IGNORE if is_blocked: # Silently drop blocked events, since that's what pygame does # (maybe worth logging somehow?) return None sdl_event = ffi.new("SDL_Event *") sdl_event.type = event.type sdl_event.user.code = _USEROBJECT_CHECK1 sdl_event.user.data1 = _USEROBJECT_CHECK2 sdl_event.user.data2 = ffi.cast("void*", sdl_event) _user_events[sdl_event] = event if sdl.SDL_PushEvent(sdl_event) == -1: raise SDLError.from_sdl_error()
def subsurface(self, *rect): self.check_opengl() try: if hasattr(rect[0], '__iter__'): rect = game_rect_from_obj(rect[0]) else: rect = game_rect_from_obj(rect) except TypeError: raise ValueError("not a valid rect style object") if (rect.x < 0 or rect.x + rect.w > self._c_surface.w or rect.y < 0 or rect.y + rect.h > self._c_surface.h): raise ValueError("subsurface rectangle outside surface area") with locked(self._c_surface): format = self._format pixeloffset = (rect.x * format.BytesPerPixel + rect.y * self._c_surface.pitch) startpixel = ffi.cast("char*", self._c_surface.pixels) + pixeloffset surf = self._c_surface sub = sdl.SDL_CreateRGBSurfaceFrom(startpixel, rect.w, rect.h, format.BitsPerPixel, surf.pitch, format.Rmask, format.Gmask, format.Bmask, format.Amask) if not sub: raise SDLError.from_sdl_error() if format.BytesPerPixel == 1 and format.palette: sdl.SDL_SetPalette(sub, sdl.SDL_LOGPAL, format.palette.colors, 0, format.palette.ncolors); if surf.flags & sdl.SDL_SRCALPHA: sdl.SDL_SetAlpha(sub, surf.flags & sdl.SDL_SRCALPHA, format.alpha); if surf.flags & sdl.SDL_SRCCOLORKEY: sdl.SDL_SetColorKey(sub, surf.flags & (sdl.SDL_SRCCOLORKEY | sdl.SDL_RLEACCEL), format.colorkey) subsurface = Surface._from_sdl_surface(sub) data = SubSurfaceData(self, pixeloffset, rect.x, rect.y) subsurface.subsurfacedata = data return subsurface
def tostring(surface, format, flipped=False): """ tostring(Surface, format, flipped=False) -> string transfer image to string buffer """ surf = surface._c_surface if surf.flags & sdl.SDL_OPENGL: raise NotImplementedError() if format == "P": if surf.format.BytesPerPixel != 1: raise ValueError("Can only create \"P\" format data with " "8bit Surfaces") with locked(surf): string = ffi.buffer(ffi.cast('char*', surf.pixels))[:] else: _tostring = globals().get('_tostring_%s' % format, None) if _tostring is None: raise ValueError("Unrecognized type of format") with locked(surf): string = _tostring(surf, flipped) return string
def set_timer(eventid, milliseconds): """set_timer(eventid, milliseconds) -> None repeatedly create an event on the event queue" """ if eventid <= sdl.SDL_NOEVENT or eventid >= sdl.SDL_NUMEVENTS: raise ValueError("Event id must be between NOEVENT(0) and" " NUMEVENTS(32)") old_event = _event_timers.pop(eventid, None) if old_event: sdl.SDL_RemoveTimer(old_event) if milliseconds <= 0: return _try_init() handle = ffi.cast("void *", eventid) newtimer = sdl.SDL_AddTimer(milliseconds, _timer_callback, handle) if not newtimer: SDLError.from_sdl_error() _event_timers[eventid] = newtimer
def set_timer(eventid, milliseconds): """set_timer(eventid, milliseconds) -> None repeatedly create an event on the event queue" """ if eventid <= sdl.SDL_NOEVENT or eventid >= sdl.SDL_NUMEVENTS: raise ValueError("Event id must be between NOEVENT(0) and" " NUMEVENTS(32)") old_event = _event_timers.pop(eventid, None) if old_event: sdl.SDL_RemoveTimer(old_event) if milliseconds <= 0: return _try_init() handle = ffi.cast("void *", eventid) newtimer = sdl.SDL_AddTimer(milliseconds, _timer_callback, handle) if not newtimer: raise SDLError.from_sdl_error() _event_timers[eventid] = newtimer
def _timer_callback(interval, param): if sdl.SDL_WasInit(sdl.SDL_INIT_VIDEO): event = ffi.new("SDL_Event") event.type = ffi.cast("intptr_t", param) sdl.SDL_PushEvent(event) return interval
return result def fromstring(string, (w, h), format, flipped=False): if w < 1 or h < 1: raise ValueError("Resolution must be positive values") if format == "P": if len(string) != w * h: raise ValueError("String length does not equal format and " "resolution size") surf = sdl.SDL_CreateRGBSurface(0, w, h, 8, 0, 0, 0, 0) if not surf: raise SDLError.from_sdl_error() with locked(surf): pixels = ffi.cast('char*', surf.pixels) for y in range(h): dest = surf.pitch * y src_start = (h - 1 - y) * w if flipped else y * w pixels[dest:dest + w] = string[src_start:src_start + w] elif format == "RGB": if len(string) != w * h * 3: raise ValueError("String length does not equal format and " "resolution size") surf = sdl.SDL_CreateRGBSurface(0, w, h, 24, 0xff, 0xff << 16, 0xff << 8, 0) if not surf: raise SDLError.from_sdl_error() with locked(surf): pixels = ffi.cast("char*", surf.pixels)
""" The pygame event module """ from pygame._sdl import sdl, ffi from pygame._error import SDLError from pygame.display import check_video from pygame.constants import ( ACTIVEEVENT, KEYDOWN, KEYUP, MOUSEMOTION, MOUSEBUTTONDOWN, MOUSEBUTTONUP, JOYAXISMOTION, JOYBALLMOTION, JOYHATMOTION, JOYBUTTONDOWN, JOYBUTTONUP, QUIT, SYSWMEVENT, VIDEORESIZE, VIDEOEXPOSE, USEREVENT, NUMEVENTS, NOEVENT, USEREVENT_DROPFILE) # We do this to avoid roundtripping issues caused by 0xDEADBEEF casting to a # negative number _USEROBJECT_CHECK1 = ffi.cast('int', 0xDEADBEEF) _USEROBJECT_CHECK2 = ffi.cast('void*', 0xFEEDF00D) # I'm not wild about this global dict, but it's the same idea as the linked # list pygame uses and I don't have a better approach right now _user_events = {} def _button_state(state, button): if state & sdl._pygame_SDL_BUTTON(button): return 1 return 0 class EventType(object): """An event object"""
def _tostring_RGBA_PREMULT(surf, flipped, argb=False): if surf.format.BytesPerPixel == 1 or surf.format.Amask == 0: raise ValueError("Can only create pre-multiplied alpha strings if " "the surface has per-pixel alpha") rmask, gmask, bmask, amask = (surf.format.Rmask, surf.format.Gmask, surf.format.Bmask, surf.format.Amask) rshift, gshift, bshift, ashift = (surf.format.Rshift, surf.format.Gshift, surf.format.Bshift, surf.format.Ashift) rloss, gloss, bloss, aloss = (surf.format.Rloss, surf.format.Gloss, surf.format.Bloss, surf.format.Aloss) bpp = surf.format.BytesPerPixel h, w = surf.h, surf.w if argb: ri, gi, bi, ai = 1, 2, 3, 0 else: ri, gi, bi, ai = 0, 1, 2, 3 data = ffi.new('char[]', w * h * 4) if bpp == 2: pixels = ffi.cast('uint16_t*', surf.pixels) for y in range(h): src_start = (h - 1 - y) * w if flipped \ else y * w for x in range(w): dest = 4 * (y * w + x) color = pixels[src_start + x] alpha = ((color & amask) >> ashift) << aloss data[dest + ri] = chr_((((color & rmask) >> rshift) << rloss) * alpha // 255) data[dest + gi] = chr_((((color & gmask) >> gshift) << gloss) * alpha // 255) data[dest + bi] = chr_((((color & bmask) >> bshift) << bloss) * alpha // 255) data[dest + ai] = chr_(alpha) elif bpp == 3: pixels = ffi.cast('uint8_t*', surf.pixels) for y in range(h): src_start = (h - 1 - y) * surf.pitch if flipped \ else y * surf.pitch for x in range(w): dest = 4 * (y * w + x) color = (pixels[src_start + x * 3 + BYTE0] + (pixels[src_start + x * 3 + BYTE1] << 8) + (pixels[src_start + x * 3 + BYTE2] << 16)) alpha = ((color & amask) >> ashift) << aloss data[dest + ri] = chr_((((color & rmask) >> rshift) << rloss) * alpha // 255) data[dest + gi] = chr_((((color & gmask) >> gshift) << gloss) * alpha // 255) data[dest + bi] = chr_((((color & bmask) >> bshift) << bloss) * alpha // 255) data[dest + ai] = chr_(alpha) elif bpp == 4: pixels = ffi.cast('uint32_t*', surf.pixels) for y in range(h): src_start = (h - 1 - y) * w if flipped \ else y * w for x in range(w): dest = 4 * (y * w + x) color = pixels[src_start + x] alpha = ((color & amask) >> ashift) << aloss if alpha == 0: data[dest + ri] = data[dest + gi] = data[dest + bi] \ = chr_(0) else: data[dest + ri] = chr_( (((color & rmask) >> rshift) << rloss) * alpha // 255) data[dest + gi] = chr_( (((color & gmask) >> gshift) << gloss) * alpha // 255) data[dest + bi] = chr_( (((color & bmask) >> bshift) << bloss) * alpha // 255) data[dest + ai] = chr_(alpha) else: raise ValueError("invalid color depth") return ffi.buffer(data)[:]
def _tostring_RGB(surf, flipped): rmask, gmask, bmask, amask = (surf.format.Rmask, surf.format.Gmask, surf.format.Bmask, surf.format.Amask) rshift, gshift, bshift, ashift = (surf.format.Rshift, surf.format.Gshift, surf.format.Bshift, surf.format.Ashift) rloss, gloss, bloss, aloss = (surf.format.Rloss, surf.format.Gloss, surf.format.Bloss, surf.format.Aloss) bpp = surf.format.BytesPerPixel h, w = surf.h, surf.w data = ffi.new('char[]', w * h * 3) if bpp == 1: pixels = ffi.cast('uint8_t*', surf.pixels) colors = surf.format.palette.colors for y in range(h): src_start = (h - 1 - y) * w if flipped \ else y * w for x in range(w): dest = 3 * (y * w + x) color = pixels[src_start + x] data[dest] = chr_(colors[color].r) data[dest + 1] = chr_(colors[color].g) data[dest + 2] = chr_(colors[color].b) elif bpp == 2: pixels = ffi.cast('uint16_t*', surf.pixels) for y in range(h): src_start = (h - 1 - y) * w if flipped \ else y * w for x in range(w): dest = 3 * (y * w + x) color = pixels[src_start + x] data[dest] = chr_(((color & rmask) >> rshift) << rloss) data[dest + 1] = chr_(((color & gmask) >> gshift) << gloss) data[dest + 2] = chr_(((color & bmask) >> bshift) << bloss) elif bpp == 3: pixels = ffi.cast('uint8_t*', surf.pixels) for y in range(h): src_start = (h - 1 - y) * surf.pitch if flipped \ else y * surf.pitch for x in range(w): dest = 3 * (y * w + x) color = (pixels[src_start + x * 3 + BYTE0] + (pixels[src_start + x * 3 + BYTE1] << 8) + (pixels[src_start + x * 3 + BYTE2] << 16)) data[dest] = chr_(((color & rmask) >> rshift) << rloss) data[dest + 1] = chr_(((color & gmask) >> gshift) << gloss) data[dest + 2] = chr_(((color & bmask) >> bshift) << bloss) elif bpp == 4: pixels = ffi.cast('uint32_t*', surf.pixels) for y in range(h): src_start = (h - 1 - y) * w if flipped \ else y * w for x in range(w): dest = 3 * (y * w + x) color = pixels[src_start + x] data[dest] = chr_(((color & rmask) >> rshift) << rloss) data[dest + 1] = chr_(((color & gmask) >> gshift) << gloss) data[dest + 2] = chr_(((color & bmask) >> bshift) << bloss) else: raise ValueError("invalid color depth") return ffi.buffer(data)[:]
def _samples_address(self): return int(ffi.cast('long', self.chunk.abuf))
def fromstring(string, size, format, flipped=False): w, h = size if w < 1 or h < 1: raise ValueError("Resolution must be positive values") if format == "P": if len(string) != w * h: raise ValueError("String length does not equal format and " "resolution size") surf = sdl.SDL_CreateRGBSurface(0, w, h, 8, 0, 0, 0, 0) if not surf: raise SDLError.from_sdl_error() with locked(surf): pixels = ffi.cast('char*', surf.pixels) for y in range(h): dest = surf.pitch * y src_start = (h - 1 - y) * w if flipped else y * w pixels[dest:dest + w] = string[src_start:src_start + w] elif format == "RGB": if len(string) != w * h * 3: raise ValueError("String length does not equal format and " "resolution size") surf = sdl.SDL_CreateRGBSurface(0, w, h, 24, 0xff, 0xff << 16, 0xff << 8, 0) if not surf: raise SDLError.from_sdl_error() with locked(surf): pixels = ffi.cast("char*", surf.pixels) for y in range(h): dest = surf.pitch * y src_start = (h - 1 - y) * w * 3 if flipped else y * w * 3 row = string[src_start:src_start + w * 3] for x in range(0, w * 3, 3): # BYTE0, BYTE1 and BYTE2 are determined by byte order pixels[dest + x + BYTE0] = row[x + BYTE0] pixels[dest + x + BYTE1] = row[x + BYTE1] pixels[dest + x + BYTE2] = row[x + BYTE2] elif format in ("RGBA", "RGBAX", "ARGB"): if len(string) != w * h * 4: raise ValueError("String length does not equal format and " "resolution size") if format == "ARGB": if get_sdl_byteorder() == sdl.SDL_LIL_ENDIAN: rmask, gmask, bmask, amask = (0xff << 8, 0xff << 16, 0xff << 24, 0xff) else: rmask, gmask, bmask, amask = (0xff << 16, 0xff << 8, 0xff, 0xff << 24) surf = sdl.SDL_CreateRGBSurface(sdl.SDL_SRCALPHA, w, h, 32, rmask, gmask, bmask, amask) else: alphamult = format == "RGBA" if get_sdl_byteorder() == sdl.SDL_LIL_ENDIAN: rmask, gmask, bmask = 0xff, 0xff << 8, 0xff << 16 amask = 0xff << 24 if alphamult else 0 else: rmask, gmask, bmask = 0xff << 24, 0xff << 16, 0xff << 8 amask = 0xff if alphamult else 0 surf = sdl.SDL_CreateRGBSurface( sdl.SDL_SRCALPHA if alphamult else 0, w, h, 32, rmask, gmask, bmask, amask) if not surf: raise SDLError.from_sdl_error() with locked(surf): pixels = ffi.cast("char*", surf.pixels) for y in range(h): dest = surf.pitch * y src_start = (h - 1 - y) * w * 4 if flipped else y * w * 4 pixels[dest:dest + w * 4] = string[src_start:src_start + w * 4] else: raise ValueError("Unrecognized type of format") return Surface._from_sdl_surface(surf)
def chop(surface, rect): """ chop(Surface, rect) -> Surface gets a copy of an image with an interior area removed """ rect = Rect(rect) width = rect.width height = rect.width x = rect.x y = rect.y if rect.right > surface._w: width = surface._w - rect.x if rect.height > surface._h: height = surface._h - rect.y if rect.x < 0: width -= -x x = 0 if rect.y < 0: height -= -y y = 0 c_surf = surface._c_surface new_surf = new_surface_from_surface(c_surf, surface._w, surface._h) bpp = c_surf.format.BytesPerPixel pitch = c_surf.pitch w, h = c_surf.w, c_surf.h with locked(new_surf): with locked(c_surf): if bpp in (1, 2, 4): ptr_type = 'uint%s_t*' % c_surf.format.BitsPerPixel srcpixels = ffi.cast(ptr_type, c_surf.pixels) destpixels = ffi.cast(ptr_type, new_surf.pixels) else: srcpixels = ffi.cast('uint8_t*', c_surf.pixels) destpixels = ffi.cast('uint8_t*', new_surf.pixels) dy = 0 for sy in range(0, surface._h): if sy >= y and sy < y + height: continue dx = 0 if bpp in (1, 2, 4): dest_row_start = dy * w src_row_start = sy * w else: dest_row_start = dy * pitch src_row_start = sy * pitch for sx in range(0, surface._w): if sx >= x and sx < x + width: continue if bpp in (1, 2, 4): destpixels[dest_row_start + dx] = \ srcpixels[src_row_start + sx] else: dest_pix_start = dest_row_start + dx src_pix_start = src_row_start + sx destpixels[dest_pix_start:dest_pix_start + 3] = \ srcpixels[src_pix_start:src_pix_start + 3] dx += 1 dy += 1 return Surface._from_sdl_surface(new_surf)
""" The pygame event module """ from pygame._sdl import sdl, ffi from pygame._error import SDLError from pygame.display import check_video from pygame.compat import unichr_ from pygame.constants import ( ACTIVEEVENT, KEYDOWN, KEYUP, MOUSEMOTION, MOUSEBUTTONDOWN, MOUSEBUTTONUP, JOYAXISMOTION, JOYBALLMOTION, JOYHATMOTION, JOYBUTTONDOWN, JOYBUTTONUP, QUIT, SYSWMEVENT, VIDEORESIZE, VIDEOEXPOSE, USEREVENT, NUMEVENTS, NOEVENT, USEREVENT_DROPFILE) # We do this to avoid roundtripping issues caused by 0xDEADBEEF casting to a # negative number _USEROBJECT_CHECK1 = ffi.cast('int', 0xDEADBEEF) _USEROBJECT_CHECK2 = ffi.cast('void*', 0xFEEDF00D) # I'm not wild about this global dict, but it's the same idea as the linked # list pygame uses and I don't have a better approach right now _user_events = {} def _button_state(state, button): if state & sdl._pygame_SDL_BUTTON(button): return 1 return 0 class EventType(object): """An event object"""
def flip(surface, xaxis, yaxis): c_surf = surface._c_surface w, h = c_surf.w, c_surf.h new_surf = new_surface_from_surface(c_surf, w, h) bpp = c_surf.format.BytesPerPixel src_pitch = c_surf.pitch dest_pitch = new_surf.pitch step = w * bpp with locked(new_surf): with locked(surface._c_surface): # only have to deal with rows if not xaxis: srcpixels = ffi.cast('uint8_t*', c_surf.pixels) destpixels = ffi.cast('uint8_t*', new_surf.pixels) if not yaxis: # no changes - just copy pixels for y in range(h): dest_start = y * dest_pitch src_start = y * src_pitch destpixels[dest_start:dest_start + step] = \ srcpixels[src_start:src_start + step] else: for y in range(h): dest_start = (h - y - 1) * dest_pitch src_start = y * src_pitch destpixels[dest_start:dest_start + step] = \ srcpixels[src_start:src_start + step] # have to calculate position for individual pixels else: if not yaxis: def get_y(y): return y else: def get_y(y): return h - y - 1 if bpp in (1, 2, 4): ptr_type = 'uint%s_t*' % c_surf.format.BitsPerPixel srcpixels = ffi.cast(ptr_type, c_surf.pixels) destpixels = ffi.cast(ptr_type, new_surf.pixels) dest_step = dest_pitch // bpp src_step = src_pitch // bpp for y in range(h): dest_row_start = get_y(y) * dest_step src_row_start = y * src_step for x in range(w): destpixels[dest_row_start + (w - x - 1)] = \ srcpixels[src_row_start + x] else: srcpixels = ffi.cast('uint8_t*', c_surf.pixels) destpixels = ffi.cast('uint8_t*', new_surf.pixels) for y in range(h): dest_row_start = get_y(y) * dest_pitch src_row_start = y * src_pitch for x in range(0, src_pitch, 3): dest_pix_start = dest_row_start + (dest_pitch - x - 3) src_pix_start = src_row_start + x destpixels[dest_pix_start:dest_pix_start + 3] = \ srcpixels[src_pix_start:src_pix_start + 3] return Surface._from_sdl_surface(new_surf)
def _tostring_RGBA_PREMULT(surf, flipped, argb=False): if surf.format.BytesPerPixel == 1 or surf.format.Amask == 0: raise ValueError("Can only create pre-multiplied alpha strings if " "the surface has per-pixel alpha") rmask, gmask, bmask, amask = (surf.format.Rmask, surf.format.Gmask, surf.format.Bmask, surf.format.Amask) rshift, gshift, bshift, ashift = (surf.format.Rshift, surf.format.Gshift, surf.format.Bshift, surf.format.Ashift) rloss, gloss, bloss, aloss = (surf.format.Rloss, surf.format.Gloss, surf.format.Bloss, surf.format.Aloss) bpp = surf.format.BytesPerPixel h, w = surf.h, surf.w if argb: ri, gi, bi, ai = 1, 2, 3, 0 else: ri, gi, bi, ai = 0, 1, 2, 3 data = ffi.new('char[]', w * h * 4) if bpp == 2: pixels = ffi.cast('uint16_t*', surf.pixels) for y in range(h): src_start = (h - 1 - y) * w if flipped \ else y * w for x in range(w): dest = 4 * (y * w + x) color = pixels[src_start + x] alpha = ((color & amask) >> ashift) << aloss data[dest + ri] = chr_( (((color & rmask) >> rshift) << rloss) * alpha // 255) data[dest + gi] = chr_( (((color & gmask) >> gshift) << gloss) * alpha // 255) data[dest + bi] = chr_( (((color & bmask) >> bshift) << bloss) * alpha // 255) data[dest + ai] = chr_(alpha) elif bpp == 3: pixels = ffi.cast('uint8_t*', surf.pixels) for y in range(h): src_start = (h - 1 - y) * surf.pitch if flipped \ else y * surf.pitch for x in range(w): dest = 4 * (y * w + x) color = (pixels[src_start + x * 3 + BYTE0] + (pixels[src_start + x * 3 + BYTE1] << 8) + (pixels[src_start + x * 3 + BYTE2] << 16)) alpha = ((color & amask) >> ashift) << aloss data[dest + ri] = chr_( (((color & rmask) >> rshift) << rloss) * alpha // 255) data[dest + gi] = chr_( (((color & gmask) >> gshift) << gloss) * alpha // 255) data[dest + bi] = chr_( (((color & bmask) >> bshift) << bloss) * alpha // 255) data[dest + ai] = chr_(alpha) elif bpp == 4: pixels = ffi.cast('uint32_t*', surf.pixels) for y in range(h): src_start = (h - 1 - y) * w if flipped \ else y * w for x in range(w): dest = 4 * (y * w + x) color = pixels[src_start + x] alpha = ((color & amask) >> ashift) << aloss if alpha == 0: data[dest + ri] = data[dest + gi] = data[dest + bi] \ = chr_(0) else: data[dest + ri] = chr_( (((color & rmask) >> rshift) << rloss) * alpha // 255) data[dest + gi] = chr_( (((color & gmask) >> gshift) << gloss) * alpha // 255) data[dest + bi] = chr_( (((color & bmask) >> bshift) << bloss) * alpha // 255) data[dest + ai] = chr_(alpha) else: raise ValueError("invalid color depth") return ffi.buffer(data)[:]
def _tostring_RGBA(surf, flipped, has_colorkey=True, argb=False): rmask, gmask, bmask, amask = (surf.format.Rmask, surf.format.Gmask, surf.format.Bmask, surf.format.Amask) rshift, gshift, bshift, ashift = (surf.format.Rshift, surf.format.Gshift, surf.format.Bshift, surf.format.Ashift) rloss, gloss, bloss, aloss = (surf.format.Rloss, surf.format.Gloss, surf.format.Bloss, surf.format.Aloss) bpp = surf.format.BytesPerPixel h, w = surf.h, surf.w colorkey = surf.format.colorkey if argb: has_colorkey = False ri, gi, bi, ai = 1, 2, 3, 0 else: has_colorkey = (has_colorkey and surf.flags & sdl.SDL_SRCCOLORKEY and not amask) ri, gi, bi, ai = 0, 1, 2, 3 data = ffi.new('char[]', w * h * 4) if bpp == 1: pixels = ffi.cast('uint8_t*', surf.pixels) colors = surf.format.palette.colors for y in range(h): src_start = (h - 1 - y) * w if flipped \ else y * w for x in range(w): dest = 4 * (y * w + x) color = pixels[src_start + x] data[dest + ri] = chr_(colors[color].r) data[dest + gi] = chr_(colors[color].g) data[dest + bi] = chr_(colors[color].b) if has_colorkey: data[dest + ai] = chr_( ffi.cast('char', color != colorkey) * 255) else: data[dest + ai] = chr_(255) elif bpp == 2: pixels = ffi.cast('uint16_t*', surf.pixels) for y in range(h): src_start = (h - 1 - y) * w if flipped \ else y * w for x in range(w): dest = 4 * (y * w + x) color = pixels[src_start + x] data[dest + ri] = chr_(((color & rmask) >> rshift) << rloss) data[dest + gi] = chr_(((color & gmask) >> gshift) << gloss) data[dest + bi] = chr_(((color & bmask) >> bshift) << bloss) if has_colorkey: data[dest + ai] = chr_( ffi.cast('char', color != colorkey) * 255) else: data[dest + ai] = chr_((( (color & amask) >> ashift) << aloss) if amask else 255) elif bpp == 3: pixels = ffi.cast('uint8_t*', surf.pixels) for y in range(h): src_start = (h - 1 - y) * surf.pitch if flipped \ else y * surf.pitch for x in range(w): dest = 4 * (y * w + x) color = (pixels[src_start + x * 3 + BYTE0] + (pixels[src_start + x * 3 + BYTE1] << 8) + (pixels[src_start + x * 3 + BYTE2] << 16)) data[dest + ri] = chr_(((color & rmask) >> rshift) << rloss) data[dest + gi] = chr_(((color & gmask) >> gshift) << gloss) data[dest + bi] = chr_(((color & bmask) >> bshift) << bloss) if has_colorkey: data[dest + ai] = chr_( ffi.cast('char', color != colorkey) * 255) else: data[dest + ai] = chr_((( (color & amask) >> ashift) << aloss) if amask else 255) elif bpp == 4: pixels = ffi.cast('uint32_t*', surf.pixels) for y in range(h): src_start = (h - 1 - y) * w if flipped \ else y * w for x in range(w): dest = 4 * (y * w + x) color = pixels[src_start + x] data[dest + ri] = chr_(((color & rmask) >> rshift) << rloss) data[dest + gi] = chr_(((color & gmask) >> gshift) << gloss) data[dest + bi] = chr_(((color & bmask) >> bshift) << bloss) if has_colorkey: data[dest + ai] = chr_( ffi.cast('char', color != colorkey) * 255) else: data[dest + ai] = chr_((( (color & amask) >> ashift) << aloss) if amask else 255) else: raise ValueError("invalid color depth") return ffi.buffer(data)[:]
def __init__(self, sdlevent, d=None, **kwargs): self._sdlevent = sdlevent if isinstance(sdlevent, int): # User specificed event with kwargs self.type = sdlevent # XXX: Pygame manipulates __dict__, we're currently don't # this causes a failure in test_Event if d: self._dict = d.copy() else: self._dict = {} if kwargs: self._dict.update(kwargs) for attr, value in self._dict.items(): setattr(self, attr, value) return if not sdlevent: self.type = sdl.SDL_NOEVENT return self.type = self._sdlevent.type if (sdlevent.user.code == int(_USEROBJECT_CHECK1) and sdlevent.user.data1 == _USEROBJECT_CHECK2): eventkey = ffi.cast("SDL_Event *", sdlevent.user.data2) if eventkey in _user_events: self._dict = _user_events[eventkey]._dict del _user_events[eventkey] for attr, value in self._dict.items(): setattr(self, attr, value) return raise NotImplementedError("TODO: Error handling for user-posted events.") if self.type == ACTIVEEVENT: self.gain = sdlevent.active.gain self.state = sdlevent.active.state elif self.type == KEYDOWN: self.unicode = sdlevent.key.keysym.unicode self.key = sdlevent.key.keysym.sym self.mod = sdlevent.key.keysym.mod self.scancode = sdlevent.key.keysym.scancode elif self.type == KEYUP: self.key = sdlevent.key.keysym.sym self.mod = sdlevent.key.keysym.mod self.scancode = sdlevent.key.keysym.scancode elif self.type == MOUSEMOTION: self.pos = (sdlevent.motion.x, sdlevent.motion.y) self.rel = (sdlevent.motion.xrel, sdlevent.motion.yrel) self.buttons = (_button_state(sdlevent.motion.state, 1), _button_state(sdlevent.motion.state, 2), _button_state(sdlevent.motion.state, 3)) elif self.type in (MOUSEBUTTONDOWN, MOUSEBUTTONUP): self.pos = (sdlevent.button.x, sdlevent.button.y) self.button = sdlevent.button.button elif self.type == JOYAXISMOTION: self.joy = sdlevent.jaxis.which self.axis = sdlevent.jaxis.axis self.value = sdlevent.jaxis.value / 32767.0 elif self.type == JOYBALLMOTION: self.joy = sdlevent.jball.which self.ball = sdlevent.jball.ball self.rel = (sdlevent.jball.xrel, sdlevent.jball.yrel) elif self.type == JOYHATMOTION: self.joy = sdlevent.jhat.which self.hat = sdlevent.jhat.hat hx = hy = 0 if sdlevent.jhat.value & sdl.SDL_HAT_UP: hy = 1 elif sdlevent.jhat.value & sdl.SDL_HAT_DOWN: hy = -1 if sdlevent.jhat.value & sdl.SDL_HAT_RIGHT: hx = 1 elif sdlevent.jhat.value & sdl.SDL_HAT_LEFT: hx = -1 self.value = (hx, hy) elif self.type in (JOYBUTTONUP, JOYBUTTONDOWN): self.joy = sdlevent.jbutton.which self.button = sdlevent.jbutton.button elif self.type == VIDEORESIZE: self.size = (sdlevent.resize.w, sdlevent.resize.h) self.w = sdlevent.resize.w self.h = sdlevent.resize.h elif self.type == SYSWMEVENT: raise NotImplementedError("SYSWMEVENT not properly supported yet.") elif self.type in (VIDEOEXPOSE, QUIT): pass # No attributes here. elif USEREVENT <= self.type < NUMEVENTS: self.code = sdlevent.user.code if self.type == USEREVENT and sdlevent.user.code == USEREVENT_DROPFILE: # mirrors what pygame does - not sure if correct self.filename = ffi.string(sdlevent.user.data1) sdl.free(sdlevent.user.data1) sdlevent.user.data1 = ffi.NULL
def __init__(self, sdlevent, d=None, **kwargs): self._sdlevent = sdlevent if isinstance(sdlevent, int): # User specificed event with kwargs self.type = sdlevent # XXX: Pygame manipulates __dict__, we're currently don't # this causes a failure in test_Event if d: self._dict = d.copy() else: self._dict = {} if kwargs: self._dict.update(kwargs) for attr, value in self._dict.items(): setattr(self, attr, value) return if not sdlevent: self.type = sdl.SDL_NOEVENT return self.type = self._sdlevent.type if (sdlevent.user.code == int(_USEROBJECT_CHECK1) and sdlevent.user.data1 == _USEROBJECT_CHECK2): eventkey = ffi.cast("SDL_Event *", sdlevent.user.data2) if eventkey in _user_events: self._dict = _user_events[eventkey]._dict del _user_events[eventkey] for attr, value in self._dict.items(): setattr(self, attr, value) return raise NotImplementedError("TODO: Error handling for user-posted events.") if self.type == ACTIVEEVENT: self.gain = sdlevent.active.gain self.state = sdlevent.active.state elif self.type == KEYDOWN: self.unicode = unichr_(sdlevent.key.keysym.unicode) self.key = sdlevent.key.keysym.sym self.mod = sdlevent.key.keysym.mod self.scancode = sdlevent.key.keysym.scancode elif self.type == KEYUP: self.key = sdlevent.key.keysym.sym self.mod = sdlevent.key.keysym.mod self.scancode = sdlevent.key.keysym.scancode elif self.type == MOUSEMOTION: self.pos = (sdlevent.motion.x, sdlevent.motion.y) self.rel = (sdlevent.motion.xrel, sdlevent.motion.yrel) self.buttons = (_button_state(sdlevent.motion.state, 1), _button_state(sdlevent.motion.state, 2), _button_state(sdlevent.motion.state, 3)) elif self.type in (MOUSEBUTTONDOWN, MOUSEBUTTONUP): self.pos = (sdlevent.button.x, sdlevent.button.y) self.button = sdlevent.button.button elif self.type == JOYAXISMOTION: self.joy = sdlevent.jaxis.which self.axis = sdlevent.jaxis.axis self.value = sdlevent.jaxis.value / 32767.0 elif self.type == JOYBALLMOTION: self.joy = sdlevent.jball.which self.ball = sdlevent.jball.ball self.rel = (sdlevent.jball.xrel, sdlevent.jball.yrel) elif self.type == JOYHATMOTION: self.joy = sdlevent.jhat.which self.hat = sdlevent.jhat.hat hx = hy = 0 if sdlevent.jhat.value & sdl.SDL_HAT_UP: hy = 1 elif sdlevent.jhat.value & sdl.SDL_HAT_DOWN: hy = -1 if sdlevent.jhat.value & sdl.SDL_HAT_RIGHT: hx = 1 elif sdlevent.jhat.value & sdl.SDL_HAT_LEFT: hx = -1 self.value = (hx, hy) elif self.type in (JOYBUTTONUP, JOYBUTTONDOWN): self.joy = sdlevent.jbutton.which self.button = sdlevent.jbutton.button elif self.type == VIDEORESIZE: self.size = (sdlevent.resize.w, sdlevent.resize.h) self.w = sdlevent.resize.w self.h = sdlevent.resize.h elif self.type == SYSWMEVENT: raise NotImplementedError("SYSWMEVENT not properly supported yet.") elif self.type in (VIDEOEXPOSE, QUIT): pass # No attributes here. elif USEREVENT <= self.type < NUMEVENTS: self.code = sdlevent.user.code if self.type == USEREVENT and sdlevent.user.code == USEREVENT_DROPFILE: # mirrors what pygame does - not sure if correct self.filename = ffi.string(sdlevent.user.data1) sdl.free(sdlevent.user.data1) sdlevent.user.data1 = ffi.NULL
def __init__(self, obj=None, **kwargs): check_mixer() self.chunk = None self._mem = None # nasty mangling of parameters! # if 1 position arg: could be filename, file or buffer # if 1 keyword arg: could be filename, file, buffer or array where # filename and file use the same keyword 'file' if obj is not None: if kwargs: raise TypeError("Sound takes either 1 positional or " "1 keyword argument") filename = None buff = None err = None if isinstance(obj, string_types): filename = obj if not isinstance(obj, unicode_): buff = obj elif isinstance(obj, bytes): # For python3, we need to try both paths filename = obj buff = obj elif isinstance(obj, IOBase): rwops = rwops_from_file(obj) self.chunk = sdl.Mix_LoadWAV_RW(rwops, 1) else: buff = obj if filename is not None: try: filename = rwops_encode_file_path(filename) rwops = rwops_from_file_path(filename) self.chunk = sdl.Mix_LoadWAV_RW(rwops, 1) except SDLError as e: err = e if not self.chunk and buff is not None: if isinstance(buff, unicode_): raise TypeError("Unicode object not allowed as " "buffer object") try: self._load_from_buffer(buff) except TypeError: # Pygame is special here, and falls through to a # different error if the object doesn't support # the buffer interface. pass else: if len(kwargs) != 1: raise TypeError("Sound takes either 1 positional or " "1 keyword argument") # Py3k Dictionary Views are iterables, not iterators arg_name, arg_value = next(iter(kwargs.items())) if arg_name == 'file': if isinstance(arg_value, string_types): filename = rwops_encode_file_path(arg_value) rwops = rwops_from_file_path(filename, 'rb') elif isinstance(arg_value, bytes): # Needed for python 3 filename = rwops_encode_file_path(arg_value) rwops = rwops_from_file_path(filename, 'rb') else: rwops = rwops_from_file(arg_value) self.chunk = sdl.Mix_LoadWAV_RW(rwops, 1) elif arg_name == 'buffer': if isinstance(arg_value, unicode_): raise TypeError("Unicode object not allowed as " "buffer object") self._load_from_buffer(arg_value) elif arg_name == 'array': raise NotImplementedError("Loading from array not " "implemented yet") else: raise TypeError("Unrecognized keyword argument '%s'" % arg_name) # pygame uses the pointer address as the tag to ensure # uniqueness, we use id for the same effect # Since we don't have the some automatic casting rules as # C, we explicitly cast to int here. This matches pygames # behaviour, so we're bug-compatible self._chunk_tag = ffi.cast("int", id(self.chunk)) if not self.chunk: if not err: raise TypeError("Unrecognized argument (type %s)" % type(obj).__name__) raise SDLError.from_sdl_error()
def _tostring_RGBA(surf, flipped, has_colorkey=True, argb=False): rmask, gmask, bmask, amask = (surf.format.Rmask, surf.format.Gmask, surf.format.Bmask, surf.format.Amask) rshift, gshift, bshift, ashift = (surf.format.Rshift, surf.format.Gshift, surf.format.Bshift, surf.format.Ashift) rloss, gloss, bloss, aloss = (surf.format.Rloss, surf.format.Gloss, surf.format.Bloss, surf.format.Aloss) bpp = surf.format.BytesPerPixel h, w = surf.h, surf.w colorkey = surf.format.colorkey if argb: has_colorkey = False ri, gi, bi, ai = 1, 2, 3, 0 else: has_colorkey = (has_colorkey and surf.flags & sdl.SDL_SRCCOLORKEY and not amask) ri, gi, bi, ai = 0, 1, 2, 3 data = ffi.new('char[]', w * h * 4) if bpp == 1: pixels = ffi.cast('uint8_t*', surf.pixels) colors = surf.format.palette.colors for y in range(h): src_start = (h - 1 - y) * w if flipped \ else y * w for x in range(w): dest = 4 * (y * w + x) color = pixels[src_start + x] data[dest + ri] = chr_(colors[color].r) data[dest + gi] = chr_(colors[color].g) data[dest + bi] = chr_(colors[color].b) if has_colorkey: data[dest + ai] = chr_( ffi.cast('char', color != colorkey) * 255) else: data[dest + ai] = chr_(255) elif bpp == 2: pixels = ffi.cast('uint16_t*', surf.pixels) for y in range(h): src_start = (h - 1 - y) * w if flipped \ else y * w for x in range(w): dest = 4 * (y * w + x) color = pixels[src_start + x] data[dest + ri] = chr_(((color & rmask) >> rshift) << rloss) data[dest + gi] = chr_(((color & gmask) >> gshift) << gloss) data[dest + bi] = chr_(((color & bmask) >> bshift) << bloss) if has_colorkey: data[dest + ai] = chr_( ffi.cast('char', color != colorkey) * 255) else: data[dest + ai] = chr_( (((color & amask) >> ashift) << aloss) if amask else 255) elif bpp == 3: pixels = ffi.cast('uint8_t*', surf.pixels) for y in range(h): src_start = (h - 1 - y) * surf.pitch if flipped \ else y * surf.pitch for x in range(w): dest = 4 * (y * w + x) color = (pixels[src_start + x * 3 + BYTE0] + (pixels[src_start + x * 3 + BYTE1] << 8) + (pixels[src_start + x * 3 + BYTE2] << 16)) data[dest + ri] = chr_(((color & rmask) >> rshift) << rloss) data[dest + gi] = chr_(((color & gmask) >> gshift) << gloss) data[dest + bi] = chr_(((color & bmask) >> bshift) << bloss) if has_colorkey: data[dest + ai] = chr_( ffi.cast('char', color != colorkey) * 255) else: data[dest + ai] = chr_( (((color & amask) >> ashift) << aloss) if amask else 255) elif bpp == 4: pixels = ffi.cast('uint32_t*', surf.pixels) for y in range(h): src_start = (h - 1 - y) * w if flipped \ else y * w for x in range(w): dest = 4 * (y * w + x) color = pixels[src_start + x] data[dest + ri] = chr_(((color & rmask) >> rshift) << rloss) data[dest + gi] = chr_(((color & gmask) >> gshift) << gloss) data[dest + bi] = chr_(((color & bmask) >> bshift) << bloss) if has_colorkey: data[dest + ai] = chr_( ffi.cast('char', color != colorkey) * 255) else: data[dest + ai] = chr_( (((color & amask) >> ashift) << aloss) if amask else 255) else: raise ValueError("invalid color depth") return ffi.buffer(data)[:]
def chop(surface, rect): """ chop(Surface, rect) -> Surface gets a copy of an image with an interior area removed """ rect = Rect(rect) width = rect.width height = rect.width x = rect.x y = rect.y if rect.right > surface._w: width = surface._w - rect.x if rect.height > surface._h: height = surface._h - rect.y if rect.x < 0: width -= -x x = 0 if rect.y < 0: height -= -y y = 0 c_surf = surface._c_surface new_surf = new_surface_from_surface(c_surf, surface._w, surface._h) bpp = c_surf.format.BytesPerPixel src_pitch = c_surf.pitch dest_pitch = new_surf.pitch w, h = c_surf.w, c_surf.h with locked(new_surf): with locked(c_surf): if bpp in (1, 2, 4): ptr_type = 'uint%s_t*' % c_surf.format.BitsPerPixel srcpixels = ffi.cast(ptr_type, c_surf.pixels) destpixels = ffi.cast(ptr_type, new_surf.pixels) else: srcpixels = ffi.cast('uint8_t*', c_surf.pixels) destpixels = ffi.cast('uint8_t*', new_surf.pixels) dy = 0 if bpp in (1, 2, 4): dest_step = dest_pitch // bpp src_step = src_pitch // bpp for sy in range(0, surface._h): if sy >= y and sy < y + height: continue dx = 0 if bpp in (1, 2, 4): dest_row_start = dy * dest_step src_row_start = sy * src_step else: dest_row_start = dy * dest_pitch src_row_start = sy * src_pitch for sx in range(0, surface._w): if sx >= x and sx < x + width: continue if bpp in (1, 2, 4): destpixels[dest_row_start + dx] = \ srcpixels[src_row_start + sx] else: dest_pix_start = dest_row_start + dx src_pix_start = src_row_start + sx destpixels[dest_pix_start:dest_pix_start + 3] = \ srcpixels[src_pix_start:src_pix_start + 3] dx += 1 dy += 1 return Surface._from_sdl_surface(new_surf)
def fromstring(string, size, format, flipped=False): w, h = size if w < 1 or h < 1: raise ValueError("Resolution must be positive values") if format == "P": if len(string) != w * h: raise ValueError("String length does not equal format and " "resolution size") surf = sdl.SDL_CreateRGBSurface(0, w, h, 8, 0, 0, 0, 0) if not surf: raise SDLError.from_sdl_error() with locked(surf): pixels = ffi.cast('char*', surf.pixels) for y in range(h): dest = surf.pitch * y src_start = (h - 1 - y) * w if flipped else y * w pixels[dest:dest + w] = string[src_start:src_start + w] elif format == "RGB": if len(string) != w * h * 3: raise ValueError("String length does not equal format and " "resolution size") surf = sdl.SDL_CreateRGBSurface(0, w, h, 24, 0xff, 0xff << 16, 0xff << 8, 0) if not surf: raise SDLError.from_sdl_error() with locked(surf): pixels = ffi.cast("char*", surf.pixels) for y in range(h): dest = surf.pitch * y src_start = (h - 1 - y) * w * 3 if flipped else y * w * 3 row = string[src_start:src_start + w * 3] for x in range(0, w * 3, 3): # BYTE0, BYTE1 and BYTE2 are determined by byte order pixels[dest + x + BYTE0] = row[x + BYTE0] pixels[dest + x + BYTE1] = row[x + BYTE1] pixels[dest + x + BYTE2] = row[x + BYTE2] elif format in ("RGBA", "RGBAX", "ARGB"): if len(string) != w * h * 4: raise ValueError("String length does not equal format and " "resolution size") if format == "ARGB": if get_sdl_byteorder() == sdl.SDL_LIL_ENDIAN: rmask, gmask, bmask, amask = (0xff << 8, 0xff << 16, 0xff << 24, 0xff) else: rmask, gmask, bmask, amask = (0xff << 16, 0xff << 8, 0xff, 0xff << 24) surf = sdl.SDL_CreateRGBSurface(sdl.SDL_SRCALPHA, w, h, 32, rmask, gmask, bmask, amask) else: alphamult = format == "RGBA" if get_sdl_byteorder() == sdl.SDL_LIL_ENDIAN: rmask, gmask, bmask = 0xff, 0xff << 8, 0xff << 16 amask = 0xff << 24 if alphamult else 0 else: rmask, gmask, bmask = 0xff << 24, 0xff << 16, 0xff << 8 amask = 0xff if alphamult else 0 surf = sdl.SDL_CreateRGBSurface(sdl.SDL_SRCALPHA if alphamult else 0, w, h, 32, rmask, gmask, bmask, amask) if not surf: raise SDLError.from_sdl_error() with locked(surf): pixels = ffi.cast("char*", surf.pixels) for y in range(h): dest = surf.pitch * y src_start = (h - 1 - y) * w * 4 if flipped else y * w * 4 pixels[dest:dest + w * 4] = string[src_start:src_start + w * 4] else: raise ValueError("Unrecognized type of format") return Surface._from_sdl_surface(surf)
def __init__(self, obj=None, **kwargs): check_mixer() self.chunk = None # nasty mangling of parameters! # if 1 position arg: could be filename, file or buffer # if 1 keyword arg: could be filename, file, buffer or array where # filename and file use the same keyword 'file' if obj is not None: if kwargs: raise TypeError("Sound takes either 1 positional or " "1 keyword argument") filename = None buff = None err = None if isinstance(obj, basestring): filename = obj if not isinstance(obj, unicode): buff = obj elif isinstance(obj, file): rwops = rwops_from_file(obj) self.chunk = sdl.Mix_LoadWAV_RW(rwops, 1) else: buff = obj if filename is not None: try: filename = rwops_encode_file_path(filename) rwops = rwops_from_file_path(filename) self.chunk = sdl.Mix_LoadWAV_RW(rwops, 1) except SDLError as e: err = e if not self.chunk and buff is not None: raise NotImplementedError("Loading from buffer not " "implemented yet") # TODO: check if buff implements buffer interface. # If it does, load from buffer. If not, re-raise # error from filename if filename is not None. else: if len(kwargs) != 1: raise TypeError("Sound takes either 1 positional or " "1 keyword argument") arg_name = kwargs.keys()[0] arg_value = kwargs[arg_name] if arg_name == 'file': if isinstance(arg_value, basestring): filename = rwops_encode_file_path(arg_value) rwops = rwops_from_file_path(filename, 'rb') else: rwops = rwops_from_file(arg_value) self.chunk = sdl.Mix_LoadWAV_RW(rwops, 1) elif arg_name == 'buffer': if isinstance(arg_name, unicode): raise TypeError("Unicode object not allowed as " "buffer object") raise NotImplementedError("Loading from buffer not " "implemented yet") elif arg_name == 'array': raise NotImplementedError("Loading from array not " "implemented yet") else: raise TypeError("Unrecognized keyword argument '%s'" % arg_name) # pygame uses the pointer address as the tag to ensure # uniqueness, we use id for the same effect # Since we don't have the some automatic casting rules as # C, we explicitly cast to int here. This matches pygames # behaviour, so we're bug-compatible self._chunk_tag = ffi.cast("int", id(self.chunk)) if not self.chunk: raise SDLError.from_sdl_error()