Ticket #1230: pdfium-poc.patch
File pdfium-poc.patch, 15.1 KB (added by , 5 years ago) |
---|
-
tests/xpra/pdfium/__init__.py
1 #!/usr/bin/env python 2 # This file is part of Xpra. 3 # Copyright (C) 2017 Antoine Martin <antoine@devloop.org.uk> 4 No newline at end of file -
tests/xpra/pdfium/pdfium.py
Property changes on: tests/xpra/pdfium/__init__.py ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property
1 #!/usr/bin/env python 2 3 import sys 4 5 from tests.xpra.pdfium.print_to_hdc import hdc_print, log, error, DOCINFO, StartDocA, EndDoc, LPCSTR 6 7 from xpra.platform.win32.common import GetDeviceCaps 8 from xpra.platform.win32 import win32con 9 from ctypes import WinDLL, c_void_p, Structure, c_int, c_uint, c_ulong, c_char_p, cast, pointer, POINTER 10 from ctypes.wintypes import HDC 11 12 class FPDF_LIBRARY_CONFIG(Structure): 13 _fields_ = [ 14 ("m_pUserFontPaths", c_void_p), 15 ("version", c_int), 16 ("m_pIsolate", c_void_p), 17 ("m_v8EmbedderSlot", c_uint), 18 ] 19 20 FPDF_DOCUMENT = c_void_p 21 FPDF_PAGE = c_void_p 22 23 pdfium = WinDLL('E:\\libpdfium.dll', use_last_error=True) 24 log("pdfium=%s", pdfium) 25 FPDF_DestroyLibrary = pdfium.FPDF_DestroyLibrary 26 FPDF_InitLibraryWithConfig = pdfium.FPDF_InitLibraryWithConfig 27 FPDF_InitLibraryWithConfig.argtypes = [POINTER(FPDF_LIBRARY_CONFIG)] 28 FPDF_GetLastError = pdfium.FPDF_GetLastError 29 FPDF_GetLastError.restype = c_ulong 30 FPDF_GetPageCount = pdfium.FPDF_GetPageCount 31 FPDF_GetPageCount.argtypes = [FPDF_DOCUMENT] 32 FPDF_GetPageCount.restype = c_int 33 FPDF_LoadPage = pdfium.FPDF_LoadPage 34 FPDF_LoadPage.argtypes = [FPDF_DOCUMENT, c_int] 35 FPDF_RenderPage = pdfium.FPDF_RenderPage 36 FPDF_RenderPage.argtypes = [HDC, FPDF_PAGE, c_int, c_int, c_int, c_int, c_int, c_int] 37 FPDF_LoadMemDocument = pdfium.FPDF_LoadMemDocument 38 FPDF_LoadMemDocument.restype = FPDF_DOCUMENT 39 FPDF_LoadMemDocument.argtypes = [c_void_p, c_int, c_void_p] 40 FPDF_CloseDocument = pdfium.FPDF_CloseDocument 41 FPDF_CloseDocument.argtypes = [FPDF_DOCUMENT] 42 43 44 FPDF_ERR_SUCCESS = 0 # No error. 45 FPDF_ERR_UNKNOWN = 1 # Unknown error. 46 FPDF_ERR_FILE = 2 # File not found or could not be opened. 47 FPDF_ERR_FORMAT = 3 # File not in PDF format or corrupted. 48 FPDF_ERR_PASSWORD = 4 # Password required or incorrect password. 49 FPDF_ERR_SECURITY = 5 # Unsupported security scheme. 50 FPDF_ERR_PAGE = 6 # Page not found or content error. 51 FPDF_ERR_XFALOAD = 7 # Load XFA error. 52 FPDF_ERR_XFALAYOUT = 8 # Layout XFA error. 53 54 ERROR_STR = { 55 #FPDF_ERR_SUCCESS : No error. 56 FPDF_ERR_UNKNOWN : "Unknown error", 57 FPDF_ERR_FILE : "File not found or could not be opened", 58 FPDF_ERR_FORMAT : "File not in PDF format or corrupted", 59 FPDF_ERR_PASSWORD : "Password required or incorrect password", 60 FPDF_ERR_SECURITY : "Unsupported security scheme", 61 FPDF_ERR_PAGE : "Page not found or content error", 62 FPDF_ERR_XFALOAD : "Load XFA error", 63 FPDF_ERR_XFALAYOUT : "Layout XFA error", 64 } 65 66 FPDF_ANNOT = 0x01 67 FPDF_LCD_TEXT = 0x02 68 FPDF_NO_NATIVETEXT = 0x04 69 FPDF_GRAYSCALE = 0x08 70 FPDF_DEBUG_INFO = 0x80 71 FPDF_NO_CATCH = 0x100 72 FPDF_RENDER_LIMITEDIMAGECACHE = 0x200 73 FPDF_RENDER_FORCEHALFTONE = 0x400 74 FPDF_PRINTING = 0x800 75 FPDF_RENDER_NO_SMOOTHTEXT = 0x1000 76 FPDF_RENDER_NO_SMOOTHIMAGE = 0x2000 77 FPDF_RENDER_NO_SMOOTHPATH = 0x4000 78 FPDF_REVERSE_BYTE_ORDER = 0x10 79 80 def get_error(): 81 global ERROR_STR 82 v = FPDF_GetLastError() 83 return ERROR_STR.get(v, v) 84 85 def print_to_hdc(hdc, title="PDF Print Test", pdf_data=None): 86 assert pdf_data, "no pdf data" 87 buf = c_char_p(pdf_data) 88 log("pdf data buffer: %s", buf) 89 log("FPDF_InitLibraryWithConfig=%s", FPDF_InitLibraryWithConfig) 90 config = FPDF_LIBRARY_CONFIG() 91 config.m_pUserFontPaths = None 92 config.version = 2 93 config.m_pIsolate = None 94 config.m_v8EmbedderSlot = 0 95 FPDF_InitLibraryWithConfig(config) 96 97 x = 0 98 y = 0 99 w = GetDeviceCaps(hdc, win32con.HORZRES) 100 h = GetDeviceCaps(hdc, win32con.VERTRES) 101 rotate = 0 102 log("printer device size: %ix%i", w, h) 103 flags = FPDF_PRINTING | FPDF_DEBUG_INFO 104 try: 105 doc = FPDF_LoadMemDocument(cast(buf, c_void_p), len(pdf_data), None) 106 if not doc: 107 error("FPDF_LoadMemDocument failed, error: %s", get_error()) 108 return 1 109 log("FPDF_LoadMemDocument(..)=%s", doc) 110 count = FPDF_GetPageCount(doc) 111 log("FPDF_GetPageCount(%s)=%s", doc, count) 112 113 docinfo = DOCINFO() 114 docinfo.lpszDocName = LPCSTR("%s\0" % title) 115 r = StartDocA(hdc, pointer(docinfo)) 116 if r<0: 117 log("StartDocA failed: %i", r) 118 return r 119 log("StartDocA()=%i" % r) 120 121 try: 122 for i in range(count): 123 page = FPDF_LoadPage(doc, i) 124 if not page: 125 log("FPDF_LoadPage failed for page %i, error: %s", i, get_error()) 126 return 1 127 log("FPDF_LoadPage()=%s page %i loaded", page, i) 128 FPDF_RenderPage(hdc, page, x, y, w, h, rotate, flags) 129 log("FPDF_RenderPage page %i rendered", i) 130 finally: 131 EndDoc(hdc) 132 finally: 133 FPDF_DestroyLibrary() 134 return 0 135 136 137 def main(): 138 if len(sys.argv)!=2: 139 print("usage: %s /path/to/document.pdf" % sys.argv[0]) 140 return 1 141 with open(sys.argv[1], 'rb') as f: 142 pdf_data = f.read() 143 144 def print_cb(hdc): 145 print_to_hdc(hdc, pdf_data=pdf_data) 146 hdc_print(print_cb) 147 148 if __name__ == "__main__": 149 sys.exit(main()) -
tests/xpra/pdfium/print_to_hdc.py
Property changes on: tests/xpra/pdfium/pdfium.py ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property
1 #!/usr/bin/env python 2 3 import sys 4 5 from xpra.platform.win32.common import CreateDCA, gdi32 6 from xpra.platform.win32.printing import get_printers 7 8 from ctypes import cdll, WinDLL, c_void_p, Structure, cast, c_char, c_int, pointer 9 from ctypes.wintypes import POINTER, HDC 10 from ctypes.wintypes import HANDLE, BOOL, BYTE, LPCSTR, DWORD, WORD 11 CHAR = BYTE 12 LPHANDLE = PHANDLE = POINTER(HANDLE) 13 LPBYTE = POINTER(BYTE) 14 LPDWORD = POINTER(DWORD) 15 LPPRINTER_DEFAULTS = c_void_p 16 PSECURITY_DESCRIPTOR = HANDLE 17 18 msvcrt = cdll.msvcrt 19 winspool = WinDLL('winspool.drv', use_last_error=True) 20 OpenPrinterA = winspool.OpenPrinterA 21 OpenPrinterA.restype = BOOL 22 ClosePrinter = winspool.ClosePrinter 23 ClosePrinter.restype = BOOL 24 ClosePrinter.argtypes = [HANDLE] 25 OpenPrinterA.argtypes = [LPCSTR, LPHANDLE, LPPRINTER_DEFAULTS] 26 GetPrinterA = winspool.GetPrinterA 27 GetPrinterA.restype = BOOL 28 GetPrinterA.argtypes = [HANDLE, DWORD, c_void_p, DWORD, LPDWORD] 29 30 class DOCINFO(Structure): 31 _fields_ = [ 32 ("cbSize", c_int), 33 ("lpszDocName", LPCSTR), 34 ("lpszOutput", LPCSTR), 35 ("lpszDatatype",LPCSTR), 36 ("fwType", DWORD), 37 ] 38 39 LPDOCINFO = POINTER(DOCINFO) 40 StartDocA = gdi32.StartDocA 41 StartDocA.argtypes = [HDC, LPDOCINFO] 42 EndDoc = gdi32.EndDoc 43 EndDoc.argtypes = [HDC] 44 EndDoc.restype = int 45 StartPage = gdi32.StartPage 46 StartPage.argtypes = [HDC] 47 EndPage = gdi32.EndPage 48 EndPage.argtypes = [HDC] 49 TextOutA = gdi32.TextOutA 50 TextOutA.restype = BOOL 51 TextOutA.argtypes = [HDC, c_int, c_int, LPCSTR, c_int] 52 53 CCHDEVICENAME = 32 54 55 class DEVMODE(Structure): 56 _fields_ = [ 57 ("dmDeviceName", c_char*CCHDEVICENAME), 58 ("dmSpecVersion", WORD), 59 ("dmDriverVersion", WORD), 60 ("dmSize", WORD), 61 ("dmDriverExtra", WORD), 62 ("dmFields", DWORD), 63 ] 64 LPDEVMODE = POINTER(DEVMODE) 65 66 class PRINTER_INFO_1(Structure): 67 _fields_ = [ 68 ("Flags", DWORD), 69 ("pDescription", LPCSTR), 70 ("pName", LPCSTR), 71 ("pComment", LPCSTR), 72 ] 73 74 class PRINTER_INFO_2(Structure): 75 _fields_ = [ 76 ("pServerName", LPCSTR), 77 ("pPrinterName", LPCSTR), 78 ("pShareName", LPCSTR), 79 ("pPortName", LPCSTR), 80 ("pDriverName", LPCSTR), 81 ("pComment", LPCSTR), 82 ("pLocation", LPCSTR), 83 ("pDevMode", LPDEVMODE), 84 ("pSepFile", LPCSTR), 85 ("pPrintProcessor", LPCSTR), 86 ("pDatatype", LPCSTR), 87 ("pParameters", LPCSTR), 88 ("pSecurityDescriptor", PSECURITY_DESCRIPTOR), 89 ("Attributes", DWORD), 90 ("Priority", DWORD), 91 ("DefaultPriority", DWORD), 92 ("StartTime", DWORD), 93 ("UntilTime", DWORD), 94 ("Status", DWORD), 95 ("cJobs", DWORD), 96 ("AveragePPM", DWORD), 97 ] 98 99 class PRINTER_INFO_8(Structure): 100 _fields_ = [ 101 ("pDevMode", LPDEVMODE), 102 ] 103 PRINTER_INFO_9 = PRINTER_INFO_8 104 105 106 def log(msg, *args): 107 sys.stdout.write(msg % args) 108 sys.stdout.write("\n") 109 sys.stdout.flush() 110 111 def error(msg, *args): 112 print(("Error: "+msg) % args) 113 114 115 def print_document(hdc, title="Test", print_doc_fn=None): 116 docinfo = DOCINFO() 117 docinfo.lpszDocName = LPCSTR("%s\0" % title) 118 r = StartDocA(hdc, pointer(docinfo)) 119 if r<0: 120 log("StartDocA failed: %i", r) 121 return r 122 log("StartDocA()=%i" % r) 123 124 r = StartPage(hdc) 125 if r<0: 126 log("StartPage failed: %i", r) 127 return r 128 129 if print_doc_fn: 130 r = print_doc_fn(hdc) 131 if r!=0: 132 return r 133 134 r = EndPage(hdc) 135 if r<0: 136 log("EndPage failed: %i", r) 137 return r 138 139 r = EndDoc(hdc) 140 if r<0: 141 log("EndDoc failed: %i" % r) 142 return r 143 log("EndDoc()=%i" % r) 144 return 0 145 146 def print_to_hdc(hdc): 147 def print_doc_fn(hdc): 148 x = 100 149 y = 100 150 import datetime 151 s = "test: %s" % (datetime.datetime.now()) 152 if not TextOutA(hdc, x, y, LPCSTR(s), len(s)): 153 log("TextOutA failed") 154 return 1 155 return 0 156 return print_document(hdc, print_doc_fn=print_doc_fn) 157 158 159 def hdc_print(print_fn): 160 printers = get_printers() 161 log("printers: %s", printers) 162 name = LPCSTR(printers.keys()[0]) 163 handle = HANDLE() 164 if not OpenPrinterA(name, pointer(handle), None): 165 error("failed to open printer %s" % name) 166 return 1 167 try: 168 log("OpenPrinter: handle=%#x" % handle.value) 169 size = DWORD() 170 GetPrinterA(handle, 1, None, 0, pointer(size)) 171 log("GetPrinter: PRINTER_INFO_1 size=%i" % size.value) 172 buf = msvcrt.malloc(size.value) 173 if not GetPrinterA(handle, 1, buf, size.value, pointer(size)): 174 error("GetPrinterA failed for %s", name) 175 return 1 176 info = cast(buf, POINTER(PRINTER_INFO_1)) 177 log(" flags=%#x" % info[0].Flags) 178 log(" name=%#s" % info[0].pName) 179 log(" description=%s" % info[0].pDescription) 180 log(" comment=%s" % info[0].pComment) 181 msvcrt.free(buf) 182 183 GetPrinterA(handle, 2, None, 0, pointer(size)) 184 log("GetPrinter: PRINTER_INFO_2 size=%i" % size.value) 185 buf = msvcrt.malloc(size.value) 186 if GetPrinterA(handle, 2, buf, size.value, pointer(size)): 187 info = cast(buf, POINTER(PRINTER_INFO_2)) 188 log(" driver=%#s" % info[0].pDriverName) 189 msvcrt.free(buf) 190 191 GetPrinterA(handle, 8, None, 0, pointer(size)) 192 log("GetPrinter: PRINTER_INFO_8 size=%i" % size.value) 193 info8 = msvcrt.malloc(size.value) 194 devmode = None 195 try: 196 if GetPrinterA(handle, 8, buf, size.value, pointer(size)): 197 info = cast(buf, POINTER(PRINTER_INFO_8)) 198 devmode = cast(info[0].pDevMode, POINTER(DEVMODE)) 199 log("devmode=%s" % devmode) 200 log("device name=%s" % devmode[0].dmDeviceName) 201 202 GetPrinterA(handle, 9, None, 0, pointer(size)) 203 log("GetPrinter: PRINTER_INFO_9 size=%i" % size.value) 204 info9 = msvcrt.malloc(size.value) 205 if GetPrinterA(handle, 9, buf, size.value, pointer(size)): 206 info = cast(buf, POINTER(PRINTER_INFO_9)) 207 if info[0].pDevMode: 208 devmode = cast(info[0].pDevMode, POINTER(DEVMODE)) 209 log("devmode=%s" % devmode) 210 log("device name=%s" % devmode[0].dmDeviceName) 211 assert devmode 212 213 hdc = CreateDCA(None, name, None, devmode) 214 log("CreateDCA()=%#x" % hdc) 215 216 return print_fn(hdc) 217 finally: 218 msvcrt.free(info8) 219 msvcrt.free(info9) 220 finally: 221 ClosePrinter(handle) 222 return 0 223 224 225 def main(): 226 return hdc_print(print_to_hdc) 227 228 229 if __name__ == "__main__": 230 sys.exit(main()) -
xpra/platform/win32/common.py
Property changes on: tests/xpra/pdfium/print_to_hdc.py ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property
6 6 7 7 import ctypes 8 8 9 from ctypes import WinDLL, Structure, c_ulong, c_ushort, c_ubyte, c_int, c_long 9 from ctypes import WinDLL, Structure, c_ulong, c_ushort, c_ubyte, c_int, c_long, c_void_p 10 10 from ctypes.wintypes import HWND, DWORD, WPARAM, LPARAM, HDC, HMONITOR, HMODULE, SHORT, ATOM, POINTER, RECT 11 from ctypes.wintypes import HANDLE, LPCWSTR, UINT, INT, WINFUNCTYPE, BOOL, HGDIOBJ, LONG, LPVOID, HBITMAP 11 from ctypes.wintypes import HANDLE, LPCWSTR, UINT, INT, WINFUNCTYPE, BOOL, HGDIOBJ, LONG, LPVOID, HBITMAP, LPCSTR 12 12 LRESULT = c_long 13 DEVMODE = c_void_p 13 14 14 15 kernel32 = WinDLL("kernel32", use_last_error=True) 15 16 SetConsoleTitleA = kernel32.SetConsoleTitleA … … 119 120 DeleteDC = gdi32.DeleteDC 120 121 DeleteDC.restype = BOOL 121 122 DeleteDC.argtypes = [HDC] 123 CreateDCA = gdi32.CreateDCA 124 CreateDCA.restype = HDC 125 CreateDCA.argtypes = [LPCSTR, LPCSTR, LPCSTR, DEVMODE] 122 126 123 124 127 #wrap EnumDisplayMonitors to hide the callback function: 125 128 MonitorEnumProc = ctypes.WINFUNCTYPE(BOOL, HMONITOR, HDC, POINTER(RECT), LPARAM) 126 129 _EnumDisplayMonitors = EnumDisplayMonitors -
xpra/platform/win32/printing.py
163 163 def get_printers(): 164 164 global PRINTER_ENUMS, PRINTER_ENUM_VALUES, SKIPPED_PRINTERS, PRINTER_LEVEL, GSVIEW_DIR 165 165 printers = {} 166 if not GSVIEW_DIR:167 #without gsprint, we can't handle printing!168 log("get_printers() gsview is missing, not querying any printers")169 return printers166 #if not GSVIEW_DIR: 167 # #without gsprint, we can't handle printing! 168 # log("get_printers() gsview is missing, not querying any printers") 169 # return printers 170 170 #default_printer = GetDefaultPrinter() 171 171 for penum in PRINTER_ENUMS: 172 172 try: … … 179 179 for p in EnumPrinters(enum_val, None, PRINTER_LEVEL): 180 180 flags, desc, name, comment = p 181 181 if name in SKIPPED_PRINTERS: 182 log("skipped printer: % s, %s, %s, %s", flags, desc, name, comment)182 log("skipped printer: %#x, %s, %s, %s", flags, desc, name, comment) 183 183 continue 184 184 if name in printers: 185 log("skipped duplicate printer: % s, %s, %s, %s", flags, desc, name, comment)185 log("skipped duplicate printer: %#x, %s, %s, %s", flags, desc, name, comment) 186 186 continue 187 log("found printer: % s, %s, %s, %s", flags, desc, name, comment)187 log("found printer: %#x, %s, %s, %s", flags, desc, name, comment) 188 188 #strip duplicated and empty strings from the description: 189 189 desc_els = [] 190 190 [desc_els.append(x) for x in desc.split(",") if (x and not desc_els.count(x))]