Code

Merge and cleanup of GSoC C++-ification project.
[inkscape.git] / src / extension / internal / win32.cpp
1 /** @file
2  * @brief Windows-specific stuff
3  */
4 /* Author:
5  *   Lauris Kaplinski <lauris@kaplinski.com>
6  *   Abhishek Sharma
7  *
8  * This code is in public domain
9  */
11 #ifdef WIN32
13 #ifdef HAVE_CONFIG_H
14 # include "config.h"
15 #endif
17 #include <glib/gmem.h>
18 #include <libnr/nr-macros.h>
19 #include <2geom/transforms.h>
21 #include "display/nr-arena-item.h"
22 #include "display/nr-arena.h"
23 #include "document.h"
25 #include "win32.h"
26 #include "extension/system.h"
27 #include "extension/print.h"
28 #include <gtk/gtk.h>
30 /* Initialization */
32 namespace Inkscape {
33 namespace Extension {
34 namespace Internal {
36 static unsigned int SPWin32Modal = FALSE;
38 /**
39  * Callback function..  not a method
40  */
41 static void
42 my_gdk_event_handler (GdkEvent *event)
43 {
44     if (SPWin32Modal) {
45         /* Win32 widget is modal, filter events */
46         switch (event->type) {
47         case GDK_NOTHING:
48         case GDK_DELETE:
49         case GDK_SCROLL:
50         case GDK_BUTTON_PRESS:
51         case GDK_2BUTTON_PRESS:
52         case GDK_3BUTTON_PRESS:
53         case GDK_BUTTON_RELEASE:
54         case GDK_KEY_PRESS:
55         case GDK_KEY_RELEASE:
56         case GDK_DRAG_STATUS:
57         case GDK_DRAG_ENTER:
58         case GDK_DRAG_LEAVE:
59         case GDK_DRAG_MOTION:
60         case GDK_DROP_START:
61         case GDK_DROP_FINISHED:
62             return;
63             break;
64         default:
65             break;
66         }
67     }
68     gtk_main_do_event (event);
69 }
71 void
72 PrintWin32::main_init (int argc, char **argv, const char *name)
73 {
74     gdk_event_handler_set ((GdkEventFunc) my_gdk_event_handler, NULL, NULL);
75 }
77 void
78 PrintWin32::finish (void)
79 {
80 }
82 #define SP_FOREIGN_MAX_ITER 10
85 /**
86  * Callback function..  not a method
87  */
88 static VOID CALLBACK
89 my_timer (HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
90 {
91     int cdown = 0;
92     while ((cdown++ < SP_FOREIGN_MAX_ITER) && gdk_events_pending ()) {
93         gtk_main_iteration_do (FALSE);
94     }
95     gtk_main_iteration_do (FALSE);
96 }
99 /* Platform detection */
101 gboolean
102 PrintWin32::is_os_wide()
104     static gboolean initialized = FALSE;
105     static gboolean is_wide = FALSE;
106     static OSVERSIONINFOA osver;
108     if ( !initialized )
109     {
110         BOOL result;
112         initialized = TRUE;
114         memset (&osver, 0, sizeof(OSVERSIONINFOA));
115         osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
116         result = GetVersionExA (&osver);
117         if (result)
118         {
119             if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT)
120                 is_wide = TRUE;
121         }
122         // If we can't even call to get the version, fall back to ANSI API
123     }
125     return is_wide;
129 /* Printing */
131 PrintWin32::PrintWin32 (void)
133     /* Nothing here */
137 PrintWin32::~PrintWin32 (void)
139     DeleteDC (_hDC);
143 /**
144  * Callback function..  not a method
145  */
146 static UINT_PTR CALLBACK
147 print_hook (HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
149 #if 0
150     int cdown = 0;
151     while ((cdown++ < SP_FOREIGN_MAX_ITER) && gdk_events_pending ()) {
152         gtk_main_iteration_do (FALSE);
153     }
154     gtk_main_iteration_do (FALSE);
155 #endif
156     return 0;
159 unsigned int
160 PrintWin32::setup (Inkscape::Extension::Print *mod)
162     HRESULT res;
163     PRINTDLG pd = {
164         sizeof (PRINTDLG),
165         NULL, /* hwndOwner */
166         NULL, /* hDevMode */
167         NULL, /* hDevNames */
168         NULL, /* hDC */
169         PD_NOPAGENUMS | PD_NOSELECTION | PD_RETURNDC | PD_USEDEVMODECOPIESANDCOLLATE, /* Flags */
170         1, 1, 1, 1, /* nFromPage, nToPage, nMinPage, nMaxPage */
171         1, /* nCoies */
172         NULL, /* hInstance */
173         0, /* lCustData */
174         NULL, NULL, NULL, NULL, NULL, NULL
175     };
176     UINT_PTR timer;
178     SPWin32Modal = TRUE;
179     pd.Flags |= PD_ENABLEPRINTHOOK;
180     pd.lpfnPrintHook = print_hook;
181     timer = SetTimer (NULL, 0, 40, my_timer);
183     res = PrintDlg (&pd);
185     KillTimer (NULL, timer);
186     SPWin32Modal = FALSE;
188     if (!res) return FALSE;
190     _hDC = pd.hDC;
192 #if 0
193     caps = GetDeviceCaps (_hDC, RASTERCAPS);
194     if (caps & RC_BANDING) {
195         printf ("needs banding\n");
196     }
197     if (caps & RC_BITBLT) {
198         printf ("does bitblt\n");
199     }
200     if (caps & RC_DIBTODEV) {
201         printf ("does dibtodev\n");
202     }
203     if (caps & RC_STRETCHDIB) {
204         printf ("does stretchdib\n");
205     }
206 #endif
207     if (pd.hDevMode) {
208         DEVMODE *devmodep;
209         devmodep = (DEVMODE *)pd.hDevMode;
210         if (devmodep->dmFields & DM_ORIENTATION) {
211             _landscape = (devmodep->dmOrientation == DMORIENT_LANDSCAPE);
212         }
213     }
215     return TRUE;
218 unsigned int
219 PrintWin32::begin (Inkscape::Extension::Print *mod, SPDocument *doc)
221     DOCINFO di = {
222         sizeof (DOCINFO),
223         NULL, /* lpszDocName */
224         NULL, /* lpszOutput */
225         NULL, /* lpszDatatype */
226         0 /* DI_APPBANDING */ /* fwType */
227     };
228     int res;
230     _PageWidth = doc->getWidth ();
231     _PageHeight = doc->getHeight ();
233     di.lpszDocName = doc->getName();
235     SPWin32Modal = TRUE;
237     res = StartDoc (_hDC, &di);
238     res = StartPage (_hDC);
240     SPWin32Modal = FALSE;
242     return 0;
245 unsigned int
246 PrintWin32::finish (Inkscape::Extension::Print *mod)
248     int dpiX, dpiY;
249     int pPhysicalWidth, pPhysicalHeight;
250     int pPhysicalOffsetX, pPhysicalOffsetY;
251     int pPrintableWidth, pPrintableHeight;
252     float scalex, scaley;
253     int x0, y0, x1, y1;
254     int width, height;
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     Geom::Matrix affine = Geom::Scale(scalex / 1.25, scaley / 1.25);
298     nr_arena_item_set_transform (mod->root, affine);
300     // Calculate printable area in device coordinates
301     x0 = pPhysicalOffsetX;
302     y0 = pPhysicalOffsetY;
303     x1 = x0 + pPrintableWidth;
304     y1 = y0 + pPrintableHeight;
305     x1 = MIN (x1, (int) (_PageWidth * scalex));
306     y1 = MIN (y1, (int) (_PageHeight * scaley));
308     width = x1 - x0;
309     height = y1 - y0;
311     px = g_new (unsigned char, 4 * 64 * width);
312     sheight = 64;
314     /* Printing goes here */
315     for (row = 0; row < height; row += 64) {
316         NRPixBlock pb;
317         NRRectL bbox;
318         NRGC gc(NULL);
319         int num_rows;
320         int i;
322         num_rows = sheight;
323         if ((row + num_rows) > height) num_rows = height - row;
325         /* Set area of interest */
326         bbox.x0 = x0;
327         bbox.y0 = y0 + row;
328         bbox.x1 = bbox.x0 + width;
329         bbox.y1 = bbox.y0 + num_rows;
330         /* Update to renderable state */
331         gc.transform.setIdentity();
332         nr_arena_item_invoke_update (mod->root, &bbox, &gc, NR_ARENA_ITEM_STATE_ALL, NR_ARENA_ITEM_STATE_NONE);
334         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);
336         /* Blitter goes here */
337         bmInfo.bmiHeader.biWidth = bbox.x1 - bbox.x0;
338         bmInfo.bmiHeader.biHeight = -(bbox.y1 - bbox.y0);
340         memset (px, 0xff, 4 * num_rows * width);
341         /* Render */
342         nr_arena_item_invoke_render (NULL, mod->root, &bbox, &pb, 0);
344         /* Swap red and blue channels; we use RGBA, whereas
345          * the Win32 GDI uses BGRx.
346          */
347         for ( i = 0 ; i < num_rows * width ; i++ ) {
348             unsigned char temp=px[i*4];
349             px[i*4] = px[i*4+2];
350             px[i*4+2] = temp;
351         }
353         SetStretchBltMode(_hDC, COLORONCOLOR);
354         res = StretchDIBits (_hDC,
355                         bbox.x0 - x0, bbox.y0 - y0, bbox.x1 - bbox.x0, bbox.y1 - bbox.y0,
356                         0, 0, bbox.x1 - bbox.x0, bbox.y1 - bbox.y0,
357                         px,
358                         &bmInfo,
359                         DIB_RGB_COLORS,
360                         SRCCOPY);
362         /* Blitter ends here */
364         nr_pixblock_release (&pb);
365     }
367     g_free (px);
369     res = EndPage (_hDC);
370     res = EndDoc (_hDC);
372     SPWin32Modal = FALSE;
374     return 0;
377 /* File dialogs */
379 char *
380 PrintWin32::get_open_filename (unsigned char *dir, unsigned char *filter, unsigned char *title)
382     char fnbuf[4096] = {0};
383     OPENFILENAME ofn = {
384         sizeof (OPENFILENAME),
385         NULL, /* hwndOwner */
386         NULL, /* hInstance */
387         (const CHAR *)filter, /* lpstrFilter */
388         NULL, /* lpstrCustomFilter */
389         0, /* nMaxCustFilter  */
390         1, /* nFilterIndex */
391         fnbuf, /* lpstrFile */
392         sizeof (fnbuf), /* nMaxFile */
393         NULL, /* lpstrFileTitle */
394         0, /* nMaxFileTitle */
395         (const CHAR *)dir, /* lpstrInitialDir */
396         (const CHAR *)title, /* lpstrTitle */
397         OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY, /* Flags */
398         0, /* nFileOffset */
399         0, /* nFileExtension */
400         NULL, /* lpstrDefExt */
401         0, /* lCustData */
402         NULL, /* lpfnHook */
403         NULL /* lpTemplateName */
404     };
405     int retval;
406     UINT_PTR timer;
408     SPWin32Modal = TRUE;
409     timer = SetTimer (NULL, 0, 40, my_timer);
411     retval = GetOpenFileName (&ofn);
413     KillTimer (NULL, timer);
414     SPWin32Modal = FALSE;
416     if (!retval) {
417         int errcode;
418         errcode = CommDlgExtendedError();
419         return NULL;
420     }
421     return g_strdup (fnbuf);
424 char *
425 PrintWin32::get_write_filename (unsigned char *dir, unsigned char *filter, unsigned char *title)
427     return NULL;
430 char *
431 PrintWin32::get_save_filename (unsigned char *dir, unsigned int *spns)
433     char fnbuf[4096] = {0};
434     OPENFILENAME ofn = {
435         sizeof (OPENFILENAME),
436         NULL, /* hwndOwner */
437         NULL, /* hInstance */
438         "Inkscape SVG (*.svg)\0*\0Plain SVG (*.svg)\0*\0", /* lpstrFilter */
439         NULL, /* lpstrCustomFilter */
440         0, /* nMaxCustFilter  */
441         1, /* nFilterIndex */
442         fnbuf, /* lpstrFile */
443         sizeof (fnbuf), /* nMaxFile */
444         NULL, /* lpstrFileTitle */
445         0, /* nMaxFileTitle */
446         (const CHAR *)dir, /* lpstrInitialDir */
447         "Save document to file", /* lpstrTitle */
448         OFN_HIDEREADONLY, /* Flags */
449         0, /* nFileOffset */
450         0, /* nFileExtension */
451         NULL, /* lpstrDefExt */
452         0, /* lCustData */
453         NULL, /* lpfnHook */
454         NULL /* lpTemplateName */
455     };
456     int retval;
457     UINT_PTR timer;
459     SPWin32Modal = TRUE;
460     timer = SetTimer (NULL, 0, 40, my_timer);
462     retval = GetSaveFileName (&ofn);
464     KillTimer (NULL, timer);
465     SPWin32Modal = FALSE;
467     if (!retval) {
468         int errcode;
469         errcode = CommDlgExtendedError();
470         return NULL;
471     }
472     *spns = (ofn.nFilterIndex != 2);
473     return g_strdup (fnbuf);
476 #include "clear-n_.h"
478 void
479 PrintWin32::init (void)
481     Inkscape::Extension::Extension * ext;
483     /* SVG in */
484     ext = Inkscape::Extension::build_from_mem(
485         "<inkscape-extension xmlns=\"" INKSCAPE_EXTENSION_URI "\">\n"
486             "<name>" N_("Windows 32-bit Print") "</name>\n"
487             "<id>" SP_MODULE_KEY_PRINT_WIN32 "</id>\n"
488             "<param name=\"textToPath\" type=\"boolean\">true</param>\n"
489             "<print/>\n"
490         "</inkscape-extension>", new PrintWin32());
492     return;
495 }  /* namespace Internal */
496 }  /* namespace Extension */
497 }  /* namespace Inkscape */
499 #endif // ifdef WIN32
501 /*
502   Local Variables:
503   mode:c++
504   c-file-style:"stroustrup"
505   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
506   indent-tabs-mode:nil
507   fill-column:99
508   End:
509 */
510 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :