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