diff --git a/Common/Options.cpp b/Common/Options.cpp index 8a5378e394c1adc606884b1071bd7586fe9ad5de..3e59ae16d97b5fd97de7a9cc65618a3f15132af2 100644 --- a/Common/Options.cpp +++ b/Common/Options.cpp @@ -52,6 +52,7 @@ #include "onelabGroup.h" #include "viewButton.h" #include "drawContextFltkCairo.h" +#include "drawContextFltkStringTexture.h" #endif // General routines for string options @@ -1247,6 +1248,9 @@ std::string opt_general_graphics_font_engine(OPT_ARGS_STR) drawContext::setGlobal(new drawContextFltkCairo); else #endif + if(CTX::instance()->glFontEngine == "StringTexture") + drawContext::setGlobal(new drawContextFltkStringTexture); + else drawContext::setGlobal(new drawContextFltk); if(old) delete old; } @@ -1256,6 +1260,7 @@ std::string opt_general_graphics_font_engine(OPT_ARGS_STR) #if defined(HAVE_CAIRO) if(CTX::instance()->glFontEngine == "Cairo") index = 1; #endif + if(CTX::instance()->glFontEngine == "StringTexture") index = 2; FlGui::instance()->options->general.choice[7]->value(index); } #endif diff --git a/Fltk/CMakeLists.txt b/Fltk/CMakeLists.txt index 545fb76198ccb49d3444122849c1359d2a8d82c9..6468c1d7906984d8d513b22390a02655397eaef3 100644 --- a/Fltk/CMakeLists.txt +++ b/Fltk/CMakeLists.txt @@ -10,6 +10,7 @@ set(SRC optionWindow.cpp colorbarWindow.cpp drawContextFltkCairo.cpp + drawContextFltkStringTexture.cpp gamepadWindow.cpp fieldWindow.cpp pluginWindow.cpp diff --git a/Fltk/drawContextFltkCairo.cpp b/Fltk/drawContextFltkCairo.cpp index 0cde498d7585c4a10f6bf5b389507039ff8fc22e..b796296f0b4848a6fae99a719c069b2f575691d0 100644 --- a/Fltk/drawContextFltkCairo.cpp +++ b/Fltk/drawContextFltkCairo.cpp @@ -18,12 +18,13 @@ class drawContextFltkCairo::queueString { GLfloat r, g, b, alpha; int fontSize; cairo_font_face_t *fontFace; - cairo_text_extents_t extent; + int width, height; + double xBearing, yBearing; } element; private: std::vector<element> _elements; - double _totalWidth, _maxHeight; + int _totalWidth, _maxHeight; public: queueString() @@ -41,30 +42,31 @@ class drawContextFltkCairo::queueString { void append(const element &elem) { - if (_totalWidth + elem.extent.width > 1000) + if (_totalWidth + elem.width > 1000) flush(); _elements.push_back(elem); - _totalWidth += elem.extent.width; - _maxHeight = std::max(_maxHeight, elem.extent.height); + _totalWidth += elem.width; + _maxHeight = std::max(_maxHeight, (int)elem.height + 1); + printf("%s : %g %i\n", elem.text.c_str(), elem.yBearing, elem.height); } void flush() { cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_A8, _totalWidth, _maxHeight); cairo_t *cr = cairo_create(surface); - float pos = 0; + int pos = 0; cairo_set_source_rgba (cr, 0., 0., 0., 0); cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); cairo_paint(cr); cairo_set_operator(cr, CAIRO_OPERATOR_OVER); cairo_set_source_rgba(cr, 1, 1, 1, 1); for(std::vector<element>::iterator it = _elements.begin(); it != _elements.end(); ++it) { - cairo_move_to(cr, pos - it->extent.x_bearing, -it->extent.y_bearing); + cairo_move_to(cr, pos - it->xBearing, -it->yBearing); cairo_set_font_size(cr, it->fontSize); cairo_set_font_face(cr, it->fontFace); cairo_show_text(cr, it->text.c_str()); cairo_font_face_destroy(it->fontFace); - pos += it->extent.width; + pos += it->width; } cairo_destroy(cr); //setup matrices @@ -100,8 +102,8 @@ class drawContextFltkCairo::queueString { for(std::vector<element>::iterator it = _elements.begin(); it != _elements.end(); ++it) { glTranslatef(it->x, it->y, it->z); glColor4f(it->r, it->g, it->b, it->alpha); - float Lx = it->extent.width; - float Ly = it->extent.height; + int Lx = it->width; + int Ly = it->height; glBegin (GL_QUADS); glTexCoord2f (pos, 0); @@ -149,7 +151,6 @@ void drawContextFltkCairo::flushString() _queue->flush(); } -//ensure the surface is large enough void drawContextFltkCairo::drawString(const char *str) { GLfloat pos[4], color[4]; @@ -159,27 +160,10 @@ void drawContextFltkCairo::drawString(const char *str) cairo_text_extents_t extent; cairo_text_extents(_cr, str, &extent); queueString::element elem = {str, pos[0], pos[1], pos[2], color[0], color[1], color[2], color[3], - _currentFontSize, cairo_get_font_face(_cr), extent}; + _currentFontSize, cairo_get_font_face(_cr), (int)ceil(extent.width), (int)ceil(extent.height), + extent.x_bearing, extent.y_bearing}; cairo_font_face_reference(elem.fontFace); _queue->append(elem); - // fltk version (fl_read_image is too slow) - /*Fl_Offscreen offscreen = fl_create_offscreen(100, 100); - fl_begin_offscreen(offscreen); - fl_color(0, 0, 0); - fl_rectf(0, 0, 100, 100); - fl_color(255, 255, 255); - fl_draw(str, 10, 90); - fl_read_image(data, 0, 0, 100, 100); - - CGContextRef src = (CGContextRef)fl_gc; // get bitmap context - - uchar *base = (uchar *)CGBitmapContextGetData(src); // get data - for (int i = 0; i < 100 * 100; ++i) { - data[i] = data[i * 3]; - } - fl_end_offscreen(); - fl_delete_offscreen(offscreen); - */ } drawContextFltkCairo::~drawContextFltkCairo() diff --git a/Fltk/drawContextFltkStringTexture.cpp b/Fltk/drawContextFltkStringTexture.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4b44f6ff1978d9e7c8b8d3486e72ce84bfeba33b --- /dev/null +++ b/Fltk/drawContextFltkStringTexture.cpp @@ -0,0 +1,160 @@ +// Gmsh - Copyright (C) 1997-2013 C. Geuzaine, J.-F. Remacle +// +// See the LICENSE.txt file for license information. Please report all +// bugs and problems to the public mailing list <gmsh@geuz.org>. +// +// Contributed by Jonathan Lambrechts + +#include "drawContextFltkStringTexture.h" + +class drawContextFltkStringTexture::queueString { + public : + typedef struct { + std::string text; + GLfloat x, y, z; + GLfloat r, g, b, alpha; + int fontSize, fontId; + int width; + int height; + } element; + + private: + std::vector<element> _elements; + int _totalWidth, _maxHeight; + + public: + queueString() + { + _totalWidth = 0; + _maxHeight = 0; + } + + void append(const element &elem) + { + if (_totalWidth + elem.width > 1000) + flush(); + _elements.push_back(elem); + _totalWidth += elem.width; + _maxHeight = std::max(_maxHeight, elem.height); + } + + void flush() + { + //1000 should be _totalWidth but it does not work + int w = 1000, h = _maxHeight; + Fl_Offscreen offscreen = fl_create_offscreen(w, h); + fl_begin_offscreen(offscreen); + fl_color(0, 0, 0); + fl_rectf(0, 0, w, h); + fl_color(255, 255, 255); + int pos = 0; + for(std::vector<element>::iterator it = _elements.begin(); it != _elements.end(); ++it) { + fl_font(it->fontId, it->fontSize); + fl_draw(it->text.c_str(), pos, it->height - fl_descent()); + pos += it->width; + } + uchar *data = fl_read_image(NULL, 0, 0, w, h); + for (int i = 0; i < w * h; ++i) { + data[i] = data[i * 3]; + } + fl_end_offscreen(); + fl_delete_offscreen(offscreen); + + //setup matrices + GLint matrixMode; + GLuint textureId; + glGetIntegerv (GL_MATRIX_MODE, &matrixMode); + glMatrixMode (GL_PROJECTION); + glPushMatrix(); + glLoadIdentity (); + glMatrixMode (GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity (); + float winw = Fl_Window::current()->w(); + float winh = Fl_Window::current()->h(); + glScalef (2.0f / winw, 2.0f / winh, 1.0f); + glTranslatef (-winw / 2.0f, -winh / 2.0f, 0.0f); + //write the texture on screen + glEnable (GL_TEXTURE_RECTANGLE); + glPushAttrib(GL_ENABLE_BIT | GL_TEXTURE_BIT | GL_COLOR_BUFFER_BIT); + glDisable(GL_LIGHTING); + glDisable (GL_DEPTH_TEST); + glEnable (GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glGenTextures (1, &textureId); + glBindTexture (GL_TEXTURE_RECTANGLE, textureId); + glTexImage2D (GL_TEXTURE_RECTANGLE, 0, GL_ALPHA, w, h, 0, + GL_ALPHA, GL_UNSIGNED_BYTE, data); + //glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_SRC0_ALPHA); + //printf("error %i %s\n", __LINE__, gluErrorString(glGetError())); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + + pos = 0; + for(std::vector<element>::iterator it = _elements.begin(); it != _elements.end(); ++it) { + glTranslatef(it->x, it->y, it->z); + glColor4f(it->r, it->g, it->b, it->alpha); + int Lx = it->width; + int Ly = it->height; + + glBegin (GL_QUADS); + glTexCoord2f(pos, 0); + glVertex2f(0.0f, Ly); + glTexCoord2f(pos + Lx, 0); + glVertex2f(Lx, Ly); + glTexCoord2f(pos + Lx, Ly); + glVertex2f(Lx, 0.0f); + glTexCoord2f(pos, Ly); + glVertex2f(0.0f, 0.0f); + glEnd (); + pos += Lx; + glTranslatef(-it->x, -it->y, -it->z); + } + glDeleteTextures(1, &textureId); + + glPopAttrib(); + + // reset original matrices + glPopMatrix(); // GL_MODELVIEW + glMatrixMode (GL_PROJECTION); + glPopMatrix(); + glMatrixMode (matrixMode); + _elements.clear(); + _maxHeight = 0; + _totalWidth = 0; + delete []data; + } +}; + +void drawContextFltkStringTexture::flushString() +{ + _queue->flush(); +} + +//ensure the surface is large enough +void drawContextFltkStringTexture::drawString(const char *str) +{ + GLfloat pos[4], color[4]; + glGetFloatv(GL_CURRENT_RASTER_POSITION, pos); + glGetFloatv(GL_CURRENT_COLOR, color); + queueString::element elem = {str, pos[0], pos[1], pos[2], color[0], color[1], color[2], color[3], + _currentFontSize, _currentFontId, getStringWidth(str) + 1, getStringHeight()}; + _queue->append(elem); +} + +drawContextFltkStringTexture::~drawContextFltkStringTexture() +{ + delete _queue; +} + +drawContextFltkStringTexture::drawContextFltkStringTexture() +{ + _queue = new queueString; +} + +void drawContextFltkStringTexture::setFont(int fontid, int fontsize) +{ + drawContextFltk::setFont(fontid, fontsize); + _currentFontId = fontid; + _currentFontSize = fontsize; +} + diff --git a/Fltk/drawContextFltkStringTexture.h b/Fltk/drawContextFltkStringTexture.h new file mode 100644 index 0000000000000000000000000000000000000000..cd0fe3e92be8e95b58ca155c6c1a1c13da0f1a73 --- /dev/null +++ b/Fltk/drawContextFltkStringTexture.h @@ -0,0 +1,28 @@ +// Gmsh - Copyright (C) 1997-2013 C. Geuzaine, J.-F. Remacle +// +// See the LICENSE.txt file for license information. Please report all +// bugs and problems to the public mailing list <gmsh@geuz.org>. +// +// Contributed by Jonathan Lambrechts + +#ifndef _DRAW_CONTEXT_FLTK_STRING_TEXTURE_H_ +#define _DRAW_CONTEXT_FLTK_STRING_TEXTURE_H_ + +#include "drawContextFltk.h" + + +class drawContextFltkStringTexture : public drawContextFltk { + class queueString; + queueString *_queue; + int _currentFontId; + int _currentFontSize; + public: + drawContextFltkStringTexture(); + ~drawContextFltkStringTexture(); + void flushString(); + void drawString(const char *str); + void setFont(int fontid, int fontsize); + std::string getName(){ return "StringTexture"; } +}; + +#endif diff --git a/Fltk/optionWindow.cpp b/Fltk/optionWindow.cpp index dbd261eb33a549926f6deca069604cf8f63d1492..f951697b0b6b87630693cb77aed0535de0e1ae49 100644 --- a/Fltk/optionWindow.cpp +++ b/Fltk/optionWindow.cpp @@ -1678,6 +1678,7 @@ optionWindow::optionWindow(int deltaFontSize) static Fl_Menu_Item menu_font_engine[] = { {"Native", 0, 0, 0}, {"Cairo", 0, 0, 0}, + {"StringTexture", 0, 0, 0}, {0} }; general.choice[7] = new Fl_Choice