import { forwardRef, useRef } from 'react' import * as gui from 'gui' import * as win from 'win' import * as ffi from 'ffi' import type { WStyle } from '../lib/react-qw/jsx.d.ts' const _user32 = win.LoadLibrary('user32.dll') const _gdi32 = win.LoadLibrary('gdi32.dll') if (!_user32 || !_gdi32) throw new Error('Failed to load user32/gdi32') function loadProc(lib: win.HMODULE, name: string): number { const ptr = win.GetProcAddress(lib, name) if (!ptr) throw new Error('Failed to load ' + name) return ptr } const GetDC_ = loadProc(_user32, 'GetDC') const ReleaseDC_ = loadProc(_user32, 'ReleaseDC') const SetDIBitsToDevice_ = loadProc(_gdi32, 'SetDIBitsToDevice') const FFI_PTR = ffi.FFI_TYPE_POINTER const FFI_U32 = ffi.FFI_TYPE_UINT32 const FFI_S32 = ffi.FFI_TYPE_SINT32 function makeBitmapInfo(w: number, h: number): ArrayBuffer { const bmi = new ArrayBuffer(40) const bv = new DataView(bmi) bv.setUint32(0, 40, true) bv.setInt32(4, w, true) bv.setInt32(8, -h, true) bv.setUint16(12, 1, true) bv.setUint16(14, 24, true) return bmi } export interface PdfCanvasProps { pixmap?: { data: ArrayBuffer; w: number; h: number } style?: WStyle } export const PdfCanvas = forwardRef( ({ pixmap, style }, ref) => { const canvasRef = useRef(null) const pixmapRef = useRef(pixmap) pixmapRef.current = pixmap return ( { canvasRef.current = h if (typeof ref === 'function') ref(h) else if (ref) (ref as React.RefObject).current = h }} onEvent={(e) => { const hwnd = e.hwnd if (e.msg === 0x14) return 1 if (e.msg === gui.WmMsg.PAINT) { const pm = pixmapRef.current if (!pm) return 0 const hdc = ffi.ffiCall(GetDC_, [ffi.FFI_TYPE_UINT64], [hwnd], ffi.FFI_TYPE_UINT64) if (hdc) { const bmi = makeBitmapInfo(pm.w, pm.h) ffi.ffiCall(SetDIBitsToDevice_, [ ffi.FFI_TYPE_UINT64, FFI_S32, FFI_S32, FFI_U32, FFI_U32, FFI_S32, FFI_S32, FFI_U32, FFI_U32, FFI_PTR, FFI_PTR, FFI_U32 ], [ hdc, 0, 0, pm.w, pm.h, 0, 0, 0, pm.h, pm.data, bmi, 0 ], FFI_S32) ffi.ffiCall(ReleaseDC_, [ffi.FFI_TYPE_UINT64, ffi.FFI_TYPE_UINT64], [hwnd, hdc], FFI_S32) } return 0 } return }} /> ) } )