-
Notifications
You must be signed in to change notification settings - Fork 0
/
text.cxx
370 lines (321 loc) · 11.4 KB
/
text.cxx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
// File: text.cpp
// Written by:
// Grant Macklem (Grant.Macklem@colorado.edu)
// Gregory Schmelter (Gregory.Schmelter@colorado.edu)
// Alan Schmidt (Alan.Schmidt@colorado.edu)
// Ivan Stashak (Ivan.Stashak@colorado.edu)
// CSCI 4830/7818: API Programming
// University of Colorado at Boulder, Spring 2003
// http://www.cs.colorado.edu/~main/bgi
//
// This file contains the code necessary to draw/modify text
//
#include <windows.h> // Provides the Win32 API
#include <windowsx.h> // Provides GDI helper macros
#include <iostream>
#include <sstream> // Provides ostringstream
#include <string> // Provides string
#include "winbgi.h" // API routines
#include "winbgitypes.h" // Internal structure data
/*****************************************************************************
*
* Some very useful arrays -- Same as previous version for consistency
* Also, the exported definition of bgiout.
*
*****************************************************************************/
std::ostringstream bgiout;
static int font_weight[] =
{
FW_BOLD, // DefaultFont
FW_NORMAL, // TriplexFont
FW_NORMAL, // SmallFont
FW_NORMAL, // SansSerifFont
FW_NORMAL, // GothicFont
FW_NORMAL, // ScriptFont
FW_NORMAL, // SimplexFont
FW_NORMAL, // TriplexScriptFont
FW_NORMAL, // ComplexFont
FW_NORMAL, // EuropeanFont
FW_BOLD // BoldFont
};
static int font_family[] =
{
FIXED_PITCH|FF_DONTCARE, // DefaultFont
VARIABLE_PITCH|FF_ROMAN, // TriplexFont
VARIABLE_PITCH|FF_MODERN, // SmallFont
VARIABLE_PITCH|FF_DONTCARE, // SansSerifFont
VARIABLE_PITCH|FF_SWISS, // GothicFont
VARIABLE_PITCH|FF_SCRIPT, // ScriptFont
VARIABLE_PITCH|FF_DONTCARE, // SimplexFont
VARIABLE_PITCH|FF_SCRIPT, // TriplexScriptFont
VARIABLE_PITCH|FF_DONTCARE, // ComplexFont
VARIABLE_PITCH|FF_DONTCARE, // EuropeanFont
VARIABLE_PITCH|FF_DONTCARE // BoldFont
};
static char* font_name[] =
{
"Console", // DefaultFont
"Times New Roman", // TriplexFont
"Small Fonts", // SmallFont
"MS Sans Serif", // SansSerifFont
"Arial", // GothicFont
"Script", // ScriptFont
"Times New Roman", // SimplexFont
"Script", // TriplexScriptFont
"Courier New", // ComplexFont
"Times New Roman", // EuropeanFont
"Courier New Bold", // BoldFont
};
static struct { int width; int height; } font_metrics[][11] = {
{{0,0},{8,8},{16,16},{24,24},{32,32},{40,40},{48,48},{56,56},{64,64},{72,72},{80,80}}, // DefaultFont
{{0,0},{13,18},{14,20},{16,23},{22,31},{29,41},{36,51},{44,62},{55,77},{66,93},{88,124}}, // TriplexFont
{{0,0},{3,5},{4,6},{4,6},{6,9},{8,12},{10,15},{12,18},{15,22},{18,27},{24,36}}, // SmallFont
{{0,0},{11,19},{12,21},{14,24},{19,32},{25,42},{31,53},{38,64},{47,80},{57,96},{76,128}}, // SansSerifFont
{{0,0},{13,19},{14,21},{16,24},{22,32},{29,42},{36,53},{44,64},{55,80},{66,96},{88,128}}, // GothicFont
// These may not be 100% correct
{{0,0},{11,19},{12,21},{14,24},{19,32},{25,42},{31,53},{38,64},{47,80},{57,96},{76,128}}, // ScriptFont
{{0,0},{11,19},{12,21},{14,24},{19,32},{25,42},{31,53},{38,64},{47,80},{57,96},{76,128}}, // SimplexFont
{{0,0},{13,18},{14,20},{16,23},{22,31},{29,41},{36,51},{44,62},{55,77},{66,93},{88,124}}, // TriplexScriptFont
{{0,0},{11,19},{12,21},{14,24},{19,32},{25,42},{31,53},{38,64},{47,80},{57,96},{76,128}}, // ComplexFont
{{0,0},{11,19},{12,21},{14,24},{19,32},{25,42},{31,53},{38,64},{47,80},{57,96},{76,128}}, // EuropeanFont
{{0,0},{11,19},{12,21},{14,24},{19,32},{25,42},{31,53},{38,64},{47,80},{57,96},{76,128}} // BoldFont
};
// horiz LEFT_TEXT 0 left-justify text
// CENTER_TEXT 1 center text
// RIGHT_TEXT 2 right-justify text
// vertical BOTTOM_TEXT 0 bottom-justify text
// CENTER_TEXT 1 center text
// TOP_TEXT 2 top-justify text
static UINT horiz_align[3] = {TA_LEFT, TA_CENTER, TA_RIGHT};
static UINT vert_align[3] = {TA_BOTTOM, TA_BASELINE, TA_TOP};
/*****************************************************************************
*
* Some helper functions
*
*****************************************************************************/
// This function
// POSTCONDITION:
//
static void set_align(WindowData* pWndData)
{
UINT alignment = pWndData->alignment;
// if we are vertical, things are swapped.
if (pWndData->textInfo.direction == HORIZ_DIR)
{
alignment |= horiz_align[pWndData->textInfo.horiz];
alignment |= vert_align[pWndData->textInfo.vert];
}
else
{
alignment |= horiz_align[pWndData->textInfo.vert];
alignment |= vert_align[pWndData->textInfo.horiz];
}
// set the alignment for all valid pages.
for ( int i = 0; i < MAX_PAGES; i++ )
SetTextAlign(pWndData->hDC[i], alignment);
}
// This function updates the current hdc with the user defined font
// POSTCONDITION: text written to the current hdc will be in the new font
//
static void set_font(WindowData* pWndData)
{
int mindex;
double xscale, yscale;
HFONT hFont;
// get the scaling factors based on charsize
if(pWndData->textInfo.charsize == 0)
{
xscale = pWndData->t_scale[0] / pWndData->t_scale[1];
yscale = pWndData->t_scale[2] / pWndData->t_scale[3];
// if font zero, only use factors.. else also multiply by 4
if (pWndData->textInfo.font == 0)
mindex = 0;
else
mindex = 4;
}
else
{
xscale = 1.0;
yscale = 1.0;
mindex = pWndData->textInfo.charsize;
}
// with the scaling decided, make a font.
hFont = CreateFont(
int(font_metrics[pWndData->textInfo.font][mindex].height * yscale),
int(font_metrics[pWndData->textInfo.font][mindex].width * xscale),
pWndData->textInfo.direction * 900,
(pWndData->textInfo.direction & 1) * 900,
font_weight[pWndData->textInfo.font],
FALSE,
FALSE,
FALSE,
DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY,
font_family[pWndData->textInfo.font],
font_name[pWndData->textInfo.font]
);
// assign the fonts to each of the hdcs
for ( int i = 0; i < MAX_PAGES; i++ )
SelectObject( pWndData->hDC[i], hFont );
}
/*****************************************************************************
*
* The actual API calls are implemented below
*
*****************************************************************************/
// This function fills the textsettingstype structure pointed to by textinfo
// with information about the current text font, direction, size, and
// justification.
// POSTCONDITION: texttypeinfo has been filled with the proper information
//
void gettextsettings(struct textsettingstype *texttypeinfo)
{
// if its null, leave.
if (!texttypeinfo)
return;
WindowData* pWndData = BGI__GetWindowDataPtr( );
*texttypeinfo = pWndData->textInfo;
}
// This function prints textstring to the screen at the current position
// POSTCONDITION: text has been written to the screen using the current font,
// direction, and size. In addition, the current position has
// been modified to reflect the text that was just output.
//
void outtext(char *textstring)
{
HDC hDC = BGI__GetWinbgiDC( );
WindowData* pWndData = BGI__GetWindowDataPtr( );
// so we can clear the screen
POINT cp;
GetCurrentPositionEx( hDC, &cp );
// check cp alignment
if (pWndData->alignment != TA_UPDATECP)
{
pWndData->alignment = TA_UPDATECP;
set_align(pWndData);
}
TextOut(hDC, 0, 0, (LPCTSTR)textstring, strlen(textstring));
BGI__ReleaseWinbgiDC( );
RefreshWindow( NULL );
// Todo: Change to refresh only the needed part.
}
// This function prints textstring to x,y
// POSTCONDITION: text has been written to the screen using the current font,
// direction, and size. If a string is printed with the default
// font using outtext or outtextxy, any part of the string that
// extends outside the current viewport is truncated.
//
void outtextxy(int x, int y, char *textstring)
{
HDC hDC = BGI__GetWinbgiDC( );
WindowData* pWndData = BGI__GetWindowDataPtr( );
// check alignment
if (pWndData->alignment != TA_NOUPDATECP)
{
pWndData->alignment = TA_NOUPDATECP;
set_align(pWndData);
}
TextOut(hDC, x, y, (LPCTSTR)textstring, strlen(textstring));
BGI__ReleaseWinbgiDC( );
RefreshWindow( NULL );
// Todo: Change to refresh only the needed part.
}
// This function sets the vertical and horizontal justification based on CP
// POSTCONDITION: Text output is justified around the current position as
// has been specified.
//
void settextjustify(int horiz, int vert)
{
WindowData* pWndData = BGI__GetWindowDataPtr( );
pWndData->textInfo.horiz = horiz;
pWndData->textInfo.vert = vert;
WaitForSingleObject(pWndData->hDCMutex, 5000);
set_align(pWndData);
ReleaseMutex(pWndData->hDCMutex);
}
// This function sets the font and it's properties that will be used
// by all text output related functions.
// POSTCONDITION: text output after a call to settextstyle should be
// in the newly specified format.
//
void settextstyle(int font, int direction, int charsize)
{
WindowData* pWndData = BGI__GetWindowDataPtr( );
pWndData->textInfo.font = font;
pWndData->textInfo.direction = direction;
pWndData->textInfo.charsize = charsize;
WaitForSingleObject(pWndData->hDCMutex, 5000);
set_font(pWndData);
ReleaseMutex(pWndData->hDCMutex);
}
// This function sets the size of stroked fonts
// POSTCONDITION: these values will be used when charsize is zero in the
// settextstyle assignments. consequently output text will
// be scaled by the appropriate x and y values when output.
//
void setusercharsize(int multx, int divx, int multy, int divy)
{
WindowData* pWndData = BGI__GetWindowDataPtr( );
pWndData->t_scale[0] = multx;
pWndData->t_scale[1] = divx;
pWndData->t_scale[2] = multy;
pWndData->t_scale[3] = divy;
WaitForSingleObject(pWndData->hDCMutex, 5000);
set_font(pWndData);
ReleaseMutex(pWndData->hDCMutex);
}
// This function returns the height in pixels of textstring using the current
// text output settings.
// POSTCONDITION: the height of the string in pixels has been returned.
//
int textheight(char *textstring)
{
HDC hDC = BGI__GetWinbgiDC( );
SIZE tb;
GetTextExtentPoint32(hDC, (LPCTSTR) textstring, strlen(textstring), &tb);
BGI__ReleaseWinbgiDC( );
return tb.cy;
}
// This function returns the width in pixels of textstring using the current
// text output settings.
// POSTCONDITION: the width of the string in pixels has been returned.
//
int textwidth(char *textstring)
{
HDC hDC = BGI__GetWinbgiDC( );
SIZE tb;
GetTextExtentPoint32(hDC, (LPCTSTR) textstring, strlen(textstring), &tb);
BGI__ReleaseWinbgiDC( );
return tb.cx;
}
void outstreamxy(int x, int y, std::ostringstream& out)
{
std::string all, line;
int i;
int startx = x;
all = out.str( );
out.str("");
moveto(x,y);
for (i = 0; i < all.length( ); i++)
{
if (all[i] == '\n')
{
if (line.length( ) > 0)
outtext((char *) line.c_str( ));
y += textheight("X");
x = startx;
line.clear( );
moveto(x,y);
}
else
line += all[i];
}
if (line.length( ) > 0)
outtext((char *) line.c_str( ));
}
void outstream(std::ostringstream& out)
{
outstreamxy(getx( ), gety( ), out);
}