Code

peeled back the gboolean code as it hit on some complexity theory principles...
[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 "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         NRMatrix 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.c[0] = scalex / 1.25;
297         affine.c[1] = 0.0;
298         affine.c[2] = 0.0;
299         affine.c[3] = scaley / 1.25;
300         affine.c[4] = 0.0;
301         affine.c[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                 nr_matrix_set_identity (&gc.transform);
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 (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>\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 */