home *** CD-ROM | disk | FTP | other *** search
/ Borland Programmer's Resource / Borland_Programmers_Resource_CD_1995.iso / code / wxwin140 / src / wx_dc.cc < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-19  |  110.1 KB  |  4,482 lines

  1. /*
  2.  * File:     wx_dc.cc
  3.  * Purpose:  Device context implementation
  4.  *
  5.  *                       wxWindows 1.40
  6.  * Copyright (c) 1993 Artificial Intelligence Applications Institute,
  7.  *                   The University of Edinburgh
  8.  *
  9.  *                     Author: Julian Smart
  10.  *                       Date: 18-4-93
  11.  *
  12.  * Permission to use, copy, modify, and distribute this software and its
  13.  * documentation for any purpose is hereby granted without fee, provided
  14.  * that the above copyright notice, author statement and this permission
  15.  * notice appear in all copies of this software and related documentation.
  16.  *
  17.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, EXPRESS,
  18.  * IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
  19.  * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
  20.  *
  21.  * IN NO EVENT SHALL THE ARTIFICIAL INTELLIGENCE APPLICATIONS INSTITUTE OR THE
  22.  * UNIVERSITY OF EDINBURGH BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT OR
  23.  * CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER RESULTING FROM
  24.  * LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF THE POSSIBILITY OF
  25.  * DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH
  26.  * THE USE OR PERFORMANCE OF THIS SOFTWARE.
  27.  */
  28.  
  29. #include <windows.h>
  30. #include <iostream.h>
  31. #include <fstream.h>
  32. #include <math.h>
  33. #include <stdio.h>
  34. #include <stdlib.h>
  35.  
  36. #ifdef wx_msw
  37. #include <commdlg.h>
  38. #endif
  39. #include <time.h>
  40.  
  41. #include "common.h"
  42. #include "wx_frame.h"
  43. #include "wx_dc.h"
  44. #include "wx_event.h"
  45. #include "wx_utils.h"
  46. #include "wx_canvs.h"
  47. #include "wx_dialg.h"
  48. #include "wx_main.h"
  49. #include "wx_privt.h"
  50.  
  51. #ifdef wx_x
  52. #include <netdb.h>
  53. #include <sys/file.h>
  54. #include <unistd.h>
  55. #include <pwd.h>
  56. // For AT&T C++ users
  57. int gethostname(char *host, unsigned const len);
  58. #endif
  59.  
  60. // Some global printer parameters
  61. char *wx_printer_command = "lpr";
  62. char *wx_preview_command = "ghostview";
  63. char *wx_printer_flags = NULL;
  64. char wx_printer_file[200];
  65. Bool wx_preview = TRUE;
  66. Bool wx_portrait = TRUE;
  67. float wx_printer_scale_x = 1.0;
  68. float wx_printer_scale_y = 1.0;
  69. float wx_printer_translate_x = 0.0;
  70. float wx_printer_translate_y = 0.0;
  71. Bool wx_print_to_file = FALSE;
  72.  
  73. // Declarations local to this file
  74.  
  75. #define YSCALE(y) (yorigin - (y))
  76.  
  77. #ifdef wx_x
  78. Bool XPrinterDialog(void);
  79. #endif
  80.  
  81. #define     wx_round(a)    (int)((a)+.5)
  82.  
  83. void wx_draw_open_spline(wxDC *dc, wxSpline *spline);
  84. void wx_draw_open_spline_ps(wxDC *dc, wxSpline *s);
  85.  
  86. void wx_quadratic_spline(float a1, float b1, float a2, float b2,
  87.                          float a3, float b3, float a4, float b4);
  88. void wx_clear_stack(void);
  89. int wx_spline_pop(float *x1, float *y1, float *x2, float *y2, float *x3,
  90.         float *y3, float *x4, float *y4);
  91. void wx_spline_push(float x1, float y1, float x2, float y2, float x3, float y3,
  92.           float x4, float y4);
  93. static Bool wx_spline_add_point(int x, int y);
  94. static void wx_spline_draw_point_array(wxDC *dc);
  95. wxSpline *wx_make_spline(int x1, int y1, int x2, int y2, int x3, int y3);
  96.  
  97.  
  98. // Default constructor
  99. wxDC::wxDC(void)
  100. {
  101. }
  102.  
  103. /*
  104.  * Create a new dc from an old dc
  105.  *
  106.  */
  107.  
  108. wxDC::wxDC(wxDC *old_dc)
  109. {
  110. #ifdef wx_msw
  111.   clipping = FALSE;
  112.   dont_delete = FALSE;
  113.   window_ext_x = VIEWPORT_EXTENT;
  114.   window_ext_y = VIEWPORT_EXTENT;
  115.   device = wxDEVICE_WINDOWS;
  116.   old_bitmap = NULL;
  117.   old_pen = NULL;
  118.   old_brush = NULL;
  119.   old_font = NULL;
  120. #endif
  121. #ifdef wx_x
  122.   device = wxDEVICE_PIXMAP;
  123.   current_colour = NULL;
  124. #endif
  125.   canvas = NULL;
  126.  
  127.   ok = FALSE;
  128.   pstream = NULL;
  129.   title = NULL;
  130.   filename = NULL;
  131.  
  132.   current_logical_function = -1;
  133.   font = NULL;
  134.   logical_origin_x = 0;
  135.   logical_origin_y = 0;
  136.  
  137.   device_origin_x = 0;
  138.   device_origin_y = 0;
  139.  
  140.   logical_scale_x = 1.0;
  141.   logical_scale_y = 1.0;
  142.  
  143.   user_scale_x = 1.0;
  144.   user_scale_y = 1.0;
  145.  
  146.   mapping_mode = MM_TEXT;
  147.  
  148.   current_pen = NULL;
  149.   current_brush = NULL;
  150.   current_background_brush = wxWHITE_BRUSH;
  151.   current_text_foreground = wxBLACK;
  152.   current_text_background = NULL;
  153.  
  154.  
  155. #ifdef wx_x
  156. #ifdef wx_xview
  157.   Xv_Screen screen = xv_get(xview_server, SERVER_NTH_SCREEN, 0);
  158.   Xv_Window root_window = xv_get(screen, XV_ROOT);
  159.   Display *dpy = (Display *)xv_get(root_window, XV_DISPLAY);
  160. #endif
  161. #ifdef wx_motif
  162.   Display *dpy = XtDisplay(wxTheApp->topLevel);
  163. #endif
  164.  
  165.   XGCValues gcvalues;
  166.   gcvalues.foreground = BlackPixel(dpy,
  167.                    DefaultScreen(dpy));
  168.   gcvalues.background = WhitePixel(dpy,
  169.                    DefaultScreen(dpy));
  170.   gcvalues.graphics_exposures = False;
  171.   gcvalues.line_width = 1;
  172.   gc = XCreateGC(dpy, RootWindow(dpy,
  173.          DefaultScreen(dpy)),
  174.     GCForeground | GCBackground | GCGraphicsExposures | GCLineWidth, 
  175.     &gcvalues);
  176.  
  177. #ifdef wx_motif
  178.   gcBacking = XCreateGC(dpy, RootWindow(dpy,
  179.          DefaultScreen(dpy)),
  180.     GCForeground | GCBackground | GCGraphicsExposures | GCLineWidth, 
  181.     &gcvalues);
  182. #endif
  183.  
  184.   background_pixel = gcvalues.background;
  185.   ok = TRUE;
  186.   current_colour = NULL;
  187.   selected_pixmap = NULL;
  188. #endif
  189. #ifdef wx_msw
  190.   wxWnd *wnd = NULL;
  191.   if (old_dc->canvas)
  192.     wnd = (wxWnd *)old_dc->canvas->handle;
  193.  
  194.   HDC dc = NULL;
  195.   if (old_dc->cdc)
  196.     dc = old_dc->cdc;
  197.   else
  198.     dc = GetDC(wnd->handle);
  199.  
  200.   cdc = ::CreateCompatibleDC(dc);
  201.   ok = (cdc != NULL);
  202.  
  203.   if (!old_dc->cdc)
  204.     ReleaseDC(wnd->handle, dc);
  205. #endif
  206.  
  207.   Colour = wxColourDisplay();
  208.   SetBrush(wxWHITE_BRUSH);
  209.   SetPen(wxBLACK_PEN);
  210. }
  211.  
  212. wxDC::wxDC(wxCanvas *the_canvas)
  213. {
  214.   canvas = the_canvas;
  215. #ifdef wx_msw
  216.   device = wxDEVICE_WINDOWS;
  217. #endif
  218. #ifdef wx_x
  219.   device = wxDEVICE_CANVAS;
  220. #endif
  221.   font = NULL;
  222.  
  223.   logical_origin_x = 0;
  224.   logical_origin_y = 0;
  225.  
  226.   device_origin_x = 0;
  227.   device_origin_y = 0;
  228.  
  229.   logical_scale_x = 1.0;
  230.   logical_scale_y = 1.0;
  231.  
  232.   user_scale_x = 1.0;
  233.   user_scale_y = 1.0;
  234.  
  235.   mapping_mode = MM_TEXT;
  236.  
  237.   pstream = NULL;
  238.   title = NULL;
  239.   filename = NULL;
  240. #ifdef wx_x
  241.   XGCValues gcvalues;
  242.   gcvalues.foreground = BlackPixel(the_canvas->display,
  243.                    DefaultScreen(the_canvas->display));
  244.   gcvalues.background = WhitePixel(the_canvas->display,
  245.                    DefaultScreen(the_canvas->display));
  246.   gcvalues.graphics_exposures = False;
  247.   gcvalues.line_width = 1;
  248.   gc = XCreateGC(the_canvas->display, RootWindow(the_canvas->display,
  249.          DefaultScreen(the_canvas->display)),
  250.     GCForeground | GCBackground | GCGraphicsExposures | GCLineWidth, 
  251.     &gcvalues);
  252. #ifdef wx_motif
  253.   gcBacking = XCreateGC(the_canvas->display, RootWindow(the_canvas->display,
  254.          DefaultScreen(the_canvas->display)),
  255.     GCForeground | GCBackground | GCGraphicsExposures | GCLineWidth, 
  256.     &gcvalues);
  257. #endif
  258.  
  259.   background_pixel = gcvalues.background;
  260.   ok = TRUE;
  261.   current_colour = NULL;
  262. #endif
  263. #ifdef wx_msw
  264.   old_bitmap = NULL;
  265.   old_pen = NULL;
  266.   old_brush = NULL;
  267.   old_font = NULL;
  268.   dont_delete = FALSE;
  269.   cdc = NULL;
  270.   clipping = FALSE;
  271.   ok = TRUE;
  272.   window_ext_x = VIEWPORT_EXTENT;
  273.   window_ext_y = VIEWPORT_EXTENT;
  274.  
  275.   wxWnd *wnd = (wxWnd *)the_canvas->handle;
  276.   HDC dc = GetDC(wnd->handle);
  277.   SetMapMode(MM_TEXT);
  278.  
  279.   ReleaseDC(wnd->handle, dc);
  280. #endif
  281.   current_logical_function = -1;
  282.  
  283.   current_pen = NULL;
  284.   current_brush = NULL;
  285.   current_background_brush = wxWHITE_BRUSH;
  286.   current_text_foreground = wxBLACK;
  287.   current_text_background = NULL;
  288.   Colour = wxColourDisplay();
  289.   SetBrush(wxWHITE_BRUSH);
  290.   SetPen(wxBLACK_PEN);
  291. }
  292.  
  293. wxDC::wxDC(char *driver_name, char *device_name, char *file, Bool interactive)
  294. {
  295.   wx_interactive = interactive;
  296.   canvas = NULL;
  297.   font = NULL;
  298. #ifdef wx_msw
  299.   if (device_name && strcmp(device_name, "PostScript") == 0)
  300.     device = wxDEVICE_EPS;
  301.   else device = wxDEVICE_WINDOWS;
  302.  
  303.   cdc = NULL;
  304.   old_bitmap = NULL;
  305.   old_pen = NULL;
  306.   old_brush = NULL;
  307.   old_font = NULL;
  308.   dont_delete = FALSE;
  309.   clipping = FALSE;
  310. #endif
  311. #ifdef wx_x
  312.   if (!device_name || strcmp(device_name, "PostScript") == 0)
  313.     device = wxDEVICE_EPS;
  314.   else { ok = FALSE; return; }
  315. #endif
  316.  
  317.   logical_origin_x = 0;
  318.   logical_origin_y = 0;
  319.  
  320.   device_origin_x = 0;
  321.   device_origin_y = 0;
  322.  
  323.   logical_scale_x = 1.0;
  324.   logical_scale_y = 1.0;
  325.  
  326.   user_scale_x = 1.0;
  327.   user_scale_y = 1.0;
  328.  
  329.   mapping_mode = MM_TEXT;
  330.  
  331.   yorigin = 792;  // For EPS output
  332.   min_x = 1000.0;
  333.   min_y = 1000.0;
  334.   max_x = -1000.0;
  335.   max_y = -1000.0;
  336.   title = NULL;
  337.   if (file)
  338.     filename = copystring(file);
  339.   else filename = NULL;
  340.  
  341.   pstream = NULL;
  342.  
  343. #ifdef wx_x
  344.   if (interactive)
  345.     ok = XPrinterDialog();
  346.   if (!ok)
  347.     return;
  348.  
  349.   if (interactive && (wx_preview || (!file && !wx_print_to_file)))
  350.   {
  351.     struct passwd *who = getpwuid(getuid());
  352.     strcpy(wx_printer_file, "/tmp/preview_");
  353.     strcat(wx_printer_file, who->pw_name);
  354.     strcat(wx_printer_file, ".ps");
  355.     file = wx_printer_file;
  356.   }
  357. #endif
  358.   if (device == wxDEVICE_EPS)
  359.   {
  360.     if (!file)
  361.     {
  362.       file = wxFileSelector("Enter PostScript file name", NULL, "", "ps", "*.ps");
  363.       if (!file)
  364.       {
  365.         ok = FALSE;
  366.         return;
  367.       }
  368.       strcpy(wx_printer_file, file);
  369.       ok = TRUE;
  370.     }
  371.     else strcpy(wx_printer_file, file);
  372.  
  373.     pstream = new ofstream(wx_printer_file);
  374.     if (!pstream)
  375.     {
  376.       (void)wxMessageBox("Error", "Cannot open file!", wxOK);
  377.       ok = FALSE;
  378.       return;
  379.     }
  380.     ok = TRUE;
  381.   }
  382. #ifdef wx_msw
  383.   else
  384.   {
  385.    if (!driver_name || !device_name || !file)
  386.    {
  387.      PRINTDLG pd;
  388.     
  389.      pd.lStructSize = sizeof( PRINTDLG );
  390.      pd.hwndOwner=NULL;
  391.      pd.hDevMode=(HANDLE)NULL;
  392.      pd.hDevNames=(HANDLE)NULL;
  393.      pd.Flags=PD_RETURNDC | PD_NOSELECTION | PD_NOPAGENUMS;
  394.      pd.nFromPage=0;
  395.      pd.nToPage=0;
  396.      pd.nMinPage=0;
  397.      pd.nMaxPage=0;
  398.      pd.nCopies=1;
  399.      pd.hInstance=(HINSTANCE)NULL;
  400.  
  401.      if ( PrintDlg( &pd ) != 0 )
  402.      {
  403.        cdc = pd.hDC;
  404.        ok = TRUE;
  405.      }
  406.      else
  407.      {
  408.        ok = FALSE;
  409.        return;
  410.      }
  411.  
  412.      dont_delete = TRUE; // ??? WHY???
  413.    }
  414.    else
  415.    {
  416.      cdc = CreateDC(driver_name, device_name, file, NULL);
  417.      ok = TRUE;
  418.    }
  419.    if (cdc)
  420.    {
  421.      int width = GetDeviceCaps(cdc, VERTRES);
  422.      int height = GetDeviceCaps(cdc, HORZRES);
  423.      SetMapMode(MM_TEXT);
  424.    }
  425.   }
  426. #endif
  427.   current_logical_function = -1;
  428.   current_pen = NULL;
  429.   current_brush = NULL;
  430.   current_background_brush = wxWHITE_BRUSH;
  431.   current_text_foreground = wxBLACK;
  432.   current_text_background = NULL;
  433.   Colour = wxColourDisplay();
  434. #ifdef wx_x
  435.   current_colour = NULL;
  436. #endif
  437.   SetBrush(wxBLACK_BRUSH);
  438.   SetPen(wxBLACK_PEN);
  439. }
  440.  
  441. wxDC::~wxDC(void)
  442. {
  443.   if (pstream)
  444.     delete pstream;
  445.   if (title)
  446.     delete title;
  447.   if (filename)
  448.     delete filename;
  449. #ifdef wx_msw
  450.   if (cdc)
  451.   {
  452.     SelectOldObjects(cdc);
  453.     DeleteDC(cdc);
  454.   }
  455. #endif
  456. }
  457.  
  458. #ifdef wx_msw
  459. // This will select current objects out of the DC,
  460. // which is what you have to do before deleting the
  461. // DC.
  462. void wxDC::SelectOldObjects(HDC dc)
  463. {
  464.   if (dc)
  465.   {
  466.     if (old_bitmap)
  467.       ::SelectObject(dc, old_bitmap);
  468.     if (old_pen)
  469.       ::SelectObject(dc, old_pen);
  470.     if (old_brush)
  471.       ::SelectObject(dc, old_brush);
  472.     if (old_font)
  473.       ::SelectObject(dc, old_font);
  474.   }
  475. }
  476. #endif
  477.  
  478. void wxDC::SetClippingRegion(float cx, float cy, float cw, float ch)
  479. {
  480.   switch (device)
  481.   {
  482. #ifdef wx_x
  483.     case wxDEVICE_CANVAS:
  484.     {
  485.       if (canvas)
  486.       {
  487.         XRectangle rects[1];
  488.  
  489.         rects[0].x = XLOG2DEV(cx); rects[0].y = YLOG2DEV(cy);
  490.         rects[0].width = XLOG2DEVREL(cw); rects[0].height = YLOG2DEVREL(ch);
  491.         XSetClipRectangles(canvas->display, gc, 0, 0, rects, 1, Unsorted);
  492. #ifdef wx_motif
  493.         if (canvas->is_retained)
  494.     {
  495.           rects[0].x = XLOG2DEV_2(cx); rects[0].y = YLOG2DEV_2(cy);
  496.           rects[0].width = XLOG2DEVREL(cw); rects[0].height = YLOG2DEVREL(ch);
  497.           XSetClipRectangles(canvas->display, gcBacking, 0, 0, rects, 1, Unsorted);
  498.     }
  499. #endif
  500.       }
  501.       break;
  502.     }
  503. #endif
  504.     case wxDEVICE_EPS:
  505.     {
  506.       clipping = TRUE;
  507.       *pstream << "gsave\n";
  508.       *pstream << "newpath\n";
  509.       *pstream << cx << " " << YSCALE(cy) << " moveto\n";
  510.       *pstream << cx+cw << " " << YSCALE(cy) << " lineto\n";
  511.       *pstream << cx+cw << " " << YSCALE(cy + ch) << " lineto\n";
  512.       *pstream << cx << " " << YSCALE(cy + ch) << " lineto\n";
  513.       *pstream << "closepath clip newpath\n";
  514.       break;
  515.     }
  516. #ifdef wx_msw
  517.     case wxDEVICE_WINDOWS:
  518.     {
  519.       clipping = TRUE;
  520.       clip_x1 = (int)cx;
  521.       clip_y1 = (int)cy;
  522.       clip_x2 = (int)(cx + cw);
  523.       clip_y2 = (int)(cy + ch);
  524.  
  525.       HDC dc = NULL;
  526.       wxWnd *wnd = NULL;
  527.       if (canvas) wnd = (wxWnd *)canvas->handle;
  528.       if (cdc)
  529.         dc = cdc;
  530.       else if (wnd)
  531.         dc = GetDC(wnd->handle);
  532.  
  533.       DoClipping(dc);
  534.  
  535.       if (!cdc)
  536.         ReleaseDC(wnd->handle, dc);
  537.       break;
  538.     }
  539. #endif
  540.   }
  541. }
  542.  
  543. #ifdef wx_msw
  544. void wxDC::DoClipping(HDC dc)
  545. {
  546.   if (clipping && dc)
  547.   {
  548.     int x_off = 0;
  549.     int y_off = 0;
  550.     if (canvas)
  551.     {
  552.       wxWnd *wnd = (wxWnd *)canvas->handle;
  553.  
  554.       wnd->CalcScrolledPosition(0, 0, &x_off, &y_off);
  555.     }
  556. //    HRGN rgn = CreateRectRgn(XLOG2DEV(clip_x1 + x_off), YLOG2DEV(clip_y1 + y_off),
  557. //                          XLOG2DEV(clip_x2 + x_off), YLOG2DEV(clip_y2 + y_off));
  558.  
  559. //    SelectClipRgn(dc, rgn);
  560. //    DeleteObject(rgn);
  561.     IntersectClipRect(dc, XLOG2DEV(clip_x1 + x_off), YLOG2DEV(clip_y1 + y_off),
  562.                           XLOG2DEV(clip_x2 + x_off), YLOG2DEV(clip_y2 + y_off));
  563.   }
  564. }
  565. #endif
  566.  
  567. void wxDC::DestroyClippingRegion(void)
  568. {
  569.   switch (device)
  570.   {
  571. #ifdef wx_x
  572.     case wxDEVICE_CANVAS:
  573.     {
  574.       if (canvas)
  575.       {
  576.         XGCValues gc_val;
  577.         gc_val.clip_mask = None;
  578.         XChangeGC(canvas->display, gc, GCClipMask, &gc_val);
  579. #ifdef wx_motif
  580.         if (canvas->is_retained)
  581.     {
  582.           XChangeGC(canvas->display, gcBacking, GCClipMask, &gc_val);
  583.     }
  584. #endif
  585. #ifdef wx_xview
  586.         if (canvas->xrects)
  587.           XSetClipRectangles(canvas->display, gc, 0, 0, canvas->xrects->rect_array,
  588.                            canvas->xrects->count, Unsorted);
  589. #endif
  590.       }
  591.       break;
  592.     }
  593. #endif
  594.     case wxDEVICE_EPS:
  595.     {
  596.       if (clipping)
  597.       {
  598.         clipping = FALSE;
  599.         *pstream << "grestore\n";
  600.       }
  601.       break;
  602.     }
  603. #ifdef wx_msw
  604.     case wxDEVICE_WINDOWS:
  605.     {
  606.       HDC dc = NULL;
  607.       wxWnd *wnd = NULL;
  608.       if (canvas)
  609.         wnd = (wxWnd *)canvas->handle;
  610.       if (cdc)
  611.         dc = cdc;
  612.       else if (wnd)
  613.         dc = GetDC(wnd->handle);
  614.  
  615.       if (clipping && dc)
  616.       {
  617. //        SelectClipRgn(dc, NULL);
  618.         HRGN rgn = CreateRectRgn(0, 0, 32000, 32000);
  619.         SelectClipRgn(dc, rgn);
  620.         DeleteObject(rgn);
  621.       }
  622.       clipping = FALSE;
  623.  
  624.       if (!cdc)
  625.         ReleaseDC(wnd->handle, dc);
  626.       break;
  627.     }
  628. #endif
  629.   }
  630. }
  631.  
  632. void wxDC::Clear(void)
  633. {
  634.   switch (device)
  635.   {
  636. #ifdef wx_x
  637.     case wxDEVICE_CANVAS:
  638.     {
  639.       if (canvas)
  640.       {
  641. #ifdef wx_xview
  642.         // If we're not in the middle of a paint event...
  643.         if (!canvas->xrects || !canvas->is_retained)
  644.           XClearWindow(canvas->display, canvas->xwindow);
  645. #endif
  646. #ifdef wx_motif
  647.         int w, h;
  648.         canvas->GetSize(&w, &h);
  649.  
  650.         if (canvas->hScroll)
  651.           w = canvas->hExtent;
  652.         if (canvas->vScroll)
  653.           h = canvas->vExtent;
  654.  
  655.         if (canvas->is_retained)
  656.         {
  657.           w = canvas->pixmapWidth;
  658.           h = canvas->pixmapHeight;
  659.         }
  660.  
  661.         SetBrush(current_background_brush);
  662.         XFillRectangle(canvas->display, canvas->xwindow, gc, 0, 0, w, h);
  663.  
  664.         if (canvas->is_retained)
  665.           XFillRectangle(canvas->display, canvas->backingPixmap, gcBacking, 0, 0, w, h);
  666. #endif
  667.       }
  668.       break;
  669.     }
  670. #endif
  671.     case wxDEVICE_EPS:
  672.     {
  673.       break;
  674.     }
  675. #ifdef wx_msw
  676.     case wxDEVICE_WINDOWS:
  677.     {
  678.       if (canvas)
  679.       {
  680.         HDC dc = NULL;
  681.         wxWnd *wnd = (wxWnd *)canvas->handle;
  682.         if (cdc)
  683.           dc = cdc;
  684.         else
  685.           dc = GetDC(wnd->handle);
  686.  
  687.         RECT rect;
  688.  
  689.         GetClientRect(wnd->handle, &rect);
  690.         int mode = ::SetMapMode(dc, MM_TEXT);
  691.  
  692.         DWORD colour = GetBkColor(dc);
  693.         HBRUSH brush = CreateSolidBrush(colour);
  694.         FillRect(dc, &rect, brush);
  695.         DeleteObject(brush);
  696.  
  697.         ::SetMapMode(dc, MM_ANISOTROPIC);
  698.         SetViewportExtEx(dc, VIEWPORT_EXTENT, VIEWPORT_EXTENT, NULL);
  699.         SetWindowExtEx(dc, window_ext_x, window_ext_y, NULL);
  700.  
  701.         if (!cdc)
  702.           ReleaseDC(wnd->handle, dc);
  703.       }
  704.       break;
  705.     }
  706. #endif
  707.   }
  708. }
  709.  
  710. void wxDC::DrawLine(float x1, float y1, float x2, float y2)
  711. {
  712.   switch (device)
  713.   {
  714. #ifdef wx_x
  715.     case wxDEVICE_CANVAS:
  716.     {
  717.       if (canvas)
  718.       {
  719.         if (current_pen)
  720.           SetPen(current_pen);
  721.         XDrawLine(canvas->display, canvas->xwindow, gc, XLOG2DEV(x1), YLOG2DEV(y1),
  722.                   XLOG2DEV(x2), YLOG2DEV(y2));
  723. #ifdef wx_motif
  724.         if (canvas->is_retained)
  725.           XDrawLine(canvas->display, canvas->backingPixmap, gcBacking, XLOG2DEV_2(x1), YLOG2DEV_2(y1),
  726.                     XLOG2DEV_2(x2), YLOG2DEV_2(y2));
  727. #endif
  728.       }
  729.       break;
  730.     }
  731. #endif
  732.     case wxDEVICE_EPS:
  733.     {
  734.       if (current_pen) SetPen(current_pen);
  735.       *pstream << "newpath\n";
  736.       *pstream << x1 << " " << YSCALE(y1) << " moveto\n";
  737.       *pstream << x2 << " " << YSCALE(y2) << " lineto\n";
  738.       *pstream << "stroke\n";
  739.       CalcBoundingBox(x1, YSCALE(y1));
  740.       CalcBoundingBox(x2, YSCALE(y2));
  741.       break;
  742.     }
  743. #ifdef wx_msw
  744.     case wxDEVICE_WINDOWS:
  745.     {
  746.       int xx1 = (int)x1;
  747.       int yy1 = (int)y1;
  748.       int xx2 = (int)x2;
  749.       int yy2 = (int)y2;
  750.  
  751.       wxWnd *wnd = NULL;
  752.       if (canvas)
  753.       {
  754.         wnd = (wxWnd *)canvas->handle;
  755.         wnd->CalcScrolledPosition((int)x1, (int)y1, &xx1, &yy1);
  756.         wnd->CalcScrolledPosition((int)x2, (int)y2, &xx2, &yy2);
  757.       }
  758.       HDC dc = NULL;
  759.       if (cdc)
  760.         dc = cdc;
  761.       else if (wnd)
  762.         dc = GetDC(wnd->handle);
  763.  
  764.       (void)MoveToEx(dc, XLOG2DEV(xx1), YLOG2DEV(yy1), NULL);
  765.       (void)LineTo(dc, XLOG2DEV(xx2), YLOG2DEV(yy2));
  766.  
  767.       if (!cdc)
  768.         ReleaseDC(wnd->handle, dc);
  769.       break;
  770.     }
  771. #endif
  772.   }
  773. }
  774.  
  775. void wxDC::DrawPoint(float x, float y)
  776. {
  777.   switch (device)
  778.   {
  779. #ifdef wx_x
  780.     case wxDEVICE_CANVAS:
  781.     {
  782.       if (canvas)
  783.       {
  784.         if (current_pen)
  785.           SetPen(current_pen);
  786.  
  787.         XDrawPoint(canvas->display, canvas->xwindow, gc, XLOG2DEV(x), YLOG2DEV(y));
  788. #ifdef wx_motif
  789.         if (canvas->is_retained)
  790.           XDrawPoint(canvas->display, canvas->backingPixmap, gcBacking, XLOG2DEV_2(x), YLOG2DEV_2(y));
  791. #endif
  792.       }
  793.       break;
  794.     }
  795. #endif
  796.     case wxDEVICE_EPS:
  797.     {
  798.       if (current_pen) SetPen(current_pen);
  799.       *pstream << "newpath\n";
  800.       *pstream << x << " " << YSCALE(y) << " moveto\n";
  801.       *pstream << x << " " << YSCALE(y) << " lineto\n";
  802.       *pstream << "stroke\n";
  803.       CalcBoundingBox(x, YSCALE(y));
  804.       break;
  805.     }
  806. #ifdef wx_msw
  807.     case wxDEVICE_WINDOWS:
  808.     {
  809.       wxWnd *wnd = NULL;
  810.  
  811.       int xx1 = (int)x;
  812.       int yy1 = (int)y;
  813.       if (canvas)
  814.       {
  815.         wnd = (wxWnd *)canvas->handle;
  816.         wnd->CalcScrolledPosition((int)x, (int)y, &xx1, &yy1);
  817.       }
  818.  
  819.       HDC dc = NULL;
  820.       if (cdc)
  821.         dc = cdc;
  822.       else
  823.         dc = GetDC(wnd->handle);
  824.  
  825.       (void)MoveTo(dc, XLOG2DEV(xx1), YLOG2DEV(yy1));
  826.       (void)LineTo(dc, XLOG2DEV(xx1), YLOG2DEV(yy1));
  827.  
  828.       if (!cdc)
  829.         ReleaseDC(wnd->handle, dc);
  830.       break;
  831.     }
  832. #endif
  833.   }
  834. }
  835.  
  836. void wxDC::DrawPolygon(int n, wxPoint points[], float xoffset, float yoffset)
  837. {
  838.   switch (device)
  839.   {
  840. #ifdef wx_x
  841.     case wxDEVICE_CANVAS:
  842.     {
  843.       if (canvas)
  844.       {
  845.         XPoint *xpoints1 = new XPoint[n];
  846.         XPoint *xpoints2 = new XPoint[n];
  847.         int i;
  848.         for (i = 0; i < n; i++)
  849.         {
  850.           xpoints1[i].x = XLOG2DEV(points[i].x + xoffset);
  851.           xpoints1[i].y = YLOG2DEV(points[i].y + yoffset);
  852.           xpoints2[i].x = XLOG2DEV_2(points[i].x + xoffset);
  853.           xpoints2[i].y = YLOG2DEV_2(points[i].y + yoffset);
  854.         }
  855.  
  856.         if (current_brush && current_brush->style != wxTRANSPARENT)
  857.         {
  858.           SetBrush(current_brush);
  859.           XFillPolygon(canvas->display, canvas->xwindow, gc, xpoints1, n, Convex, 0);
  860. #ifdef wx_motif
  861.           if (canvas->is_retained)
  862.             XFillPolygon(canvas->display, canvas->backingPixmap, gcBacking, xpoints2, n, Convex, 0);
  863. #endif
  864.         }
  865.  
  866.         if (current_pen && current_pen->style != wxTRANSPARENT)
  867.         {
  868.           SetPen(current_pen);
  869.           XDrawLines(canvas->display, canvas->xwindow, gc, xpoints1, n, 0);
  870. #ifdef wx_motif
  871.           if (canvas->is_retained)
  872.             XDrawLines(canvas->display, canvas->backingPixmap, gcBacking, xpoints2, n, 0);
  873. #endif
  874.         }
  875.  
  876.         delete[] xpoints1;
  877.         delete[] xpoints2;
  878.       }
  879.       break;
  880.     }
  881. #endif
  882.     case wxDEVICE_EPS:
  883.     {
  884.       if (n > 0)
  885.       {
  886.         if (current_brush && current_brush->style != wxTRANSPARENT)
  887.         {
  888.           SetBrush(current_brush);
  889.           *pstream << "newpath\n";
  890.  
  891.           float xx = points[0].x + xoffset;
  892.           float yy = YSCALE(points[0].y + yoffset);
  893.           *pstream << xx << " " << yy << " moveto\n";
  894.           CalcBoundingBox(xx, yy);
  895.  
  896.           int i;
  897.           for (i = 1; i < n; i++)
  898.       {
  899.             xx = points[i].x + xoffset;
  900.             yy = YSCALE(points[i].y + yoffset);
  901.             *pstream << xx << " " << yy << " lineto\n";
  902.             CalcBoundingBox(xx, yy);
  903.       }
  904.           *pstream << "fill\n";
  905.     }
  906.  
  907.         if (current_pen && current_pen->style != wxTRANSPARENT)
  908.         {
  909.           SetPen(current_pen);
  910.           *pstream << "newpath\n";
  911.  
  912.           float xx = points[0].x + xoffset;
  913.           float yy = YSCALE(points[0].y + yoffset);
  914.           *pstream << xx << " " << yy << " moveto\n";
  915.           CalcBoundingBox(xx, yy);
  916.  
  917.           int i;
  918.           for (i = 1; i < n; i++)
  919.       {
  920.             xx = points[i].x + xoffset;
  921.             yy = YSCALE(points[i].y + yoffset);
  922.             *pstream << xx << " " << yy << " lineto\n";
  923.             CalcBoundingBox(xx, yy);
  924.       }
  925.           *pstream << "stroke\n";
  926.     }
  927.  
  928.       }
  929.       break;
  930.     }
  931. #ifdef wx_msw
  932.     case wxDEVICE_WINDOWS:
  933.     {
  934.       int xoffset1 = 0;
  935.       int yoffset1 = 0;
  936.       wxWnd *wnd = NULL;
  937.  
  938.       if (canvas)
  939.       {
  940.         wnd = (wxWnd *)canvas->handle;
  941.         wnd->CalcScrolledPosition(0, 0, &xoffset1, &yoffset1);
  942.       }
  943.  
  944.       xoffset1 += (int)xoffset; yoffset1 += (int)yoffset;
  945.  
  946.       HDC dc = NULL;
  947.       if (cdc)
  948.         dc = cdc;
  949.       else
  950.         dc = GetDC(wnd->handle);
  951.  
  952.       POINT *cpoints = new POINT[n];
  953.       int i;
  954.       for (i = 0; i < n; i++)
  955.       {
  956.         cpoints[i].x = (int)(XLOG2DEV(points[i].x + xoffset1));
  957.         cpoints[i].y = (int)(YLOG2DEV(points[i].y + yoffset1));
  958.       }
  959.  
  960.       (void)Polygon(dc, cpoints, n);
  961.  
  962.       if (!cdc)
  963.         ReleaseDC(wnd->handle, dc);
  964.  
  965.       delete[] cpoints;
  966.       break;
  967.     }
  968. #endif
  969.   }
  970. }
  971.  
  972. void wxDC::DrawPolygon(wxList *list, float xoffset, float yoffset)
  973. {
  974.   switch (device)
  975.   {
  976. #ifdef wx_x
  977.     case wxDEVICE_CANVAS:
  978.     {
  979.       if (canvas)
  980.       {
  981.         if (current_pen)
  982.           SetPen(current_pen);
  983.  
  984.         int n = list->Number();
  985.         wxNode *current = list->First();
  986.     
  987.         XPoint *xpoints1 = new XPoint[n];
  988.         XPoint *xpoints2 = new XPoint[n];
  989.         int i;
  990.         for (i = 0; i < n; i++)
  991.         {
  992.           wxPoint *point = (wxPoint *)current->Data();
  993.           xpoints1[i].x = XLOG2DEV(point->x + xoffset);
  994.           xpoints1[i].y = YLOG2DEV(point->y + yoffset);
  995.           xpoints2[i].x = XLOG2DEV_2(point->x + xoffset);
  996.           xpoints2[i].y = YLOG2DEV_2(point->y + yoffset);
  997.           current = current->Next();
  998.         }
  999.  
  1000.         if (current_brush && current_brush->style != wxTRANSPARENT)
  1001.         {
  1002.           SetBrush(current_brush);
  1003.           XFillPolygon(canvas->display, canvas->xwindow, gc, xpoints1, n, Convex, 0);
  1004. #ifdef wx_motif
  1005.           if (canvas->is_retained)
  1006.             XFillPolygon(canvas->display, canvas->backingPixmap, gcBacking, xpoints2, n, Convex, 0);
  1007. #endif
  1008.         }
  1009.  
  1010.         if (current_pen && current_pen->style != wxTRANSPARENT)
  1011.         {
  1012.           SetPen(current_pen);
  1013.           XDrawLines(canvas->display, canvas->xwindow, gc, xpoints1, n, 0);
  1014. #ifdef wx_motif
  1015.           if (canvas->is_retained)
  1016.             XDrawLines(canvas->display, canvas->backingPixmap, gcBacking, xpoints2, n, 0);
  1017. #endif
  1018.         }
  1019.  
  1020.         delete[] xpoints1;
  1021.         delete[] xpoints2;
  1022.       }
  1023.       break;
  1024.     }
  1025. #endif
  1026.     case wxDEVICE_EPS:
  1027.     {
  1028.       int n = list->Number();
  1029.  
  1030.       if (n > 0)
  1031.       {
  1032.         if (current_brush && current_brush->style != wxTRANSPARENT)
  1033.         {
  1034.           SetBrush(current_brush);
  1035.  
  1036.           *pstream << "newpath\n";
  1037.  
  1038.           wxNode *node = list->First();
  1039.           wxPoint *point = (wxPoint *)node->Data();
  1040.           float xx = point->x + xoffset;
  1041.           float yy = YSCALE(point->y + yoffset);
  1042.  
  1043.           *pstream << xx << " " << yy << " moveto\n";
  1044.           CalcBoundingBox(xx, yy);
  1045.  
  1046.           node = node->Next();
  1047.  
  1048.           while (node)
  1049.           {
  1050.             point = (wxPoint *)node->Data();
  1051.             xx = point->x + xoffset;
  1052.             yy = YSCALE(point->y + yoffset);
  1053.             *pstream << xx << " " << yy << " lineto\n";
  1054.             CalcBoundingBox(xx, yy);
  1055.             node = node->Next();
  1056.           }
  1057.           *pstream << "closepath\nfill\n";
  1058.         }
  1059.  
  1060.         if (current_pen && current_pen->style != wxTRANSPARENT)
  1061.         {
  1062.           SetPen(current_pen);
  1063.  
  1064.           *pstream << "newpath\n";
  1065.  
  1066.           wxNode *node = list->First();
  1067.           wxPoint *point = (wxPoint *)node->Data();
  1068.  
  1069.           float xx = point->x + xoffset;
  1070.           float yy = YSCALE(point->y + yoffset);
  1071.           *pstream << xx << " " << yy << " moveto\n";
  1072.           CalcBoundingBox(xx, yy);
  1073.  
  1074.           node = node->Next();
  1075.  
  1076.           while (node)
  1077.           {
  1078.             point = (wxPoint *)node->Data();
  1079.             xx = point->x + xoffset;
  1080.             yy = YSCALE(point->y + yoffset);
  1081.             *pstream << xx << " " << yy << " lineto\n";
  1082.             CalcBoundingBox(xx, yy);
  1083.  
  1084.             node = node->Next();
  1085.           }
  1086.           *pstream << "closepath\nstroke\n";
  1087.         }
  1088.       }
  1089.       break;
  1090.     }
  1091. #ifdef wx_msw
  1092.     case wxDEVICE_WINDOWS:
  1093.     {
  1094.       int xoffset1 = 0;
  1095.       int yoffset1 = 0;
  1096.       wxWnd *wnd = NULL;
  1097.  
  1098.       if (canvas)
  1099.       {
  1100.         wnd = (wxWnd *)canvas->handle;
  1101.         wnd->CalcScrolledPosition(0, 0, &xoffset1, &yoffset1);
  1102.       }
  1103.       xoffset1 += (int)xoffset; yoffset1 += (int)yoffset;
  1104.  
  1105.       HDC dc = NULL;
  1106.       if (cdc)
  1107.         dc = cdc;
  1108.       else
  1109.         dc = GetDC(wnd->handle);
  1110.  
  1111.       POINT *cpoints = new POINT[list->Number()];
  1112.       int i;
  1113.       wxNode *node = list->First();
  1114.       for (i = 0; i < list->Number(); i++)
  1115.       {
  1116.         wxPoint *point = (wxPoint *)node->Data();
  1117.         cpoints[i].x = (int)(XLOG2DEV(point->x + xoffset1));
  1118.         cpoints[i].y = (int)(YLOG2DEV(point->y + yoffset1));
  1119.         node = node->Next();
  1120.       }
  1121.  
  1122.       (void)Polygon(dc, cpoints, list->Number());
  1123.  
  1124.       if (!cdc)
  1125.         ReleaseDC(wnd->handle, dc);
  1126.  
  1127.       delete[] cpoints;
  1128.       break;
  1129.     }
  1130. #endif
  1131.   }
  1132. }
  1133.  
  1134. void wxDC::DrawLines(int n, wxPoint points[], float xoffset, float yoffset)
  1135. {
  1136.   switch (device)
  1137.   {
  1138. #ifdef wx_x
  1139.     case wxDEVICE_CANVAS:
  1140.     {
  1141.       if (canvas)
  1142.       {
  1143.         XPoint *xpoints1 = new XPoint[n];
  1144.         XPoint *xpoints2 = new XPoint[n];
  1145.         int i;
  1146.         for (i = 0; i < n; i++)
  1147.         {
  1148.           xpoints1[i].x = XLOG2DEV(points[i].x + xoffset);
  1149.           xpoints1[i].y = YLOG2DEV(points[i].y + yoffset);
  1150.           xpoints2[i].x = XLOG2DEV_2(points[i].x + xoffset);
  1151.           xpoints2[i].y = YLOG2DEV_2(points[i].y + yoffset);
  1152.         }
  1153.  
  1154.         if (current_pen && current_pen->style != wxTRANSPARENT)
  1155.         {
  1156.           SetPen(current_pen);
  1157.           XDrawLines(canvas->display, canvas->xwindow, gc, xpoints1, n, 0);
  1158. #ifdef wx_motif
  1159.           if (canvas->is_retained)
  1160.             XDrawLines(canvas->display, canvas->backingPixmap, gcBacking, xpoints2, n, 0);
  1161. #endif
  1162.         }
  1163.  
  1164.         delete[] xpoints1;
  1165.         delete[] xpoints2;
  1166.       }
  1167.       break;
  1168.     }
  1169. #endif
  1170.     case wxDEVICE_EPS:
  1171.     {
  1172.       if (n > 0)
  1173.       {
  1174.         if (current_pen) SetPen(current_pen);
  1175.  
  1176.         *pstream << "newpath\n";
  1177.  
  1178.         float xx = points[0].x + xoffset;
  1179.         float yy = YSCALE(points[0].y + yoffset);
  1180.         *pstream << xx << " " << yy << " moveto\n";
  1181.         CalcBoundingBox(xx, yy);
  1182.  
  1183.         int i;
  1184.         for (i = 1; i < n; i++)
  1185.     {
  1186.           xx = points[i].x + xoffset;
  1187.           yy = YSCALE(points[i].y + yoffset);
  1188.           *pstream << xx << " " << yy << " lineto\n";
  1189.           CalcBoundingBox(xx, yy);
  1190.     }
  1191.         *pstream << "stroke\n";
  1192.  
  1193.       }
  1194.       break;
  1195.     }
  1196. #ifdef wx_msw
  1197.    case wxDEVICE_WINDOWS:
  1198.    {
  1199.       int xoffset1 = 0;
  1200.       int yoffset1 = 0;
  1201.       wxWnd *wnd = NULL;
  1202.  
  1203.       if (canvas)
  1204.       {
  1205.         wnd = (wxWnd *)canvas->handle;
  1206.         wnd->CalcScrolledPosition(0, 0, &xoffset1, &yoffset1);
  1207.       }
  1208.       xoffset1 += (int)xoffset; yoffset1 += (int)yoffset;
  1209.  
  1210.       HDC dc = NULL;
  1211.       if (cdc)
  1212.         dc = cdc;
  1213.       else
  1214.         dc = GetDC(wnd->handle);
  1215.  
  1216.       POINT *cpoints = new POINT[n];
  1217.       int i;
  1218.       for (i = 0; i < n; i++)
  1219.       {
  1220.         cpoints[i].x = (int)(XLOG2DEV(points[i].x + xoffset1));
  1221.         cpoints[i].y = (int)(YLOG2DEV(points[i].y + yoffset1));
  1222.       }
  1223.  
  1224.       (void)Polyline(dc, cpoints, n);
  1225.  
  1226.       if (!cdc)
  1227.         ReleaseDC(wnd->handle, dc);
  1228.  
  1229.       delete[] cpoints;
  1230.       break;
  1231.     }
  1232. #endif
  1233.   }
  1234. }
  1235.  
  1236. void wxDC::DrawLines(wxList *list, float xoffset, float yoffset)
  1237. {
  1238.   switch (device)
  1239.   {
  1240. #ifdef wx_x
  1241.     case wxDEVICE_CANVAS:
  1242.     {
  1243.  
  1244.       if (canvas)
  1245.       {
  1246.         if (current_pen)
  1247.           SetPen(current_pen);
  1248.  
  1249.         int n = list->Number();
  1250.         wxNode *current = list->First();
  1251.  
  1252.         XPoint *xpoints1 = new XPoint[n];
  1253.         XPoint *xpoints2 = new XPoint[n];
  1254.         int i;
  1255.         for (i = 0; i < n; i++)
  1256.         {
  1257.           wxPoint *point = (wxPoint *)current->Data();
  1258.           xpoints1[i].x = XLOG2DEV(point->x + xoffset);
  1259.           xpoints1[i].y = YLOG2DEV(point->y + yoffset);
  1260.           xpoints2[i].x = XLOG2DEV_2(point->x + xoffset);
  1261.           xpoints2[i].y = YLOG2DEV_2(point->y + yoffset);
  1262.           current = current->Next();
  1263.         }
  1264.  
  1265.         XDrawLines(canvas->display, canvas->xwindow, gc, xpoints1, n, 0);
  1266. #ifdef wx_motif
  1267.         if (canvas->is_retained)
  1268.           XDrawLines(canvas->display, canvas->backingPixmap, gcBacking, xpoints2, n, 0);
  1269. #endif
  1270.         delete[] xpoints1;
  1271.         delete[] xpoints2;
  1272.       }
  1273.       break;
  1274.     }
  1275. #endif
  1276.     case wxDEVICE_EPS:
  1277.     {
  1278.       int n = list->Number();
  1279.  
  1280.       if (n > 0)
  1281.       {
  1282.         if (current_pen) SetPen(current_pen);
  1283.         *pstream << "newpath\n";
  1284.  
  1285.         wxNode *node = list->First();
  1286.         wxPoint *point = (wxPoint *)node->Data();
  1287.  
  1288.         float xx = point->x + xoffset;
  1289.         float yy = YSCALE(point->y + yoffset);
  1290.         CalcBoundingBox(xx, yy);
  1291.  
  1292.         *pstream << xx << " " << yy << " moveto\n";
  1293.         node = node->Next();
  1294.  
  1295.         while (node)
  1296.     {
  1297.           point = (wxPoint *)node->Data();
  1298.  
  1299.           xx = point->x + xoffset;
  1300.           yy = YSCALE(point->y + yoffset);
  1301.           CalcBoundingBox(xx, yy);
  1302.  
  1303.           *pstream << xx << " " << yy << " lineto\n";
  1304.           node = node->Next();
  1305.     }
  1306.         *pstream << "stroke\n";
  1307.       }
  1308.       break;
  1309.     }
  1310. #ifdef wx_msw
  1311.     case wxDEVICE_WINDOWS:
  1312.     {
  1313.       int xoffset1 = 0;
  1314.       int yoffset1 = 0;
  1315.       wxWnd *wnd = NULL;
  1316.  
  1317.       if (canvas)
  1318.       {
  1319.         wnd = (wxWnd *)canvas->handle;
  1320.         wnd->CalcScrolledPosition(0, 0, &xoffset1, &yoffset1);
  1321.       }
  1322.       xoffset1 += (int)xoffset; yoffset1 += (int)yoffset;
  1323.  
  1324.       HDC dc = NULL;
  1325.       if (cdc)
  1326.         dc = cdc;
  1327.       else
  1328.         dc = GetDC(wnd->handle);
  1329.  
  1330.       POINT *cpoints = new POINT[list->Number()];
  1331.       int i;
  1332.       wxNode *node = list->First();
  1333.       for (i = 0; i < list->Number(); i++)
  1334.       {
  1335.         wxPoint *point = (wxPoint *)node->Data();
  1336.         cpoints[i].x = (int)(XLOG2DEV(point->x + xoffset1));
  1337.         cpoints[i].y = (int)(YLOG2DEV(point->y + yoffset1));
  1338.         node = node->Next();
  1339.       }
  1340.  
  1341.       (void)Polyline(dc, cpoints, list->Number());
  1342.  
  1343.       if (!cdc)
  1344.         ReleaseDC(wnd->handle, dc);
  1345.  
  1346.       delete[] cpoints;
  1347.       break;
  1348.     }
  1349. #endif
  1350.   }
  1351. }
  1352.  
  1353. void wxDC::DrawRectangle(float x, float y, float width, float height)
  1354. {
  1355.   switch (device)
  1356.   {
  1357. #ifdef wx_x
  1358.     case wxDEVICE_CANVAS:
  1359.     {
  1360.       if (canvas)
  1361.       {
  1362.         if (current_brush && current_brush->style != wxTRANSPARENT)
  1363.         {
  1364.           SetBrush(current_brush);
  1365.           XFillRectangle(canvas->display, canvas->xwindow, gc, XLOG2DEV(x), YLOG2DEV(y),
  1366.                          XLOG2DEVREL(width), YLOG2DEVREL(height));
  1367. #ifdef wx_motif
  1368.           if (canvas->is_retained)
  1369.             XFillRectangle(canvas->display, canvas->backingPixmap, gcBacking, XLOG2DEV_2(x), YLOG2DEV_2(y),
  1370.                            XLOG2DEVREL(width), YLOG2DEVREL(height));
  1371. #endif
  1372.         }
  1373.  
  1374.         if (current_pen && current_pen->style != wxTRANSPARENT)
  1375.         {
  1376.           SetPen(current_pen);
  1377.           XDrawRectangle(canvas->display, canvas->xwindow, gc, XLOG2DEV(x), YLOG2DEV(y),
  1378.                          XLOG2DEVREL(width), YLOG2DEVREL(height));
  1379. #ifdef wx_motif
  1380.           if (canvas->is_retained)
  1381.             XDrawRectangle(canvas->display, canvas->backingPixmap, gcBacking, XLOG2DEV_2(x), YLOG2DEV_2(y),
  1382.                          XLOG2DEVREL(width), YLOG2DEVREL(height));
  1383. #endif
  1384.         }
  1385.       }
  1386.       break;
  1387.     }
  1388. #endif
  1389.     case wxDEVICE_EPS:
  1390.     {
  1391.       if (current_brush && current_brush->style != wxTRANSPARENT)
  1392.       {
  1393.         SetBrush(current_brush);
  1394.       
  1395.         *pstream << "newpath\n";
  1396.         *pstream << x << " " << YSCALE(y) << " moveto\n";
  1397.         *pstream << x+width << " " << YSCALE(y) << " lineto\n";
  1398.         *pstream << x+width << " " << YSCALE(y+height) << " lineto\n";
  1399.         *pstream << x << " " << YSCALE(y+height) << " lineto\n";
  1400.         *pstream << "closepath\n";
  1401.         *pstream << "fill\n";
  1402.  
  1403.         CalcBoundingBox(x, YSCALE(y));
  1404.         CalcBoundingBox(x+width, YSCALE(y+height));
  1405.       }
  1406.       if (current_pen && current_pen->style != wxTRANSPARENT)
  1407.       {
  1408.         SetPen(current_pen);
  1409.       
  1410.         *pstream << "newpath\n";
  1411.         *pstream << x << " " << YSCALE(y) << " moveto\n";
  1412.         *pstream << x+width << " " << YSCALE(y) << " lineto\n";
  1413.         *pstream << x+width << " " << YSCALE(y+height) << " lineto\n";
  1414.         *pstream << x << " " << YSCALE(y+height) << " lineto\n";
  1415.         *pstream << "closepath\n";
  1416.         *pstream << "stroke\n";
  1417.  
  1418.         CalcBoundingBox(x, YSCALE(y));
  1419.         CalcBoundingBox(x+width, YSCALE(y+height));
  1420.       }
  1421.       break;
  1422.     }
  1423. #ifdef wx_msw
  1424.     case wxDEVICE_WINDOWS:
  1425.     {
  1426.       wxWnd *wnd = NULL;
  1427.  
  1428.       int x1 = (int)x;
  1429.       int y1 = (int)y;
  1430.       int x2 = (int)(x+width);
  1431.       int y2 = (int)(y+height);
  1432.  
  1433.       if (canvas)
  1434.       {
  1435.         wnd = (wxWnd *)canvas->handle;
  1436.         wnd->CalcScrolledPosition((int)x, (int)y, &x1, &y1);
  1437.         wnd->CalcScrolledPosition((int)(x+width), (int)(y+height), &x2, &y2);
  1438.       }
  1439.  
  1440.       HDC dc = NULL;
  1441.       if (cdc)
  1442.         dc = cdc;
  1443.       else
  1444.         dc = GetDC(wnd->handle);
  1445.  
  1446.       (void)Rectangle(dc, XLOG2DEV(x1), YLOG2DEV(y1), XLOG2DEV(x2), YLOG2DEV(y2));
  1447.  
  1448.       if (!cdc)
  1449.         ReleaseDC(wnd->handle, dc);
  1450.       break;
  1451.     }
  1452. #endif
  1453.   }
  1454. }
  1455.  
  1456. void wxDC::DrawRoundedRectangle(float x, float y, float width, float height, float radius)
  1457. {
  1458.   switch (device)
  1459.   {
  1460. #ifdef wx_x
  1461.     case wxDEVICE_CANVAS:
  1462.     {
  1463.       if (canvas)
  1464.       {
  1465.         float rwidth = radius*2;
  1466.         float rheight = rwidth;
  1467.  
  1468.         if (current_brush && current_brush->style != wxTRANSPARENT)
  1469.         {
  1470.           SetBrush(current_brush);
  1471.           XFillRectangle(canvas->display, canvas->xwindow, gc, 
  1472.                 XLOG2DEV(x+radius), YLOG2DEV(y), 
  1473.                 XLOG2DEVREL(width - rwidth), YLOG2DEVREL(height));
  1474.           XFillRectangle(canvas->display, canvas->xwindow, gc, 
  1475.                 XLOG2DEV(x), YLOG2DEV(y+radius),
  1476.                 XLOG2DEVREL(width), YLOG2DEVREL(height - rheight));
  1477.  
  1478.           XFillArc(canvas->display, canvas->xwindow, gc, 
  1479.                 XLOG2DEV(x), YLOG2DEV(y), 
  1480.                 XLOG2DEVREL(rwidth), YLOG2DEVREL(rheight), 90*64, 90*64);
  1481.           XFillArc(canvas->display, canvas->xwindow, gc, 
  1482.                 XLOG2DEV(x+width - rwidth), YLOG2DEV(y), 
  1483.                 XLOG2DEVREL(rwidth), YLOG2DEVREL(rheight), 0, 90*64);
  1484.           XFillArc(canvas->display, canvas->xwindow, gc, 
  1485.                 XLOG2DEV(x+width - rwidth), 
  1486.                 YLOG2DEV(y+height - rheight),
  1487.                 XLOG2DEVREL(rwidth), YLOG2DEVREL(rheight), 270*64, 90*64);
  1488.           XFillArc(canvas->display, canvas->xwindow, gc, 
  1489.                 XLOG2DEV(x), YLOG2DEV(y+height - rheight),
  1490.             XLOG2DEVREL(rwidth), YLOG2DEVREL(rheight), 180*64, 90*64);
  1491. #ifdef wx_motif
  1492.           if (canvas->is_retained)
  1493.       {
  1494.           XFillRectangle(canvas->display, canvas->backingPixmap, gcBacking, 
  1495.                 XLOG2DEV_2(x+radius), YLOG2DEV_2(y), 
  1496.                 XLOG2DEVREL(width - rwidth), YLOG2DEVREL(height));
  1497.           XFillRectangle(canvas->display, canvas->backingPixmap, gcBacking, 
  1498.                 XLOG2DEV_2(x), YLOG2DEV_2(y+radius),
  1499.                 XLOG2DEVREL(width), YLOG2DEVREL(height - rheight));
  1500.  
  1501.           XFillArc(canvas->display, canvas->backingPixmap, gcBacking, 
  1502.                 XLOG2DEV_2(x), YLOG2DEV_2(y), 
  1503.                 XLOG2DEVREL(rwidth), YLOG2DEVREL(rheight), 90*64, 90*64);
  1504.           XFillArc(canvas->display, canvas->backingPixmap, gcBacking, 
  1505.                 XLOG2DEV_2(x+width - rwidth), YLOG2DEV_2(y), 
  1506.                 XLOG2DEVREL(rwidth), YLOG2DEVREL(rheight), 0, 90*64);
  1507.           XFillArc(canvas->display, canvas->backingPixmap, gcBacking, 
  1508.                 XLOG2DEV_2(x+width - rwidth), 
  1509.                 YLOG2DEV_2(y+height - rheight),
  1510.                 XLOG2DEVREL(rwidth), YLOG2DEVREL(rheight), 270*64, 90*64);
  1511.           XFillArc(canvas->display, canvas->backingPixmap, gcBacking, 
  1512.                 XLOG2DEV_2(x), YLOG2DEV_2(y+height - rheight),
  1513.             XLOG2DEVREL(rwidth), YLOG2DEVREL(rheight), 180*64, 90*64);
  1514.       }
  1515. #endif
  1516.         }
  1517.  
  1518.         if (current_pen && current_pen->style != wxTRANSPARENT)
  1519.         {
  1520.           SetPen(current_pen);
  1521.           XDrawLine(canvas->display, canvas->xwindow, gc, 
  1522.                XLOG2DEV(x+radius), YLOG2DEV(y),
  1523.                XLOG2DEV(x+width-radius), YLOG2DEV(y));
  1524.           XDrawLine(canvas->display, canvas->xwindow, gc, 
  1525.                XLOG2DEV(x+radius), YLOG2DEV(y+height), 
  1526.                XLOG2DEV(x+width-radius), YLOG2DEV(y+height));
  1527.  
  1528.           XDrawLine(canvas->display, canvas->xwindow, gc, 
  1529.                XLOG2DEV(x), YLOG2DEV(y+radius),
  1530.                XLOG2DEV(x), YLOG2DEV(y+height-radius));
  1531.           XDrawLine(canvas->display, canvas->xwindow, gc, 
  1532.                XLOG2DEV(x+width), YLOG2DEV(y+radius),
  1533.                XLOG2DEV(x+width), YLOG2DEV(y+height-radius));
  1534.           XDrawArc(canvas->display, canvas->xwindow, gc, 
  1535.                 XLOG2DEV(x), YLOG2DEV(y), 
  1536.                 XLOG2DEVREL(rwidth), YLOG2DEVREL(rheight), 90*64, 90*64);
  1537.           XDrawArc(canvas->display, canvas->xwindow, gc, 
  1538.                 XLOG2DEV(x+width - rwidth), YLOG2DEV(y), 
  1539.                 XLOG2DEVREL(rwidth), YLOG2DEVREL(rheight), 0, 90*64);
  1540.           XDrawArc(canvas->display, canvas->xwindow, gc, 
  1541.                 XLOG2DEV(x+width - rwidth), 
  1542.                 YLOG2DEV(y+height - rheight),
  1543.                 XLOG2DEVREL(rwidth), YLOG2DEVREL(rheight), 270*64, 90*64);
  1544.           XDrawArc(canvas->display, canvas->xwindow, gc, 
  1545.                 XLOG2DEV(x), YLOG2DEV(y+height - rheight),
  1546.             XLOG2DEVREL(rwidth), YLOG2DEVREL(rheight), 180*64, 90*64);
  1547. #ifdef wx_motif
  1548.           if (canvas->is_retained)
  1549.       {
  1550.           XDrawLine(canvas->display, canvas->backingPixmap, gcBacking, 
  1551.                XLOG2DEV_2(x+radius), YLOG2DEV_2(y),
  1552.                XLOG2DEV_2(x+width-radius), YLOG2DEV_2(y));
  1553.           XDrawLine(canvas->display, canvas->backingPixmap, gcBacking, 
  1554.                XLOG2DEV_2(x+radius), YLOG2DEV_2(y+height), 
  1555.                XLOG2DEV_2(x+width-radius), YLOG2DEV_2(y+height));
  1556.  
  1557.           XDrawLine(canvas->display, canvas->backingPixmap, gcBacking, 
  1558.                XLOG2DEV_2(x), YLOG2DEV_2(y+radius),
  1559.                XLOG2DEV_2(x), YLOG2DEV_2(y+height-radius));
  1560.           XDrawLine(canvas->display, canvas->backingPixmap, gcBacking, 
  1561.                XLOG2DEV(x+width), YLOG2DEV_2(y+radius),
  1562.                XLOG2DEV_2(x+width), YLOG2DEV_2(y+height-radius));
  1563.           XDrawArc(canvas->display, canvas->backingPixmap, gcBacking, 
  1564.                 XLOG2DEV_2(x), YLOG2DEV_2(y), 
  1565.                 XLOG2DEVREL(rwidth), YLOG2DEVREL(rheight), 90*64, 90*64);
  1566.           XDrawArc(canvas->display, canvas->backingPixmap, gcBacking, 
  1567.                 XLOG2DEV_2(x+width - rwidth), YLOG2DEV_2(y), 
  1568.                 XLOG2DEVREL(rwidth), YLOG2DEVREL(rheight), 0, 90*64);
  1569.           XDrawArc(canvas->display, canvas->backingPixmap, gcBacking, 
  1570.                 XLOG2DEV_2(x+width - rwidth), 
  1571.                 YLOG2DEV_2(y+height - rheight),
  1572.                 XLOG2DEVREL(rwidth), YLOG2DEVREL(rheight), 270*64, 90*64);
  1573.           XDrawArc(canvas->display, canvas->backingPixmap, gcBacking, 
  1574.                 XLOG2DEV_2(x), YLOG2DEV_2(y+height - rheight),
  1575.             XLOG2DEVREL(rwidth), YLOG2DEVREL(rheight), 180*64, 90*64);
  1576.       }
  1577. #endif
  1578.         }
  1579.       }
  1580.       break;
  1581.     }
  1582. #endif
  1583.     case wxDEVICE_EPS:
  1584.     {
  1585.       if (current_brush && current_brush->style != wxTRANSPARENT)
  1586.       {
  1587.         SetBrush(current_brush);
  1588.         // Draw rectangle anticlockwise
  1589.         *pstream << "newpath\n";
  1590.         *pstream << x+radius << " " << YSCALE(y+radius) << " " << radius << " 90 180 arc\n";
  1591.  
  1592.         *pstream << x << " " << YSCALE(y + radius) << " moveto\n";
  1593.  
  1594.         *pstream << x+radius << " " << YSCALE(y+height-radius) << " " << radius << " 180 270 arc\n";
  1595.         *pstream << x+width-radius << " " << YSCALE(y+height) << " lineto\n";
  1596.  
  1597.         *pstream << x+width-radius << " " << YSCALE(y+height-radius) << " " << radius << " 270 0 arc\n";
  1598.         *pstream << x+width << " " << YSCALE(y+radius) << " lineto\n";
  1599.  
  1600.         *pstream << x+width-radius << " " << YSCALE(y+radius) << " " << radius << " 0 90 arc\n";
  1601.  
  1602.         *pstream << x+radius << " " << YSCALE(y) << " lineto\n";
  1603.  
  1604.         *pstream << "closepath\n";
  1605.  
  1606.         *pstream << "fill\n";
  1607.  
  1608.         CalcBoundingBox(x, YSCALE(y));
  1609.         CalcBoundingBox(x+width, YSCALE(y+height));
  1610.       }
  1611.       if (current_pen && current_pen->style != wxTRANSPARENT)
  1612.       {
  1613.         SetPen(current_pen);
  1614.         // Draw rectangle anticlockwise
  1615.         *pstream << "newpath\n";
  1616.         *pstream << x+radius << " " << YSCALE(y+radius) << " " << radius << " 90 180 arc\n";
  1617.  
  1618.         *pstream << x << " " << YSCALE(y + height - radius) << " lineto\n";
  1619.  
  1620.         *pstream << x+radius << " " << YSCALE(y+height-radius) << " " << radius << " 180 270 arc\n";
  1621.         *pstream << x+width-radius << " " << YSCALE(y+height) << " lineto\n";
  1622.  
  1623.         *pstream << x+width-radius << " " << YSCALE(y+height-radius) << " " << radius << " 270 0 arc\n";
  1624.         *pstream << x+width << " " << YSCALE(y+radius) << " lineto\n";
  1625.  
  1626.         *pstream << x+width-radius << " " << YSCALE(y+radius) << " " << radius << " 0 90 arc\n";
  1627.  
  1628.         *pstream << x+radius << " " << YSCALE(y) << " lineto\n";
  1629.  
  1630.         *pstream << "closepath\n";
  1631.  
  1632.         *pstream << "stroke\n";
  1633.  
  1634.         CalcBoundingBox(x, YSCALE(y));
  1635.         CalcBoundingBox(x+width, YSCALE(y+height));
  1636.       }
  1637.       break;
  1638.     }
  1639. #ifdef wx_msw
  1640.     case wxDEVICE_WINDOWS:
  1641.     {
  1642.       wxWnd *wnd = NULL;
  1643.  
  1644.       int x1 = (int)x;
  1645.       int y1 = (int)y;
  1646.       int x2 = (int)(x+width);
  1647.       int y2 = (int)(y+height);
  1648.  
  1649.       if (canvas)
  1650.       {
  1651.         wnd = (wxWnd *)canvas->handle;
  1652.         wnd->CalcScrolledPosition((int)x, (int)y, &x1, &y1);
  1653.         wnd->CalcScrolledPosition((int)(x+width), (int)(y+height), &x2, &y2);
  1654.       }
  1655.  
  1656.       HDC dc = NULL;
  1657.       if (cdc)
  1658.         dc = cdc;
  1659.       else
  1660.         dc = GetDC(wnd->handle);
  1661.  
  1662.       (void)RoundRect(dc, XLOG2DEV(x1), YLOG2DEV(y1), XLOG2DEV(x2),
  1663.                           YLOG2DEV(y2), XLOG2DEV(radius), YLOG2DEV(radius));
  1664.  
  1665.       if (!cdc)
  1666.         ReleaseDC(wnd->handle, dc);
  1667.       break;
  1668.     }
  1669. #endif
  1670.   }
  1671. }
  1672.  
  1673. void wxDC::DrawEllipse(float x, float y, float width, float height)
  1674. {
  1675.   switch (device)
  1676.   {
  1677. #ifdef wx_x
  1678.     case wxDEVICE_CANVAS:
  1679.     {
  1680.       if (canvas)
  1681.       {
  1682.         static const int angle = 23040;
  1683.  
  1684.         if (current_brush && current_brush->style != wxTRANSPARENT)
  1685.         {
  1686.           SetBrush(current_brush);
  1687.           XFillArc(canvas->display, canvas->xwindow, gc, 
  1688.               XLOG2DEV(x), YLOG2DEV(y), XLOG2DEVREL(width), YLOG2DEVREL(height), 0, angle);
  1689. #ifdef wx_motif
  1690.           if (canvas->is_retained)
  1691.             XFillArc(canvas->display, canvas->backingPixmap, gcBacking, 
  1692.                 XLOG2DEV(x), YLOG2DEV(y), XLOG2DEVREL(width), YLOG2DEVREL(height), 0, angle);
  1693. #endif
  1694.         }
  1695.  
  1696.         if (current_pen && current_pen->style != wxTRANSPARENT)
  1697.         {
  1698.           SetPen(current_pen);
  1699.           XDrawArc(canvas->display, canvas->xwindow, gc, 
  1700.               XLOG2DEV(x), YLOG2DEV(y), XLOG2DEVREL(width), YLOG2DEVREL(height), 0, angle);
  1701. #ifdef wx_motif
  1702.           if (canvas->is_retained)
  1703.             XDrawArc(canvas->display, canvas->backingPixmap, gcBacking, 
  1704.               XLOG2DEV_2(x), YLOG2DEV_2(y), XLOG2DEVREL(width), YLOG2DEVREL(height), 0, angle);
  1705. #endif
  1706.         }
  1707.       }
  1708.       break;
  1709.     }
  1710. #endif
  1711.     case wxDEVICE_EPS:
  1712.     {
  1713.       if (current_brush && current_brush->style != wxTRANSPARENT)
  1714.       {
  1715.         SetBrush(current_brush);
  1716.  
  1717.         *pstream << "newpath\n";
  1718.         *pstream << x + width/2 << " " << YSCALE(y + height/2) << " ";
  1719.         *pstream << width/2 << " " << height/2 << " 0 360 ellipse\n";
  1720.         *pstream << "fill\n";
  1721.  
  1722.         CalcBoundingBox(x-width, YSCALE(y-height));
  1723.         CalcBoundingBox(x+width, YSCALE(y+height));
  1724.       }
  1725.       if (current_pen && current_pen->style != wxTRANSPARENT)
  1726.       {
  1727.         SetPen(current_pen);
  1728.  
  1729.         *pstream << "newpath\n";
  1730.         *pstream << x + width/2 << " " << YSCALE(y + height/2) << " ";
  1731.         *pstream << width/2 << " " << height/2 << " 0 360 ellipse\n";
  1732.         *pstream << "stroke\n";
  1733.  
  1734.         CalcBoundingBox(x-width, YSCALE(y-height));
  1735.         CalcBoundingBox(x+width, YSCALE(y+height));
  1736.       }
  1737.       break;
  1738.     }
  1739. #ifdef wx_msw
  1740.     case wxDEVICE_WINDOWS:
  1741.     {
  1742.       wxWnd *wnd = NULL;
  1743.  
  1744.       int x1 = (int)x;
  1745.       int y1 = (int)y;
  1746.       int x2 = (int)(x+width);
  1747.       int y2 = (int)(y+height);
  1748.  
  1749.       if (canvas)
  1750.       {
  1751.         wnd = (wxWnd *)canvas->handle;
  1752.         wnd->CalcScrolledPosition((int)x, (int)y, &x1, &y1);
  1753.         wnd->CalcScrolledPosition((int)(x+width), (int)(y+height), &x2, &y2);
  1754.       }
  1755.  
  1756.       HDC dc = NULL;
  1757.       if (cdc)
  1758.         dc = cdc;
  1759.       else
  1760.         dc = GetDC(wnd->handle);
  1761.  
  1762.       (void)Ellipse(dc, XLOG2DEV(x1), YLOG2DEV(y1), XLOG2DEV(x2), YLOG2DEV(y2));
  1763.  
  1764.       if (!cdc)
  1765.         ReleaseDC(wnd->handle, dc);
  1766.       break;
  1767.     }
  1768. #endif
  1769.   }
  1770. }
  1771.  
  1772. void wxDC::DrawIcon(wxIcon *icon, float x, float y)
  1773. {
  1774.   switch (device)
  1775.   {
  1776. #ifdef wx_x
  1777.     case wxDEVICE_CANVAS:
  1778.     {
  1779.       if (canvas)
  1780.       {
  1781. #ifdef wx_xview
  1782.         Xv_Screen screen = xv_get(xview_server, SERVER_NTH_SCREEN, 0);
  1783.         Xv_Window root_window = xv_get(screen, XV_ROOT);
  1784. /*
  1785.         Canvas xview_canvas = (Canvas)canvas->handle;
  1786.         Xv_Window paint_window = (Xv_Window)xv_get(xview_canvas, CANVAS_NTH_PAINT_WINDOW, 0);
  1787.         Window canvas_window = (Window)xv_get(paint_window, XV_XID);
  1788. */
  1789.         Display *dpy = (Display *)xv_get(root_window, XV_DISPLAY);
  1790.         Pixmap pixmap = (Pixmap)xv_get(icon->x_image, SERVER_IMAGE_PIXMAP);
  1791.         int width = (int)xv_get(icon->x_image, XV_WIDTH);
  1792.         int height = (int)xv_get(icon->x_image, XV_HEIGHT);
  1793. #endif
  1794. #ifdef wx_motif
  1795.         Display *dpy = XtDisplay(wxTheApp->topLevel);
  1796.         Pixmap pixmap = icon->x_pixmap;
  1797.         int width = icon->iconWidth;
  1798.         int height = icon->iconHeight;
  1799. #endif
  1800.         XCopyPlane(dpy, pixmap, canvas->xwindow, gc,
  1801.                    0, 0, width, height,
  1802.                    (int)XLOG2DEV(x), (int)YLOG2DEV(y), 1);
  1803. #ifdef wx_motif
  1804.         if (canvas->is_retained)
  1805.           XCopyPlane(dpy, pixmap, canvas->backingPixmap, gcBacking,
  1806.                      0, 0, width, height,
  1807.                      (int)XLOG2DEV_2(x), (int)YLOG2DEV_2(y), 1);
  1808. #endif
  1809.       }
  1810.       break;
  1811.     }
  1812. #endif
  1813.     case wxDEVICE_EPS:
  1814.       break;
  1815.  
  1816. #ifdef wx_msw
  1817.     case wxDEVICE_WINDOWS:
  1818.     {
  1819.       wxWnd *wnd = NULL;
  1820.  
  1821.       int x1 = (int)x;
  1822.       int y1 = (int)y;
  1823.  
  1824.       if (canvas)
  1825.       {
  1826.         wnd = (wxWnd *)canvas->handle;
  1827.         wnd->CalcScrolledPosition((int)x, (int)y, &x1, &y1);
  1828.       }
  1829.  
  1830.       HDC dc = NULL;
  1831.       if (cdc)
  1832.         dc = cdc;
  1833.       else
  1834.         dc = GetDC(wnd->handle);
  1835.  
  1836.       ::DrawIcon(dc, x1, y1, icon->ms_icon);
  1837.  
  1838.       if (!cdc)
  1839.         ReleaseDC(wnd->handle, dc);
  1840.       break;
  1841.     }
  1842. #endif
  1843.   }
  1844. }
  1845.  
  1846.  
  1847. void wxDC::SetFont(wxFont *the_font)
  1848. {
  1849.   font = the_font;
  1850.   switch (device)
  1851.   {
  1852. #ifdef wx_motif
  1853. #endif
  1854. #ifdef wx_x
  1855.     case wxDEVICE_CANVAS:
  1856.     {
  1857.       if (canvas)
  1858.       {
  1859. #ifdef wx_xview
  1860.         // Set the font according to the current scaling
  1861.         int scaled_size = (int)(user_scale_y*font->point_size + 0.5);
  1862.         Xv_Font xfont = wxFontPool->FindNearestFont(font->family, font->style,
  1863.                                                   font->weight, scaled_size, 0, 0);
  1864.         font->x_font = xfont;
  1865.         Font theFont = (Font)xv_get(xfont, XV_XID);
  1866. #endif
  1867. #ifdef wx_motif
  1868. //        Display *dpy = XtDisplay(wxTheApp->topLevel);
  1869. //        int screen = DefaultScreen(dpy);
  1870.  
  1871. /*
  1872.         int res_x = (int)(DisplayWidth(dpy, screen)/(DisplayWidthMM(dpy, screen)/25.4));
  1873.         int res_y = (int)(DisplayHeight(dpy, screen)/(DisplayHeightMM(dpy, screen)/25.4));
  1874. */
  1875.         int res_x = 100;
  1876.         int res_y = 100;
  1877.  
  1878.         int scaled_size = (int)(10 * ((int)(user_scale_y*font->point_size + 0.5)));
  1879.  
  1880.         XFontStruct *fontStruct = wxFontPool->FindNearestFont(font->family, font->style,
  1881.                                                    font->weight, scaled_size,
  1882.                                                    res_x, res_y);
  1883.         font->xFont = fontStruct;
  1884.         Font theFont = fontStruct->fid;
  1885. #endif
  1886.         XSetFont(canvas->display, gc, theFont);
  1887. #ifdef wx_motif
  1888.         if (canvas->is_retained)
  1889.           XSetFont(canvas->display, gcBacking, theFont);
  1890. #endif
  1891.       }
  1892.       break;
  1893.     }
  1894. #endif
  1895.     case wxDEVICE_EPS:
  1896.     {
  1897.       char buf[100];
  1898.       char *name;
  1899.       char *style = "";
  1900.       int Style = font->style;
  1901.       int Weight = font->weight;
  1902.  
  1903.       switch (font->family)
  1904.       {
  1905.  
  1906.         case wxMODERN:     name = "/Courier";
  1907.                            break;
  1908.         case wxSWISS:      name = "/Helvetica";
  1909.                            break;
  1910.         default:
  1911.         case wxDEFAULT:
  1912.         case wxROMAN:      name = "/Times";
  1913.                            break;
  1914.       }
  1915.  
  1916.       if (Style == wxNORMAL && (Weight == wxNORMAL || Weight == wxLIGHT))
  1917.       {
  1918.         if (font->family == wxROMAN)
  1919.           style = "-Roman";
  1920.         else
  1921.           style = "";
  1922.       }
  1923.       else if (Style == wxNORMAL && Weight == wxBOLD)
  1924.         style = "-Bold";
  1925.  
  1926.       else if (Style == wxITALIC && (Weight == wxNORMAL || Weight == wxLIGHT))
  1927.       {
  1928.         if (font->family == wxROMAN)
  1929.           style = "-Italic";
  1930.         else
  1931.           style = "-Oblique";
  1932.       }
  1933.       else if (Style == wxITALIC && Weight == wxBOLD)
  1934.       {
  1935.         if (font->family == wxROMAN)
  1936.           style = "-BoldItalic";
  1937.         else
  1938.           style = "-BoldOblique";
  1939.       }
  1940.       else if (Style == wxSLANT && (Weight == wxNORMAL || Weight == wxLIGHT))
  1941.       {
  1942.         if (font->family == wxROMAN)
  1943.           style = "-Italic";
  1944.         else
  1945.           style = "-Oblique";
  1946.       }
  1947.       else if (Style == wxSLANT && Weight == wxBOLD)
  1948.       {
  1949.         if (font->family == wxROMAN)
  1950.           style = "-BoldItalic";
  1951.         else
  1952.           style = "-BoldOblique";
  1953.       }
  1954.       else style = "";
  1955.  
  1956.       strcpy(buf, name);
  1957.       strcat(buf, style);
  1958.       *pstream << buf << " findfont\n";
  1959.       *pstream << font->point_size << " scalefont setfont\n";
  1960.  
  1961.       break;
  1962.     }
  1963. #ifdef wx_msw
  1964.     case wxDEVICE_WINDOWS:
  1965.     {
  1966.       wxWnd *wnd = NULL;
  1967.       if (canvas)
  1968.         wnd = (wxWnd *)canvas->handle;
  1969.  
  1970.       HDC dc = NULL;
  1971.       if (cdc)
  1972.         dc = cdc;
  1973.       else
  1974.         dc = GetDC(wnd->handle);
  1975.  
  1976.       if (font && !font->cfont)
  1977.       {
  1978.  
  1979.         BYTE italic;
  1980.         int weight = 0;
  1981.         int family = 0;
  1982.         char *face = NULL;
  1983.  
  1984.         switch (font->family)
  1985.         {
  1986.           case wxDECORATIVE: family = FF_DECORATIVE;
  1987.                              break;
  1988.           case wxROMAN:      family = FF_ROMAN;
  1989.                              break;
  1990.           case wxMODERN:     family = FF_MODERN;
  1991.                              break;
  1992.           case wxSWISS:      family = FF_SWISS;
  1993.                              face = "Arial";
  1994.                              break;
  1995.           case wxDEFAULT:
  1996.           default:           family = FF_DONTCARE;
  1997.         }
  1998.  
  1999.         if (font->style == wxITALIC || font->style == wxSLANT)
  2000.           italic = 1;
  2001.         else
  2002.           italic = 0;
  2003.  
  2004.         if (font->weight == wxNORMAL)
  2005.           weight = FW_NORMAL;
  2006.         else if (font->weight == wxLIGHT)
  2007.           weight = FW_LIGHT;
  2008.         else if (font->weight == wxBOLD)
  2009.           weight = FW_BOLD;
  2010.  
  2011.         int nHeight = font->point_size*GetDeviceCaps(dc, LOGPIXELSY)/72;
  2012.         font->cfont = CreateFont(nHeight, 0, 0, 0, weight, italic, 0, 0,
  2013.                     ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  2014.                     PROOF_QUALITY, DEFAULT_PITCH | family,
  2015.                     face);
  2016.       }
  2017.  
  2018.       if (font && font->cfont)
  2019.       {
  2020.         HFONT f = ::SelectObject(dc, font->cfont);
  2021.         if (!old_font)
  2022.           old_font = f;
  2023.       }
  2024.       if (!cdc)
  2025.         ReleaseDC(wnd->handle, dc);
  2026.       break;
  2027.     }
  2028. #endif
  2029.   }
  2030. }
  2031.  
  2032. void wxDC::SetPen(wxPen *pen)
  2033. {
  2034. #ifdef wx_x
  2035.   wxColour *old_colour = current_colour;
  2036.   int old_pen_style = -1;
  2037.   int old_pen_width = -1;
  2038.   if (current_pen)
  2039.   {
  2040.     old_pen_style = current_pen->style;
  2041.     old_pen_width = current_pen->width;
  2042.   }
  2043. #endif
  2044.   current_pen = pen;
  2045.   if (!pen)
  2046.   {
  2047. #ifdef wx_x
  2048.     current_colour = NULL;
  2049. #endif
  2050.     return;
  2051.   }
  2052. #ifdef wx_x
  2053.   current_colour = pen->colour;
  2054. #endif
  2055.   switch (device)
  2056.   {
  2057. #ifdef wx_x
  2058.     case wxDEVICE_CANVAS:
  2059.     {
  2060.       if (canvas)
  2061.       {
  2062.         Bool same_style = (old_pen_style == pen->style && old_pen_width == pen->width);
  2063.         if (!same_style)
  2064.     {
  2065.           int scaled_width = (int)XLOG2DEVREL(pen->width);
  2066.           if (scaled_width < 0)
  2067.             scaled_width = 0;
  2068.  
  2069.           int style;
  2070.           static char dotted[] = {2, 5};
  2071.           static char short_dashed[] = {4, 4};
  2072.           static char long_dashed[] = {4, 8};
  2073.           static char dotted_dashed[] = {6, 6, 2, 6};
  2074.  
  2075.           switch (pen->style)
  2076.           {
  2077.             case wxDOT:
  2078.               XSetDashes(canvas->display, gc, 0, dotted, 2);
  2079. #ifdef wx_motif
  2080.               if (canvas->is_retained)
  2081.                 XSetDashes(canvas->display, gcBacking, 0, dotted, 2);
  2082. #endif
  2083.               style = LineOnOffDash;
  2084.               break;
  2085.             case wxSHORT_DASH:
  2086.               XSetDashes(canvas->display, gc, 0, short_dashed, 2);
  2087. #ifdef wx_motif
  2088.               if (canvas->is_retained)
  2089.                 XSetDashes(canvas->display, gcBacking, 0, short_dashed, 2);
  2090. #endif
  2091.               style = LineOnOffDash;
  2092.           break;
  2093.             case wxLONG_DASH:
  2094.               XSetDashes(canvas->display, gc, 0, long_dashed, 2);
  2095. #ifdef wx_motif
  2096.               if (canvas->is_retained)
  2097.                 XSetDashes(canvas->display, gcBacking, 0, long_dashed, 2);
  2098. #endif
  2099.               style = LineOnOffDash;
  2100.               break;
  2101.             case wxDOT_DASH:
  2102.               XSetDashes(canvas->display, gc, 0, dotted_dashed, 4);
  2103. #ifdef wx_motif
  2104.               if (canvas->is_retained)
  2105.                 XSetDashes(canvas->display, gcBacking, 0, dotted_dashed, 2);
  2106. #endif
  2107.           style = LineOnOffDash;
  2108.           break;
  2109.             case wxSOLID:
  2110.             case wxTRANSPARENT:
  2111.             default:
  2112.           style = LineSolid;
  2113.           }
  2114.  
  2115.           XSetLineAttributes(canvas->display, gc, scaled_width, style, CapRound,
  2116.                         JoinRound);
  2117. #ifdef wx_motif
  2118.           if (canvas->is_retained)
  2119.             XSetLineAttributes(canvas->display, gcBacking, scaled_width, style, CapRound,
  2120.                            JoinRound);
  2121. #endif
  2122.  
  2123.     }
  2124.  
  2125.         Bool same_colour = (old_colour &&
  2126.                             (old_colour->red == pen->colour->red) &&
  2127.                             (old_colour->blue == pen->colour->blue) &&
  2128.                             (old_colour->green == pen->colour->green));
  2129.  
  2130.         if (!same_colour)
  2131.     {
  2132.         int pixel = -1;
  2133.         if (pen->style == wxTRANSPARENT)
  2134.           pixel = background_pixel;
  2135.         else if (!Colour)
  2136.         {
  2137.           unsigned char red = pen->colour->Red();
  2138.           unsigned char blue = pen->colour->Blue();
  2139.           unsigned char green = pen->colour->Green();
  2140.           if (red == (unsigned char )255 && blue == (unsigned char)255
  2141.                && green == (unsigned char)255)
  2142.       {
  2143.             pixel = WhitePixel(canvas->display, DefaultScreen(canvas->display));
  2144.             current_colour = wxWHITE;
  2145.       }
  2146.           else
  2147.       {
  2148.             pixel = BlackPixel(canvas->display, DefaultScreen(canvas->display));
  2149.             current_colour = wxBLACK;
  2150.       }
  2151.         }
  2152.         else if (pen->colour)
  2153.           {
  2154.             XColor exact_def;
  2155.         exact_def.red = pen->colour->Red();
  2156.         exact_def.green = pen->colour->Green();
  2157.         exact_def.blue = pen->colour->Blue();
  2158.         exact_def.flags = DoRed | DoGreen | DoBlue;
  2159.  
  2160.         Colormap cmap = DefaultColormap(canvas->display, DefaultScreen(canvas->display));
  2161.             if (!XAllocColor(canvas->display, cmap, &exact_def))
  2162.         {
  2163.               pixel = BlackPixel(canvas->display, DefaultScreen(canvas->display));
  2164.           fprintf(stderr, "wxWindows warning: cannot allocate pen colour; using black instead\n");
  2165.         }
  2166.         else
  2167.           pixel = exact_def.pixel;
  2168.           }
  2169.  
  2170.          // Finally, set the GC to the required colour
  2171.         if (pixel > -1)
  2172.     {
  2173.           XSetForeground(canvas->display, gc, pixel);
  2174. #ifdef wx_motif
  2175.           if (canvas->is_retained)
  2176.             XSetForeground(canvas->display, gcBacking, pixel);
  2177. #endif
  2178.     }
  2179.         }
  2180.        }
  2181.       break;
  2182.     }
  2183. #endif
  2184.     case wxDEVICE_EPS:
  2185.     {
  2186.       // Line width
  2187.       *pstream << pen->width << " setlinewidth\n";
  2188.  
  2189.       // Line style
  2190.       static char *dotted = "[2 5] 2";
  2191.       static char *short_dashed = "[4 4] 2";
  2192.       static char *long_dashed = "[4 8] 2";
  2193.       static char *dotted_dashed = "[6 6 2 6] 4";
  2194.  
  2195.       char *psdash = NULL;
  2196.       switch (pen->style)
  2197.       {
  2198.         case wxDOT:
  2199.           psdash = dotted;
  2200.           break;
  2201.         case wxSHORT_DASH:
  2202.           psdash = short_dashed;
  2203.           break;
  2204.         case wxLONG_DASH:
  2205.           psdash = long_dashed;
  2206.           break;
  2207.         case wxDOT_DASH:
  2208.           psdash = dotted_dashed;
  2209.           break;
  2210.         case wxSOLID:
  2211.         case wxTRANSPARENT:
  2212.         default:
  2213.           psdash = "[] 0";
  2214.           break;
  2215.       }
  2216.       *pstream << psdash << " setdash\n";
  2217.  
  2218.       // Line colour
  2219.       unsigned char red = pen->colour->Red();
  2220.       unsigned char blue = pen->colour->Blue();
  2221.       unsigned char green = pen->colour->Green();
  2222.  
  2223.       if (!Colour)
  2224.       {
  2225.         // Anything not white is black
  2226.         if (!(red == (unsigned char )255 && blue == (unsigned char)255
  2227.                        && green == (unsigned char)255))
  2228.         {
  2229.           red = (unsigned char )0;
  2230.           green = (unsigned char )0;
  2231.           blue = (unsigned char )0;
  2232.         }
  2233.       }
  2234.       *pstream << (int)red << " " << (int)green << " " << (int)blue << " setrgbcolor\n";
  2235.  
  2236.       break;
  2237.     }
  2238. #ifdef wx_msw
  2239.     case wxDEVICE_WINDOWS:
  2240.     {
  2241.       HDC dc = NULL;
  2242.       wxWnd *wnd = NULL;
  2243.       if (canvas)
  2244.         wnd = (wxWnd *)canvas->handle;
  2245.       if (cdc)
  2246.         dc = cdc;
  2247.       else if (wnd)
  2248.         dc = GetDC(wnd->handle);
  2249.  
  2250.       HPEN p = ::SelectObject(dc, pen->cpen);
  2251.       if (!old_pen)
  2252.         old_pen = p;
  2253.  
  2254.       if (!cdc)
  2255.         ReleaseDC(wnd->handle, dc);
  2256.       break;
  2257.     }
  2258. #endif
  2259.   }
  2260. }
  2261.  
  2262. void wxDC::SetTextForeground(wxColour *colour)
  2263. {
  2264.   current_text_foreground = colour;
  2265. }
  2266.  
  2267. void wxDC::SetTextBackground(wxColour *colour)
  2268. {
  2269.   current_text_background = colour;
  2270. }
  2271.  
  2272. void wxDC::SetBrush(wxBrush *brush)
  2273. {
  2274. #ifdef wx_x
  2275.   wxColour *old_colour = current_colour;
  2276.   int old_brush_style = -1;
  2277.   if (current_brush)
  2278.   {
  2279.     old_brush_style = current_brush->style;
  2280.   }
  2281. #endif
  2282.   current_brush = brush;
  2283.   if (!brush)
  2284.   {
  2285. #ifdef wx_x
  2286.     current_colour = NULL;
  2287. #endif
  2288.     return;
  2289.   }
  2290. #ifdef wx_x
  2291.   current_colour = brush->colour;
  2292. #endif
  2293.   switch (device)
  2294.   {
  2295. #ifdef wx_x
  2296.     case wxDEVICE_CANVAS:
  2297.     {
  2298.       if (canvas)
  2299.       {
  2300.         if (old_brush_style != brush->style)
  2301.     {
  2302.           switch (brush->style)
  2303.           {
  2304.             case wxTRANSPARENT:
  2305.               break;
  2306.             case wxSOLID:
  2307.             case wxSTIPPLE:
  2308.             default:
  2309.               XSetFillStyle(canvas->display, gc, FillSolid);
  2310. #ifdef wx_motif
  2311.               if (canvas->is_retained)
  2312.                 XSetFillStyle(canvas->display, gcBacking, FillSolid);
  2313. #endif
  2314.           }
  2315.     }
  2316.  
  2317.         Bool same_colour = (old_colour &&
  2318.                             (old_colour->red == brush->colour->red) &&
  2319.                             (old_colour->blue == brush->colour->blue) &&
  2320.                             (old_colour->green == brush->colour->green));
  2321.         if (!same_colour)
  2322.     {
  2323.         int pixel = -1;
  2324.         if (!Colour)
  2325.     {
  2326.           // Policy - on a monochrome screen, all brushes are white.
  2327.           pixel = WhitePixel(canvas->display, DefaultScreen(canvas->display));
  2328.           current_colour = wxWHITE;
  2329.  
  2330.           // N.B. comment out the above line and uncomment the following lines
  2331.           // if you want non-white colours to be black on a monochrome display.
  2332. /*
  2333.           unsigned char red = brush->colour->Red();
  2334.           unsigned char blue = brush->colour->Blue();
  2335.           unsigned char green = brush->colour->Green();
  2336.           if (red == (unsigned char )255 && blue == (unsigned char)255
  2337.                && green == (unsigned char)255)
  2338.             pixel = WhitePixel(canvas->display, DefaultScreen(canvas->display));
  2339.           else
  2340.             pixel = BlackPixel(canvas->display, DefaultScreen(canvas->display));
  2341. */
  2342.         }
  2343.         else if (brush->style != wxTRANSPARENT && brush->colour)
  2344.           {
  2345.             XColor exact_def;
  2346.         exact_def.red = brush->colour->Red();
  2347.         exact_def.green = brush->colour->Green();
  2348.         exact_def.blue = brush->colour->Blue();
  2349.         exact_def.flags = DoRed | DoGreen | DoBlue;
  2350.  
  2351.             Colormap cmap = DefaultColormap(canvas->display, DefaultScreen(canvas->display));
  2352.  
  2353.         if (!XAllocColor(canvas->display, cmap, &exact_def))
  2354.         {
  2355.           pixel = BlackPixel(canvas->display, DefaultScreen(canvas->display));
  2356.           fprintf(stderr, "wxWindows warning: cannot allocate brush colour; using black instead\n");
  2357.         }
  2358.         else
  2359.           pixel = exact_def.pixel;
  2360.           }
  2361. //        if (pixel > -1) cout << "Setting foreground to " << pixel << "\n";
  2362.         if (pixel > -1)
  2363.     {
  2364.           // Finally, set the GC to the required colour
  2365.           XSetForeground(canvas->display, gc, pixel);
  2366. #ifdef wx_motif
  2367.           if (canvas->is_retained)
  2368.             XSetForeground(canvas->display, gcBacking, pixel);
  2369. #endif
  2370.     }
  2371.         }
  2372.       }
  2373.       break;
  2374.     }
  2375. #endif
  2376.     case wxDEVICE_EPS:
  2377.     {
  2378.       // Brush colour
  2379.       unsigned char red = brush->colour->Red();
  2380.       unsigned char blue = brush->colour->Blue();
  2381.       unsigned char green = brush->colour->Green();
  2382.  
  2383.       if (!Colour)
  2384.       {
  2385.         // Anything not black is white
  2386.         if (!(red == (unsigned char )0 && blue == (unsigned char)0
  2387.                        && green == (unsigned char)0))
  2388.         {
  2389.           red = (unsigned char )255;
  2390.           green = (unsigned char )255;
  2391.           blue = (unsigned char )255;
  2392.         }
  2393.       }
  2394.       *pstream << (int)red << " " << (int)green << " " << (int)blue << " setrgbcolor\n";
  2395.  
  2396.       break;
  2397.     }
  2398. #ifdef wx_msw
  2399.     case wxDEVICE_WINDOWS:
  2400.     {
  2401.       HDC dc = NULL;
  2402.       wxWnd *wnd = NULL;
  2403.       if (canvas)
  2404.         wnd = (wxWnd *)canvas->handle;
  2405.       if (cdc)
  2406.         dc = cdc;
  2407.       else
  2408.         dc = GetDC(wnd->handle);
  2409.  
  2410.       if (current_brush && current_brush->cbrush)
  2411.       {
  2412.         HBRUSH b = ::SelectObject(dc, current_brush->cbrush);
  2413.         if (!old_brush)
  2414.           old_brush = b;
  2415.       }
  2416.       if (!cdc)
  2417.         ReleaseDC(wnd->handle, dc);
  2418.       break;
  2419.     }
  2420. #endif
  2421.   }
  2422. }
  2423.  
  2424. void wxDC::DrawText(char *text, float x, float y)
  2425. {
  2426.   switch (device)
  2427.   {
  2428. #ifdef wx_motif
  2429. #endif
  2430. #ifdef wx_x
  2431.     case wxDEVICE_CANVAS:
  2432.     {
  2433.       if (canvas)
  2434.       {
  2435.         // Since X draws from the baseline of the text, must
  2436.         // add the text height
  2437.         int cx = 0;
  2438.         int cy = 0;
  2439.         int ascent = 0;
  2440.         if (font)
  2441.     {
  2442. #ifdef wx_xview
  2443.           XFontStruct *font_info = (XFontStruct *)xv_get(font->x_font, FONT_INFO);
  2444. #endif
  2445. #ifdef wx_motif
  2446.           XFontStruct *font_info = font->xFont;
  2447. #endif
  2448.           int direction, descent;
  2449.           XCharStruct overall_return;
  2450.           (void)XTextExtents(font_info, text, strlen(text), &direction,
  2451.                              &ascent, &descent, &overall_return);
  2452.           cx = overall_return.width;
  2453.           cy = ascent + descent;
  2454.     }
  2455.  
  2456.         // First draw a rectangle representing the text background,
  2457.         // if a text background is specified
  2458.         if (current_text_background)
  2459.     {
  2460.           wxColour *old_colour = current_colour;
  2461.           current_colour = current_text_background;
  2462.           Bool same_colour = (old_colour && current_text_background &&
  2463.                               (old_colour->red == current_text_background->red) &&
  2464.                               (old_colour->blue == current_text_background->blue) &&
  2465.                               (old_colour->green == current_text_background->green));
  2466.  
  2467.     
  2468.           if (!same_colour)
  2469.           {
  2470.             int pixel = -1;
  2471.             if (current_text_background)
  2472.             {
  2473.               XColor exact_def;
  2474.               exact_def.red = current_text_background->Red();
  2475.               exact_def.green = current_text_background->Green();
  2476.               exact_def.blue = current_text_background->Blue();
  2477.               exact_def.flags = DoRed | DoGreen | DoBlue;
  2478.  
  2479.           Colormap cmap = DefaultColormap(canvas->display, DefaultScreen(canvas->display));
  2480.           if (!XAllocColor(canvas->display, cmap, &exact_def))
  2481.           {
  2482.             pixel = WhitePixel(canvas->display, DefaultScreen(canvas->display));
  2483.             fprintf(stderr, "wxWindows warning: cannot allocate text background colour; using white instead\n");
  2484.           }
  2485.           else
  2486.             pixel = exact_def.pixel;
  2487.         }
  2488.  
  2489.             // Set the GC to the required colour
  2490.            if (pixel > -1)
  2491.        {
  2492.              XSetForeground(canvas->display, gc, pixel);
  2493. #ifdef wx_motif
  2494.              if (canvas->is_retained)
  2495.                XSetForeground(canvas->display, gcBacking, pixel);
  2496. #endif
  2497.        }
  2498.       }
  2499.           XFillRectangle(canvas->display, canvas->xwindow, gc, 
  2500.                          XLOG2DEV(x), YLOG2DEV(y),
  2501.                          cx, cy);
  2502. #ifdef wx_motif
  2503.           if (canvas->is_retained)
  2504.             XFillRectangle(canvas->display, canvas->backingPixmap, gcBacking, 
  2505.                            XLOG2DEV_2(x), YLOG2DEV_2(y),
  2506.                            cx, cy);
  2507. #endif
  2508.     }
  2509.  
  2510.         // Now set the text foreground and draw the text
  2511.         if (current_text_foreground)
  2512.     {
  2513.           wxColour *old_colour = current_colour;
  2514.           current_colour = current_text_foreground;
  2515.           Bool same_colour = (old_colour && current_text_foreground &&
  2516.                         (old_colour->red == current_text_foreground->red) &&
  2517.                         (old_colour->blue == current_text_foreground->blue) &&
  2518.                         (old_colour->green == current_text_foreground->green));
  2519.  
  2520.  
  2521.     
  2522.           if (!same_colour)
  2523.           {
  2524.               int pixel = -1;
  2525.               if (!Colour)
  2526.               {
  2527.                 // Unless foreground is really white, draw it in black
  2528.                 unsigned char red = current_text_foreground->Red();
  2529.                 unsigned char blue = current_text_foreground->Blue();
  2530.                 unsigned char green = current_text_foreground->Green();
  2531.                 if (red == (unsigned char )255 && blue == (unsigned char)255
  2532.                      && green == (unsigned char)255)
  2533.                 {
  2534.                   pixel = WhitePixel(canvas->display, DefaultScreen(canvas->display));
  2535.                   current_colour = wxWHITE;
  2536.                 }
  2537.                 else
  2538.                 {
  2539.                   pixel = BlackPixel(canvas->display, DefaultScreen(canvas->display));
  2540.                   current_colour = wxBLACK;
  2541.                 }
  2542.               }
  2543.               else
  2544.           {
  2545.                 XColor exact_def;
  2546.                 exact_def.red = current_text_foreground->Red();
  2547.             exact_def.green = current_text_foreground->Green();
  2548.             exact_def.blue = current_text_foreground->Blue();
  2549.             exact_def.flags = DoRed | DoGreen | DoBlue;
  2550.  
  2551.             Colormap cmap = DefaultColormap(canvas->display, DefaultScreen(canvas->display));
  2552.             if (!XAllocColor(canvas->display, cmap, &exact_def))
  2553.             {
  2554.               pixel = BlackPixel(canvas->display, DefaultScreen(canvas->display));
  2555.               fprintf(stderr, "wxWindows warning: cannot allocate text colour; using black instead\n");
  2556.             }
  2557.             else
  2558.               pixel = exact_def.pixel;
  2559.           }
  2560.              // Set the GC to the required colour
  2561.              if (pixel > -1)
  2562.          {
  2563.                XSetForeground(canvas->display, gc, pixel);
  2564. #ifdef wx_motif
  2565.                if (canvas->is_retained)
  2566.                  XSetForeground(canvas->display, gcBacking, pixel);
  2567. #endif
  2568.          }
  2569.       }
  2570.     }
  2571.  
  2572.         // We need to add the ascent, not the whole height, since X draws
  2573.         // at the point above the descender.
  2574.         XDrawString(canvas->display, canvas->xwindow, gc, 
  2575.                       XLOG2DEV(x), YLOG2DEV(y)+ascent, text, strlen(text));
  2576. #ifdef wx_motif
  2577.         if (canvas->is_retained)
  2578.           XDrawString(canvas->display, canvas->backingPixmap, gcBacking, 
  2579.                         XLOG2DEV_2(x), YLOG2DEV_2(y)+ascent, text, strlen(text));
  2580. #endif
  2581.       }
  2582.       break;
  2583.     }
  2584. #endif
  2585.     case wxDEVICE_EPS:
  2586.     {
  2587.       if (font)
  2588.         SetFont(font);
  2589.  
  2590.       if (current_text_foreground)
  2591.       {
  2592.         unsigned char red = current_text_foreground->Red();
  2593.         unsigned char blue = current_text_foreground->Blue();
  2594.         unsigned char green = current_text_foreground->Green();
  2595.  
  2596.         if (!Colour)
  2597.         {
  2598.           // Anything not white is black
  2599.           if (!(red == (unsigned char )255 && blue == (unsigned char)255
  2600.                          && green == (unsigned char)255))
  2601.           {
  2602.             red = (unsigned char )0;
  2603.             green = (unsigned char )0;
  2604.             blue = (unsigned char )0;
  2605.           }
  2606.         }
  2607.         *pstream << (int)red << " " << (int)green << " " << (int)blue << " setrgbcolor\n";
  2608.       }
  2609.  
  2610.       int size = 10;
  2611.       if (font) size = font->point_size;
  2612.  
  2613.       *pstream << x << " " << YSCALE(y + size) << " moveto\n";
  2614.  
  2615.       *pstream << "(" << text << ")" << " show\n";
  2616.  
  2617.       CalcBoundingBox(x, YSCALE(y+size));
  2618.       CalcBoundingBox(x + size*strlen(text), YSCALE(y));
  2619.       break;
  2620.     }
  2621. #ifdef wx_msw
  2622.     case wxDEVICE_WINDOWS:
  2623.     {
  2624.       wxWnd *wnd = NULL;
  2625.  
  2626.       int xx1 = (int)x;
  2627.       int yy1 = (int)y;
  2628.  
  2629.       if (canvas)
  2630.       {
  2631.         wnd = (wxWnd *)canvas->handle;
  2632.         wnd->CalcScrolledPosition((int)x, (int)y, &xx1, &yy1);
  2633.       }
  2634.  
  2635.       HDC dc = NULL;
  2636.       if (cdc)
  2637.         dc = cdc;
  2638.       else
  2639.         dc = GetDC(wnd->handle);
  2640.  
  2641.       if (font && font->cfont)
  2642.       {
  2643.         HFONT f = ::SelectObject(dc, font->cfont);
  2644.         if (!old_font)
  2645.           old_font = f;
  2646.       }
  2647.  
  2648.       if (current_text_foreground)
  2649.         SetTextColor(dc, RGB(current_text_foreground->Red(),
  2650.                              current_text_foreground->Green(),
  2651.                              current_text_foreground->Blue()));
  2652.  
  2653.       DWORD old_background;
  2654.       if (current_text_background)
  2655.         old_background = SetBkColor(dc, RGB(current_text_background->Red(),
  2656.                                             current_text_background->Green(),
  2657.                                             current_text_background->Blue()));
  2658.  
  2659.       (void)TextOut(dc, XLOG2DEV(xx1), YLOG2DEV(yy1), text, strlen(text));
  2660.  
  2661.       if (current_text_background)
  2662.         (void)SetBkColor(dc, old_background);
  2663.  
  2664.       if (!cdc)
  2665.         ReleaseDC(wnd->handle, dc);
  2666.  
  2667.       break;
  2668.     }
  2669. #endif
  2670.   }
  2671. }
  2672.  
  2673. void wxDC::SetBackground(wxBrush *brush)
  2674. {
  2675.   current_background_brush = brush;
  2676.   switch (device)
  2677.   {
  2678. #ifdef wx_motif
  2679. #endif
  2680. #ifdef wx_x
  2681.     case wxDEVICE_CANVAS:
  2682.     {
  2683.       if (canvas)
  2684.       {
  2685.         XColor exact_def;
  2686.         exact_def.red = brush->colour->Red();
  2687.         exact_def.green = brush->colour->Green();
  2688.         exact_def.blue = brush->colour->Blue();
  2689.         exact_def.flags = DoRed | DoGreen | DoBlue;
  2690.         int pixel;
  2691.  
  2692.         Colormap cmap = DefaultColormap(canvas->display, DefaultScreen(canvas->display));
  2693.           
  2694.         if (!XAllocColor(canvas->display, cmap, &exact_def))
  2695.         {
  2696.           pixel = WhitePixel(canvas->display, DefaultScreen(canvas->display));
  2697.           cerr << "wxWindows warning: cannot allocate background colour; using white instead\n";
  2698.         }
  2699.         else
  2700.           pixel = exact_def.pixel;
  2701.  
  2702. #ifdef wx_xview
  2703.         // Finally, set the background to the required colour
  2704.         Xv_Window pw = canvas_paint_window((Canvas)(canvas->handle));
  2705.  
  2706.         Window win = (Window)xv_get(pw, XV_XID);
  2707.         XSetWindowBackground(canvas->display, win, pixel);
  2708. #endif
  2709. #ifdef wx_motif
  2710.         XSetWindowBackground(canvas->display, canvas->xwindow, pixel);
  2711.         if (canvas->is_retained)
  2712.           XSetWindowBackground(canvas->display, canvas->backingPixmap, pixel);
  2713. #endif
  2714.       }
  2715.       break;
  2716.     }
  2717. #endif
  2718.     case wxDEVICE_EPS:
  2719.     {
  2720.       break;
  2721.     }
  2722. #ifdef wx_msw
  2723.     case wxDEVICE_WINDOWS:
  2724.     {
  2725.       break;
  2726.     }
  2727. #endif
  2728.   }
  2729. }
  2730.  
  2731. void wxDC::SetLogicalFunction(int function)
  2732. {
  2733.   switch (device)
  2734.   {
  2735. #ifdef wx_x
  2736.     case wxDEVICE_CANVAS:
  2737.     {
  2738.       if (canvas)
  2739.       {
  2740.         int x_function;
  2741.         switch (function)
  2742.         {
  2743.           case wxXOR:  x_function = GXxor; break;
  2744.           case wxINVERT: x_function = GXinvert; break;
  2745.           case wxOR_REVERSE: x_function = GXorReverse; break;
  2746.           case wxAND_REVERSE: x_function = GXandReverse; break;
  2747.           case wxCOPY:
  2748.           default:
  2749.             x_function = GXcopy; break;
  2750.         }
  2751.  
  2752.         XSetFunction(canvas->display, gc, x_function);
  2753. #ifdef wx_motif
  2754.         if (canvas->is_retained)
  2755.           XSetFunction(canvas->display, gcBacking, x_function);
  2756. #endif
  2757.       }
  2758.       break;
  2759.     }
  2760. #endif
  2761.     case wxDEVICE_EPS:
  2762.     {
  2763.       break;
  2764.     }
  2765. #ifdef wx_msw
  2766.     case wxDEVICE_WINDOWS:
  2767.     {
  2768.       current_logical_function = function;
  2769.  
  2770.       HDC dc = NULL;
  2771.       wxWnd *wnd = NULL;
  2772.       if (canvas)
  2773.         wnd = (wxWnd *)canvas->handle;
  2774.       if (cdc)
  2775.         dc = cdc;
  2776.       else
  2777.         dc = GetDC(wnd->handle);
  2778.  
  2779.       SetRop(dc);
  2780.  
  2781.       if (!cdc)
  2782.         ReleaseDC(wnd->handle, dc);
  2783.     }
  2784. #endif
  2785.   }
  2786. }
  2787.  
  2788. #ifdef wx_msw
  2789. void wxDC::SetRop(HDC dc)
  2790. {
  2791.   if (!dc || current_logical_function < 0)
  2792.     return;
  2793.  
  2794.   int c_rop;
  2795.   // These may be wrong
  2796.   switch (current_logical_function)
  2797.   {
  2798.     case wxXOR: c_rop = R2_XORPEN; break;
  2799.     case wxINVERT: c_rop = R2_NOT; break;
  2800.     case wxOR_REVERSE: c_rop = R2_MERGEPENNOT; break;
  2801.     case wxAND_REVERSE: c_rop = R2_MASKNOTPEN; break;
  2802.     case wxCOPY:
  2803.     default:
  2804.       c_rop = R2_COPYPEN; break;
  2805.   }
  2806.   SetROP2(dc, c_rop);
  2807. }
  2808. #endif
  2809.  
  2810. // Make a 3-point spline
  2811. void wxDC::DrawSpline(float x1, float y1, float x2, float y2, float x3, float y3)
  2812. {
  2813.  
  2814.   wxList *point_list = new wxList;
  2815.  
  2816.   wxPoint *point1 = new wxPoint;
  2817.   point1->x = x1; point1->y = y1;
  2818.   point_list->Append(point1);
  2819.  
  2820.   wxPoint *point2 = new wxPoint;
  2821.   point2->x = x2; point2->y = y2;
  2822.   point_list->Append(point2);
  2823.  
  2824.   wxPoint *point3 = new wxPoint;
  2825.   point3->x = x3; point3->y = y3;
  2826.   point_list->Append(point3);
  2827.  
  2828.   wxSpline spline(point_list);
  2829.  
  2830.   if (device == wxDEVICE_EPS)
  2831.   {
  2832.     wx_draw_open_spline_ps(this, &spline);
  2833.   }
  2834.   else wx_draw_open_spline(this, &spline);
  2835.   spline.DeletePoints();
  2836. }
  2837.  
  2838. void wxDC::DrawSpline(wxList *list)
  2839. {
  2840.   wxSpline spline(list);
  2841.  
  2842.   if (device == wxDEVICE_EPS)
  2843.     wx_draw_open_spline_ps(this, &spline);
  2844.   else wx_draw_open_spline(this, &spline);
  2845. }
  2846.  
  2847.  
  2848. int wxDC::GetTextFamily(void)
  2849. {
  2850.   switch (device)
  2851.   {
  2852. #ifdef wx_x
  2853.     case wxDEVICE_CANVAS:
  2854.     {
  2855. #ifdef wx_motif
  2856.     if (!font)
  2857.       return -1;
  2858.     else return font->family;
  2859. #endif
  2860. #ifdef wx_xview
  2861.       if (!(font && font->x_font))
  2862.         return -1;
  2863.  
  2864.       // Is this the right syntax????
  2865.       char *family = (char *)xv_get((Xv_opaque)NULL, font->x_font, FONT_FAMILY);
  2866.       int wx_family;
  2867.  
  2868.       if (strcmp(family, FONT_FAMILY_LUCIDA) == 0)
  2869.         wx_family = wxDECORATIVE;
  2870.       else if (strcmp(family, FONT_FAMILY_ROMAN) == 0)
  2871.         wx_family = wxROMAN;
  2872.       else if (strcmp(family, FONT_FAMILY_HELVETICA) == 0)
  2873.         wx_family = wxSWISS;
  2874.      else if (strcmp(family, FONT_FAMILY_COUR) == 0)
  2875.         wx_family = wxMODERN;
  2876.       else
  2877.         wx_family = wxDEFAULT;
  2878.  
  2879.       return wx_family;
  2880. #endif
  2881.       break;
  2882.     }
  2883. #endif
  2884.     case wxDEVICE_EPS:
  2885.     {
  2886.       if (font)
  2887.         return font->family;
  2888.       else return wxDEFAULT;
  2889.       break;
  2890.     }
  2891. #ifdef wx_msw
  2892.     case wxDEVICE_WINDOWS:
  2893.     {
  2894.       TEXTMETRIC lpTextMetric;
  2895.       wxWnd *wnd = NULL;
  2896.  
  2897.       if (canvas)
  2898.         wnd = (wxWnd *)canvas->handle;
  2899.  
  2900.       HDC dc = NULL;
  2901.       if (cdc)
  2902.         dc = cdc;
  2903.       else
  2904.         dc = GetDC(wnd->handle);
  2905.  
  2906.       GetTextMetrics(dc, &lpTextMetric);
  2907.  
  2908.       if (!cdc)
  2909.         ReleaseDC(wnd->handle, dc);
  2910.  
  2911.       int family;
  2912.       switch (lpTextMetric.tmPitchAndFamily & 0xF0)
  2913.       {
  2914.         case FF_DECORATIVE:
  2915.           family = wxDECORATIVE;
  2916.           break;
  2917.         case FF_MODERN:
  2918.           family = wxMODERN;
  2919.           break;
  2920.         case FF_ROMAN:
  2921.           family = wxROMAN;
  2922.           break;
  2923.         case FF_SWISS:
  2924.           family = wxSWISS;
  2925.           break;
  2926.         default:
  2927.         case FF_DONTCARE:
  2928.           family = wxDEFAULT;
  2929.       }
  2930.       return family;
  2931.       break;
  2932.     }
  2933. #endif
  2934.   }
  2935.   return wxDEFAULT;
  2936. }
  2937.  
  2938. int wxDC::GetTextStyle(void)
  2939. {
  2940.   switch (device)
  2941.   {
  2942. #ifdef wx_x
  2943.     case wxDEVICE_CANVAS:
  2944.     {
  2945. #ifdef wx_motif
  2946.     if (!font)
  2947.       return -1;
  2948.     else return font->style;
  2949. #endif
  2950. #ifdef wx_xview
  2951.       if (!(font && font->x_font))
  2952.         return -1;
  2953.  
  2954.       // Is this the right syntax????
  2955.       char *style = (char *)xv_get((Xv_opaque)NULL, font->x_font, FONT_STYLE);
  2956.       int wx_style;
  2957.  
  2958.       if (strcmp(style, FONT_STYLE_NORMAL) == 0)
  2959.         wx_style = wxNORMAL;
  2960.       else if (strcmp(style, FONT_STYLE_BOLD) == 0)
  2961.         wx_style = wxNORMAL;
  2962.       else if (strcmp(style, FONT_STYLE_ITALIC) == 0)
  2963.         wx_style = wxITALIC;
  2964.       else if (strcmp(style, FONT_STYLE_BOLD_ITALIC) == 0)
  2965.         wx_style = wxITALIC;
  2966.       else if (strcmp(style, FONT_STYLE_OBLIQUE) == 0)
  2967.         wx_style = wxSLANT;
  2968.       else if (strcmp(style, FONT_STYLE_BOLD_OBLIQUE) == 0)
  2969.         wx_style = wxSLANT;
  2970.       else wx_style = wxDEFAULT;
  2971.  
  2972.       return wx_style;
  2973. #endif
  2974.       break;
  2975.     }
  2976. #endif
  2977.     case wxDEVICE_EPS:
  2978.     {
  2979.       if (font)
  2980.         return font->style;
  2981.       else return wxDEFAULT;
  2982.       break;
  2983.     }
  2984. #ifdef wx_msw
  2985.     case wxDEVICE_WINDOWS:
  2986.     {
  2987.       TEXTMETRIC lpTextMetric;
  2988.       wxWnd *wnd = NULL;
  2989.  
  2990.       if (canvas)
  2991.       {
  2992.         wnd = (wxWnd *)canvas->handle;
  2993.       }
  2994.  
  2995.       HDC dc = NULL;
  2996.  
  2997.       if (cdc)
  2998.         dc = cdc;
  2999.       else dc = GetDC(wnd->handle);
  3000.  
  3001.       GetTextMetrics(dc, &lpTextMetric);
  3002.  
  3003.       if (!cdc)
  3004.         ReleaseDC(wnd->handle, dc);
  3005.  
  3006.       int wx_style;
  3007.       if (lpTextMetric.tmItalic)
  3008.         wx_style = wxITALIC;
  3009.       else wx_style = wxNORMAL;
  3010.  
  3011.       return wx_style;
  3012.       break;
  3013.     }
  3014. #endif
  3015.   }
  3016.   return wxNORMAL;
  3017. }
  3018.  
  3019. int wxDC::GetTextWeight(void)
  3020. {
  3021.   switch (device)
  3022.   {
  3023. #ifdef wx_x
  3024.     case wxDEVICE_CANVAS:
  3025.     {
  3026. #ifdef wx_motif
  3027.       if (!font)
  3028.         return -1;
  3029.       else return font->weight;
  3030. #endif
  3031. #ifdef wx_xview
  3032.       if (!(font && font->x_font))
  3033.         return -1;
  3034.  
  3035.       char *style = (char *)xv_get((Xv_opaque)NULL, font->x_font, FONT_STYLE);
  3036.       int wx_weight;
  3037.  
  3038.       if (strcmp(style, FONT_STYLE_NORMAL) == 0)
  3039.         wx_weight = wxNORMAL;
  3040.       else if (strcmp(style, FONT_STYLE_BOLD) == 0)
  3041.         wx_weight = wxBOLD;
  3042.       else if (strcmp(style, FONT_STYLE_ITALIC) == 0)
  3043.         wx_weight = wxNORMAL;
  3044.       else if (strcmp(style, FONT_STYLE_BOLD_ITALIC) == 0)
  3045.         wx_weight = wxBOLD;
  3046.       else if (strcmp(style, FONT_STYLE_OBLIQUE) == 0)
  3047.         wx_weight = wxNORMAL;
  3048.       else if (strcmp(style, FONT_STYLE_BOLD_OBLIQUE) == 0)
  3049.         wx_weight = wxBOLD;
  3050.       else wx_weight = wxNORMAL;
  3051.  
  3052.       return wx_weight;
  3053. #endif
  3054.       break;
  3055.     }
  3056. #endif
  3057.     case wxDEVICE_EPS:
  3058.     {
  3059.       if (font)
  3060.         return font->weight;
  3061.       else return wxNORMAL;
  3062.       break;
  3063.     }
  3064. #ifdef wx_msw
  3065.     case wxDEVICE_WINDOWS:
  3066.     {
  3067.       TEXTMETRIC lpTextMetric;
  3068.       wxWnd *wnd = NULL;
  3069.  
  3070.       if (canvas)
  3071.       {
  3072.         wnd = (wxWnd *)canvas->handle;
  3073.       }
  3074.  
  3075.       HDC dc = NULL;
  3076.  
  3077.       if (cdc)
  3078.         dc = cdc;
  3079.       else dc = GetDC(wnd->handle);
  3080.  
  3081.       GetTextMetrics(dc, &lpTextMetric);
  3082.  
  3083.       if (!cdc)
  3084.         ReleaseDC(wnd->handle, dc);
  3085.  
  3086.       int wx_weight;
  3087.       int cweight = lpTextMetric.tmWeight;
  3088.       if (cweight > 0 && cweight < 350)
  3089.         wx_weight = wxLIGHT;  // light
  3090.       else if (cweight >= 350 && cweight < 500)
  3091.         wx_weight = wxNORMAL; // normal
  3092.       else if (cweight >= 500)
  3093.         wx_weight = wxBOLD; // bold
  3094.       else wx_weight = wxNORMAL;
  3095.  
  3096.       return wx_weight;
  3097.       break;
  3098.     }
  3099. #endif
  3100.   }
  3101.   return wxNORMAL;
  3102. }
  3103.  
  3104. float wxDC::GetTextHeight(void)
  3105. {
  3106.   switch (device)
  3107.   {
  3108. #ifdef wx_x
  3109.     case wxDEVICE_CANVAS:
  3110.     {
  3111. #ifdef wx_xview
  3112.       if (!(font && font->x_font))
  3113.         return YDEV2LOGREL(12);
  3114.  
  3115.       return YDEV2LOGREL((int)xv_get((Xv_opaque)NULL, font->x_font, FONT_DEFAULT_CHAR_HEIGHT));
  3116. #endif
  3117. #ifdef wx_motif
  3118.       if (!(font && font->xFont))
  3119.         return XDEV2LOGREL(12);
  3120.  
  3121.       int direction, ascent, descent;
  3122.       XCharStruct overall;
  3123.       XTextExtents(font->xFont, "x", 1, &direction, &ascent,
  3124.                    &descent, &overall);
  3125.       return overall.ascent + overall.descent;
  3126. #endif
  3127.       break;
  3128.     }
  3129. #endif
  3130.     case wxDEVICE_EPS:
  3131.     {
  3132.       if (font)
  3133.         return font->point_size;
  3134.       else return 12.0;
  3135.       break;
  3136.     }
  3137. #ifdef wx_msw
  3138.     case wxDEVICE_WINDOWS:
  3139.     {
  3140.       TEXTMETRIC lpTextMetric;
  3141.       wxWnd *wnd = NULL;
  3142.  
  3143.       if (canvas)
  3144.       {
  3145.         wnd = (wxWnd *)canvas->handle;
  3146.       }
  3147.  
  3148.       HDC dc = NULL;
  3149.  
  3150.       if (cdc)
  3151.         dc = cdc;
  3152.       else dc = GetDC(wnd->handle);
  3153.  
  3154.       GetTextMetrics(dc, &lpTextMetric);
  3155.  
  3156.       if (!cdc)
  3157.         ReleaseDC(wnd->handle, dc);
  3158.  
  3159.       return YDEV2LOGREL(lpTextMetric.tmHeight);
  3160.       break;
  3161.     }
  3162. #endif
  3163.   }
  3164.   return 12.0;
  3165. }
  3166.  
  3167. float wxDC::GetTextWidth(void)
  3168. {
  3169.   switch (device)
  3170.   {
  3171. #ifdef wx_x
  3172.     case wxDEVICE_CANVAS:
  3173.     {
  3174. #ifdef wx_xview
  3175.       if (!(font && font->x_font))
  3176.         return XDEV2LOGREL(16);
  3177.  
  3178.       return XDEV2LOGREL((int)xv_get((Xv_opaque)NULL, font->x_font, FONT_DEFAULT_CHAR_WIDTH));
  3179. #endif
  3180. #ifdef wx_motif
  3181.       if (!(font && font->xFont))
  3182.         return XDEV2LOGREL(16);
  3183.  
  3184.       int direction, ascent, descent;
  3185.       XCharStruct overall;
  3186.       XTextExtents(font->xFont, "x", 1, &direction, &ascent,
  3187.                    &descent, &overall);
  3188.       return overall.width;
  3189. #endif
  3190.       break;
  3191.     }
  3192. #endif
  3193.     case wxDEVICE_EPS:
  3194.     {
  3195.       return 0;
  3196.       break;
  3197.     }
  3198. #ifdef wx_msw
  3199.  
  3200.     case wxDEVICE_WINDOWS:
  3201.     {
  3202.       TEXTMETRIC lpTextMetric;
  3203.       wxWnd *wnd = NULL;
  3204.  
  3205.       if (canvas)
  3206.       {
  3207.         wnd = (wxWnd *)canvas->handle;
  3208.       }
  3209.  
  3210.       HDC dc = NULL;
  3211.  
  3212.       if (cdc)
  3213.         dc = cdc;
  3214.       else dc = GetDC(wnd->handle);
  3215.  
  3216.       GetTextMetrics(dc, &lpTextMetric);
  3217.  
  3218.       if (!cdc)
  3219.         ReleaseDC(wnd->handle, dc);
  3220.  
  3221.       return XDEV2LOGREL(lpTextMetric.tmAveCharWidth);
  3222.       break;
  3223.     }
  3224. #endif
  3225.   }
  3226.   return 0.0;
  3227. }
  3228.  
  3229. void wxDC::GetTextExtent(char *string, float *x, float *y)
  3230. {
  3231.   switch (device)
  3232.   {
  3233. #ifdef wx_x
  3234.     case wxDEVICE_CANVAS:
  3235.     {
  3236. #ifdef wx_xview
  3237.       if (!(font && font->x_font))
  3238.       {
  3239.         cerr << "wxWindows warning - set a font before calling GetTextExtent!\n";
  3240.         *x = -1;
  3241.         *y = -1;
  3242.         return;
  3243.       }
  3244.  
  3245.       Font_string_dims dims;
  3246.  
  3247.       (void)xv_get(font->x_font, FONT_STRING_DIMS, string, &dims);
  3248.       *x = XDEV2LOGREL(dims.width);
  3249.       *y = YDEV2LOGREL(dims.height);
  3250. #endif
  3251. #ifdef wx_motif
  3252.       if (!(font && font->xFont))
  3253.       {
  3254.         cerr << "wxWindows warning - set a font before calling GetTextExtent!\n";
  3255.         *x = -1;
  3256.         *y = -1;
  3257.         return;
  3258.       }
  3259.       int direction, ascent, descent;
  3260.       XCharStruct overall;
  3261.       XTextExtents(font->xFont, string, strlen(string), &direction, &ascent,
  3262.                    &descent, &overall);
  3263. //      *x = XDEV2LOGREL(overall.width);
  3264. //      *y = YDEV2LOGREL(overall.ascent + overall.descent);
  3265.       *x = XDEV2LOGREL(overall.width);
  3266.       *y = YDEV2LOGREL(ascent + descent);
  3267. #endif
  3268.       break;
  3269.     }
  3270. #endif
  3271.     case wxDEVICE_EPS:
  3272.     {
  3273.       // Provide a VERY rough estimate (avoid using it)
  3274.       int width = 12;
  3275.       int height = 12;
  3276.  
  3277.       if (font)
  3278.         { height = font->point_size; width = height; }
  3279.       *x = strlen(string)*width;
  3280.       *y = strlen(string)*height;
  3281.       break;
  3282.     }
  3283. #ifdef wx_msw
  3284.     case wxDEVICE_WINDOWS:
  3285.     {
  3286.       TEXTMETRIC lpTextMetric;
  3287.       wxWnd *wnd = NULL;
  3288.  
  3289.       if (canvas)
  3290.       {
  3291.         wnd = (wxWnd *)canvas->handle;
  3292.       }
  3293.  
  3294.       HDC dc = NULL;
  3295.  
  3296.       if (cdc)
  3297.         dc = cdc;
  3298.       else dc = GetDC(wnd->handle);
  3299.  
  3300.       GetTextMetrics(dc, &lpTextMetric);
  3301.  
  3302.       SIZE sizeRect;
  3303.       GetTextExtentPoint(dc, string, strlen(string), &sizeRect);
  3304.  
  3305.       if (!cdc)
  3306.         ReleaseDC(wnd->handle, dc);
  3307.  
  3308.       *x = XDEV2LOGREL(sizeRect.cx);
  3309.       *y = YDEV2LOGREL(sizeRect.cy);
  3310.       break;
  3311.     }
  3312. #endif
  3313.   }
  3314. }
  3315.  
  3316. Bool wxDC::Ok(void)
  3317. {
  3318.   return ok;
  3319. }
  3320.  
  3321. #define ELLIPSE_PS  "\
  3322. /ellipsedict 8 dict def\n\
  3323. ellipsedict /mtrx matrix put\n\
  3324. /ellipse\n\
  3325. { ellipsedict begin\n\
  3326.   /endangle exch def\n\
  3327.   /startangle exch def\n\
  3328.   /yrad exch def\n\
  3329.   /xrad exch def\n\
  3330.   /y exch def\n\
  3331.   /x exch def\n\
  3332.   /savematrix mtrx currentmatrix def\n\
  3333.   x y translate\n\
  3334.   xrad yrad scale\n\
  3335.   0 0 1 startangle endangle arc\n\
  3336.   savematrix setmatrix\n\
  3337.   end\n\
  3338.   } def\n\
  3339. "
  3340.  
  3341. #define        SPLINE_PS    " \
  3342. /DrawSplineSection {\n\
  3343.     /y3 exch def\n\
  3344.     /x3 exch def\n\
  3345.     /y2 exch def\n\
  3346.     /x2 exch def\n\
  3347.     /y1 exch def\n\
  3348.     /x1 exch def\n\
  3349.     /xa x1 x2 x1 sub 0.666667 mul add def\n\
  3350.     /ya y1 y2 y1 sub 0.666667 mul add def\n\
  3351.     /xb x3 x2 x3 sub 0.666667 mul add def\n\
  3352.     /yb y3 y2 y3 sub 0.666667 mul add def\n\
  3353.     x1 y1 lineto\n\
  3354.     xa ya xb yb x3 y3 curveto\n\
  3355.     } def\n\
  3356. "
  3357.  
  3358. Bool wxDC::StartDoc(char *message)
  3359. {
  3360.   Bool flag = FALSE;
  3361.   switch (device)
  3362.   {
  3363.     case wxDEVICE_EPS:
  3364.     {
  3365.       if (message) title = copystring(message);
  3366.       flag = TRUE;
  3367.       break;
  3368.     }
  3369. #ifdef wx_msw
  3370.     case wxDEVICE_WINDOWS:
  3371.     {
  3372.       DOCINFO docinfo;
  3373.       docinfo.cbSize = sizeof(DOCINFO);
  3374.       docinfo.lpszDocName = message;
  3375.       docinfo.lpszOutput = filename;
  3376.       if (cdc) flag = ::StartDoc(cdc, &docinfo);
  3377.       else flag = FALSE;
  3378.       break;
  3379.     }
  3380. #endif
  3381.     default:
  3382.       break;
  3383.   }
  3384.   return flag;
  3385. }
  3386.  
  3387. void wxDC::EndDoc(void)
  3388. {
  3389.   switch (device)
  3390.   {
  3391.     case wxDEVICE_EPS:
  3392.     {
  3393.       if (clipping) { clipping = FALSE; *pstream << "grestore\n"; }
  3394.  
  3395.       // Will reuse pstream for header
  3396.       if (pstream) { delete pstream; pstream = NULL; }
  3397.  
  3398. #ifdef wx_x
  3399.       char buf[300];
  3400.       long when;
  3401. #endif
  3402. #ifdef wx_msw
  3403.       time_t when;
  3404. #endif
  3405.       (void) time(&when);
  3406.  
  3407.       // Write header now
  3408. #ifdef wx_x
  3409.       char *header_file = "/tmp/_header.ps";
  3410. #endif
  3411. #ifdef wx_msw
  3412.       char *header_file = "_header.ps";
  3413. #endif
  3414.       pstream = new ofstream(header_file);
  3415.  
  3416.       *pstream << "%!\n";   /* PostScript magic strings */
  3417.       if (title) *pstream << "%%Title: " << title << "\n";
  3418.       *pstream << "%%Creator: " << wxTheApp->argv[0] << "\n";
  3419.       *pstream << "%%CreationDate: " << ctime(&when);
  3420. #ifdef wx_x
  3421.       char host[256];
  3422.       struct passwd *who = getpwuid(getuid());
  3423.       if (-1 == gethostname(host, sizeof(host)))
  3424.         (void)strcpy(host, "unknown-host!");
  3425.       *pstream << "%%For: " << who->pw_name << "@" << host << " (" <<
  3426.         who->pw_gecos << ")\n";
  3427. #endif
  3428.       // In landscape mode, what should bounding box be changed to????
  3429.       // Bounding box is currently wrong in landscape mode.
  3430.  
  3431.       *pstream << "%%BoundingBox: " << min_x << " " << min_y << " " << max_x << " " << max_y << "\n";
  3432.       *pstream << "%%EndComments\n\n";
  3433.  
  3434.       // Output scaling
  3435.       float real_translate_y = wx_printer_translate_y;
  3436.       if (!wx_portrait)
  3437.       {
  3438.         real_translate_y -= max_y;
  3439.         *pstream << "90 rotate\n";
  3440.       }
  3441.  
  3442.       *pstream << wx_printer_scale_x << " " << wx_printer_scale_y << " scale\n";
  3443.       *pstream << wx_printer_translate_x << " " << real_translate_y << " translate\n";
  3444.  
  3445.       *pstream << ELLIPSE_PS;
  3446.       *pstream << SPLINE_PS;
  3447.  
  3448.       delete pstream;
  3449.       pstream = NULL;
  3450.  
  3451. #ifdef wx_x
  3452.       char *concat_name = "/tmp/_concat.tmp";
  3453. #endif
  3454. #ifdef wx_msw
  3455.       char *concat_name = "concat.tmp";
  3456. #endif
  3457.  
  3458.       // Would be better not to write to wx_printer_file initially,
  3459.       // clear up sometime
  3460.       wxConcatFiles(header_file, wx_printer_file, concat_name);
  3461.       wxRemoveFile(wx_printer_file);
  3462.       wxCopyFile(concat_name, wx_printer_file);
  3463.       wxRemoveFile(concat_name);
  3464.       wxRemoveFile(header_file);
  3465. #ifdef wx_x
  3466.       if (wx_interactive)
  3467.       {
  3468.         if (ok && wx_preview)
  3469.         {
  3470.           strcpy(buf, wx_preview_command);
  3471.           strcat(buf, " ");
  3472.           strcat(buf, wx_printer_file);
  3473.           strcat(buf, " &");
  3474.           system(buf);
  3475.         }
  3476.         else if (ok && !wx_preview && !wx_print_to_file)
  3477.         {
  3478.           strcpy(buf, wx_printer_command);
  3479.           strcat(buf, " ");
  3480.           strcat(buf, wx_printer_flags);
  3481.           strcat(buf, " ");
  3482.           strcat(buf, wx_printer_file);
  3483.           strcat(buf, " &");
  3484.           system(buf);
  3485.         }
  3486.       }
  3487. #endif
  3488.       break;
  3489.     }
  3490. #ifdef wx_msw
  3491.     case wxDEVICE_WINDOWS:
  3492.     {
  3493.       if (cdc) ::EndDoc(cdc);
  3494.       break;
  3495.     }
  3496. #endif
  3497.   }
  3498. }
  3499.  
  3500. void wxDC::GetSize(float *width, float *height)
  3501. {
  3502.   switch (device)
  3503.   {
  3504.     case wxDEVICE_EPS:
  3505.     {
  3506.       if (!(min_x == 1000.0 && min_y == 1000.0 && max_x == -1000.0 && max_y == -1000.0))
  3507.       {
  3508.         *width = (float)(max_x - min_x);
  3509.         *height = (float)(max_y - min_y);
  3510.       }
  3511.       else
  3512.       {
  3513.         *width = 0.0;
  3514.         *height = 0.0;
  3515.       }
  3516.       break;
  3517.     }
  3518.     default:
  3519.     {
  3520.       *width = 0.0; *height = 0.0;
  3521.       break;
  3522.     }
  3523.   }
  3524. }
  3525.  
  3526. void wxDC::StartPage(void)
  3527. {
  3528.   switch (device)
  3529.   {
  3530. #ifdef wx_msw
  3531.     case wxDEVICE_WINDOWS:
  3532.     {
  3533.       if (cdc)
  3534.         ::StartPage(cdc);
  3535.       break;
  3536.     }
  3537. #endif
  3538.     default:
  3539.       break;
  3540.   }
  3541. }
  3542.  
  3543. void wxDC::EndPage(void)
  3544. {
  3545.   switch (device)
  3546.   {
  3547.     case wxDEVICE_EPS:
  3548.     {
  3549.       *pstream << "showpage\n";
  3550.       break;
  3551.     }
  3552. #ifdef wx_msw
  3553.     case wxDEVICE_WINDOWS:
  3554.     {
  3555.       if (cdc)
  3556.         ::EndPage(cdc);
  3557.       break;
  3558.     }
  3559. #endif
  3560.     default:
  3561.       break;
  3562.   }
  3563. }
  3564.  
  3565. void wxDC::SetMapMode(int mode)
  3566. {
  3567.   mapping_mode = mode;
  3568.  
  3569.   int pixel_width = 0;
  3570.   int pixel_height = 0;
  3571.   int mm_width = 0;
  3572.   int mm_height = 0;
  3573.  
  3574.   switch (device)
  3575.   {
  3576. #ifdef wx_x
  3577.     case wxDEVICE_CANVAS:
  3578.     {
  3579.       // First, calculate how to scale from mm to pixels.
  3580.       // Then we just need to find the scaling factor from ? to mm and multiply
  3581.       // by the first scaling factor.
  3582. #ifdef wx_xview
  3583.       Xv_Screen screen = xv_get(xview_server, SERVER_NTH_SCREEN, 0);
  3584.       Xv_Window root_window = xv_get(screen, XV_ROOT);
  3585.  
  3586.       Display *dpy = (Display *)xv_get(root_window, XV_DISPLAY);
  3587. #endif
  3588. #ifdef wx_motif
  3589.       Display *dpy = NULL;
  3590.       if (wxTheApp->wx_frame)
  3591.       {
  3592.         dpy = XtDisplay(wxTheApp->wx_frame->frameShell);
  3593.       } else if (canvas)
  3594.       {
  3595.         dpy = XtDisplay(canvas->scrolledWindow);
  3596.       }
  3597. #endif
  3598.  
  3599.       int screen_no = DefaultScreen(dpy);
  3600.       pixel_width = DisplayWidth(dpy, screen_no);
  3601.       pixel_height = DisplayHeight(dpy, screen_no);
  3602.       mm_width = DisplayWidthMM(dpy, screen_no);
  3603.       mm_height = DisplayHeightMM(dpy, screen_no);
  3604.       break;
  3605.     }
  3606. #endif
  3607.     case wxDEVICE_EPS:
  3608.     {
  3609.       return;
  3610.       break;
  3611.     }
  3612. #ifdef wx_msw
  3613.     case wxDEVICE_WINDOWS:
  3614.     {
  3615.       HDC dc = NULL;
  3616.       wxWnd *wnd = NULL;
  3617.       if (canvas)
  3618.         wnd = (wxWnd *)canvas->handle;
  3619.  
  3620.       if (cdc)
  3621.         dc = cdc;
  3622.       else if (wnd)
  3623.         dc = GetDC(wnd->handle);
  3624.  
  3625.       pixel_width = GetDeviceCaps(dc, HORZRES);
  3626.       pixel_height = GetDeviceCaps(dc, VERTRES);
  3627.       mm_width = GetDeviceCaps(dc, HORZSIZE);
  3628.       mm_height = GetDeviceCaps(dc, VERTSIZE);
  3629.       if (!cdc)
  3630.         ReleaseDC(wnd->handle, dc);
  3631.       break;
  3632.     }
  3633. #endif
  3634.   }
  3635.   float mm2pixelsX = pixel_width/mm_width;
  3636.   float mm2pixelsY = pixel_height/mm_height;
  3637.  
  3638.   switch (mode)
  3639.   {
  3640.     case MM_TWIPS:
  3641.     {
  3642.       logical_scale_x = (float)(twips2mm * mm2pixelsX);
  3643.       logical_scale_y = (float)(twips2mm * mm2pixelsY);
  3644.       break;
  3645.     }
  3646.     case MM_POINTS:
  3647.     {
  3648.       logical_scale_x = (float)(pt2mm * mm2pixelsX);
  3649.       logical_scale_y = (float)(pt2mm * mm2pixelsY);
  3650.       break;
  3651.     }
  3652.     case MM_METRIC:
  3653.     {
  3654.       logical_scale_x = mm2pixelsX;
  3655.       logical_scale_y = mm2pixelsY;
  3656.       break;
  3657.     }
  3658.     case MM_LOMETRIC:
  3659.     {
  3660.       logical_scale_x = (float)(mm2pixelsX/10.0);
  3661.       logical_scale_y = (float)(mm2pixelsY/10.0);
  3662.       break;
  3663.     }
  3664.     default:
  3665.     case MM_TEXT:
  3666.     {
  3667.       logical_scale_x = 1.0;
  3668.       logical_scale_y = 1.0;
  3669.       break;
  3670.     }
  3671.   }
  3672. #ifdef wx_msw
  3673.   if (device == wxDEVICE_WINDOWS)
  3674.   {
  3675.     HDC dc = NULL;
  3676.     wxWnd *wnd = NULL;
  3677.     if (canvas)
  3678.       wnd = (wxWnd *)canvas->handle;
  3679.  
  3680.     if (cdc)
  3681.       dc = cdc;
  3682.     else if (wnd)
  3683.       dc = GetDC(wnd->handle);
  3684.  
  3685.     ::SetMapMode(dc, MM_ANISOTROPIC);
  3686.     SetViewportExtEx(dc, VIEWPORT_EXTENT, VIEWPORT_EXTENT, NULL);
  3687.     window_ext_x = MS_XDEV2LOG(VIEWPORT_EXTENT);
  3688.     window_ext_y = MS_YDEV2LOG(VIEWPORT_EXTENT);
  3689.     SetWindowExtEx(dc, window_ext_x, window_ext_y, NULL);
  3690.  
  3691.     if (!cdc)
  3692.       ReleaseDC(wnd->handle, dc);
  3693.   }
  3694. #endif
  3695. }
  3696.  
  3697. int wxDC::GetMapMode(void)
  3698. {
  3699.   return mapping_mode;
  3700. }
  3701.  
  3702. void wxDC::SetLogicalOrigin(float x, float y)
  3703. {
  3704.   logical_origin_x = x;
  3705.   logical_origin_y = y;
  3706. }
  3707.  
  3708. void wxDC::SetDeviceOrigin(float x, float y)
  3709. {
  3710.   device_origin_x = x;
  3711.   device_origin_y = y;
  3712. }
  3713.  
  3714. // For use by wxWindows only, unless custom units are required.
  3715. void wxDC::SetLogicalScale(float x, float y)
  3716. {
  3717.   logical_scale_x = x;
  3718.   logical_scale_y = y;
  3719. }
  3720.  
  3721. void wxDC::SetUserScale(float x, float y)
  3722. {
  3723.   user_scale_x = x;
  3724.   user_scale_y = y;
  3725.  
  3726. #ifdef wx_msw
  3727.   SetMapMode(mapping_mode);
  3728. #endif
  3729. #ifdef wx_x
  3730.   // Force recalculation of line width
  3731.   wxPen *old_pen = current_pen;
  3732.   if (old_pen)
  3733.   {
  3734.     current_pen = NULL;
  3735.     SetPen(old_pen);
  3736.   }
  3737. #endif
  3738. }
  3739.  
  3740. float wxDC::DeviceToLogicalX(int x)
  3741. {
  3742. #ifdef wx_x
  3743.   return XDEV2LOG(x);
  3744. #endif
  3745. #ifdef wx_msw
  3746.   return MS_XDEV2LOG(x);
  3747. #endif
  3748. }
  3749.  
  3750. float wxDC::DeviceToLogicalY(int y)
  3751. {
  3752. #ifdef wx_x
  3753.   return YDEV2LOG(y);
  3754. #endif
  3755. #ifdef wx_msw
  3756.   return MS_YDEV2LOG(y);
  3757. #endif
  3758. }
  3759.  
  3760. int wxDC::LogicalToDeviceX(float x)
  3761. {
  3762. #ifdef wx_x
  3763.   return XLOG2DEV(x);
  3764. #endif
  3765. #ifdef wx_msw
  3766.   return MS_XLOG2DEV(x);
  3767. #endif
  3768. }
  3769.  
  3770. int wxDC::LogicalToDeviceY(float y)
  3771. {
  3772. #ifdef wx_x
  3773.   return YLOG2DEV(y);
  3774. #endif
  3775. #ifdef wx_msw
  3776.   return MS_YLOG2DEV(y);
  3777. #endif
  3778. }
  3779.  
  3780. void wxDC::CalcBoundingBox(float x, float y)
  3781. {
  3782.   if (x < min_x)
  3783.     min_x = x;
  3784.   if (y < min_y)
  3785.     min_y = y;
  3786.  
  3787.   if (x > max_x)
  3788.     max_x = x;
  3789.  
  3790.   if (y > max_y)
  3791.     max_y = y;
  3792. }
  3793.  
  3794. // Creates a memory DC
  3795. wxDC *wxDC::CreateCompatibleDC(void)
  3796. {
  3797.   wxDC *wxdc = new wxDC(this);
  3798.   return wxdc;
  3799. }
  3800.  
  3801. void wxDC::SelectObject(wxBitmap *bitmap)
  3802. {
  3803.   switch (device)
  3804.   {
  3805. #ifdef wx_x
  3806.     case wxDEVICE_CANVAS:
  3807.       return;
  3808.     case wxDEVICE_PIXMAP:
  3809.     {
  3810.       selected_pixmap = bitmap;
  3811.       return;
  3812.     }
  3813. #endif
  3814.     case wxDEVICE_EPS:
  3815.       return;
  3816. #ifdef wx_msw
  3817.     case wxDEVICE_WINDOWS:
  3818.     {
  3819.       HBITMAP bm = ::SelectObject(cdc, bitmap->ms_bitmap);
  3820.       if (!old_bitmap)
  3821.         old_bitmap = bm;
  3822.       return;
  3823.     }
  3824. #endif
  3825.   }
  3826. }
  3827.  
  3828. Bool wxDC::Blit(float xdest, float ydest, float width, float height,
  3829.                 wxDC *source, float xsrc, float ysrc, int rop)
  3830. {
  3831.   switch (device)
  3832.   {
  3833. #ifdef wx_x
  3834.     case wxDEVICE_CANVAS:
  3835.     {
  3836.       if (source->device == wxDEVICE_PIXMAP)
  3837.       {
  3838.         wxBitmap *bitmap = source->selected_pixmap;
  3839.         if (bitmap && bitmap->x_pixmap)
  3840.     {
  3841. #ifdef wx_xview
  3842.           Xv_Screen screen = xv_get(xview_server, SERVER_NTH_SCREEN, 0);
  3843.           Xv_Window root_window = xv_get(screen, XV_ROOT);
  3844.           Canvas xview_canvas = (Canvas)canvas->handle;
  3845.           Xv_Window paint_window = (Xv_Window)xv_get(xview_canvas, CANVAS_NTH_PAINT_WINDOW, 0);
  3846.           Window canvas_window = (Window)xv_get(paint_window, XV_XID);
  3847.  
  3848.           Display *dpy = (Display *)xv_get(root_window, XV_DISPLAY);
  3849. #endif
  3850. #ifdef wx_motif
  3851.           Display *dpy = canvas->display;
  3852.           Window canvas_window = canvas->xwindow;
  3853.  
  3854.           if (canvas->is_retained)
  3855.             XCopyPlane(dpy, bitmap->x_pixmap, canvas->backingPixmap, gcBacking,
  3856.                        (int)source->LogicalToDeviceX(xsrc), (int)source->LogicalToDeviceY(ysrc), (int)width, (int)height,
  3857.                        (int)XLOG2DEV_2(xdest), (int)YLOG2DEV_2(ydest), 1);
  3858. #endif
  3859.           XCopyPlane(dpy, bitmap->x_pixmap, canvas_window, gc,
  3860.                      (int)source->LogicalToDeviceX(xsrc), (int)source->LogicalToDeviceY(ysrc), (int)width, (int)height,
  3861.                      (int)XLOG2DEV(xdest), (int)YLOG2DEV(ydest), 1);
  3862.  
  3863.           return TRUE;
  3864.     }
  3865.       }
  3866.       return FALSE;
  3867.     }
  3868.  
  3869.     case wxDEVICE_PIXMAP:
  3870.       return FALSE;
  3871. #endif
  3872.     case wxDEVICE_EPS:
  3873.       return FALSE;
  3874. #ifdef wx_msw
  3875.     case wxDEVICE_WINDOWS:
  3876.     {
  3877.       wxWnd *wnd = NULL;
  3878.       wxWnd *wnd_src = NULL;
  3879.       if (canvas)
  3880.         wnd = (wxWnd *)canvas->handle;
  3881.       if (source->canvas)
  3882.         wnd_src = (wxWnd *)source->canvas->handle;
  3883.  
  3884.       HDC dc = NULL;
  3885.       if (cdc)
  3886.         dc = cdc;
  3887.       else
  3888.         dc = GetDC(wnd->handle);
  3889.  
  3890.       HDC dc_src = NULL;
  3891.       if (source->cdc)
  3892.         dc_src = source->cdc;
  3893.       else if (wnd)
  3894.         dc_src = GetDC(wnd_src->handle);
  3895.  
  3896.       int xdest1 = (int)xdest;
  3897.       int ydest1 = (int)ydest;
  3898.       int xsrc1 = (int)xsrc;
  3899.       int ysrc1 = (int)ysrc;
  3900.  
  3901.       if (canvas)
  3902.       {
  3903.         wnd->CalcScrolledPosition((int)xdest, (int)ydest, &xdest1, &ydest1);
  3904.       }
  3905.       if (source->canvas)
  3906.       {
  3907.         wnd_src->CalcScrolledPosition((int)xsrc, (int)ysrc, &xsrc1, &ysrc1);
  3908.       }
  3909.  
  3910.       Bool success = BitBlt(dc, xdest1, ydest1, (int)width, (int)height, dc_src,
  3911.                                 xsrc1, ysrc1, 
  3912.                 rop == wxCOPY ? SRCCOPY :
  3913.                 rop == wxINVERT ? NOTSRCCOPY :
  3914.                 rop == wxXOR ? SRCINVERT :
  3915.                 rop == wxOR_REVERSE ? MERGEPAINT :
  3916.                 rop == wxAND_REVERSE ? SRCERASE :
  3917.                 SRCCOPY);
  3918.  
  3919.       if (!cdc)
  3920.         ReleaseDC(wnd->handle, dc);
  3921.       if (!source->cdc)
  3922.         ReleaseDC(wnd_src->handle, dc_src);
  3923.       return success;
  3924.       break;
  3925.     }
  3926. #endif
  3927.   }
  3928.   return FALSE;
  3929. }
  3930.  
  3931. /***************************************************************************
  3932.  * Spline code taken from xfig - see below   
  3933.  *
  3934.  * FIG : Facility for Interactive Generation of figures
  3935.  * Copyright (c) 1985 by Supoj Sutanthavibul
  3936.  *
  3937.  * "Permission to use, copy, modify, distribute, and sell this software and its
  3938.  * documentation for any purpose is hereby granted without fee, provided that
  3939.  * the above copyright notice appear in all copies and that both that
  3940.  * copyright notice and this permission notice appear in supporting
  3941.  * documentation, and that the name of M.I.T. not be used in advertising or
  3942.  * publicity pertaining to distribution of the software without specific,
  3943.  * written prior permission.  M.I.T. makes no representations about the
  3944.  * suitability of this software for any purpose.  It is provided "as is"
  3945.  * without express or implied warranty."
  3946.  *
  3947.  **************************************************************************/
  3948.  
  3949. wxList wx_spline_point_list;
  3950.  
  3951. void wx_draw_open_spline(wxDC *dc, wxSpline *spline)
  3952. {
  3953.     wxPoint *p;
  3954.     float           cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4;
  3955.     float           x1, y1, x2, y2;
  3956.  
  3957.     wxNode *node = spline->points->First();
  3958.     p = (wxPoint *)node->Data();
  3959.  
  3960.     x1 = p->x;
  3961.     y1 = p->y;
  3962.  
  3963.     node = node->Next();
  3964.     p = (wxPoint *)node->Data();
  3965.  
  3966.     x2 = p->x;
  3967.     y2 = p->y;
  3968.     cx1 = (float)((x1 + x2) / 2);
  3969.     cy1 = (float)((y1 + y2) / 2);
  3970.     cx2 = (float)((cx1 + x2) / 2);
  3971.     cy2 = (float)((cy1 + y2) / 2);
  3972.  
  3973.     wx_spline_add_point((int) x1, (int) y1);
  3974.  
  3975.     node = node->Next();
  3976.  
  3977.     while (node)
  3978.     {
  3979.         p = (wxPoint *)node->Data();
  3980.     x1 = x2;
  3981.     y1 = y2;
  3982.     x2 = p->x;
  3983.     y2 = p->y;
  3984.         cx4 = (float)(x1 + x2) / 2;
  3985.         cy4 = (float)(y1 + y2) / 2;
  3986.         cx3 = (float)(x1 + cx4) / 2;
  3987.         cy3 = (float)(y1 + cy4) / 2;
  3988.  
  3989.         wx_quadratic_spline(cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4);
  3990.  
  3991.     cx1 = cx4;
  3992.     cy1 = cy4;
  3993.         cx2 = (float)(cx1 + x2) / 2;
  3994.         cy2 = (float)(cy1 + y2) / 2;
  3995.  
  3996.         node = node->Next();
  3997.     }
  3998.  
  3999.     wx_spline_add_point(wx_round(cx1), wx_round(cy1));
  4000.     wx_spline_add_point((int) x2, (int) y2);
  4001.  
  4002.     wx_spline_draw_point_array(dc);
  4003.  
  4004. }
  4005.  
  4006. void wx_draw_open_spline_ps(wxDC *dc, wxSpline *s)
  4007. {
  4008.     double        a, b, c, d, x1, y1, x2, y2, x3, y3;
  4009.         wxPoint *p, *q;
  4010.         dc->SetPen(dc->current_pen);
  4011.  
  4012.         wxNode *node = s->points->First();
  4013.         p = (wxPoint *)node->Data();
  4014.  
  4015.     x1 = p->x; y1 = p->y;
  4016.  
  4017.         node = node->Next();
  4018.         p = (wxPoint *)node->Data();
  4019.     c = p->x; d = p->y;
  4020.         x3 = a = (float)(x1 + c) / 2;
  4021.         y3 = b = (float)(y1 + d) / 2;
  4022.  
  4023.         *(dc->pstream) << "newpath " << x1 << " " << dc->yorigin - y1 << " moveto " << x3 << " " << dc->yorigin - y3;
  4024.         *(dc->pstream) << " lineto\n";
  4025.         dc->CalcBoundingBox((float)x1, (float)(dc->yorigin - y1));
  4026.         dc->CalcBoundingBox((float)x3, (float)(dc->yorigin - y3));
  4027.  
  4028.         node = node->Next();
  4029.  
  4030.         while (node)
  4031.     {
  4032.           q = (wxPoint *)node->Data();
  4033.  
  4034.       x1 = x3; y1 = y3;
  4035.       x2 = c;  y2 = d;
  4036.       c = q->x; d = q->y;
  4037.           x3 = (float)(x2 + c) / 2;
  4038.           y3 = (float)(y2 + d) / 2;
  4039.           *(dc->pstream) << x1 << " " << dc->yorigin - y1 << " " << x2 << " " << dc->yorigin - y2 << " ";
  4040.           *(dc->pstream) << x3 << " " << dc->yorigin - y3 << " DrawSplineSection\n";
  4041.  
  4042.           dc->CalcBoundingBox((float)x1, (float)(dc->yorigin - y1));
  4043.           dc->CalcBoundingBox((float)x3, (float)(dc->yorigin - y3));
  4044.  
  4045.  
  4046.          node = node->Next();
  4047.         }
  4048.     /*
  4049.     * At this point, (x2,y2) and (c,d) are the position of the 
  4050.     * next-to-last and last point respectively, in the point list
  4051.     */
  4052.         *(dc->pstream) << c << " " << dc->yorigin - d << " lineto stroke\n";
  4053. }
  4054.  
  4055. /********************* CURVES FOR SPLINES *****************************
  4056.  
  4057.     The following spline drawing routine is from
  4058.  
  4059.     "An Algorithm for High-Speed Curve Generation"
  4060.     by George Merrill Chaikin,
  4061.     Computer Graphics and Image Processing, 3, Academic Press,
  4062.     1974, 346-349.
  4063.  
  4064.     and
  4065.  
  4066.     "On Chaikin's Algorithm" by R. F. Riesenfeld,
  4067.     Computer Graphics and Image Processing, 4, Academic Press,
  4068.     1975, 304-310.
  4069.  
  4070. ***********************************************************************/
  4071.  
  4072. #define        half(z1, z2)    ((z1+z2)/2.0)
  4073. #define        THRESHOLD    5
  4074.  
  4075. /* iterative version */
  4076.  
  4077. void wx_quadratic_spline(float a1, float b1, float a2, float b2, float a3, float b3, float a4,
  4078.                  float b4)
  4079. {
  4080.     register float  xmid, ymid;
  4081.     float           x1, y1, x2, y2, x3, y3, x4, y4;
  4082.  
  4083.     wx_clear_stack();
  4084.     wx_spline_push(a1, b1, a2, b2, a3, b3, a4, b4);
  4085.  
  4086.     while (wx_spline_pop(&x1, &y1, &x2, &y2, &x3, &y3, &x4, &y4)) {
  4087.         xmid = (float)half(x2, x3);
  4088.         ymid = (float)half(y2, y3);
  4089.     if (fabs(x1 - xmid) < THRESHOLD && fabs(y1 - ymid) < THRESHOLD &&
  4090.         fabs(xmid - x4) < THRESHOLD && fabs(ymid - y4) < THRESHOLD) {
  4091.             wx_spline_add_point(wx_round(x1), wx_round(y1));
  4092.             wx_spline_add_point(wx_round(xmid), wx_round(ymid));
  4093.     } else {
  4094.             wx_spline_push(xmid, ymid, (float)half(xmid, x3), (float)half(ymid, y3),
  4095.                  (float)half(x3, x4), (float)half(y3, y4), x4, y4);
  4096.             wx_spline_push(x1, y1, (float)half(x1, x2), (float)half(y1, y2),
  4097.                  (float)half(x2, xmid), (float)half(y2, ymid), xmid, ymid);
  4098.     }
  4099.     }
  4100. }
  4101.  
  4102.  
  4103. /* utilities used by spline drawing routines */
  4104.  
  4105.  
  4106. typedef struct wx_spline_stack_struct {
  4107.     float           x1, y1, x2, y2, x3, y3, x4, y4;
  4108. }
  4109.                 Stack;
  4110.  
  4111. #define         SPLINE_STACK_DEPTH             20
  4112. static Stack    wx_spline_stack[SPLINE_STACK_DEPTH];
  4113. static Stack   *wx_stack_top;
  4114. static int      wx_stack_count;
  4115.  
  4116. void wx_clear_stack(void)
  4117. {
  4118.     wx_stack_top = wx_spline_stack;
  4119.     wx_stack_count = 0;
  4120. }
  4121.  
  4122. void wx_spline_push(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4)
  4123. {
  4124.     wx_stack_top->x1 = x1;
  4125.     wx_stack_top->y1 = y1;
  4126.     wx_stack_top->x2 = x2;
  4127.     wx_stack_top->y2 = y2;
  4128.     wx_stack_top->x3 = x3;
  4129.     wx_stack_top->y3 = y3;
  4130.     wx_stack_top->x4 = x4;
  4131.     wx_stack_top->y4 = y4;
  4132.     wx_stack_top++;
  4133.     wx_stack_count++;
  4134. }
  4135.  
  4136. int wx_spline_pop(float *x1, float *y1, float *x2, float *y2,
  4137.                   float *x3, float *y3, float *x4, float *y4)
  4138. {
  4139.     if (wx_stack_count == 0)
  4140.     return (0);
  4141.     wx_stack_top--;
  4142.     wx_stack_count--;
  4143.     *x1 = wx_stack_top->x1;
  4144.     *y1 = wx_stack_top->y1;
  4145.     *x2 = wx_stack_top->x2;
  4146.     *y2 = wx_stack_top->y2;
  4147.     *x3 = wx_stack_top->x3;
  4148.     *y3 = wx_stack_top->y3;
  4149.     *x4 = wx_stack_top->x4;
  4150.     *y4 = wx_stack_top->y4;
  4151.     return (1);
  4152. }
  4153.  
  4154. static Bool wx_spline_add_point(int x, int y)
  4155. {
  4156.   wxPoint *point = new wxPoint(x, y);
  4157.   wx_spline_point_list.Append(point);
  4158.   return TRUE;
  4159. }
  4160.  
  4161. static void wx_spline_draw_point_array(wxDC *dc)
  4162. {
  4163.   dc->DrawLines(&wx_spline_point_list);
  4164.   wxNode *node = wx_spline_point_list.First();
  4165.   while (node)
  4166.   {
  4167.     wxPoint *point = (wxPoint *)node->Data();
  4168.     delete point;
  4169.     delete node;
  4170.     node = wx_spline_point_list.First();
  4171.   }
  4172. }
  4173.  
  4174. wxSpline::wxSpline(wxList *list)
  4175. {
  4176.   points = list;
  4177. }
  4178.  
  4179. wxSpline::~wxSpline(void)
  4180. {
  4181. }
  4182.  
  4183. void wxSpline::DeletePoints(void)
  4184. {
  4185.   wxNode *node = points->First();
  4186.   while (node)
  4187.   {
  4188.     wxPoint *point = (wxPoint *)node->Data();
  4189.     delete point;
  4190.     delete node;
  4191.     node = points->First();
  4192.   }
  4193.   delete points;
  4194. }
  4195.  
  4196.  
  4197. #ifdef wx_x
  4198. class wxPrinterDialogBox: public wxDialogBox
  4199. {
  4200.  public:
  4201.   wxPrinterDialogBox(wxFrame *frame, char *title, Bool modal = FALSE,
  4202.               int x = -1, int y = -1, int
  4203.               width = -1, int height = -1);
  4204. };
  4205.  
  4206. wxPrinterDialogBox::wxPrinterDialogBox(wxFrame *frame, char *title, Bool modal,
  4207.               int x, int y, int width, int height):
  4208.   wxDialogBox(frame, title, modal, x, y, width, height)
  4209. {
  4210. }
  4211.  
  4212. Bool wxPrinterDialogAnswer = TRUE;
  4213.  
  4214. void wxPrinterDialogOk(wxButton& button, wxEvent& event)
  4215. {
  4216.   wxPrinterDialogAnswer = TRUE;
  4217.   wxPrinterDialogBox *dialog = (wxPrinterDialogBox *)button.GetParent();
  4218.   dialog->Show(FALSE);
  4219. }
  4220.  
  4221. void wxPrinterDialogCancel(wxButton& button, wxEvent& event)
  4222. {
  4223.   wxPrinterDialogAnswer = FALSE;
  4224.   wxPrinterDialogBox *dialog = (wxPrinterDialogBox *)button.GetParent();
  4225.   dialog->Show(FALSE);
  4226. }
  4227.  
  4228. Bool XPrinterDialog(void)
  4229. {
  4230.   char buf[100];
  4231.   wxPrinterDialogBox dialog(NULL, "Printer Settings", TRUE, 150, 150, 400, 400);
  4232.  
  4233.   (void)new wxButton(&dialog, (wxFunction)wxPrinterDialogOk, "Ok");
  4234.   (void)new wxButton(&dialog, (wxFunction)wxPrinterDialogCancel, "Cancel");
  4235.   dialog.NewLine();
  4236.   dialog.NewLine();
  4237.  
  4238.   wxText text_prt(&dialog, (wxFunction)NULL, "Printer Command: ", wx_printer_command, -1, -1, 100, -1);
  4239.   dialog.NewLine();
  4240.  
  4241.   wxText text0(&dialog, (wxFunction)NULL, "Printer Options: ", wx_printer_flags, -1, -1, 200, -1);
  4242.   dialog.NewLine();
  4243.  
  4244.   wxCheckBox checkbox0(&dialog, (wxFunction)NULL, "Portrait");
  4245.   checkbox0.SetValue(wx_portrait);
  4246.  
  4247.   wxCheckBox checkbox1(&dialog, (wxFunction)NULL, "Print to file");
  4248.   checkbox1.SetValue(wx_print_to_file);
  4249.  
  4250.   wxCheckBox checkbox2(&dialog, (wxFunction)NULL, "Preview only");
  4251.   checkbox2.SetValue(wx_preview);
  4252.   dialog.NewLine();
  4253.  
  4254.   sprintf(buf, "%.2f", wx_printer_scale_x);
  4255.   wxText text1(&dialog, (wxFunction)NULL, "X Scaling: ", buf, -1, -1, 100, -1);
  4256.  
  4257.   sprintf(buf, "%.2f", wx_printer_scale_y);
  4258.   wxText text2(&dialog, (wxFunction)NULL, "Y Scaling: ", buf, -1, -1, 100, -1);
  4259.  
  4260.   dialog.NewLine();
  4261.  
  4262.   sprintf(buf, "%.2f", wx_printer_translate_x);
  4263.   wxText text3(&dialog, (wxFunction)NULL, "X Translation: ", buf, -1, -1, 100, -1);
  4264.  
  4265.   sprintf(buf, "%.2f", wx_printer_translate_y);
  4266.   wxText text4(&dialog, (wxFunction)NULL, "Y Translation: ", buf, -1, -1, 100, -1);
  4267.  
  4268.   dialog.NewLine();
  4269.  
  4270.   dialog.Fit();
  4271.  
  4272.   dialog.Show(TRUE);
  4273.  
  4274.   if (wxPrinterDialogAnswer)
  4275.   {
  4276.     StringToFloat(text1.GetValue(), &wx_printer_scale_x);
  4277.     StringToFloat(text2.GetValue(), &wx_printer_scale_y);
  4278.     StringToFloat(text3.GetValue(), &wx_printer_translate_x);
  4279.     StringToFloat(text4.GetValue(), &wx_printer_translate_y);
  4280.  
  4281.     wx_printer_flags = copystring(text0.GetValue());
  4282.     wx_printer_command = copystring(text_prt.GetValue());
  4283.  
  4284.     wx_portrait = checkbox0.GetValue();
  4285.     wx_print_to_file = checkbox1.GetValue();
  4286.     wx_preview = checkbox2.GetValue();
  4287.   }
  4288.  
  4289.   return wxPrinterDialogAnswer;
  4290. }
  4291.  
  4292. #endif
  4293.  
  4294. /*
  4295.  * Metafiles - Windows 3.1 only
  4296.  * Currently, the only purpose for making a metafile is to put
  4297.  * it on the clipboard.
  4298.  */
  4299.  
  4300. wxMetaFile::wxMetaFile(void)
  4301. {
  4302. #ifdef wx_msw
  4303.   metafile = NULL;
  4304. #endif
  4305. }
  4306.  
  4307. wxMetaFile::~wxMetaFile(void)
  4308. {
  4309. #ifdef wx_msw
  4310.   if (metafile)
  4311.     { DeleteMetaFile(metafile); metafile = NULL; }
  4312. #endif
  4313. }
  4314.  
  4315. Bool wxMetaFile::SetClipboard(int width, int height)
  4316. {
  4317. #ifdef wx_msw
  4318.   HANDLE data = GlobalAlloc(GHND, sizeof(METAFILEPICT) + 1);
  4319.   METAFILEPICT *mf = (METAFILEPICT *)GlobalLock(data);
  4320.   mf->mm = MM_ANISOTROPIC;
  4321.   mf->xExt = width;
  4322.   mf->yExt = height;
  4323.   mf->hMF = metafile;
  4324.   GlobalUnlock(data);
  4325.   metafile = NULL;
  4326.  
  4327.   wxFrame *frame = wxTheApp->wx_frame;
  4328.   if (!frame)
  4329.     return FALSE;
  4330.  
  4331.   wxWnd *wnd = (wxWnd *)frame->handle;
  4332.   OpenClipboard(wnd->handle);
  4333.   EmptyClipboard();
  4334.   HANDLE success = SetClipboardData(CF_METAFILEPICT, data);
  4335.   CloseClipboard();
  4336.   return (Bool)success;
  4337. #endif
  4338. #ifdef wx_x
  4339.   return FALSE;
  4340. #endif
  4341. }
  4342.  
  4343. /*
  4344.  * Metafile device context
  4345.  *
  4346.  */
  4347.  
  4348. wxMetaFileDC::wxMetaFileDC(char *file)
  4349. {
  4350. #ifdef wx_x
  4351.   ok = FALSE;
  4352. #endif
  4353. #ifdef wx_msw
  4354.   old_bitmap = NULL;
  4355.   old_pen = NULL;
  4356.   old_brush = NULL;
  4357.   old_font = NULL;
  4358.  
  4359.   metafile = NULL;
  4360.   wx_interactive = FALSE;
  4361.   canvas = NULL;
  4362.   font = NULL;
  4363.  
  4364.   device = wxDEVICE_WINDOWS;
  4365.  
  4366.   cdc = NULL;
  4367.   dont_delete = FALSE;
  4368.   clipping = FALSE;
  4369.  
  4370.   logical_origin_x = 0;
  4371.   logical_origin_y = 0;
  4372.  
  4373.   device_origin_x = 0;
  4374.   device_origin_y = 0;
  4375.  
  4376.   logical_scale_x = 1.0;
  4377.   logical_scale_y = 1.0;
  4378.  
  4379.   user_scale_x = 1.0;
  4380.   user_scale_y = 1.0;
  4381.  
  4382.   mapping_mode = MM_TEXT;
  4383.  
  4384.   min_x = 1000.0;
  4385.   min_y = 1000.0;
  4386.   max_x = -1000.0;
  4387.   max_y = -1000.0;
  4388.   title = NULL;
  4389.  
  4390.   pstream = NULL;
  4391.   filename = NULL;
  4392.  
  4393.   cdc = CreateMetaFile(file);
  4394.   ok = TRUE;
  4395.   SetMapMode(MM_TEXT);
  4396.  
  4397.   current_logical_function = -1;
  4398.   current_pen = wxBLACK_PEN;
  4399.   current_brush = wxBLACK_BRUSH;
  4400.   current_background_brush = wxWHITE_BRUSH;
  4401.   current_text_foreground = wxBLACK;
  4402.   current_text_background = wxWHITE;
  4403.   Colour = wxColourDisplay();
  4404. #endif
  4405. }
  4406.  
  4407. wxMetaFileDC::~wxMetaFileDC(void)
  4408. {
  4409. }
  4410.  
  4411. wxMetaFile *wxMetaFileDC::Close(void)
  4412. {
  4413. #ifdef wx_x
  4414.   return NULL;
  4415. #endif
  4416. #ifdef wx_msw
  4417.   HANDLE mf = CloseMetaFile(cdc);
  4418.   if (mf)
  4419.   {
  4420.     wxMetaFile *wx_mf = new wxMetaFile;
  4421.     wx_mf->metafile = mf;
  4422.     return wx_mf;
  4423.   }
  4424.   return NULL;
  4425. #endif
  4426. }
  4427.  
  4428. void wxMetaFileDC::SetMapMode(int mode)
  4429. {
  4430. #ifdef wx_msw
  4431.   mapping_mode = mode;
  4432.  
  4433.   int pixel_width = 0;
  4434.   int pixel_height = 0;
  4435.   int mm_width = 0;
  4436.   int mm_height = 0;
  4437.  
  4438.   float mm2pixelsX = 10.0;
  4439.   float mm2pixelsY = 10.0;
  4440.  
  4441.   switch (mode)
  4442.   {
  4443.     case MM_TWIPS:
  4444.     {
  4445.       logical_scale_x = (float)(twips2mm * mm2pixelsX);
  4446.       logical_scale_y = (float)(twips2mm * mm2pixelsY);
  4447.       break;
  4448.     }
  4449.     case MM_POINTS:
  4450.     {
  4451.       logical_scale_x = (float)(pt2mm * mm2pixelsX);
  4452.       logical_scale_y = (float)(pt2mm * mm2pixelsY);
  4453.       break;
  4454.     }
  4455.     case MM_METRIC:
  4456.     {
  4457.       logical_scale_x = mm2pixelsX;
  4458.       logical_scale_y = mm2pixelsY;
  4459.       break;
  4460.     }
  4461.     case MM_LOMETRIC:
  4462.     {
  4463.       logical_scale_x = (float)(mm2pixelsX/10.0);
  4464.       logical_scale_y = (float)(mm2pixelsY/10.0);
  4465.       break;
  4466.     }
  4467.     default:
  4468.     case MM_TEXT:
  4469.     {
  4470.       logical_scale_x = 1.0;
  4471.       logical_scale_y = 1.0;
  4472.       break;
  4473.     }
  4474.   }
  4475.   ::SetMapMode(cdc, MM_ANISOTROPIC);
  4476.   SetViewportExtEx(cdc, VIEWPORT_EXTENT, VIEWPORT_EXTENT, NULL);
  4477.   window_ext_x = MS_XDEV2LOG(VIEWPORT_EXTENT);
  4478.   window_ext_y = MS_YDEV2LOG(VIEWPORT_EXTENT);
  4479.   SetWindowExtEx(cdc, window_ext_x, window_ext_y, NULL);
  4480. #endif
  4481. }
  4482.