|
fltk 1.3.0rc3
About: FLTK (Fast Light Tool Kit) is a cross-platform C++ GUI toolkit for UNIX/Linux (X11), Microsoft Windows, and MacOS X. Release candidate.
SfR Fresh Dox: fltk-1.3.0rc3-source.tar.gz ("inofficial" and yet experimental doxygen-generated source code documentation) ![]() |
00001 // 00002 // "$Id: fl_vertex.cxx 7903 2010-11-28 21:06:39Z matt $" 00003 // 00004 // Portable drawing routines for the Fast Light Tool Kit (FLTK). 00005 // 00006 // Copyright 1998-2010 by Bill Spitzak and others. 00007 // 00008 // This library is free software; you can redistribute it and/or 00009 // modify it under the terms of the GNU Library General Public 00010 // License as published by the Free Software Foundation; either 00011 // version 2 of the License, or (at your option) any later version. 00012 // 00013 // This library is distributed in the hope that it will be useful, 00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 // Library General Public License for more details. 00017 // 00018 // You should have received a copy of the GNU Library General Public 00019 // License along with this library; if not, write to the Free Software 00020 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 00021 // USA. 00022 // 00023 // Please report all bugs and problems on the following page: 00024 // 00025 // http://www.fltk.org/str.php 00026 // 00027 00034 // Portable drawing code for drawing arbitrary shapes with 00035 // simple 2D transformations. See also fl_arc.cxx 00036 00037 // matt: the Quartz implementation purposely doesn't use the Quartz matrix 00038 // operations for reasons of compatibility and maintainability 00039 00040 #include <config.h> 00041 #include <FL/fl_draw.H> 00042 #include <FL/x.H> 00043 #include <FL/Fl.H> 00044 #include <FL/math.h> 00045 #include <stdlib.h> 00046 00047 struct matrix {double a, b, c, d, x, y;}; 00048 00049 static matrix m = {1, 0, 0, 1, 0, 0}; 00050 00051 static matrix stack[32]; 00052 matrix * fl_matrix = &m; 00053 static int sptr = 0; 00054 00059 void fl_push_matrix() { 00060 if (sptr==32) 00061 Fl::error("fl_push_matrix(): matrix stack overflow."); 00062 else 00063 stack[sptr++] = m; 00064 } 00065 00069 void fl_pop_matrix() { 00070 if (sptr==0) 00071 Fl::error("fl_pop_matrix(): matrix stack underflow."); 00072 else 00073 m = stack[--sptr]; 00074 } 00075 00082 void fl_mult_matrix(double a, double b, double c, double d, double x, double y) { 00083 matrix o; 00084 o.a = a*m.a + b*m.c; 00085 o.b = a*m.b + b*m.d; 00086 o.c = c*m.a + d*m.c; 00087 o.d = c*m.b + d*m.d; 00088 o.x = x*m.a + y*m.c + m.x; 00089 o.y = x*m.b + y*m.d + m.y; 00090 m = o; 00091 } 00092 00097 void fl_scale(double x,double y) {fl_mult_matrix(x,0,0,y,0,0);} 00098 00103 void fl_scale(double x) {fl_mult_matrix(x,0,0,x,0,0);} 00104 00109 void fl_translate(double x,double y) {fl_mult_matrix(1,0,0,1,x,y);} 00110 00115 void fl_rotate(double d) { 00116 if (d) { 00117 double s, c; 00118 if (d == 0) {s = 0; c = 1;} 00119 else if (d == 90) {s = 1; c = 0;} 00120 else if (d == 180) {s = 0; c = -1;} 00121 else if (d == 270 || d == -90) {s = -1; c = 0;} 00122 else {s = sin(d*M_PI/180); c = cos(d*M_PI/180);} 00123 fl_mult_matrix(c,-s,s,c,0,0); 00124 } 00125 } 00126 00127 // typedef what the x,y fields in a point are: 00128 #ifdef WIN32 00129 typedef int COORD_T; 00130 # define XPOINT XPoint 00131 #elif defined(__APPLE_QUARTZ__) 00132 typedef float COORD_T; 00133 typedef struct { float x; float y; } QPoint; 00134 # define XPOINT QPoint 00135 extern float fl_quartz_line_width_; 00136 #else 00137 typedef short COORD_T; 00138 # define XPOINT XPoint 00139 #endif 00140 00141 static XPOINT *p = (XPOINT *)0; 00142 00143 static int p_size; 00144 static int n; 00145 static int what; 00146 enum {LINE, LOOP, POLYGON, POINT_}; 00147 00148 void Fl_Graphics_Driver::begin_points() {n = 0; what = POINT_;} 00149 00150 void Fl_Graphics_Driver::begin_line() {n = 0; what = LINE;} 00151 00152 void Fl_Graphics_Driver::begin_loop() {n = 0; what = LOOP;} 00153 00154 void Fl_Graphics_Driver::begin_polygon() {n = 0; what = POLYGON;} 00155 00160 double fl_transform_x(double x, double y) {return x*m.a + y*m.c + m.x;} 00161 00166 double fl_transform_y(double x, double y) {return x*m.b + y*m.d + m.y;} 00167 00172 double fl_transform_dx(double x, double y) {return x*m.a + y*m.c;} 00173 00178 double fl_transform_dy(double x, double y) {return x*m.b + y*m.d;} 00179 00180 static void fl_transformed_vertex(COORD_T x, COORD_T y) { 00181 if (!n || x != p[n-1].x || y != p[n-1].y) { 00182 if (n >= p_size) { 00183 p_size = p ? 2*p_size : 16; 00184 p = (XPOINT*)realloc((void*)p, p_size*sizeof(*p)); 00185 } 00186 p[n].x = x; 00187 p[n].y = y; 00188 n++; 00189 } 00190 } 00191 00192 void Fl_Graphics_Driver::transformed_vertex(double xf, double yf) { 00193 #ifdef __APPLE_QUARTZ__ 00194 fl_transformed_vertex(COORD_T(xf), COORD_T(yf)); 00195 #else 00196 fl_transformed_vertex(COORD_T(rint(xf)), COORD_T(rint(yf))); 00197 #endif 00198 } 00199 00200 void Fl_Graphics_Driver::vertex(double x,double y) { 00201 fl_transformed_vertex(x*m.a + y*m.c + m.x, x*m.b + y*m.d + m.y); 00202 } 00203 00204 void Fl_Graphics_Driver::end_points() { 00205 #if defined(USE_X11) 00206 if (n>1) XDrawPoints(fl_display, fl_window, fl_gc, p, n, 0); 00207 #elif defined(WIN32) 00208 for (int i=0; i<n; i++) SetPixel(fl_gc, p[i].x, p[i].y, fl_RGB()); 00209 #elif defined(__APPLE_QUARTZ__) 00210 if (fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, true); 00211 for (int i=0; i<n; i++) { 00212 CGContextMoveToPoint(fl_gc, p[i].x, p[i].y); 00213 CGContextAddLineToPoint(fl_gc, p[i].x, p[i].y); 00214 CGContextStrokePath(fl_gc); 00215 } 00216 if (fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, false); 00217 #else 00218 # error unsupported platform 00219 #endif 00220 } 00221 00222 void Fl_Graphics_Driver::end_line() { 00223 if (n < 2) { 00224 fl_end_points(); 00225 return; 00226 } 00227 #if defined(USE_X11) 00228 if (n>1) XDrawLines(fl_display, fl_window, fl_gc, p, n, 0); 00229 #elif defined(WIN32) 00230 if (n>1) Polyline(fl_gc, p, n); 00231 #elif defined(__APPLE_QUARTZ__) 00232 if (n<=1) return; 00233 CGContextSetShouldAntialias(fl_gc, true); 00234 CGContextMoveToPoint(fl_gc, p[0].x, p[0].y); 00235 for (int i=1; i<n; i++) 00236 CGContextAddLineToPoint(fl_gc, p[i].x, p[i].y); 00237 CGContextStrokePath(fl_gc); 00238 CGContextSetShouldAntialias(fl_gc, false); 00239 #else 00240 # error unsupported platform 00241 #endif 00242 } 00243 00244 static void fixloop() { // remove equal points from closed path 00245 while (n>2 && p[n-1].x == p[0].x && p[n-1].y == p[0].y) n--; 00246 } 00247 00248 void Fl_Graphics_Driver::end_loop() { 00249 fixloop(); 00250 if (n>2) fl_transformed_vertex((COORD_T)p[0].x, (COORD_T)p[0].y); 00251 fl_end_line(); 00252 } 00253 00254 void Fl_Graphics_Driver::end_polygon() { 00255 fixloop(); 00256 if (n < 3) { 00257 fl_end_line(); 00258 return; 00259 } 00260 #if defined(USE_X11) 00261 if (n>2) XFillPolygon(fl_display, fl_window, fl_gc, p, n, Convex, 0); 00262 #elif defined(WIN32) 00263 if (n>2) { 00264 SelectObject(fl_gc, fl_brush()); 00265 Polygon(fl_gc, p, n); 00266 } 00267 #elif defined(__APPLE_QUARTZ__) 00268 if (n<=1) return; 00269 CGContextSetShouldAntialias(fl_gc, true); 00270 CGContextMoveToPoint(fl_gc, p[0].x, p[0].y); 00271 for (int i=1; i<n; i++) 00272 CGContextAddLineToPoint(fl_gc, p[i].x, p[i].y); 00273 CGContextClosePath(fl_gc); 00274 CGContextFillPath(fl_gc); 00275 CGContextSetShouldAntialias(fl_gc, false); 00276 #else 00277 # error unsupported platform 00278 #endif 00279 } 00280 00281 static int gap_; 00282 #if defined(WIN32) 00283 static int counts[20]; 00284 static int numcount; 00285 #endif 00286 00287 void Fl_Graphics_Driver::begin_complex_polygon() { 00288 fl_begin_polygon(); 00289 gap_ = 0; 00290 #if defined(WIN32) 00291 numcount = 0; 00292 #endif 00293 } 00294 00295 void Fl_Graphics_Driver::gap() { 00296 while (n>gap_+2 && p[n-1].x == p[gap_].x && p[n-1].y == p[gap_].y) n--; 00297 if (n > gap_+2) { 00298 fl_transformed_vertex((COORD_T)p[gap_].x, (COORD_T)p[gap_].y); 00299 #if defined(WIN32) 00300 counts[numcount++] = n-gap_; 00301 #endif 00302 gap_ = n; 00303 } else { 00304 n = gap_; 00305 } 00306 } 00307 00308 void Fl_Graphics_Driver::end_complex_polygon() { 00309 fl_gap(); 00310 if (n < 3) { 00311 fl_end_line(); 00312 return; 00313 } 00314 #if defined(USE_X11) 00315 if (n>2) XFillPolygon(fl_display, fl_window, fl_gc, p, n, 0, 0); 00316 #elif defined(WIN32) 00317 if (n>2) { 00318 SelectObject(fl_gc, fl_brush()); 00319 PolyPolygon(fl_gc, p, counts, numcount); 00320 } 00321 #elif defined(__APPLE_QUARTZ__) 00322 if (n<=1) return; 00323 CGContextSetShouldAntialias(fl_gc, true); 00324 CGContextMoveToPoint(fl_gc, p[0].x, p[0].y); 00325 for (int i=1; i<n; i++) 00326 CGContextAddLineToPoint(fl_gc, p[i].x, p[i].y); 00327 CGContextClosePath(fl_gc); 00328 CGContextFillPath(fl_gc); 00329 CGContextSetShouldAntialias(fl_gc, false); 00330 #else 00331 # error unsupported platform 00332 #endif 00333 } 00334 00335 // shortcut the closed circles so they use XDrawArc: 00336 // warning: these do not draw rotated ellipses correctly! 00337 // See fl_arc.c for portable version. 00338 00339 void Fl_Graphics_Driver::circle(double x, double y,double r) { 00340 double xt = fl_transform_x(x,y); 00341 double yt = fl_transform_y(x,y); 00342 double rx = r * (m.c ? sqrt(m.a*m.a+m.c*m.c) : fabs(m.a)); 00343 double ry = r * (m.b ? sqrt(m.b*m.b+m.d*m.d) : fabs(m.d)); 00344 int llx = (int)rint(xt-rx); 00345 int w = (int)rint(xt+rx)-llx; 00346 int lly = (int)rint(yt-ry); 00347 int h = (int)rint(yt+ry)-lly; 00348 00349 #if defined(USE_X11) 00350 (what == POLYGON ? XFillArc : XDrawArc) 00351 (fl_display, fl_window, fl_gc, llx, lly, w, h, 0, 360*64); 00352 #elif defined(WIN32) 00353 if (what==POLYGON) { 00354 SelectObject(fl_gc, fl_brush()); 00355 Pie(fl_gc, llx, lly, llx+w, lly+h, 0,0, 0,0); 00356 } else 00357 Arc(fl_gc, llx, lly, llx+w, lly+h, 0,0, 0,0); 00358 #elif defined(__APPLE_QUARTZ__) 00359 // Quartz warning : circle won't scale to current matrix! 00360 //last argument must be 0 (counterclockwise) or it draws nothing under __LP64__ !!!! 00361 CGContextSetShouldAntialias(fl_gc, true); 00362 CGContextAddArc(fl_gc, xt, yt, (w+h)*0.25f, 0, 2.0f*M_PI, 0); 00363 (what == POLYGON ? CGContextFillPath : CGContextStrokePath)(fl_gc); 00364 CGContextSetShouldAntialias(fl_gc, false); 00365 #else 00366 # error unsupported platform 00367 #endif 00368 } 00369 00370 // 00371 // End of "$Id: fl_vertex.cxx 7903 2010-11-28 21:06:39Z matt $". 00372 //