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

495 lines
15 KiB
Python

#--------------------------------------------------------------------
#
# PyGUI - Win32 - GDI Plus
#
#--------------------------------------------------------------------
from ctypes import *
from ctypes.wintypes import BOOL
try:
from numpy import ndarray, float32
except ImportError:
class ndarray(object):
pass
#wg = windll.gdiplus
wg = oledll.gdiplus
#--------------------------------------------------------------------
# enum Unit
UnitWorld = 0
UnitDisplay = 1
UnitPixel = 2
UnitPoint = 3
# enum FillMode
FillModeAlternate = 0
# enum CombineMode
CombineModeIntersect = 1
# enum MatrixOrder
MatrixOrderPrepend = 0
MatrixOrderAppend = 1
# Pixel Formats
# In-memory pixel data formats:
# bits 0-7 = format index
# bits 8-15 = pixel size (in bits)
# bits 16-23 = flags
# bits 24-31 = reserved
PixelFormatIndexed = 0x00010000 # Indexes into a palette
PixelFormatGDI = 0x00020000 # Is a GDI-supported format
PixelFormatAlpha = 0x00040000 # Has an alpha component
PixelFormatPAlpha = 0x00080000 # Pre-multiplied alpha
PixelFormatExtended = 0x00100000 # Extended color 16 bits/channel
PixelFormatCanonical = 0x00200000
PixelFormat1bppIndexed = (1 | ( 1 << 8) | PixelFormatIndexed | PixelFormatGDI)
PixelFormat4bppIndexed = (2 | ( 4 << 8) | PixelFormatIndexed | PixelFormatGDI)
PixelFormat8bppIndexed = (3 | ( 8 << 8) | PixelFormatIndexed | PixelFormatGDI)
PixelFormat16bppGrayScale = (4 | (16 << 8) | PixelFormatExtended)
PixelFormat16bppRGB555 = (5 | (16 << 8) | PixelFormatGDI)
PixelFormat16bppRGB565 = (6 | (16 << 8) | PixelFormatGDI)
PixelFormat16bppARGB1555 = (7 | (16 << 8) | PixelFormatAlpha | PixelFormatGDI)
PixelFormat24bppRGB = (8 | (24 << 8) | PixelFormatGDI)
PixelFormat32bppRGB = (9 | (32 << 8) | PixelFormatGDI)
PixelFormat32bppARGB = (10 | (32 << 8) | PixelFormatAlpha | PixelFormatGDI | PixelFormatCanonical)
PixelFormat32bppPARGB = (11 | (32 << 8) | PixelFormatAlpha | PixelFormatPAlpha | PixelFormatGDI)
PixelFormat48bppRGB = (12 | (48 << 8) | PixelFormatExtended)
PixelFormat64bppARGB = (13 | (64 << 8) | PixelFormatAlpha | PixelFormatCanonical | PixelFormatExtended)
PixelFormat64bppPARGB = (14 | (64 << 8) | PixelFormatAlpha | PixelFormatPAlpha | PixelFormatExtended)
# enum FontStyle
FontStyleBold = 1
FontStyleItalic = 2
FontStyleUnderline = 4
FontStyleStrikeout = 8
class PointF(Structure):
_fields_ = [("x", c_float), ("y", c_float)]
class RectF(Structure):
_fields_ = [
("x", c_float), ("y", c_float),
("width", c_float), ("height", c_float)]
#--------------------------------------------------------------------
def rect_args(rect):
l, t, r, b = rect
return c_float(l), c_float(t), c_float(r - l), c_float(b - t)
def points_args(points):
if isinstance(points, ndarray) and points.flags['C_CONTIGUOUS'] and points.dtype == float32:
#print "GDIPlus.points_args: using ndarray" ###
n = points.size // 2
buf = points.ctypes.data
else:
n = len(points)
buf = (PointF * n)()
for i, p in enumerate(points):
buf[i].x, buf[i].y = p
return buf, n
def arc_args(c, r, a0, a1):
x, y = c
d = c_float(2 * r)
return c_float(x - r), c_float(y - r), d, d, \
c_float(a0), c_float((a1 - a0) % 360.0)
#--------------------------------------------------------------------
class GdiplusStartupInput(Structure):
_fields_ = [
('GdiplusVersion', c_uint),
('DebugEventCallback', c_void_p),
('SuppressBackgroundThread', BOOL),
('SuppressExternalCodecs', BOOL),
]
def __init__(self):
Structure.__init__(self)
self.GdiplusVersion = 1
self.DebugEventCallback = None
self.SuppressBackgroundThread = 0
self.SuppressExternalCodecs = 0
StartupInput = GdiplusStartupInput()
token = c_ulong()
wg.GdiplusStartup(pointer(token), pointer(StartupInput), None)
#--------------------------------------------------------------------
class Pen(object):
def __init__(self, argb, size):
ptr = c_void_p()
wg.GdipCreatePen1(argb, c_float(size), UnitWorld, byref(ptr))
self.ptr = ptr
def __del__(self, wg = wg):
wg.GdipDeletePen(self.ptr)
#--------------------------------------------------------------------
class SolidBrush(object):
def __init__(self, argb):
ptr = c_void_p()
wg.GdipCreateSolidFill(argb, byref(ptr))
self.ptr = ptr
def __del__(self, wg = wg):
wg.GdipDeleteBrush(self.ptr)
def __str__(self):
argb = c_ulong()
wg.GdipGetSolidFillColor(self.ptr, byref(argb))
return "<SolidBrush argb=0x%08x>" % argb.value
#--------------------------------------------------------------------
class Font(object):
def __init__(self, family, size, style):
uname = create_unicode_buffer(family)
fam = c_void_p()
wg.GdipCreateFontFamilyFromName(uname, None, byref(fam))
flags = 0
if 'bold' in style:
flags |= FontStyleBold
if 'italic' in style:
flags |= FontStyleItalic
ptr = c_void_p()
wg.GdipCreateFont(fam, c_float(size), flags, UnitWorld, byref(ptr))
self.ptr = ptr
wg.GdipDeleteFontFamily(fam)
def from_hdc(cls, hdc):
self = cls.__new__(cls)
ptr = c_void_p()
wg.GdipCreateFontFromDC(hdc, byref(ptr))
self.ptr = ptr
return self
from_hdc = classmethod(from_hdc)
def __del__(self, wg = wg):
wg.GdipDeleteFont(self.ptr)
#--------------------------------------------------------------------
class Image(object):
def __str__(self):
return "<Image 0x%x>" % self.ptr.value
def from_file(cls, path):
self = cls.__new__(cls)
ptr = c_void_p()
upath = create_unicode_buffer(path)
self._create_from_file(upath, ptr)
self.ptr = ptr
return self
from_file = classmethod(from_file)
def _create_from_file(self, upath, ptr):
wg.GdipLoadImageFromFile(upath, byref(ptr))
def __del__(self, wg = wg):
wg.GdipDisposeImage(self.ptr)
def GetWidth(self):
uint = c_uint()
wg.GdipGetImageWidth(self.ptr, byref(uint))
return uint.value
def GetHeight(self):
uint = c_uint()
wg.GdipGetImageHeight(self.ptr, byref(uint))
return uint.value
#--------------------------------------------------------------------
class Bitmap(Image):
def __init__(self, width, height):
ptr = c_void_p()
format = PixelFormat32bppARGB
wg.GdipCreateBitmapFromScan0(width, height, 0, format, None, byref(ptr))
self.ptr = ptr
#print "GDIPlus.Bitmap:", (width, height), repr(self), "ptr =", self.ptr ###
def _create_from_file(self, upath, ptr):
wg.GdipCreateBitmapFromFile(upath, byref(ptr))
def from_data(cls, width, height, format, data):
self = cls.__new__(cls)
ptr = c_void_p()
bits_per_pixel = (format >> 8) & 0xff
row_stride = (width * bits_per_pixel) >> 3
wg.GdipCreateBitmapFromScan0(width, height, row_stride, format, data, byref(ptr))
self.ptr = ptr
return self
from_data = classmethod(from_data)
def __str__(self):
return "<Bitmap 0x%x>" % self.ptr.value
def GetHICON(self):
hicon = c_ulong()
wg.GdipCreateHICONFromBitmap(self.ptr, byref(hicon))
return hicon.value
def GetPixel(self, x, y):
c = c_ulong()
wg.GdipBitmapGetPixel(self.ptr, x, y, byref(c))
return c.value
def SetPixel(self, x, y, c):
wg.GdipBitmapSetPixel(self.ptr, x, y, c)
#--------------------------------------------------------------------
class GraphicsPath(object):
def __init__(self):
ptr = c_void_p()
wg.GdipCreatePath(FillModeAlternate, byref(ptr))
self.ptr = ptr
def __del__(self, wg = wg):
wg.GdipDeletePath(self.ptr)
def Reset(self):
wg.GdipResetPath(self.ptr)
def StartFigure(self):
wg.GdipStartPathFigure(self.ptr)
def AddLine_4f(self, x0, y0, x1, y1):
wg.GdipAddPathLine(self.ptr,
c_float(x0), c_float(y0), c_float(x1), c_float(y1))
def AddBezier_4p(self, p0, p1, p2, p3):
x0, y0 = p0
x1, y1 = p1
x2, y2 = p2
x3, y3 = p3
wg.GdipAddPathBezier(self.ptr,
c_float(x0), c_float(y0), c_float(x1), c_float(y1),
c_float(x2), c_float(y2), c_float(x3), c_float(y3))
def AddBeziers_pv(self, points):
wg.GdipAddPathBeziers(self.ptr, *points_args(points))
def AddRectangle_r(self, rect):
wg.GdipAddPathRectangle(self.ptr, *rect_args(rect))
def AddEllipse_r(self, rect):
wg.GdipAddPathEllipse(self.ptr, *rect_args(rect))
def AddArc_p3f(self, c, r, a0, a1):
wg.GdipAddPathArc(self.ptr, *arc_args(c, r, a0, a1))
def AddPie_p3f(self, c, r, a0, a1):
wg.GdipAddPathPie(self.ptr, *arc_args(c, r, a0, a1))
def AddLines_pv(self, points):
wg.GdipAddPathLine2(self.ptr, *points_args(points))
def AddPolygon_pv(self, points):
wg.GdipAddPathPolygon(self.ptr, *points_args(points))
def CloseFigure(self):
wg.GdipClosePathFigure(self.ptr)
def GetLastPoint(self):
p = PointF()
wg.GdipGetPathLastPoint(self.ptr, byref(p))
return p.x, p.y
#--------------------------------------------------------------------
class Graphics(object):
def from_hdc(cls, hdc):
self = cls.__new__(cls)
ptr = c_void_p()
wg.GdipCreateFromHDC(c_ulong(hdc), byref(ptr))
self.ptr = ptr
return self
from_hdc = classmethod(from_hdc)
def from_dc(cls, dc):
return cls.from_hdc(dc.GetSafeHdc())
from_dc = classmethod(from_dc)
def from_image(cls, image):
#print "Graphics.from_image:", repr(image) ###
#print "...", image ###
self = cls.__new__(cls)
ptr = c_void_p()
wg.GdipGetImageGraphicsContext(image.ptr, byref(ptr))
self.ptr = ptr
return self
from_image = classmethod(from_image)
def __del__(self, wg = wg):
wg.GdipDeleteGraphics(self.ptr)
def __str__(self):
return "<Graphics 0x%x>" % self.ptr.value
def GetHDC(self):
hdc = c_long()
wg.GdipGetDC(self.ptr, byref(hdc))
return hdc.value
def ReleaseHDC(self, hdc):
wg.GdipReleaseDC(self.ptr, hdc)
def GetDpiX(self):
result = c_float()
wg.GdipGetDpiX(self.ptr, byref(result))
return result.value
def GetDpiY(self):
result = c_float()
wg.GdipGetDpiY(self.ptr, byref(result))
return result.value
def SetPageUnit(self, unit):
self.unit = unit
wg.GdipSetPageUnit(self.ptr, unit)
def GetClipBounds(self):
r = RectF()
wg.GdipGetClipBounds(self.ptr, byref(r))
return (r.x, r.y, r.x + r.width, r.y + r.height)
def Save(self):
state = c_uint()
wg.GdipSaveGraphics(self.ptr, byref(state))
return state.value
def Restore(self, state):
wg.GdipRestoreGraphics(self.ptr, state)
def DrawImage_rr(self, image, dst_rect, src_rect):
sl, st, sr, sb = src_rect
dl, dt, dr, db = dst_rect
wg.GdipDrawImageRectRect(self.ptr, image.ptr,
c_float(dl), c_float(dt), c_float(dr - dl), c_float(db - dt),
c_float(sl), c_float(st), c_float(sr - sl), c_float(sb - st),
UnitPixel, None, None, None)
def DrawPath(self, pen, path):
wg.GdipDrawPath(self.ptr, pen.ptr, path.ptr)
def FillPath(self, brush, path):
wg.GdipFillPath(self.ptr, brush.ptr, path.ptr)
def DrawAndMeasureStringWidth_2f(self, text, font, x, y, brush):
wtext = unicode(text)
n = len(text)
pos = PointF(x, y)
flags = 5 # DriverStringOptions CmapLookup+RealizedAdvance
b = RectF()
wg.GdipDrawDriverString(self.ptr, wtext, n, font.ptr, brush.ptr,
byref(pos), flags, None)
wg.GdipMeasureDriverString(self.ptr, wtext, n, font.ptr, byref(pos),
flags, None, byref(b))
return b.width
def MeasureStringWidth(self, text, font):
wtext = unicode(text)
n = len(text)
pos = PointF(0, 0)
flags = 5 # DriverStringOptions CmapLookup+RealizedAdvance
b = RectF()
wg.GdipMeasureDriverString(self.ptr, wtext, n, font.ptr, byref(pos),
flags, None, byref(b))
return b.width
def SetClip_PI(self, path):
wg.GdipSetClipPath(self.ptr, path.ptr, CombineModeIntersect)
def SetClip_rI(self, rect):
x, y, w, h = rect_args(rect)
wg.GdipSetClipRect(self.ptr, x, y, w, h, CombineModeIntersect)
def DrawRectangle_r(self, pen, rect):
wg.GdipDrawRectangle(self.ptr, pen.ptr, *rect_args(rect))
def FillRectangle_r(self, brush, rect):
#print "Graphics.FillRectangle_r:", self, brush, rect ###
#print "... clip bounds =", self.GetClipBounds() ###
wg.GdipFillRectangle(self.ptr, brush.ptr, *rect_args(rect))
def DrawEllipse_r(self, pen, rect):
wg.GdipDrawEllipse(self.ptr, pen.ptr, *rect_args(rect))
def FillEllipse_r(self, brush, rect):
wg.GdipFillEllipse(self.ptr, brush.ptr, *rect_args(rect))
def DrawArc_3pf(self, pen, c, r, a0, a1):
wg.GdipDrawArc(self.ptr, pen.ptr, *arc_args(c, r, a0, a1))
def DrawPie_p3f(self, pen, c, r, a0, a1):
wg.GdipDrawPie(self.ptr, pen.ptr, *arc_args(c, r, a0, a1))
def FillPie_p3f(self, brush, c, r, a0, a1):
wg.GdipFillPie(self.ptr, brush.ptr, *arc_args(c, r, a0, a1))
def DrawPolygon_pv(self, pen, points):
wg.GdipDrawPolygon(self.ptr, pen.ptr, *points_args(points))
def FillPolygon_pv(self, brush, points):
buf, n = points_args(points)
wg.GdipFillPolygon(self.ptr, brush.ptr, buf, n, FillModeAlternate)
def DrawBeziers_pv(self, pen, points):
wg.GdipDrawBeziers(self.ptr, pen.ptr, *points_args(points))
def DrawLines_pv(self, pen, points):
wg.GdipDrawLines(self.ptr, pen.ptr, *points_args(points))
def Translate_2f(self, dx, dy):
wg.GdipTranslateWorldTransform(self.ptr, c_float(dx), c_float(dy),
MatrixOrderAppend)
def Scale_2f(self, sx, sy):
wg.GdipScaleWorldTransform(self.ptr, c_float(sx), c_float(sy),
MatrixOrderAppend)
def Rotate_1f(self, r):
wg.GdipRotateWorldTransform(self.ptr, c_float(r),
MatrixOrderAppend)
def GetTransform(self):
matrix = c_void_p()
elems = (c_float * 6)()
wg.GdipCreateMatrix(byref(matrix))
wg.GdipGetWorldTransform(self.ptr, matrix)
wg.GdipGetMatrixElements(matrix, elems)
wg.GdipDeleteMatrix(matrix)
return list(elems)