def from_threshold(surf, color, threshold=(0, 0, 0, 255), othersurface=None, palette_colors=1): """from_threshold(surf, color, threshold = (0,0,0,255), othersurface = None, palette_colors = 1) -> Mask Creates a mask by thresholding Surfaces""" c_surf = surf._c_surface color = create_color(color, surf._c_surface.format) if threshold: threshold = create_color(threshold, c_surf.format) output_mask = Mask((surf._w, surf._h)) with locked(c_surf): if othersurface: surf2 = othersurface._c_surface with locked(surf2): sdl.bitmask_threshold(output_mask._mask, c_surf, surf2, color, threshold, palette_colors) else: sdl.bitmask_threshold(output_mask._mask, c_surf, ffi.NULL, color, threshold, palette_colors) return output_mask
def fill(self, color, rect=None, special_flags=0): """ fill(color, rect=None, special_flags=0) -> Rect fill Surface with a solid color """ self.check_opengl() c_color = create_color(color, self._format) sdlrect = ffi.new('SDL_Rect*') if rect is not None: sdlrect.x, sdlrect.y, sdlrect.w, sdlrect.h = rect_vals_from_obj( rect) else: sdlrect.w = self._w sdlrect.h = self._h if self.crop_to_surface(sdlrect): if special_flags: res = sdl.surface_fill_blend(self._c_surface, sdlrect, c_color, special_flags) else: with locked(self._c_surface): # TODO: prep/unprep res = sdl.SDL_FillRect(self._c_surface, sdlrect, c_color) if res == -1: raise SDLError.from_sdl_error() return Rect._from4(sdlrect.x, sdlrect.y, sdlrect.w, sdlrect.h)
def fill(self, color, rect=None, special_flags=0): """ fill(color, rect=None, special_flags=0) -> Rect fill Surface with a solid color """ self.check_opengl() c_color = create_color(color, self._format) sdlrect = ffi.new('SDL_Rect*') if rect is not None: sdlrect.x, sdlrect.y, sdlrect.w, sdlrect.h = rect_vals_from_obj(rect) else: sdlrect.w = self._w sdlrect.h = self._h if self.crop_to_surface(sdlrect): if special_flags: res = sdl.surface_fill_blend(self._c_surface, sdlrect, c_color, special_flags) else: with locked(self._c_surface): # TODO: prep/unprep res = sdl.SDL_FillRect(self._c_surface, sdlrect, c_color) if res == -1: raise SDLError.from_sdl_error() return Rect._from4(sdlrect.x, sdlrect.y, sdlrect.w, sdlrect.h)
def set_at(self, pos, color): self.check_opengl() x, y = pos if x < 0 or y < 0 or x >= self._w or y >= self._h: raise IndexError("index out of bounds") c_color = create_color(color, self._format) with locked(self._c_surface): self._set_at(x, y, c_color)
def set_colorkey(self, color=None, flags=0): self.check_opengl() c_color = 0 if color is not None: c_color = create_color(color, self._format) flags |= sdl.SDL_SRCCOLORKEY with locked(self._c_surface): if sdl.SDL_SetColorKey(self._c_surface, flags, c_color) == -1: raise SDLError.from_sdl_error()
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 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)