Code

NR:: to Geom:: for most of src/extension/
[inkscape.git] / src / extension / internal / win32.cpp
1 #define __SP_MODULE_WIN32_C__
3 /*
4  * Windows stuff
5  *
6  * Author:
7  *   Lauris Kaplinski <lauris@kaplinski.com>
8  *
9  * This code is in public domain
10  */
12 #ifdef HAVE_CONFIG_H
13 # include "config.h"
14 #endif
16 #include <glib/gmem.h>
17 #include <libnr/nr-macros.h>
18 #include <libnr/nr-matrix.h>
20 #include "display/nr-arena-item.h"
21 #include "display/nr-arena.h"
22 #include "document.h"
24 #include "win32.h"
25 #include "extension/system.h"
26 #include "extension/print.h"
27 #include <gtk/gtk.h>
29 /* Initialization */
31 namespace Inkscape {
32 namespace Extension {
33 namespace Internal {
35 static unsigned int SPWin32Modal = FALSE;
37 /**
38  * Callback function..  not a method
39  */
40 static void
41 my_gdk_event_handler (GdkEvent *event)
42 {
43     if (SPWin32Modal) {
44         /* Win32 widget is modal, filter events */
45         switch (event->type) {
46         case GDK_NOTHING:
47         case GDK_DELETE:
48         case GDK_SCROLL:
49         case GDK_BUTTON_PRESS:
50         case GDK_2BUTTON_PRESS:
51         case GDK_3BUTTON_PRESS:
52         case GDK_BUTTON_RELEASE:
53         case GDK_KEY_PRESS:
54         case GDK_KEY_RELEASE:
55         case GDK_DRAG_STATUS:
56         case GDK_DRAG_ENTER:
57         case GDK_DRAG_LEAVE:
58         case GDK_DRAG_MOTION:
59         case GDK_DROP_START:
60         case GDK_DROP_FINISHED:
61             return;
62             break;
63         default:
64             break;
65         }
66     }
67     gtk_main_do_event (event);
68 }
70 void
71 PrintWin32::main_init (int argc, char **argv, const char *name)
72 {
73     gdk_event_handler_set ((GdkEventFunc) my_gdk_event_handler, NULL, NULL);
74 }
76 void
77 PrintWin32::finish (void)
78 {
79 }
81 #define SP_FOREIGN_MAX_ITER 10
84 /**
85  * Callback function..  not a method
86  */
87 static VOID CALLBACK
88 my_timer (HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
89 {
90     int cdown = 0;
91     while ((cdown++ < SP_FOREIGN_MAX_ITER) && gdk_events_pending ()) {
92         gtk_main_iteration_do (FALSE);
93     }
94     gtk_main_iteration_do (FALSE);
95 }
98 /* Platform detection */
100 gboolean
101 PrintWin32::is_os_wide()
103     static gboolean initialized = FALSE;
104     static gboolean is_wide = FALSE;
105     static OSVERSIONINFOA osver;
107     if ( !initialized )
108     {
109         BOOL result;
111         initialized = TRUE;
113         memset (&osver, 0, sizeof(OSVERSIONINFOA));
114         osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
115         result = GetVersionExA (&osver);
116         if (result)
117         {
118             if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT)
119                 is_wide = TRUE;
120         }
121         // If we can't even call to get the version, fall back to ANSI API
122     }
124     return is_wide;
128 /* Printing */
130 PrintWin32::PrintWin32 (void)
132     /* Nothing here */
136 PrintWin32::~PrintWin32 (void)
138     DeleteDC (_hDC);
142 /**
143  * Callback function..  not a method
144  */
145 static UINT_PTR CALLBACK
146 print_hook (HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
148 #if 0
149     int cdown = 0;
150     while ((cdown++ < SP_FOREIGN_MAX_ITER) && gdk_events_pending ()) {
151         gtk_main_iteration_do (FALSE);
152     }
153     gtk_main_iteration_do (FALSE);
154 #endif
155     return 0;
158 unsigned int
159 PrintWin32::setup (Inkscape::Extension::Print *mod)
161     HRESULT res;
162     PRINTDLG pd = {
163         sizeof (PRINTDLG),
164         NULL, /* hwndOwner */
165         NULL, /* hDevMode */
166         NULL, /* hDevNames */
167         NULL, /* hDC */
168         PD_NOPAGENUMS | PD_NOSELECTION | PD_RETURNDC | PD_USEDEVMODECOPIESANDCOLLATE, /* Flags */
169         1, 1, 1, 1, /* nFromPage, nToPage, nMinPage, nMaxPage */
170         1, /* nCoies */
171         NULL, /* hInstance */
172         0, /* lCustData */
173         NULL, NULL, NULL, NULL, NULL, NULL
174     };
175     UINT_PTR timer;
177     SPWin32Modal = TRUE;
178     pd.Flags |= PD_ENABLEPRINTHOOK;
179     pd.lpfnPrintHook = print_hook;
180     timer = SetTimer (NULL, 0, 40, my_timer);
182     res = PrintDlg (&pd);
184     KillTimer (NULL, timer);
185     SPWin32Modal = FALSE;
187     if (!res) return FALSE;
189     _hDC = pd.hDC;
191 #if 0
192     caps = GetDeviceCaps (_hDC, RASTERCAPS);
193     if (caps & RC_BANDING) {
194         printf ("needs banding\n");
195     }
196     if (caps & RC_BITBLT) {
197         printf ("does bitblt\n");
198     }
199     if (caps & RC_DIBTODEV) {
200         printf ("does dibtodev\n");
201     }
202     if (caps & RC_STRETCHDIB) {
203         printf ("does stretchdib\n");
204     }
205 #endif
206     if (pd.hDevMode) {
207         DEVMODE *devmodep;
208         devmodep = (DEVMODE *)pd.hDevMode;
209         if (devmodep->dmFields & DM_ORIENTATION) {
210             _landscape = (devmodep->dmOrientation == DMORIENT_LANDSCAPE);
211         }
212     }
214     return TRUE;
217 unsigned int
218 PrintWin32::begin (Inkscape::Extension::Print *mod, SPDocument *doc)
220     DOCINFO di = {
221         sizeof (DOCINFO),
222         NULL, /* lpszDocName */
223         NULL, /* lpszOutput */
224         NULL, /* lpszDatatype */
225         0 /* DI_APPBANDING */ /* fwType */
226     };
227     int res;
229     _PageWidth = sp_document_width (doc);
230     _PageHeight = sp_document_height (doc);
232     di.lpszDocName = SP_DOCUMENT_NAME (doc);
234     SPWin32Modal = TRUE;
236     res = StartDoc (_hDC, &di);
237     res = StartPage (_hDC);
239     SPWin32Modal = FALSE;
241     return 0;
244 unsigned int
245 PrintWin32::finish (Inkscape::Extension::Print *mod)
247     int dpiX, dpiY;
248     int pPhysicalWidth, pPhysicalHeight;
249     int pPhysicalOffsetX, pPhysicalOffsetY;
250     int pPrintableWidth, pPrintableHeight;
251     float scalex, scaley;
252     int x0, y0, x1, y1;
253     int width, height;
254     NR::Matrix affine;
255     unsigned char *px;
256     int sheight, row;
257     BITMAPINFO bmInfo = {
258         {
259             sizeof (BITMAPINFOHEADER), // bV4Size
260             64,      // biWidth
261             64,      // biHeight
262             1,       // biPlanes
263             32,      // biBitCount
264             BI_RGB,  // biCompression
265             0,       // biSizeImage
266             2835,    // biXPelsPerMeter
267             2835,    // biYPelsPerMeter
268             0,       // biClrUsed
269             0        // biClrImportant
270         },
271         { { 0, 0, 0, 0 } } // bmiColors
272     };
273     //RECT wrect;
274     int res;
276     SPWin32Modal = TRUE;
278     // Number of pixels per logical inch
279     dpiX = (int) GetDeviceCaps (_hDC, LOGPIXELSX);
280     dpiY = (int) GetDeviceCaps (_hDC, LOGPIXELSY);
281     // Size in pixels of the printable area
282     pPhysicalWidth = GetDeviceCaps (_hDC, PHYSICALWIDTH);
283     pPhysicalHeight = GetDeviceCaps (_hDC, PHYSICALHEIGHT);
284     // Top left corner of prontable area
285     pPhysicalOffsetX = GetDeviceCaps (_hDC, PHYSICALOFFSETX);
286     pPhysicalOffsetY = GetDeviceCaps (_hDC, PHYSICALOFFSETY);
287     // Size in pixels of the printable area
288     pPrintableWidth = GetDeviceCaps (_hDC, HORZRES);
289     pPrintableHeight = GetDeviceCaps (_hDC, VERTRES);
291     // Scaling from document to device
292     scalex = dpiX / 72.0;
293     scaley = dpiY / 72.0;
295     // We simply map document 0,0 to physical page 0,0
296     affine[0] = scalex / 1.25;
297     affine[1] = 0.0;
298     affine[2] = 0.0;
299     affine[3] = scaley / 1.25;
300     affine[4] = 0.0;
301     affine[5] = 0.0;
303     nr_arena_item_set_transform (mod->root, &affine);
305     // Calculate printable area in device coordinates
306     x0 = pPhysicalOffsetX;
307     y0 = pPhysicalOffsetY;
308     x1 = x0 + pPrintableWidth;
309     y1 = y0 + pPrintableHeight;
310     x1 = MIN (x1, (int) (_PageWidth * scalex));
311     y1 = MIN (y1, (int) (_PageHeight * scaley));
313     width = x1 - x0;
314     height = y1 - y0;
316     px = g_new (unsigned char, 4 * 64 * width);
317     sheight = 64;
319     /* Printing goes here */
320     for (row = 0; row < height; row += 64) {
321         NRPixBlock pb;
322         NRRectL bbox;
323         NRGC gc(NULL);
324         int num_rows;
325         int i;
327         num_rows = sheight;
328         if ((row + num_rows) > height) num_rows = height - row;
330         /* Set area of interest */
331         bbox.x0 = x0;
332         bbox.y0 = y0 + row;
333         bbox.x1 = bbox.x0 + width;
334         bbox.y1 = bbox.y0 + num_rows;
335         /* Update to renderable state */
336         gc.transform.set_identity();
337         nr_arena_item_invoke_update (mod->root, &bbox, &gc, NR_ARENA_ITEM_STATE_ALL, NR_ARENA_ITEM_STATE_NONE);
339         nr_pixblock_setup_extern (&pb, NR_PIXBLOCK_MODE_R8G8B8A8N, bbox.x0, bbox.y0, bbox.x1, bbox.y1, px, 4 * (bbox.x1 - bbox.x0), FALSE, FALSE);
341         /* Blitter goes here */
342         bmInfo.bmiHeader.biWidth = bbox.x1 - bbox.x0;
343         bmInfo.bmiHeader.biHeight = -(bbox.y1 - bbox.y0);
345         memset (px, 0xff, 4 * num_rows * width);
346         /* Render */
347         nr_arena_item_invoke_render (NULL, mod->root, &bbox, &pb, 0);
349         /* Swap red and blue channels; we use RGBA, whereas
350          * the Win32 GDI uses BGRx.
351          */
352         for ( i = 0 ; i < num_rows * width ; i++ ) {
353             unsigned char temp=px[i*4];
354             px[i*4] = px[i*4+2];
355             px[i*4+2] = temp;
356         }
358         SetStretchBltMode(_hDC, COLORONCOLOR);
359         res = StretchDIBits (_hDC,
360                         bbox.x0 - x0, bbox.y0 - y0, bbox.x1 - bbox.x0, bbox.y1 - bbox.y0,
361                         0, 0, bbox.x1 - bbox.x0, bbox.y1 - bbox.y0,
362                         px,
363                         &bmInfo,
364                         DIB_RGB_COLORS,
365                         SRCCOPY);
367         /* Blitter ends here */
369         nr_pixblock_release (&pb);
370     }
372     g_free (px);
374     res = EndPage (_hDC);
375     res = EndDoc (_hDC);
377     SPWin32Modal = FALSE;
379     return 0;
382 /* File dialogs */
384 char *
385 PrintWin32::get_open_filename (unsigned char *dir, unsigned char *filter, unsigned char *title)
387     char fnbuf[4096] = {0};
388     OPENFILENAME ofn = {
389         sizeof (OPENFILENAME),
390         NULL, /* hwndOwner */
391         NULL, /* hInstance */
392         (const CHAR *)filter, /* lpstrFilter */
393         NULL, /* lpstrCustomFilter */
394         0, /* nMaxCustFilter  */
395         1, /* nFilterIndex */
396         fnbuf, /* lpstrFile */
397         sizeof (fnbuf), /* nMaxFile */
398         NULL, /* lpstrFileTitle */
399         0, /* nMaxFileTitle */
400         (const CHAR *)dir, /* lpstrInitialDir */
401         (const CHAR *)title, /* lpstrTitle */
402         OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY, /* Flags */
403         0, /* nFileOffset */
404         0, /* nFileExtension */
405         NULL, /* lpstrDefExt */
406         0, /* lCustData */
407         NULL, /* lpfnHook */
408         NULL /* lpTemplateName */
409     };
410     int retval;
411     UINT_PTR timer;
413     SPWin32Modal = TRUE;
414     timer = SetTimer (NULL, 0, 40, my_timer);
416     retval = GetOpenFileName (&ofn);
418     KillTimer (NULL, timer);
419     SPWin32Modal = FALSE;
421     if (!retval) {
422         int errcode;
423         errcode = CommDlgExtendedError();
424         return NULL;
425     }
426     return g_strdup (fnbuf);
429 char *
430 PrintWin32::get_write_filename (unsigned char *dir, unsigned char *filter, unsigned char *title)
432     return NULL;
435 char *
436 PrintWin32::get_save_filename (unsigned char *dir, unsigned int *spns)
438     char fnbuf[4096] = {0};
439     OPENFILENAME ofn = {
440         sizeof (OPENFILENAME),
441         NULL, /* hwndOwner */
442         NULL, /* hInstance */
443         "Inkscape SVG (*.svg)\0*\0Plain SVG (*.svg)\0*\0", /* lpstrFilter */
444         NULL, /* lpstrCustomFilter */
445         0, /* nMaxCustFilter  */
446         1, /* nFilterIndex */
447         fnbuf, /* lpstrFile */
448         sizeof (fnbuf), /* nMaxFile */
449         NULL, /* lpstrFileTitle */
450         0, /* nMaxFileTitle */
451         (const CHAR *)dir, /* lpstrInitialDir */
452         "Save document to file", /* lpstrTitle */
453         OFN_HIDEREADONLY, /* Flags */
454         0, /* nFileOffset */
455         0, /* nFileExtension */
456         NULL, /* lpstrDefExt */
457         0, /* lCustData */
458         NULL, /* lpfnHook */
459         NULL /* lpTemplateName */
460     };
461     int retval;
462     UINT_PTR timer;
464     SPWin32Modal = TRUE;
465     timer = SetTimer (NULL, 0, 40, my_timer);
467     retval = GetSaveFileName (&ofn);
469     KillTimer (NULL, timer);
470     SPWin32Modal = FALSE;
472     if (!retval) {
473         int errcode;
474         errcode = CommDlgExtendedError();
475         return NULL;
476     }
477     *spns = (ofn.nFilterIndex != 2);
478     return g_strdup (fnbuf);
481 #include "clear-n_.h"
483 void
484 PrintWin32::init (void)
486     Inkscape::Extension::Extension * ext;
488     /* SVG in */
489     ext = Inkscape::Extension::build_from_mem(
490         "<inkscape-extension xmlns=\"" INKSCAPE_EXTENSION_URI "\">\n"
491             "<name>" N_("Windows 32-bit Print") "</name>\n"
492             "<id>" SP_MODULE_KEY_PRINT_WIN32 "</id>\n"
493             "<param name=\"textToPath\" type=\"boolean\">true</param>\n"
494             "<print/>\n"
495         "</inkscape-extension>", new PrintWin32());
497     return;
500 }  /* namespace Internal */
501 }  /* namespace Extension */
502 }  /* namespace Inkscape */