Lightningbeam/PyGUI-2.5.3/GUI/Win32/Canvas.py

337 lines
9.8 KiB
Python

#--------------------------------------------------------------------
#
# PyGUI - Canvas - Win32
#
#--------------------------------------------------------------------
from math import sin, cos, pi
import win32con as wc, win32ui as ui, win32gui as gui
from win32con import PS_SOLID, BS_SOLID, RGN_AND
#from win32ui import CreatePen, CreateBrush
#from win32gui import CloseFigure, PathToRegion, AngleArc
from GUI import export
import GUI.GDIPlus as gdip
from GUI.StdColors import black, white
from GUI.StdFonts import application_font
from GUI.WinUtils import win_null_brush
from GUI.GCanvases import Canvas as GCanvas
deg = pi / 180
def ir(x, i = int, r = round):
return i(r(x))
def irr(rect, ir = ir):
l, t, r, b = rect
return (ir(l), ir(t), ir(r), ir(b))
#--------------------------------------------------------------------
class GState(object):
pencolor = black
fillcolor = black
textcolor = black
backcolor = white
pensize = 1
font = application_font
win_pen = gdip.Pen(pencolor._win_argb, 1)
win_fill_brush = gdip.SolidBrush(fillcolor._win_argb)
win_text_brush = gdip.SolidBrush(textcolor._win_argb)
win_bg_brush = gdip.SolidBrush(backcolor._win_argb)
def __init__(self, clone = None):
if clone:
self.__dict__.update(clone.__dict__)
#--------------------------------------------------------------------
class Canvas(GCanvas):
_current_point = None
# def __init__(self, win_graphics, dc = None):
# if not dc:
# print "Canvas.__init__: before get dc: clip bounds =", win_graphics.GetClipBounds() ###
# dc = ui.CreateDCFromHandle(win_graphics.GetHDC())
# print "Canvas.__init__: after get dc: clip bounds =", win_graphics.GetClipBounds() ###
# dc.SetBkMode(wc.TRANSPARENT)
# dc.SetTextAlign(wc.TA_LEFT | wc.TA_BASELINE | wc.TA_UPDATECP)
# print "Canvas.__init__: clip bounds =", win_graphics.GetClipBounds() ###
# self._win_graphics = win_graphics
# self._win_dc = dc
# self._win_hdc = dc.GetHandleOutput()
# self._win_path = gdip.GraphicsPath()
# self._state = GState()
# self._stack = []
def __init__(self, win_graphics, for_printing = False):
self._win_graphics = win_graphics
self._win_path = gdip.GraphicsPath()
self._state = GState()
self._stack = []
if for_printing:
unit = gdip.UnitPoint
win_graphics.SetPageUnit(unit)
#else:
# unit = gdip.UnitPixel
# dpix = win_graphics.GetDpiX()
# dpiy = win_graphics.GetDpiY()
# print "Canvas: dpi =", dpix, dpiy ###
# win_graphics.SetPageUnit(gdip.UnitPoint)
# if not for_printing:
# sx = 72.0 / dpix
# sy = 72.0 / dpiy
# self.scale(sx, sy)
def _from_win_dc(cls, dc):
return cls._from_win_hdc(dc.GetSafeHdc())
_from_win_dc = classmethod(_from_win_dc)
def _from_win_hdc(cls, hdc, **kwds):
win_graphics = gdip.Graphics.from_hdc(hdc)
return cls(win_graphics, **kwds)
_from_win_hdc = classmethod(_from_win_hdc)
def _from_win_image(cls, win_image):
win_graphics = gdip.Graphics.from_image(win_image)
#print "Canvas._from_win_image: win_graphics =", win_graphics ###
#print "... clip bounds =", win_graphics.GetClipBounds() ###
return cls(win_graphics)
_from_win_image = classmethod(_from_win_image)
def get_pencolor(self):
return self._state.pencolor
def set_pencolor(self, c):
state = self._state
state.pencolor = c
state.win_pen = gdip.Pen(c._win_argb, state.pensize)
def get_fillcolor(self):
return self._state.fillcolor
def set_fillcolor(self, c):
state = self._state
state.fillcolor = c
state.win_fill_brush = gdip.SolidBrush(c._win_argb)
def get_textcolor(self):
return self._state.textcolor
def set_textcolor(self, c):
state = self._state
state.textcolor = c
state.win_text_brush = gdip.SolidBrush(c._win_argb)
def get_backcolor(self):
return self._state.backcolor
def set_backcolor(self, c):
state = self._state
state.backcolor = c
state.win_bg_brush = gdip.SolidBrush(c._win_argb)
def get_pensize(self):
return self._state.pensize
def set_pensize(self, x):
state = self._state
state.pensize = x
state.win_pen = gdip.Pen(state.pencolor._win_argb, x)
def get_current_point(self):
return self._current_point
def get_font(self):
return self._state.font
def set_font(self, f):
self._state.font = f
def newpath(self):
self._win_path.Reset()
def moveto(self, x, y):
p = (x, y)
self._current_point = p
self._win_path.StartFigure()
def lineto(self, x, y):
x0, y0 = self._current_point
self._win_path.AddLine_4f(x0, y0, x, y)
self._current_point = (x, y)
def curveto(self, p1, p2, p3):
p0 = self._current_point
self._win_path.AddBezier_4p(p0, p1, p2, p3)
self._current_point = p3
def arc(self, c, r, a0, a1):
g = self._win_path
g.AddArc_p3f(c, r, a0, a1)
self._current_point = g.GetLastPoint()
def closepath(self):
self._win_path.CloseFigure()
self._current_point = None
def fill(self):
self._win_graphics.FillPath(self._state.win_fill_brush, self._win_path)
def stroke(self):
self._win_graphics.DrawPath(self._state.win_pen, self._win_path)
def erase(self):
g = self._win_graphics
g.SetSourceCopyMode()
g.FillPath(self._state.win_bg_brush, self._win_path)
g.SetSourceOverMode()
def show_text(self, text):
font = self._state.font
gf = font._win_gdip_font
x, y = self._current_point
brush = self._state.win_text_brush
g = self._win_graphics
w = g.DrawAndMeasureStringWidth_2f(text, gf, x, y, brush)
self._current_point = x + w, y
##
## GDI+ screws up some fonts (e.g. Times) for some reason.
## Using plain GDI to draw text for now.
##
# def show_text(self, text):
# state = self._state
# x, y = self._current_point
# dc = self._win_dc
# dc.SelectObject(state.font._win_font)
# dc.SetTextColor(state.textcolor._win_color)
# dc.MoveTo(ir(x), ir(y))
# dc.TextOut(20, 20, text)
# self._current_point = dc.GetCurrentPosition()
def clip(self):
self._win_graphics.SetClip_PI(self._win_path)
def rectclip(self, rect):
self._win_graphics.SetClip_rI(rect)
def gsave(self):
old_state = self._state
old_state.win_state = self._win_graphics.Save()
self._stack.append(old_state)
self._state = GState(old_state)
def grestore(self):
old_state = self._stack.pop()
self._win_graphics.Restore(old_state.win_state)
self._state = old_state
# Rectangles
def rect(self, rect):
self._win_path.AddRectangle_r(rect)
self._current_point = None
def fill_rect(self, rect):
self._win_graphics.FillRectangle_r(self._state.win_fill_brush, rect)
def stroke_rect(self, rect):
self._win_graphics.DrawRectangle_r(self._state.win_pen, rect)
def erase_rect(self, rect):
self._win_graphics.FillRectangle_r(self._state.win_bg_brush, rect)
# Ovals
def oval(self, rect):
self._win_path.AddEllipse_r(rect)
self._current_point = None
def fill_oval(self, rect):
self._win_graphics.FillEllipse_r(self._state.win_fill_brush, rect)
def stroke_oval(self, rect):
self._win_graphics.DrawEllipse_r(self._state.win_pen, rect)
def erase_oval(self, rect):
self._win_graphics.FillEllipse_r(self._state.win_bg_brush, rect)
# Arcs
def stroke_arc(self, c, r, a0, a1):
self._win_graphics.DrawArc_3pf(self._state.win_pen, c, r, a0, a1)
# Wedges
def wedge(self, c, r, a0, a1):
self._win_path.AddPie_p3f(c, r, a0, a1)
self._current_point = None
def stroke_wedge(self, c, r, a0, a1):
self._win_graphics.DrawPie_p3f(self._state.win_pen, c, r, a0, a1)
def fill_wedge(self, c, r, a0, a1):
self._win_graphics.FillPie_p3f(self._state.win_fill_brush, c, r, a0, a1)
def erase_wedge(self, c, r, a0, a1):
self._win_graphics.FillPie_p3f(self._state.win_bg_brush, c, r, a0, a1)
# Polylines
def lines(self, points):
self._win_path.AddLines_pv(points)
self._current_point = points[-1]
def linesto(self, points):
self.lines([self._current_point] + points)
def stroke_lines(self, points):
self._win_graphics.DrawLines_pv(self._state.win_pen, points)
# Polygons
def poly(self, points):
self._win_path.AddPolygon_pv(points)
self._current_point = None
def stroke_poly(self, points):
self._win_graphics.DrawPolygon_pv(self._state.win_pen, points)
def fill_poly(self, points):
self._win_graphics.FillPolygon_pv(self._state.win_fill_brush, points)
def erase_poly(self, points):
self._win_graphics.FillPolygon_pv(self._state.win_bg_brush, points)
# Polycurves
def curves(self, points):
self._win_path.AddBeziers_pv(points)
self._current_point = points[-1]
def curvesto(self, points):
self.curves([self._current_point] + points)
def stroke_curves(self, points):
self._win_graphics.DrawBeziers_pv(self._state.win_pen, points)
# Transformations
def translate(self, dx, dy):
self._win_graphics.Translate_2f(dx, dy)
def scale(self, sx, sy):
self._win_graphics.Scale_2f(sx, sy)
def rotate(self, rotation):
self._win_graphics.Rotate_1f(rotation)
export(Canvas)