source: git/src/printwin.c@ a1b8692

RELEASE/1.0 RELEASE/1.1 RELEASE/1.2 debug-ci debug-ci-sanitisers faster-cavernlog log-select main stereo stereo-2025 walls-data walls-data-hanging-as-warning warn-only-for-hanging-survey
Last change on this file since a1b8692 was ca4058d, checked in by Olly Betts <olly@…>, 24 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
RevLine 
[396b9dd]1/* printwin.c */
[55b7334]2/* Device dependent part of Survex Win32 driver */
[b7b666d]3/* Copyright (C) 1993-2002 Olly Betts
[4888f06]4 * Copyright (C) 2001 Philip Underwood
[55b7334]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
[c34796a]34#include "debug.h" /* for BUG and ASSERT */
35#include "filelist.h"
[55b7334]36#include "filename.h"
[c34796a]37#include "ini.h"
[55b7334]38#include "message.h"
39#include "prcore.h"
[c34796a]40#include "prio.h"
41#include "useful.h"
42
[55b7334]43#include <windows.h>
44
[6974a34]45static double MarginLeft, MarginRight, MarginTop, MarginBottom;
[55b7334]46static int fontsize, fontsize_labels;
[6974a34]47static double LineWidth;
[55b7334]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);
[3857e321]54static char *win_Init(FILE **fh_list, const char *pth, const char *outfnm,
55 double *pscX, double *pscY, bool fCalibrate);
[08e95aa]56static int win_Charset(void);
[55b7334]57static void win_MoveTo(long x, long y);
58static void win_DrawTo(long x, long y);
59static void win_DrawCross(long x, long y);
[abb82a4]60static void win_SetFont(int fontcode);
[55b7334]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 = {
[a7f068f]67 PR_FLAG_NOFILEOUTPUT, /* |PR_FLAG_NOINI - now read fontsize from ini file */
[55b7334]68 win_Name,
69 win_Init,
[08e95aa]70 win_Charset,
[55b7334]71 win_Pre,
72 win_NewPage,
73 win_MoveTo,
74 win_DrawTo,
75 win_DrawCross,
[abb82a4]76 win_SetFont,
[ca4058d]77 win_SetColour,
[55b7334]78 win_WriteString,
79 win_DrawCircle,
80 win_ShowPage,
[9d46af2]81 NULL, /* win_Post */
[55b7334]82 win_Quit
83};
84
[d0ffc05]85static HDC pd; /* printer context */
[55b7334]86
[9e58834]87static TEXTMETRIC *tm, tm_labels, tm_default; /* font info */
[55b7334]88
[ca4058d]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
[6974a34]93static double scX, scY;
[55b7334]94
[396b9dd]95static int cur_pass;
96
[55b7334]97static border clip;
98
99static long xpPageWidth, ypPageDepth;
100
[0658e7b]101static long x_t, y_t;
102
[396b9dd]103static int
104check_intersection(long x_p, long y_p)
105{
106#define U 1
107#define D 2
108#define L 4
[421b7d2]109#define R 8
[f7cdeb2]110 int mask_p = 0, mask_t = 0;
[f17dbe2]111 if (x_p < 0)
[396b9dd]112 mask_p = L;
[f17dbe2]113 else if (x_p > xpPageWidth)
[396b9dd]114 mask_p = R;
115
[f17dbe2]116 if (y_p < 0)
[396b9dd]117 mask_p |= D;
[f17dbe2]118 else if (y_p > ypPageDepth)
[396b9dd]119 mask_p |= U;
120
[f17dbe2]121 if (x_t < 0)
[396b9dd]122 mask_t = L;
[f17dbe2]123 else if (x_t > xpPageWidth)
[396b9dd]124 mask_t = R;
125
[f17dbe2]126 if (y_t < 0)
[396b9dd]127 mask_t |= D;
[f17dbe2]128 else if (y_t > ypPageDepth)
[396b9dd]129 mask_t |= U;
130
131#if 0
132 /* approximation to correct answer */
133 return !(mask_t & mask_p);
[69fde77]134#else
[396b9dd]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) {
[f17dbe2]143 double v = (double)(y_p - ypPageDepth) / (y_p - y_t);
[396b9dd]144 return v >= 0 && v <= 1;
145 }
146 if (mask_t & D) {
[f17dbe2]147 double v = (double)y_p / (y_p - y_t);
[396b9dd]148 return v >= 0 && v <= 1;
149 }
150 if (mask_t & R) {
[f17dbe2]151 double v = (double)(x_p - xpPageWidth) / (x_p - x_t);
[396b9dd]152 return v >= 0 && v <= 1;
153 }
154 ASSERT(mask_t & L);
155 {
[f17dbe2]156 double v = (double)x_p / (x_p - x_t);
[396b9dd]157 return v >= 0 && v <= 1;
158 }
159#endif
160#undef U
161#undef D
162#undef L
163#undef R
164}
165
[55b7334]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;
[396b9dd]177 if (cur_pass != -1) MoveToEx(pd, x_t, y_t, NULL);
[55b7334]178}
179
180static void
181win_DrawTo(long x, long y)
182{
[396b9dd]183 long x_p = x_t, y_p = y_t;
[55b7334]184 x_t = x - clip.x_min;
185 y_t = clip.y_max - y;
[396b9dd]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 }
[55b7334]191}
192
[7be0ba8]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
[55b7334]197static void
198win_DrawCross(long x, long y)
199{
[396b9dd]200 if (cur_pass != -1) {
[d3d9230]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);
[396b9dd]205 win_MoveTo(x, y);
206 } else {
[39e4399a]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)) {
[396b9dd]211 fBlankPage = fFalse;
212 }
213 }
[55b7334]214}
215
[b7b666d]216static HFONT font_labels, font_default, font_old;
217
[abb82a4]218static void
219win_SetFont(int fontcode)
220{
221 switch (fontcode) {
222 case PR_FONT_DEFAULT:
[b7b666d]223 SelectObject(pd, font_default);
[9e58834]224 tm = &tm_default;
[abb82a4]225 break;
226 case PR_FONT_LABELS:
[b7b666d]227 SelectObject(pd, font_labels);
[9e58834]228 tm = &tm_labels;
[abb82a4]229 break;
230 default:
231 BUG("unknown font code");
232 }
233}
234
[ca4058d]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
[55b7334]262static void
263win_WriteString(const char *s)
264{
[396b9dd]265 if (cur_pass != -1) {
[9e58834]266 TextOut(pd, x_t, y_t - tm->tmAscent, s, strlen(s));
[396b9dd]267 } else {
[9e58834]268 if ((y_t + tm->tmDescent > 0 &&
269 y_t - tm->tmAscent < clip.y_max - clip.y_min) ||
[396b9dd]270 (x_t < clip.x_max - clip.x_min &&
[9e58834]271 x_t + strlen(s) * tm->tmAveCharWidth > 0)) {
[396b9dd]272 fBlankPage = fFalse;
273 }
274 }
[55b7334]275}
276
277static void
278win_DrawCircle(long x, long y, long r)
279{
[396b9dd]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 }
[55b7334]286}
287
[08e95aa]288static int
289win_Charset(void)
290{
291 return CHARSET_ISO_8859_1;
292}
293
[55b7334]294static int
295win_Pre(int pagesToPrint, const char *title)
296{
[5824d76]297 PRINTDLGA psd;
298 DOCINFO info;
[6b1901c]299 int logpixelsy;
[5824d76]300
301 pagesToPrint = pagesToPrint; /* suppress compiler warning */
[9d46af2]302
[5824d76]303 memset(&psd, 0, sizeof(PRINTDLGA));
[d0ffc05]304 psd.lStructSize = 66;
[5824d76]305 psd.Flags = PD_RETURNDC | PD_RETURNDEFAULT;
[8bc2567]306
[5824d76]307 if (!PrintDlgA(&psd)) exit(1);
[d0ffc05]308 pd = psd.hDC;
[5824d76]309
[cdbfeff]310 logpixelsy = GetDeviceCaps(pd, LOGPIXELSY);
[6b1901c]311 font_labels = CreateFont(-MulDiv(fontsize_labels, logpixelsy, 72),
312 0, 0, 0, FW_NORMAL, 0, 0, 0,
[abb82a4]313 ANSI_CHARSET, OUT_DEFAULT_PRECIS,
314 CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
[9e58834]315 FF_DONTCARE | DEFAULT_PITCH, "Arial");
[6b1901c]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,
[9e58834]320 FF_DONTCARE | DEFAULT_PITCH, "Arial");
[ca4058d]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);
[abb82a4]325 font_old = SelectObject(pd, font_labels);
326 GetTextMetrics(pd, &tm_labels);
327 SelectObject(pd, font_default);
328 GetTextMetrics(pd, &tm_default);
[9e58834]329
[8bc2567]330 memset(&info, 0, sizeof(DOCINFO));
[d0ffc05]331 info.cbSize = sizeof(DOCINFO);
[5824d76]332 info.lpszDocName = title;
333
[d0ffc05]334 StartDoc(pd, &info);
335 return 1; /* only need 1 pass */
[55b7334]336}
337
338static void
339win_NewPage(int pg, int pass, int pagesX, int pagesY)
340{
341 int x, y;
342
[396b9dd]343 x = (pg - 1) % pagesX;
344 y = pagesY - 1 - ((pg - 1) / pagesX);
345
[f17dbe2]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
[396b9dd]351 cur_pass = pass;
[f3ed07f]352 if (pass == -1) return;
[55b7334]353
354 StartPage(pd);
[7be0ba8]355 drawticks(clip, 9 * scX / POINTS_PER_MM, x, y);
[55b7334]356}
357
358static void
359win_ShowPage(const char *szPageDetails)
360{
[d0ffc05]361 win_MoveTo((long)(6 * scX) + clip.x_min, clip.y_min - (long)(7 * scY));
362 win_WriteString(szPageDetails);
363 EndPage(pd);
[55b7334]364}
365
[ca4058d]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
[9d46af2]373/* Initialise printer routines */
[3857e321]374static char *
[e1fb3cb]375win_Init(FILE **fh_list, const char *pth, const char *out_fnm,
[b7b666d]376 double *pscX, double *pscY, bool fCalibrate)
[55b7334]377{
[5824d76]378 PRINTDLGA psd;
[de035c3]379 LPDEVNAMES dn;
[abb82a4]380 static const char *vars[] = {
381 "like",
382 "font_size_labels",
[ca4058d]383 "colour_text",
384 "colour_labels",
385 "colour_frame",
386 "colour_legs",
387 "colour_crosses",
388 "colour_surface_legs",
[abb82a4]389 NULL
390 };
391 char **vals;
392
393 fCalibrate = fCalibrate; /* suppress unused argument warning */
[e1fb3cb]394 out_fnm = out_fnm;
[c34796a]395 pth = pth;
[9d46af2]396
[abb82a4]397 vals = ini_read_hier(fh_list, "win", vars);
398
[3aff368]399 fontsize_labels = as_int(vars[1], vals[1], 1, INT_MAX);
[abb82a4]400 fontsize = 10;
401
[ca4058d]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
[5824d76]408 memset(&psd, 0, sizeof(PRINTDLGA));
[d0ffc05]409 psd.lStructSize = 66;
[5824d76]410 psd.Flags = PD_RETURNDC | PD_RETURNDEFAULT;
411
[421b7d2]412 if (!PrintDlgA(&psd)) exit(1);
[5824d76]413
[d0ffc05]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);
[5757725]427
[3857e321]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;
[55b7334]435}
436
437static void
438win_Quit(void)
439{
[abb82a4]440 SelectObject(pd, font_old);
441 DeleteObject(font_labels);
442 DeleteObject(font_default);
[d0ffc05]443 EndDoc(pd);
444 DeleteDC(pd);
[55b7334]445}
Note: See TracBrowser for help on using the repository browser.