source: git/src/printwin.c @ bbeacdb

RELEASE/1.0
Last change on this file since bbeacdb was bbeacdb, checked in by Olly Betts <olly@…>, 13 years ago

src/printwin.c: Fix C++ comment.

git-svn-id: file:///home/survex-svn/survex/branches/1.0@3684 4b37db11-9a0c-4f06-9ece-9ab7cdaee568

  • Property mode set to 100644
File size: 11.1 KB
Line 
1/* printwin.c */
2/* Device dependent part of Survex Win32 driver */
3/* Copyright (C) 1993-2003,2005 Olly Betts
4 * Copyright (C) 2001 Philip Underwood
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19 */
20
21#ifdef HAVE_CONFIG_H
22# include <config.h>
23#endif
24
25#include <stdio.h>
26#include <stdlib.h>
27#include <math.h>
28#include <string.h>
29#include <time.h>
30#include <ctype.h>
31#include <float.h>
32#include <limits.h>
33
34#include "debug.h" /* for BUG and SVX_ASSERT */
35#include "filelist.h"
36#include "filename.h"
37#include "ini.h"
38#include "message.h"
39#include "prcore.h"
40#include "prio.h"
41#include "useful.h"
42
43#include <windows.h>
44
45static double MarginLeft, MarginRight, MarginTop, MarginBottom;
46static int fontsize, fontsize_labels;
47static double LineWidth;
48
49/* FIXME: allow the font to be set */
50static const char *fontname = "Arial", *fontname_labels = "Arial";
51
52static const char *win_Name(void);
53static int win_Pre(int pagesToPrint, const char *title);
54static void win_NewPage(int pg, int pass, int pagesX, int pagesY);
55static char *win_Init(FILE **fh_list, const char *pth, const char *outfnm,
56                      double *pscX, double *pscY, bool fCalibrate);
57static int  win_Charset(void);
58static void win_MoveTo(long x, long y);
59static void win_DrawTo(long x, long y);
60static void win_DrawCross(long x, long y);
61static void win_SetFont(int fontcode);
62static void win_SetColour(int colourcode);
63static void win_WriteString(const char *s);
64static void win_DrawCircle(long x, long y, long r);
65static void win_ShowPage(const char *szPageDetails);
66static void win_Quit(void);
67
68device printer = {
69   PR_FLAG_NOFILEOUTPUT, /* |PR_FLAG_NOINI - now read fontsize from ini file */
70   win_Name,
71   win_Init,
72   win_Charset,
73   win_Pre,
74   win_NewPage,
75   win_MoveTo,
76   win_DrawTo,
77   win_DrawCross,
78   win_SetFont,
79   win_SetColour,
80   win_WriteString,
81   win_DrawCircle,
82   win_ShowPage,
83   NULL, /* win_Post */
84   win_Quit
85};
86
87static HDC pd; /* printer context */
88
89static TEXTMETRIC *tm, tm_labels, tm_default; /* font info */
90
91static COLORREF colour_leg, colour_surface_leg, colour_cross, colour_frame;
92static COLORREF colour_text, colour_labels;
93static HPEN pen_leg, pen_surface_leg, pen_cross, pen_frame;
94
95static double scX, scY;
96
97static int cur_pass;
98
99static border clip;
100
101static long xpPageWidth, ypPageDepth;
102
103static long x_t, y_t;
104
105static int
106check_intersection(long x_p, long y_p)
107{
108#define U 1
109#define D 2
110#define L 4
111#define R 8
112   int mask_p = 0, mask_t = 0;
113   if (x_p < 0)
114      mask_p = L;
115   else if (x_p > xpPageWidth)
116      mask_p = R;
117
118   if (y_p < 0)
119      mask_p |= D;
120   else if (y_p > ypPageDepth)
121      mask_p |= U;
122
123   if (x_t < 0)
124      mask_t = L;
125   else if (x_t > xpPageWidth)
126      mask_t = R;
127
128   if (y_t < 0)
129      mask_t |= D;
130   else if (y_t > ypPageDepth)
131      mask_t |= U;
132
133#if 0
134   /* approximation to correct answer */
135   return !(mask_t & mask_p);
136#else
137   /* One end of the line is on the page */
138   if (!mask_t || !mask_p) return 1;
139
140   /* whole line is above, left, right, or below page */
141   if (mask_t & mask_p) return 0;
142
143   if (mask_t == 0) mask_t = mask_p;
144   if (mask_t & U) {
145      double v = (double)(y_p - ypPageDepth) / (y_p - y_t);
146      return v >= 0 && v <= 1;
147   }
148   if (mask_t & D) {
149      double v = (double)y_p / (y_p - y_t);
150      return v >= 0 && v <= 1;
151   }
152   if (mask_t & R) {
153      double v = (double)(x_p - xpPageWidth) / (x_p - x_t);
154      return v >= 0 && v <= 1;
155   }
156   SVX_ASSERT(mask_t & L);
157   {
158      double v = (double)x_p / (x_p - x_t);
159      return v >= 0 && v <= 1;
160   }
161#endif
162#undef U
163#undef D
164#undef L
165#undef R
166}
167
168static const char *
169win_Name(void)
170{
171   return "Win32 Printer";
172}
173
174static void
175win_MoveTo(long x, long y)
176{
177   x_t = x - clip.x_min;
178   y_t = clip.y_max - y;
179   if (cur_pass != -1) MoveToEx(pd, x_t, y_t, NULL);
180}
181
182static void
183win_DrawTo(long x, long y)
184{
185   long x_p = x_t, y_p = y_t;
186   x_t = x - clip.x_min;
187   y_t = clip.y_max - y;
188   if (cur_pass != -1) {
189      LineTo(pd, x_t, y_t);
190   } else {
191      if (check_intersection(x_p, y_p)) fBlankPage = fFalse;
192   }
193}
194
195#define POINTS_PER_INCH 72.0
196#define POINTS_PER_MM (POINTS_PER_INCH / MM_PER_INCH)
197#define WIN_CROSS_SIZE (int)(2 * scX / POINTS_PER_MM)
198
199static void
200win_DrawCross(long x, long y)
201{
202   if (cur_pass != -1) {
203      win_MoveTo(x - WIN_CROSS_SIZE, y - WIN_CROSS_SIZE);
204      win_DrawTo(x + WIN_CROSS_SIZE, y + WIN_CROSS_SIZE);
205      win_MoveTo(x + WIN_CROSS_SIZE, y - WIN_CROSS_SIZE);
206      win_DrawTo(x - WIN_CROSS_SIZE, y + WIN_CROSS_SIZE);
207      win_MoveTo(x, y);
208   } else {
209      if ((x + WIN_CROSS_SIZE > clip.x_min &&
210           x - WIN_CROSS_SIZE < clip.x_max) ||
211          (y + WIN_CROSS_SIZE > clip.y_min &&
212           y - WIN_CROSS_SIZE < clip.y_max)) {
213         fBlankPage = fFalse;
214      }
215   }
216}
217
218static HFONT font_labels, font_default, font_old;
219
220static void
221win_SetFont(int fontcode)
222{
223   switch (fontcode) {
224      case PR_FONT_DEFAULT:
225         SelectObject(pd, font_default);
226         tm = &tm_default;
227         break;
228      case PR_FONT_LABELS:
229         SelectObject(pd, font_labels);
230         tm = &tm_labels;
231         break;
232      default:
233         BUG("unknown font code");
234   }
235}
236
237static void
238win_SetColour(int colourcode)
239{
240   switch (colourcode) {
241      case PR_COLOUR_TEXT:
242         SetTextColor(pd, colour_text);
243         break;
244      case PR_COLOUR_LABELS:
245         SetTextColor(pd, colour_labels);
246         SetBkMode(pd, TRANSPARENT);
247         break;
248      case PR_COLOUR_FRAME:
249         SelectObject(pd, pen_frame);
250         break;
251      case PR_COLOUR_LEG:
252         SelectObject(pd, pen_leg);
253         break;
254      case PR_COLOUR_CROSS:
255         SelectObject(pd, pen_cross);
256         break;
257      case PR_COLOUR_SURFACE_LEG:
258         SelectObject(pd, pen_surface_leg);
259         break;
260      default:
261         BUG("unknown colour code");
262   }
263}
264
265static void
266win_WriteString(const char *s)
267{
268   if (cur_pass != -1) {
269      TextOut(pd, x_t, y_t - tm->tmAscent, s, strlen(s));
270   } else {
271      if ((y_t + tm->tmDescent > 0 &&
272           y_t - tm->tmAscent < clip.y_max - clip.y_min) ||
273          (x_t < clip.x_max - clip.x_min &&
274           x_t + strlen(s) * tm->tmAveCharWidth > 0)) {
275         fBlankPage = fFalse;
276      }
277   }
278}
279
280static void
281win_DrawCircle(long x, long y, long r)
282{
283   /* Don't need to check in first-pass - circle is only used in title box */
284   if (cur_pass != -1) {
285      x_t = x - clip.x_min;
286      y_t = clip.y_max - y;
287      Ellipse(pd, x_t - r, y_t - r, x_t + r, y_t + r);
288   }
289}
290
291static int
292win_Charset(void)
293{
294   return CHARSET_ISO_8859_1;
295}
296
297static int
298win_Pre(int pagesToPrint, const char *title)
299{
300   PRINTDLGA psd;
301   DOCINFO info;
302   int logpixelsy;
303
304   pagesToPrint = pagesToPrint; /* suppress compiler warning */
305
306   memset(&psd, 0, sizeof(PRINTDLGA));
307   psd.lStructSize = 66;
308   psd.Flags = PD_RETURNDC | PD_RETURNDEFAULT;
309
310   if (!PrintDlgA(&psd)) exit(1);
311   pd = psd.hDC;
312
313   logpixelsy = GetDeviceCaps(pd, LOGPIXELSY);
314   font_labels = CreateFont(-MulDiv(fontsize_labels, logpixelsy, 72),
315                            0, 0, 0, FW_NORMAL, 0, 0, 0,
316                            ANSI_CHARSET, OUT_DEFAULT_PRECIS,
317                            CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
318                            FF_DONTCARE | DEFAULT_PITCH, fontname_labels);
319   font_default = CreateFont(-MulDiv(fontsize, logpixelsy, 72),
320                             0, 0, 0, FW_NORMAL, 0, 0, 0,
321                             ANSI_CHARSET, OUT_DEFAULT_PRECIS,
322                             CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
323                             FF_DONTCARE | DEFAULT_PITCH, fontname);
324   /* Pen width of 0 should work, but seemed to give problems, so we'll
325    * try 1 instead... */
326   pen_leg = CreatePen(PS_SOLID, 1, colour_leg);
327   pen_surface_leg = CreatePen(PS_SOLID, 1, colour_surface_leg);
328   pen_cross = CreatePen(PS_SOLID, 1, colour_cross);
329   pen_frame = CreatePen(PS_SOLID, 1, colour_frame);
330   font_old = SelectObject(pd, font_labels);
331   GetTextMetrics(pd, &tm_labels);
332   SelectObject(pd, font_default);
333   GetTextMetrics(pd, &tm_default);
334
335   memset(&info, 0, sizeof(DOCINFO));
336   info.cbSize = sizeof(DOCINFO);
337   info.lpszDocName = title;
338
339   StartDoc(pd, &info);
340   return 1; /* only need 1 pass */
341}
342
343static void
344win_NewPage(int pg, int pass, int pagesX, int pagesY)
345{
346   int x, y;
347
348   x = (pg - 1) % pagesX;
349   y = pagesY - 1 - ((pg - 1) / pagesX);
350
351   clip.x_min = (long)x * xpPageWidth;
352   clip.y_min = (long)y * ypPageDepth;
353   clip.x_max = clip.x_min + xpPageWidth; /* dm/pcl/ps had -1; */
354   clip.y_max = clip.y_min + ypPageDepth; /* dm/pcl/ps had -1; */
355
356   cur_pass = pass;
357   if (pass == -1) return;
358
359   StartPage(pd);
360   drawticks(clip, (int)(9 * scX / POINTS_PER_MM), x, y);
361}
362
363static void
364win_ShowPage(const char *szPageDetails)
365{
366   win_MoveTo((long)(6 * scX) + clip.x_min, clip.y_min - (long)(7 * scY));
367   win_WriteString(szPageDetails);
368   EndPage(pd);
369}
370
371static COLORREF
372to_rgb(const char *var, char *val)
373{
374   unsigned long rgb;
375   if (!val) return RGB(0, 0, 0);
376   rgb = as_colour(var, val);
377   return RGB((rgb & 0xff0000) >> 16, (rgb & 0xff00) >> 8, rgb & 0xff);
378}
379
380/* Initialise printer routines */
381static char *
382win_Init(FILE **fh_list, const char *pth, const char *out_fnm,
383         double *pscX, double *pscY, bool fCalibrate)
384{
385   PRINTDLGA psd;
386   LPDEVNAMES dn;
387   static const char *vars[] = {
388      "like",
389      "font_size_labels",
390      "colour_text",
391      "colour_labels",
392      "colour_frame",
393      "colour_legs",
394      "colour_crosses",
395      "colour_surface_legs",
396      NULL
397   };
398   char **vals;
399
400   fCalibrate = fCalibrate; /* suppress unused argument warning */
401   out_fnm = out_fnm;
402   pth = pth;
403
404   vals = ini_read_hier(fh_list, "win", vars);
405
406   fontsize_labels = as_int(vars[1], vals[1], 1, INT_MAX);
407   fontsize = 10;
408
409   colour_text = to_rgb(vars[2], vals[2]);
410   colour_labels = to_rgb(vars[3], vals[3]);
411   colour_frame = to_rgb(vars[4], vals[4]);
412   colour_leg = to_rgb(vars[5], vals[5]);
413   colour_cross = to_rgb(vars[6], vals[6]);
414   colour_surface_leg = to_rgb(vars[7], vals[7]);
415
416   memset(&psd, 0, sizeof(PRINTDLGA));
417   psd.lStructSize = 66;
418   psd.Flags = PD_RETURNDC | PD_RETURNDEFAULT;
419
420   if (!PrintDlgA(&psd)) exit(1);
421
422   PaperWidth = GetDeviceCaps(psd.hDC, HORZSIZE);
423   PaperDepth = GetDeviceCaps(psd.hDC, VERTSIZE);
424   xpPageWidth = GetDeviceCaps(psd.hDC, HORZRES);
425   ypPageDepth = GetDeviceCaps(psd.hDC, VERTRES);
426   MarginLeft = MarginBottom = 0;
427   MarginRight = PaperWidth;
428   MarginTop = PaperDepth;
429   LineWidth = 0;
430   scX = *pscX = xpPageWidth / PaperWidth;
431   scY = *pscY = ypPageDepth / PaperDepth;
432   xpPageWidth--;
433   /* Allow for the page footer. */
434   ypPageDepth -= (int)(10 * *pscY);
435   PaperDepth -= 10.0;
436   DeleteDC(psd.hDC);
437
438   dn = GlobalLock(psd.hDevNames);
439   if (dn) {
440      char *p = osstrdup((char *)dn + dn->wDeviceOffset);
441      GlobalUnlock(psd.hDevNames);
442      return p;
443   }
444   return NULL;
445}
446
447static void
448win_Quit(void)
449{
450   SelectObject(pd, font_old);
451   DeleteObject(font_labels);
452   DeleteObject(font_default);
453   EndDoc(pd);
454   DeleteDC(pd);
455}
Note: See TracBrowser for help on using the repository browser.