def _make_drawn_rect(points, surface): rect = surface.get_clip() left = max(rect.left, min(p[0] for p in points)) right = min(rect.right, max(p[0] for p in points)) top = max(rect.top, min(p[1] for p in points)) bottom = min(rect.bottom, max(p[1] for p in points)) return Rect(left, top, right - left + 1, bottom - top + 1)
def _make_drawn_rect(points, surface): rect = surface.get_clip() left = max(rect.left, min(p[0] for p in points)) right = min(rect.right, max(p[0] for p in points)) top = max(rect.top, min(p[1] for p in points)) bottom = min(rect.bottom, max(p[1] for p in points)) return Rect(left, top, max(right - left + 1, 0), max(bottom - top + 1, 0))
def _clip_and_draw_line(surface, c_color, start, end): # rect = surface.get_clip().inflate(-60, -60) # start, end = _clipline(rect, start, end) start, end = _clipline(surface.get_clip(), start, end) if start is None: return False _drawline(surface, c_color, start, end) return True
def DrawRoundRect(surface, color, rect, width, xr, yr): clip = surface.get_clip() surface.set_clip(clip.clip(rect.inflate(0, -yr*2))) pygame.draw.rect(surface, color, rect.inflate(1-width,0), width) surface.set_clip(clip.clip(rect.inflate(-xr*2, 0))) pygame.draw.rect(surface, color, rect.inflate(0,1-width), width) surface.set_clip(clip.clip(rect.left, rect.top, xr, yr)) pygame.draw.ellipse(surface, color, pygame.Rect(rect.left, rect.top, 2*xr, 2*yr), width) surface.set_clip(clip.clip(rect.right-xr, rect.top, xr, yr)) pygame.draw.ellipse(surface, color, pygame.Rect(rect.right-2*xr, rect.top, 2*xr, 2*yr), width) surface.set_clip(clip.clip(rect.left, rect.bottom-yr, xr, yr)) pygame.draw.ellipse(surface, color, pygame.Rect(rect.left, rect.bottom-2*yr, 2*xr, 2*yr), width) surface.set_clip(clip.clip(rect.right-xr, rect.bottom-yr, xr, yr)) pygame.draw.ellipse(surface, color, pygame.Rect(rect.right-2*xr, rect.bottom-2*yr, 2*xr, 2*yr), width) surface.set_clip(clip)
def _draw_fillpoly(surface, points, c_color): # Very traditional scanline fill approach # (also the approach used by pygame) ys = [p[1] for p in points] miny = min(ys) maxy = max(ys) times = [] # For speed reasons, we integrate clipping into the calculations, # rather than calling _clip_and_draw_line clip_rect = surface.get_clip() all_points = list(zip(points, points[-1:] + points[:-1])) for y in range(miny, maxy + 1): if y < clip_rect.top or y >= clip_rect.bottom: continue intercepts = [] for p1, p2 in all_points: if p1[1] == p2[1]: # Edge of the polygon, so skip (due to division by 0) continue elif p1[1] < p2[1]: x1, y1 = p1 x2, y2 = p2 else: x1, y1 = p2 x2, y2 = p1 if not (y1 <= y < y2) and not (y == maxy and y1 < y <= y2): continue # XXX: Here be dragons with very sharp teeth # C99 specifies truncates integer division towards zero always, # python integer division takes the floor, so they differ # on negatives numerator = (y - y1) * (x2 - x1) if numerator < 0: # N.B. order matters - force the postive division before # multiplication by -1 x = -1 * (-numerator // (y2 - y1)) + x1 else: x = numerator // (y2 - y1) + x1 # This works because we're drawing horizontal lines if x < clip_rect.left: x = clip_rect.left elif x >= clip_rect.right: x = clip_rect.right - 1 intercepts.append(x) intercepts.sort() for x1, x2 in zip(intercepts[::2], intercepts[1::2]): _drawhorizline(surface, c_color, x1, x2, y)
def _draw_fillpoly(surface, points, c_color): # Very traditional scanline fill approach # (also the approach used by pygame) ys = [p[1] for p in points] miny = min(ys) maxy = max(ys) times = [] # For speed reasons, we integrate clipping into the calculations, # rather than calling _clip_and_draw_line clip_rect = surface.get_clip() all_points = zip(points, points[-1:] + points[:-1]) for y in range(miny, maxy + 1): if y < clip_rect.top or y >= clip_rect.bottom: continue intercepts = [] for p1, p2 in all_points: if p1[1] == p2[1]: # Edge of the polygon, so skip (due to division by 0) continue elif p1[1] < p2[1]: x1, y1 = p1 x2, y2 = p2 else: x1, y1 = p2 x2, y2 = p1 if not (y1 <= y < y2) and not (y == maxy and y1 < y <= y2): continue # XXX: Here be dragons with very sharp teeth # C99 specifies truncates integer division towards zero always, # python integer division takes the floor, so they differ # on negatives numerator = (y - y1) * (x2 - x1) if numerator < 0: # N.B. order matters - force the postive division before # multiplication by -1 x = -1 * (-numerator / (y2 - y1)) + x1 else: x = numerator / (y2 - y1) + x1 # This works because we're drawing horizontal lines if x < clip_rect.left: x = clip_rect.left elif x >= clip_rect.right: x = clip_rect.right - 1 intercepts.append(x) intercepts.sort() for x1, x2 in zip(intercepts[::2], intercepts[1::2]): _drawhorizline(surface, c_color, x1, x2, y)
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 DrawRoundRect(surface, color, rect, width, xr, yr): clip = surface.get_clip() surface.set_clip(clip.clip(rect.inflate(0, -yr * 2))) pygame.draw.rect(surface, color, rect.inflate(1 - width, 0), width) surface.set_clip(clip.clip(rect.inflate(-xr * 2, 0))) pygame.draw.rect(surface, color, rect.inflate(0, 1 - width), width) surface.set_clip(clip.clip(rect.left, rect.top, xr, yr)) pygame.draw.ellipse(surface, color, pygame.Rect(rect.left, rect.top, 2 * xr, 2 * yr), width) surface.set_clip(clip.clip(rect.right - xr, rect.top, xr, yr)) pygame.draw.ellipse( surface, color, pygame.Rect(rect.right - 2 * xr, rect.top, 2 * xr, 2 * yr), width) surface.set_clip(clip.clip(rect.left, rect.bottom - yr, xr, yr)) pygame.draw.ellipse( surface, color, pygame.Rect(rect.left, rect.bottom - 2 * yr, 2 * xr, 2 * yr), width) surface.set_clip(clip.clip(rect.right - xr, rect.bottom - yr, xr, yr)) pygame.draw.ellipse( surface, color, pygame.Rect(rect.right - 2 * xr, rect.bottom - 2 * yr, 2 * xr, 2 * yr), width) surface.set_clip(clip)