source: git/src/printwin.c @ 65ad692

RELEASE/1.0RELEASE/1.1RELEASE/1.2debug-cidebug-ci-sanitisersfaster-cavernloglog-selectstereowalls-datawalls-data-hanging-as-warningwarn-only-for-hanging-survey
Last change on this file since 65ad692 was ca4058d, checked in by Olly Betts <olly@…>, 22 years ago

Added colour printing to printps, printwin, and printxbm.

git-svn-id: file:///home/survex-svn/survex/trunk@1981 4b37db11-9a0c-4f06-9ece-9ab7cdaee568

  • Property mode set to 100644
File size: 10.7 KB
Line 
1/* printwin.c */
2/* Device dependent part of Survex Win32 driver */
3/* Copyright (C) 1993-2002 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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 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
49static char *fontname, *fontname_labels;
50
51static const char *win_Name(void);
52static int win_Pre(int pagesToPrint, const char *title);
53static void win_NewPage(int pg, int pass, int pagesX, int pagesY);
54static char *win_Init(FILE **fh_list, const char *pth, const char *outfnm,
55                      double *pscX, double *pscY, bool fCalibrate);
56static int  win_Charset(void);
57static void win_MoveTo(long x, long y);
58static void win_DrawTo(long x, long y);
59static void win_DrawCross(long x, long y);
60static void win_SetFont(int fontcode);
61static void win_WriteString(const char *s);
62static void win_DrawCircle(long x, long y, long r);
63static void win_ShowPage(const char *szPageDetails);
64static void win_Quit(void);
65
66device printer = {
67   PR_FLAG_NOFILEOUTPUT, /* |PR_FLAG_NOINI - now read fontsize from ini file */
68   win_Name,
69   win_Init,
70   win_Charset,
71   win_Pre,
72   win_NewPage,
73   win_MoveTo,
74   win_DrawTo,
75   win_DrawCross,
76   win_SetFont,
77   win_SetColour,
78   win_WriteString,
79   win_DrawCircle,
80   win_ShowPage,
81   NULL, /* win_Post */
82   win_Quit
83};
84
85static HDC pd; /* printer context */
86
87static TEXTMETRIC *tm, tm_labels, tm_default; /* font info */
88
89static COLORREF colour_leg, colour_surface_leg, colour_cross, colour_frame;
90static COLORREF colour_text, colour_labels;
91static HPEN pen_leg, pen_surface_leg, pen_crosses, pen_frame;
92
93static double scX, scY;
94
95static int cur_pass;
96
97static border clip;
98
99static long xpPageWidth, ypPageDepth;
100
101static long x_t, y_t;
102
103static int
104check_intersection(long x_p, long y_p)
105{
106#define U 1
107#define D 2
108#define L 4
109#define R 8
110   int mask_p = 0, mask_t = 0;
111   if (x_p < 0)
112      mask_p = L;
113   else if (x_p > xpPageWidth)
114      mask_p = R;
115
116   if (y_p < 0)
117      mask_p |= D;
118   else if (y_p > ypPageDepth)
119      mask_p |= U;
120
121   if (x_t < 0)
122      mask_t = L;
123   else if (x_t > xpPageWidth)
124      mask_t = R;
125
126   if (y_t < 0)
127      mask_t |= D;
128   else if (y_t > ypPageDepth)
129      mask_t |= U;
130
131#if 0
132   /* approximation to correct answer */
133   return !(mask_t & mask_p);
134#else
135   /* One end of the line is on the page */
136   if (!mask_t || !mask_p) return 1;
137
138   /* whole line is above, left, right, or below page */
139   if (mask_t & mask_p) return 0;
140
141   if (mask_t == 0) mask_t = mask_p;
142   if (mask_t & U) {
143      double v = (double)(y_p - ypPageDepth) / (y_p - y_t);
144      return v >= 0 && v <= 1;
145   }
146   if (mask_t & D) {
147      double v = (double)y_p / (y_p - y_t);
148      return v >= 0 && v <= 1;
149   }
150   if (mask_t & R) {
151      double v = (double)(x_p - xpPageWidth) / (x_p - x_t);
152      return v >= 0 && v <= 1;
153   }
154   ASSERT(mask_t & L);
155   {
156      double v = (double)x_p / (x_p - x_t);
157      return v >= 0 && v <= 1;
158   }
159#endif
160#undef U
161#undef D
162#undef L
163#undef R
164}
165
166static const char *
167win_Name(void)
168{
169   return "Win32 Printer";
170}
171
172static void
173win_MoveTo(long x, long y)
174{
175   x_t = x - clip.x_min;
176   y_t = clip.y_max - y;
177   if (cur_pass != -1) MoveToEx(pd, x_t, y_t, NULL);
178}
179
180static void
181win_DrawTo(long x, long y)
182{
183   long x_p = x_t, y_p = y_t;
184   x_t = x - clip.x_min;
185   y_t = clip.y_max - y;
186   if (cur_pass != -1) {
187      LineTo(pd, x_t, y_t);
188   } else {
189      if (check_intersection(x_p, y_p)) fBlankPage = fFalse;
190   }
191}
192
193#define POINTS_PER_INCH 72.0
194#define POINTS_PER_MM (POINTS_PER_INCH / MM_PER_INCH)
195#define WIN_CROSS_SIZE (2 * scX / POINTS_PER_MM)
196
197static void
198win_DrawCross(long x, long y)
199{
200   if (cur_pass != -1) {
201      win_MoveTo(x - WIN_CROSS_SIZE, y - WIN_CROSS_SIZE);
202      win_DrawTo(x + WIN_CROSS_SIZE, y + WIN_CROSS_SIZE);
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, y);
206   } else {
207      if ((x + WIN_CROSS_SIZE > clip.x_min &&
208           x - WIN_CROSS_SIZE < clip.x_max) ||
209          (y + WIN_CROSS_SIZE > clip.y_min &&
210           y - WIN_CROSS_SIZE < clip.y_max)) {
211         fBlankPage = fFalse;
212      }
213   }
214}
215
216static HFONT font_labels, font_default, font_old;
217
218static void
219win_SetFont(int fontcode)
220{
221   switch (fontcode) {
222      case PR_FONT_DEFAULT:
223         SelectObject(pd, font_default);
224         tm = &tm_default;
225         break;
226      case PR_FONT_LABELS:
227         SelectObject(pd, font_labels);
228         tm = &tm_labels;
229         break;
230      default:
231         BUG("unknown font code");
232   }
233}
234
235static void
236win_SetColour(int colourcode)
237{
238   switch (colourcode) {
239      case PR_COLOUR_TEXT:
240         SetTextColour(colour_text);
241         break;
242      case PR_COLOUR_LABELS:
243         SetTextColour(colour_labels);
244         break;
245      case PR_COLOUR_FRAME:
246         SelectObject(pd, pen_frame);
247         break;
248      case PR_COLOUR_LEG:
249         SelectObject(pd, pen_leg);
250         break;
251      case PR_COLOUR_CROSS:
252         SelectObject(pd, pen_cross);
253         break;
254      case PR_COLOUR_SURFACE_LEG:
255         SelectObject(pd, pen_surface_leg);
256         break;
257      default:
258         BUG("unknown colour code");
259   }
260}
261
262static void
263win_WriteString(const char *s)
264{
265   if (cur_pass != -1) {
266      TextOut(pd, x_t, y_t - tm->tmAscent, s, strlen(s));
267   } else {
268      if ((y_t + tm->tmDescent > 0 &&
269           y_t - tm->tmAscent < clip.y_max - clip.y_min) ||
270          (x_t < clip.x_max - clip.x_min &&
271           x_t + strlen(s) * tm->tmAveCharWidth > 0)) {
272         fBlankPage = fFalse;
273      }
274   }
275}
276
277static void
278win_DrawCircle(long x, long y, long r)
279{
280   /* Don't need to check in first-pass - circle is only used in title box */
281   if (cur_pass != -1) {
282      x_t = x - clip.x_min;
283      y_t = clip.y_max - y;
284      Ellipse(pd, x_t - r, y_t - r, x_t + r, y_t + r);
285   }
286}
287
288static int
289win_Charset(void)
290{
291   return CHARSET_ISO_8859_1;
292}
293
294static int
295win_Pre(int pagesToPrint, const char *title)
296{
297   PRINTDLGA psd;
298   DOCINFO info;
299   int logpixelsy;
300
301   pagesToPrint = pagesToPrint; /* suppress compiler warning */
302
303   memset(&psd, 0, sizeof(PRINTDLGA));
304   psd.lStructSize = 66;
305   psd.Flags = PD_RETURNDC | PD_RETURNDEFAULT;
306
307   if (!PrintDlgA(&psd)) exit(1);
308   pd = psd.hDC;
309
310   logpixelsy = GetDeviceCaps(pd, LOGPIXELSY);
311   font_labels = CreateFont(-MulDiv(fontsize_labels, logpixelsy, 72),
312                            0, 0, 0, FW_NORMAL, 0, 0, 0,
313                            ANSI_CHARSET, OUT_DEFAULT_PRECIS,
314                            CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
315                            FF_DONTCARE | DEFAULT_PITCH, "Arial");
316   font_default = CreateFont(-MulDiv(fontsize, logpixelsy, 72),
317                             0, 0, 0, FW_NORMAL, 0, 0, 0,
318                             ANSI_CHARSET, OUT_DEFAULT_PRECIS,
319                             CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
320                             FF_DONTCARE | DEFAULT_PITCH, "Arial");
321   pen_leg = CreatePen(PS_SOLID, 0, colour_leg);
322   pen_surface_leg = CreatePen(PS_SOLID, 0, colour_surface_leg);
323   pen_cross = CreatePen(PS_SOLID, 0, colour_cross);
324   pen_frame = CreatePen(PS_SOLID, 0, colour_frame);
325   font_old = SelectObject(pd, font_labels);
326   GetTextMetrics(pd, &tm_labels);
327   SelectObject(pd, font_default);
328   GetTextMetrics(pd, &tm_default);
329
330   memset(&info, 0, sizeof(DOCINFO));
331   info.cbSize = sizeof(DOCINFO);
332   info.lpszDocName = title;
333
334   StartDoc(pd, &info);
335   return 1; /* only need 1 pass */
336}
337
338static void
339win_NewPage(int pg, int pass, int pagesX, int pagesY)
340{
341   int x, y;
342
343   x = (pg - 1) % pagesX;
344   y = pagesY - 1 - ((pg - 1) / pagesX);
345
346   clip.x_min = (long)x * xpPageWidth;
347   clip.y_min = (long)y * ypPageDepth;
348   clip.x_max = clip.x_min + xpPageWidth; /* dm/pcl/ps had -1; */
349   clip.y_max = clip.y_min + ypPageDepth; /* dm/pcl/ps had -1; */
350
351   cur_pass = pass;
352   if (pass == -1) return;
353
354   StartPage(pd);
355   drawticks(clip, 9 * scX / POINTS_PER_MM, x, y);
356}
357
358static void
359win_ShowPage(const char *szPageDetails)
360{
361   win_MoveTo((long)(6 * scX) + clip.x_min, clip.y_min - (long)(7 * scY));
362   win_WriteString(szPageDetails);
363   EndPage(pd);
364}
365
366static COLORREF
367to_rgb(const char *var, char *val)
368{
369   unsigned long rgb = as_colour(var, val);
370   return RGB((rgb & 0xff0000) >> 16, (rgb & 0xff00) >> 8, rgb & 0xff);
371}
372
373/* Initialise printer routines */
374static char *
375win_Init(FILE **fh_list, const char *pth, const char *out_fnm,
376         double *pscX, double *pscY, bool fCalibrate)
377{
378   PRINTDLGA psd;
379   LPDEVNAMES dn;
380   static const char *vars[] = {
381      "like",
382      "font_size_labels",
383      "colour_text",
384      "colour_labels",
385      "colour_frame",
386      "colour_legs",
387      "colour_crosses",
388      "colour_surface_legs",
389      NULL
390   };
391   char **vals;
392
393   fCalibrate = fCalibrate; /* suppress unused argument warning */
394   out_fnm = out_fnm;
395   pth = pth;
396
397   vals = ini_read_hier(fh_list, "win", vars);
398
399   fontsize_labels = as_int(vars[1], vals[1], 1, INT_MAX);
400   fontsize = 10;
401
402   colour_text = to_rgb(vars[2], vals[2]);
403   colour_labels = to_rgb(vars[3], vals[3]);
404   colour_frame = to_rgb(vars[4], vals[4]);
405   colour_leg = to_rgb(vars[5], vals[5]);
406   colour_cross = to_rgb(vars[6], vals[6]);
407
408   memset(&psd, 0, sizeof(PRINTDLGA));
409   psd.lStructSize = 66;
410   psd.Flags = PD_RETURNDC | PD_RETURNDEFAULT;
411
412   if (!PrintDlgA(&psd)) exit(1);
413
414   PaperWidth = GetDeviceCaps(psd.hDC, HORZSIZE);
415   PaperDepth = GetDeviceCaps(psd.hDC, VERTSIZE);
416   xpPageWidth = GetDeviceCaps(psd.hDC, HORZRES);
417   ypPageDepth = GetDeviceCaps(psd.hDC, VERTRES);
418   MarginLeft = MarginBottom = 0;
419   MarginRight = PaperWidth;
420   MarginTop = PaperDepth;
421   LineWidth = 0;
422   scX = *pscX = xpPageWidth / PaperWidth;
423   scY = *pscY = ypPageDepth / PaperDepth;
424   xpPageWidth--;
425   ypPageDepth = ypPageDepth - (int)(10 * *pscY);
426   DeleteDC(psd.hDC);
427
428   dn = GlobalLock(psd.hDevNames);
429   if (dn) {
430      char *p = osstrdup((char *)dn + dn->wDeviceOffset);
431      GlobalUnlock(psd.hDevNames);
432      return p;
433   }
434   return NULL;
435}
436
437static void
438win_Quit(void)
439{
440   SelectObject(pd, font_old);
441   DeleteObject(font_labels);
442   DeleteObject(font_default);
443   EndDoc(pd);
444   DeleteDC(pd);
445}
Note: See TracBrowser for help on using the repository browser.