1 /**
2  * Test rubber-band selection box w/ logicops and blend.
3  */
4 
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <math.h>
8 #include <glad/glad.h>
9 #include "glut_wrap.h"
10 #include "readtex.c"
11 
12 #define IMAGE_FILE DEMOS_DATA_DIR "arch.rgb"
13 
14 static int ImgWidth, ImgHeight;
15 static GLenum ImgFormat;
16 static GLubyte *Image = NULL;
17 
18 static int Win;
19 static int Width = 512, Height = 512;
20 
21 struct rect
22 {
23    int x0, y0, x1, y1;
24 };
25 
26 static struct rect OldRect, NewRect;
27 
28 static GLboolean ButtonDown = GL_FALSE;
29 static GLboolean LogicOp = GL_TRUE;
30 
31 static GLboolean RedrawBackground = GL_TRUE;
32 
33 static int color = 0;
34 
35 
36 /*
37  * Draw rubberband box in front buffer
38  */
39 static void
DrawRect(const struct rect * r)40 DrawRect(const struct rect *r)
41 {
42    glDrawBuffer(GL_FRONT);
43 
44    if (LogicOp) {
45       glLogicOp(GL_XOR);
46       glEnable(GL_COLOR_LOGIC_OP);
47 
48       if (color == 0)
49          glColor3f(1, 1, 1);
50       else
51          glColor3ub(152, 105, 58);
52    }
53    else {
54       glEnable(GL_BLEND);
55       glBlendFunc(GL_ONE, GL_ONE);
56       glBlendEquation(GL_FUNC_SUBTRACT);
57       glColor3f(1, 1, 1);
58    }
59 
60    glBegin(GL_LINE_LOOP);
61    glVertex2i(r->x0, r->y0);
62    glVertex2i(r->x1, r->y0);
63    glVertex2i(r->x1, r->y1);
64    glVertex2i(r->x0, r->y1);
65    glEnd();
66 
67    glDisable(GL_COLOR_LOGIC_OP);
68    glDisable(GL_BLEND);
69 
70    /* Need this to ensure the front buffer drawing is actually displayed */
71    glFlush();
72 
73    glDrawBuffer(GL_BACK);
74 }
75 
76 
77 static void
PrintString(const char * s)78 PrintString(const char *s)
79 {
80    while (*s) {
81       glutBitmapCharacter(GLUT_BITMAP_8_BY_13, (int) *s);
82       s++;
83    }
84 }
85 
86 
87 static void
DrawBackground(void)88 DrawBackground(void)
89 {
90    char s[100];
91 
92    sprintf(s, "[L/B] %s mode.   Use mouse to make selection box.",
93                LogicOp ? "LogicOp" : "Blend");
94 
95    glClear(GL_COLOR_BUFFER_BIT);
96 
97    glWindowPos2i((Width - ImgWidth) / 2, (Height - ImgHeight) / 2);
98    glDrawPixels(ImgWidth, ImgHeight, ImgFormat, GL_UNSIGNED_BYTE, Image);
99 
100    glColor3f(1, 1, 1);
101    glWindowPos2i(10, 10);
102    PrintString(s);
103 
104    glutSwapBuffers();
105 }
106 
107 
108 static void
Draw(void)109 Draw(void)
110 {
111    if (RedrawBackground) {
112       DrawBackground();
113    }
114 
115    if (ButtonDown) {
116       if (!RedrawBackground)
117          DrawRect(&OldRect); /* erase old */
118 
119       DrawRect(&NewRect); /* draw new */
120 
121       OldRect = NewRect;
122    }
123 
124    RedrawBackground = GL_FALSE;
125 }
126 
127 
128 static void
Reshape(int width,int height)129 Reshape(int width, int height)
130 {
131    Width = width;
132    Height = height;
133 
134    glViewport(0, 0, width, height);
135 
136    glMatrixMode(GL_PROJECTION);
137    glLoadIdentity();
138    glOrtho(0, Width, Height, 0, -1, 1); /* Inverted Y! */
139 
140    glMatrixMode(GL_MODELVIEW);
141    glLoadIdentity();
142 
143    RedrawBackground = GL_TRUE;
144 }
145 
146 
147 static void
Key(unsigned char key,int x,int y)148 Key(unsigned char key, int x, int y)
149 {
150    (void) x;
151    (void) y;
152    switch (key) {
153    case '1':
154       glLineWidth(1);
155       break;
156    case '2':
157       glLineWidth(2);
158       break;
159    case '3':
160       glLineWidth(3);
161       break;
162    case '4':
163       glLineWidth(4);
164       break;
165    case 'b':
166    case 'B':
167       LogicOp = GL_FALSE;
168       break;
169    case 'c':
170    case 'C':
171       color = !color;
172       printf("using color %d\n", color);
173       fflush(stdout);
174       break;
175    case 'l':
176    case 'L':
177       LogicOp = GL_TRUE;
178       break;
179    case 27:
180       glutDestroyWindow(Win);
181       exit(0);
182       break;
183    }
184    RedrawBackground = GL_TRUE;
185    glutPostRedisplay();
186 }
187 
188 
189 static void
SpecialKey(int key,int x,int y)190 SpecialKey(int key, int x, int y)
191 {
192    (void) x;
193    (void) y;
194    switch (key) {
195    case GLUT_KEY_UP:
196       break;
197    case GLUT_KEY_DOWN:
198       break;
199    case GLUT_KEY_LEFT:
200       break;
201    case GLUT_KEY_RIGHT:
202       break;
203    }
204    glutPostRedisplay();
205 }
206 
207 
208 static void
MouseMotion(int x,int y)209 MouseMotion(int x, int y)
210 {
211    if (ButtonDown) {
212       NewRect.x1 = x;
213       NewRect.y1 = y;
214       glutPostRedisplay();
215    }
216 }
217 
218 
219 static void
MouseButton(int button,int state,int x,int y)220 MouseButton(int button, int state, int x, int y)
221 {
222   if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
223      ButtonDown = GL_TRUE;
224      RedrawBackground = GL_TRUE;
225      NewRect.x0 = NewRect.x1 = x;
226      NewRect.y0 = NewRect.y1 = y;
227      OldRect = NewRect;
228   }
229   else if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
230      ButtonDown = GL_FALSE;
231   }
232   glutPostRedisplay();
233 }
234 
235 
236 static void
Init(void)237 Init(void)
238 {
239    Image = LoadRGBImage(IMAGE_FILE, &ImgWidth, &ImgHeight, &ImgFormat);
240    if (!Image) {
241       printf("Couldn't read %s\n", IMAGE_FILE);
242       exit(0);
243    }
244 
245    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
246    glPixelStorei(GL_PACK_ALIGNMENT, 1);
247    glLineWidth(3);
248 }
249 
250 
251 int
main(int argc,char * argv[])252 main(int argc, char *argv[])
253 {
254    glutInit(&argc, argv);
255    glutInitWindowSize(Width, Height);
256    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
257    Win = glutCreateWindow(argv[0]);
258    gladLoadGL();
259    glutReshapeFunc(Reshape);
260    glutKeyboardFunc(Key);
261    glutSpecialFunc(SpecialKey);
262    glutMotionFunc(MouseMotion);
263    glutMouseFunc(MouseButton);
264    glutDisplayFunc(Draw);
265    Init();
266    glutPostRedisplay();
267    glutMainLoop();
268    return 0;
269 }
270