Code

r10820@tres: ted | 2006-01-29 16:56:50 -0800
[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 <libnr/nr-macros.h>
17 #include <libnr/nr-matrix.h>
19 #include "display/nr-arena-item.h"
20 #include "display/nr-arena.h"
21 #include "document.h"
23 #include "win32.h"
24 #include "system.h"
25 #include "extension/print.h"
26 #include <gtk/gtk.h>
28 /* Initialization */
30 namespace Inkscape {
31 namespace Extension {
32 namespace Internal {
34 static unsigned int SPWin32Modal = FALSE;
36 /**
37  * Callback function..  not a method
38  */
39 static void
40 my_gdk_event_handler (GdkEvent *event)
41 {
42         if (SPWin32Modal) {
43                 /* Win32 widget is modal, filter events */
44                 switch (event->type) {
45                 case GDK_NOTHING:
46                 case GDK_DELETE:
47                 case GDK_SCROLL:
48                 case GDK_BUTTON_PRESS:
49                 case GDK_2BUTTON_PRESS:
50                 case GDK_3BUTTON_PRESS:
51                 case GDK_BUTTON_RELEASE:
52                 case GDK_KEY_PRESS:
53                 case GDK_KEY_RELEASE:
54                 case GDK_DRAG_STATUS:
55                 case GDK_DRAG_ENTER:
56                 case GDK_DRAG_LEAVE:
57                 case GDK_DRAG_MOTION:
58                 case GDK_DROP_START:
59                 case GDK_DROP_FINISHED:
60                         return;
61                         break;
62                 default:
63                         break;
64                 }
65         }
66         gtk_main_do_event (event);
67 }
69 void
70 PrintWin32::main_init (int argc, char **argv, const char *name)
71 {
72         gdk_event_handler_set ((GdkEventFunc) my_gdk_event_handler, NULL, NULL);
73 }
75 void
76 PrintWin32::finish (void)
77 {
78 }
80 #define SP_FOREIGN_MAX_ITER 10
83 /**
84  * Callback function..  not a method
85  */
86 static VOID CALLBACK
87 my_timer (HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
88 {
89         int cdown = 0;
90         while ((cdown++ < SP_FOREIGN_MAX_ITER) && gdk_events_pending ()) {
91                 gtk_main_iteration_do (FALSE);
92         }
93         gtk_main_iteration_do (FALSE);
94 }
97 /* Platform detection */
99 gboolean
100 PrintWin32::is_os_wide()
102         static gboolean initialized = FALSE;
103         static gboolean is_wide = FALSE;
104         static OSVERSIONINFOA osver;
106         if ( !initialized )
107         {
108                 BOOL result;
110                 initialized = TRUE;
112                 memset (&osver, 0, sizeof(OSVERSIONINFOA));
113                 osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
114                 result = GetVersionExA (&osver);
115                 if (result)
116                 {
117                         if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT)
118                                 is_wide = TRUE;
119                 }
120                 // If we can't even call to get the version, fall back to ANSI API
121         }
123         return is_wide;
127 /* Printing */
129 PrintWin32::PrintWin32 (void)
131         /* Nothing here */
135 PrintWin32::~PrintWin32 (void)
137         DeleteDC (_hDC);
141 /**
142  * Callback function..  not a method
143  */
144 static UINT_PTR CALLBACK
145 print_hook (HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
147 #if 0
148         int cdown = 0;
149         while ((cdown++ < SP_FOREIGN_MAX_ITER) && gdk_events_pending ()) {
150                 gtk_main_iteration_do (FALSE);
151         }
152         gtk_main_iteration_do (FALSE);
153 #endif
154         return 0;
157 unsigned int
158 PrintWin32::setup (Inkscape::Extension::Print *mod)
160         HRESULT res;
161         PRINTDLG pd = {
162                 sizeof (PRINTDLG),
163                 NULL, /* hwndOwner */
164                 NULL, /* hDevMode */
165                 NULL, /* hDevNames */
166                 NULL, /* hDC */
167                 PD_NOPAGENUMS | PD_NOSELECTION | PD_RETURNDC | PD_USEDEVMODECOPIESANDCOLLATE, /* Flags */
168                 1, 1, 1, 1, /* nFromPage, nToPage, nMinPage, nMaxPage */
169                 1, /* nCoies */
170                 NULL, /* hInstance */
171                 0, /* lCustData */
172                 NULL, NULL, NULL, NULL, NULL, NULL
173         };
174         UINT_PTR timer;
176         SPWin32Modal = TRUE;
177         pd.Flags |= PD_ENABLEPRINTHOOK;
178         pd.lpfnPrintHook = print_hook;
179         timer = SetTimer (NULL, 0, 40, my_timer);
181         res = PrintDlg (&pd);
183         KillTimer (NULL, timer);
184         SPWin32Modal = FALSE;
186         if (!res) return FALSE;
188         _hDC = pd.hDC;
190 #if 0
191         caps = GetDeviceCaps (_hDC, RASTERCAPS);
192         if (caps & RC_BANDING) {
193                 printf ("needs banding\n");
194         }
195         if (caps & RC_BITBLT) {
196                 printf ("does bitblt\n");
197         }
198         if (caps & RC_DIBTODEV) {
199                 printf ("does dibtodev\n");
200         }
201         if (caps & RC_STRETCHDIB) {
202                 printf ("does stretchdib\n");
203         }
204 #endif
205         if (pd.hDevMode) {
206                 DEVMODE *devmodep;
207                 devmodep = (DEVMODE *)pd.hDevMode;
208                 if (devmodep->dmFields & DM_ORIENTATION) {
209                         _landscape = (devmodep->dmOrientation == DMORIENT_LANDSCAPE);
210                 }
211         }
213         return TRUE;
216 unsigned int
217 PrintWin32::begin (Inkscape::Extension::Print *mod, SPDocument *doc)
219         DOCINFO di = {
220                 sizeof (DOCINFO),
221                 NULL, /* lpszDocName */
222                 NULL, /* lpszOutput */
223                 NULL, /* lpszDatatype */
224                 0 /* DI_APPBANDING */ /* fwType */
225         };
226         int res;
228         _PageWidth = sp_document_width (doc);
229         _PageHeight = sp_document_height (doc);
231         di.lpszDocName = SP_DOCUMENT_NAME (doc);
233         SPWin32Modal = TRUE;
235         res = StartDoc (_hDC, &di);
236         res = StartPage (_hDC);
238         SPWin32Modal = FALSE;
240         return 0;
243 unsigned int
244 PrintWin32::finish (Inkscape::Extension::Print *mod)
246         int dpiX, dpiY;
247         int pPhysicalWidth, pPhysicalHeight;
248         int pPhysicalOffsetX, pPhysicalOffsetY;
249         int pPrintableWidth, pPrintableHeight;
250         float scalex, scaley;
251         int x0, y0, x1, y1;
252         int width, height;
253         NRMatrix affine;
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         affine.c[0] = scalex / 1.25;
296         affine.c[1] = 0.0;
297         affine.c[2] = 0.0;
298         affine.c[3] = scaley / 1.25;
299         affine.c[4] = 0.0;
300         affine.c[5] = 0.0;
302         nr_arena_item_set_transform (mod->root, &affine);
304         // Calculate printable area in device coordinates
305         x0 = pPhysicalOffsetX;
306         y0 = pPhysicalOffsetY;
307         x1 = x0 + pPrintableWidth;
308         y1 = y0 + pPrintableHeight;
309         x1 = MIN (x1, (int) (_PageWidth * scalex));
310         y1 = MIN (y1, (int) (_PageHeight * scaley));
312         width = x1 - x0;
313         height = y1 - y0;
315         px = nr_new (unsigned char, 4 * 64 * width);
316         sheight = 64;
318         /* Printing goes here */
319         for (row = 0; row < height; row += 64) {
320                 NRPixBlock pb;
321                 NRRectL bbox;
322                 NRGC gc(NULL);
323                 int num_rows;
324                 int i;
326                 num_rows = sheight;
327                 if ((row + num_rows) > height) num_rows = height - row;
329                 /* Set area of interest */
330                 bbox.x0 = x0;
331                 bbox.y0 = y0 + row;
332                 bbox.x1 = bbox.x0 + width;
333                 bbox.y1 = bbox.y0 + num_rows;
334                 /* Update to renderable state */
335                 nr_matrix_set_identity (&gc.transform);
336                 nr_arena_item_invoke_update (mod->root, &bbox, &gc, NR_ARENA_ITEM_STATE_ALL, NR_ARENA_ITEM_STATE_NONE);
338                 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);
340                 /* Blitter goes here */
341                 bmInfo.bmiHeader.biWidth = bbox.x1 - bbox.x0;
342                 bmInfo.bmiHeader.biHeight = -(bbox.y1 - bbox.y0);
344                 memset (px, 0xff, 4 * num_rows * width);
345                 /* Render */
346                 nr_arena_item_invoke_render (mod->root, &bbox, &pb, 0);
348                 /* Swap red and blue channels; we use RGBA, whereas
349                  * the Win32 GDI uses BGRx.
350                  */
351                 for ( i = 0 ; i < num_rows * width ; i++ ) {
352                         unsigned char temp=px[i*4];
353                         px[i*4] = px[i*4+2];
354                         px[i*4+2] = temp;
355                 }
357                 SetStretchBltMode(_hDC, COLORONCOLOR);
358                 res = StretchDIBits (_hDC,
359                                                 bbox.x0 - x0, bbox.y0 - y0, bbox.x1 - bbox.x0, bbox.y1 - bbox.y0,
360                                                 0, 0, bbox.x1 - bbox.x0, bbox.y1 - bbox.y0,
361                                                 px,
362                                                 &bmInfo,
363                         DIB_RGB_COLORS,
364                         SRCCOPY);
366                 /* Blitter ends here */
368                 nr_pixblock_release (&pb);
369         }
371         nr_free (px);
373         res = EndPage (_hDC);
374         res = EndDoc (_hDC);
376         SPWin32Modal = FALSE;
378         return 0;
381 /* File dialogs */
383 char *
384 PrintWin32::get_open_filename (unsigned char *dir, unsigned char *filter, unsigned char *title)
386         char fnbuf[4096] = {0};
387         OPENFILENAME ofn = {
388                 sizeof (OPENFILENAME),
389                 NULL, /* hwndOwner */
390                 NULL, /* hInstance */
391                 (const CHAR *)filter, /* lpstrFilter */
392                 NULL, /* lpstrCustomFilter */
393                 0, /* nMaxCustFilter  */
394                 1, /* nFilterIndex */
395                 fnbuf, /* lpstrFile */
396                 sizeof (fnbuf), /* nMaxFile */
397                 NULL, /* lpstrFileTitle */
398                 0, /* nMaxFileTitle */
399                 (const CHAR *)dir, /* lpstrInitialDir */
400                 (const CHAR *)title, /* lpstrTitle */
401                 OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY, /* Flags */
402                 0, /* nFileOffset */
403                 0, /* nFileExtension */
404                 NULL, /* lpstrDefExt */
405                 0, /* lCustData */
406                 NULL, /* lpfnHook */
407                 NULL /* lpTemplateName */
408         };
409         int retval;
410         UINT_PTR timer;
412         SPWin32Modal = TRUE;
413         timer = SetTimer (NULL, 0, 40, my_timer);
415         retval = GetOpenFileName (&ofn);
417         KillTimer (NULL, timer);
418         SPWin32Modal = FALSE;
420         if (!retval) {
421                 int errcode;
422                 errcode = CommDlgExtendedError();
423                 return NULL;
424     }
425         return g_strdup (fnbuf);
428 char *
429 PrintWin32::get_write_filename (unsigned char *dir, unsigned char *filter, unsigned char *title)
431         return NULL;
434 char *
435 PrintWin32::get_save_filename (unsigned char *dir, unsigned int *spns)
437         char fnbuf[4096] = {0};
438         OPENFILENAME ofn = {
439                 sizeof (OPENFILENAME),
440                 NULL, /* hwndOwner */
441                 NULL, /* hInstance */
442                 "Inkscape SVG (*.svg)\0*\0Plain SVG (*.svg)\0*\0", /* lpstrFilter */
443                 NULL, /* lpstrCustomFilter */
444                 0, /* nMaxCustFilter  */
445                 1, /* nFilterIndex */
446                 fnbuf, /* lpstrFile */
447                 sizeof (fnbuf), /* nMaxFile */
448                 NULL, /* lpstrFileTitle */
449                 0, /* nMaxFileTitle */
450                 (const CHAR *)dir, /* lpstrInitialDir */
451                 "Save document to file", /* lpstrTitle */
452                 OFN_HIDEREADONLY, /* Flags */
453                 0, /* nFileOffset */
454                 0, /* nFileExtension */
455                 NULL, /* lpstrDefExt */
456                 0, /* lCustData */
457                 NULL, /* lpfnHook */
458                 NULL /* lpTemplateName */
459         };
460         int retval;
461         UINT_PTR timer;
463         SPWin32Modal = TRUE;
464         timer = SetTimer (NULL, 0, 40, my_timer);
466         retval = GetSaveFileName (&ofn);
468         KillTimer (NULL, timer);
469         SPWin32Modal = FALSE;
471         if (!retval) {
472                 int errcode;
473                 errcode = CommDlgExtendedError();
474                 return NULL;
475     }
476         *spns = (ofn.nFilterIndex != 2);
477         return g_strdup (fnbuf);
480 #include "clear-n_.h"
482 void
483 PrintWin32::init (void)
485         Inkscape::Extension::Extension * ext;
487         /* SVG in */
488     ext = Inkscape::Extension::build_from_mem(
489                 "<inkscape-extension>\n"
490                         "<name>" N_("Windows 32-bit Print") "</name>\n"
491                         "<id>" SP_MODULE_KEY_PRINT_WIN32 "</id>\n"
492                         "<param name=\"textToPath\" type=\"boolean\">TRUE</param>\n"
493                         "<print/>\n"
494                 "</inkscape-extension>", new PrintWin32());
496         return;
499 }  /* namespace Internal */
500 }  /* namespace Extension */
501 }  /* namespace Inkscape */