Screenshot using convoluted SDL2 approach
[ipdf/code.git] / src / screen.cpp
1 #include "common.h"
2 #include "screen.h"
3
4 #include "SDL_opengl.h"
5
6 using namespace IPDF;
7 using namespace std;
8
9 Screen::Screen()
10 {
11         SDL_Init(SDL_INIT_VIDEO);
12         m_window = SDL_CreateWindow("IPDF", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
13                         800, 600, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
14
15         if (!m_window)
16         {
17                 Fatal("Couldn't create window!");
18         }
19
20         m_gl_context = SDL_GL_CreateContext(m_window);
21         
22         ResizeViewport(800, 600);
23
24 }
25
26 Screen::~Screen()
27 {
28         SDL_GL_DeleteContext(m_gl_context);
29         SDL_DestroyWindow(m_window);
30         SDL_Quit();
31 }
32
33 void Screen::ResizeViewport(int width, int height)
34 {
35         glViewport(0, 0, width, height);
36         m_viewport_width = width;
37         m_viewport_height = height;
38 }
39
40 bool Screen::PumpEvents()
41 {
42         SDL_Event evt;
43         bool no_quit_requested = true;
44         while (SDL_PollEvent(&evt))
45         {
46                 switch (evt.type)
47                 {
48                 case SDL_QUIT:
49                         no_quit_requested = false;
50                         break;
51                 case SDL_WINDOWEVENT:
52                         switch (evt.window.event)
53                         {
54                         case SDL_WINDOWEVENT_RESIZED:
55                         case SDL_WINDOWEVENT_SIZE_CHANGED:
56                                 ResizeViewport(evt.window.data1, evt.window.data2);
57                                 break;
58                         }
59                         break;
60                 case SDL_MOUSEMOTION:
61                         m_last_mouse_x = evt.motion.x;
62                         m_last_mouse_y = evt.motion.y;
63                         if (m_mouse_handler)
64                         {
65                                 m_mouse_handler(evt.motion.x, evt.motion.y,evt.motion.state, 0);
66                         }
67                         break;
68                 case SDL_MOUSEBUTTONDOWN:
69                 case SDL_MOUSEBUTTONUP:
70                         m_last_mouse_x = evt.button.x;
71                         m_last_mouse_y = evt.button.y;
72                         if (m_mouse_handler)
73                         {
74                                 m_mouse_handler(evt.button.x, evt.button.y, evt.button.state, 0);
75                         }
76                         break;
77                 case SDL_MOUSEWHEEL:
78                         if (m_mouse_handler)
79                         {
80                                 m_mouse_handler(m_last_mouse_x, m_last_mouse_y, 0, evt.wheel.y);
81                         }
82                         break;
83                 case SDL_KEYDOWN:
84                 {
85                         Debug("Key %c down", (char)evt.key.keysym.sym);
86                         if (isalnum((char)evt.key.keysym.sym))
87                         {
88                                 char filename[] = "0.bmp";
89                                 filename[0] = (char)evt.key.keysym.sym;
90                                 ScreenShot(filename);
91                         }
92                 }
93                 default:
94                         break;
95                 }
96         }
97         return no_quit_requested;
98 }
99
100 void Screen::SetMouseCursor(Screen::MouseCursors cursor)
101 {
102         SDL_SystemCursor system_cursor_id = SDL_SYSTEM_CURSOR_ARROW;
103         switch (cursor)
104         {
105         case CursorArrow: system_cursor_id = SDL_SYSTEM_CURSOR_ARROW; break;
106         case CursorWait: system_cursor_id = SDL_SYSTEM_CURSOR_WAIT; break;
107         case CursorWaitArrow: system_cursor_id = SDL_SYSTEM_CURSOR_WAITARROW; break;
108         case CursorMove: system_cursor_id = SDL_SYSTEM_CURSOR_SIZEALL; break;
109         case CursorHand: system_cursor_id = SDL_SYSTEM_CURSOR_HAND; break;
110         default: break;
111         }
112         SDL_Cursor *system_cursor = SDL_CreateSystemCursor(system_cursor_id);
113         SDL_SetCursor(system_cursor);
114         //TODO: Check if we need to free the system cursors.
115 }
116
117 void Screen::Present()
118 {
119         SDL_GL_SwapWindow(m_window);
120 }
121
122 void Screen::ScreenShot(const char * filename) const
123 {
124         Debug("Attempting to save BMP to file %s", filename);
125         SDL_Surface * info = SDL_GetWindowSurface(m_window);
126         if (info == NULL)
127         {
128                 Fatal("Failed to create info surface from m_window - %s", SDL_GetError());
129         }
130         
131         unsigned num_pix = info->w * info->h * info->format->BytesPerPixel;
132         unsigned char * pixels = new unsigned char[num_pix];
133         if (pixels == NULL)
134         {
135                 Fatal("Failed to allocate %u pixel array - %s", num_pix, strerror(errno));
136         }
137
138         SDL_Renderer * renderer = SDL_GetRenderer(m_window);
139         if (renderer == NULL)
140         {
141                 Fatal("Couldn't get renderer from m_window - %s", SDL_GetError());
142         }
143         if (SDL_RenderReadPixels(renderer, &(info->clip_rect), info->format->format, pixels, info->w * info->format->BytesPerPixel) != 0)
144         {
145                 Fatal("SDL_RenderReadPixels failed - %s", SDL_GetError());
146         }
147
148         // This line is disgusting
149         SDL_Surface * save = SDL_CreateRGBSurfaceFrom(pixels, info->w, info->h, info->format->BitsPerPixel, info->w * info->format->BytesPerPixel, 
150                                                                                         info->format->Rmask, info->format->Gmask, info->format->Bmask, info->format->Amask);
151         if (save == NULL)
152         {
153                 Fatal("Couldn't create SDL_Surface from renderer pixel data - %s", SDL_GetError());
154         }
155         if (SDL_SaveBMP(save, filename) != 0)
156         {
157                 Fatal("SDL_SaveBMP to %s failed - %s", filename, SDL_GetError());
158         }
159
160         //SDL_DestroyRenderer(renderer);
161         SDL_FreeSurface(save);
162         SDL_FreeSurface(info);
163         delete [] pixels;
164
165         Debug("Succeeded!");
166
167
168 }

UCC git Repository :: git.ucc.asn.au