|
|
@ -1,7 +1,7 @@ |
|
|
|
//
|
|
|
|
//
|
|
|
|
// "$Id$"
|
|
|
|
// "$Id$"
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// OpenGL drawing support routines for the Fast Light Tool Kit (FLTK).
|
|
|
|
// OpenGL text drawing support routines for the Fast Light Tool Kit (FLTK).
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// Copyright 1998-2018 by Bill Spitzak and others.
|
|
|
|
// Copyright 1998-2018 by Bill Spitzak and others.
|
|
|
|
//
|
|
|
|
//
|
|
|
@ -19,12 +19,23 @@ |
|
|
|
// Functions from <FL/gl.h>
|
|
|
|
// Functions from <FL/gl.h>
|
|
|
|
// See also Fl_Gl_Window and gl_start.cxx
|
|
|
|
// See also Fl_Gl_Window and gl_start.cxx
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Note about implementing GL text support for a new platform
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1) if the GL_EXT_texture_rectangle (a.k.a. GL_ARB_texture_rectangle) GL extension |
|
|
|
|
|
|
|
is available, no platform-specific code is needed, besides support for fl_draw() and Fl_Image_Surface for the platform. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2) if the GL_EXT_texture_rectangle GL extension is not available, |
|
|
|
|
|
|
|
a rudimentary support through GLUT is obtained without any platform-specific code. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3) A more elaborate support can be obtained implementing |
|
|
|
|
|
|
|
get_list(), gl_bitmap_font() and draw_string_legacy() for the platform's Fl_XXX_Gl_Window_Driver. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
#include "config_lib.h" |
|
|
|
#include "config_lib.h" |
|
|
|
#if defined(FL_PORTING) |
|
|
|
#if defined(FL_PORTING) |
|
|
|
# pragma message "FL_PORTING: implement OpenGL text rendering here" |
|
|
|
# pragma message "FL_PORTING: implement OpenGL text rendering here" |
|
|
|
#endif |
|
|
|
#endif // defined(FL_PORTING)
|
|
|
|
|
|
|
|
|
|
|
|
#include "flstring.h" |
|
|
|
|
|
|
|
#if HAVE_GL || defined(FL_DOXYGEN) |
|
|
|
#if HAVE_GL || defined(FL_DOXYGEN) |
|
|
|
|
|
|
|
|
|
|
|
#include <FL/Fl.H> |
|
|
|
#include <FL/Fl.H> |
|
|
@ -32,25 +43,13 @@ |
|
|
|
#include <FL/gl_draw.H> |
|
|
|
#include <FL/gl_draw.H> |
|
|
|
#include <FL/fl_draw.H> |
|
|
|
#include <FL/fl_draw.H> |
|
|
|
#include <FL/Fl_Gl_Window_Driver.H> |
|
|
|
#include <FL/Fl_Gl_Window_Driver.H> |
|
|
|
|
|
|
|
#include <FL/Fl_Image_Surface.H> |
|
|
|
|
|
|
|
#include <FL/glu.h> // for gluUnProject() |
|
|
|
|
|
|
|
#include <FL/glut.H> // for glutStrokeString() and glutStrokeLength() |
|
|
|
|
|
|
|
|
|
|
|
#if defined(FL_CFG_GFX_QUARTZ) |
|
|
|
#ifndef GL_TEXTURE_RECTANGLE_ARB |
|
|
|
#include "drivers/Quartz/Fl_Font.H" |
|
|
|
# define GL_TEXTURE_RECTANGLE_ARB 0x84F5 |
|
|
|
# define GENLISTSIZE 0 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#elif defined(FL_CFG_GFX_GDI) |
|
|
|
|
|
|
|
#include "drivers/GDI/Fl_Font.H" |
|
|
|
|
|
|
|
#define GENLISTSIZE 0x10000 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#elif defined(FL_CFG_GFX_XLIB) |
|
|
|
|
|
|
|
#include "drivers/Xlib/Fl_Font.H" |
|
|
|
|
|
|
|
#if USE_XFT |
|
|
|
|
|
|
|
# define GENLISTSIZE 256 |
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
# define GENLISTSIZE 0x10000 |
|
|
|
|
|
|
|
#endif // USE_XFT
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endif |
|
|
|
#endif |
|
|
|
#include <FL/fl_utf8.h> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Returns the current font's height */ |
|
|
|
/** Returns the current font's height */ |
|
|
@ -65,43 +64,55 @@ double gl_width(const char* s, int n) {return fl_width(s,n);} |
|
|
|
double gl_width(uchar c) {return fl_width(c);} |
|
|
|
double gl_width(uchar c) {return fl_width(c);} |
|
|
|
|
|
|
|
|
|
|
|
static Fl_Font_Descriptor *gl_fontsize; |
|
|
|
static Fl_Font_Descriptor *gl_fontsize; |
|
|
|
|
|
|
|
static int has_texture_rectangle = 0; // true means GL_EXT_texture_rectangle is available
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
extern float gl_start_scale; // in gl_start.cxx
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
Sets the current OpenGL font to the same font as calling fl_font() |
|
|
|
Sets the current OpenGL font to the same font as calling fl_font(). |
|
|
|
|
|
|
|
\see Fl::draw_GL_text_with_textures(int val) |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
void gl_font(int fontid, int size) { |
|
|
|
void gl_font(int fontid, int size) { |
|
|
|
|
|
|
|
static bool once = true; |
|
|
|
|
|
|
|
if (once) { |
|
|
|
|
|
|
|
once = false; |
|
|
|
|
|
|
|
if (Fl::draw_GL_text_with_textures()) { |
|
|
|
|
|
|
|
// For the font texture pile to work, we need a texture rectangle extension, so check for
|
|
|
|
|
|
|
|
// one here. First we check for GL_EXT_texture_rectangle and if that fails we try
|
|
|
|
|
|
|
|
// for GL_ARB_texture_rectangle instead. If that also fails, we fall back to the
|
|
|
|
|
|
|
|
// legacy methods used by fltk-1.3 and earlier.
|
|
|
|
|
|
|
|
has_texture_rectangle = (strstr((const char*)glGetString(GL_EXTENSIONS), "GL_EXT_texture_rectangle") != NULL); |
|
|
|
|
|
|
|
if (!has_texture_rectangle) has_texture_rectangle = |
|
|
|
|
|
|
|
(strstr((const char*)glGetString(GL_EXTENSIONS), "GL_ARB_texture_rectangle") != NULL); |
|
|
|
|
|
|
|
Fl::draw_GL_text_with_textures(has_texture_rectangle); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
fl_font(fontid, size); |
|
|
|
fl_font(fontid, size); |
|
|
|
Fl_Font_Descriptor *fl_fontsize = fl_graphics_driver->font_descriptor(); |
|
|
|
Fl_Font_Descriptor *fl_fontsize = fl_graphics_driver->font_descriptor(); |
|
|
|
Fl_Gl_Window_Driver::global()->gl_bitmap_font(fl_fontsize); |
|
|
|
if (!has_texture_rectangle) Fl_Gl_Window_Driver::global()->gl_bitmap_font(fl_fontsize); |
|
|
|
gl_fontsize = fl_fontsize; |
|
|
|
gl_fontsize = fl_fontsize; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#if defined(FL_CFG_GFX_QUARTZ) || defined(FL_CFG_GFX_GDI) || defined(FL_CFG_GFX_XLIB) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void gl_remove_displaylist_fonts() |
|
|
|
void gl_remove_displaylist_fonts() |
|
|
|
{ |
|
|
|
{ |
|
|
|
# if HAVE_GL |
|
|
|
|
|
|
|
// clear variables used mostly in fl_font
|
|
|
|
// clear variables used mostly in fl_font
|
|
|
|
fl_graphics_driver->font(0, 0); |
|
|
|
fl_graphics_driver->font(0, 0); |
|
|
|
|
|
|
|
|
|
|
|
for (int j = 0 ; j < FL_FREE_FONT ; ++j) |
|
|
|
for (int j = 0 ; j < FL_FREE_FONT ; ++j) |
|
|
|
{ |
|
|
|
{ |
|
|
|
Fl_Font_Descriptor* past = 0; |
|
|
|
Fl_Font_Descriptor* past = 0; |
|
|
|
Fl_Fontdesc* s = fl_fonts + j ; |
|
|
|
Fl_Font_Descriptor** s_first = Fl_Gl_Window_Driver::global()->fontnum_to_fontdescriptor(j); |
|
|
|
Fl_Font_Descriptor* f = s->first; |
|
|
|
Fl_Font_Descriptor* f = *s_first; |
|
|
|
while (f != 0) { |
|
|
|
while (f != 0) { |
|
|
|
if(f->listbase) { |
|
|
|
if(f->listbase) { |
|
|
|
if(f == s->first) { |
|
|
|
if(f == *s_first) { |
|
|
|
s->first = f->next; |
|
|
|
*s_first = f->next; |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
else { |
|
|
|
past->next = f->next; |
|
|
|
past->next = f->next; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// It would be nice if this next line was in a destructor somewhere
|
|
|
|
// It would be nice if this next line was in a destructor somewhere
|
|
|
|
glDeleteLists(f->listbase, GENLISTSIZE); |
|
|
|
glDeleteLists(f->listbase, Fl_Gl_Window_Driver::global()->genlistsize()); |
|
|
|
|
|
|
|
|
|
|
|
Fl_Font_Descriptor* tmp = f; |
|
|
|
Fl_Font_Descriptor* tmp = f; |
|
|
|
f = f->next; |
|
|
|
f = f->next; |
|
|
|
delete tmp; |
|
|
|
delete tmp; |
|
|
@ -112,44 +123,22 @@ void gl_remove_displaylist_fonts() |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
#endif // HAVE_GL
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
Draws an array of n characters of the string in the current font |
|
|
|
Draws an array of n characters of the string in the current font at the current position. |
|
|
|
at the current position. |
|
|
|
\see gl_texture_pile_height(int) |
|
|
|
\see On the Mac OS X platform, see gl_texture_pile_height(int) |
|
|
|
|
|
|
|
*/ |
|
|
|
*/ |
|
|
|
void gl_draw(const char* str, int n) { |
|
|
|
void gl_draw(const char* str, int n) { |
|
|
|
Fl_Gl_Window_Driver::global()->draw_string(str, n); |
|
|
|
if (has_texture_rectangle) Fl_Gl_Window_Driver::draw_string_with_texture(str, n); |
|
|
|
|
|
|
|
else Fl_Gl_Window_Driver::global()->draw_string_legacy(str, n); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void Fl_Gl_Window_Driver::draw_string(const char* str, int n) { |
|
|
|
|
|
|
|
static unsigned short *buf = NULL; |
|
|
|
|
|
|
|
static int l = 0; |
|
|
|
|
|
|
|
int wn = fl_utf8toUtf16(str, n, (unsigned short*)buf, l); |
|
|
|
|
|
|
|
if(wn >= l) { |
|
|
|
|
|
|
|
buf = (unsigned short*) realloc(buf, sizeof(unsigned short) * (wn + 1)); |
|
|
|
|
|
|
|
l = wn + 1; |
|
|
|
|
|
|
|
wn = fl_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);
|
|
|
|
|
|
|
|
this->get_list(gl_fontsize, r); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
glCallLists(n, GL_UNSIGNED_SHORT, buf); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
Draws n characters of the string in the current font at the given position |
|
|
|
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) |
|
|
|
\see gl_texture_pile_height(int) |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
void gl_draw(const char* str, int n, int x, int y) { |
|
|
|
void gl_draw(const char* str, int n, int x, int y) { |
|
|
|
glRasterPos2i(x, y); |
|
|
|
glRasterPos2i(x, y); |
|
|
@ -158,7 +147,7 @@ void gl_draw(const char* str, int n, int x, int y) { |
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
Draws n characters of the string in the current font at the given position |
|
|
|
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) |
|
|
|
\see gl_texture_pile_height(int) |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
void gl_draw(const char* str, int n, float x, float y) { |
|
|
|
void gl_draw(const char* str, int n, float x, float y) { |
|
|
|
glRasterPos2f(x, y); |
|
|
|
glRasterPos2f(x, y); |
|
|
@ -167,7 +156,7 @@ void gl_draw(const char* str, int n, float x, float y) { |
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
Draws a nul-terminated string in the current font at the current position |
|
|
|
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) |
|
|
|
\see gl_texture_pile_height(int) |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
void gl_draw(const char* str) { |
|
|
|
void gl_draw(const char* str) { |
|
|
|
gl_draw(str, strlen(str)); |
|
|
|
gl_draw(str, strlen(str)); |
|
|
@ -175,7 +164,7 @@ void gl_draw(const char* str) { |
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
Draws a nul-terminated string in the current font at the given position |
|
|
|
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) |
|
|
|
\see gl_texture_pile_height(int) |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
void gl_draw(const char* str, int x, int y) { |
|
|
|
void gl_draw(const char* str, int x, int y) { |
|
|
|
gl_draw(str, strlen(str), x, y); |
|
|
|
gl_draw(str, strlen(str), x, y); |
|
|
@ -183,7 +172,7 @@ void gl_draw(const char* str, int x, int y) { |
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
Draws a nul-terminated string in the current font at the given position |
|
|
|
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) |
|
|
|
\see gl_texture_pile_height(int) |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
void gl_draw(const char* str, float x, float y) { |
|
|
|
void gl_draw(const char* str, float x, float y) { |
|
|
|
gl_draw(str, strlen(str), x, y); |
|
|
|
gl_draw(str, strlen(str), x, y); |
|
|
@ -229,6 +218,13 @@ void gl_rect(int x, int y, int w, int h) { |
|
|
|
glEnd(); |
|
|
|
glEnd(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
Sets the curent OpenGL color to an FLTK color. |
|
|
|
Sets the curent OpenGL color to an FLTK color. |
|
|
@ -244,155 +240,29 @@ void gl_color(Fl_Color i) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if defined(FL_CFG_GFX_XLIB) |
|
|
|
#if ! defined(FL_DOXYGEN) // do not want too much of the gl_texture_fifo internals in the documentation
|
|
|
|
#include <FL/platform.H> |
|
|
|
|
|
|
|
#include <GL/glx.h> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Fl_X11_Gl_Window_Driver::gl_bitmap_font(Fl_Font_Descriptor *fl_fontsize) { |
|
|
|
|
|
|
|
if (!fl_fontsize->listbase) { |
|
|
|
|
|
|
|
#if !USE_XFT |
|
|
|
|
|
|
|
fl_fontsize->listbase = glGenLists(GENLISTSIZE); |
|
|
|
|
|
|
|
#else // Fltk-1.1.8 style GL font selection
|
|
|
|
|
|
|
|
// 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.value(); |
|
|
|
|
|
|
|
int base = font->min_char_or_byte2; |
|
|
|
|
|
|
|
int count = font->max_char_or_byte2-base+1; |
|
|
|
|
|
|
|
fl_fontsize->listbase = glGenLists(GENLISTSIZE); |
|
|
|
|
|
|
|
glXUseXFont(font->fid, base, count, fl_fontsize->listbase+base); |
|
|
|
|
|
|
|
#endif // !USE_XFT
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
glListBase(fl_fontsize->listbase); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Fl_X11_Gl_Window_Driver::get_list(Fl_Font_Descriptor *gl_fd, int r) { |
|
|
|
|
|
|
|
if (gl_fd->glok[r]) return; |
|
|
|
|
|
|
|
gl_fd->glok[r] = 1; |
|
|
|
|
|
|
|
# if USE_XFT |
|
|
|
|
|
|
|
// FIXME
|
|
|
|
|
|
|
|
# else |
|
|
|
|
|
|
|
unsigned int ii = r * 0x400; |
|
|
|
|
|
|
|
for (int i = 0; i < 0x400; i++) { |
|
|
|
|
|
|
|
XFontStruct *font = NULL; |
|
|
|
|
|
|
|
unsigned short id; |
|
|
|
|
|
|
|
fl_XGetUtf8FontAndGlyph(gl_fd->font, ii, &font, &id); |
|
|
|
|
|
|
|
if (font) glXUseXFont(font->fid, id, 1, gl_fd->listbase+ii); |
|
|
|
|
|
|
|
ii++; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
# endif |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if HAVE_GL_OVERLAY |
|
|
|
|
|
|
|
extern uchar fl_overlay; |
|
|
|
|
|
|
|
int Fl_X11_Gl_Window_Driver::overlay_color(Fl_Color i) { |
|
|
|
|
|
|
|
if (fl_overlay) {glIndexi(int(fl_xpixel(i))); return 1;} |
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
#endif // HAVE_GL_OVERLAY
|
|
|
|
|
|
|
|
#endif // FL_CFG_GFX_XLIB
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if defined(FL_CFG_GFX_GDI) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Fl_WinAPI_Gl_Window_Driver::gl_bitmap_font(Fl_Font_Descriptor *fl_fontsize) { |
|
|
|
|
|
|
|
if (!fl_fontsize->listbase) { |
|
|
|
|
|
|
|
fl_fontsize->listbase = glGenLists(GENLISTSIZE); |
|
|
|
|
|
|
|
/* old, unused WIN32 code
|
|
|
|
|
|
|
|
int base = fl_fontsize->metr.tmFirstChar; |
|
|
|
|
|
|
|
int count = fl_fontsize->metr.tmLastChar-base+1; |
|
|
|
|
|
|
|
HFONT oldFid = (HFONT)SelectObject((HDC)fl_graphics_driver->gc(), fl_fontsize->fid); |
|
|
|
|
|
|
|
fl_fontsize->listbase = glGenLists(256); |
|
|
|
|
|
|
|
wglUseFontBitmaps((HDC)fl_graphics_driver->gc(), base, count, fl_fontsize->listbase+base); |
|
|
|
|
|
|
|
SelectObject((HDC)fl_graphics_driver->gc(), oldFid); |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
glListBase(fl_fontsize->listbase); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Fl_WinAPI_Gl_Window_Driver::get_list(Fl_Font_Descriptor *gl_fd, int r) { |
|
|
|
|
|
|
|
if (gl_fd->glok[r]) return; |
|
|
|
|
|
|
|
gl_fd->glok[r] = 1; |
|
|
|
|
|
|
|
unsigned int ii = r * 0x400; |
|
|
|
|
|
|
|
HFONT oldFid = (HFONT)SelectObject((HDC)fl_graphics_driver->gc(), gl_fd->fid); |
|
|
|
|
|
|
|
wglUseFontBitmapsW((HDC)fl_graphics_driver->gc(), ii, ii + 0x03ff, gl_fd->listbase+ii); |
|
|
|
|
|
|
|
SelectObject((HDC)fl_graphics_driver->gc(), oldFid); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if HAVE_GL_OVERLAY |
|
|
|
|
|
|
|
extern uchar fl_overlay; |
|
|
|
|
|
|
|
extern int fl_overlay_depth; |
|
|
|
|
|
|
|
int Fl_WinAPI_Gl_Window_Driver::overlay_color(Fl_Color i) { |
|
|
|
|
|
|
|
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 : FL_GRAY_RAMP); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return 1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
#endif // HAVE_GL_OVERLAY
|
|
|
|
|
|
|
|
#endif // FL_CFG_GFX_GDI
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void gl_draw_image(const uchar* b, int x, int y, int w, int h, int d, int ld) { |
|
|
|
/* Implement the gl_texture_fifo mechanism:
|
|
|
|
if (!ld) ld = w*d; |
|
|
|
Strings to be drawn are memorized in a fifo pile (which max size can |
|
|
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, ld/d); |
|
|
|
be increased calling gl_texture_pile_height(int)). |
|
|
|
glRasterPos2i(x,y); |
|
|
|
Each pile element contains the string, the font, the GUI scale, and |
|
|
|
glDrawPixels(w,h,d<4?GL_RGB:GL_RGBA,GL_UNSIGNED_BYTE,(const ulong*)b); |
|
|
|
an image of the string in the form of a GL texture. |
|
|
|
} |
|
|
|
Strings are drawn in 2 steps: |
|
|
|
|
|
|
|
1) compute the texture for that string if it was not computed before; |
|
|
|
|
|
|
|
2) draw the texture using the current GL color. |
|
|
|
#if defined(FL_CFG_GFX_QUARTZ) || defined(FL_DOXYGEN) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if ! defined(FL_DOXYGEN) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <FL/platform.H> |
|
|
|
|
|
|
|
#if !defined(kCGBitmapByteOrder32Host) // doc says available 10.4 but some 10.4 don't have it
|
|
|
|
|
|
|
|
# define kCGBitmapByteOrder32Host 0 |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_4 |
|
|
|
|
|
|
|
# include <OpenGL/glext.h> |
|
|
|
|
|
|
|
# define GL_TEXTURE_RECTANGLE_ARB GL_TEXTURE_RECTANGLE_EXT |
|
|
|
|
|
|
|
#endif // MAC_OS_X_VERSION_MAX_ALLOWED
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Text drawing to an OpenGL scene under Mac OS X is implemented using textures, as recommended by Apple.
|
|
|
|
|
|
|
|
This allows to use any font at any size, and any Unicode character. |
|
|
|
|
|
|
|
Some old Apple hardware doesn't implement the required GL_EXT_texture_rectangle extension. |
|
|
|
|
|
|
|
For these, glutStrokeString() is used to draw text. In that case, it's possible to vary text size, |
|
|
|
|
|
|
|
but not text font, and only ASCII characters can be drawn. |
|
|
|
|
|
|
|
*/ |
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
static float gl_scale = 1; // set to 2 for high resolution Fl_Gl_Window
|
|
|
|
static float gl_scale = 1; // scaling factor between FLTK and GL drawing units: GL = FLTK * gl_scale
|
|
|
|
static int has_texture_rectangle = 0; // true means GL_EXT_texture_rectangle is available
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <FL/glu.h> // for gluUnProject() and gluCheckExtension() |
|
|
|
|
|
|
|
#include <FL/glut.H> // for glutStrokeString() and glutStrokeLength() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// manages a fifo pile of pre-computed string textures
|
|
|
|
// manages a fifo pile of pre-computed string textures
|
|
|
|
class gl_texture_fifo { |
|
|
|
class gl_texture_fifo { |
|
|
|
friend class Fl_Cocoa_Gl_Window_Driver; |
|
|
|
friend class Fl_Gl_Window_Driver; |
|
|
|
private: |
|
|
|
private: |
|
|
|
typedef struct { // information for a pre-computed texture
|
|
|
|
typedef struct { // information for a pre-computed texture
|
|
|
|
GLuint texName; // its name
|
|
|
|
GLuint texName; // its name
|
|
|
|
char *utf8; //its text
|
|
|
|
char *utf8; //its text
|
|
|
|
Fl_Font_Descriptor *fdesc; // its font
|
|
|
|
Fl_Font_Descriptor *fdesc; // its font
|
|
|
|
float ratio; // used without rectangle texture
|
|
|
|
float scale; // scaling factor of the GUI
|
|
|
|
int scale; // 1 or 2 for low/high resolution
|
|
|
|
|
|
|
|
} data; |
|
|
|
} data; |
|
|
|
data *fifo; // array of pile elements
|
|
|
|
data *fifo; // array of pile elements
|
|
|
|
int size_; // pile height
|
|
|
|
int size_; // pile height
|
|
|
@ -425,6 +295,30 @@ gl_texture_fifo::~gl_texture_fifo() |
|
|
|
free(fifo); |
|
|
|
free(fifo); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 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) && (fifo[rank].scale == gl_scale) ) { |
|
|
|
|
|
|
|
return rank; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return -1; // means no texture exists yet for that string
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static gl_texture_fifo *gl_fifo = NULL; // points to the texture pile class instance
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void gl_texture_reset() |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (gl_fifo) gl_texture_pile_height(gl_texture_pile_height()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Cross-platform implementation of the texture mechanism for text rendering
|
|
|
|
|
|
|
|
// using textures with the alpha channel only.
|
|
|
|
|
|
|
|
|
|
|
|
// displays a pre-computed texture on the GL scene
|
|
|
|
// displays a pre-computed texture on the GL scene
|
|
|
|
void gl_texture_fifo::display_texture(int rank) |
|
|
|
void gl_texture_fifo::display_texture(int rank) |
|
|
|
{ |
|
|
|
{ |
|
|
@ -443,43 +337,36 @@ void gl_texture_fifo::display_texture(int rank) |
|
|
|
glPushAttrib(GL_ENABLE_BIT | GL_TEXTURE_BIT | GL_COLOR_BUFFER_BIT); |
|
|
|
glPushAttrib(GL_ENABLE_BIT | GL_TEXTURE_BIT | GL_COLOR_BUFFER_BIT); |
|
|
|
glDisable (GL_DEPTH_TEST); // ensure text is not removed by depth buffer test.
|
|
|
|
glDisable (GL_DEPTH_TEST); // ensure text is not removed by depth buffer test.
|
|
|
|
glEnable (GL_BLEND); // for text fading
|
|
|
|
glEnable (GL_BLEND); // for text fading
|
|
|
|
glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA); // ditto
|
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
|
|
|
glDisable(GL_LIGHTING); |
|
|
|
glDisable(GL_LIGHTING); |
|
|
|
GLfloat pos[4]; |
|
|
|
GLfloat pos[4]; |
|
|
|
glGetFloatv(GL_CURRENT_RASTER_POSITION, pos); |
|
|
|
glGetFloatv(GL_CURRENT_RASTER_POSITION, pos); |
|
|
|
float R = 2; |
|
|
|
if (gl_start_scale != 1) { // using gl_start() / gl_finish()
|
|
|
|
if (!has_texture_rectangle) { |
|
|
|
pos[0] /= gl_start_scale; |
|
|
|
R *= fifo[rank].ratio; |
|
|
|
pos[1] /= gl_start_scale; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
float R = 2; |
|
|
|
glScalef (R/winw, R/winh, 1.0f); |
|
|
|
glScalef (R/winw, R/winh, 1.0f); |
|
|
|
glTranslatef (-winw/R, -winh/R, 0.0f); |
|
|
|
glTranslatef (-winw/R, -winh/R, 0.0f); |
|
|
|
GLint width; |
|
|
|
|
|
|
|
if (has_texture_rectangle) { |
|
|
|
|
|
|
|
glEnable (GL_TEXTURE_RECTANGLE_ARB); |
|
|
|
glEnable (GL_TEXTURE_RECTANGLE_ARB); |
|
|
|
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, fifo[rank].texName); |
|
|
|
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, fifo[rank].texName); |
|
|
|
GLint height; |
|
|
|
GLint width, height; |
|
|
|
glGetTexLevelParameteriv(GL_TEXTURE_RECTANGLE_ARB, 0, GL_TEXTURE_WIDTH, &width); |
|
|
|
glGetTexLevelParameteriv(GL_TEXTURE_RECTANGLE_ARB, 0, GL_TEXTURE_WIDTH, &width); |
|
|
|
glGetTexLevelParameteriv(GL_TEXTURE_RECTANGLE_ARB, 0, GL_TEXTURE_HEIGHT, &height); |
|
|
|
glGetTexLevelParameteriv(GL_TEXTURE_RECTANGLE_ARB, 0, GL_TEXTURE_HEIGHT, &height); |
|
|
|
CGRect bounds = CGRectMake (pos[0], pos[1] - gl_scale*fl_descent(), width, height); |
|
|
|
|
|
|
|
//write the texture on screen
|
|
|
|
//write the texture on screen
|
|
|
|
glBegin (GL_QUADS); |
|
|
|
glBegin (GL_QUADS); |
|
|
|
|
|
|
|
float ox = pos[0]; |
|
|
|
|
|
|
|
float oy = pos[1] + height - gl_scale * fl_descent(); |
|
|
|
glTexCoord2f (0.0f, 0.0f); // draw lower left in world coordinates
|
|
|
|
glTexCoord2f (0.0f, 0.0f); // draw lower left in world coordinates
|
|
|
|
glVertex2f (bounds.origin.x, bounds.origin.y); |
|
|
|
glVertex2f (ox, oy); |
|
|
|
|
|
|
|
|
|
|
|
glTexCoord2f (0.0f, height); // draw upper left in world coordinates
|
|
|
|
glTexCoord2f (0.0f, height); // draw upper left in world coordinates
|
|
|
|
glVertex2f (bounds.origin.x, bounds.origin.y + bounds.size.height); |
|
|
|
glVertex2f (ox, oy - height); |
|
|
|
|
|
|
|
|
|
|
|
glTexCoord2f (width, height); // draw upper right in world coordinates
|
|
|
|
glTexCoord2f (width, height); // draw upper right in world coordinates
|
|
|
|
glVertex2f (bounds.origin.x + bounds.size.width, bounds.origin.y + bounds.size.height); |
|
|
|
glVertex2f (ox + width, oy - height); |
|
|
|
|
|
|
|
|
|
|
|
glTexCoord2f (width, 0.0f); // draw lower right in world coordinates
|
|
|
|
glTexCoord2f (width, 0.0f); // draw lower right in world coordinates
|
|
|
|
glVertex2f (bounds.origin.x + bounds.size.width, bounds.origin.y); |
|
|
|
glVertex2f (ox + width, oy); |
|
|
|
glEnd (); |
|
|
|
glEnd (); |
|
|
|
} else { |
|
|
|
|
|
|
|
glTranslatef(pos[0]*2/R, pos[1]*2/R, 0.0); |
|
|
|
|
|
|
|
glutStrokeString(GLUT_STROKE_ROMAN, (uchar*)fifo[rank].utf8); |
|
|
|
|
|
|
|
width = fl_width(fifo[rank].utf8); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
glPopAttrib(); |
|
|
|
glPopAttrib(); |
|
|
|
|
|
|
|
|
|
|
|
// reset original matrices
|
|
|
|
// reset original matrices
|
|
|
@ -498,14 +385,18 @@ void gl_texture_fifo::display_texture(int rank) |
|
|
|
GLint viewport[4]; |
|
|
|
GLint viewport[4]; |
|
|
|
glGetIntegerv (GL_VIEWPORT, viewport); |
|
|
|
glGetIntegerv (GL_VIEWPORT, viewport); |
|
|
|
gluUnProject(pos[0], pos[1], pos[2], modelmat, projmat, viewport, &objX, &objY, &objZ); |
|
|
|
gluUnProject(pos[0], pos[1], pos[2], modelmat, projmat, viewport, &objX, &objY, &objZ); |
|
|
|
glRasterPos2d(objX, objY); |
|
|
|
|
|
|
|
|
|
|
|
if (gl_start_scale != 1) { // using gl_start() / gl_finish()
|
|
|
|
|
|
|
|
objX *= gl_start_scale; |
|
|
|
|
|
|
|
objY *= gl_start_scale; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
glRasterPos2d(objX, objY); |
|
|
|
|
|
|
|
} // display_texture
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// pre-computes a string texture
|
|
|
|
// pre-computes a string texture
|
|
|
|
int gl_texture_fifo::compute_texture(const char* str, int n) |
|
|
|
int gl_texture_fifo::compute_texture(const char* str, int n) |
|
|
|
{ |
|
|
|
{ |
|
|
|
Fl_Graphics_Driver *prev_driver = fl_graphics_driver; |
|
|
|
|
|
|
|
fl_graphics_driver = Fl_Display_Device::display_device()->driver(); |
|
|
|
|
|
|
|
current = (current + 1) % size_; |
|
|
|
current = (current + 1) % size_; |
|
|
|
if (current > last) last = current; |
|
|
|
if (current > last) last = current; |
|
|
|
if ( fifo[current].utf8 ) free(fifo[current].utf8); |
|
|
|
if ( fifo[current].utf8 ) free(fifo[current].utf8); |
|
|
@ -515,114 +406,390 @@ int gl_texture_fifo::compute_texture(const char* str, int n) |
|
|
|
fl_graphics_driver->font_descriptor(gl_fontsize); |
|
|
|
fl_graphics_driver->font_descriptor(gl_fontsize); |
|
|
|
int w, h; |
|
|
|
int w, h; |
|
|
|
w = fl_width(fifo[current].utf8, n) * gl_scale; |
|
|
|
w = fl_width(fifo[current].utf8, n) * gl_scale; |
|
|
|
|
|
|
|
// Hack - make w be aligned
|
|
|
|
|
|
|
|
w = (w + 3) & 0xFFFFFFC; |
|
|
|
h = fl_height() * gl_scale; |
|
|
|
h = fl_height() * gl_scale; |
|
|
|
|
|
|
|
|
|
|
|
fifo[current].scale = gl_scale; |
|
|
|
fifo[current].scale = gl_scale; |
|
|
|
fifo[current].fdesc = gl_fontsize; |
|
|
|
fifo[current].fdesc = gl_fontsize; |
|
|
|
if (has_texture_rectangle) { |
|
|
|
char *txt_buf = Fl_Gl_Window_Driver::global()->alpha_mask_for_string(str, n, w, h); |
|
|
|
//write str to a bitmap just big enough
|
|
|
|
|
|
|
|
CGColorSpaceRef lut = CGColorSpaceCreateDeviceRGB(); |
|
|
|
// put the bitmap in an alpha-component-only texture
|
|
|
|
void *base = NULL; |
|
|
|
|
|
|
|
if (fl_mac_os_version < 100600) base = calloc(4*w, h); |
|
|
|
|
|
|
|
void* save_gc = fl_graphics_driver->gc(); |
|
|
|
|
|
|
|
CGContextRef gc = CGBitmapContextCreate(base, w, h, 8, w*4, lut, |
|
|
|
|
|
|
|
(CGBitmapInfo)(kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host)); |
|
|
|
|
|
|
|
fl_graphics_driver->gc(gc); |
|
|
|
|
|
|
|
CGColorSpaceRelease(lut); |
|
|
|
|
|
|
|
GLfloat colors[4]; |
|
|
|
|
|
|
|
glGetFloatv(GL_CURRENT_COLOR, colors); |
|
|
|
|
|
|
|
fl_color((uchar)(colors[0]*255), (uchar)(colors[1]*255), (uchar)(colors[2]*255)); |
|
|
|
|
|
|
|
CGContextTranslateCTM(gc, 0, h - gl_scale*fl_descent()); |
|
|
|
|
|
|
|
CGContextScaleCTM(gc, gl_scale, gl_scale); |
|
|
|
|
|
|
|
fl_draw(str, n, 0, 0); |
|
|
|
|
|
|
|
//put this bitmap in a texture
|
|
|
|
|
|
|
|
glPushAttrib(GL_TEXTURE_BIT); |
|
|
|
glPushAttrib(GL_TEXTURE_BIT); |
|
|
|
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, fifo[current].texName); |
|
|
|
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, fifo[current].texName); |
|
|
|
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
|
|
|
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
|
|
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, w); |
|
|
|
//glPixelStorei(GL_UNPACK_ROW_LENGTH, w);
|
|
|
|
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, w, h, 0, GL_BGRA_EXT, GL_UNSIGNED_INT_8_8_8_8_REV, CGBitmapContextGetData(gc)); |
|
|
|
// GL_ALPHA8 is defined in GL/gl.h of X11 and of MinGW32 and of MinGW64 and of OpenGL.framework for MacOS
|
|
|
|
|
|
|
|
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_ALPHA8, w, h, 0, GL_ALPHA, GL_UNSIGNED_BYTE, txt_buf); |
|
|
|
|
|
|
|
/* For the record: texture construction if an alpha-only-texture is not possible
|
|
|
|
|
|
|
|
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, w, h, 0, GL_BGRA_EXT, GL_UNSIGNED_INT_8_8_8_8_REV, rgba_buf); |
|
|
|
|
|
|
|
and also, replace GL_SRC_ALPHA by GL_ONE in glBlendFunc() call of display_texture() |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
delete[] txt_buf; // free the buffer now we have copied it into the Gl texture
|
|
|
|
glPopAttrib(); |
|
|
|
glPopAttrib(); |
|
|
|
CGContextRelease(gc); |
|
|
|
|
|
|
|
fl_graphics_driver->gc(save_gc); |
|
|
|
|
|
|
|
if (base) free(base); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
fifo[current].ratio = float(w)/glutStrokeLength(GLUT_STROKE_ROMAN, (uchar*)fifo[current].utf8); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
fl_graphics_driver = prev_driver; |
|
|
|
|
|
|
|
return current; |
|
|
|
return current; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// returns rank of pre-computed texture for a string if it exists
|
|
|
|
#endif // ! defined(FL_DOXYGEN)
|
|
|
|
int gl_texture_fifo::already_known(const char *str, int n) |
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
Returns the current maximum height of the pile of pre-computed string textures. |
|
|
|
|
|
|
|
The default value is 100 |
|
|
|
|
|
|
|
\see Fl::draw_GL_text_with_textures(int) |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
int gl_texture_pile_height(void) |
|
|
|
{ |
|
|
|
{ |
|
|
|
int rank; |
|
|
|
if (! gl_fifo) gl_fifo = new gl_texture_fifo(); |
|
|
|
for ( rank = 0; rank <= last; rank++) { |
|
|
|
return gl_fifo->size(); |
|
|
|
if ( memcmp(str, fifo[rank].utf8, n) == 0 && fifo[rank].utf8[n] == 0 && |
|
|
|
} |
|
|
|
fifo[rank].fdesc == gl_fontsize && fifo[rank].scale == gl_scale) return rank; |
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
Changes the maximum 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 Maximum height of the texture pile |
|
|
|
|
|
|
|
\see Fl::draw_GL_text_with_textures(int) |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
void gl_texture_pile_height(int max) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (gl_fifo) delete gl_fifo; |
|
|
|
|
|
|
|
gl_fifo = new gl_texture_fifo(max); |
|
|
|
} |
|
|
|
} |
|
|
|
return -1; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Fl_Gl_Window_Driver::draw_string_legacy(const char* str, int n) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
draw_string_legacy_glut(str, n); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static gl_texture_fifo *gl_fifo = NULL; // points to the texture pile class instance
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// draws a utf8 string using pre-computed texture if available
|
|
|
|
/** draws a utf8 string using an OpenGL texture */ |
|
|
|
void Fl_Cocoa_Gl_Window_Driver::draw_string(const char* str, int n) |
|
|
|
void Fl_Gl_Window_Driver::draw_string_with_texture(const char* str, int n) |
|
|
|
{ |
|
|
|
{ |
|
|
|
Fl_Gl_Window *gwin = Fl_Window::current()->as_gl_window(); |
|
|
|
Fl_Gl_Window *gwin = Fl_Window::current()->as_gl_window(); |
|
|
|
gl_scale = (gwin ? gwin->pixels_per_unit() : 1); |
|
|
|
gl_scale = (gwin ? gwin->pixels_per_unit() : 1); |
|
|
|
|
|
|
|
|
|
|
|
//fprintf(stderr,"gl_scale=%d\n",gl_scale);
|
|
|
|
|
|
|
|
if (!gl_fifo) gl_fifo = new gl_texture_fifo(); |
|
|
|
if (!gl_fifo) gl_fifo = new gl_texture_fifo(); |
|
|
|
if (!gl_fifo->textures_generated) { |
|
|
|
if (!gl_fifo->textures_generated) { |
|
|
|
has_texture_rectangle = gluCheckExtension((GLubyte*)"GL_EXT_texture_rectangle", glGetString(GL_EXTENSIONS)); |
|
|
|
|
|
|
|
if (has_texture_rectangle) for (int i = 0; i < gl_fifo->size_; i++) glGenTextures(1, &(gl_fifo->fifo[i].texName)); |
|
|
|
if (has_texture_rectangle) for (int i = 0; i < gl_fifo->size_; i++) glGenTextures(1, &(gl_fifo->fifo[i].texName)); |
|
|
|
gl_fifo->textures_generated = 1; |
|
|
|
gl_fifo->textures_generated = 1; |
|
|
|
} |
|
|
|
} |
|
|
|
int rank = gl_fifo->already_known(str, n); |
|
|
|
int index = gl_fifo->already_known(str, n); |
|
|
|
if (rank == -1) { |
|
|
|
if (index == -1) { |
|
|
|
rank = gl_fifo->compute_texture(str, n); |
|
|
|
index = gl_fifo->compute_texture(str, n); |
|
|
|
} |
|
|
|
} |
|
|
|
gl_fifo->display_texture(rank); |
|
|
|
gl_fifo->display_texture(index); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void gl_texture_reset() |
|
|
|
|
|
|
|
|
|
|
|
char *Fl_Gl_Window_Driver::alpha_mask_for_string(const char *str, int n, int w, int h) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (gl_fifo) gl_texture_pile_height(gl_texture_pile_height()); |
|
|
|
// write str to a bitmap that is just big enough
|
|
|
|
|
|
|
|
// create an Fl_Image_Surface object
|
|
|
|
|
|
|
|
Fl_Image_Surface *image_surface = new Fl_Image_Surface(w, h); |
|
|
|
|
|
|
|
Fl_Font fnt = fl_font(); // get the current font
|
|
|
|
|
|
|
|
// direct all further graphics requests to the image
|
|
|
|
|
|
|
|
Fl_Surface_Device::push_current(image_surface); |
|
|
|
|
|
|
|
// fill the background with black, which we will interpret as transparent
|
|
|
|
|
|
|
|
fl_color(0,0,0); |
|
|
|
|
|
|
|
fl_rectf(0, 0, w, h); |
|
|
|
|
|
|
|
// set up the text colour as white, which we will interpret as opaque
|
|
|
|
|
|
|
|
fl_color(255,255,255); |
|
|
|
|
|
|
|
// Fix the font scaling
|
|
|
|
|
|
|
|
fl_font (fnt, gl_fontsize->size); // resize "fltk" font to current GL view scaling
|
|
|
|
|
|
|
|
int desc = fl_descent(); |
|
|
|
|
|
|
|
// Render the text to the buffer
|
|
|
|
|
|
|
|
fl_draw(str, n, 0, h - desc); |
|
|
|
|
|
|
|
// get the resulting image
|
|
|
|
|
|
|
|
Fl_RGB_Image* image = image_surface->image(); |
|
|
|
|
|
|
|
// direct graphics requests back to previous state
|
|
|
|
|
|
|
|
Fl_Surface_Device::pop_current(); |
|
|
|
|
|
|
|
delete image_surface; |
|
|
|
|
|
|
|
// This gives us an RGB rendering of the text. We build an alpha channel from that.
|
|
|
|
|
|
|
|
char *txt_buf = new char [w * h]; |
|
|
|
|
|
|
|
for (int idx = 0; idx < w * h; ++idx) |
|
|
|
|
|
|
|
{ // Fake up the alpha component using the green component's value
|
|
|
|
|
|
|
|
txt_buf[idx] = image->array[idx * 3 + 1]; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
delete image; |
|
|
|
|
|
|
|
return txt_buf; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// platform-independent, no-texture GL text drawing procedure
|
|
|
|
|
|
|
|
// when Fl_XXX_Gl_Window_Driver::get_list() and gl_bitmap_font() are implemented
|
|
|
|
|
|
|
|
void Fl_Gl_Window_Driver::draw_string_legacy_get_list(const char* str, int n) { |
|
|
|
|
|
|
|
static unsigned short *buf = NULL; |
|
|
|
|
|
|
|
static unsigned l = 0; |
|
|
|
|
|
|
|
unsigned wn = fl_utf8toUtf16(str, n, buf, l); |
|
|
|
|
|
|
|
if (wn >= l) { |
|
|
|
|
|
|
|
buf = (unsigned short*) realloc(buf, sizeof(unsigned short) * (wn + 1)); |
|
|
|
|
|
|
|
l = wn + 1; |
|
|
|
|
|
|
|
wn = fl_utf8toUtf16(str, n, buf, l); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
int size = 0; |
|
|
|
|
|
|
|
if (gl_start_scale != 1) { // using gl_start() / gl_finish()
|
|
|
|
|
|
|
|
size = fl_graphics_driver->font_descriptor()->size; |
|
|
|
|
|
|
|
gl_font(fl_font(), size * gl_start_scale); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
for (unsigned i = 0; i < wn; i++) { |
|
|
|
|
|
|
|
unsigned int r; |
|
|
|
|
|
|
|
r = (buf[i] & 0xFC00) >> 10; |
|
|
|
|
|
|
|
get_list(gl_fontsize, r); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
glCallLists(wn, GL_UNSIGNED_SHORT, buf); |
|
|
|
|
|
|
|
if (gl_start_scale != 1) { // using gl_start() / gl_finish()
|
|
|
|
|
|
|
|
gl_font(fl_font(), size); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#endif //! defined(FL_DOXYGEN)
|
|
|
|
/* Platform-independent, no-texture, GL text drawing procedure when there's no OS support whatsoever:
|
|
|
|
|
|
|
|
glutStrokeString() is used to draw text. It's possible to vary text size, but not text font, |
|
|
|
/** \addtogroup group_macosx
|
|
|
|
and only ASCII characters can be drawn. |
|
|
|
@{ */ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
\brief Returns the current height of the pile of pre-computed string textures |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
The default value is 100 |
|
|
|
|
|
|
|
*/ |
|
|
|
*/ |
|
|
|
int gl_texture_pile_height(void) |
|
|
|
void Fl_Gl_Window_Driver::draw_string_legacy_glut(const char* str, int n) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (! gl_fifo) gl_fifo = new gl_texture_fifo(); |
|
|
|
uchar *str_nul = new uchar[n + 1]; |
|
|
|
return gl_fifo->size(); |
|
|
|
int m = 0; |
|
|
|
|
|
|
|
for (int i = 0; i < n; i++) { |
|
|
|
|
|
|
|
if ((uchar)str[i] < 128) str_nul[m++] = str[i]; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
str_nul[m] = 0; |
|
|
|
|
|
|
|
n = m; |
|
|
|
|
|
|
|
Fl_Surface_Device::push_current(Fl_Display_Device::display_device()); |
|
|
|
|
|
|
|
fl_graphics_driver->font_descriptor(gl_fontsize); |
|
|
|
|
|
|
|
Fl_Gl_Window *gwin = Fl_Window::current()->as_gl_window(); |
|
|
|
|
|
|
|
gl_scale = (gwin ? gwin->pixels_per_unit() : 1); |
|
|
|
|
|
|
|
float ratio = fl_width((char*)str_nul, n) * gl_scale/glutStrokeLength(GLUT_STROKE_ROMAN, str_nul); |
|
|
|
|
|
|
|
Fl_Surface_Device::pop_current(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//setup matrices
|
|
|
|
|
|
|
|
GLint matrixMode; |
|
|
|
|
|
|
|
glGetIntegerv (GL_MATRIX_MODE, &matrixMode); |
|
|
|
|
|
|
|
glMatrixMode (GL_PROJECTION); |
|
|
|
|
|
|
|
glPushMatrix(); |
|
|
|
|
|
|
|
glLoadIdentity (); |
|
|
|
|
|
|
|
glMatrixMode (GL_MODELVIEW); |
|
|
|
|
|
|
|
glPushMatrix(); |
|
|
|
|
|
|
|
glLoadIdentity (); |
|
|
|
|
|
|
|
float winw = gl_scale * Fl_Window::current()->w(); |
|
|
|
|
|
|
|
float winh = gl_scale * Fl_Window::current()->h(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
GLfloat pos[4]; |
|
|
|
|
|
|
|
glGetFloatv(GL_CURRENT_RASTER_POSITION, pos); |
|
|
|
|
|
|
|
if (gl_start_scale != 1) { // using gl_start() / gl_finish()
|
|
|
|
|
|
|
|
pos[0] /= gl_start_scale; |
|
|
|
|
|
|
|
pos[1] /= gl_start_scale; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
float R = 2 * ratio; |
|
|
|
|
|
|
|
glScalef (R/winw, R/winh, 1.0f); |
|
|
|
|
|
|
|
glTranslatef (-winw/R, -winh/R, 0.0f); |
|
|
|
|
|
|
|
glTranslatef(pos[0]*2/R, pos[1]*2/R, 0.0); |
|
|
|
|
|
|
|
glutStrokeString(GLUT_STROKE_ROMAN, str_nul); |
|
|
|
|
|
|
|
float width = fl_width((char*)str_nul); |
|
|
|
|
|
|
|
delete[] str_nul; |
|
|
|
|
|
|
|
glPopAttrib(); |
|
|
|
|
|
|
|
// reset original matrices
|
|
|
|
|
|
|
|
glPopMatrix(); // GL_MODELVIEW
|
|
|
|
|
|
|
|
glMatrixMode (GL_PROJECTION); |
|
|
|
|
|
|
|
glPopMatrix(); |
|
|
|
|
|
|
|
glMatrixMode (matrixMode); |
|
|
|
|
|
|
|
//set the raster position to end of string
|
|
|
|
|
|
|
|
pos[0] += 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); |
|
|
|
|
|
|
|
if (gl_start_scale != 1) { // using gl_start() / gl_finish()
|
|
|
|
|
|
|
|
objX *= gl_start_scale; |
|
|
|
|
|
|
|
objY *= gl_start_scale; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
glRasterPos2d(objX, objY); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
\brief Changes the height of the pile of pre-computed string textures |
|
|
|
#if defined(FL_CFG_GFX_XLIB) |
|
|
|
* |
|
|
|
# include "drivers/Xlib/Fl_Font.H" |
|
|
|
Strings that are often re-displayed can be processed much faster if |
|
|
|
# include <FL/platform.H> |
|
|
|
this pile is set high enough to hold all of them. |
|
|
|
# include <GL/glx.h> |
|
|
|
\param max Height of the texture pile |
|
|
|
|
|
|
|
|
|
|
|
void Fl_X11_Gl_Window_Driver::draw_string_legacy(const char* str, int n) { |
|
|
|
|
|
|
|
draw_string_legacy_get_list(str, n); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int Fl_X11_Gl_Window_Driver::genlistsize() { |
|
|
|
|
|
|
|
#if USE_XFT |
|
|
|
|
|
|
|
return 256; |
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
return 0x10000; |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Fl_X11_Gl_Window_Driver::gl_bitmap_font(Fl_Font_Descriptor *fl_fontsize) { |
|
|
|
|
|
|
|
/* This method should ONLY be triggered if our GL font texture pile mechanism
|
|
|
|
|
|
|
|
* is not working on this platform. This code might not reliably render glyphs |
|
|
|
|
|
|
|
* from higher codepoints. */ |
|
|
|
|
|
|
|
if (!fl_fontsize->listbase) { |
|
|
|
|
|
|
|
#if USE_XFT |
|
|
|
|
|
|
|
/* Ideally, for XFT, we need a glXUseXftFont implementation here... But we
|
|
|
|
|
|
|
|
* do not have such a thing. Instead, we try to find a legacy Xlib font that |
|
|
|
|
|
|
|
* matches the current XFT font and use that. |
|
|
|
|
|
|
|
* Ideally, we never come here - we hope the texture pile implementation |
|
|
|
|
|
|
|
* will work correctly so that XFT can render the face directly without the |
|
|
|
|
|
|
|
* need for this workaround. */ |
|
|
|
|
|
|
|
XFontStruct *font = fl_xfont.value(); |
|
|
|
|
|
|
|
int base = font->min_char_or_byte2; |
|
|
|
|
|
|
|
int count = font->max_char_or_byte2 - base + 1; |
|
|
|
|
|
|
|
fl_fontsize->listbase = glGenLists(genlistsize()); |
|
|
|
|
|
|
|
glXUseXFont(font->fid, base, count, fl_fontsize->listbase+base); |
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
/* Not using XFT to render text - the legacy Xlib fonts can usually be rendered
|
|
|
|
|
|
|
|
* directly by using glXUseXFont mechanisms. */ |
|
|
|
|
|
|
|
fl_fontsize->listbase = glGenLists(genlistsize()); |
|
|
|
|
|
|
|
#endif // !USE_XFT
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
glListBase(fl_fontsize->listbase); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Fl_X11_Gl_Window_Driver::get_list(Fl_Font_Descriptor *fd, int r) { |
|
|
|
|
|
|
|
Fl_Xlib_Font_Descriptor *gl_fd = (Fl_Xlib_Font_Descriptor*)fd; |
|
|
|
|
|
|
|
if (gl_fd->glok[r]) return; |
|
|
|
|
|
|
|
gl_fd->glok[r] = 1; |
|
|
|
|
|
|
|
# if USE_XFT |
|
|
|
|
|
|
|
/* We hope not to come here: We hope that any system using XFT will also
|
|
|
|
|
|
|
|
* have sufficient GL capability to support our font texture pile mechansim, |
|
|
|
|
|
|
|
* allowing XFT to render the face directly. */ |
|
|
|
|
|
|
|
// Face already set by gl_bitmap_font in this case.
|
|
|
|
|
|
|
|
# else |
|
|
|
|
|
|
|
unsigned int ii = r * 0x400; |
|
|
|
|
|
|
|
for (int i = 0; i < 0x400; i++) { |
|
|
|
|
|
|
|
XFontStruct *font = NULL; |
|
|
|
|
|
|
|
unsigned short id; |
|
|
|
|
|
|
|
fl_XGetUtf8FontAndGlyph(gl_fd->font, ii, &font, &id); |
|
|
|
|
|
|
|
if (font) glXUseXFont(font->fid, id, 1, gl_fd->listbase+ii); |
|
|
|
|
|
|
|
ii++; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
# endif |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if !USE_XFT |
|
|
|
|
|
|
|
Fl_Font_Descriptor** Fl_X11_Gl_Window_Driver::fontnum_to_fontdescriptor(int fnum) { |
|
|
|
|
|
|
|
Fl_Xlib_Fontdesc *s = ((Fl_Xlib_Fontdesc*)fl_fonts) + fnum; |
|
|
|
|
|
|
|
return &(s->first); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if HAVE_GL_OVERLAY |
|
|
|
|
|
|
|
extern uchar fl_overlay; |
|
|
|
|
|
|
|
int Fl_X11_Gl_Window_Driver::overlay_color(Fl_Color i) { |
|
|
|
|
|
|
|
if (fl_overlay) {glIndexi(int(fl_xpixel(i))); return 1;} |
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
#endif // HAVE_GL_OVERLAY
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endif // FL_CFG_GFX_XLIB
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if defined(FL_CFG_GFX_GDI) |
|
|
|
|
|
|
|
# include "drivers/GDI/Fl_Font.H" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Fl_WinAPI_Gl_Window_Driver::draw_string_legacy(const char* str, int n) { |
|
|
|
|
|
|
|
draw_string_legacy_get_list(str, n); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int Fl_WinAPI_Gl_Window_Driver::genlistsize() { |
|
|
|
|
|
|
|
return 0x10000; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Fl_WinAPI_Gl_Window_Driver::gl_bitmap_font(Fl_Font_Descriptor *fl_fontsize) { |
|
|
|
|
|
|
|
if (!fl_fontsize->listbase) { |
|
|
|
|
|
|
|
fl_fontsize->listbase = glGenLists(genlistsize()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
glListBase(fl_fontsize->listbase); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Fl_WinAPI_Gl_Window_Driver::get_list(Fl_Font_Descriptor *fd, int r) { |
|
|
|
|
|
|
|
Fl_GDI_Font_Descriptor* gl_fd = (Fl_GDI_Font_Descriptor*)fd; |
|
|
|
|
|
|
|
if (gl_fd->glok[r]) return; |
|
|
|
|
|
|
|
gl_fd->glok[r] = 1; |
|
|
|
|
|
|
|
unsigned int ii = r * 0x400; |
|
|
|
|
|
|
|
HFONT oldFid = (HFONT)SelectObject((HDC)fl_graphics_driver->gc(), gl_fd->fid); |
|
|
|
|
|
|
|
wglUseFontBitmapsW((HDC)fl_graphics_driver->gc(), ii, 0x400, gl_fd->listbase+ii); |
|
|
|
|
|
|
|
SelectObject((HDC)fl_graphics_driver->gc(), oldFid); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if HAVE_GL_OVERLAY |
|
|
|
|
|
|
|
extern uchar fl_overlay; |
|
|
|
|
|
|
|
extern int fl_overlay_depth; |
|
|
|
|
|
|
|
int Fl_WinAPI_Gl_Window_Driver::overlay_color(Fl_Color i) { |
|
|
|
|
|
|
|
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 : FL_GRAY_RAMP); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return 1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
#endif // HAVE_GL_OVERLAY
|
|
|
|
|
|
|
|
#endif // FL_CFG_GFX_GDI
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if defined(FL_CFG_GFX_QUARTZ) |
|
|
|
|
|
|
|
# include "drivers/Quartz/Fl_Font.H" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# if !defined(kCGBitmapByteOrder32Host) // doc says available 10.4 but some 10.4 don't have it
|
|
|
|
|
|
|
|
# define kCGBitmapByteOrder32Host 0 |
|
|
|
|
|
|
|
# endif // !defined(kCGBitmapByteOrder32Host)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Some old Apple hardware doesn't implement the GL_EXT_texture_rectangle extension.
|
|
|
|
|
|
|
|
For it, draw_string_legacy_glut() is used to draw text. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
void gl_texture_pile_height(int max) |
|
|
|
|
|
|
|
|
|
|
|
char *Fl_Cocoa_Gl_Window_Driver::alpha_mask_for_string(const char *str, int n, int w, int h) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (gl_fifo) delete gl_fifo; |
|
|
|
// write str to a bitmap just big enough
|
|
|
|
gl_fifo = new gl_texture_fifo(max); |
|
|
|
CGColorSpaceRef lut = CGColorSpaceCreateDeviceRGB(); |
|
|
|
|
|
|
|
void *base = NULL; |
|
|
|
|
|
|
|
if (fl_mac_os_version < 100600) base = calloc(4*w, h); |
|
|
|
|
|
|
|
void* save_gc = fl_graphics_driver->gc(); |
|
|
|
|
|
|
|
CGContextRef gc = CGBitmapContextCreate(base, w, h, 8, w*4, lut, |
|
|
|
|
|
|
|
(CGBitmapInfo)(kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host)); |
|
|
|
|
|
|
|
CGColorSpaceRelease(lut); |
|
|
|
|
|
|
|
fl_graphics_driver->gc(gc); |
|
|
|
|
|
|
|
fl_color(FL_WHITE); |
|
|
|
|
|
|
|
CGContextScaleCTM(gc, gl_scale, -gl_scale); |
|
|
|
|
|
|
|
CGContextTranslateCTM(gc, 0, -fl_descent()); |
|
|
|
|
|
|
|
fl_draw(str, n, 0, 0); |
|
|
|
|
|
|
|
// get the alpha channel only of the bitmap
|
|
|
|
|
|
|
|
char *txt_buf = new char[w*h], *r = txt_buf, *q; |
|
|
|
|
|
|
|
q = (char*)CGBitmapContextGetData(gc); |
|
|
|
|
|
|
|
for (int i = 0; i < h; i++) { |
|
|
|
|
|
|
|
for (int j = 0; j < w; j++) { |
|
|
|
|
|
|
|
*r++ = *(q+3); |
|
|
|
|
|
|
|
q += 4; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
CGContextRelease(gc); |
|
|
|
|
|
|
|
fl_graphics_driver->gc(save_gc); |
|
|
|
|
|
|
|
if (base) free(base); |
|
|
|
|
|
|
|
return txt_buf; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** @} */ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endif // FL_CFG_GFX_QUARTZ
|
|
|
|
#endif // FL_CFG_GFX_QUARTZ
|
|
|
|
|
|
|
|
|
|
|
|
#endif // HAVE_GL
|
|
|
|
#endif // HAVE_GL || defined(FL_DOXYGEN)
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// End of "$Id$".
|
|
|
|
// End of "$Id$".
|
|
|
|