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 _check_special_ellipse(surface, c_x, c_y, radius_x, radius_y, c_color): if radius_x == 0 and radius_y == 0: with locked(surface._c_surface): surface._set_at(c_x, c_y, c_color) return True elif radius_x == 0: # vertical line _drawvertline(surface, c_color, c_y - radius_y, c_y + radius_y, c_x) return True elif radius_y == 0: _drawhorizline(surface, c_color, c_x - radius_x, c_x + radius_x, c_y) return True return False
def polygon(surface, color, points, width=0): _check_surface(surface) if width != 0: return lines(surface, color, 1, points, width) c_color = create_color(color, surface._format) points = _check_and_filter_points(points, 3) with locked(surface._c_surface): _draw_fillpoly(surface, points, c_color) return _make_drawn_rect(points, surface)
def _check_special_ellipse(surface, c_x, c_y, radius_x, radius_y, c_color): if radius_x == 0 and radius_y == 0: clip = surface.get_clip() # Throw away points outside the clip area if c_x < clip.x or c_x > (clip.x + clip.w): return True if c_y < clip.y or c_y > (clip.y + clip.h): return True with locked(surface._c_surface): surface._set_at(c_x, c_y, c_color) return True elif radius_x == 0: # vertical line _drawvertline(surface, c_color, c_y - radius_y, c_y + radius_y, c_x) return True elif radius_y == 0: _drawhorizline(surface, c_color, c_x - radius_x, c_x + radius_x, c_y) return True return False
def _check_special_ellipse(surface, c_x, c_y, radius_x, radius_y, c_color): if radius_x == 0 and radius_y == 0: clip = surface.get_clip() # Throw away points outside the clip area if c_x < clip.x or c_x >= (clip.x + clip.w): return True if c_y < clip.y or c_y >= (clip.y + clip.h): return True with locked(surface._c_surface): surface._set_at(c_x, c_y, c_color) return True elif radius_x == 0: # vertical line _drawvertline(surface, c_color, c_y - radius_y, c_y + radius_y, c_x) return True elif radius_y == 0: _drawhorizline(surface, c_color, c_x - radius_x, c_x + radius_x, c_y) return True return False
def line(surface, color, start, end, width=1): _check_surface(surface) c_color = create_color(color, surface._format) _check_point(start, "Invalid start position argument") _check_point(end, "Invalid end position argument") [start] = _check_and_filter_points([start]) [end] = _check_and_filter_points([end]) if width < 1: return Rect(start, (0, 0)) with locked(surface._c_surface): drawn = _clip_and_draw_line_width(surface, c_color, width, start, end) if drawn is None: return Rect(start, (0, 0)) return drawn
def lines(surface, color, closed, points, width=1): _check_surface(surface) c_color = create_color(color, surface._format) points = _check_and_filter_points(points, 2) drawn_points = set() with locked(surface._c_surface): start_point = points[0] for point in points[1:]: drawn = _clip_and_draw_line_width(surface, c_color, width, start_point, point) if drawn is not None: drawn_points.add(drawn.topleft) drawn_points.add(drawn.bottomright) start_point = point if closed and len(points) > 2: _clip_and_draw_line_width(surface, c_color, width, points[0], points[-1]) return _make_drawn_rect(drawn_points, surface)
def lines(surface, color, closed, points, width=1): _check_surface(surface) c_color = create_color(color, surface._format) points = _check_and_filter_points(points, 2) drawn_points = set() with locked(surface._c_surface): start_point = points[0] for point in points[1:]: drawn = _clip_and_draw_line_width( surface, c_color, width, start_point, point) if drawn is not None: drawn_points.add(drawn.topleft) drawn_points.add(drawn.bottomright) start_point = point if closed and len(points) > 2: _clip_and_draw_line_width( surface, c_color, width, points[0], points[-1]) return _make_drawn_rect(drawn_points, surface)
def _fillellipse(surface, pos, radius_x, radius_y, color): """Internal helper function draw a filled ellipse on surface.""" c_surf = surface._c_surface c_x, c_y = pos c_color = create_color(color, surface._format) if _check_special_ellipse(surface, c_x, c_y, radius_x, radius_y, c_color): return # Draw the filled ellipse # We inherit this structure from pygame # We draw by drawing horizontal lines between points, while _ellipse # is orientated towards creating vertical pairs. # There are also some annoying other differences between how # the filled ellipse and hollow ellipse are constructed that makes it # hard to do both in a single function # Why, pygame, why? stop_h = stop_i = stop_j = stop_k = -1 with locked(c_surf): i = 1 h = 0 if radius_x > radius_y: ix = 0 iy = radius_x * 64 while i > h: h = (ix + 8) // 64 i = (iy + 8) // 64 j = (h * radius_y) // radius_x k = (i * radius_y) // radius_x if stop_k != k and stop_j != k and k < radius_y: _drawhorizline(surface, c_color, c_x - h, c_x + h - 1, c_y - k - 1) _drawhorizline(surface, c_color, c_x - h, c_x + h - 1, c_y + k) stop_k = k if stop_j != j and stop_k != j and k != j: _drawhorizline(surface, c_color, c_x - i, c_x + i - 1, c_y - j - 1) _drawhorizline(surface, c_color, c_x - i, c_x + i - 1, c_y + j) stop_j = j ix = ix + _c_div(iy, radius_x) iy = iy - _c_div(ix, radius_x) else: ix = 0 iy = radius_y * 64 while i > h: h = (ix + 8) // 64 i = (iy + 8) // 64 j = (h * radius_x) // radius_y k = (i * radius_x) // radius_y if stop_i != i and stop_h != i and i < radius_y: _drawhorizline(surface, c_color, c_x - j, c_x + j - 1, c_y - i - 1) _drawhorizline(surface, c_color, c_x - j, c_x + j - 1, c_y + i) stop_i = i if stop_h != h and stop_i != h and i != h: _drawhorizline(surface, c_color, c_x - k, c_x + k - 1, c_y - h - 1) _drawhorizline(surface, c_color, c_x - k, c_x + k - 1, c_y + h) stop_h = h ix = ix + _c_div(iy, radius_y) iy = iy - _c_div(ix, radius_y)
def _ellipse(surface, pos, radius_x, radius_y, color): """Internal helper function draw a ellipse with line thickness 1 on surface.""" c_surf = surface._c_surface c_x, c_y = pos c_color = create_color(color, surface._format) if _check_special_ellipse(surface, c_x, c_y, radius_x, radius_y, c_color): return # Draw the ellipse # Pygame's ellipse drawing algorithm appears to come from allegro, via sge # and SDL_gfxPrimitives. It's known to be non-optimal, but we're aiming # for pygame compatibility, so we're doing the same thing, much as # it grates me to do so. # We assume suitable diligence in terms of the licensing, but allegro's # zlib'ish license should mean we're OK anyway. stop_h = stop_i = stop_j = stop_k = -1 bounds = surface.get_bounding_rect() with locked(c_surf): i = 1 h = 0 if radius_x > radius_y: ix = 0 iy = radius_x * 64 while i > h: h = (ix + 16) // 64 i = (iy + 16) // 64 j = (h * radius_y) // radius_x k = (i * radius_y) // radius_x if (stop_k != k and stop_j != k) or (stop_j != j and stop_k != k) or (k != j): plus_x = c_x + h - 1 minus_x = c_x - h if k > 0: plus_y = c_y + k - 1 minus_y = c_y - k if h > 0: if bounds.collidepoint(minus_x, plus_y): surface._set_at(minus_x, plus_y, c_color) if bounds.collidepoint(minus_x, minus_y): surface._set_at(minus_x, minus_y, c_color) if bounds.collidepoint(plus_x, plus_y): surface._set_at(plus_x, plus_y, c_color) if bounds.collidepoint(plus_x, minus_y): surface._set_at(plus_x, minus_y, c_color) stop_k = k plus_x = c_x + i - 1 minus_x = c_x - i if j > 0: plus_y = c_y + j - 1 minus_y = c_y - j if bounds.collidepoint(plus_x, plus_y): surface._set_at(plus_x, plus_y, c_color) if bounds.collidepoint(plus_x, minus_y): surface._set_at(plus_x, minus_y, c_color) if bounds.collidepoint(minus_x, plus_y): surface._set_at(minus_x, plus_y, c_color) if bounds.collidepoint(minus_x, minus_y): surface._set_at(minus_x, minus_y, c_color) stop_j = j ix = ix + _c_div(iy, radius_x) iy = iy - _c_div(ix, radius_x) else: ix = 0 iy = radius_y * 64 while i > h: h = (ix + 32) // 64 i = (iy + 32) // 64 j = (h * radius_x) // radius_y k = (i * radius_x) // radius_y if (stop_i != i and stop_h != i) or (stop_i != h and stop_h != h) or (h != i): plus_x = c_x + j - 1 minus_x = c_x - j if i > 0: plus_y = c_y + i - 1 minus_y = c_y - i if j > 0: if bounds.collidepoint(minus_x, plus_y): surface._set_at(minus_x, plus_y, c_color) if bounds.collidepoint(minus_x, minus_y): surface._set_at(minus_x, minus_y, c_color) if bounds.collidepoint(plus_x, plus_y): surface._set_at(plus_x, plus_y, c_color) if bounds.collidepoint(plus_x, minus_y): surface._set_at(plus_x, minus_y, c_color) stop_i = i plus_x = c_x + k - 1 minus_x = c_x - k if h > 0: plus_y = c_y + h - 1 minus_y = c_y - h if bounds.collidepoint(plus_x, plus_y): surface._set_at(plus_x, plus_y, c_color) if bounds.collidepoint(plus_x, minus_y): surface._set_at(plus_x, minus_y, c_color) if bounds.collidepoint(minus_x, plus_y): surface._set_at(minus_x, plus_y, c_color) if bounds.collidepoint(minus_x, minus_y): surface._set_at(minus_x, minus_y, c_color) stop_h = h ix = ix + _c_div(iy, radius_y) iy = iy - _c_div(ix, radius_y)
raise IOError("PNGError: %s" % ffi.string(err_msg[0])) 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):
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 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)