2 * psychlops_g_canvas_Win32_GL.cpp
3 * Psychlops Standard Library (Universal)
5 * Last Modified 2007/07/07 by Kenchi HOSOKAWA
6 * (C) 2006 Kenchi HOSOKAWA, Kazushi MARUYA and Takao SATO
14 #include "psychlops_g_GL_h.h"
16 #include "../../core/ApplicationInterfaces/psychlops_app_info.h"
17 #include "../../core/ApplicationInterfaces/psychlops_app_thread.h"
18 #include "../../core/devices/psychlops_io_hid.h"
19 #include "../../core/math/psychlops_math.h"
20 #include "../../core/graphic/psychlops_g_fundamental.h"
21 #include "../../core/graphic/psychlops_g_color.h"
22 #include "../../core/graphic/psychlops_g_module.h"
23 #include "../../core/graphic/psychlops_g_shape.h"
24 #include "../../core/graphic/psychlops_g_canvas.h"
25 #include "../../core/graphic/psychlops_g_image.h"
27 #define PSYCHLOPS_WINDOW_API_PLATFORM
28 #include "../../platform/psychlops_platform_selector.h"
36 GLuint fillOvalPrimitives[4], drawOvalPrimitives[4];
37 int Canvas::font_LCD_height;
40 //////// Construct and Destruct ////////
41 class DirectGetColor {
43 inline static unsigned char round8bit(double value) {
44 double val = value*255.0+0.5, integer_part, frac;
45 frac = modf(val, &integer_part);
46 if(frac!=0.0) return (unsigned char)integer_part;
47 if((int)(integer_part)%2==0) return (unsigned char)integer_part; else return (unsigned char)integer_part-1;
49 static void setColor4ub(const Color &color) {
50 glColor4ub(round8bit(color.Red), round8bit(color.Green), round8bit(color.Blue), round8bit(color.Alpha));
52 static void setColorClear4ub(const Color &color) {
53 glClearColor((GLclampf)round8bit(color.Red)/255.0, (GLclampf)round8bit(color.Green)/255.0, (GLclampf)round8bit(color.Blue)/255.0, (GLclampf)round8bit(color.Alpha)/255.0);
55 static void setColor4Through(const Color &color) {
56 glColor4d(color.Red, color.Green, color.Blue, color.Alpha);
58 static void setColorClaer4Through(const Color &color) {
59 glClearColor(color.Red, color.Green, color.Blue, color.Alpha);
63 void Canvas::popMatrices() {
64 glMatrixMode(GL_MODELVIEW);
66 glMatrixMode(GL_PROJECTION);
69 void Canvas::pushPixToPixProjection() {
70 glMatrixMode(GL_PROJECTION);
73 glOrtho(-0.375, Width-0.375, Height-0.375, -0.375, -1000, 1000);
74 glMatrixMode(GL_MODELVIEW);
77 glDisable(GL_LIGHTING);
78 glDisable(GL_DEPTH_TEST);
80 void Canvas::RenderModeSmooth2D() {
81 glShadeModel(GL_SMOOTH);
82 glEnable(GL_POINT_SMOOTH);
83 glEnable(GL_LINE_SMOOTH);
84 // glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
85 // glEnable(GL_POLYGON_SMOOTH_HINT);
86 // glEnable(GL_POLYGON_SMOOTH);
88 void Canvas::RenderModeSmooth3D(double left, double right, double top, double bottom, double near, double far) {
89 glMatrixMode(GL_PROJECTION);
92 //gluPerspective(left, top, near, far);
93 //glFrustum(left, right, top, bottom, near, far);
94 glRotated(180, 0, 1, 0);
96 glMatrixMode(GL_MODELVIEW);
100 //glShadeModel(GL_SMOOTH);
101 //glEnable(GL_POINT_SMOOTH);
102 //glEnable(GL_LINE_SMOOTH);
103 // glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
104 // glEnable(GL_POLYGON_SMOOTH_HINT);
105 // glEnable(GL_POLYGON_SMOOTH);
106 glEnable(GL_DEPTH_TEST);
108 // glEnable(GL_LIGHTING);
109 glDisable(GL_LIGHTING);
112 void Canvas::initAPIprop() {
116 APIsetColor = &(DirectGetColor::setColor4ub);
117 APIsetColorClear = &(DirectGetColor::setColorClear4ub);
120 APIsetColor = &(DirectGetColor::setColor4Through);
121 APIsetColorClear = &(DirectGetColor::setColorClaer4Through);
125 glDrawBuffer(GL_BACK);
126 glReadBuffer(GL_BACK);
127 //glMatrixMode(GL_PROJECTION);
129 // glOrtho(0, Width, Height, 0, -1, 1);
130 //glOrtho(-0.375, Width-0.375, Height-0.375, 0-0.375, -1, 1);
131 //glMatrixMode(GL_MODELVIEW);
133 // glTranslated(0.375, 0.375, 0.0);
136 pushPixToPixProjection();
139 GLclampf red=0.0, green=0.0, blue=0.0, alpha=1.0;
140 // default_drawing_mode_ = GL_POINTS;
141 glClearColor(red,green,blue,alpha);
148 void Canvas::initAPIattributes() {
149 glPushAttrib(GL_ALL_ATTRIB_BITS);
151 //// default settings ////
152 glShadeModel(GL_FLAT);
153 glEnable(GL_ALPHA_TEST);
155 glEnable(GL_LINE_STIPPLE);
156 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
157 glDisable(GL_POINT_SMOOTH);
158 glDisable(GL_LINE_SMOOTH);
159 glDisable(GL_POLYGON_SMOOTH);
160 glDisable(GL_DEPTH_TEST);
161 glDisable(GL_DITHER);
163 glDisable(GL_LIGHTING);
164 glDisable(GL_LOGIC_OP);
165 glDisable(GL_STENCIL_TEST);
166 glDisable(GL_TEXTURE_1D);
167 glDisable(GL_TEXTURE_2D);
168 glPixelTransferi(GL_MAP_COLOR, GL_FALSE);
169 glPixelTransferi(GL_MAP_STENCIL, GL_FALSE);
170 glPixelTransferi(GL_RED_SCALE, 1);
171 glPixelTransferi(GL_RED_BIAS, 0);
172 glPixelTransferi(GL_GREEN_SCALE, 1);
173 glPixelTransferi(GL_GREEN_BIAS, 0);
174 glPixelTransferi(GL_BLUE_SCALE, 1);
175 glPixelTransferi(GL_BLUE_BIAS, 0);
176 glPixelTransferi(GL_ALPHA_SCALE, 1);
177 glPixelTransferi(GL_ALPHA_BIAS, 0);
178 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
179 glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
180 glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
181 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
182 glPixelStoref(GL_UNPACK_ALIGNMENT, 4);
183 glPixelStorei(GL_PACK_ALIGNMENT, 4);
184 glPixelStoref(GL_PACK_ALIGNMENT, 4);
185 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
187 void Canvas::popAPIattributes() {
194 //// Prepare Primitives
200 //////// Drawing Graphical Elements ////////
201 inline void Canvas::setStrokeState(const Stroke& strk) {
202 APIsetColor(strk.color);
203 glLineWidth(strk.width);
204 glLineStipple((int)Math::round(strk.width), strk.pattern);
208 Drawable& Canvas::pix(double x, double y, const Color &col) {
215 Canvas& Canvas::pix(const Point &po, const Color &col) {
216 pix(po.x, po.y, col);
219 void Canvas::pix(int dotsCnt, double x[], double y[], const Color col[]) {
221 for(int i=0; i<dotsCnt; i++) {
223 glVertex2d(x[i], y[i]);
227 void Canvas::pix(int dotsCnt, double x[], double y[], const Color &col=Color::white) {
230 for(int i=0; i<dotsCnt; i++) {
231 glVertex2d(x[i], y[i]);
235 void Canvas::pix(int dotsCnt, const Point po[], const Color col[]) {
237 for(int i=0; i<dotsCnt; i++) {
239 glVertex3d(po[i].x, po[i].y, po[i].z);
243 void Canvas::line(double x1, double y1, double x2, double y2, const Color &col) {
250 void Canvas::line(const Point &po1, const Point &po2, const Color &col) {
251 line(po1.x, po1.y, po2.x, po2.y, col);
253 void Canvas::line(double x1, double y1, double x2, double y2, const Stroke &strk) {
254 glPushAttrib(GL_ALL_ATTRIB_BITS);
255 setStrokeState(strk);
262 void Canvas::line(const Point &po1, const Point &po2, const Stroke &strk) {
263 line(po1.x, po1.y, po2.x, po2.y, strk);
265 Canvas& Canvas::line(const Line &drawee, const Color &col) {
266 line(drawee.datum.x, drawee.datum.y, drawee.end.x, drawee.end.y, col);
269 Canvas& Canvas::line(const Line &drawee, const Stroke &strk) {
270 line(drawee.datum.x, drawee.datum.y, drawee.end.x, drawee.end.y, strk);
273 Canvas& Canvas::rect(const Rectangle &rec, const Color &col) {
274 if(APIsetColor!=0) APIsetColor(col);
275 // DirectGetColor::setColor4ub(col);
276 glRectd(rec.left, rec.top, rec.right+1, rec.bottom+1);
279 Canvas& Canvas::rect(const int nRects, const Rectangle *rec, const Color &col) {
281 for(unsigned int i=0; i<nRects; i++) {
282 glRectd(rec[i].left, rec[i].top, rec[i].right+1, rec[i].bottom+1);
286 Canvas& Canvas::rect(const int nRects, const Rectangle *rec, const Color *col) {
287 for(unsigned int i=0; i<nRects; i++) rect(rec[i], col[i]);
290 Canvas& Canvas::rect(const unsigned int nRectsBegin, const unsigned int nRectsEnd, const Rectangle *rec, const Color *col) {
291 for(unsigned int i=nRectsBegin; i<nRectsEnd; i++) rect(rec[i], col[i]);
294 Canvas& Canvas::rect(const Rectangle &rec, const Stroke &strk) {
295 glPushAttrib(GL_ALL_ATTRIB_BITS);
296 setStrokeState(strk);
297 glBegin(GL_LINE_LOOP);
298 glVertex2d(rec.left, rec.top);
299 glVertex2d(rec.right, rec.top);
300 glVertex2d(rec.right, rec.bottom);
301 glVertex2d(rec.left, rec.bottom);
306 Canvas& Canvas::rect(const int nRects, const Rectangle *rec, const Stroke &strk) {
307 glPushAttrib(GL_ALL_ATTRIB_BITS);
308 setStrokeState(strk);
309 for(int i=0; i<nRects; i++) {
310 glBegin(GL_LINE_LOOP);
311 glVertex2d(rec[i].left, rec[i].top);
312 glVertex2d(rec[i].right, rec[i].top);
313 glVertex2d(rec[i].right, rec[i].bottom);
314 glVertex2d(rec[i].left, rec[i].bottom);
320 Canvas& Canvas::rect(const int nRects, const Rectangle *rec, const Stroke *strk) {
321 for(int i=0; i<nRects; i++) rect(rec[i], strk[i]);
324 Canvas& Canvas::rect(const unsigned int nRectsBegin, const unsigned int nRectsEnd, const Rectangle *rec, const Stroke *strk) {
325 for(unsigned int i=nRectsBegin; i<nRectsEnd; i++) rect(rec[i], strk[i]);
328 Canvas& Canvas::ellipse(const Ellipse &ell) {
\r
329 ellipse(ell, ell.fill);
\r
330 ellipse(ell, ell.stroke);
\r
333 Canvas& Canvas::ellipse(const Ellipse &ovl, const Color &col) {
\r
334 const double wi = ovl.radius;
336 glPushAttrib(GL_ALL_ATTRIB_BITS);
338 glTranslatef(ovl.datum.x-ovl.radius/2, ovl.datum.y-ovl.v_radius/2, 0);
339 glScalef(wi, ovl.v_radius+1, 1.0);
341 glCallList(fillOvalPrimitives[0]);
343 glCallList(fillOvalPrimitives[1]);
345 glCallList(fillOvalPrimitives[2]);
347 glCallList(fillOvalPrimitives[3]);
353 Canvas& Canvas::ellipse(const Ellipse &ovl, const Stroke &strk) {
354 const double wi = ovl.radius;
356 glPushAttrib(GL_ALL_ATTRIB_BITS);
357 setStrokeState(strk);
358 glTranslatef(ovl.datum.x-ovl.radius/2, ovl.datum.y-ovl.v_radius/2, 0);
359 glScalef(wi, ovl.v_radius+1, 1.0);
361 glCallList(drawOvalPrimitives[0]);
363 glCallList(drawOvalPrimitives[1]);
365 glCallList(drawOvalPrimitives[2]);
367 glCallList(drawOvalPrimitives[3]);
373 Canvas& Canvas::ellipse(const Rectangle &rect, const Color &col) {
374 const double wi = rect.getWidth();
376 glPushAttrib(GL_ALL_ATTRIB_BITS);
378 glTranslatef(rect.left, rect.top, 0);
379 glScalef(wi, rect.getHeight()+1, 1.0);
381 glCallList(fillOvalPrimitives[0]);
383 glCallList(fillOvalPrimitives[1]);
385 glCallList(fillOvalPrimitives[2]);
387 glCallList(fillOvalPrimitives[3]);
393 Canvas& Canvas::ellipse(const Rectangle &rect, const Stroke &strk) {
394 const double wi = rect.getWidth();
396 glPushAttrib(GL_ALL_ATTRIB_BITS);
397 setStrokeState(strk);
398 glTranslatef(rect.left, rect.top, 0);
399 glScalef(wi, rect.getHeight()+1, 1.0);
401 glCallList(drawOvalPrimitives[0]);
403 glCallList(drawOvalPrimitives[1]);
405 glCallList(drawOvalPrimitives[2]);
407 glCallList(drawOvalPrimitives[3]);
413 void Canvas::polygon(Point *vertices, unsigned int nVertices, const Color &col) {
416 for(unsigned int i=0; i<nVertices; i++) {
417 glVertex2d(vertices[i].x, vertices[i].y);
421 void Canvas::polygon(Point *vertices, unsigned int nVertices, const Stroke &strk) {
422 glPushAttrib(GL_ALL_ATTRIB_BITS);
423 setStrokeState(strk);
424 glBegin(GL_LINE_LOOP);
425 for(unsigned int i=0; i<nVertices; i++) {
426 glVertex2d(vertices[i].x, vertices[i].y);
431 Canvas& Canvas::polygon(const Polygon &drawee) {
432 if(drawee.vertices.empty()) return *this;
434 const Point datum = drawee.getDatum();
435 glTranslatef(datum.x, datum.y, datum.z);
437 for(std::deque<Point>::const_iterator v=drawee.vertices.begin(); v!=drawee.vertices.end(); v++) {
438 glVertex3d((*v).x, (*v).y, (*v).z);
444 Canvas& Canvas::polygon(const Polygon &drawee, const Color &col) {
445 if(drawee.vertices.empty()) return *this;
448 const Point datum = drawee.getDatum();
449 glTranslatef(datum.x, datum.y, datum.z);
451 for(std::deque<Point>::const_iterator v=drawee.vertices.begin(); v!=drawee.vertices.end(); v++) {
452 glVertex3d((*v).x, (*v).y, (*v).z);
458 Canvas& Canvas::polygon(const Polygon &drawee, const Stroke &strk) {
459 if(drawee.vertices.empty()) return *this;
460 glPushAttrib(GL_ALL_ATTRIB_BITS);
461 setStrokeState(strk);
463 const Point datum = drawee.getDatum();
464 glTranslatef(datum.x, datum.y, datum.z);
465 glBegin(GL_LINE_LOOP);
466 for(std::deque<Point>::const_iterator v=drawee.vertices.begin(); v!=drawee.vertices.end(); v++) {
467 glVertex3d((*v).x, (*v).y, (*v).z);
474 Canvas& Canvas::polyline(const PolyLine &drawee) {
475 polyline(drawee, drawee.stroke);
478 Canvas& Canvas::polyline(const PolyLine &drawee, const Color &col) {
479 Stroke strk(col, 1, Stroke::SOLID);
480 polyline(drawee, strk);
483 Canvas& Canvas::polyline(const PolyLine &drawee, const Stroke &strk) {
484 if(drawee.vertices.empty()) return *this;
485 glPushAttrib(GL_ALL_ATTRIB_BITS);
486 setStrokeState(strk);
488 const Point datum = drawee.getDatum();
489 glTranslatef(datum.x, datum.y, datum.z);
490 glBegin(GL_LINE_STRIP);
491 for(std::deque<Point>::const_iterator v=drawee.vertices.begin(); v!=drawee.vertices.end(); v++) {
492 glVertex3d((*v).x, (*v).y, (*v).z);
500 Canvas& Canvas::figures(const Group &drawee) {
501 const Color zero_alpha(1,1,1,0,false);
502 const Point datum = drawee.getDatum();
503 bool clipper_cached ;
504 glPushAttrib(GL_ALL_ATTRIB_BITS);
505 if(drawee.clip_type==Group::ALPHA) {
506 clipper_cached = drawee.alpha_mask->caches.count(this);
507 if(!clipper_cached) drawee.alpha_mask->cache(*this);
509 // nulling alpha value in buffer
510 glBlendFunc(GL_ZERO, GL_SRC_COLOR);
511 Rectangle fullcanvas(getWidth(), getHeight());
512 fullcanvas.draw(zero_alpha);
515 if(drawee.clip_type==Group::RECT) {
516 glEnable(GL_SCISSOR_TEST);
517 glScissor((int)(drawee.scissor_left+datum.x), (int)(drawee.scissor_top+datum.y),
518 (int)(drawee.scissor_width), (int)(drawee.scissor_height));
520 glTranslated(datum.x, datum.y, datum.z);
521 if(drawee.scaling.x!=0.0 || drawee.scaling.y!=0.0 || drawee.scaling.z!=0.0) glScaled(drawee.scaling.x, drawee.scaling.y, drawee.scaling.z);
522 if(drawee.rotation!=0.0) glRotated(drawee.rotation, drawee.axis.x, drawee.axis.y, drawee.axis.z);
523 if(drawee.clip_type==Group::ALPHA) {
524 // nulling alpha value in buffer
525 //glBlendFunc(GL_ZERO, GL_SRC_COLOR);
526 //drawee.alpha_mask->targetarea_.draw(zero_alpha);
527 // write alpha value to buffer
528 glBlendFunc(GL_ONE, GL_ONE);
529 drawee.alpha_mask->draw();
531 glBlendFunc(GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA);
532 if(!clipper_cached) drawee.alpha_mask->uncache(*this);
534 if(!drawee.contents.empty()) {
535 for(int i=0; i<drawee.contents.size(); i++) {
536 drawee.contents[i]->draw(*this);
539 if(drawee.clip_type==Group::RECT) {
540 glDisable(GL_SCISSOR_TEST);
542 if(drawee.clip_type==Group::ALPHA) {
543 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
550 Canvas& Canvas::image(const Image &img, const double alpha) {
551 const Color zero_alpha(1,1,1,0,false), alpha_mask(0,0,0,alpha);
552 Rectangle area = img.targetarea_;
553 area.set(area.left-1, area.top-1, area.right+1, area.bottom+1);
554 glPushAttrib(GL_ALL_ATTRIB_BITS);
557 // nulling alpha value in buffer
558 glBlendFunc(GL_ZERO, GL_SRC_COLOR);
559 rect(area, zero_alpha);
560 // write alpha value to buffer
561 glBlendFunc(GL_ONE, GL_ONE);
562 rect(area, alpha_mask);
563 glBlendFunc(GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA);
567 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
569 //glPopMatrix(); can't found corresponding glPushMatrix
577 void Canvas::copy(const Rectangle &source, const Rectangle &target, bool doesdeletesource, const Color &delcol) {
578 glReadBuffer(GL_BACK);
579 glDrawBuffer(GL_BACK);
580 glRasterPos2d(target.left, target.bottom);
581 glCopyPixels((GLuint)source.left, (GLuint)(Height-source.bottom-1), (GLuint)source.getWidth(), (GLuint)source.getHeight(), GL_COLOR);
582 if(doesdeletesource) {
583 fillRect(source, delcol);
586 void Canvas::to(Image &img, const Rectangle &srcrect) const {
\r
587 Rectangle src = srcrect, cvsr(getWidth(), getHeight());
\r
589 int sw=(GLuint)srcrect.getWidth(), sh=(GLuint)srcrect.getHeight();
\r
590 int tw=(GLuint)img.getWidth(), th=(GLuint)img.getHeight();
\r
591 if(!(img.hasInstance()) || (tw!=sw || th!=sh)) {
\r
595 // glReadBuffer(GL_BACK);
596 glReadPixels((GLuint)(src.getLeft()), (GLuint)(Height-src.getBottom()-1), (GLuint)src.getWidth(), (GLuint)src.getHeight(), APIImageProperties::PixCompGL_[img.pixcomp_], APIImageProperties::PixPrecGL_[img.pixprec_], const_cast<void *>(img.getBitmapPtr()) );
599 /* void Canvas::to(Image &img, const Rectangle &srcrect, const Rectangle &tgtrect) const {
600 if(!img.hasInstance()) img.set(srcrect);
601 Rectangle src = srcrect, tgt = tgtrect, imgrect(img.getWidth(), img.getHeight());
603 GLuint sw=(GLuint)srcrect.getWidth(), sh=(GLuint)srcrect.getHeight(), tw=(GLuint)tgt.getWidth(), th=(GLuint)tgt.getHeight(), iw=(GLuint)img.getWidth(), ih=(GLuint)img.getHeight();
604 if(tw!=sw || th!=sh) {
605 src.resize(tw<sw?tw:sw, th<sh?th:sh).centering(srcrect);
607 glReadBuffer(GL_BACK);
608 glReadPixels((GLuint)(srcrect.left), (GLuint)(Height-srcrect.bottom), (GLuint)src.getWidth(), (GLuint)src.getHeight(), Image::PixCompGL_[img.pixcomp_], Image::PixPrecGL_[img.pixprec_], const_cast<void *>(img.getBitmapPtr()) );
609 unsigned int lines, sl, sr, sb, tl, tr, tb;
610 for(int l=0; l<lines; l++)
617 void Canvas::var_(std::string str, double x, double y, const Color &col, bool fillForward) {
619 glPushAttrib(GL_ALL_ATTRIB_BITS);
622 std::string::iterator itr=str.begin(), end=str.end();
623 glTranslatef(x-12,y,0);
625 glTranslatef(12,0,0);
626 glCallList(font_LCD[(int)(*itr)]);
630 std::string::reverse_iterator itr=str.rbegin(), end=str.rend();
633 glTranslatef(-12,0,0);
634 glCallList(font_LCD[(int)(*itr)]);
641 int Canvas::msg(const char* str, const double x, const double y, const Color &col, const int horiz_align, const int vertical_align, const double max__width) {
643 const Color zero_alpha(1,1,1,0,false), alpha_mask(1,1,1,col.getA(),false);
645 glPushAttrib(GL_COLOR_BUFFER_BIT | GL_TEXTURE_BIT);
648 int i=0, line_begin_i=0, num_lines=0, cursol_xpos=0;
649 double line_x, line_y=0, max_width=0;
651 switch(horiz_align) {
652 case Letters::TEXT_ALIGN_RIGHT:
653 max_width = (max__width>0) ? (int)max__width : (int)(x);
655 case Letters::TEXT_ALIGN_CENTER:
656 if(max__width>0) max_width = (int)max__width;
657 else max_width = (x>Width/2) ? (int)(Width-x)*2 : (int)(x)*2;
659 case Letters::TEXT_ALIGN_LEFT:
661 max_width = (max__width>0) ? (int)max__width : (int)(Width-x);
669 while(cursol_xpos<max_width && str[i]!=0 && str[i]!='\r' && str[i]!='\n') {
670 cursol_xpos += Font::font_minimum_proportion[str[i++]];
672 switch(horiz_align) {
673 case Letters::TEXT_ALIGN_RIGHT:
674 line_x = x - cursol_xpos + 3;
676 case Letters::TEXT_ALIGN_CENTER:
677 line_x = x - cursol_xpos/2.0 + 3;
679 case Letters::TEXT_ALIGN_LEFT:
686 line_y = y + num_lines*8 - 8;
687 mask.set(line_x-4, line_y, line_x+cursol_xpos, line_y+8);
688 glBlendFunc(GL_ZERO, GL_SRC_COLOR); // clear destination alpha
689 rect(mask, zero_alpha);
690 glBlendFunc(GL_ONE, GL_ONE); // draw font in alpha channel
692 for(int c=line_begin_i; c<i; c++) {
694 drawImage(Font::font_minimum[str[c]], line_x+cursol_xpos, line_y);
695 cursol_xpos+=Font::font_minimum_proportion[str[c]];
699 if(col.getA()!=1) { // apply alpha factor
700 glBlendFunc(GL_ZERO, GL_SRC_COLOR);
701 rect(mask, alpha_mask);
703 glBlendFunc(GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA); // drawing in specified color by destination alpha
705 if( str[i]=='\r') i++;
706 if( str[i]=='\n') i++;
716 //////// Critical Operations ////////
717 void Canvas::flip(const int frame_duration_by_vsyncs) {
718 Clock time_thisFrame, elapsed;
721 if(frame_duration_by_vsyncs<1) throw Exception(typeid(*this), "ARGUMENT ERROR", "frame duration must be more than zero.");
723 if(!billboard.empty()) {
724 for(int i=0; i<billboard.size(); i++) billboard[i]->draw(*this);
726 if(displayingFPS) displayFPS();
727 if(Mouse::showLocalPointer()) Mouse::drawPointer(mouse(), *this);
732 if(rest_wating_vsyncs_>1) {
734 time_thisFrame.update();
735 elapsed = time_thisFrame - time_lastFrame_before_flip_;
740 time_thisFrame.update();
741 elapsed = time_thisFrame - time_lastFrame_before_flip_;
742 } while(elapsed.at_msec()<frameIntervalAccurate*(rest_wating_vsyncs_-0.5));
744 // TIME BASED ROUTINE
745 wait_time = frameIntervalAccurate*(rest_wating_vsyncs_);
747 if(not_time_critical_) Prototype::Thread::sleep(1000);
748 time_thisFrame.update();
749 elapsed = time_thisFrame - time_lastFrame_before_flip_;
750 } while(elapsed.at_msec()<wait_time);
752 // VSYNC BASED ROUTINE
753 /* int rest_frames = rest_wating_vsyncs_ - (int)( elapsed.at_msec() / frameIntervalAccurate );
754 //int rest_frames = (int)(((rest_wating_vsyncs_)*frameIntervalAccurate - elapsed.at_msec())/frameIntervalAccurate);
756 glReadBuffer(GL_BACK);
757 glDrawBuffer(GL_AUX0);
758 glRasterPos2d(0, Height-0.625);
759 glCopyPixels(0, 0, Width, Height, GL_COLOR);
760 glReadBuffer(GL_FRONT);
761 glDrawBuffer(GL_BACK);
762 glRasterPos2d(0, Height-0.625);
763 glCopyPixels(0, 0, Width, Height, GL_COLOR);
764 // glDrawBuffer(GL_AUX0);
765 for(int i=0; i<rest_frames; i++) {
766 rect(Rectangle(Width, Height), Color(0.0,0.0,0.0,0.5)); glFinish(); api->flip(); }
767 glReadBuffer(GL_AUX0);
768 glDrawBuffer(GL_BACK);
769 glRasterPos2d(0, Height-0.625);
770 glCopyPixels(0, 0, Width, Height, GL_COLOR);
774 wait_time = frameIntervalAccurate*0.1;
776 if(not_time_critical_) Prototype::Thread::sleep(1000);
777 time_thisFrame.update();
778 elapsed = time_thisFrame - time_lastFrame_before_flip_;
779 } while(elapsed.at_msec()<wait_time);
783 time_lastFrame_before_flip_.update();
787 //int rest_wating_vsyncs_before = rest_wating_vsyncs_;
788 rest_wating_vsyncs_ = frame_duration_by_vsyncs;
790 time_thisFrame.update();
791 elapsed = time_thisFrame - time_lastFrame;
792 frameInterval = elapsed.at_msec();
793 time_lastFrame = time_thisFrame;
796 displayedFrames+=frame_duration_by_vsyncs;
797 if(checkingFPS_last) {
798 lastFailedFrames_ = (long)floor( ((frameInterval-1.0-(frameIntervalAccurate*((double)rest_wating_vsyncs_-1)) ) / frameIntervalAccurate) );
799 failedFrames += lastFailedFrames_;
800 DISPLAYED_FRAMES = displayedFrames;
801 FAILED_FRAMES = failedFrames;
802 FAILED_FLIPS += ( lastFailedFrames_==0 ? 0 : 1);
803 TOTAL_REFRESH = failedFrames+displayedFrames;
804 LAST_FAILED_FRAMES = lastFailedFrames_;
806 checkingFPS_last = true;
811 Canvas& Canvas::clear(const Color &col, TargetSurface target) {
812 APIsetColorClear(col);
815 glDrawBuffer(GL_FRONT || GL_BACK);
816 //rect(clear_area_, col);
817 glClear(GL_COLOR_BUFFER_BIT);
820 glDrawBuffer(GL_FRONT);
821 //rect(clear_area_, col);
822 glClear(GL_COLOR_BUFFER_BIT);
825 glDrawBuffer(GL_BACK);
826 //rect(clear_area_, col);
827 glClear(GL_COLOR_BUFFER_BIT);
830 glDrawBuffer(GL_BACK);
835 //////// Utilities ////////
837 void Canvas::progressbar(double percentage) {
838 Rectangle filledrect;
839 Color fillcolor = progressbarfillcolor;
840 if( percentage>1.0 ) {
841 fillcolor = progressbarerrorcolor;
844 glDrawBuffer(GL_FRONT);
845 fillRect(progressbarrect, progressbaremptycolor);
847 filledrect.set(progressbarrect.left, progressbarrect.top, progressbarrect.left+(long)(progressbarrect.getWidth()*percentage), progressbarrect.bottom);
848 fillRect(filledrect, progressbarfillcolor);
851 glDrawBuffer(GL_BACK);
856 //////// Properties ////////
858 //////// Element Preparation ////////
860 void Canvas::setfontLCD() {
863 LIST: 0123456789AbCdEF+-* /=<>.,%
872 //int font_LCD_vertices[7*4] = { 2,2+len+len,2+len,2+len+len , 1,2+len,1,2+len+len , 2+len,2+len,2+len,2+len+len , 2,1+len,2+len,1+len , 1,1,1,1+len , 2+len,1,2+len,1+len , 2,0,2+len,0 };
873 int font_LCD_vertices[7*4] = {
880 for(int i=0; i<7*4; i+=4) {
881 if(font_LCD_vertices[i+0]==font_LCD_vertices[i+2]) {
882 font_LCD_vertices[i+0] = font_LCD_vertices[i+0]*len;
883 font_LCD_vertices[i+2] = font_LCD_vertices[i+2]*len;
885 font_LCD_vertices[i+0] = font_LCD_vertices[i+0]*len+1;
886 font_LCD_vertices[i+2] = font_LCD_vertices[i+2]*len;
888 if(font_LCD_vertices[i+1]==font_LCD_vertices[i+3]) {
889 font_LCD_vertices[i+1] = font_LCD_vertices[i+1]*len;
890 font_LCD_vertices[i+3] = font_LCD_vertices[i+3]*len;
892 font_LCD_vertices[i+1] = font_LCD_vertices[i+1]*len+1;
893 font_LCD_vertices[i+3] = font_LCD_vertices[i+3]*len;
895 font_LCD_vertices[i+1] -= len*2;
896 font_LCD_vertices[i+3] -= len*2;
898 //int font_LCD_GEN[16] = { 119,36,93,109,46,107,123,39,127,47,63,122,83,124,91,27 };
899 int font_LCD_GEN[128] = {
900 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
917 119,36,93,109,46,107,123,39,127,47,// 0123456789
918 0,0,0,0,0,0,0,// :;<=>?@
919 63,122,83,124,91,27,115,62,32,100,// AbCdEFGHiJ
921 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
922 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
923 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
926 font_LCD[0] = glGenLists(128);
928 for(int i=0; i<128; i++) {
929 font_LCD[i] = font_LCD[0]+i;
930 if(font_LCD_GEN[i] != 0) {
931 glNewList(font_LCD[i], GL_COMPILE);
933 for(int j=0; j<7; j++) {
934 if( font_LCD_GEN[i] >> j & 1 != 0 ) {
935 glVertex2i(font_LCD_vertices[j*4 + 0], font_LCD_vertices[j*4 + 1]);
936 glVertex2i(font_LCD_vertices[j*4 + 2], font_LCD_vertices[j*4 + 3]);
942 glNewList(font_LCD[i], GL_COMPILE);
944 glVertex2i(font_LCD_vertices[6*4 + 2], font_LCD_vertices[6*4 + 3]);
950 font_LCD_height = len*2+3;
953 void Canvas::setFillOvalPrimitives() {
954 // set display-lists index
955 fillOvalPrimitives[0] = glGenLists(4);
956 for(int i=1; i<4; i++) { fillOvalPrimitives[i]=fillOvalPrimitives[0]+i; }
957 drawOvalPrimitives[0] = glGenLists(4);
958 for(int i=1; i<4; i++) { drawOvalPrimitives[i]=drawOvalPrimitives[0]+i; }
962 for(int i=0; i<4; i++) {
963 glNewList(fillOvalPrimitives[i], GL_COMPILE);
965 for(int j=0; j<(k=pow(5.0, 2.0+i*0.2)); j++) {
966 glVertex2f(cos(2.0*(j/k)*PI)/2.0+0.5, sin(2.0*(j/k)*PI)/2.0+0.5); }
967 glVertex2f(cos(2.0*(0)*PI)/2.0+0.5, sin(2.0*(0)*PI)/2.0+0.5);
971 for(int i=0; i<4; i++) {
972 glNewList(drawOvalPrimitives[i], GL_COMPILE);
973 glBegin(GL_LINE_LOOP);
974 for(int j=0; j<(k=pow(5.0, 2.0+i*0.2)); j++) {
975 glVertex2f(cos(2.0*(j/k)*PI)/2.0+0.5, sin(2.0*(j/k)*PI)/2.0+0.5); }
976 glVertex2f(cos(2.0*(0)*PI)/2.0+0.5, sin(2.0*(0)*PI)/2.0+0.5);
984 } /* <- namespace Psycholops */