OSDN Git Service

first
[psychlops/cpp.git] / psychlops / platform / win32gl / psychlops_g_API_win32gl.cpp
1 /*
2  *  psychlops_g_canvas_API_WIN32.cpp
3  *  Psychlops Standard Library (MacOSX)
4  *
5  *  Last Modified 2009/05/12 by Kenchi HOSOKAWA
6  *  (C) 2005-2009 Kenchi HOSOKAWA, Kazushi MARUYA, Takao SATO
7  */
8
9 #include <vector>
10 #include <map>\r
11 \r
12 #include <windows.h>\r
13 #include <gl/gl.h>\r
14 #include <gl/glu.h>\r
15 \r
16 #include "psychlops_g_API_win32gl.h"\r
17 #include "../win32/psychlops_app_state_Win32.h"\r
18 #include "../win32/psychlops_io_API_WIN32.h"
19 #include "../win32/psychlops_io_display_Win32.h"\r
20 #include "../../core/ApplicationInterfaces/psychlops_code_exception.h"\r
21 #include "../../core/graphic/psychlops_g_color.h"
22 #include "../../core/graphic/psychlops_g_image.h"\r
23 #include "../../core/graphic/psychlops_g_font.h"\r
24 #include "../../core/math/psychlops_m_util.h"\r
25 \r
26 \r
27 \r
28 \r
29 namespace Psychlops {\r
30 \r
31
32         WNDCLASSEX APICanvasProperties::wcx;
33         bool APICanvasProperties::wcx_setted = false;
34         void APICanvasProperties::setWindowClass() {
35                 if(!wcx_setted) {
36                         wcx.cbSize        = sizeof(WNDCLASSEX);
37                         wcx.style         = CS_GLOBALCLASS;
38                         wcx.lpfnWndProc   = (WNDPROC)&(APIApplicationProperties::proc);
39                         wcx.cbClsExtra    = 0;
40                         wcx.cbWndExtra    = 0;
41                         wcx.hInstance     = APIApplicationProperties::startupinfo.hInstance_;
42                         wcx.hIcon         = NULL;
43                         wcx.hIconSm       = NULL;
44                         wcx.hCursor       = NULL;
45                         wcx.hbrBackground = NULL;
46                         wcx.lpszMenuName  = "Psychlops Window";
47                         wcx.lpszClassName = APIApplicationProperties::startupinfo.pClassName;
48                         if (!RegisterClassEx(&wcx)) Exception(typeid(APICanvasProperties), "API ERROR", "Failed to regist main window.");
49                         wcx_setted = true;
50                 }
51         }\r
52
53         APICanvasProperties::APICanvasProperties()\r
54          : outer(0), has_instance_(false), the_display_(0), savedGammaRamp_ptr_(&savedGammaRamp_), calibration_mode_(Color::NOTHING)
55           ,vleft(0), vright(0), vtop(0), vbottom(0)\r
56         {
57                 the_display_ = GetDC(0);\r
58         }\r
59         APICanvasProperties::~APICanvasProperties() {
60                 outer = 0;\r
61                 destroyCanvasInstance();\r
62         }\r
63         void APICanvasProperties::getDisplayMertix(const Display& d) {
64                 HDC display_ = d.api_->display_;
65                 width_ = GetDeviceCaps(display_, HORZRES);
66                 height_ = GetDeviceCaps(display_, VERTRES);
67                 colordepth_ = GetDeviceCaps(display_, BITSPIXEL);
68                 refreshrate_ = GetDeviceCaps(display_, VREFRESH);
69                 vleft=d.area.getLeft(); vright=d.area.getRight(); vtop=d.area.getTop(); vbottom=d.area.getBottom();
70         }
71         void APICanvasProperties::generateCanvasInstance(const Display& d) {
72                 the_display_ = d.api_->display_;
73                 vleft=d.area.getLeft(); vright=d.area.getRight(); vtop=d.area.getTop(); vbottom=d.area.getBottom();\r
74                 memset(&mode_,0,sizeof(mode_));\r
75                 memset(&original_mode_,0,sizeof(original_mode_));\r
76                 original_mode_.dmSize = sizeof(mode_);\r
77                 original_mode_.dmPelsWidth  = GetDeviceCaps(the_display_, HORZRES);\r
78                 original_mode_.dmPelsHeight = GetDeviceCaps(the_display_, VERTRES);\r
79                 original_mode_.dmBitsPerPel     = GetDeviceCaps(the_display_, BITSPIXEL);\r
80                 original_mode_.dmDisplayFrequency = GetDeviceCaps(the_display_, VREFRESH);\r
81                 original_mode_.dmFields     = DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT|DM_DISPLAYFREQUENCY;\r
82                 mode_ = original_mode_;\r
83                 generateCanvasInstance(mode_, d);\r
84         }\r
85         void APICanvasProperties::generateCanvasInstance(int d_width, int d_height, int d_colordepth, double d_refreshrate, const Display& d) {\r
86                 the_display_ = d.api_->display_;
87                 vleft=d.area.getLeft(); vright=d.area.getRight(); vtop=d.area.getTop(); vbottom=d.area.getBottom();
88                 memset(&mode_,0,sizeof(mode_));\r
89                 memset(&original_mode_,0,sizeof(original_mode_));\r
90                 mode_.dmSize       = sizeof(mode_);\r
91                 mode_.dmPelsWidth       = d_width;\r
92                 mode_.dmPelsHeight      = d_height;\r
93                 mode_.dmBitsPerPel      = d_colordepth;\r
94                 mode_.dmDisplayFrequency = d_refreshrate;\r
95                 mode_.dmFields     = DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT|DM_DISPLAYFREQUENCY;\r
96                 generateCanvasInstance(mode_, d);\r
97         }\r
98         void APICanvasProperties::generateCanvasInstance(DEVMODE &d_mode, const Display& d) {
99                 setWindowClass();
100 \r
101                 // Try to set selected mode and get results. NOTE: CDS_FULLSCREEN gets rid of start bar.\r
102                 //if (ChangeDisplaySettings(&d_mode,CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) throw Exception(typeid(APICanvasProperties), "API ERROR", "API Error (Failed to switch display mode)");\r
103                 if(ChangeDisplaySettingsEx(d.name.c_str(), &d_mode, NULL, CDS_FULLSCREEN, NULL) != DISP_CHANGE_SUCCESSFUL)
104                         throw Exception(typeid(APICanvasProperties), "API ERROR", "API Error (Failed to switch display mode)");\r
105                 width_       = d_mode.dmPelsWidth;\r
106                 height_      = d_mode.dmPelsHeight;\r
107                 colordepth_  = d_mode.dmBitsPerPel;\r
108                 refreshrate_ = d_mode.dmDisplayFrequency;\r
109                 ShowCursor(false);\r
110 \r
111                 the_window_ = CreateWindowEx(\r
112                         WS_EX_APPWINDOW | WS_EX_TOPMOST,\r
113                         APIApplicationProperties::startupinfo.pClassName,\r
114                         "Psychlops Window",\r
115                         WS_POPUP,\r
116                         //0, 0, d_width, d_height,\r
117                         //vleft, vtop, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN),\r
118                         vleft, vtop, width_, height_,\r
119                         NULL, NULL, wcx.hInstance, NULL );\r
120                 if(the_window_==NULL) throw Exception(typeid(APICanvasProperties), "API ERROR", "Failed to regist main window.");\r
121 \r
122                 // attach OpenGL context for the window\r
123                 attachOpenGLContext( &the_window_, &the_display_, &the_GL_context_, mode_.dmBitsPerPel );\r
124                 //glAddSwapHintRectWIN(0, 0, width_, height_);\r
125 \r
126                 has_instance_ = true;\r
127                 calibration_mode_ = Color::NOTHING;\r
128 \r
129                 MSG msg;\r
130                 PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);\r
131 \r
132 //              if(0==AttachThreadInput(GetWindowThreadProcessId(hWnd, NULL), GetWindowThreadProcessId(APIInputProperties::hWnd, NULL), TRUE) )\r
133 //                      throw Exception(typeid(APICanvasProperties), "API ERROR", "Failed to regist control message listner.");\r
134 //              if(0==SetFocus(APIInputProperties::hWnd))\r
135 //                      throw Exception(typeid(APICanvasProperties), "API ERROR", "Failed to regist control message listner.");\r
136 //              SetActiveWindow(APIInputProperties::hWnd);\r
137                 ShowWindow(the_window_, APIApplicationProperties::startupinfo.iCmdShow_);\r
138 //              BringWindowToTop(hWnd);\r
139         }\r
140         void APICanvasProperties::attachOpenGLContext(HWND *hWnd, HDC * hDC, HGLRC * hRC, int d_colordepth) {\r
141                 int format;\r
142 \r
143                 // get the device context (DC)\r
144                 *hDC = GetDC( *hWnd );\r
145 \r
146                 // set the pixel format for the DC\r
147                 /*PIXELFORMATDESCRIPTOR pfd = {\r
148                         sizeof(PIXELFORMATDESCRIPTOR),   // size of this pfd\r
149                         1,                     // version number\r
150                         PFD_GENERIC_ACCELERATED |\r
151                         PFD_SWAP_COPY |\r
152                         PFD_DRAW_TO_WINDOW |   // support window\r
153                         PFD_DRAW_TO_BITMAP |\r
154                         PFD_SUPPORT_OPENGL |   // support OpenGL\r
155                         PFD_DOUBLEBUFFER,      // double buffered\r
156                         PFD_TYPE_RGBA,         // RGBA type\r
157                         d_colordepth,          // color depth\r
158                         0, 0, 0, 0, 0, 0,      // color bits ignored\r
159                         0,                     // no alpha buffer\r
160                         0,                     // shift bit ignored\r
161                         0,                     // no accumulation buffer\r
162                         0, 0, 0, 0,            // accum bits ignored\r
163                         16,                    // 16-bit z-buffer\r
164                         1,                     // 1 stencil buffer\r
165                         4,                     // 4 auxiliary buffer\r
166                         PFD_MAIN_PLANE,        // main layer\r
167                         0,                     // reserved\r
168                         0, 0, 0                // layer masks ignored\r
169                 };*/\r
170                 PIXELFORMATDESCRIPTOR pfd;\r
171                 ZeroMemory( &pfd, sizeof( pfd ) );\r
172                 pfd.nSize = sizeof( pfd );\r
173                 pfd.nVersion = 2;\r
174                 pfd.dwFlags = PFD_GENERIC_ACCELERATED | PFD_SWAP_EXCHANGE |\r
175                  PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;\r
176                 pfd.iPixelType = PFD_TYPE_RGBA;\r
177                 pfd.cColorBits = d_colordepth;\r
178                 pfd.cRedBits = d_colordepth/4;\r
179                 pfd.cGreenBits = d_colordepth/4;\r
180                 pfd.cBlueBits = d_colordepth/4;\r
181                 pfd.cAlphaBits = d_colordepth/4;\r
182                 pfd.cDepthBits = 32;\r
183                 pfd.iLayerType = PFD_MAIN_PLANE;\r
184                 pfd.cStencilBits = 1;\r
185                 pfd.cAuxBuffers = 4;\r
186                 format = ChoosePixelFormat( *hDC, &pfd );\r
187                 if(!(SetPixelFormat( *hDC, format, &pfd ))) throw Exception(typeid(APICanvasProperties), "API ERROR", "API Error (Failed to set pixel format).");\r
188 \r
189                 // create and enable the render context (RC)\r
190                 if(!(*hRC = wglCreateContext( *hDC ))) throw Exception(typeid(APICanvasProperties), "API ERROR", "API Error (Failed to set OpenGL context).");\r
191                 if(!(wglMakeCurrent( *hDC, *hRC ))) throw Exception(typeid(APICanvasProperties), "API ERROR", "API Error (Failed to set OpenGL context).");\r
192 /**/\r
193                 //PROC vsync = wglGetProcAddress("wglSwapInterval");\r
194                 //if(vsync!=NULL) {\r
195                 //      vsync();\r
196                 //}\r
197                 typedef bool (APIENTRY *PFNWGLSWAPINTERVALFARPROC)(int);
198                 PFNWGLSWAPINTERVALFARPROC wglSwapIntervalEXT = 0;
199                 wglSwapIntervalEXT = (PFNWGLSWAPINTERVALFARPROC)wglGetProcAddress("wglSwapIntervalEXT");
200                 if( wglSwapIntervalEXT ) {
201                         wglSwapIntervalEXT(1);
202                         vsync_available_ = true;
203                 } else {
204                         //throw Exception("API function[wglSwapIntervalEXT] failed to enforce buffer swap to synchronize to vsync.");
205                         vsync_available_ = false;
206                 }
207 /**/\r
208         }\r
209 \r
210         void APICanvasProperties::destroyCanvasInstance() {\r
211                 if(has_instance_) {\r
212                         destroyGammaSettings();\r
213                         detachOpenGLContext( the_window_, the_display_, the_GL_context_ );\r
214                         DestroyWindow( the_window_ );\r
215                         if(window_type == FULLSCREEN) {\r
216                                 ChangeDisplaySettings(NULL,0);\r
217                                 ShowCursor(true);\r
218                         }\r
219                 }\r
220                 has_instance_ = false;\r
221         }\r
222         void APICanvasProperties::detachOpenGLContext(HWND hWnd, HDC hDC, HGLRC hRC) {\r
223                 wglMakeCurrent( NULL, NULL );\r
224                 wglDeleteContext( hRC );\r
225                 ReleaseDC( hWnd, hDC );\r
226         }\r
227 \r
228         double APICanvasProperties::limit(double v) {\r
229                 double r = v;\r
230                 if(r<0     && !Color::strict_match) throw Exception(typeid(*this), "Gamma Table Error", "Out of Range");\r
231                 if(r>65535 && !Color::strict_match) throw Exception(typeid(*this), "Gamma Table Error", "Out of Range");\r
232                 r = ( r<0     ? 0 : r );\r
233                 r = ( r>65535 ? 0 : r );\r
234                 return r;\r
235         }\r
236         void APICanvasProperties::setGammaValue(const double gamma_r, const double gamma_g, const double gamma_b) {\r
237                 const WORD MAX = 65535;\r
238                 if(has_instance_) {\r
239                         GAMMA_RAMP_TABLE table;\r
240                         for(int j=0; j<RAMP_STEPS_; j++) {\r
241                                 table.r[j] = (WORD)limit(MAX*pow(j/255.0, 1.0/gamma_r));\r
242                                 table.g[j] = (WORD)limit(MAX*pow(j/255.0, 1.0/gamma_g));\r
243                                 table.b[j] = (WORD)limit(MAX*pow(j/255.0, 1.0/gamma_b));\r
244                         }\r
245                         LPVOID ptr = &table;\r
246                         setGammaTable(ptr);\r
247                         calibration_mode_ = Color::GAMMA_VALUE;\r
248                 }\r
249         }\r
250         void APICanvasProperties::setGammaTable(const std::vector<double> &table_r, const std::vector<double> &table_g, const std::vector<double> &table_b) {\r
251                 const WORD MAX = 65535;\r
252                 if(has_instance_) {\r
253                         if(table_r.size()!=256 || table_g.size()!=256 || table_b.size()!=256)\r
254                                 throw Exception(typeid(*this), "Gamma Table Error", "Table size is out of order (not 256).");\r
255                         GAMMA_RAMP_TABLE table;\r
256                         for(int j=0; j<RAMP_STEPS_; j++) {\r
257                                 table.r[j] = (WORD)limit(MAX*table_r[j]);\r
258                                 table.g[j] = (WORD)limit(MAX*table_g[j]);\r
259                                 table.b[j] = (WORD)limit(MAX*table_b[j]);\r
260                         }\r
261                         LPVOID ptr = &table;\r
262                         setGammaTable(ptr);\r
263                         calibration_mode_ = Color::TABLE;\r
264                 }\r
265         }\r
266         void APICanvasProperties::setGammaTable(LPVOID table) {\r
267                 if(has_instance_) {\r
268                         saveGammaValue();\r
269                         err = SetDeviceGammaRamp(the_display_, table);\r
270                         if(err=FALSE) throw Exception(typeid(*this), "API ERROR", "Failed to set color calibration table for the video renderer.");\r
271                 }\r
272         }\r
273         void APICanvasProperties::saveGammaValue() {\r
274                 if(has_instance_) {\r
275                         if(calibration_mode_==Color::NOTHING) {\r
276                                 err = GetDeviceGammaRamp(the_display_, savedGammaRamp_ptr_);\r
277                                 if(err=FALSE) throw Exception(typeid(*this), "API ERROR", "Failed to set color calibration table for the video renderer.");\r
278                         }\r
279                 }\r
280         }\r
281         void APICanvasProperties::destroyGammaSettings() {\r
282                 if(has_instance_) {\r
283                         switch(calibration_mode_) {\r
284                                 case Color::GAMMA_VALUE:\r
285                                 case Color::TABLE:\r
286                                         setGammaTable(savedGammaRamp_ptr_);\r
287                                         break;\r
288                                 case Color::NOTHING:\r
289                                 default:\r
290                                         break;\r
291                         }\r
292                         calibration_mode_ = Color::NOTHING;\r
293                 }\r
294         }\r
295         int APICanvasProperties::getGammaMode() {\r
296                 return calibration_mode_;\r
297         }\r
298 \r
299         void APICanvasProperties::flip() {\r
300                 SwapBuffers(the_display_);\r
301         }\r
302 \r
303 \r
304 /*
305         void APICanvasProperties::uncacheLetters(Letters &letters) {
306                 if(letters.caches.count(outer)!=0) {
307                         letters.caches[outer].id->uncache(the_display_);
308                         letters.caches.erase(outer);
309                 }
310         }
311         void APICanvasProperties::cacheLetters(Letters &letters) {
312                 if(letters.caches.count(outer)!=0) { uncacheLetters(letters); }
313                 letters.caches.insert(std::pair<DrawableWithCache*, Letters::Cache>(outer, Letters::Cache(new APIFontProperties, false)));
314                 letters.caches[outer].id->cache(the_display_, letters);
315         }
316         void APICanvasProperties::drawLetters(
317                 Letters &letters, const double x, const double y,
318                 const double r, const double g, const double b, const double a,
319                 const int horiz_align, const double max_width) {
320                 if(letters.caches.count(outer)==0) {
321                         outer->cacheLetters(letters);
322                 }
323                 letters.caches[outer].id->draw(the_display_, letters, x,y,r,g,b,a,horiz_align,max_width);
324         }
325 */\r
326 \r
327         Point APICanvasProperties::left_top() {\r
328                 RECT rect;\r
329                 GetWindowRect(the_window_, &rect);\r
330                 return Point(rect.left, rect.top);\r
331         }\r
332 \r
333         void APICanvasProperties::shift(int x, int y) {\r
334         }\r
335
336
337
338         APICanvasPropertiesFullscreen::APICanvasPropertiesFullscreen(const Display &d)
339          : APICanvasProperties() {
340                 getDisplayMertix(d);
341                 generateCanvasInstance(d);
342         }
343         APICanvasPropertiesFullscreen::APICanvasPropertiesFullscreen(int d_width, int d_height, int d_colordepth, double d_refreshrate, const Display &d)
344          : APICanvasProperties() {
345                 getDisplayMertix(d);
346                 generateCanvasInstance(d_width, d_height, d_colordepth, d_refreshrate, d);
347         }
348
349
350
351         APICanvasPropertiesWindow::APICanvasPropertiesWindow(int d_width, int d_height, const Display& d)
352          : APICanvasProperties() {
353                 getDisplayMertix(d);
354                 generate(d.area.getLeft()+10, d.area.getTop()+10, d_width, d_height);
355         }
356         APICanvasPropertiesWindow::APICanvasPropertiesWindow(int d_left, int d_top, int d_width, int d_height)
357          : APICanvasProperties() {
358                 getDisplayMertix(Display::primary);
359                 generate(d_left, d_top, d_width, d_height);
360         }
361         APICanvasPropertiesWindow::~APICanvasPropertiesWindow() {
362                 ShowCursor(true);
363         }
364         void APICanvasPropertiesWindow::generate(int d_left, int d_top, int d_width, int d_height) {
365                 setWindowClass();
366                 width_ = d_width;
367                 height_ = d_height;
368
369                 the_window_ = CreateWindowEx(
370                         WS_EX_APPWINDOW | WS_EX_ACCEPTFILES,
371                         APIApplicationProperties::startupinfo.pClassName,
372                         "Psychlops Window",
373                         WS_POPUP,// | WS_CAPTION,
374                         d_left, d_top, width_, height_,
375                         HWND_DESKTOP, NULL, wcx.hInstance, NULL );
376                 if(the_window_==NULL) throw Exception(typeid(APICanvasProperties), "API ERROR", "Failed to regist main window.");
377
378                 // get the device context (DC)
379                 the_display_ = GetDC( the_window_ );
380                 // attach OpenGL context for the window
381                 attachOpenGLContext( &the_window_, &the_display_, &the_GL_context_, GetDeviceCaps(the_display_, BITSPIXEL) );
382                 //glAddSwapHintRectWIN(0, 0, width_, height_);
383
384                 has_instance_ = true;
385                 calibration_mode_ = Color::NOTHING;
386                 MSG msg;
387                 PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
388                 ShowWindow(the_window_, APIApplicationProperties::startupinfo.iCmdShow_);
389                 ShowCursor(false);
390         }
391
392
393 \r
394 ////////        TextCacheAllocation     ////////\r
395         void APICanvasProperties::draw(\r
396                 Letters &drawee, const double xx, const double yy,\r
397                 const double r, const double g, const double b, const double a,\r
398                 const int horiz_align, const int vertical_align, const double max_width)\r
399         //void APICanvasProperties::draw(Letters &drawee)\r
400         {\r
401 //MessageBoxW( NULL, drawee.str.c_str(), L"Notification", MB_OK );\r
402                 if( !text_cache.isCached(&drawee) ) cache(drawee);\r
403                 if( text_cache.isCached(&drawee) ) {\r
404                         text_cache.map[&drawee]->draw(drawee, xx, yy, r, g, b, a, horiz_align, vertical_align, max_width, *outer);\r
405                 }\r
406                 /*\r
407                 const int anchor = horiz_align, vertical_anchor = vertical_align;\r
408                 double mx = xx, my = yy;\r
409                 //double mx = drawee.getDatum().x, my = drawee.getDatum().y;\r
410                 if( !text_cache.isCached(&drawee) ) cache(drawee);\r
411                 if( text_cache.isCached(&drawee) ) {\r
412                         double x, y;\r
413                         switch(anchor) {\r
414                                 case Letters::TEXT_ALIGN_CENTER:\r
415                                         x = mx - text_cache.map[&drawee]->img.getWidth() / 2;\r
416                                         break;\r
417                                 case Letters::TEXT_ALIGN_RIGHT:\r
418                                         x = mx - text_cache.map[&drawee]->img.getWidth();\r
419                                         break;\r
420                                 case Letters::NOT_SPECIFIED:\r
421                                 case Letters::TEXT_ALIGN_LEFT:\r
422                                 default:\r
423                                         x = mx;\r
424                                         break;\r
425                         }\r
426                         switch(vertical_anchor) {\r
427                                 case Letters::TEXT_ALIGN_MIDDLE:\r
428                                         y = my;\r
429                                         text_cache.map[&drawee]->img.centering(x, y);\r
430                                         break;\r
431                                 case Letters::TEXT_ALIGN_TOP:\r
432                                         y = my;\r
433                                         text_cache.map[&drawee]->img.move_to(x, y);\r
434                                         break;\r
435                                 default:\r
436                                         y = my - drawee.font.size;\r
437                                         text_cache.map[&drawee]->img.move_to(x, y);\r
438                                         break;\r
439                         }\r
440                         text_cache.map[&drawee]->img.draw(*outer);\r
441                 }\r
442                 */\r
443         }\r
444         void APICanvasProperties::cache(Letters &drawee)\r
445         {\r
446                 Utilities::CacheOnImage *alloc;\r
447                 if( !text_cache.isCached(&drawee) ) {\r
448                         text_cache.map[&drawee] = new Utilities::CacheOnImage();\r
449                 }\r
450                 cacheText(drawee, *(text_cache.map[&drawee]));\r
451         }\r
452         void APICanvasProperties::cacheText(Letters &drawee, Utilities::CacheOnImage& t)\r
453         {\r
454                 int fontsize = (int)(drawee.font.size);\r
455                 int ix = 0, iy = 0;\r
456                 //std:: str = wtext(drawee.text).dup;\r
457 \r
458 //if(letters.font.weight==0) letters.font = Font::default_font; // patch for VC\r
459 //              FontAPI fontprop;\r
460 //              fontprop.apply(letters.font);\r
461 //              HFONT font = CreateFontIndirectW(fontprop.font_prop);\r
462 //              if(fontapi==NULL) {\r
463 //                      Font tmpfont(letters.font.size, letters.font.weight, letters.font.style, Font::default_font.family[0]);\r
464 //                      fontprop.apply(tmpfont);\r
465 //                      fontapi = CreateFontIndirectW(fontprop.font_prop);\r
466 //              }\r
467                 HFONT font = CreateFontW(\r
468                         fontsize, 0, 0, 0,\r
469                         drawee.font.weight,\r
470                         drawee.font.style==Font::normal_style ? FALSE : TRUE,\r
471                         //drawee.font.style==Font.Style.NORMAL ? FALSE : TRUE,\r
472                         FALSE, //drawee.font.decoration.underline ? TRUE : FALSE,\r
473                         FALSE, //drawee.font.decoration.line_through ? TRUE : FALSE,\r
474                         DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, OUT_DEFAULT_PRECIS, PROOF_QUALITY, FF_DONTCARE\r
475                         //, Font::default_font.family[0].c_str()\r
476                         , drawee.font.family[0].c_str()\r
477                 );\r
478                 SIZE s;\r
479 \r
480                 HDC hdc_ = the_display_;\r
481                 SelectObject(hdc_, font);\r
482                 GetTextExtentPoint32W(hdc_, drawee.str.c_str(), drawee.str.length(), &s);\r
483 \r
484                 t.img.release();\r
485                 t.img.set(s.cx, s.cy, Image::RGBA);\r
486 \r
487                 BITMAP bitmap_s;\r
488                 HBITMAP hBitmap = CreateCompatibleBitmap(hdc_, t.img.getWidth(), t.img.getHeight() );\r
489                 HDC hdcBitmap = CreateCompatibleDC(hdc_);\r
490 \r
491                 SelectObject(hdcBitmap, hBitmap);\r
492                 SelectObject(hdcBitmap, font);\r
493 \r
494                 RECT area;\r
495                 area.left = 0;\r
496                 area.right = t.img.getWidth();\r
497                 area.top = 0;\r
498                 area.bottom = t.img.getHeight();\r
499 \r
500                 Color fg_;\r
501                 //if(drawee.fill !is null)// && drawee.fill.paint !is null && drawee.fill.paint.color !is null)\r
502                 //      fg_ = drawee.fill;\r
503                 //else\r
504                         fg_ = Color(1,1,1,1);\r
505                 Color tmp = fg_;\r
506                 SetTextColor(hdcBitmap, 0xffffff);\r
507                 SetBkColor(hdcBitmap, 0);\r
508                 int err = DrawTextExW(hdcBitmap, (WCHAR*)drawee.str.c_str(), drawee.str.length(), &area, DT_LEFT | DT_EXPANDTABS, NULL);\r
509                 if(err==0) throw Exception("DrawTextExW failed.");\r
510                 for(int y=0; y<t.img.getHeight(); y++) {\r
511                         for(int x=0; x<t.img.getWidth(); x++) {\r
512                                 COLORREF c = GetPixel(hdcBitmap, x, y);\r
513 //                              if(c!=0) { tmp.set( fg_.getR(), fg_.getG(), fg_.getB(),   ((c&0xff0000)>>16)/255.0 ); } else tmp=Color::null_color;\r
514                                 if(c!=0) { tmp.set( 0,0,0, ((c&0xff0000)>>16)/255.0 ); } else tmp=Color::null_color;\r
515 //                              t.img.pix_raw(x, t.img.getHeight()-y-1, tmp);\r
516                                 t.img.pix_raw(x, y, tmp);\r
517                         }\r
518                 }\r
519                 t.img.cache(*outer);\r
520                 DeleteObject(hdcBitmap);\r
521                 DeleteObject(hBitmap);\r
522                 DeleteObject(font);\r
523         }\r
524 \r
525         void APICanvasProperties::uncache(Letters &drawee)\r
526         {\r
527                 if( text_cache.isCached(&drawee) ) {\r
528                         text_cache.map[&drawee]->uncache();\r
529                 }\r
530         }\r
531         void APICanvasProperties::uncacheAllLetters()\r
532         {\r
533                 text_cache.uncacheAll();\r
534         }\r
535 \r
536
537 ////////        APIFontProperties       ////////
538
539 const std::wstring default_facename(L"MS UI Gothic");
540 struct FontAPI {
541         LOGFONTW storage;
542         LOGFONTW* font_prop;
543         FontAPI() {
544                 font_prop = &storage;
545                 font_prop->lfHeight      = 12;
546                 font_prop->lfWidth       = 0;
547                 font_prop->lfEscapement  = 0;
548                 font_prop->lfOrientation = 0;
549                 font_prop->lfWeight      = FW_NORMAL;
550                 font_prop->lfItalic      = FALSE;
551                 font_prop->lfUnderline   = FALSE;
552                 font_prop->lfStrikeOut   = FALSE;
553                 font_prop->lfCharSet     = DEFAULT_CHARSET;
554                 font_prop->lfOutPrecision   = OUT_DEFAULT_PRECIS;
555                 font_prop->lfClipPrecision  = CLIP_DEFAULT_PRECIS;
556                 font_prop->lfQuality        = ANTIALIASED_QUALITY;//CLEARTYPE_COMPAT_QUALITY;
557                 font_prop->lfPitchAndFamily = FF_DONTCARE|DEFAULT_PITCH;
558                 applyFacename(default_facename);
559         }
560
561         void apply(const Font &font) {
562                 font_prop->lfHeight      = (LONG)Math::round(font.size);
563                 font_prop->lfWeight      = (font.weight==0 ? FW_NORMAL : (LONG)Math::round(font.weight));
564                 font_prop->lfItalic      = font.style;
565                 applyFacename(font.family.size()>0 ? font.family[0] : default_facename);
566         }
567         void applyFacename(const std::wstring &facename) {
568                 for(unsigned int i=0; i<LF_FACESIZE; i++) {
569                         if(i<facename.length()) font_prop->lfFaceName[i] = facename[i];
570                         else font_prop->lfFaceName[i] = L'\0';
571                 }
572         }
573
574 };
575
576         APIFontProperties::APIFontProperties() : cached(false), cache_id(0), length(0), lists(0) {
577         }
578         APIFontProperties::~APIFontProperties() {
579                 uncache();
580         }
581         void APIFontProperties::uncache() {
582                 if(cached) {
583                         glDeleteLists(cache_id, length);
584                         if(length>100) delete [] lists;
585                         cache_id = 0;
586                         length = 0;
587                         lists = 0;
588                         cached = false;
589                 }
590         }
591         void APIFontProperties::uncache(const HDC &ctx) {
592                 if(cached) {
593                         glDeleteLists(cache_id, length);
594                         if(length>100) delete [] lists;
595                         cache_id = 0;
596                         length = 0;
597                         lists = 0;
598                         cached = false;
599                 }
600         }
601         void APIFontProperties::cache(const HDC &ctx, Letters &letters) {
602                 if(cached) {\r
603                 } else {
604 if(letters.font.weight==0) letters.font = Font::default_font; // patch for VC
605                         FontAPI fontprop;
606                         fontprop.apply(letters.font);
607                         HFONT fontapi = CreateFontIndirectW(fontprop.font_prop);
608                         if(fontapi==NULL) {
609                                 Font tmpfont(letters.font.size, letters.font.weight, letters.font.style, Font::default_font.family[0]);
610                                 fontprop.apply(tmpfont);
611                                 fontapi = CreateFontIndirectW(fontprop.font_prop);
612                         }
613                         SelectObject(ctx, fontapi);
614                         const unsigned int result = glGenLists(letters.str.length());
615                         int error;\r
616                         GLYPHMETRICSFLOAT metrix;
617                         double width=0.0, height=0.0;\r
618
619                         for(int i=0; i<letters.str.length(); i++) {
620                                 // outline
621                                         error = wglUseFontOutlinesW( ctx, letters.str.at(i), 1, result+i, 0.0, 0.0, WGL_FONT_POLYGONS, &metrix);\r
622                                         width += (metrix.gmfCellIncX!=0) ? metrix.gmfCellIncX : metrix.gmfBlackBoxY;\r
623                                         height = (height>metrix.gmfBlackBoxY) ? height : metrix.gmfBlackBoxY;
624                                 // bitmap
625                                         //error = wglUseFontBitmapsW( the_display_, letters.str.at(i), 1, result+i );\r
626                                         //width += (metrix.gmfCellIncX!=0) ? metrix.gmfCellIncX : metrix.gmfBlackBoxY;\r
627                                         //height = (height>metrix.gmfBlackBoxY) ? height : metrix.gmfBlackBoxY;\r
628                                 // image\r
629                                         ////HBITMAP CreateDIBitmap(HDC hdc, CONST BITMAPINFOHEADER *lpbmih, DWORD fdwInit, CONST VOID *lpbInit, CONST BITMAPINFO *lpbmi, UINT fuUsage);\r
630 \r
631                                         //HDC memDC = CreateCompatibleDC(hdc);\r
632                                         //HBITMAP memBM = CreateCompatibleBitmap(HDC hdc,int nWidth,int nHeight);\r
633 \r
634 \r
635                                         ////hdc = BeginPaint(hwnd , &ps);\r
636                                         //SelectObject(hBuffer , hBitmap);\r
637                                         //int DrawText(HDC hDC, LPCTSTR lpString, int nCount, LPRECT lpRect, DT_CALCRECT);\r
638 \r
639                                         //COLORREF GetPixel(memDC, x, y);\r
640                                         //if(DeleteObject(memBM)) ;\r
641                                         //if(DeleteObject(memDC)) ;\r
642
643                                 if(error!=TRUE) {
644         //                              putErrorMessage;
645                                         throw Exception("Failed to load font.");
646                                 }
647                         }
648
649                         cache_id = result;
650                         length = letters.str.length();\r
651                         base_width = width;\r
652                         base_height = height;\r
653                         culcVirtualMetrix(letters);
654
655                         if(length>100) {
656                                 lists = new GLushort[length];
657                                 for(int i=0; i<length; i++) lists[i] = i;
658                         } else {
659                                 lists = const_cast<GLushort*>(lists100);
660                         }
661 \r
662                         cached = true;
663                 }
664         }\r
665         void APIFontProperties::culcVirtualMetrix(Letters &letters) {\r
666                 letters.width_ = base_width * letters.font.size;\r
667                 letters.height_ = base_height * letters.font.size;\r
668         }
669         void APIFontProperties::draw(const HDC &ctx,
670                         const Letters &letters, const double x, const double y,
671                         const double r, const double g, const double b, const double a,
672                         const int horiz_align, const double max_width) const {
673
674                 if(!cached) { throw Exception("Please ask to developpers to implement drawing uncached Letters."); }
675                 glPushMatrix();
676                 glPushAttrib(GL_ALL_ATTRIB_BITS);
677                 glColor4f(r, g, b, a);
678
679                 //      bitmap edition
680 //              glRasterPos2d(x,y);
681
682                 //      outline eddition
683 /*              glDisable(GL_DEPTH_TEST);\r
684                 glDisable(GL_ALPHA_TEST);
685                 glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
686                 glEnable(GL_LINE_SMOOTH);
687                 glHint(GL_LINE_SMOOTH_HINT,GL_NICEST);
688                 glEnable(GL_POLYGON_SMOOTH);
689                 glHint(GL_POLYGON_SMOOTH_HINT,GL_NICEST);
690                 glEnable(GL_BLEND);
691                 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
692 */\r
693 \r
694                 glTranslated(x,y,0.0);
695                 glScaled(letters.font.size, - letters.font.size, 1.0);
696
697                 glListBase(cache_id);
698                 glCallLists(length, GL_UNSIGNED_SHORT, lists);
699                 glListBase(0);
700
701                 glPopAttrib();
702                 glPopMatrix();
703         }
704 \r
705 const GLushort APIFontProperties::lists100[100] =
706                         { 0, 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
707                         ,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};
708
709
710 ////////        APIImageProperties      ////////\r
711 \r
712         APIImageProperties::APIImageProperties() : outer_(NULL) {
713 //              for(int i=0; i<max_reg; i++) { rights_[i]=-1; bottoms_[i]=0; }
714 //              rights_[0]=-1; bottoms_[0]=-1;
715         }
716         APIImageProperties::APIImageProperties(Image *outer) : outer_(outer) {
717                 attach();
718         }
719         APIImageProperties::~APIImageProperties() {
720                 detach();
721         }
722 \r
723         void APIImageProperties::attach() {}\r
724         void APIImageProperties::detach() {}\r
725 \r
726
727         APIImageCache::APIImageCache() : VRAMoffset(0), tex_width(0), tex_height(0) {}\r
728         unsigned int APIImageCache::getTexIndex() {\r
729                 return VRAMoffset;\r
730         }\r
731 /*\r
732         bool APIImageProperties::regist(int maxwidth, int maxheight, int width, int height, int &left, int &top) {\r
733                 for(int i=1; i<max_reg; i++) {\r
734                         if( (rights_[i]+width <= maxwidth && (bottoms_[i-1]+height<=bottoms_[i]) || (bottoms_[i-1]+height <= maxheight && bottoms_[i+1]==0) ) ) {\r
735                                 left = rights_[i]+1;\r
736                                 top = bottoms_[i-1]+1;\r
737                                 rights_[i] = left+width-1;\r
738                                 bottoms_[i] =  (bottoms_[i-1]+height<bottoms_[i]) ? bottoms_[i] : bottoms_[i-1]+height;\r
739                                 return true;\r
740                         }\r
741                 }\r
742                 throw Exception(typeid(APIImageProperties), "Memory Error", "Image accelerater failed to allocate VRAM.");\r
743         }\r
744 */\r
745 \r
746 \r
747 \r
748 }       /*      <- namespace Psychlops  */\r
749 \r