Code

A simple layout document as to what, why and how is cppification.
[inkscape.git] / src / extension / internal / win32.cpp
1 /** @file
2  * @brief Windows-specific stuff
3  */
4 /* Author:
5  *   Lauris Kaplinski <lauris@kaplinski.com>
6  *
7  * This code is in public domain
8  */
10 #ifdef WIN32
12 #ifdef HAVE_CONFIG_H
13 # include "config.h"
14 #endif
16 #include <glib/gmem.h>
17 #include <libnr/nr-macros.h>
18 #include <2geom/transforms.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 = doc->getWidth ();
230     _PageHeight = doc->getHeight ();
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     unsigned char *px;
255     int sheight, row;
256     BITMAPINFO bmInfo = {
257         {
258             sizeof (BITMAPINFOHEADER), // bV4Size
259             64,      // biWidth
260             64,      // biHeight
261             1,       // biPlanes
262             32,      // biBitCount
263             BI_RGB,  // biCompression
264             0,       // biSizeImage
265             2835,    // biXPelsPerMeter
266             2835,    // biYPelsPerMeter
267             0,       // biClrUsed
268             0        // biClrImportant
269         },
270         { { 0, 0, 0, 0 } } // bmiColors
271     };
272     //RECT wrect;
273     int res;
275     SPWin32Modal = TRUE;
277     // Number of pixels per logical inch
278     dpiX = (int) GetDeviceCaps (_hDC, LOGPIXELSX);
279     dpiY = (int) GetDeviceCaps (_hDC, LOGPIXELSY);
280     // Size in pixels of the printable area
281     pPhysicalWidth = GetDeviceCaps (_hDC, PHYSICALWIDTH);
282     pPhysicalHeight = GetDeviceCaps (_hDC, PHYSICALHEIGHT);
283     // Top left corner of prontable area
284     pPhysicalOffsetX = GetDeviceCaps (_hDC, PHYSICALOFFSETX);
285     pPhysicalOffsetY = GetDeviceCaps (_hDC, PHYSICALOFFSETY);
286     // Size in pixels of the printable area
287     pPrintableWidth = GetDeviceCaps (_hDC, HORZRES);
288     pPrintableHeight = GetDeviceCaps (_hDC, VERTRES);
290     // Scaling from document to device
291     scalex = dpiX / 72.0;
292     scaley = dpiY / 72.0;
294     // We simply map document 0,0 to physical page 0,0
295     Geom::Matrix affine = Geom::Scale(scalex / 1.25, scaley / 1.25);
297     nr_arena_item_set_transform (mod->root, affine);
299     // Calculate printable area in device coordinates
300     x0 = pPhysicalOffsetX;
301     y0 = pPhysicalOffsetY;
302     x1 = x0 + pPrintableWidth;
303     y1 = y0 + pPrintableHeight;
304     x1 = MIN (x1, (int) (_PageWidth * scalex));
305     y1 = MIN (y1, (int) (_PageHeight * scaley));
307     width = x1 - x0;
308     height = y1 - y0;
310     px = g_new (unsigned char, 4 * 64 * width);
311     sheight = 64;
313     /* Printing goes here */
314     for (row = 0; row < height; row += 64) {
315         NRPixBlock pb;
316         NRRectL bbox;
317         NRGC gc(NULL);
318         int num_rows;
319         int i;
321         num_rows = sheight;
322         if ((row + num_rows) > height) num_rows = height - row;
324         /* Set area of interest */
325         bbox.x0 = x0;
326         bbox.y0 = y0 + row;
327         bbox.x1 = bbox.x0 + width;
328         bbox.y1 = bbox.y0 + num_rows;
329         /* Update to renderable state */
330         gc.transform.setIdentity();
331         nr_arena_item_invoke_update (mod->root, &bbox, &gc, NR_ARENA_ITEM_STATE_ALL, NR_ARENA_ITEM_STATE_NONE);
333         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);
335         /* Blitter goes here */
336         bmInfo.bmiHeader.biWidth = bbox.x1 - bbox.x0;
337         bmInfo.bmiHeader.biHeight = -(bbox.y1 - bbox.y0);
339         memset (px, 0xff, 4 * num_rows * width);
340         /* Render */
341         nr_arena_item_invoke_render (NULL, mod->root, &bbox, &pb, 0);
343         /* Swap red and blue channels; we use RGBA, whereas
344          * the Win32 GDI uses BGRx.
345          */
346         for ( i = 0 ; i < num_rows * width ; i++ ) {
347             unsigned char temp=px[i*4];
348             px[i*4] = px[i*4+2];
349             px[i*4+2] = temp;
350         }
352         SetStretchBltMode(_hDC, COLORONCOLOR);
353         res = StretchDIBits (_hDC,
354                         bbox.x0 - x0, bbox.y0 - y0, bbox.x1 - bbox.x0, bbox.y1 - bbox.y0,
355                         0, 0, bbox.x1 - bbox.x0, bbox.y1 - bbox.y0,
356                         px,
357                         &bmInfo,
358                         DIB_RGB_COLORS,
359                         SRCCOPY);
361         /* Blitter ends here */
363         nr_pixblock_release (&pb);
364     }
366     g_free (px);
368     res = EndPage (_hDC);
369     res = EndDoc (_hDC);
371     SPWin32Modal = FALSE;
373     return 0;
376 /* File dialogs */
378 char *
379 PrintWin32::get_open_filename (unsigned char *dir, unsigned char *filter, unsigned char *title)
381     char fnbuf[4096] = {0};
382     OPENFILENAME ofn = {
383         sizeof (OPENFILENAME),
384         NULL, /* hwndOwner */
385         NULL, /* hInstance */
386         (const CHAR *)filter, /* lpstrFilter */
387         NULL, /* lpstrCustomFilter */
388         0, /* nMaxCustFilter  */
389         1, /* nFilterIndex */
390         fnbuf, /* lpstrFile */
391         sizeof (fnbuf), /* nMaxFile */
392         NULL, /* lpstrFileTitle */
393         0, /* nMaxFileTitle */
394         (const CHAR *)dir, /* lpstrInitialDir */
395         (const CHAR *)title, /* lpstrTitle */
396         OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY, /* Flags */
397         0, /* nFileOffset */
398         0, /* nFileExtension */
399         NULL, /* lpstrDefExt */
400         0, /* lCustData */
401         NULL, /* lpfnHook */
402         NULL /* lpTemplateName */
403     };
404     int retval;
405     UINT_PTR timer;
407     SPWin32Modal = TRUE;
408     timer = SetTimer (NULL, 0, 40, my_timer);
410     retval = GetOpenFileName (&ofn);
412     KillTimer (NULL, timer);
413     SPWin32Modal = FALSE;
415     if (!retval) {
416         int errcode;
417         errcode = CommDlgExtendedError();
418         return NULL;
419     }
420     return g_strdup (fnbuf);
423 char *
424 PrintWin32::get_write_filename (unsigned char *dir, unsigned char *filter, unsigned char *title)
426     return NULL;
429 char *
430 PrintWin32::get_save_filename (unsigned char *dir, unsigned int *spns)
432     char fnbuf[4096] = {0};
433     OPENFILENAME ofn = {
434         sizeof (OPENFILENAME),
435         NULL, /* hwndOwner */
436         NULL, /* hInstance */
437         "Inkscape SVG (*.svg)\0*\0Plain SVG (*.svg)\0*\0", /* lpstrFilter */
438         NULL, /* lpstrCustomFilter */
439         0, /* nMaxCustFilter  */
440         1, /* nFilterIndex */
441         fnbuf, /* lpstrFile */
442         sizeof (fnbuf), /* nMaxFile */
443         NULL, /* lpstrFileTitle */
444         0, /* nMaxFileTitle */
445         (const CHAR *)dir, /* lpstrInitialDir */
446         "Save document to file", /* lpstrTitle */
447         OFN_HIDEREADONLY, /* Flags */
448         0, /* nFileOffset */
449         0, /* nFileExtension */
450         NULL, /* lpstrDefExt */
451         0, /* lCustData */
452         NULL, /* lpfnHook */
453         NULL /* lpTemplateName */
454     };
455     int retval;
456     UINT_PTR timer;
458     SPWin32Modal = TRUE;
459     timer = SetTimer (NULL, 0, 40, my_timer);
461     retval = GetSaveFileName (&ofn);
463     KillTimer (NULL, timer);
464     SPWin32Modal = FALSE;
466     if (!retval) {
467         int errcode;
468         errcode = CommDlgExtendedError();
469         return NULL;
470     }
471     *spns = (ofn.nFilterIndex != 2);
472     return g_strdup (fnbuf);
475 #include "clear-n_.h"
477 void
478 PrintWin32::init (void)
480     Inkscape::Extension::Extension * ext;
482     /* SVG in */
483     ext = Inkscape::Extension::build_from_mem(
484         "<inkscape-extension xmlns=\"" INKSCAPE_EXTENSION_URI "\">\n"
485             "<name>" N_("Windows 32-bit Print") "</name>\n"
486             "<id>" SP_MODULE_KEY_PRINT_WIN32 "</id>\n"
487             "<param name=\"textToPath\" type=\"boolean\">true</param>\n"
488             "<print/>\n"
489         "</inkscape-extension>", new PrintWin32());
491     return;
494 }  /* namespace Internal */
495 }  /* namespace Extension */
496 }  /* namespace Inkscape */
498 #endif // ifdef WIN32
500 /*
501   Local Variables:
502   mode:c++
503   c-file-style:"stroustrup"
504   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
505   indent-tabs-mode:nil
506   fill-column:99
507   End:
508 */
509 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :