DR -> DR SDK #16

Merged
shenjackyuanjie merged 41 commits from feature/dr-sdk into main 2023-05-03 00:40:53 +08:00
4 changed files with 56 additions and 112 deletions
Showing only changes of commit f53460a24b - Show all commits

View File

@ -3,7 +3,6 @@ from .base import Display, Screen, ScreenMode, Canvas
from pyglet.libs.win32 import _user32 from pyglet.libs.win32 import _user32
from pyglet.libs.win32.constants import * from pyglet.libs.win32.constants import *
from pyglet.libs.win32.types import * from pyglet.libs.win32.types import *
from pyglet.libs.win32.context_managers import device_context
class Win32Display(Display): class Win32Display(Display):
@ -31,13 +30,13 @@ class Win32Screen(Screen):
self._handle = handle self._handle = handle
def get_matching_configs(self, template): def get_matching_configs(self, template):
with device_context(None) as hdc: hdc = _user32.GetDC(0)
canvas = Win32Canvas(self.display, 0, hdc) canvas = Win32Canvas(self.display, 0, hdc)
configs = template.match(canvas) configs = template.match(canvas)
# XXX deprecate config's being screen-specific # XXX deprecate config's being screen-specific
for config in configs: for config in configs:
config.screen = self config.screen = self
_user32.ReleaseDC(0, hdc)
return configs return configs
def get_device_name(self): def get_device_name(self):

View File

@ -9,7 +9,6 @@ from pyglet.font import base
from pyglet.font import win32query from pyglet.font import win32query
import pyglet.image import pyglet.image
from pyglet.libs.win32.constants import * from pyglet.libs.win32.constants import *
from pyglet.libs.win32.context_managers import device_context
from pyglet.libs.win32.types import * from pyglet.libs.win32.types import *
from pyglet.libs.win32 import _gdi32 as gdi32, _user32 as user32 from pyglet.libs.win32 import _gdi32 as gdi32, _user32 as user32
from pyglet.libs.win32 import _kernel32 as kernel32 from pyglet.libs.win32 import _kernel32 as kernel32
@ -196,13 +195,14 @@ class Win32Font(base.Font):
self.hfont = gdi32.CreateFontIndirectW(byref(self.logfont)) self.hfont = gdi32.CreateFontIndirectW(byref(self.logfont))
# Create a dummy DC for coordinate mapping # Create a dummy DC for coordinate mapping
with device_context(None) as dc: dc = user32.GetDC(0)
metrics = TEXTMETRIC() metrics = TEXTMETRIC()
gdi32.SelectObject(dc, self.hfont) gdi32.SelectObject(dc, self.hfont)
gdi32.GetTextMetricsA(dc, byref(metrics)) gdi32.GetTextMetricsA(dc, byref(metrics))
self.ascent = metrics.tmAscent self.ascent = metrics.tmAscent
self.descent = -metrics.tmDescent self.descent = -metrics.tmDescent
self.max_glyph_width = metrics.tmMaxCharWidth self.max_glyph_width = metrics.tmMaxCharWidth
user32.ReleaseDC(0, dc)
def __del__(self): def __del__(self):
gdi32.DeleteObject(self.hfont) gdi32.DeleteObject(self.hfont)
@ -210,22 +210,22 @@ class Win32Font(base.Font):
@staticmethod @staticmethod
def get_logfont(name, size, bold, italic, dpi): def get_logfont(name, size, bold, italic, dpi):
# Create a dummy DC for coordinate mapping # Create a dummy DC for coordinate mapping
with device_context(None) as dc: dc = user32.GetDC(0)
if dpi is None: if dpi is None:
dpi = 96 dpi = 96
logpixelsy = dpi logpixelsy = dpi
logfont = LOGFONTW()
# Conversion of point size to device pixels
logfont.lfHeight = int(-size * logpixelsy // 72)
if bold:
logfont.lfWeight = FW_BOLD
else:
logfont.lfWeight = FW_NORMAL
logfont.lfItalic = italic
logfont.lfFaceName = name
logfont.lfQuality = ANTIALIASED_QUALITY
logfont = LOGFONTW()
# Conversion of point size to device pixels
logfont.lfHeight = int(-size * logpixelsy // 72)
if bold:
logfont.lfWeight = FW_BOLD
else:
logfont.lfWeight = FW_NORMAL
logfont.lfItalic = italic
logfont.lfFaceName = name
logfont.lfQuality = ANTIALIASED_QUALITY
user32.ReleaseDC(0, dc)
return logfont return logfont
@classmethod @classmethod

View File

@ -71,7 +71,6 @@ appropriate typeface name and create the font using CreateFont or
CreateFontIndirect. CreateFontIndirect.
""" """
from pyglet.libs.win32.context_managers import device_context
DEBUG = False DEBUG = False
@ -386,33 +385,36 @@ def query(charset=DEFAULT_CHARSET):
global FONTDB global FONTDB
# 1. Get device context of the entire screen # 1. Get device context of the entire screen
with device_context(None) as hdc: hdc = user32.GetDC(None)
# 2. Call EnumFontFamiliesExA (ANSI version) # 2. Call EnumFontFamiliesExA (ANSI version)
# 2a. Call with empty font name to query all available fonts # 2a. Call with empty font name to query all available fonts
# (or fonts for the specified charset) # (or fonts for the specified charset)
# #
# NOTES: # NOTES:
# #
# * there are fonts that don't support ANSI charset # * there are fonts that don't support ANSI charset
# * for DEFAULT_CHARSET font is passed to callback function as # * for DEFAULT_CHARSET font is passed to callback function as
# many times as charsets it supports # many times as charsets it supports
# [ ] font name should be less than 32 symbols with terminating \0 # [ ] font name should be less than 32 symbols with terminating \0
# [ ] check double purpose - enumerate all available font names # [ ] check double purpose - enumerate all available font names
# - enumerate all available charsets for a single font # - enumerate all available charsets for a single font
# - other params? # - other params?
logfont = LOGFONTW(0, 0, 0, 0, 0, 0, 0, 0, charset, 0, 0, 0, 0, '') logfont = LOGFONTW(0, 0, 0, 0, 0, 0, 0, 0, charset, 0, 0, 0, 0, '')
FONTDB = [] # clear cached FONTDB for enum_font_names callback FONTDB = [] # clear cached FONTDB for enum_font_names callback
res = gdi32.EnumFontFamiliesExW( res = gdi32.EnumFontFamiliesExW(
hdc, # handle to device context hdc, # handle to device context
ctypes.byref(logfont), ctypes.byref(logfont),
enum_font_names, # pointer to callback function enum_font_names, # pointer to callback function
0, # lParam - application-supplied data 0, # lParam - application-supplied data
0) # dwFlags - reserved = 0 0) # dwFlags - reserved = 0
# res here is the last value returned by callback function # res here is the last value returned by callback function
# 3. Release DC
user32.ReleaseDC(None, hdc)
return FONTDB return FONTDB

View File

@ -1,57 +0,0 @@
"""
Win32 resources as handy context managers.
These are intended to help keep loader code clean & stable at the price
of a tiny bit of execution speed. Performance-critical code should avoid
using these helpers in favor of direct win32 API calls.
Before::
def loader_function(arg):
context_handle = user32.GetResource(None)
result = calculation(arg)
# Easily forgotten!
user32.ReleaseResource(context_handle)
return result
After::
def loader_function(arg):
with resource_context() as context_handle:
result = calculation(arg)
return result
"""
from contextlib import contextmanager
from typing import Optional, Generator
from ctypes.wintypes import HANDLE
from ctypes import WinError
from pyglet.libs.win32 import _user32 as user32
@contextmanager
def device_context(window_handle: Optional[int] = None) -> Generator[HANDLE, None, None]:
"""
A Windows device context wrapped as a context manager.
Args:
window_handle: A specific window handle to use, if any.
Raises:
WinError: Raises if a device context cannot be acquired or released
Yields:
HANDLE: the managed drawing context handle to auto-close.
"""
if not (_dc := user32.GetDC(window_handle)):
raise WinError()
try:
yield _dc
finally:
if not user32.ReleaseDC(None, _dc):
raise WinError()