Author: matt Date: 2011-08-25 15:05:10 -0700 (Thu, 25 Aug 2011) New Revision: 9012 Log: Missing files
Added: branches/branch-3.0/src/fltk3gl/gl_draw.cxx branches/branch-3.0/src/fltk3gl/gl_start.cxx branches/branch-3.0/src/fltk3gl/glut_compatability.cxx branches/branch-3.0/src/fltk3gl/glut_font.cxx Added: branches/branch-3.0/src/fltk3gl/gl_draw.cxx =================================================================== --- branches/branch-3.0/src/fltk3gl/gl_draw.cxx (rev 0) +++ branches/branch-3.0/src/fltk3gl/gl_draw.cxx 2011-08-25 22:05:10 UTC (rev 9012) @@ -0,0 +1,580 @@ +// +// "$Id: gl_draw.cxx 8991 2011-08-22 15:21:44Z matt $" +// +// OpenGL drawing support routines for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2011 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Functions from <fltk3/gl.h> +// See also fltk3::GLWindow and gl_start.cxx + +#include "../fltk3/flstring.h" +#if HAVE_GL || defined(FLTK3_DOXYGEN) + +#include <fltk3/run.h> +#include <fltk3gl/gl.h> +#include <fltk3/x.h> +#include <fltk3/draw.h> +#include <fltk3/Device.h> +#include "GLChoice.H" +#include "../fltk3/font.h" +#include <fltk3/utf8.h> + +#if !defined(WIN32) && !defined(__APPLE__) +#include <fltk3/Xutf8.h> +#endif + +#if USE_XFT +//extern XFontStruct* fl_xxfont(); +#endif // USE_XFT + +/** Returns the current font's height */ +int gl_height() {return fltk3::height();} +/** Returns the current font's descent */ +int gl_descent() {return fltk3::descent();} +/** Returns the width of the string in the current fnt */ +double gl_width(const char* s) {return fltk3::width(s);} +/** Returns the width of n characters of the string in the current font */ +double gl_width(const char* s, int n) {return fltk3::width(s,n);} +/** Returns the width of the character in the current font */ +double gl_width(uchar c) {return fltk3::width(c);} + +static Fl_Font_Descriptor *gl_fontsize; + +#define GL_DRAW_USES_TEXTURES (defined(__APPLE__) && !__ppc__) // 1 only for non-PPC OSX +#ifndef __APPLE__ +# define USE_OksiD_style_GL_font_selection 1 // Most hosts except OSX +#else +# undef USE_OksiD_style_GL_font_selection // OSX +#endif + +#if USE_XFT +# undef USE_OksiD_style_GL_font_selection // turn this off for XFT also +#endif + +/** + Sets the current OpenGL font to the same font as calling fltk3::font() + */ +void gl_font(int fontid, int size) { + fltk3::font(fontid, size); + Fl_Font_Descriptor *fontsize = fltk3::graphics_driver->font_descriptor(); +#if !GL_DRAW_USES_TEXTURES + if (!fontsize->listbase) { + +#ifdef USE_OksiD_style_GL_font_selection + fontsize->listbase = glGenLists(0x10000); +#else // Fltk-1.1.8 style GL font selection + +#if defined (USE_X11) // X-windows options follow, either XFT or "plain" X +// FIXME: warning Ideally, for XFT, we really need a glXUseXftFont implementation here... +// FIXME: warning GL font selection is basically wrong here +/* OksiD had a fairly sophisticated scheme for storing multiple X fonts in a XUtf8FontStruct, + * then sorting through them at draw time (for normal X rendering) to find which one can + * render the current glyph... But for now, just use the first font in the list for GL... + */ + XFontStruct *font = fl_xfont; + int base = font->min_char_or_byte2; + int count = font->max_char_or_byte2-base+1; + fontsize->listbase = glGenLists(256); + glXUseXFont(font->fid, base, count, fontsize->listbase+base); +# elif defined(WIN32) + // this is unused because USE_OksiD_style_GL_font_selection == 1 + int base = fontsize->metr.tmFirstChar; + int count = fontsize->metr.tmLastChar-base+1; + HFONT oldFid = (HFONT)SelectObject(fl_gc, fontsize->fid); + fontsize->listbase = glGenLists(256); + wglUseFontBitmaps(fl_gc, base, count, fontsize->listbase+base); + SelectObject(fl_gc, oldFid); +# elif defined(__APPLE_QUARTZ__) +//AGL is not supported for use in 64-bit applications: +//http://developer.apple.com/mac/library/documentation/Carbon/Conceptual/Carbon64BitGuide/OtherAPIChanges/OtherAPIChanges.html + short font, face, size; + uchar fn[256]; + fn[0]=strlen(fontsize->q_name); + strcpy((char*)(fn+1), fontsize->q_name); + GetFNum(fn, &font); + face = 0; + size = fontsize->size; + fontsize->listbase = glGenLists(256); + aglUseFont(aglGetCurrentContext(), font, face, + size, 0, 256, fontsize->listbase); +# else +# error unsupported platform +# endif + +#endif // USE_OksiD_style_GL_font_selection + } + glListBase(fontsize->listbase); +#endif // !GL_DRAW_USES_TEXTURES + gl_fontsize = fontsize; +} + +#ifndef __APPLE__ +static void get_list(int r) { + gl_fontsize->glok[r] = 1; +#if defined(USE_X11) +# if USE_XFT +// FIXME +# else + unsigned int ii = r * 0x400; + for (int i = 0; i < 0x400; i++) { + XFontStruct *font = NULL; + unsigned short id; + XGetUtf8FontAndGlyph(gl_fontsize->font, ii, &font, &id); + if (font) glXUseXFont(font->fid, id, 1, gl_fontsize->listbase+ii); + ii++; + } +# endif +#elif defined(WIN32) + unsigned int ii = r * 0x400; + HFONT oldFid = (HFONT)SelectObject(fl_gc, gl_fontsize->fid); + wglUseFontBitmapsW(fl_gc, ii, ii + 0x03ff, gl_fontsize->listbase+ii); + SelectObject(fl_gc, oldFid); +#elif defined(__APPLE_QUARTZ__) +// handled by textures +#else +# error unsupported platform +#endif +} // get_list +#endif + +void gl_remove_displaylist_fonts() +{ +# if HAVE_GL + + // clear variables used mostly in fltk3::font + fltk3::graphics_driver->font(0, 0); + + for (int j = 0 ; j < fltk3::FREE_FONT ; ++j) + { + Fl_Font_Descriptor* past = 0; + Fl_Fontdesc* s = fltk3::fonts + j ; + Fl_Font_Descriptor* f = s->first; + while (f != 0) { + if(f->listbase) { + if(f == s->first) { + s->first = f->next; + } + else { + past->next = f->next; + } + + // It would be nice if this next line was in a desctructor somewhere + glDeleteLists(f->listbase, 256); + + Fl_Font_Descriptor* tmp = f; + f = f->next; + delete tmp; + } + else { + past = f; + f = f->next; + } + } + } + +#endif +} + +#if GL_DRAW_USES_TEXTURES +static void gl_draw_textures(const char* str, int n); +#endif + +/** + Draws an array of n characters of the string in the current font + at the current position. + \see On the Mac OS X platform, see gl_texture_pile_height(int) + */ +void gl_draw(const char* str, int n) { +#ifdef __APPLE__ + +#if GL_DRAW_USES_TEXTURES + gl_draw_textures(str, n); +#else + glCallLists(n, GL_UNSIGNED_BYTE, str); +#endif + +#else + static xchar *buf = NULL; + static int l = 0; + int wn = fltk3::utf8toUtf16(str, n, (unsigned short*)buf, l); + if(wn >= l) { + buf = (xchar*) realloc(buf, sizeof(xchar) * (wn + 1)); + l = wn + 1; + wn = fltk3::utf8toUtf16(str, n, (unsigned short*)buf, l); + } + n = wn; + + int i; + for (i = 0; i < n; i++) { + unsigned int r; + r = (str[i] & 0xFC00) >> 10; + if (!gl_fontsize->glok[r]) get_list(r); + } + glCallLists(n, GL_UNSIGNED_SHORT, buf); +#endif +} + +/** + Draws n characters of the string in the current font at the given position + \see On the Mac OS X platform, see gl_texture_pile_height(int) + */ +void gl_draw(const char* str, int n, int x, int y) { + glRasterPos2i(x, y); + gl_draw(str, n); +} + +/** + Draws n characters of the string in the current font at the given position + \see On the Mac OS X platform, see gl_texture_pile_height(int) + */ +void gl_draw(const char* str, int n, float x, float y) { + glRasterPos2f(x, y); + gl_draw(str, n); +} + +/** + Draws a nul-terminated string in the current font at the current position + \see On the Mac OS X platform, see gl_texture_pile_height(int) + */ +void gl_draw(const char* str) { + gl_draw(str, strlen(str)); +} + +/** + Draws a nul-terminated string in the current font at the given position + \see On the Mac OS X platform, see gl_texture_pile_height(int) + */ +void gl_draw(const char* str, int x, int y) { + gl_draw(str, strlen(str), x, y); +} + +/** + Draws a nul-terminated string in the current font at the given position + \see On the Mac OS X platform, see gl_texture_pile_height(int) + */ +void gl_draw(const char* str, float x, float y) { + gl_draw(str, strlen(str), x, y); +} + +static void gl_draw_invert(const char* str, int n, int x, int y) { + glRasterPos2i(x, -y); + gl_draw(str, n); +} + +/** + Draws a string formatted into a box, with newlines and tabs expanded, + other control characters changed to ^X. and aligned with the edges or + center. Exactly the same output as fltk3::draw(). + */ +void gl_draw( + const char* str, // the (multi-line) string + int x, int y, int w, int h, // bounding box + fltk3::Align align) { + fltk3::draw(str, x, -y-h, w, h, align, gl_draw_invert); +} + +/** Measure how wide and tall the string will be when drawn by the gl_draw() function */ +void gl_measure(const char* str, int& x, int& y) {fltk3::measure(str,x,y);} + +/** + Outlines the given rectangle with the current color. + If fltk3::GLWindow::ortho() has been called, then the rectangle will + exactly fill the given pixel rectangle. + */ +void gl_rect(int x, int y, int w, int h) { + if (w < 0) {w = -w; x = x-w;} + if (h < 0) {h = -h; y = y-h;} + glBegin(GL_LINE_STRIP); + glVertex2i(x+w-1, y+h-1); + glVertex2i(x+w-1, y); + glVertex2i(x, y); + glVertex2i(x, y+h-1); + glVertex2i(x+w, y+h-1); + glEnd(); +} + +#if HAVE_GL_OVERLAY +extern uchar fl_overlay; +extern int fl_overlay_depth; +#endif + +/** + Sets the curent OpenGL color to an FLTK color. + + For color-index modes it will use fl_xpixel(c), which is only + right if the window uses the default colormap! + */ +void gl_color(fltk3::Color i) { +#if HAVE_GL_OVERLAY +#if defined(WIN32) + if (fl_overlay && fl_overlay_depth) { + if (fl_overlay_depth < 8) { + // only black & white produce the expected colors. This could + // be improved by fixing the colormap set in Fl_Gl_Overlay.cxx + int size = 1<<fl_overlay_depth; + if (!i) glIndexi(size-2); + else if (i >= size-2) glIndexi(size-1); + else glIndexi(i); + } else { + glIndexi(i ? i : fltk3::GRAY_RAMP); + } + return; + } +#else + if (fl_overlay) {glIndexi(int(fl_xpixel(i))); return;} +#endif +#endif + uchar red, green, blue; + fltk3::get_color(i, red, green, blue); + glColor3ub(red, green, blue); +} + +void gl_draw_image(const uchar* b, int x, int y, int w, int h, int d, int ld) { + if (!ld) ld = w*d; + glPixelStorei(GL_UNPACK_ROW_LENGTH, ld/d); + glRasterPos2i(x,y); + glDrawPixels(w,h,d<4?GL_RGB:GL_RGBA,GL_UNSIGNED_BYTE,(const ulong*)b); +} + +#if GL_DRAW_USES_TEXTURES || defined(FLTK3_DOXYGEN) + +#include <fltk3gl/glu.h> + +// manages a fifo pile of pre-computed string textures +class gl_texture_fifo { + friend void gl_draw_textures(const char *, int); +private: + typedef struct { // information for a pre-computed texture + GLuint texName; // its name + char *utf8; //its text + Fl_Font_Descriptor *fdesc; // its font + int width; // its width + int height; // its height + } data; + data *fifo; // array of pile elements + int size_; // pile height + int current; // the oldest texture to have entered the pile + int last; // pile top + int textures_generated; // true iff glGenTextures has been called + void display_texture(int rank); + int compute_texture(const char* str, int n); + int already_known(const char *str, int n); +public: + gl_texture_fifo(int max = 100); // 100 = default height of texture pile + inline int size(void) {return size_; }; + ~gl_texture_fifo(void); +}; + +gl_texture_fifo::gl_texture_fifo(int max) +{ + size_ = max; + last = current = -1; + textures_generated = 0; + fifo = (data*)calloc(size_, sizeof(data)); +} + +gl_texture_fifo::~gl_texture_fifo() +{ + for (int i = 0; i < size_; i++) { + if (fifo[i].utf8) free(fifo[i].utf8); + if (textures_generated) glDeleteTextures(1, &fifo[i].texName); + } + free(fifo); +} + +// displays a pre-computed texture on the GL scene +void gl_texture_fifo::display_texture(int rank) +{ + //setup matrices + GLint matrixMode; + glGetIntegerv (GL_MATRIX_MODE, &matrixMode); + glMatrixMode (GL_PROJECTION); + glPushMatrix(); + glLoadIdentity (); + glMatrixMode (GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity (); + float winw = fltk3::Window::current()->w(); + float winh = fltk3::Window::current()->h(); + glScalef (2.0f / winw, 2.0f / winh, 1.0f); + glTranslatef (-winw / 2.0f, -winh / 2.0f, 0.0f); + //write the texture on screen + GLfloat pos[4]; + glGetFloatv(GL_CURRENT_RASTER_POSITION, pos); + CGRect bounds = CGRectMake (pos[0], pos[1] - fltk3::descent(), fifo[rank].width, fifo[rank].height); + + // GL_COLOR_BUFFER_BIT for glBlendFunc, GL_ENABLE_BIT for glEnable / glDisable + glPushAttrib(GL_ENABLE_BIT | GL_TEXTURE_BIT | GL_COLOR_BUFFER_BIT); + glDisable (GL_DEPTH_TEST); // ensure text is not removed by depth buffer test. + glEnable (GL_BLEND); // for text fading + glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA); // ditto + glEnable (GL_TEXTURE_RECTANGLE_EXT); + glDisable(GL_LIGHTING); + glBindTexture (GL_TEXTURE_RECTANGLE_EXT, fifo[rank].texName); + glBegin (GL_QUADS); + glTexCoord2f (0.0f, 0.0f); // draw lower left in world coordinates + glVertex2f (bounds.origin.x, bounds.origin.y); + + glTexCoord2f (0.0f, fifo[rank].height); // draw upper left in world coordinates + glVertex2f (bounds.origin.x, bounds.origin.y + bounds.size.height); + + glTexCoord2f (fifo[rank].width, fifo[rank].height); // draw upper right in world coordinates + glVertex2f (bounds.origin.x + bounds.size.width, bounds.origin.y + bounds.size.height); + + glTexCoord2f (fifo[rank].width, 0.0f); // draw lower right in world coordinates + glVertex2f (bounds.origin.x + bounds.size.width, bounds.origin.y); + glEnd (); + glPopAttrib(); + + // reset original matrices + glPopMatrix(); // GL_MODELVIEW + glMatrixMode (GL_PROJECTION); + glPopMatrix(); + glMatrixMode (matrixMode); + + //set the raster position to end of string + pos[0] += fifo[rank].width; + GLdouble modelmat[16]; + glGetDoublev (GL_MODELVIEW_MATRIX, modelmat); + GLdouble projmat[16]; + glGetDoublev (GL_PROJECTION_MATRIX, projmat); + GLdouble objX, objY, objZ; + GLint viewport[4]; + glGetIntegerv (GL_VIEWPORT, viewport); + gluUnProject(pos[0], pos[1], pos[2], modelmat, projmat, viewport, &objX, &objY, &objZ); + glRasterPos2d(objX, objY); +} + +// pre-computes a string texture +int gl_texture_fifo::compute_texture(const char* str, int n) +{ + current = (current + 1) % size_; + if (current > last) last = current; + //write str to a bitmap just big enough + if ( fifo[current].utf8 ) free(fifo[current].utf8); + fifo[current].utf8 = (char *)malloc(n + 1); + memcpy(fifo[current].utf8, str, n); + fifo[current].utf8[n] = 0; + fifo[current].width = 0, fifo[current].height = 0; + fltk3::measure(fifo[current].utf8, fifo[current].width, fifo[current].height, 0); + CGColorSpaceRef lut = CGColorSpaceCreateDeviceRGB(); + void *base = calloc(4*fifo[current].width, fifo[current].height); + if (base == NULL) return -1; + fl_gc = CGBitmapContextCreate(base, fifo[current].width, fifo[current].height, 8, fifo[current].width*4, lut, kCGImageAlphaPremultipliedLast); + CGColorSpaceRelease(lut); + fltk3::graphics_driver->font_descriptor(gl_fontsize); + GLfloat colors[4]; + glGetFloatv(GL_CURRENT_COLOR, colors); + fltk3::color((uchar)(colors[0]*255), (uchar)(colors[1]*255), (uchar)(colors[2]*255)); + fltk3::draw(str, n, 0, fifo[current].height - fltk3::descent()); + //put this bitmap in a texture + glPushAttrib(GL_TEXTURE_BIT); + glBindTexture (GL_TEXTURE_RECTANGLE_EXT, fifo[current].texName); + glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, GL_RGBA, fifo[current].width, fifo[current].height, 0, GL_RGBA, GL_UNSIGNED_BYTE, base); + glPopAttrib(); + CGContextRelease(fl_gc); + fl_gc = NULL; + free(base); + fifo[current].fdesc = gl_fontsize; + return current; +} + +// returns rank of pre-computed texture for a string if it exists +int gl_texture_fifo::already_known(const char *str, int n) +{ + int rank; + for ( rank = 0; rank <= last; rank++) { + if ( memcmp(str, fifo[rank].utf8, n) == 0 && fifo[rank].utf8[n] == 0 && + fifo[rank].fdesc == gl_fontsize) return rank; + } + return -1; +} + +static gl_texture_fifo *gl_fifo = NULL; // points to the texture pile class instance + +// draws a utf8 string using pre-computed texture if available +static void gl_draw_textures(const char* str, int n) +{ + if (! gl_fifo) gl_fifo = new gl_texture_fifo(); + if (!gl_fifo->textures_generated) { + for (int i = 0; i < gl_fifo->size_; i++) glGenTextures (1, &(gl_fifo->fifo[i].texName)); + gl_fifo->textures_generated = 1; + } + int rank = gl_fifo->already_known(str, n); + if (rank == -1) { + rank = gl_fifo->compute_texture(str, n); + } + gl_fifo->display_texture(rank); +} + +/** \addtogroup group_macosx + @{ */ + +/** + \brief Returns the current height of the pile of pre-computed string textures + * + The default value is 100 + */ +int gl_texture_pile_height(void) +{ + if (! gl_fifo) gl_fifo = new gl_texture_fifo(); + return gl_fifo->size(); +} + +/** + \brief Changes the height of the pile of pre-computed string textures + * + Strings that are often re-displayed can be processed much faster if + this pile is set high enough to hold all of them. + \param max Height of the texture pile + */ +void gl_texture_pile_height(int max) +{ + if (gl_fifo) delete gl_fifo; + gl_fifo = new gl_texture_fifo(max); +} + +/** @} */ + +#elif defined(__APPLE__) +// used only if __ppc__ +int gl_texture_pile_height(void) {return 0;} +void gl_texture_pile_height(int max) {} +#endif // GL_DRAW_USES_TEXTURES +#if defined(__APPLE__) +void gl_texture_reset() +{ +#if GL_DRAW_USES_TEXTURES + if (gl_fifo) gl_texture_pile_height(gl_texture_pile_height()); +#endif // GL_DRAW_USES_TEXTURES +} +#endif // __APPLE__ + +#endif // HAVE_GL + +// +// End of "$Id: gl_draw.cxx 8991 2011-08-22 15:21:44Z matt $". +// Added: branches/branch-3.0/src/fltk3gl/gl_start.cxx =================================================================== --- branches/branch-3.0/src/fltk3gl/gl_start.cxx (rev 0) +++ branches/branch-3.0/src/fltk3gl/gl_start.cxx 2011-08-25 22:05:10 UTC (rev 9012) @@ -0,0 +1,132 @@ +// +// "$Id: gl_start.cxx 8991 2011-08-22 15:21:44Z matt $" +// +// OpenGL context routines for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2010 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// You MUST use gl_visual() to select the default visual before doing +// show() of any windows. Mesa will crash if you try to use a visual +// not returned by glxChooseVisual. + +// This does not work with fltk3::DoubleWindow's! It will try to draw +// into the front buffer. Depending on the system this will either +// crash or do nothing (when pixmaps are being used as back buffer +// and GL is being done by hardware), work correctly (when GL is done +// with software, such as Mesa), or draw into the front buffer and +// be erased when the buffers are swapped (when double buffer hardware +// is being used) + +#include <config.h> +#if HAVE_GL + +#include <fltk3/run.h> +#include <fltk3/Window.h> +#include <fltk3/x.h> +#include <fltk3/draw.h> +#include "GLChoice.H" + +static GLContext context; +static int clip_state_number=-1; +static int pw, ph; + +#ifdef WIN32 +static fltk3::GLChoice* gl_choice; +#endif + +#ifdef __APPLE__ +static fltk3::GLChoice* gl_choice; +#endif + +fltk3::Region XRectangleRegion(int x, int y, int w, int h); // in fltk3::rect.cxx + +/** Creates an OpenGL context */ +void gl_start() { + if (!context) { +#if defined(USE_X11) + context = fl_create_gl_context(fl_visual); +#elif defined(WIN32) + if (!gl_choice) fltk3::gl_visual(0); + context = fl_create_gl_context(fltk3::Window::current(), gl_choice); +#elif defined(__APPLE_QUARTZ__) + // warning: the Quartz version should probably use Core GL (CGL) instead of AGL + context = fl_create_gl_context(fltk3::Window::current(), gl_choice); +#else +# error Unsupported platform +#endif + } + fl_set_gl_context(fltk3::Window::current(), context); +#if !defined(WIN32) && !defined(__APPLE__) + glXWaitX(); +#endif + if (pw != fltk3::Window::current()->w() || ph != fltk3::Window::current()->h()) { + pw = fltk3::Window::current()->w(); + ph = fltk3::Window::current()->h(); + glLoadIdentity(); + glViewport(0, 0, pw, ph); + glOrtho(0, pw, 0, ph, -1, 1); + glDrawBuffer(GL_FRONT); + } + if (clip_state_number != fltk3::graphics_driver->fl_clip_state_number) { + clip_state_number = fltk3::graphics_driver->fl_clip_state_number; + int x, y, w, h; + if (fltk3::clip_box(0, 0, fltk3::Window::current()->w(), fltk3::Window::current()->h(), + x, y, w, h)) { + fltk3::clip_region(XRectangleRegion(x,y,w,h)); + glScissor(x, fltk3::Window::current()->h()-(y+h), w, h); + glEnable(GL_SCISSOR_TEST); + } else { + glDisable(GL_SCISSOR_TEST); + } + } +} + +/** Releases an OpenGL context */ +void gl_finish() { + glFlush(); +#if !defined(WIN32) && !defined(__APPLE__) + glXWaitGL(); +#endif +} + +int fltk3::gl_visual(int mode, int *alist) { + fltk3::GLChoice *c = fltk3::GLChoice::find(mode,alist); + if (!c) return 0; +#if defined(USE_X11) + fl_visual = c->vis; + fl_colormap = c->colormap; +#elif defined(WIN32) + gl_choice = c; +#elif defined(__APPLE_QUARTZ__) + // warning: the Quartz version should probably use Core GL (CGL) instead of AGL + gl_choice = c; +#else +# error Unsupported platform +#endif + return 1; +} +#endif + +// +// End of "$Id: gl_start.cxx 8991 2011-08-22 15:21:44Z matt $". +// Added: branches/branch-3.0/src/fltk3gl/glut_compatability.cxx =================================================================== --- branches/branch-3.0/src/fltk3gl/glut_compatability.cxx (rev 0) +++ branches/branch-3.0/src/fltk3gl/glut_compatability.cxx 2011-08-25 22:05:10 UTC (rev 9012) @@ -0,0 +1,526 @@ +// +// "$Id: glut_compatability.cxx 8991 2011-08-22 15:21:44Z matt $" +// +// GLUT emulation routines for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2010 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +// Emulation of Glut using fltk. + +// GLUT is Copyright (c) Mark J. Kilgard, 1994, 1995, 1996. +// "This program is freely distributable without licensing fees and is +// provided without guarantee or warrantee expressed or implied. This +// program is -not- in the public domain." + +// Although I have copied the GLUT API, none of my code is based on +// any Glut implementation details and is therefore covered by the LGPL. + +#include "../fltk3/flstring.h" +#if HAVE_GL + +# include <fltk3gl/glut.h> +# ifdef HAVE_GLXGETPROCADDRESSARB +# define GLX_GLXEXT_LEGACY +# include <GL/glx.h> +# endif // HAVE_GLXGETPROCADDRESSARB +# ifdef HAVE_DLFCN_H +# include <dlfcn.h> +# endif // HAVE_DLFCN_H +# define MAXWINDOWS 32 +#include <fltk3/Wrapper.h> + +static fltk3::GlutWindow *windows[MAXWINDOWS+1]; + +static void (*glut_idle_func)() = 0; // global glut idle function + +fltk3::GlutWindow *glut_window; +int glut_menu; +void (*glut_menustate_function)(int); +void (*glut_menustatus_function)(int,int,int); + +static void default_reshape(int w, int h) {glViewport(0,0,w,h);} +static void default_display() {} + +void fltk3::GlutWindow::make_current() { + glut_window = this; + if (shown()) GLWindow::make_current(); +} + +static int indraw; +void fltk3::GlutWindow::draw() { + FLTK3_OBJECT_VCALLS_WRAPPER(draw(), Draw) + glut_window = this; + indraw = 1; + if (!valid()) {reshape(w(),h()); valid(1);} + display(); + indraw = 0; +} + +void glutSwapBuffers() { + if (!indraw) glut_window->swap_buffers(); +} + +void fltk3::GlutWindow::draw_overlay() { + glut_window = this; + if (!valid()) {reshape(w(),h()); valid(1);} + overlaydisplay(); +} + +static void domenu(int, int, int); + +int fltk3::GlutWindow::handle(int event) { + FLTK3_OBJECT_VCALLS_WRAPPER_RET(int, handle(event), Handle) + make_current(); + int ex = fltk3::event_x(); + int ey = fltk3::event_y(); + int button; + switch (event) { + + case fltk3::PUSH: + if (keyboard || special) fltk3::focus(this); + button = fltk3::event_button()-1; + if (button<0) button = 0; + if (button>2) button = 2; + if (menu[button]) {domenu(menu[button],ex,ey); return 1;} + mouse_down |= 1<<button; + if (mouse) {mouse(button,GLUT_DOWN,ex,ey); return 1;} + if (motion) return 1; + break; + + case fltk3::MOUSEWHEEL: + button = fltk3::event_dy(); + while (button < 0) {if (mouse) mouse(3,GLUT_DOWN,ex,ey); ++button;} + while (button > 0) {if (mouse) mouse(4,GLUT_DOWN,ex,ey); --button;} + return 1; + + case fltk3::RELEASE: + for (button = 0; button < 3; button++) if (mouse_down & (1<<button)) { + if (mouse) mouse(button,GLUT_UP,ex,ey); + } + mouse_down = 0; + return 1; + + case fltk3::ENTER: + if (entry) {entry(GLUT_ENTERED); return 1;} + if (passivemotion) return 1; + break; + + case fltk3::LEAVE: + if (entry) {entry(GLUT_LEFT); return 1;} + if (passivemotion) return 1; + break; + + case fltk3::DRAG: + if (motion) {motion(ex, ey); return 1;} + break; + + case fltk3::MOVE: + if (passivemotion) {passivemotion(ex, ey); return 1;} + break; + + case fltk3::FOCUS: + if (keyboard || special) return 1; + break; + + case fltk3::SHORTCUT: + if (!keyboard && !special) break; + + case fltk3::KEYBOARD: + if (fltk3::event_text()[0]) { + if (keyboard) {keyboard(fltk3::event_text()[0],ex,ey); return 1;} + break; + } else { + if (special) { + unsigned k = fltk3::event_key(); + if (k > fltk3::FKey && k <= fltk3::FLastKey) k -= fltk3::FKey; + special(k,ex,ey); + return 1; + } + break; + } + + case fltk3::HIDE: + if (visibility) visibility(GLUT_NOT_VISIBLE); + break; + + case fltk3::SHOW: + if (visibility) visibility(GLUT_VISIBLE); + break; + } + + return GLWindow::handle(event); +} + +static int glut_mode = GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH; + +void fltk3::GlutWindow::_init() { + for (number=1; number<MAXWINDOWS; number++) if (!windows[number]) break; + windows[number] = this; + menu[0] = menu[1] = menu[2] = 0; + reshape = default_reshape; + display = default_display; + overlaydisplay = default_display; + keyboard = 0; + mouse = 0; + motion = 0; + passivemotion = 0; + entry = 0; + visibility = 0; + special = 0; + mouse_down = 0; + mode(glut_mode); +} + +/** Creates a glut window, registers to the glut windows list.*/ +fltk3::GlutWindow::GlutWindow(int W, int H, const char *t) : + fltk3::GLWindow(W,H,t) {_init();} + +/** Creates a glut window, registers to the glut windows list.*/ +fltk3::GlutWindow::GlutWindow(int X,int Y,int W,int H, const char *t) : + fltk3::GLWindow(X,Y,W,H,t) {_init();} + +static int initargc; +static char **initargv; + +void glutInit(int *argc, char **argv) { + initargc = *argc; + initargv = new char*[*argc+1]; + int i,j; + for (i=0; i<=*argc; i++) initargv[i] = argv[i]; + for (i=j=1; i<*argc; ) { + if (fltk3::arg(*argc,argv,i)); + else argv[j++] = argv[i++]; + } + argv[j] = 0; + *argc = j; +} + +void glutInitDisplayMode(unsigned int mode) { + glut_mode = mode; +} + +void glutMainLoop() {fltk3::run();} + +//////////////////////////////////////////////////////////////// + +static int initx=0, inity=0, initw=300, inith=300, initpos=0; + +void glutInitWindowPosition(int x, int y) { + initx = x; inity = y; initpos = 1; +} + +void glutInitWindowSize(int w, int h) { + initw = w; inith = h; +} + +int glutCreateWindow(char *title) { + return glutCreateWindow((const char*)title); +} + +int glutCreateWindow(const char *title) { + fltk3::GlutWindow *W; + if (initpos) { + W = new fltk3::GlutWindow(initx,inity,initw,inith,title); + initpos = 0; + } else { + W = new fltk3::GlutWindow(initw,inith,title); + } + W->resizable(W); + if (initargc) { + W->show(initargc,initargv); + initargc = 0; + } else { + W->show(); + } + W->valid(0); + W->context_valid(0); + W->make_current(); + return W->number; +} + +int glutCreateSubWindow(int win, int x, int y, int w, int h) { + fltk3::GlutWindow *W = new fltk3::GlutWindow(x,y,w,h,0); + windows[win]->add(W); + if (windows[win]->shown()) W->show(); + W->make_current(); + return W->number; +} +/** Destroys the glut window, first unregister it from the glut windows list */ +fltk3::GlutWindow::~GlutWindow() { + if (glut_window == this) glut_window = 0; + windows[number] = 0; +} + +void glutDestroyWindow(int win) { + // should destroy children!!! + delete windows[win]; +} + +void glutPostWindowRedisplay(int win) { + windows[win]->redraw(); +} + +void glutSetWindow(int win) { + windows[win]->make_current(); +} + +//////////////////////////////////////////////////////////////// +#include <fltk3/MenuItem.h> + +struct menu { + void (*cb)(int); + fltk3::MenuItem *m; + int size; + int alloc; +}; + +#define MAXMENUS 32 +static menu menus[MAXMENUS+1]; + +static void domenu(int n, int ex, int ey) { + glut_menu = n; + menu *m = &menus[n]; + if (glut_menustate_function) glut_menustate_function(1); + if (glut_menustatus_function) glut_menustatus_function(1,ex,ey); + const fltk3::MenuItem* g = m->m->popup(fltk3::event_x(), fltk3::event_y(), 0); + if (g && g->callback_) ((void (*)(int))(g->callback_))(int(g->argument())); + if (glut_menustatus_function) glut_menustatus_function(0,ex,ey); + if (glut_menustate_function) glut_menustate_function(0); +} + +int glutCreateMenu(void (*cb)(int)) { + int i; + for (i=1; i<MAXMENUS; i++) if (!menus[i].cb) break; + menu *m = &menus[i]; + m->cb = cb; + return glut_menu = i; +} + +void glutDestroyMenu(int n) { + menu *m = &menus[n]; + delete[] m->m; + m->m = 0; + m->cb = 0; + m->size = m->alloc = 0; +} + +static fltk3::MenuItem* additem(menu *m) { + if (m->size+1 >= m->alloc) { + m->alloc = m->size*2+10; + fltk3::MenuItem* nm = new fltk3::MenuItem[m->alloc]; + for (int i=0; i<m->size; i++) nm[i] = m->m[i]; + delete[] m->m; + m->m = nm; + } + int n = m->size++; + m->m[n+1].text = 0; + fltk3::MenuItem* i = &(m->m[n]); + i->shortcut_ = 0; + i->flags = 0; + i->labeltype_ = i->labelfont_ = i->labelsize_ = i->labelcolor_ = 0; + return i; +} + +void glutAddMenuEntry(char *label, int value) { + menu *m = &menus[glut_menu]; + fltk3::MenuItem* i = additem(m); + i->text = label; + i->callback_ = (fltk3::Callback*)(m->cb); + i->user_data_ = (void *)value; +} + +void glutAddSubMenu(char *label, int submenu) { + menu *m = &menus[glut_menu]; + fltk3::MenuItem* i = additem(m); + i->text = label; + i->callback_ = 0; + i->user_data_ = (void *)(menus[submenu].m); + i->flags = fltk3::SUBMENU; +} + +void glutChangeToMenuEntry(int item, char *label, int value) { + menu *m = &menus[glut_menu]; + fltk3::MenuItem* i = &m->m[item-1]; + i->text = label; + i->callback_ = (fltk3::Callback*)(m->cb); + i->user_data_ = (void *)value; + i->flags = 0; +} + +void glutChangeToSubMenu(int item, char *label, int submenu) { + menu *m = &menus[glut_menu]; + fltk3::MenuItem* i = &m->m[item-1]; + i->text = label; + i->callback_ = 0; + i->user_data_ = (void *)(menus[submenu].m); + i->flags = fltk3::SUBMENU; +} + +void glutRemoveMenuItem(int item) { + menu *m = &menus[glut_menu]; + if (item > m->size || item < 1) return; + for (int i = item-1; i <= m->size; i++) m->m[i] = m->m[i+1]; + m->size--; +} + +//////////////////////////////////////////////////////////////// + +int glutGet(GLenum type) { + switch (type) { + case GLUT_RETURN_ZERO: return 0; + case GLUT_WINDOW_X: return glut_window->x(); + case GLUT_WINDOW_Y: return glut_window->y(); + case GLUT_WINDOW_WIDTH: return glut_window->w(); + case GLUT_WINDOW_HEIGHT: return glut_window->h(); + case GLUT_WINDOW_PARENT: + if (glut_window->parent()) + return ((fltk3::GlutWindow *)(glut_window->parent()))->number; + else + return 0; +//case GLUT_WINDOW_NUM_CHILDREN: +//case GLUT_WINDOW_CURSOR: return + case GLUT_SCREEN_WIDTH: return fltk3::w(); + case GLUT_SCREEN_HEIGHT: return fltk3::h(); +//case GLUT_SCREEN_WIDTH_MM: +//case GLUT_SCREEN_HEIGHT_MM: + case GLUT_MENU_NUM_ITEMS: return menus[glut_menu].size; + case GLUT_DISPLAY_MODE_POSSIBLE: return fltk3::GLWindow::can_do(glut_mode); + case GLUT_INIT_WINDOW_X: return initx; + case GLUT_INIT_WINDOW_Y: return inity; + case GLUT_INIT_WINDOW_WIDTH: return initw; + case GLUT_INIT_WINDOW_HEIGHT: return inith; + case GLUT_INIT_DISPLAY_MODE: return glut_mode; +//case GLUT_ELAPSED_TIME: + case GLUT_WINDOW_BUFFER_SIZE: + if (glutGet(GLUT_WINDOW_RGBA)) + return glutGet(GLUT_WINDOW_RED_SIZE)+ + glutGet(GLUT_WINDOW_GREEN_SIZE)+ + glutGet(GLUT_WINDOW_BLUE_SIZE)+ + glutGet(GLUT_WINDOW_ALPHA_SIZE); + else + return glutGet(GLUT_WINDOW_COLORMAP_SIZE); + case GLUT_VERSION: return 20400; + default: {GLint p; glGetIntegerv(type, &p); return p;} + } +} + +int glutLayerGet(GLenum type) { + switch (type) { + case GLUT_OVERLAY_POSSIBLE: return glut_window->can_do_overlay(); +//case GLUT_LAYER_IN_USE: +//case GLUT_HAS_OVERLAY: + case GLUT_TRANSPARENT_INDEX: return 0; // true for SGI + case GLUT_NORMAL_DAMAGED: return glut_window->damage(); + case GLUT_OVERLAY_DAMAGED: return 1; // kind of works... + default: return 0; + } +} + +int glutDeviceGet(GLenum type) { + switch (type) { + case GLUT_HAS_KEYBOARD : return 1; + case GLUT_HAS_MOUSE : return 1; + case GLUT_NUM_MOUSE_BUTTONS : return 3; + default : return 0; + } +} + +// Get extension function address... +GLUTproc glutGetProcAddress(const char *procName) { +# ifdef WIN32 + return (GLUTproc)wglGetProcAddress((LPCSTR)procName); + +# elif defined(HAVE_DLSYM) && defined(HAVE_DLFCN_H) + char symbol[1024]; + + snprintf(symbol, sizeof(symbol), "_%s", procName); + +# ifdef RTLD_DEFAULT + return (GLUTproc)dlsym(RTLD_DEFAULT, symbol); + +# else // No RTLD_DEFAULT support, so open the current a.out symbols... + static void *rtld_default = 0; + + if (!rtld_default) rtld_default = dlopen(0, RTLD_LAZY); + + if (rtld_default) return (GLUTproc)dlsym(rtld_default, symbol); + else return 0; + +# endif // RTLD_DEFAULT + +# elif defined(HAVE_GLXGETPROCADDRESSARB) + return (GLUTproc)glXGetProcAddressARB((const GLubyte *)procName); + +# else + return (GLUTproc)0; +# endif // WIN32 +} + +// Parse the GL_EXTENSIONS string to see if the named extension is +// supported. +// +// This code was copied from FreeGLUT 2.4.0 which carries the +// following notice: +// +// Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. +int glutExtensionSupported( const char* extension ) +{ + if (!extension || strchr(extension, ' ')) return 0; + + const char *extensions, *start; + const int len = strlen( extension ); + + start = extensions = (const char *) glGetString(GL_EXTENSIONS); + + if (!extensions) return 0; + + for (;;) { + const char *p = strstr(extensions, extension); + if (!p) return 0; /* not found */ + /* check that the match isn't a super string */ + if ((p == start || p[-1] == ' ') && + (p[len] == ' ' || p[len] == 0)) return 1; + /* skip the false match and continue */ + extensions = p + len; + } +} + +// Add a mechanism to handle adding/removing the glut idle function +// without depending on the (deprecated) set_idle method. +void glutIdleFunc(void (*f)()) +{ + // no change + if(glut_idle_func == f) return; + // remove current idle + if(glut_idle_func) fltk3::remove_idle((void (*)(void *))glut_idle_func); + // install new idle func - if one was passed + if(f) fltk3::add_idle((void (*)(void *))f); + // record new idle func - even if it is NULL + glut_idle_func = f; +} // glutIdleFunc + +#endif // HAVE_GL + +// +// End of "$Id: glut_compatability.cxx 8991 2011-08-22 15:21:44Z matt $". +// Added: branches/branch-3.0/src/fltk3gl/glut_font.cxx =================================================================== --- branches/branch-3.0/src/fltk3gl/glut_font.cxx (rev 0) +++ branches/branch-3.0/src/fltk3gl/glut_font.cxx 2011-08-25 22:05:10 UTC (rev 9012) @@ -0,0 +1,198 @@ +// +// "$Id: glut_font.cxx 8991 2011-08-22 15:21:44Z matt $" +// +// GLUT font routines for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2010 by Bill Spitzak and others. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// +// The stroked text code was copied from FreeGLUT 2.4.0 which carries +// the following notice: +// +// Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. +// + +// (sort of) emulation of Glut's bitmap drawing functions, using fltk3's +// font stuff. Not all the fonts match! + +#include <config.h> +#if HAVE_GL +# include <fltk3gl/glut.h> + +Fl_Glut_Bitmap_Font glutBitmap9By15 = {fltk3::SCREEN, 15}; +Fl_Glut_Bitmap_Font glutBitmap8By13 = {fltk3::SCREEN, 13}; +Fl_Glut_Bitmap_Font glutBitmapTimesRoman10 = {fltk3::TIMES, 10}; +Fl_Glut_Bitmap_Font glutBitmapTimesRoman24 = {fltk3::TIMES, 24}; +Fl_Glut_Bitmap_Font glutBitmapHelvetica10 = {fltk3::HELVETICA, 10}; +Fl_Glut_Bitmap_Font glutBitmapHelvetica12 = {fltk3::HELVETICA, 12}; +Fl_Glut_Bitmap_Font glutBitmapHelvetica18 = {fltk3::HELVETICA, 18}; + +void glutBitmapCharacter(void* font, int character) { + gl_font(((Fl_Glut_Bitmap_Font *)font)->font,((Fl_Glut_Bitmap_Font *)font)->size); + char a[1]; a[0] = character; + gl_draw(a,1); +} + +int glutBitmapHeight(void* font) { + gl_font(((Fl_Glut_Bitmap_Font *)font)->font,((Fl_Glut_Bitmap_Font *)font)->size); + return gl_height(); +} + +int glutBitmapLength(void *font, const unsigned char *string) { + gl_font(((Fl_Glut_Bitmap_Font *)font)->font,((Fl_Glut_Bitmap_Font *)font)->size); + const char *s = (const char*)string; + return int(gl_width(s)+.5); +} + +void glutBitmapString(void *font, const unsigned char *string) { + gl_font(((Fl_Glut_Bitmap_Font *)font)->font,((Fl_Glut_Bitmap_Font *)font)->size); + const char *s = (const char*)string; + gl_draw(s); +} + +int glutBitmapWidth(void* font, int character) { + gl_font(((Fl_Glut_Bitmap_Font *)font)->font,((Fl_Glut_Bitmap_Font *)font)->size); + return int(gl_width(character)+.5); +} + + +/* + * Draw a stroke character + */ +void glutStrokeCharacter(void* fontID, int character) { + const Fl_Glut_StrokeChar *schar; + const Fl_Glut_StrokeStrip *strip; + int i, j; + Fl_Glut_StrokeFont* font = (Fl_Glut_StrokeFont *)fontID; + + if (character < 0 || character >= font->Quantity) return; + + schar = font->Characters[character]; + if (!schar) return; + + strip = schar->Strips; + + for (i = 0; i < schar->Number; i++, strip++) + { + glBegin(GL_LINE_STRIP); + for (j = 0; j < strip->Number; j++) + glVertex2f(strip->Vertices[j].X, strip->Vertices[j].Y); + glEnd(); + } + + glTranslatef(schar->Right, 0.0, 0.0); +} + +void glutStrokeString(void* fontID, const unsigned char *string) { + unsigned char c; + int i, j; + float length = 0.0; + Fl_Glut_StrokeFont* font = (Fl_Glut_StrokeFont *)fontID; + + if (!string || ! *string) return; + + /* + * Step through the string, drawing each character. + * A newline will simply translate the next character's insertion + * point back to the start of the line and down one line. + */ + while ((c = *string++) != 0) { + if (c < font->Quantity) { + if (c == '\n') { + glTranslatef(-length, -(float)(font->Height), 0.0); + length = 0.0; + } else { + /* Not an EOL, draw the bitmap character */ + const Fl_Glut_StrokeChar *schar = font->Characters[c]; + if (schar) { + const Fl_Glut_StrokeStrip *strip = schar->Strips; + + for (i = 0; i < schar->Number; i++, strip++) { + glBegin(GL_LINE_STRIP); + for (j = 0; j < strip->Number; j++) + glVertex2f(strip->Vertices[j].X, strip->Vertices[j].Y); + glEnd(); + } + + length += schar->Right; + glTranslatef(schar->Right, 0.0, 0.0); + } + } + } + } +} + +/* + * Return the width in pixels of a stroke character + */ +int glutStrokeWidth( void* fontID, int character ) +{ + const Fl_Glut_StrokeChar *schar; + Fl_Glut_StrokeFont* font = (Fl_Glut_StrokeFont *)fontID; + if (character < 0 || character >= font->Quantity) return 0; + schar = font->Characters[ character ]; + + return schar ? (int)(schar->Right + 0.5) : 0; +} + +/* + * Return the width of a string drawn using a stroke font + */ +int glutStrokeLength(void* fontID, const unsigned char* string) { + unsigned char c; + float length = 0.0; + float this_line_length = 0.0; + Fl_Glut_StrokeFont* font = (Fl_Glut_StrokeFont *)fontID; + + if (!string || ! *string) return 0; + + while ((c = *string++) != 0) { + if (c < font->Quantity) { + if (c == '\n') { + /* EOL; reset the length of this line */ + if (length < this_line_length) length = this_line_length; + this_line_length = 0.0; + } else { + /* Not an EOL, increment the length of this line */ + const Fl_Glut_StrokeChar *schar = font->Characters[c]; + if (schar) this_line_length += schar->Right; + } + } + } + + if (length < this_line_length) length = this_line_length; + + return (int)(length + 0.5); +} + +/* + * Returns the height of a stroke font + */ +GLfloat glutStrokeHeight(void* fontID) { + Fl_Glut_StrokeFont* font = (Fl_Glut_StrokeFont *)fontID; + return font->Height; +} + +#endif // HAVE_GL + +// +// End of "$Id: glut_font.cxx 8991 2011-08-22 15:21:44Z matt $". +// _______________________________________________ fltk-commit mailing list [email protected] http://lists.easysw.com/mailman/listinfo/fltk-commit
