forked from JACoders/OpenJK
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcm_draw.h
263 lines (202 loc) · 9.04 KB
/
cm_draw.h
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
/*
This file is part of Jedi Academy.
Jedi Academy is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
Jedi Academy is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Jedi Academy. If not, see <http://www.gnu.org/licenses/>.
*/
// Copyright 2001-2013 Raven Software
///////////////////////////////////////////////////////////////////////////////
// CDraw32 Class Interface
//
// Basic drawing routines for 32-bit per pixel buffer
///////////////////////////////////////////////////////////////////////////////
#if !defined(CM_DRAW_H_INC)
#define CM_DRAW_H_INC
// calc offset into image array for a pixel at (x,y)
#define PIXPOS(x,y,stride) (((y)*(stride))+(x))
#ifndef MIN
// handy macros
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#define ABS(x) ((x)<0 ? -(x):(x))
#define SIGN(x) (((x) < 0) ? -1 : (((x) > 0) ? 1 : 0))
#endif
#ifndef CLAMP
#define SWAP(a,b) { a^=b; b^=a; a^=b; }
#define SQR(a) ((a)*(a))
#define CLAMP(v,l,h) ((v)<(l) ? (l) : (v) > (h) ? (h) : (v))
#define LERP(t, a, b) (((b)-(a))*(t) + (a))
// round a to nearest integer towards 0
#define FLOOR(a) ((a)>0 ? (int)(a) : -(int)(-a))
// round a to nearest integer away from 0
#define CEILING(a) \
((a)==(int)(a) ? (a) : (a)>0 ? 1+(int)(a) : -(1+(int)(-a)))
#include <stdlib.h>
#endif
class CPixel32
{
public:
byte r;
byte g;
byte b;
byte a;
CPixel32(byte R = 0, byte G = 0, byte B = 0, byte A = 255) : r(R), g(G), b(B), a(A) {}
CPixel32(long l) {r = (l >> 24) & 0xff; g = (l >> 16) & 0xff; b = (l >> 8) & 0xff; a = l & 0xff;};
~CPixel32()
{}
};
#define PIX32_SIZE sizeof(CPixel32)
// standard image operator macros
#define IMAGE_SIZE(width,height) ((width)*(height)*(PIX32_SIZE))
inline CPixel32 AVE_PIX (CPixel32 x, CPixel32 y)
{ CPixel32 t; t.r = (byte)(((int)x.r + (int)y.r)>>1);
t.g = (byte)(((int)x.g + (int)y.g)>>1);
t.b = (byte)(((int)x.b + (int)y.b)>>1);
t.a = (byte)(((int)x.a + (int)y.a)>>1); return t;}
inline CPixel32 ALPHA_PIX (CPixel32 x, CPixel32 y, long alpha, long inv_alpha)
{ CPixel32 t; t.r = (byte)((x.r*alpha + y.r*inv_alpha)>>8);
t.g = (byte)((x.g*alpha + y.g*inv_alpha)>>8);
t.b = (byte)((x.b*alpha + y.b*inv_alpha)>>8);
// t.a = (byte)((x.a*alpha + y.a*inv_alpha)>>8); return t;}
t.a = y.a; return t;}
inline CPixel32 LIGHT_PIX (CPixel32 p, long light)
{ CPixel32 t;
t.r = (byte)CLAMP(((p.r * light)>>10) + p.r, 0, 255);
t.g = (byte)CLAMP(((p.g * light)>>10) + p.g, 0, 255);
t.b = (byte)CLAMP(((p.b * light)>>10) + p.b, 0, 255);
t.a = p.a; return t;}
// Colors are 32-bit RGBA
// draw class
class CDraw32
{
public: // static drawing context - static so we set only ONCE for many draw calls
static CPixel32* buffer; // pointer to pixel buffer (one active)
static long buf_width; // size of buffer
static long buf_height; // size of buffer
static long stride; // stride of buffer in pixels
static long clip_min_x; // clip bounds
static long clip_min_y; // clip bounds
static long clip_max_x; // clip bounds
static long clip_max_y; // clip bounds
static long* row_off; // Table for quick Y calculations
private:
void BlitClip(long& dstX, long& dstY,
long& width, long& height,
long& srcX, long& srcY);
protected:
public:
CDraw32(); // constructor
~CDraw32(); // destructor
// set the rect to clip drawing functions to
static void SetClip(long min_x, long min_y,long max_x, long max_y)
{clip_min_x = MAX(min_x,0); clip_max_x = MIN(max_x,buf_width-1);
clip_min_y = MAX(min_y,0); clip_max_y = MIN(max_y,buf_height-1);}
static void GetClip(long& min_x, long& min_y,long& max_x, long& max_y)
{min_x = clip_min_x; min_y = clip_min_y;
max_x = clip_max_x; max_y = clip_max_y; }
// set the buffer to use for drawing off-screen
static void SetBuffer(CPixel32* buf) {buffer = buf;};
// set the dimensions of the off-screen buffer
static bool SetBufferSize(long width,long height,long stride_len);
// call this to free the table for quick y calcs before the program ends
static void CleanUp(void)
{if (row_off) delete [] row_off; row_off=NULL; buf_width=0; buf_height=0;}
// set a pixel at (x,y) to color (no clipping)
void PutPixNC(long x, long y, CPixel32 color)
{buffer[row_off[y] + x] = color;}
// set a pixel at (x,y) to color
void PutPix(long x, long y, CPixel32 color)
{ // clipping check
if (x < clip_min_x || x > clip_max_x ||
y < clip_min_y || y > clip_max_y)
return;
PutPixNC(x,y,color);
}
// get the color of a pixel at (x,y)
CPixel32 GetPix(long x, long y)
{return buffer[row_off[y] + x];}
// set a pixel at (x,y) with 50% translucency (no clip)
void PutPixAveNC(long x, long y, CPixel32 color)
{ PutPixNC(x,y,AVE_PIX(GetPix(x, y), color)); }
// set a pixel at (x,y) with 50% translucency
void PutPixAve(long x, long y, CPixel32 color)
{ // clipping check
if (x < clip_min_x || x > clip_max_x ||
y < clip_min_y || y > clip_max_y)
return;
PutPixNC(x,y,AVE_PIX(GetPix(x, y), color));
}
// set a pixel at (x,y) with translucency level (no clip)
void PutPixAlphaNC(long x, long y, CPixel32 color)
{ PutPixNC(x,y,ALPHA_PIX(color, GetPix(x, y), color.a, 256-color.a));}
// set a pixel at (x,y) with translucency level
void PutPixAlpha(long x, long y, CPixel32 color)
{ // clipping check
if (x < clip_min_x || x > clip_max_x ||
y < clip_min_y || y > clip_max_y)
return;
PutPixNC(x,y,ALPHA_PIX(color, GetPix(x, y), color.a, 256-color.a));}
// clear screen buffer to color from start to end line
void ClearLines(CPixel32 color,long start,long end);
// clear screen buffer to color provided
void ClearBuffer(CPixel32 color)
{ClearLines(color,0,buf_height-1);};
// fill buffer alpha from start to end line
void SetAlphaLines(byte alpha,long start,long end);
// clear screen buffer to color provided
void SetAlphaBuffer(byte alpha)
{SetAlphaLines(alpha,0,buf_height-1);};
// clip a line segment to the clip rect
bool ClipLine(long& x1, long& y1, long& x2, long& y2);
// draw a solid colored line, no clipping
void DrawLineNC(long x1, long y1, long x2, long y2, CPixel32 color);
// draw a solid color line
void DrawLine(long x1, long y1, long x2, long y2, CPixel32 color)
{ if (ClipLine(x1,y1,x2,y2)) DrawLineNC(x1,y1,x2,y2,color);}
void DrawLineAveNC(long x1, long y1, long x2, long y2, CPixel32 color);
// draw a translucent solid color line
void DrawLineAve(long x1, long y1, long x2, long y2, CPixel32 color)
{ if (ClipLine(x1,y1,x2,y2)) DrawLineAveNC(x1,y1,x2,y2,color);}
// draw an anti-aliased line, no clipping
void DrawLineAANC(long x0, long y0, long x1, long y1, CPixel32 color);
// draw an anti-aliased line
void DrawLineAA(long x1, long y1, long x2, long y2, CPixel32 color)
{ if (ClipLine(x1,y1,x2,y2)) DrawLineAANC(x1,y1,x2,y2,color);}
// draw a filled rectangle, no clipping
void DrawRectNC(long ulx, long uly, long width, long height,CPixel32 color);
// draw a filled rectangle
void DrawRect(long ulx, long uly, long width, long height, CPixel32 color);
// draw a filled rectangle
void DrawRectAve(long ulx, long uly, long width, long height,CPixel32 color);
// draw a box (unfilled rectangle) no clip
void DrawBoxNC(long ulx, long uly, long width, long height, CPixel32 color);
// draw a box (unfilled rectangle)
void DrawBox(long ulx, long uly, long width, long height, CPixel32 color);
// draw a box (unfilled rectangle)
void DrawBoxAve(long ulx, long uly, long width, long height, CPixel32 color);
// draw a circle with fill and edge colors
void DrawCircle(long xc, long yc, long r, CPixel32 edge, CPixel32 fill);
// draw a circle with fill and edge colors averaged with dest
void DrawCircleAve(long xc, long yc, long r, CPixel32 edge, CPixel32 fill);
// draw a polygon (complex) with fill and edge colors
void DrawPolygon(long nvert, Point *point, CPixel32 edge, CPixel32 fill);
// simple blit function
void BlitNC(long dstX, long dstY, long dstWidth, long dstHeight,
CPixel32* srcImage, long srcX, long srcY, long srcStride);
void Blit(long dstX, long dstY, long dstWidth, long dstHeight,
CPixel32* srcImage, long srcX, long srcY, long srcStride);
// blit image times color
void BlitColor(long dstX, long dstY, long dstWidth, long dstHeight,
CPixel32* srcImage, long srcX, long srcY, long srcStride, CPixel32 color);
void Emboss(long dstX, long dstY, long width, long height,
CPixel32* clrImage, long clrX, long clrY, long clrStride);
};
///////////////////////////////////////////////////////////////////////////////
#endif