mirror of
https://github.com/wxWidgets/Phoenix.git
synced 2026-01-08 04:50:07 +01:00
phoenix and py3 port patch from CMcP
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxPython/Phoenix/trunk@73758 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -2,13 +2,14 @@
|
||||
# Name: wx.lib.wxcairo
|
||||
# Purpose: Glue code to allow the pycairo package to be used
|
||||
# with a wx.DC as the cairo surface.
|
||||
#
|
||||
#
|
||||
# Author: Robin Dunn
|
||||
#
|
||||
# Created: 3-Sept-2008
|
||||
# RCS-ID: $Id$
|
||||
# Copyright: (c) 2008 by Total Control Software
|
||||
# Licence: wxWindows license
|
||||
#
|
||||
# Tags: phoenix-port, py3-port
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
"""
|
||||
@@ -18,8 +19,8 @@ drawing surface. The `CairoContextFromDC` function in this module
|
||||
will return an instance of the pycairo Context class that is ready for
|
||||
drawing, using the native cairo surface type for the current platform.
|
||||
|
||||
This module requires the pycairo pacakge, and makes use of ctypes for
|
||||
fetching the pycairo C API and also for digging into the cairo library
|
||||
This module requires the pycairo package, and makes use of ctypes for
|
||||
fetching the pycairo C API and also for digging into the cairo library
|
||||
itself.
|
||||
|
||||
To use Cairo with wxPython you will need to have a few dependencies
|
||||
@@ -51,6 +52,8 @@ installer for the pycairo pacakge here:
|
||||
|
||||
|
||||
import wx
|
||||
from wx.lib.six import PY3
|
||||
|
||||
import cairo
|
||||
import ctypes
|
||||
import ctypes.util
|
||||
@@ -59,16 +62,19 @@ import ctypes.util
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
# A reference to the cairo shared lib via ctypes.CDLL
|
||||
cairoLib = None
|
||||
cairoLib = None
|
||||
|
||||
# A reference to the pycairo C API structure
|
||||
pycairoAPI = None
|
||||
|
||||
|
||||
# a convenience funtion, just to save a bit of typing below
|
||||
# a convenience function, just to save a bit of typing below
|
||||
def voidp(ptr):
|
||||
"""Convert a SWIGged void* type to a ctypes c_void_p"""
|
||||
return ctypes.c_void_p(long(ptr))
|
||||
"""Convert a SIP void* type to a ctypes c_void_p"""
|
||||
if PY3:
|
||||
return ctypes.c_void_p(int(ptr))
|
||||
else:
|
||||
return ctypes.c_void_p(long(ptr))
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
@@ -79,8 +85,8 @@ def ContextFromDC(dc):
|
||||
at this time.)
|
||||
"""
|
||||
if not isinstance(dc, wx.WindowDC) and not isinstance(dc, wx.MemoryDC):
|
||||
raise TypeError, "Only window and memory DC's are supported at this time."
|
||||
|
||||
raise TypeError("Only window and memory DC's are supported at this time.")
|
||||
|
||||
if 'wxMac' in wx.PlatformInfo:
|
||||
width, height = dc.GetSize()
|
||||
|
||||
@@ -88,15 +94,9 @@ def ContextFromDC(dc):
|
||||
cgc = dc.GetHandle()
|
||||
assert cgc is not None, "Unable to get CGContext from DC."
|
||||
cgref = voidp( cgc )
|
||||
surface_create = cairoLib.cairo_quartz_surface_create_for_cg_context
|
||||
surface_create.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_int]
|
||||
surface_create.restype = ctypes.c_void_p
|
||||
surfaceptr = voidp(surface_create(cgref, width, height))
|
||||
|
||||
# create a cairo context for that surface
|
||||
cairo_create = cairoLib.cairo_create
|
||||
cairo_create.argtypes = [ctypes.c_void_p]
|
||||
cairo_create.restype = ctypes.c_void_p
|
||||
ctxptr = voidp(cairo_create(surfaceptr))
|
||||
|
||||
# Turn it into a pycairo context object
|
||||
@@ -105,7 +105,7 @@ def ContextFromDC(dc):
|
||||
# The context keeps its own reference to the surface
|
||||
cairoLib.cairo_surface_destroy(surfaceptr)
|
||||
|
||||
|
||||
|
||||
elif 'wxMSW' in wx.PlatformInfo:
|
||||
# This one is easy, just fetch the HDC and use PyCairo to make
|
||||
# the surface and context.
|
||||
@@ -114,25 +114,22 @@ def ContextFromDC(dc):
|
||||
hdc = ctypes.c_long(hdc)
|
||||
surface = cairo.Win32Surface(hdc.value)
|
||||
ctx = cairo.Context(surface)
|
||||
|
||||
|
||||
|
||||
elif 'wxGTK' in wx.PlatformInfo:
|
||||
gdkLib = _findGDKLib()
|
||||
|
||||
# Get the GdkDrawable from the dc
|
||||
drawable = voidp( dc.GetHandle() )
|
||||
|
||||
# Call a GDK API to create a cairo context
|
||||
gdkLib.gdk_cairo_create.restype = ctypes.c_void_p
|
||||
ctxptr = gdkLib.gdk_cairo_create(drawable)
|
||||
|
||||
# Turn it into a pycairo context object
|
||||
ctx = pycairoAPI.Context_FromContext(ctxptr, pycairoAPI.Context_Type, None)
|
||||
|
||||
else:
|
||||
raise NotImplementedError, "Help me, I'm lost..."
|
||||
|
||||
return ctx
|
||||
else:
|
||||
raise NotImplementedError("Help me, I'm lost...")
|
||||
|
||||
return ctx
|
||||
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
@@ -142,43 +139,30 @@ def FontFaceFromFont(font):
|
||||
Creates and returns a cairo.FontFace object from the native
|
||||
information in a wx.Font.
|
||||
"""
|
||||
|
||||
|
||||
if 'wxMac' in wx.PlatformInfo:
|
||||
font_face_create = cairoLib.cairo_quartz_font_face_create_for_cgfont
|
||||
font_face_create.argtypes = [ctypes.c_void_p]
|
||||
font_face_create.restype = ctypes.c_void_p
|
||||
|
||||
fontfaceptr = font_face_create(voidp(font.OSXGetCGFont()))
|
||||
fontface = pycairoAPI.FontFace_FromFontFace(fontfaceptr)
|
||||
|
||||
|
||||
elif 'wxMSW' in wx.PlatformInfo:
|
||||
cairoLib.cairo_win32_font_face_create_for_hfont.restype = ctypes.c_void_p
|
||||
fontfaceptr = voidp( cairoLib.cairo_win32_font_face_create_for_hfont(
|
||||
ctypes.c_ulong(font.GetHFONT())) )
|
||||
fontface = pycairoAPI.FontFace_FromFontFace(fontfaceptr)
|
||||
|
||||
|
||||
elif 'wxGTK' in wx.PlatformInfo:
|
||||
gdkLib = _findGDKLib()
|
||||
pcLib = _findPangoCairoLib()
|
||||
|
||||
# wow, this is a hell of a lot of steps...
|
||||
desc = voidp( font.GetPangoFontDescription() )
|
||||
|
||||
pcLib.pango_cairo_font_map_get_default.restype = ctypes.c_void_p
|
||||
pcfm = voidp(pcLib.pango_cairo_font_map_get_default())
|
||||
|
||||
gdkLib.gdk_pango_context_get.restype = ctypes.c_void_p
|
||||
pctx = voidp(gdkLib.gdk_pango_context_get())
|
||||
|
||||
pcLib.pango_font_map_load_font.restype = ctypes.c_void_p
|
||||
pfnt = voidp( pcLib.pango_font_map_load_font(pcfm, pctx, desc) )
|
||||
|
||||
pcLib.pango_cairo_font_get_scaled_font.restype = ctypes.c_void_p
|
||||
scaledfontptr = voidp( pcLib.pango_cairo_font_get_scaled_font(pfnt) )
|
||||
|
||||
cairoLib.cairo_scaled_font_get_font_face.restype = ctypes.c_void_p
|
||||
fontfaceptr = voidp(cairoLib.cairo_scaled_font_get_font_face(scaledfontptr))
|
||||
cairoLib.cairo_font_face_reference(fontfaceptr)
|
||||
|
||||
@@ -187,7 +171,7 @@ def FontFaceFromFont(font):
|
||||
gdkLib.g_object_unref(pctx)
|
||||
|
||||
else:
|
||||
raise NotImplementedError, "Help me, I'm lost..."
|
||||
raise NotImplementedError("Help me, I'm lost...")
|
||||
|
||||
return fontface
|
||||
|
||||
@@ -202,7 +186,7 @@ def BitmapFromImageSurface(surface):
|
||||
format = surface.get_format()
|
||||
if format not in [cairo.FORMAT_ARGB32, cairo.FORMAT_RGB24]:
|
||||
raise TypeError("Unsupported format")
|
||||
|
||||
|
||||
width = surface.get_width()
|
||||
height = surface.get_height()
|
||||
stride = surface.get_stride()
|
||||
@@ -212,7 +196,7 @@ def BitmapFromImageSurface(surface):
|
||||
else:
|
||||
fmt = wx.BitmapBufferFormat_RGB32
|
||||
|
||||
bmp = wx.EmptyBitmap(width, height, 32)
|
||||
bmp = wx.Bitmap(width, height, 32)
|
||||
bmp.CopyFromBuffer(data, fmt, stride)
|
||||
return bmp
|
||||
|
||||
@@ -222,7 +206,7 @@ def ImageSurfaceFromBitmap(bitmap):
|
||||
Create an ImageSurface from a wx.Bitmap
|
||||
"""
|
||||
width, height = bitmap.GetSize()
|
||||
if bitmap.HasAlpha():
|
||||
if bitmap.ConvertToImage().HasAlpha():
|
||||
format = cairo.FORMAT_ARGB32
|
||||
fmt = wx.BitmapBufferFormat_ARGB32
|
||||
else:
|
||||
@@ -233,7 +217,7 @@ def ImageSurfaceFromBitmap(bitmap):
|
||||
stride = cairo.ImageSurface.format_stride_for_width(format, width)
|
||||
except AttributeError:
|
||||
stride = width * 4
|
||||
|
||||
|
||||
surface = cairo.ImageSurface(format, width, height)
|
||||
bitmap.CopyToBuffer(surface.get_data(), fmt, stride)
|
||||
surface.mark_dirty()
|
||||
@@ -265,14 +249,14 @@ def _findCairoLib():
|
||||
# if that didn't work then use the ctypes util to search the paths
|
||||
# appropriate for the system
|
||||
for name in names:
|
||||
location = ctypes.util.find_library(name)
|
||||
location = ctypes.util.find_library(name)
|
||||
if location:
|
||||
try:
|
||||
cairoLib = ctypes.CDLL(location)
|
||||
return
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
# If the above didn't find it on OS X then we still have a
|
||||
# trick up our sleeve...
|
||||
if 'wxMac' in wx.PlatformInfo:
|
||||
@@ -289,9 +273,9 @@ def _findCairoLib():
|
||||
pass
|
||||
|
||||
if not cairoLib:
|
||||
raise RuntimeError, "Unable to find the Cairo shared library"
|
||||
|
||||
|
||||
raise RuntimeError("Unable to find the Cairo shared library")
|
||||
|
||||
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
@@ -309,7 +293,7 @@ def _findHelper(names, key, msg):
|
||||
if location:
|
||||
break
|
||||
if not location:
|
||||
raise RuntimeError, msg
|
||||
raise RuntimeError(msg)
|
||||
dll = ctypes.CDLL(location)
|
||||
_dlls[key] = dll
|
||||
return dll
|
||||
@@ -325,7 +309,7 @@ def _findPangoCairoLib():
|
||||
def _findAppSvcLib():
|
||||
return _findHelper(['ApplicationServices'], 'appsvc',
|
||||
"Unable to find the ApplicationServices Framework")
|
||||
|
||||
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
@@ -374,7 +358,7 @@ class Pycairo_CAPI(ctypes.Structure):
|
||||
# This structure is known good with pycairo 1.8.4.
|
||||
# We have to also test for (1,10,8) because pycairo 1.8.10 has an
|
||||
# incorrect version_info value
|
||||
elif cairo.version_info < (1,9) or cairo.version_info == (1,10,8):
|
||||
elif cairo.version_info < (1,9) or cairo.version_info == (1,10,8):
|
||||
_fields_ = [
|
||||
('Context_Type', ctypes.py_object),
|
||||
('Context_FromContext', ctypes.PYFUNCTYPE(ctypes.py_object,
|
||||
@@ -414,7 +398,7 @@ class Pycairo_CAPI(ctypes.Structure):
|
||||
|
||||
# This structure is known good with pycairo 1.10.0. They keep adding stuff
|
||||
# to the middle of the structure instead of only adding to the end!
|
||||
elif cairo.version_info < (1,11):
|
||||
elif cairo.version_info < (1,11):
|
||||
_fields_ = [
|
||||
('Context_Type', ctypes.py_object),
|
||||
('Context_FromContext', ctypes.PYFUNCTYPE(ctypes.py_object,
|
||||
@@ -422,7 +406,7 @@ class Pycairo_CAPI(ctypes.Structure):
|
||||
ctypes.py_object,
|
||||
ctypes.py_object)),
|
||||
('FontFace_Type', ctypes.py_object),
|
||||
('ToyFontFace_Type', ctypes.py_object),
|
||||
('ToyFontFace_Type', ctypes.py_object),
|
||||
('FontFace_FromFontFace', ctypes.PYFUNCTYPE(ctypes.py_object, ctypes.c_void_p)),
|
||||
('FontOptions_Type', ctypes.py_object),
|
||||
('FontOptions_FromFontOptions', ctypes.PYFUNCTYPE(ctypes.py_object, ctypes.c_void_p)),
|
||||
@@ -459,11 +443,17 @@ def _loadPycairoAPI():
|
||||
global pycairoAPI
|
||||
if pycairoAPI is not None:
|
||||
return
|
||||
|
||||
PyCObject_AsVoidPtr = ctypes.pythonapi.PyCObject_AsVoidPtr
|
||||
PyCObject_AsVoidPtr.argtypes = [ctypes.py_object]
|
||||
PyCObject_AsVoidPtr.restype = ctypes.c_void_p
|
||||
ptr = PyCObject_AsVoidPtr(cairo.CAPI)
|
||||
|
||||
if PY3:
|
||||
PyCapsule_GetPointer = ctypes.pythonapi.PyCapsule_GetPointer
|
||||
PyCapsule_GetPointer.argtypes = [ctypes.py_object, ctypes.c_char_p]
|
||||
PyCapsule_GetPointer.restype = ctypes.c_void_p
|
||||
ptr = PyCapsule_GetPointer(cairo.CAPI, b'cairo.CAPI')
|
||||
else:
|
||||
PyCObject_AsVoidPtr = ctypes.pythonapi.PyCObject_AsVoidPtr
|
||||
PyCObject_AsVoidPtr.argtypes = [ctypes.py_object]
|
||||
PyCObject_AsVoidPtr.restype = ctypes.c_void_p
|
||||
ptr = PyCObject_AsVoidPtr(cairo.CAPI)
|
||||
pycairoAPI = ctypes.cast(ptr, ctypes.POINTER(Pycairo_CAPI)).contents
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
@@ -473,4 +463,30 @@ def _loadPycairoAPI():
|
||||
_findCairoLib()
|
||||
_loadPycairoAPI()
|
||||
|
||||
if 'wxMac' in wx.PlatformInfo:
|
||||
surface_create = cairoLib.cairo_quartz_surface_create_for_cg_context
|
||||
surface_create.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_int]
|
||||
surface_create.restype = ctypes.c_void_p
|
||||
|
||||
cairo_create = cairoLib.cairo_create
|
||||
cairo_create.argtypes = [ctypes.c_void_p]
|
||||
cairo_create.restype = ctypes.c_void_p
|
||||
|
||||
font_face_create = cairoLib.cairo_quartz_font_face_create_for_cgfont
|
||||
font_face_create.argtypes = [ctypes.c_void_p]
|
||||
font_face_create.restype = ctypes.c_void_p
|
||||
|
||||
elif 'wxMSW' in wx.PlatformInfo:
|
||||
cairoLib.cairo_win32_font_face_create_for_hfont.restype = ctypes.c_void_p
|
||||
|
||||
elif 'wxGTK' in wx.PlatformInfo:
|
||||
gdkLib = _findGDKLib()
|
||||
pcLib = _findPangoCairoLib()
|
||||
|
||||
gdkLib.gdk_cairo_create.restype = ctypes.c_void_p
|
||||
pcLib.pango_cairo_font_map_get_default.restype = ctypes.c_void_p
|
||||
gdkLib.gdk_pango_context_get.restype = ctypes.c_void_p
|
||||
pcLib.pango_font_map_load_font.restype = ctypes.c_void_p
|
||||
pcLib.pango_cairo_font_get_scaled_font.restype = ctypes.c_void_p
|
||||
cairoLib.cairo_scaled_font_get_font_face.restype = ctypes.c_void_p
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user