2 * psychlops_g_canvas_API_WIN32.cpp
3 * Psychlops Standard Library (MacOSX)
5 * Last Modified 2009/05/12 by Kenchi HOSOKAWA
6 * (C) 2005-2009 Kenchi HOSOKAWA, Kazushi MARUYA, Takao SATO
12 #include <windows.h>
\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
29 namespace Psychlops {
\r
32 WNDCLASSEX APICanvasProperties::wcx;
33 bool APICanvasProperties::wcx_setted = false;
34 void APICanvasProperties::setWindowClass() {
36 wcx.cbSize = sizeof(WNDCLASSEX);
37 wcx.style = CS_GLOBALCLASS;
38 wcx.lpfnWndProc = (WNDPROC)&(APIApplicationProperties::proc);
41 wcx.hInstance = APIApplicationProperties::startupinfo.hInstance_;
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.");
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
57 the_display_ = GetDC(0);
\r
59 APICanvasProperties::~APICanvasProperties() {
61 destroyCanvasInstance();
\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();
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
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
98 void APICanvasProperties::generateCanvasInstance(DEVMODE &d_mode, const Display& d) {
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
111 the_window_ = CreateWindowEx(
\r
112 WS_EX_APPWINDOW | WS_EX_TOPMOST,
\r
113 APIApplicationProperties::startupinfo.pClassName,
\r
114 "Psychlops Window",
\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
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
126 has_instance_ = true;
\r
127 calibration_mode_ = Color::NOTHING;
\r
130 PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
\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
140 void APICanvasProperties::attachOpenGLContext(HWND *hWnd, HDC * hDC, HGLRC * hRC, int d_colordepth) {
\r
143 // get the device context (DC)
\r
144 *hDC = GetDC( *hWnd );
\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
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
168 0, 0, 0 // layer masks ignored
\r
170 PIXELFORMATDESCRIPTOR pfd;
\r
171 ZeroMemory( &pfd, sizeof( pfd ) );
\r
172 pfd.nSize = sizeof( pfd );
\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
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
193 //PROC vsync = wglGetProcAddress("wglSwapInterval");
\r
194 //if(vsync!=NULL) {
\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;
204 //throw Exception("API function[wglSwapIntervalEXT] failed to enforce buffer swap to synchronize to vsync.");
205 vsync_available_ = false;
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
220 has_instance_ = false;
\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
228 double APICanvasProperties::limit(double 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
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
245 LPVOID ptr = &table;
\r
246 setGammaTable(ptr);
\r
247 calibration_mode_ = Color::GAMMA_VALUE;
\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
261 LPVOID ptr = &table;
\r
262 setGammaTable(ptr);
\r
263 calibration_mode_ = Color::TABLE;
\r
266 void APICanvasProperties::setGammaTable(LPVOID table) {
\r
267 if(has_instance_) {
\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
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
281 void APICanvasProperties::destroyGammaSettings() {
\r
282 if(has_instance_) {
\r
283 switch(calibration_mode_) {
\r
284 case Color::GAMMA_VALUE:
\r
286 setGammaTable(savedGammaRamp_ptr_);
\r
288 case Color::NOTHING:
\r
292 calibration_mode_ = Color::NOTHING;
\r
295 int APICanvasProperties::getGammaMode() {
\r
296 return calibration_mode_;
\r
299 void APICanvasProperties::flip() {
\r
300 SwapBuffers(the_display_);
\r
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);
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);
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);
323 letters.caches[outer].id->draw(the_display_, letters, x,y,r,g,b,a,horiz_align,max_width);
327 Point APICanvasProperties::left_top() {
\r
329 GetWindowRect(the_window_, &rect);
\r
330 return Point(rect.left, rect.top);
\r
333 void APICanvasProperties::shift(int x, int y) {
\r
338 APICanvasPropertiesFullscreen::APICanvasPropertiesFullscreen(const Display &d)
339 : APICanvasProperties() {
341 generateCanvasInstance(d);
343 APICanvasPropertiesFullscreen::APICanvasPropertiesFullscreen(int d_width, int d_height, int d_colordepth, double d_refreshrate, const Display &d)
344 : APICanvasProperties() {
346 generateCanvasInstance(d_width, d_height, d_colordepth, d_refreshrate, d);
351 APICanvasPropertiesWindow::APICanvasPropertiesWindow(int d_width, int d_height, const Display& d)
352 : APICanvasProperties() {
354 generate(d.area.getLeft()+10, d.area.getTop()+10, d_width, d_height);
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);
361 APICanvasPropertiesWindow::~APICanvasPropertiesWindow() {
364 void APICanvasPropertiesWindow::generate(int d_left, int d_top, int d_width, int d_height) {
369 the_window_ = CreateWindowEx(
370 WS_EX_APPWINDOW | WS_EX_ACCEPTFILES,
371 APIApplicationProperties::startupinfo.pClassName,
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.");
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_);
384 has_instance_ = true;
385 calibration_mode_ = Color::NOTHING;
387 PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
388 ShowWindow(the_window_, APIApplicationProperties::startupinfo.iCmdShow_);
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
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
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
414 case Letters::TEXT_ALIGN_CENTER:
\r
415 x = mx - text_cache.map[&drawee]->img.getWidth() / 2;
\r
417 case Letters::TEXT_ALIGN_RIGHT:
\r
418 x = mx - text_cache.map[&drawee]->img.getWidth();
\r
420 case Letters::NOT_SPECIFIED:
\r
421 case Letters::TEXT_ALIGN_LEFT:
\r
426 switch(vertical_anchor) {
\r
427 case Letters::TEXT_ALIGN_MIDDLE:
\r
429 text_cache.map[&drawee]->img.centering(x, y);
\r
431 case Letters::TEXT_ALIGN_TOP:
\r
433 text_cache.map[&drawee]->img.move_to(x, y);
\r
436 y = my - drawee.font.size;
\r
437 text_cache.map[&drawee]->img.move_to(x, y);
\r
440 text_cache.map[&drawee]->img.draw(*outer);
\r
444 void APICanvasProperties::cache(Letters &drawee)
\r
446 Utilities::CacheOnImage *alloc;
\r
447 if( !text_cache.isCached(&drawee) ) {
\r
448 text_cache.map[&drawee] = new Utilities::CacheOnImage();
\r
450 cacheText(drawee, *(text_cache.map[&drawee]));
\r
452 void APICanvasProperties::cacheText(Letters &drawee, Utilities::CacheOnImage& t)
\r
454 int fontsize = (int)(drawee.font.size);
\r
455 int ix = 0, iy = 0;
\r
456 //std:: str = wtext(drawee.text).dup;
\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
467 HFONT font = CreateFontW(
\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
480 HDC hdc_ = the_display_;
\r
481 SelectObject(hdc_, font);
\r
482 GetTextExtentPoint32W(hdc_, drawee.str.c_str(), drawee.str.length(), &s);
\r
485 t.img.set(s.cx, s.cy, Image::RGBA);
\r
488 HBITMAP hBitmap = CreateCompatibleBitmap(hdc_, t.img.getWidth(), t.img.getHeight() );
\r
489 HDC hdcBitmap = CreateCompatibleDC(hdc_);
\r
491 SelectObject(hdcBitmap, hBitmap);
\r
492 SelectObject(hdcBitmap, font);
\r
496 area.right = t.img.getWidth();
\r
498 area.bottom = t.img.getHeight();
\r
501 //if(drawee.fill !is null)// && drawee.fill.paint !is null && drawee.fill.paint.color !is null)
\r
502 // fg_ = drawee.fill;
\r
504 fg_ = Color(1,1,1,1);
\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
519 t.img.cache(*outer);
\r
520 DeleteObject(hdcBitmap);
\r
521 DeleteObject(hBitmap);
\r
522 DeleteObject(font);
\r
525 void APICanvasProperties::uncache(Letters &drawee)
\r
527 if( text_cache.isCached(&drawee) ) {
\r
528 text_cache.map[&drawee]->uncache();
\r
531 void APICanvasProperties::uncacheAllLetters()
\r
533 text_cache.uncacheAll();
\r
537 //////// APIFontProperties ////////
539 const std::wstring default_facename(L"MS UI Gothic");
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);
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);
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';
576 APIFontProperties::APIFontProperties() : cached(false), cache_id(0), length(0), lists(0) {
578 APIFontProperties::~APIFontProperties() {
581 void APIFontProperties::uncache() {
583 glDeleteLists(cache_id, length);
584 if(length>100) delete [] lists;
591 void APIFontProperties::uncache(const HDC &ctx) {
593 glDeleteLists(cache_id, length);
594 if(length>100) delete [] lists;
601 void APIFontProperties::cache(const HDC &ctx, Letters &letters) {
604 if(letters.font.weight==0) letters.font = Font::default_font; // patch for VC
606 fontprop.apply(letters.font);
607 HFONT fontapi = CreateFontIndirectW(fontprop.font_prop);
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);
613 SelectObject(ctx, fontapi);
614 const unsigned int result = glGenLists(letters.str.length());
616 GLYPHMETRICSFLOAT metrix;
617 double width=0.0, height=0.0;
\r
619 for(int i=0; i<letters.str.length(); i++) {
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;
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
629 ////HBITMAP CreateDIBitmap(HDC hdc, CONST BITMAPINFOHEADER *lpbmih, DWORD fdwInit, CONST VOID *lpbInit, CONST BITMAPINFO *lpbmi, UINT fuUsage);
\r
631 //HDC memDC = CreateCompatibleDC(hdc);
\r
632 //HBITMAP memBM = CreateCompatibleBitmap(HDC hdc,int nWidth,int nHeight);
\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
639 //COLORREF GetPixel(memDC, x, y);
\r
640 //if(DeleteObject(memBM)) ;
\r
641 //if(DeleteObject(memDC)) ;
\r
645 throw Exception("Failed to load font.");
650 length = letters.str.length();
\r
651 base_width = width;
\r
652 base_height = height;
\r
653 culcVirtualMetrix(letters);
656 lists = new GLushort[length];
657 for(int i=0; i<length; i++) lists[i] = i;
659 lists = const_cast<GLushort*>(lists100);
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
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 {
674 if(!cached) { throw Exception("Please ask to developpers to implement drawing uncached Letters."); }
676 glPushAttrib(GL_ALL_ATTRIB_BITS);
677 glColor4f(r, g, b, a);
680 // glRasterPos2d(x,y);
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);
691 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
694 glTranslated(x,y,0.0);
695 glScaled(letters.font.size, - letters.font.size, 1.0);
697 glListBase(cache_id);
698 glCallLists(length, GL_UNSIGNED_SHORT, lists);
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};
710 //////// APIImageProperties ////////
\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;
716 APIImageProperties::APIImageProperties(Image *outer) : outer_(outer) {
719 APIImageProperties::~APIImageProperties() {
723 void APIImageProperties::attach() {}
\r
724 void APIImageProperties::detach() {}
\r
727 APIImageCache::APIImageCache() : VRAMoffset(0), tex_width(0), tex_height(0) {}
\r
728 unsigned int APIImageCache::getTexIndex() {
\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
742 throw Exception(typeid(APIImageProperties), "Memory Error", "Image accelerater failed to allocate VRAM.");
\r
748 } /* <- namespace Psychlops */
\r