diff options
| author | Manolo Gouy <Manolo> | 2018-02-07 15:34:44 +0000 |
|---|---|---|
| committer | Manolo Gouy <Manolo> | 2018-02-07 15:34:44 +0000 |
| commit | dcc82d8926e447e422f200d01e1aa990233bc16a (patch) | |
| tree | bc0d120f1381e0e8c0ef5c66262289e93d3b9a08 /src | |
| parent | 90630409cbe8740d2c8b66823757a4ea5441aa21 (diff) | |
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
Diffstat (limited to 'src')
| -rw-r--r-- | src/Fl.cxx | 2 | ||||
| -rw-r--r-- | src/Fl_Gl_Window.cxx | 4 | ||||
| -rw-r--r-- | src/Fl_Graphics_Driver.cxx | 12 | ||||
| -rw-r--r-- | src/drivers/GDI/Fl_Font.H | 30 | ||||
| -rw-r--r-- | src/drivers/GDI/Fl_GDI_Graphics_Driver.H | 3 | ||||
| -rw-r--r-- | src/drivers/GDI/Fl_GDI_Graphics_Driver_font.cxx | 31 | ||||
| -rw-r--r-- | src/drivers/Quartz/Fl_Font.H | 32 | ||||
| -rw-r--r-- | src/drivers/Quartz/Fl_Quartz_Graphics_Driver.H | 11 | ||||
| -rw-r--r-- | src/drivers/Quartz/Fl_Quartz_Graphics_Driver_font.cxx | 45 | ||||
| -rw-r--r-- | src/drivers/Xlib/Fl_Font.H | 28 | ||||
| -rw-r--r-- | src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H | 2 | ||||
| -rw-r--r-- | src/drivers/Xlib/Fl_Xlib_Graphics_Driver.cxx | 20 | ||||
| -rw-r--r-- | src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.cxx | 53 | ||||
| -rw-r--r-- | src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.cxx | 45 | ||||
| -rw-r--r-- | src/gl_draw.cxx | 797 | ||||
| -rw-r--r-- | src/gl_start.cxx | 15 |
16 files changed, 628 insertions, 502 deletions
diff --git a/src/Fl.cxx b/src/Fl.cxx index e6af1297b..630d77d3f 100644 --- a/src/Fl.cxx +++ b/src/Fl.cxx @@ -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(); diff --git a/src/Fl_Gl_Window.cxx b/src/Fl_Gl_Window.cxx index 27aa4ced5..9687fd1ec 100644 --- a/src/Fl_Gl_Window.cxx +++ b/src/Fl_Gl_Window.cxx @@ -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> diff --git a/src/Fl_Graphics_Driver.cxx b/src/Fl_Graphics_Driver.cxx index 2cbf0f238..d7cb15031 100644 --- a/src/Fl_Graphics_Driver.cxx +++ b/src/Fl_Graphics_Driver.cxx @@ -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; diff --git a/src/drivers/GDI/Fl_Font.H b/src/drivers/GDI/Fl_Font.H index fd36aab24..b530ec422 100644 --- a/src/drivers/GDI/Fl_Font.H +++ b/src/drivers/GDI/Fl_Font.H @@ -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 diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver.H b/src/drivers/GDI/Fl_GDI_Graphics_Driver.H index fea0ccac4..8de2a9a1d 100644 --- a/src/drivers/GDI/Fl_GDI_Graphics_Driver.H +++ b/src/drivers/GDI/Fl_GDI_Graphics_Driver.H @@ -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(); }; diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver_font.cxx b/src/drivers/GDI/Fl_GDI_Graphics_Driver_font.cxx index 360076b0f..c9d74e59e 100644 --- a/src/drivers/GDI/Fl_GDI_Graphics_Driver_font.cxx +++ b/src/drivers/GDI/Fl_GDI_Graphics_Driver_font.cxx @@ -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; diff --git a/src/drivers/Quartz/Fl_Font.H b/src/drivers/Quartz/Fl_Font.H index 00a96370c..e6c56a75c 100644 --- a/src/drivers/Quartz/Fl_Font.H +++ b/src/drivers/Quartz/Fl_Font.H @@ -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 diff --git a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.H b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.H index 7e936c2d3..60a261e94 100644 --- a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.H +++ b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.H @@ -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 }; diff --git a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_font.cxx b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_font.cxx index 597c1c1cc..7e1717650 100644 --- a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_font.cxx +++ b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_font.cxx @@ -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; diff --git a/src/drivers/Xlib/Fl_Font.H b/src/drivers/Xlib/Fl_Font.H index 0bc4b200e..49917b6d3 100644 --- a/src/drivers/Xlib/Fl_Font.H +++ b/src/drivers/Xlib/Fl_Font.H @@ -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 diff --git a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H index 09f0dd31b..8e44e2371 100644 --- a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H +++ b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H @@ -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); diff --git a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.cxx b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.cxx index fd21de07c..dfae0c006 100644 --- a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.cxx +++ b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.cxx @@ -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; } diff --git a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.cxx b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.cxx index dcb209154..377be7c91 100644 --- a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.cxx +++ b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.cxx @@ -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); diff --git a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.cxx b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.cxx index 5bda05e5c..e5d62492a 100644 --- a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.cxx +++ b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.cxx @@ -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; } diff --git a/src/gl_draw.cxx b/src/gl_draw.cxx index 6ce4c8d57..ebaa1d2e5 100644 --- a/src/gl_draw.cxx +++ b/src/gl_draw.cxx @@ -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,114 +406,390 @@ 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) +#endif // ! defined(FL_DOXYGEN) + +/** + 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; - 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; + if (! gl_fifo) gl_fifo = new gl_texture_fifo(); + return gl_fifo->size(); } -static gl_texture_fifo *gl_fifo = NULL; // points to the texture pile class instance +/** + Changes the maximum height of the pile of pre-computed string textures -// draws a utf8 string using pre-computed texture if available -void Fl_Cocoa_Gl_Window_Driver::draw_string(const char* str, int n) + 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); +} + + +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); - - //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) { - 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); + int index = gl_fifo->already_known(str, n); + if (index == -1) { + 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; } -#endif //! defined(FL_DOXYGEN) -/** \addtogroup group_macosx - @{ */ +// 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); + } +} -/** - \brief Returns the current height of the pile of pre-computed string textures - * - The default value is 100 +/* 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. */ -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(); - return gl_fifo->size(); + 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); } -/** - \brief Changes the height of the pile of pre-computed string textures - * - Strings that are often re-displayed can be processed much faster if - this pile is set high enough to hold all of them. - \param max Height of the texture pile + +#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. */ -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; - gl_fifo = new gl_texture_fifo(max); + // 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$". diff --git a/src/gl_start.cxx b/src/gl_start.cxx index 878b99a55..c2f4727ee 100644 --- a/src/gl_start.cxx +++ b/src/gl_start.cxx @@ -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) { |
