STR#3450: Draw text with OpenGL using textures on all platforms.

git-svn-id: file:///fltk/svn/fltk/branches/branch-1.4@12650 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
Manolo Gouy 2018-02-07 15:34:44 +00:00
parent 90630409cb
commit dcc82d8926
21 changed files with 718 additions and 531 deletions

View File

@ -18,6 +18,10 @@ Changes in FLTK 1.4.0 Released: ??? ?? 2017
New Features and Extensions
- (add new items here)
- OpenGL draws text using textures on all platforms, when the necessary
hardware support is present (a backup mechanism is available in absence
of this support). Thus, all text drawable in Fl_Window's can be drawn
in Fl_GL_Window's (STR#3450).
- New member functions FL::run_also_windowless(),
and FL::wait_also_windowless(double secnds) to run the event
loop even without any mapped window if the platform supports it.

22
FL/Fl.H
View File

@ -134,6 +134,7 @@ class FL_EXPORT Fl {
private:
static int use_high_res_GL_;
static int draw_GL_text_with_textures_;
public:
@ -1279,6 +1280,27 @@ int main() {
\version 1.3.4
*/
static int use_high_res_GL() { return use_high_res_GL_; }
/** sets whether OpenGL uses textures to draw all text.
By default, FLTK draws OpenGL text using textures, if the necessary
hardware support is available. Call \p Fl::draw_GL_text_with_textures(0)
once in your program before the first call to gl_font() to have FLTK
draw instead OpenGL text using a legacy, platform-dependent procedure.
It's recommended not to deactivate textures under the MacOS platform
because the MacOS legacy procedure is extremely rudimentary.
\param val use 0 to prevent FLTK from drawing GL text with textures
\see gl_texture_pile_height(int max)
\version 1.4.0
*/
static void draw_GL_text_with_textures(int val) { draw_GL_text_with_textures_ = val; }
/** returns whether whether OpenGL uses textures to draw all text.
Default is yes.
\see draw_GL_text_with_textures(int val)
\version 1.4.0
*/
static int draw_GL_text_with_textures() { return draw_GL_text_with_textures_; }
#ifdef FLTK_HAVE_CAIRO
/** \defgroup group_cairo Cairo Support Functions and Classes

View File

@ -4,7 +4,7 @@
// Definition of class Fl_Gl_Window_Driver, and of its platform-specific derived classes
// for the Fast Light Tool Kit (FLTK).
//
// Copyright 2016-2017 by Bill Spitzak and others.
// Copyright 2016-2018 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@ -44,7 +44,7 @@ public:
void alist(const int *l) { pWindow->alist = l;}
void* overlay() {return pWindow->overlay;}
void draw_overlay() {pWindow->draw_overlay();}
Fl_Gl_Window_Driver(Fl_Gl_Window *win) : pWindow(win) {}
virtual ~Fl_Gl_Window_Driver() {}
static Fl_Gl_Window_Driver *newGlWindowDriver(Fl_Gl_Window *w);
@ -79,10 +79,17 @@ public:
virtual void gl_visual(Fl_Gl_Choice*); // support for Fl::gl_visual() function
virtual void gl_start() {} // support for gl_start() function
virtual void* GetProcAddress(const char *procName); // support for glutGetProcAddress()
virtual void draw_string(const char* str, int n); // support for gl_draw()
virtual void draw_string_legacy(const char* str, int n); // support for gl_draw()
void draw_string_legacy_get_list(const char* str, int n); // support for gl_draw()
static void draw_string_legacy_glut(const char* str, int n); // support for gl_draw()
virtual void get_list(Fl_Font_Descriptor* fd, int r) {} // support for gl_draw() without textures
virtual void gl_bitmap_font(Fl_Font_Descriptor *fl_fontsize) {} // support for gl_font() without textures
virtual int overlay_color(Fl_Color i) {return 0;} // support for gl_color() with HAVE_GL_OVERLAY
static void draw_string_with_texture(const char* str, int n); // cross-platform
// support for gl_draw(). The cross-platform version may be enough.
virtual char *alpha_mask_for_string(const char *str, int n, int w, int h);
virtual int genlistsize() { return 0; } // support for gl_draw()
virtual Fl_Font_Descriptor** fontnum_to_fontdescriptor(int fnum);
};
#ifdef FL_CFG_GFX_QUARTZ
@ -111,13 +118,13 @@ class Fl_Cocoa_Gl_Window_Driver : public Fl_Gl_Window_Driver {
virtual void make_overlay_current();
virtual void redraw_overlay();
virtual void gl_start();
virtual void draw_string(const char* str, int n);
static NSOpenGLContext* create_GLcontext_for_window(NSOpenGLPixelFormat *pixelformat, NSOpenGLContext *shared_ctx, Fl_Window *window);
static NSOpenGLPixelFormat *mode_to_NSOpenGLPixelFormat(int mode, const int*); // uses Objective-c
static void GLcontext_update(NSOpenGLContext*); // uses Objective-c
static void GLcontext_release(NSOpenGLContext*); // uses Objective-c
static void GLcontext_makecurrent(NSOpenGLContext*); // uses Objective-c
static void GL_cleardrawable(void); // uses Objective-c
virtual char *alpha_mask_for_string(const char *str, int n, int w, int h);
};
#endif // FL_CFG_GFX_QUARTZ
@ -141,8 +148,10 @@ class Fl_WinAPI_Gl_Window_Driver : public Fl_Gl_Window_Driver {
virtual void make_overlay_current();
virtual void redraw_overlay();
virtual void* GetProcAddress(const char *procName);
virtual void draw_string_legacy(const char* str, int n);
virtual void gl_bitmap_font(Fl_Font_Descriptor *fl_fontsize);
virtual void get_list(Fl_Font_Descriptor *fd, int r);
virtual int genlistsize();
#if HAVE_GL_OVERLAY
virtual int can_do_overlay();
virtual int overlay_color(Fl_Color i);
@ -153,7 +162,7 @@ class Fl_WinAPI_Gl_Window_Driver : public Fl_Gl_Window_Driver {
#ifdef FL_CFG_GFX_XLIB
#include <X11/Xutil.h>
#include <X11/Xutil.h> // for XVisualInfo
class Fl_X11_Gl_Window_Driver : public Fl_Gl_Window_Driver {
friend class Fl_Gl_Window_Driver;
Fl_X11_Gl_Window_Driver(Fl_Gl_Window *win) : Fl_Gl_Window_Driver(win) {}
@ -178,9 +187,14 @@ class Fl_X11_Gl_Window_Driver : public Fl_Gl_Window_Driver {
virtual void waitGL();
virtual void gl_visual(Fl_Gl_Choice*); // support for Fl::gl_visual()
virtual void gl_start();
virtual void draw_string_legacy(const char* str, int n);
virtual void gl_bitmap_font(Fl_Font_Descriptor *fl_fontsize);
virtual void get_list(Fl_Font_Descriptor *fd, int r);
public:
virtual int genlistsize();
#if !USE_XFT
virtual Fl_Font_Descriptor** fontnum_to_fontdescriptor(int fnum);
#endif
public:
static GLContext create_gl_context(XVisualInfo* vis);
};

View File

@ -4,7 +4,7 @@
// Definition of classes Fl_Graphics_Driver, Fl_Surface_Device, Fl_Display_Device
// for the Fast Light Tool Kit (FLTK).
//
// Copyright 2010-2017 by Bill Spitzak and others.
// Copyright 2010-2018 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@ -90,6 +90,7 @@ class FL_EXPORT Fl_Graphics_Driver {
friend void fl_copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy);
friend FL_EXPORT int fl_draw_pixmap(const char*const* cdata, int x, int y, Fl_Color bg);
friend FL_EXPORT void gl_start();
friend FL_EXPORT void gl_finish();
friend FL_EXPORT Fl_Bitmask fl_create_bitmask(int w, int h, const uchar *array);
friend FL_EXPORT void fl_delete_bitmask(Fl_Bitmask);
private:
@ -387,7 +388,7 @@ public:
/** Some platforms may need to implement this to support fonts */
virtual Fl_Fontdesc* calc_fl_fonts(void) {return NULL;}
/** Support for Fl::set_font() */
virtual unsigned font_desc_size() {return 0;}
virtual unsigned font_desc_size();
/** Support for Fl::get_font() */
virtual const char *font_name(int num) {return NULL;}
/** Support for Fl::set_font() */
@ -397,6 +398,33 @@ public:
};
#ifndef FL_DOXYGEN
/* This class is not part of FLTK's public API.
Platforms usually define a derived class called Fl_XXX_Font_Descriptor
containing extra platform-specific data/functions.
This is a class for an actual system font, with junk to
help choose it and info on character sizes. Each Fl_Fontdesc has a
linked list of these. These are created the first time each system
font/size combination is used.
*/
class Fl_Font_Descriptor {
public:
/** linked list for this Fl_Fontdesc */
Fl_Font_Descriptor *next;
Fl_Fontsize size; /**< font size */
Fl_Font_Descriptor(const char* fontname, Fl_Fontsize size);
FL_EXPORT ~Fl_Font_Descriptor() {}
short ascent, descent, q_width;
unsigned int listbase;// base of display list, 0 = none
};
// This struct is not part of FLTK's public API.
struct Fl_Fontdesc {
const char *name;
char fontname[128]; // "Pretty" font name
Fl_Font_Descriptor *first; // linked list of sizes of this style
};
/* Abstract class Fl_Scalable_Graphics_Driver is platform-independent.
It supports the scaling of all graphics coordinates by a
float factor helpful to support HiDPI displays.

21
FL/gl.h
View File

@ -3,7 +3,7 @@
//
// OpenGL header file for the Fast Light Tool Kit (FLTK).
//
// Copyright 1998-2011 by Bill Spitzak and others.
// Copyright 1998-2018 by Bill Spitzak and others.
//
// You must include this instead of GL/gl.h to get the Microsoft
// APIENTRY stuff included (from <windows.h>) prior to the OpenGL
@ -28,10 +28,11 @@
*
* To use OpenGL from within an FLTK application you MUST use gl_visual()
* to select the default visual before doing show() on any windows. Mesa
* will crash if yoy try to use a visual not returned by glxChooseVidual.
* will crash if you try to use a visual not returned by glxChooseVisual.
*
* This does not work with Fl_Double_Window's! It will try to draw
* into the front buffer. Depending on the system this will either
* Historically, this did not always work well with Fl_Double_Window's!
* It can try to draw into the front buffer.
* Depending on the system this might 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
@ -89,16 +90,8 @@ FL_EXPORT void gl_draw(const char*, int n, int x, int y);
FL_EXPORT void gl_draw(const char*, int n, float x, float y);
FL_EXPORT void gl_draw(const char*, int x, int y, int w, int h, Fl_Align);
FL_EXPORT void gl_measure(const char*, int& x, int& y);
#ifdef __APPLE__ // PORTME: OpenGL platform texture
extern FL_EXPORT void gl_texture_pile_height(int max);
extern FL_EXPORT int gl_texture_pile_height();
#elif defined(WIN32)
// not needed
#elif defined(FL_PORTING)
# pragma message "FL_PORTING: define functions to control OpenGL texture pile height if supported"
#else // X11
// not needed
#endif
FL_EXPORT void gl_texture_pile_height(int max);
FL_EXPORT int gl_texture_pile_height();
FL_EXPORT void gl_draw_image(const uchar *, int x,int y,int w,int h, int d=3, int ld=0);

View File

@ -1914,6 +1914,8 @@ Fl_Widget_Tracker::~Fl_Widget_Tracker()
int Fl::use_high_res_GL_ = 0;
int Fl::draw_GL_text_with_textures_ = 1;
int Fl::dnd()
{
return Fl::screen_driver()->dnd();

View File

@ -495,6 +495,10 @@ void* Fl_Gl_Window_Driver::GetProcAddress(const char *procName) {
#endif // HAVE_DLSYM
}
Fl_Font_Descriptor** Fl_Gl_Window_Driver::fontnum_to_fontdescriptor(int fnum) {
extern FL_EXPORT Fl_Fontdesc *fl_fonts;
return &(fl_fonts[fnum].first);
}
#ifdef FL_CFG_GFX_QUARTZ
#include <FL/platform.H>

View File

@ -217,8 +217,20 @@ void Fl_Graphics_Driver::draw(Fl_Shared_Image *shared, int X, int Y) {
shared->scaled_image_->draw(X, Y, shared->scaled_image_->w(), shared->scaled_image_->h(), 0, 0);
}
unsigned Fl_Graphics_Driver::font_desc_size() {
return (unsigned)sizeof(Fl_Fontdesc);
}
#ifndef FL_DOXYGEN
Fl_Font_Descriptor::Fl_Font_Descriptor(const char* name, Fl_Fontsize Size) {
next = 0;
# if HAVE_GL
listbase = 0;
# endif
// OpenGL needs those for its font handling
size = Size;
}
Fl_Scalable_Graphics_Driver::Fl_Scalable_Graphics_Driver() : Fl_Graphics_Driver() {
scale_ = 1;
line_width_ = 0;

View File

@ -3,7 +3,7 @@
//
// Font definitions for the Fast Light Tool Kit (FLTK).
//
// Copyright 1998-2011 by Bill Spitzak and others.
// Copyright 1998-2018 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@ -26,39 +26,17 @@
#include <config.h>
/**
This a structure for an actual system font, with junk to
help choose it and info on character sizes. Each Fl_Fontdesc has a
linked list of these. These are created the first time each system
font/size combination is used.
*/
class Fl_Font_Descriptor {
class Fl_GDI_Font_Descriptor : public Fl_Font_Descriptor {
public:
/** linked list for this Fl_Fontdesc */
Fl_Font_Descriptor *next;
Fl_Fontsize size; /**< font size */
#ifndef FL_DOXYGEN // don't bother with platorm dependant details in the doc.
HFONT fid;
int *width[64];
TEXTMETRIC metr;
int angle;
FL_EXPORT Fl_Font_Descriptor(const char* fontname, Fl_Fontsize size);
FL_EXPORT Fl_GDI_Font_Descriptor(const char* fontname, Fl_Fontsize size);
# if HAVE_GL
unsigned int listbase;// base of display list, 0 = none
char glok[64];
# endif // HAVE_GL
FL_EXPORT ~Fl_Font_Descriptor();
#endif // FL_DOXYGEN
};
//extern FL_EXPORT Fl_Font_Descriptor *fl_fontsize; // the currently selected one
struct Fl_Fontdesc {
const char *name;
char fontname[128]; // "Pretty" font name
Fl_Font_Descriptor *first; // linked list of sizes of this style
FL_EXPORT ~Fl_GDI_Font_Descriptor();
};
extern FL_EXPORT Fl_Fontdesc *fl_fonts; // the table

View File

@ -4,7 +4,7 @@
// Definition of classes Fl_Graphics_Driver, Fl_Surface_Device, Fl_Display_Device
// for the Fast Light Tool Kit (FLTK).
//
// Copyright 2010-2017 by Bill Spitzak and others.
// Copyright 2010-2018 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@ -146,7 +146,6 @@ protected:
virtual const char* get_font_name(Fl_Font fnum, int* ap);
virtual const char *font_name(int num);
virtual void font_name(int num, const char *name);
virtual unsigned font_desc_size();
void global_gc();
};

View File

@ -189,10 +189,6 @@ int Fl_GDI_Graphics_Driver::get_font_sizes(Fl_Font fnum, int*& sizep) {
return nbSize;
}
unsigned Fl_GDI_Graphics_Driver::font_desc_size() {
return (unsigned)sizeof(Fl_Fontdesc);
}
const char *Fl_GDI_Graphics_Driver::font_name(int num) {
return fl_fonts[num].name;
}
@ -215,7 +211,7 @@ void Fl_GDI_Graphics_Driver::font_name(int num, const char *name) {
static int fl_angle_ = 0;
#ifndef FL_DOXYGEN
Fl_Font_Descriptor::Fl_Font_Descriptor(const char* name, Fl_Fontsize fsize) {
Fl_GDI_Font_Descriptor::Fl_GDI_Font_Descriptor(const char* name, Fl_Fontsize fsize) : Fl_Font_Descriptor(name,fsize) {
int weight = FW_NORMAL;
int italic = 0;
switch (*name++) {
@ -252,13 +248,12 @@ Fl_Font_Descriptor::Fl_Font_Descriptor(const char* name, Fl_Fontsize fsize) {
int i;
memset(width, 0, 64 * sizeof(int*));
#if HAVE_GL
listbase = 0;
for (i = 0; i < 64; i++) glok[i] = 0;
#endif
size = fsize;
}
Fl_Font_Descriptor::~Fl_Font_Descriptor() {
Fl_GDI_Font_Descriptor::~Fl_GDI_Font_Descriptor() {
#if HAVE_GL
// Delete list created by gl_draw(). This is not done by this code
// as it will link in GL unnecessarily. There should be some kind
@ -296,13 +291,13 @@ static Fl_Fontdesc built_in_table[] = {
Fl_Fontdesc* fl_fonts = built_in_table;
static Fl_Font_Descriptor* find(Fl_Font fnum, Fl_Fontsize size, int angle) {
static Fl_GDI_Font_Descriptor* find(Fl_Font fnum, Fl_Fontsize size, int angle) {
Fl_Fontdesc* s = fl_fonts+fnum;
if (!s->name) s = fl_fonts; // use 0 if fnum undefined
Fl_Font_Descriptor* f;
for (f = s->first; f; f = f->next)
Fl_GDI_Font_Descriptor* f;
for (f = (Fl_GDI_Font_Descriptor*)s->first; f; f = (Fl_GDI_Font_Descriptor*)f->next)
if (f->size == size && f->angle == angle) return f;
f = new Fl_Font_Descriptor(s->name, size);
f = new Fl_GDI_Font_Descriptor(s->name, size);
f->next = s->first;
s->first = f;
return f;
@ -328,13 +323,13 @@ void Fl_GDI_Graphics_Driver::font_unscaled(Fl_Font fnum, Fl_Fontsize size) {
}
int Fl_GDI_Graphics_Driver::height_unscaled() {
Fl_Font_Descriptor *fl_fontsize = font_descriptor();
Fl_GDI_Font_Descriptor *fl_fontsize = (Fl_GDI_Font_Descriptor*)font_descriptor();
if (fl_fontsize) return (fl_fontsize->metr.tmAscent + fl_fontsize->metr.tmDescent);
else return -1;
}
int Fl_GDI_Graphics_Driver::descent_unscaled() {
Fl_Font_Descriptor *fl_fontsize = font_descriptor();
Fl_GDI_Font_Descriptor *fl_fontsize = (Fl_GDI_Font_Descriptor*)font_descriptor();
if (fl_fontsize) return fl_fontsize->metr.tmDescent;
else return -1;
}
@ -369,7 +364,7 @@ double Fl_GDI_Graphics_Driver::width_unscaled(const char* c, int n) {
}
double Fl_GDI_Graphics_Driver::width_unscaled(unsigned int c) {
Fl_Font_Descriptor *fl_fontsize = font_descriptor();
Fl_GDI_Font_Descriptor *fl_fontsize = (Fl_GDI_Font_Descriptor*)font_descriptor();
unsigned int r;
SIZE s;
// Special Case Handling of Unicode points over U+FFFF.
@ -468,7 +463,7 @@ static void on_printer_extents_update(int &dx, int &dy, int &w, int &h, HDC gc)
// Function to determine the extent of the "inked" area of the glyphs in a string
void Fl_GDI_Graphics_Driver::text_extents_unscaled(const char *c, int n, int &dx, int &dy, int &w, int &h) {
Fl_Font_Descriptor *fl_fontsize = font_descriptor();
Fl_GDI_Font_Descriptor *fl_fontsize = (Fl_GDI_Font_Descriptor*)font_descriptor();
if (!fl_fontsize) { // no valid font, nothing to measure
w = 0; h = 0;
dx = dy = 0;
@ -582,7 +577,7 @@ void Fl_GDI_Graphics_Driver::draw_unscaled(const char* str, int n, int x, int y)
COLORREF oldColor = SetTextColor(gc_, fl_RGB());
// avoid crash if no font has been set yet
if (!font_descriptor()) this->font(FL_HELVETICA, FL_NORMAL_SIZE);
SelectObject(gc_, font_descriptor()->fid);
SelectObject(gc_, ((Fl_GDI_Font_Descriptor*)font_descriptor())->fid);
int wn = fl_utf8toUtf16(str, n, wstr, wstr_len);
if(wn >= wstr_len) {
wstr = (unsigned short*) realloc(wstr, sizeof(unsigned short) * (wn + 1));
@ -597,7 +592,7 @@ void Fl_GDI_Graphics_Driver::draw_unscaled(int angle, const char* str, int n, in
fl_font(this, Fl_Graphics_Driver::font(), size_unscaled(), angle);
int wn = 0; // count of UTF16 cells to render full string
COLORREF oldColor = SetTextColor(gc_, fl_RGB());
SelectObject(gc_, font_descriptor()->fid);
SelectObject(gc_, ((Fl_GDI_Font_Descriptor*)font_descriptor())->fid);
wn = fl_utf8toUtf16(str, n, wstr, wstr_len);
if(wn >= wstr_len) { // Array too small
wstr = (unsigned short*) realloc(wstr, sizeof(unsigned short) * (wn + 1));
@ -619,7 +614,7 @@ void Fl_GDI_Graphics_Driver::rtl_draw_unscaled(const char* c, int n, int x, int
}
COLORREF oldColor = SetTextColor(gc_, fl_RGB());
SelectObject(gc_, font_descriptor()->fid);
SelectObject(gc_, ((Fl_GDI_Font_Descriptor*)font_descriptor())->fid);
#ifdef RTL_CHAR_BY_CHAR
int i = 0;
int lx = 0;

View File

@ -3,7 +3,7 @@
//
// Font definitions for the Fast Light Tool Kit (FLTK).
//
// Copyright 1998-2011 by Bill Spitzak and others.
// Copyright 1998-2018 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@ -28,21 +28,10 @@
#include "Fl_Quartz_Graphics_Driver.H"
#include <ApplicationServices/ApplicationServices.h>
/**
This a structure for an actual system font, with junk to
help choose it and info on character sizes. Each Fl_Fontdesc has a
linked list of these. These are created the first time each system
font/size combination is used.
*/
class Fl_Font_Descriptor {
class Fl_Quartz_Font_Descriptor : public Fl_Font_Descriptor {
public:
/** linked list for this Fl_Fontdesc */
Fl_Font_Descriptor *next;
Fl_Fontsize size; /**< font size */
#ifndef FL_DOXYGEN // don't bother with platorm dependant details in the doc.
Fl_Font_Descriptor(const char* fontname, Fl_Fontsize size);
FL_EXPORT ~Fl_Font_Descriptor();
short ascent, descent, q_width;
Fl_Quartz_Font_Descriptor(const char* fontname, Fl_Fontsize size);
FL_EXPORT ~Fl_Quartz_Font_Descriptor();
# if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
CTFontRef fontref;
// the unicode span is divided in 512 blocks of 128 characters
@ -52,19 +41,6 @@ public:
ATSUTextLayout layout;
ATSUStyle style;
# endif
# if HAVE_GL
unsigned int listbase;// base of display list, 0 = none
# endif // HAVE_GL
#endif // FL_DOXYGEN
};
//extern FL_EXPORT Fl_Font_Descriptor *fl_fontsize; // the currently selected one
struct Fl_Fontdesc {
const char *name;
char fontname[128]; // "Pretty" font name
Fl_Font_Descriptor *first; // linked list of sizes of this style
};
extern FL_EXPORT Fl_Fontdesc *fl_fonts; // the table

View File

@ -34,6 +34,7 @@
MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5)
struct Fl_Fontdesc;
class Fl_Quartz_Font_Descriptor;
/**
\brief The Mac OS X-specific graphics class.
@ -43,6 +44,7 @@ struct Fl_Fontdesc;
class Fl_Quartz_Graphics_Driver : public Fl_Graphics_Driver {
friend class Fl_Font_Descriptor;
friend class Fl_Cocoa_Printer_Driver;
friend class Fl_Quartz_Font_Descriptor;
protected:
CGContextRef gc_;
int p_size;
@ -146,10 +148,9 @@ protected:
virtual bool high_resolution() { return high_resolution_; }
virtual void global_gc();
void quartz_restore_line_style();
inline Fl_Font_Descriptor *valid_font_descriptor();
inline Fl_Quartz_Font_Descriptor *valid_font_descriptor();
virtual const char* get_font_name(Fl_Font fnum, int* ap);
virtual int get_font_sizes(Fl_Font fnum, int*& sizep);
virtual unsigned font_desc_size();
virtual const char *font_name(int num);
virtual void font_name(int num, const char *name);
Fl_Fontdesc* calc_fl_fonts(void);
@ -165,13 +166,13 @@ protected:
static void init_CoreText_or_ATSU();
void draw_CoreText(const char *str, int n, float x, float y);
double width_CoreText(const UniChar* txt, int n);
void descriptor_init_CoreText(const char* name, Fl_Fontsize Size, Fl_Font_Descriptor *d);
void descriptor_init_CoreText(const char* name, Fl_Fontsize Size, Fl_Quartz_Font_Descriptor *d);
void text_extents_CoreText(const char*, int n, int& dx, int& dy, int& w, int& h);
Fl_Font set_fonts_CoreText(const char* xstarname);
void draw_ATSU(const char *str, int n, float x, float y);
double width_ATSU(const UniChar* txt, int n);
void descriptor_init_ATSU(const char* name, Fl_Fontsize Size, Fl_Font_Descriptor *d);
void descriptor_init_ATSU(const char* name, Fl_Fontsize Size, Fl_Quartz_Font_Descriptor *d);
void text_extents_ATSU(const char*, int n, int& dx, int& dy, int& w, int& h);
Fl_Font set_fonts_ATSU(const char* xstarname);
@ -181,7 +182,7 @@ protected:
static pter_to_draw_member CoreText_or_ATSU_draw;
static pter_to_width_member CoreText_or_ATSU_width;
#else
void descriptor_init(const char* name, Fl_Fontsize Size, Fl_Font_Descriptor *d);
void descriptor_init(const char* name, Fl_Fontsize Size, Fl_Quartz_Font_Descriptor *d);
#endif
};

View File

@ -179,13 +179,7 @@ int Fl_Quartz_Graphics_Driver::get_font_sizes(Fl_Font fnum, int*& sizep) {
return cnt;
}
Fl_Font_Descriptor::Fl_Font_Descriptor(const char* name, Fl_Fontsize Size) {
next = 0;
# if HAVE_GL
listbase = 0;
# endif
// OpenGL needs those for its font handling
size = Size;
Fl_Quartz_Font_Descriptor::Fl_Quartz_Font_Descriptor(const char* name, Fl_Fontsize Size) : Fl_Font_Descriptor(name, Size) {
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
fontref = NULL;
#endif
@ -205,7 +199,7 @@ Fl_Font_Descriptor::Fl_Font_Descriptor(const char* name, Fl_Fontsize Size) {
}
Fl_Font_Descriptor::~Fl_Font_Descriptor() {
Fl_Quartz_Font_Descriptor::~Fl_Quartz_Font_Descriptor() {
/*
#if HAVE_GL
// ++ todo: remove OpenGL font allocations
@ -257,7 +251,7 @@ static Fl_Font_Descriptor* find(Fl_Font fnum, Fl_Fontsize size) {
Fl_Font_Descriptor* f;
for (f = s->first; f; f = f->next)
if (f->size == size) return f;
f = new Fl_Font_Descriptor(s->name, size);
f = new Fl_Quartz_Font_Descriptor(s->name, size);
f->next = s->first;
s->first = f;
return f;
@ -273,19 +267,19 @@ void Fl_Quartz_Graphics_Driver::font(Fl_Font fnum, Fl_Fontsize size) {
font_descriptor( find(fnum, size) );
}
Fl_Font_Descriptor *Fl_Quartz_Graphics_Driver::valid_font_descriptor() {
Fl_Quartz_Font_Descriptor *Fl_Quartz_Graphics_Driver::valid_font_descriptor() {
// avoid a crash if no font has been selected by user yet
if (!font_descriptor()) font(FL_HELVETICA, FL_NORMAL_SIZE);
return font_descriptor();
return (Fl_Quartz_Font_Descriptor*)font_descriptor();
}
int Fl_Quartz_Graphics_Driver::height() {
Fl_Font_Descriptor *fl_fontsize = valid_font_descriptor();
Fl_Quartz_Font_Descriptor *fl_fontsize = valid_font_descriptor();
return fl_fontsize->ascent + fl_fontsize->descent;
}
int Fl_Quartz_Graphics_Driver::descent() {
Fl_Font_Descriptor *fl_fontsize = valid_font_descriptor();
Fl_Quartz_Font_Descriptor *fl_fontsize = valid_font_descriptor();
return fl_fontsize->descent + 1;
}
@ -351,11 +345,6 @@ void Fl_Quartz_Graphics_Driver::set_fontname_in_fontdesc(Fl_Fontdesc *f) {
#endif
}
unsigned Fl_Quartz_Graphics_Driver::font_desc_size() {
return (unsigned)sizeof(Fl_Fontdesc);
}
const char *Fl_Quartz_Graphics_Driver::font_name(int num) {
if (!fl_fonts) fl_fonts = calc_fl_fonts();
return fl_fonts[num].name;
@ -421,7 +410,7 @@ void Fl_Quartz_Graphics_Driver::text_extents(const char* txt, int n, int& dx, in
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
void Fl_Quartz_Graphics_Driver::ADD_SUFFIX(descriptor_init, _CoreText)(const char* name,
Fl_Fontsize size, Fl_Font_Descriptor *d)
Fl_Fontsize size, Fl_Quartz_Font_Descriptor *d)
{
CFStringRef str = CFStringCreateWithCString(NULL, name, kCFStringEncodingUTF8);
d->fontref = CTFontCreateWithName(str, size, NULL);
@ -470,7 +459,7 @@ void Fl_Quartz_Graphics_Driver::ADD_SUFFIX(descriptor_init, _CoreText)(const cha
}
// returns width of a pair of UniChar's in the surrogate range
static CGFloat surrogate_width(const UniChar *txt, Fl_Font_Descriptor *fl_fontsize)
static CGFloat surrogate_width(const UniChar *txt, Fl_Quartz_Font_Descriptor *fl_fontsize)
{
CTFontRef font2 = fl_fontsize->fontref;
bool must_release = false;
@ -491,7 +480,7 @@ static CGFloat surrogate_width(const UniChar *txt, Fl_Font_Descriptor *fl_fontsi
return a.width;
}
static CGFloat variation_selector_width(CFStringRef str16, Fl_Font_Descriptor *fl_fontsize)
static CGFloat variation_selector_width(CFStringRef str16, Fl_Quartz_Font_Descriptor *fl_fontsize)
{
CGFloat retval;
CFDictionarySetValue(attributes, kCTFontAttributeName, fl_fontsize->fontref);
@ -508,7 +497,7 @@ double Fl_Quartz_Graphics_Driver::ADD_SUFFIX(width, _CoreText)(const UniChar* tx
double retval = 0;
UniChar uni;
int i;
Fl_Font_Descriptor *fl_fontsize = valid_font_descriptor();
Fl_Quartz_Font_Descriptor *fl_fontsize = valid_font_descriptor();
for (i = 0; i < n; i++) { // loop over txt
uni = txt[i];
if (uni >= 0xD800 && uni <= 0xDBFF) { // handles the surrogate range
@ -576,7 +565,7 @@ double Fl_Quartz_Graphics_Driver::ADD_SUFFIX(width, _CoreText)(const UniChar* tx
// text extent calculation
void Fl_Quartz_Graphics_Driver::ADD_SUFFIX(text_extents, _CoreText)(const char *str8, int n,
int &dx, int &dy, int &w, int &h) {
Fl_Font_Descriptor *fl_fontsize = valid_font_descriptor();
Fl_Quartz_Font_Descriptor *fl_fontsize = valid_font_descriptor();
UniChar *txt = mac_Utf8_to_Utf16(str8, n, &n);
CFStringRef str16 = CFStringCreateWithCharactersNoCopy(NULL, txt, n, kCFAllocatorNull);
CFDictionarySetValue (attributes, kCTFontAttributeName, fl_fontsize->fontref);
@ -610,7 +599,7 @@ static CGColorRef flcolortocgcolor(Fl_Color i)
void Fl_Quartz_Graphics_Driver::ADD_SUFFIX(draw, _CoreText)(const char *str, int n, float x, float y)
{
Fl_Font_Descriptor *fl_fontsize = valid_font_descriptor();
Fl_Quartz_Font_Descriptor *fl_fontsize = valid_font_descriptor();
// convert to UTF-16 first
UniChar *uniStr = mac_Utf8_to_Utf16(str, n, &n);
CGContextRef gc = (CGContextRef)this->gc();
@ -710,7 +699,7 @@ Fl_Font Fl_Quartz_Graphics_Driver::ADD_SUFFIX(set_fonts, _CoreText)(const char*
#if HAS_ATSU
void Fl_Quartz_Graphics_Driver::ADD_SUFFIX(descriptor_init, _ATSU)(const char* name,
Fl_Fontsize size, Fl_Font_Descriptor *d)
Fl_Fontsize size, Fl_Quartz_Font_Descriptor *d)
{
OSStatus err;
// fill our structure with a few default values
@ -766,7 +755,7 @@ void Fl_Quartz_Graphics_Driver::ADD_SUFFIX(descriptor_init, _ATSU)(const char* n
void Fl_Quartz_Graphics_Driver::ADD_SUFFIX(draw, _ATSU)(const char *str, int n, float x, float y)
{
Fl_Font_Descriptor *fl_fontsize = valid_font_descriptor();
Fl_Quartz_Font_Descriptor *fl_fontsize = valid_font_descriptor();
// convert to UTF-16 first
UniChar *uniStr = mac_Utf8_to_Utf16(str, n, &n);
CGContextRef gc = (CGContextRef)this->gc();
@ -793,7 +782,7 @@ double Fl_Quartz_Graphics_Driver::ADD_SUFFIX(width, _ATSU)(const UniChar* txt, i
ATSUAttributeTag iTag;
ATSUAttributeValuePtr iValuePtr;
Fl_Font_Descriptor *fl_fontsize = valid_font_descriptor();
Fl_Quartz_Font_Descriptor *fl_fontsize = valid_font_descriptor();
// Here's my ATSU text measuring attempt... This seems to do the Right Thing
// now collect our ATSU resources and measure our text string
layout = fl_fontsize->layout;
@ -814,7 +803,7 @@ double Fl_Quartz_Graphics_Driver::ADD_SUFFIX(width, _ATSU)(const UniChar* txt, i
void Fl_Quartz_Graphics_Driver::ADD_SUFFIX(text_extents, _ATSU)(const char *str8, int n,
int &dx, int &dy, int &w, int &h)
{
Fl_Font_Descriptor *fl_fontsize = valid_font_descriptor();
Fl_Quartz_Font_Descriptor *fl_fontsize = valid_font_descriptor();
UniChar *txt = mac_Utf8_to_Utf16(str8, n, &n);
OSStatus err;
ATSUTextLayout layout;

View File

@ -3,7 +3,7 @@
//
// Font definitions for the Fast Light Tool Kit (FLTK).
//
// Copyright 1998-2011 by Bill Spitzak and others.
// Copyright 1998-2018 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@ -32,18 +32,8 @@ typedef struct _XftFont XftFont;
# include "../../Xutf8.h"
#endif // USE_XFT
/**
This a structure for an actual system font, with junk to
help choose it and info on character sizes. Each Fl_Fontdesc has a
linked list of these. These are created the first time each system
font/size combination is used.
*/
class Fl_Font_Descriptor {
class Fl_Xlib_Font_Descriptor : public Fl_Font_Descriptor {
public:
/** linked list for this Fl_Fontdesc */
Fl_Font_Descriptor *next;
Fl_Fontsize size; /**< font size */
#ifndef FL_DOXYGEN // don't bother with platorm dependant details in the doc.
# if USE_XFT
# if USE_PANGO
int descent_;
@ -52,30 +42,28 @@ public:
XftFont* font;
# endif
int angle;
FL_EXPORT Fl_Font_Descriptor(const char* xfontname, Fl_Fontsize size, int angle);
FL_EXPORT Fl_Xlib_Font_Descriptor(const char* xfontname, Fl_Fontsize size, int angle);
# else
XUtf8FontStruct* font; // X UTF-8 font information
FL_EXPORT Fl_Font_Descriptor(const char* xfontname);
FL_EXPORT Fl_Xlib_Font_Descriptor(const char* xfontname);
# endif
# if HAVE_GL
unsigned int listbase;// base of display list, 0 = none
char glok[64];
# endif // HAVE_GL
FL_EXPORT ~Fl_Font_Descriptor();
#endif // FL_DOXYGEN
FL_EXPORT ~Fl_Xlib_Font_Descriptor();
};
//extern FL_EXPORT Fl_Font_Descriptor *fl_fontsize; // the currently selected one
struct Fl_Fontdesc {
#if !USE_XFT
struct Fl_Xlib_Fontdesc { // replaces Fl_Fontdesc
const char *name;
char fontname[128]; // "Pretty" font name
Fl_Font_Descriptor *first; // linked list of sizes of this style
char **xlist; // matched X font names
int n; // size of xlist, negative = don't free xlist!
};
#endif
extern FL_EXPORT Fl_Fontdesc *fl_fonts; // the table

View File

@ -180,7 +180,9 @@ protected:
virtual void reset_spot();
virtual const char* get_font_name(Fl_Font fnum, int* ap);
virtual int get_font_sizes(Fl_Font fnum, int*& sizep);
#if !USE_XFT
virtual unsigned font_desc_size();
#endif
virtual const char *font_name(int num);
virtual void font_name(int num, const char *name);
virtual Fl_Font set_fonts(const char* xstarname);

View File

@ -202,22 +202,34 @@ void Fl_Xlib_Graphics_Driver::set_spot(int font, int size, int X, int Y, int W,
XFree(preedit_attr);
}
#if !USE_XFT
unsigned Fl_Xlib_Graphics_Driver::font_desc_size() {
return (unsigned)sizeof(Fl_Fontdesc);
return (unsigned)sizeof(Fl_Xlib_Fontdesc);
}
#endif
const char *Fl_Xlib_Graphics_Driver::font_name(int num) {
#if USE_XFT
return fl_fonts[num].name;
#else
return ((Fl_Xlib_Fontdesc*)fl_fonts)[num].name;
#endif
}
void Fl_Xlib_Graphics_Driver::font_name(int num, const char *name) {
#if USE_PANGO
#if USE_XFT
# if USE_PANGO
init_built_in_fonts();
#endif
# endif
Fl_Fontdesc *s = fl_fonts + num;
#else
Fl_Xlib_Fontdesc *s = ((Fl_Xlib_Fontdesc*)fl_fonts) + num;
#endif
if (s->name) {
if (!strcmp(s->name, name)) {s->name = name; return;}
#if !USE_XFT
if (s->xlist && s->n >= 0) XFreeFontNames(s->xlist);
#endif
for (Fl_Font_Descriptor* f = s->first; f;) {
Fl_Font_Descriptor* n = f->next; delete f; f = n;
}
@ -225,7 +237,9 @@ void Fl_Xlib_Graphics_Driver::font_name(int num, const char *name) {
}
s->name = name;
s->fontname[0] = 0;
#if !USE_XFT
s->xlist = 0;
#endif
s->first = 0;
}

View File

@ -94,7 +94,7 @@ static int use_registry(const char *p) {
// turn a stored (with *'s) X font name into a pretty name:
const char* Fl_Xlib_Graphics_Driver::get_font_name(Fl_Font fnum, int* ap) {
Fl_Fontdesc *f = fl_fonts + fnum;
Fl_Xlib_Fontdesc *f = ((Fl_Xlib_Fontdesc*)fl_fonts) + fnum;
if (!f->fontname[0]) {
int type = 0;
const char* p = f->name;
@ -312,9 +312,10 @@ Fl_Font Fl_Xlib_Graphics_Driver::set_fonts(const char* xstarname) {
break;
}
}
if (!fl_fonts[j].xlist) {
fl_fonts[j].xlist = xlist+first_xlist;
fl_fonts[j].n = -(i-first_xlist);
Fl_Xlib_Fontdesc *s = ((Fl_Xlib_Fontdesc*)fl_fonts)+j;
if (!s->xlist) {
s->xlist = xlist+first_xlist;
s->n = -(i-first_xlist);
used_xlist = 1;
}
}
@ -323,8 +324,8 @@ Fl_Font Fl_Xlib_Graphics_Driver::set_fonts(const char* xstarname) {
}
int Fl_Xlib_Graphics_Driver::get_font_sizes(Fl_Font fnum, int*& sizep) {
Fl_Fontdesc *s = fl_fonts+fnum;
if (!s->name) s = fl_fonts; // empty slot in table, use entry 0
Fl_Xlib_Fontdesc *s = ((Fl_Xlib_Fontdesc*)fl_fonts)+fnum;
if (!s->name) s = ((Fl_Xlib_Fontdesc*)fl_fonts); // empty slot in table, use entry 0
if (!s->xlist) {
fl_open_display();
s->xlist = XListFonts(fl_display, s->name, 100, &(s->n));
@ -358,7 +359,7 @@ int Fl_Xlib_Graphics_Driver::get_font_sizes(Fl_Font fnum, int*& sizep) {
#ifndef FL_DOXYGEN
Fl_Font_Descriptor::Fl_Font_Descriptor(const char* name) {
Fl_Xlib_Font_Descriptor::Fl_Xlib_Font_Descriptor(const char* name) : Fl_Font_Descriptor(name, 0) {
font = XCreateUtf8FontStruct(fl_display, name);
if (!font) {
Fl::warning("bad font: %s", name);
@ -372,7 +373,7 @@ Fl_Font_Descriptor::Fl_Font_Descriptor(const char* name) {
Fl_XFont_On_Demand fl_xfont;
Fl_Font_Descriptor::~Fl_Font_Descriptor() {
Fl_Xlib_Font_Descriptor::~Fl_Xlib_Font_Descriptor() {
# if HAVE_GL
// Delete list created by gl_draw(). This is not done by this code
// as it will link in GL unnecessarily. There should be some kind
@ -389,7 +390,7 @@ Fl_Font_Descriptor::~Fl_Font_Descriptor() {
// WARNING: if you add to this table, you must redefine FL_FREE_FONT
// in Enumerations.H & recompile!!
static Fl_Fontdesc built_in_table[] = {
static Fl_Xlib_Fontdesc built_in_table[] = {
{"-*-helvetica-medium-r-normal--*"},
{"-*-helvetica-bold-r-normal--*"},
{"-*-helvetica-medium-o-normal--*"},
@ -408,7 +409,7 @@ static Fl_Fontdesc built_in_table[] = {
{"-*-*zapf dingbats-*"}
};
Fl_Fontdesc* fl_fonts = built_in_table;
Fl_Fontdesc* fl_fonts = (Fl_Fontdesc*)built_in_table;
#define MAXSIZE 32767
@ -554,8 +555,8 @@ static char *put_font_size(const char *n, int size)
char *fl_get_font_xfld(int fnum, int size) {
Fl_Fontdesc* s = fl_fonts+fnum;
if (!s->name) s = fl_fonts; // use font 0 if still undefined
Fl_Xlib_Fontdesc* s = ((Fl_Xlib_Fontdesc*)fl_fonts)+fnum;
if (!s->name) s = (Fl_Xlib_Fontdesc*)fl_fonts; // use font 0 if still undefined
fl_open_display();
return put_font_size(s->name, size);
}
@ -563,15 +564,15 @@ char *fl_get_font_xfld(int fnum, int size) {
// locate or create an Fl_Font_Descriptor for a given Fl_Fontdesc and size:
static Fl_Font_Descriptor* find(int fnum, int size) {
char *name;
Fl_Fontdesc* s = fl_fonts+fnum;
if (!s->name) s = fl_fonts; // use font 0 if still undefined
Fl_Xlib_Fontdesc* s = ((Fl_Xlib_Fontdesc*)fl_fonts)+fnum;
if (!s->name) s = (Fl_Xlib_Fontdesc*)fl_fonts; // use font 0 if still undefined
Fl_Font_Descriptor* f;
for (f = s->first; f; f = f->next)
if (f->size == size) return f;
fl_open_display();
name = put_font_size(s->name, size);
f = new Fl_Font_Descriptor(name);
f = new Fl_Xlib_Font_Descriptor(name);
f->size = size;
f->next = s->first;
s->first = f;
@ -597,7 +598,7 @@ void Fl_Xlib_Graphics_Driver::font_unscaled(Fl_Font fnum, Fl_Fontsize size) {
}
if (fnum == Fl_Graphics_Driver::font() && size == Fl_Graphics_Driver::size()) return;
Fl_Graphics_Driver::font(fnum, size);
Fl_Font_Descriptor* f = find(fnum, size);
Fl_Xlib_Font_Descriptor* f = (Fl_Xlib_Font_Descriptor*)find(fnum, size);
if (f != this->font_descriptor()) {
this->font_descriptor(f);
fl_xfont = f->font->fonts[0];
@ -606,12 +607,12 @@ void Fl_Xlib_Graphics_Driver::font_unscaled(Fl_Font fnum, Fl_Fontsize size) {
}
int Fl_Xlib_Graphics_Driver::height_unscaled() {
if (font_descriptor()) return font_descriptor()->font->ascent + font_descriptor()->font->descent;
if (font_descriptor()) return ((Fl_Xlib_Font_Descriptor*)font_descriptor())->font->ascent + ((Fl_Xlib_Font_Descriptor*)font_descriptor())->font->descent;
else return -1;
}
int Fl_Xlib_Graphics_Driver::descent_unscaled() {
if (font_descriptor()) return font_descriptor()->font->descent;
if (font_descriptor()) return ((Fl_Xlib_Font_Descriptor*)font_descriptor())->font->descent;
else return -1;
}
@ -621,12 +622,12 @@ Fl_Fontsize Fl_Xlib_Graphics_Driver::size_unscaled() {
}
double Fl_Xlib_Graphics_Driver::width_unscaled(const char* c, int n) {
if (font_descriptor()) return (double) XUtf8TextWidth(font_descriptor()->font, c, n);
if (font_descriptor()) return (double) XUtf8TextWidth(((Fl_Xlib_Font_Descriptor*)font_descriptor())->font, c, n);
else return -1;
}
double Fl_Xlib_Graphics_Driver::width_unscaled(unsigned int c) {
if (font_descriptor()) return (double) XUtf8UcsWidth(font_descriptor()->font, c);
if (font_descriptor()) return (double) XUtf8UcsWidth(((Fl_Xlib_Font_Descriptor*)font_descriptor())->font, c);
else return -1;
}
@ -634,11 +635,11 @@ void Fl_Xlib_Graphics_Driver::text_extents_unscaled(const char *c, int n, int &d
if (font_gc != gc_) {
if (!font_descriptor()) font(FL_HELVETICA, FL_NORMAL_SIZE);
font_gc = gc_;
XSetFont(fl_display, gc_, font_descriptor()->font->fid);
XSetFont(fl_display, gc_, ((Fl_Xlib_Font_Descriptor*)font_descriptor())->font->fid);
}
int xx, yy, ww, hh;
xx = yy = ww = hh = 0;
if (gc_) XUtf8_measure_extents(fl_display, fl_window, font_descriptor()->font, gc_, &xx, &yy, &ww, &hh, c, n);
if (gc_) XUtf8_measure_extents(fl_display, fl_window, ((Fl_Xlib_Font_Descriptor*)font_descriptor())->font, gc_, &xx, &yy, &ww, &hh, c, n);
W = ww; H = hh; dx = xx; dy = yy;
// This is the safe but mostly wrong thing we used to do...
@ -652,9 +653,9 @@ void Fl_Xlib_Graphics_Driver::draw_unscaled(const char* c, int n, int x, int y)
if (font_gc != gc_) {
if (!font_descriptor()) this->font(FL_HELVETICA, FL_NORMAL_SIZE);
font_gc = gc_;
XSetFont(fl_display, gc_, font_descriptor()->font->fid);
XSetFont(fl_display, gc_, ((Fl_Xlib_Font_Descriptor*)font_descriptor())->font->fid);
}
if (gc_) XUtf8DrawString(fl_display, fl_window, font_descriptor()->font, gc_, x+offset_x_, y+offset_y_, c, n);
if (gc_) XUtf8DrawString(fl_display, fl_window, ((Fl_Xlib_Font_Descriptor*)font_descriptor())->font, gc_, x+offset_x_, y+offset_y_, c, n);
}
void Fl_Xlib_Graphics_Driver::draw_unscaled(int angle, const char *str, int n, int x, int y) {
@ -673,14 +674,14 @@ void Fl_Xlib_Graphics_Driver::rtl_draw_unscaled(const char* c, int n, int x, int
if (!font_descriptor()) this->font(FL_HELVETICA, FL_NORMAL_SIZE);
font_gc = gc_;
}
if (gc_) XUtf8DrawRtlString(fl_display, fl_window, font_descriptor()->font, gc_, x+offset_x_, y+offset_y_, c, n);
if (gc_) XUtf8DrawRtlString(fl_display, fl_window, ((Fl_Xlib_Font_Descriptor*)font_descriptor())->font, gc_, x+offset_x_, y+offset_y_, c, n);
}
float Fl_Xlib_Graphics_Driver::scale_font_for_PostScript(Fl_Font_Descriptor *desc, int s) {
float ps_size = (float) s;
// Non-Xft fonts can be smaller than required.
// Set the PostScript font size to the display font height
char *name = desc->font->font_name_list[0];
char *name = ((Fl_Xlib_Font_Descriptor*)desc)->font->font_name_list[0];
char *p = strstr(name, "--");
if (p) {
sscanf(p + 2, "%f", &ps_size);

View File

@ -695,13 +695,9 @@ puts("Font Opened"); fflush(stdout);
}
} // end of fontopen
Fl_Font_Descriptor::Fl_Font_Descriptor(const char* name, Fl_Fontsize fsize, int fangle) {
Fl_Xlib_Font_Descriptor::Fl_Xlib_Font_Descriptor(const char* name, Fl_Fontsize fsize, int fangle) : Fl_Font_Descriptor(name, fsize) {
// encoding = fl_encoding_;
size = fsize;
angle = fangle;
#if HAVE_GL
listbase = 0;
#endif // HAVE_GL
font = fontopen(name, fsize, false, angle);
}
@ -729,7 +725,7 @@ static const wchar_t *utf8reformat(const char *str, int& n)
return buffer;
}
static void utf8extents(Fl_Font_Descriptor *desc, const char *str, int n, XGlyphInfo *extents)
static void utf8extents(Fl_Xlib_Font_Descriptor *desc, const char *str, int n, XGlyphInfo *extents)
{
memset(extents, 0, sizeof(XGlyphInfo));
const wchar_t *buffer = utf8reformat(str, n);
@ -741,26 +737,26 @@ static void utf8extents(Fl_Font_Descriptor *desc, const char *str, int n, XGlyph
}
int Fl_Xlib_Graphics_Driver::height_unscaled() {
if (font_descriptor()) return font_descriptor()->font->ascent + font_descriptor()->font->descent;
if (font_descriptor()) return ((Fl_Xlib_Font_Descriptor*)font_descriptor())->font->ascent + ((Fl_Xlib_Font_Descriptor*)font_descriptor())->font->descent;
else return -1;
}
int Fl_Xlib_Graphics_Driver::descent_unscaled() {
if (font_descriptor()) return font_descriptor()->font->descent;
if (font_descriptor()) return ((Fl_Xlib_Font_Descriptor*)font_descriptor())->font->descent;
else return -1;
}
double Fl_Xlib_Graphics_Driver::width_unscaled(const char* str, int n) {
if (!font_descriptor()) return -1.0;
XGlyphInfo i;
utf8extents(font_descriptor(), str, n, &i);
utf8extents((Fl_Xlib_Font_Descriptor*)font_descriptor(), str, n, &i);
return i.xOff;
}
static double fl_xft_width(Fl_Font_Descriptor *desc, FcChar32 *str, int n) {
if (!desc) return -1.0;
XGlyphInfo i;
XftTextExtents32(fl_display, desc->font, str, n, &i);
XftTextExtents32(fl_display, ((Fl_Xlib_Font_Descriptor*)desc)->font, str, n, &i);
return i.xOff;
}
@ -776,7 +772,7 @@ void Fl_Xlib_Graphics_Driver::text_extents_unscaled(const char *c, int n, int &d
return;
}
XGlyphInfo gi;
utf8extents(font_descriptor(), c, n, &gi);
utf8extents((Fl_Xlib_Font_Descriptor*)font_descriptor(), c, n, &gi);
w = gi.width;
h = gi.height;
@ -818,9 +814,9 @@ void Fl_Xlib_Graphics_Driver::draw_unscaled(const char *str, int n, int x, int y
const wchar_t *buffer = utf8reformat(str, n);
#ifdef __CYGWIN__
XftDrawString16(draw_, &color, font_descriptor()->font, x+offset_x_*scale_+line_delta_, y+offset_y_*scale_+line_delta_, (XftChar16 *)buffer, n);
XftDrawString16(draw_, &color, ((Fl_Xlib_Font_Descriptor*)font_descriptor())->font, x+offset_x_*scale_+line_delta_, y+offset_y_*scale_+line_delta_, (XftChar16 *)buffer, n);
#else
XftDrawString32(draw_, &color, font_descriptor()->font, x+offset_x_*scale_+line_delta_, y+offset_y_*scale_+line_delta_, (XftChar32 *)buffer, n);
XftDrawString32(draw_, &color, ((Fl_Xlib_Font_Descriptor*)font_descriptor())->font, x+offset_x_*scale_+line_delta_, y+offset_y_*scale_+line_delta_, (XftChar32 *)buffer, n);
#endif
}
}
@ -862,7 +858,7 @@ void Fl_Xlib_Graphics_Driver::drawUCS4(const void *str, int n, int x, int y) {
color.color.blue = ((int)b)*0x101;
color.color.alpha = 0xffff;
XftDrawString32(draw_, &color, font_descriptor()->font, x+offset_x_*scale_+line_delta_, y+offset_y_*scale_+line_delta_, (FcChar32 *)str, n);
XftDrawString32(draw_, &color, ((Fl_Xlib_Font_Descriptor*)font_descriptor())->font, x+offset_x_*scale_+line_delta_, y+offset_y_*scale_+line_delta_, (FcChar32 *)str, n);
}
@ -998,7 +994,7 @@ float Fl_Xlib_Graphics_Driver::scale_bitmap_for_PostScript() {
return 2;
}
Fl_Font_Descriptor::~Fl_Font_Descriptor() {
Fl_Xlib_Font_Descriptor::~Fl_Xlib_Font_Descriptor() {
if (this == fl_graphics_driver->font_descriptor()) fl_graphics_driver->font_descriptor(NULL);
// XftFontClose(fl_display, font);
}
@ -1019,18 +1015,18 @@ static void fl_xft_font(Fl_Xlib_Graphics_Driver *driver, Fl_Font fnum, Fl_Fontsi
driver->Fl_Graphics_Driver::font(0, 0);
return;
}
Fl_Font_Descriptor* f = driver->font_descriptor();
Fl_Xlib_Font_Descriptor* f = (Fl_Xlib_Font_Descriptor*)driver->font_descriptor();
if (fnum == driver->Fl_Graphics_Driver::font() && size == driver->size_unscaled() && f && f->angle == angle)
return;
driver->Fl_Graphics_Driver::font(fnum, size);
Fl_Fontdesc *font = fl_fonts + fnum;
// search the fontsizes we have generated already
for (f = font->first; f; f = f->next) {
for (f = (Fl_Xlib_Font_Descriptor*)font->first; f; f = (Fl_Xlib_Font_Descriptor*)f->next) {
if (f->size == size && f->angle == angle)// && !strcasecmp(f->encoding, fl_encoding_))
break;
}
if (!f) {
f = new Fl_Font_Descriptor(font->name, size, angle);
f = new Fl_Xlib_Font_Descriptor(font->name, size, angle);
f->next = font->first;
font->first = f;
}
@ -1202,6 +1198,7 @@ PangoContext *Fl_Xlib_Graphics_Driver::context() {
return pctxt_;
}
void Fl_Xlib_Graphics_Driver::font_unscaled(Fl_Font fnum, Fl_Fontsize size) {
if (!size) return;
if (size < 0) {
@ -1215,7 +1212,7 @@ void Fl_Xlib_Graphics_Driver::font_unscaled(Fl_Font fnum, Fl_Fontsize size) {
pfd_ = pango_font_description_from_string(Fl::get_font_name(fnum));
pango_font_description_set_absolute_size(pfd_, size*PANGO_SCALE); // 1.8
if (!pctxt_) context();
Fl_Font_Descriptor *fd = font_descriptor();
Fl_Xlib_Font_Descriptor *fd = (Fl_Xlib_Font_Descriptor*)font_descriptor();
if (!fd->height_) {
PangoFont *pfont = pango_font_map_load_font(pfmap_, pctxt_, pfd_);
PangoRectangle logical_rect;
@ -1339,7 +1336,7 @@ void Fl_Xlib_Graphics_Driver::text_extents_unscaled(const char *str, int n, int
}
int Fl_Xlib_Graphics_Driver::height_unscaled() {
if (font_descriptor()) return font_descriptor()->height_;
if (font_descriptor()) return ((Fl_Xlib_Font_Descriptor*)font_descriptor())->height_;
else return -1;
}
@ -1350,7 +1347,7 @@ double Fl_Xlib_Graphics_Driver::width_unscaled(unsigned int c) {
}
int Fl_Xlib_Graphics_Driver::descent_unscaled() {
if (font_descriptor()) return font_descriptor()->descent_;
if (font_descriptor()) return ((Fl_Xlib_Font_Descriptor*)font_descriptor())->descent_;
else return -1;
}
@ -1433,13 +1430,9 @@ int Fl_Xlib_Graphics_Driver::get_font_sizes(Fl_Font fnum, int*& sizep) {
return 1;
}
Fl_Font_Descriptor::Fl_Font_Descriptor(const char* name, Fl_Fontsize fsize, int fangle) {
Fl_Xlib_Font_Descriptor::Fl_Xlib_Font_Descriptor(const char* name, Fl_Fontsize fsize, int fangle) : Fl_Font_Descriptor(name, fsize) {
fl_open_display();
size = fsize;
angle = fangle;
#if HAVE_GL
listbase = 0;
#endif // HAVE_GL
height_ = 0;
descent_ = 0;
}

View File

@ -1,7 +1,7 @@
//
// "$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.
//
@ -19,12 +19,23 @@
// Functions from <FL/gl.h>
// 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"
#if defined(FL_PORTING)
# pragma message "FL_PORTING: implement OpenGL text rendering here"
#endif
#endif // defined(FL_PORTING)
#include "flstring.h"
#if HAVE_GL || defined(FL_DOXYGEN)
#include <FL/Fl.H>
@ -32,25 +43,13 @@
#include <FL/gl_draw.H>
#include <FL/fl_draw.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)
#include "drivers/Quartz/Fl_Font.H"
# 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
#ifndef GL_TEXTURE_RECTANGLE_ARB
# define GL_TEXTURE_RECTANGLE_ARB 0x84F5
#endif
#include <FL/fl_utf8.h>
/** 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);}
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) {
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_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;
}
#if defined(FL_CFG_GFX_QUARTZ) || defined(FL_CFG_GFX_GDI) || defined(FL_CFG_GFX_XLIB)
void gl_remove_displaylist_fonts()
{
# if HAVE_GL
// clear variables used mostly in fl_font
fl_graphics_driver->font(0, 0);
for (int j = 0 ; j < FL_FREE_FONT ; ++j)
{
Fl_Font_Descriptor* past = 0;
Fl_Fontdesc* s = fl_fonts + j ;
Fl_Font_Descriptor* f = s->first;
Fl_Font_Descriptor** s_first = Fl_Gl_Window_Driver::global()->fontnum_to_fontdescriptor(j);
Fl_Font_Descriptor* f = *s_first;
while (f != 0) {
if(f->listbase) {
if(f == s->first) {
s->first = f->next;
if(f == *s_first) {
*s_first = f->next;
}
else {
past->next = f->next;
}
// 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;
f = f->next;
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
at the current position.
\see On the Mac OS X platform, see gl_texture_pile_height(int)
Draws an array of n characters of the string in the current font at the current position.
\see gl_texture_pile_height(int)
*/
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
\see On the Mac OS X platform, see gl_texture_pile_height(int)
Draws n characters of the string in the current font at the given position
\see gl_texture_pile_height(int)
*/
void gl_draw(const char* str, int n, int x, int y) {
glRasterPos2i(x, y);
@ -157,8 +146,8 @@ 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
\see On the Mac OS X platform, see gl_texture_pile_height(int)
Draws n characters of the string in the current font at the given position
\see gl_texture_pile_height(int)
*/
void gl_draw(const char* str, int n, float x, float y) {
glRasterPos2f(x, y);
@ -167,23 +156,23 @@ 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
\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) {
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)
Draws a nul-terminated string in the current font at the given position
\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)
Draws a nul-terminated string in the current font at the given position
\see gl_texture_pile_height(int)
*/
void gl_draw(const char* str, float x, float y) {
gl_draw(str, strlen(str), x, y);
@ -229,6 +218,13 @@ void gl_rect(int x, int y, int w, int h) {
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.
@ -244,155 +240,29 @@ void gl_color(Fl_Color i) {
}
#if defined(FL_CFG_GFX_XLIB)
#include <FL/platform.H>
#include <GL/glx.h>
#if ! defined(FL_DOXYGEN) // do not want too much of the gl_texture_fifo internals in the documentation
/* Implement the gl_texture_fifo mechanism:
Strings to be drawn are memorized in a fifo pile (which max size can
be increased calling gl_texture_pile_height(int)).
Each pile element contains the string, the font, the GUI scale, and
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.
*/
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) {
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 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 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()
static float gl_scale = 1; // scaling factor between FLTK and GL drawing units: GL = FLTK * gl_scale
// manages a fifo pile of pre-computed string textures
class gl_texture_fifo {
friend class Fl_Cocoa_Gl_Window_Driver;
friend class Fl_Gl_Window_Driver;
private:
typedef struct { // information for a pre-computed texture
GLuint texName; // its name
char *utf8; //its text
Fl_Font_Descriptor *fdesc; // its font
float ratio; // used without rectangle texture
int scale; // 1 or 2 for low/high resolution
float scale; // scaling factor of the GUI
} data;
data *fifo; // array of pile elements
int size_; // pile height
@ -421,10 +291,34 @@ 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);
}
// 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
void gl_texture_fifo::display_texture(int rank)
{
@ -440,46 +334,39 @@ void gl_texture_fifo::display_texture(int rank)
float winw = gl_scale * Fl_Window::current()->w();
float winh = gl_scale * Fl_Window::current()->h();
// GL_COLOR_BUFFER_BIT for glBlendFunc, GL_ENABLE_BIT for glEnable / glDisable
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.
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);
GLfloat pos[4];
glGetFloatv(GL_CURRENT_RASTER_POSITION, pos);
float R = 2;
if (!has_texture_rectangle) {
R *= fifo[rank].ratio;
if (gl_start_scale != 1) { // using gl_start() / gl_finish()
pos[0] /= gl_start_scale;
pos[1] /= gl_start_scale;
}
float R = 2;
glScalef (R/winw, R/winh, 1.0f);
glTranslatef (-winw/R, -winh/R, 0.0f);
GLint width;
if (has_texture_rectangle) {
glEnable (GL_TEXTURE_RECTANGLE_ARB);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, fifo[rank].texName);
GLint height;
glGetTexLevelParameteriv(GL_TEXTURE_RECTANGLE_ARB, 0, GL_TEXTURE_WIDTH, &width);
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
glBegin (GL_QUADS);
glTexCoord2f (0.0f, 0.0f); // draw lower left in world coordinates
glVertex2f (bounds.origin.x, bounds.origin.y);
glTexCoord2f (0.0f, height); // draw upper left in world coordinates
glVertex2f (bounds.origin.x, bounds.origin.y + bounds.size.height);
glTexCoord2f (width, height); // draw upper right in world coordinates
glVertex2f (bounds.origin.x + bounds.size.width, bounds.origin.y + bounds.size.height);
glTexCoord2f (width, 0.0f); // draw lower right in world coordinates
glVertex2f (bounds.origin.x + bounds.size.width, bounds.origin.y);
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);
}
glEnable (GL_TEXTURE_RECTANGLE_ARB);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, fifo[rank].texName);
GLint width, height;
glGetTexLevelParameteriv(GL_TEXTURE_RECTANGLE_ARB, 0, GL_TEXTURE_WIDTH, &width);
glGetTexLevelParameteriv(GL_TEXTURE_RECTANGLE_ARB, 0, GL_TEXTURE_HEIGHT, &height);
//write the texture on screen
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
glVertex2f (ox, oy);
glTexCoord2f (0.0f, height); // draw upper left in world coordinates
glVertex2f (ox, oy - height);
glTexCoord2f (width, height); // draw upper right in world coordinates
glVertex2f (ox + width, oy - height);
glTexCoord2f (width, 0.0f); // draw lower right in world coordinates
glVertex2f (ox + width, oy);
glEnd ();
glPopAttrib();
// reset original matrices
@ -498,14 +385,18 @@ void gl_texture_fifo::display_texture(int rank)
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);
}
} // display_texture
// pre-computes a string texture
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_;
if (current > last) last = current;
if ( fifo[current].utf8 ) free(fifo[current].utf8);
@ -515,89 +406,36 @@ int gl_texture_fifo::compute_texture(const char* str, int n)
fl_graphics_driver->font_descriptor(gl_fontsize);
int w, h;
w = fl_width(fifo[current].utf8, n) * gl_scale;
// Hack - make w be aligned
w = (w + 3) & 0xFFFFFFC;
h = fl_height() * gl_scale;
fifo[current].scale = gl_scale;
fifo[current].fdesc = gl_fontsize;
if (has_texture_rectangle) {
//write str to a bitmap just big enough
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));
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);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, fifo[current].texName);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
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));
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;
char *txt_buf = Fl_Gl_Window_Driver::global()->alpha_mask_for_string(str, n, w, h);
// put the bitmap in an alpha-component-only texture
glPushAttrib(GL_TEXTURE_BIT);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, fifo[current].texName);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
//glPixelStorei(GL_UNPACK_ROW_LENGTH, w);
// 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();
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 && fifo[rank].scale == gl_scale) 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
void Fl_Cocoa_Gl_Window_Driver::draw_string(const char* str, int n)
{
Fl_Gl_Window *gwin = Fl_Window::current()->as_gl_window();
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->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));
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);
}
void gl_texture_reset()
{
if (gl_fifo) gl_texture_pile_height(gl_texture_pile_height());
}
#endif //! defined(FL_DOXYGEN)
/** \addtogroup group_macosx
@{ */
#endif // ! defined(FL_DOXYGEN)
/**
\brief Returns the current height of the pile of pre-computed string textures
*
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)
{
@ -606,23 +444,352 @@ int gl_texture_pile_height(void)
}
/**
\brief Changes the height of the pile of pre-computed string textures
*
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 Height of the texture pile
*/
\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);
}
/** @} */
void Fl_Gl_Window_Driver::draw_string_legacy(const char* str, int n)
{
draw_string_legacy_glut(str, n);
}
/** draws a utf8 string using an OpenGL texture */
void Fl_Gl_Window_Driver::draw_string_with_texture(const char* str, int n)
{
Fl_Gl_Window *gwin = Fl_Window::current()->as_gl_window();
gl_scale = (gwin ? gwin->pixels_per_unit() : 1);
if (!gl_fifo) gl_fifo = new gl_texture_fifo();
if (!gl_fifo->textures_generated) {
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;
}
int index = gl_fifo->already_known(str, n);
if (index == -1) {
index = gl_fifo->compute_texture(str, n);
}
gl_fifo->display_texture(index);
}
char *Fl_Gl_Window_Driver::alpha_mask_for_string(const char *str, int n, int w, int h)
{
// 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);
}
}
/* 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,
and only ASCII characters can be drawn.
*/
void Fl_Gl_Window_Driver::draw_string_legacy_glut(const char* str, int n)
{
uchar *str_nul = new uchar[n + 1];
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);
}
#if defined(FL_CFG_GFX_XLIB)
# include "drivers/Xlib/Fl_Font.H"
# include <FL/platform.H>
# include <GL/glx.h>
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.
*/
char *Fl_Cocoa_Gl_Window_Driver::alpha_mask_for_string(const char *str, int n, int w, int h)
{
// write str to a bitmap just big enough
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 // HAVE_GL
#endif // HAVE_GL || defined(FL_DOXYGEN)
//
// End of "$Id$".

View File

@ -42,23 +42,25 @@ class Fl_Gl_Choice;
static GLContext context;
static int clip_state_number=-1;
static int pw, ph;
float gl_start_scale = 1;
static Fl_Gl_Choice* gl_choice;
/** Creates an OpenGL context */
void gl_start() {
gl_start_scale = Fl_Display_Device::display_device()->driver()->scale();
if (!context) {
if (!gl_choice) Fl::gl_visual(0);
context = Fl_Gl_Window_Driver::global()->create_gl_context(Fl_Window::current(), gl_choice);
}
Fl_Gl_Window_Driver::global()->set_gl_context(Fl_Window::current(), context);
Fl_Gl_Window_Driver::global()->gl_start();
if (pw != Fl_Window::current()->w() || ph != Fl_Window::current()->h()) {
pw = Fl_Window::current()->w();
ph = Fl_Window::current()->h();
if (pw != int(Fl_Window::current()->w() * gl_start_scale) || ph != int(Fl_Window::current()->h() * gl_start_scale)) {
pw = int(Fl_Window::current()->w() * gl_start_scale);
ph = int(Fl_Window::current()->h() * gl_start_scale);
glLoadIdentity();
glViewport(0, 0, pw, ph);
glOrtho(0, pw, 0, ph, -1, 1);
glOrtho(0, Fl_Window::current()->w(), 0, Fl_Window::current()->h(), -1, 1);
glDrawBuffer(GL_FRONT);
}
if (clip_state_number != fl_graphics_driver->fl_clip_state_number) {
@ -67,18 +69,21 @@ void gl_start() {
if (fl_clip_box(0, 0, Fl_Window::current()->w(), Fl_Window::current()->h(),
x, y, w, h)) {
fl_clip_region(Fl_Graphics_Driver::default_driver().XRectangleRegion(x,y,w,h));
glScissor(x, Fl_Window::current()->h()-(y+h), w, h);
glScissor(x*gl_start_scale, (Fl_Window::current()->h()-(y+h))*gl_start_scale, w*gl_start_scale, h*gl_start_scale);
glEnable(GL_SCISSOR_TEST);
} else {
glDisable(GL_SCISSOR_TEST);
}
}
Fl_Display_Device::display_device()->driver()->scale(1);
}
/** Releases an OpenGL context */
void gl_finish() {
glFlush();
Fl_Gl_Window_Driver::global()->waitGL();
Fl_Display_Device::display_device()->driver()->scale(gl_start_scale);
gl_start_scale = 1;
}
void Fl_Gl_Window_Driver::gl_visual(Fl_Gl_Choice *c) {