From 348a95ad30770023457f13642fe7313044de10d5 Mon Sep 17 00:00:00 2001
From: Christophe Geuzaine <cgeuzaine@ulg.ac.be>
Date: Tue, 9 Dec 2014 20:13:41 +0000
Subject: [PATCH] prepare retina support

---
 Common/CreateFile.cpp   | 39 +++++++++++++++++++++------------------
 Fltk/FlGui.cpp          |  6 ++++--
 Fltk/graphicWindow.cpp  |  6 ++++--
 Fltk/openglWindow.cpp   | 34 ++++++++++++++++++++++++++--------
 Fltk/openglWindow.h     |  3 +++
 Graphics/drawScales.cpp | 30 +++++++++++++++---------------
 doc/CREDITS.txt         |  3 ++-
 7 files changed, 75 insertions(+), 46 deletions(-)

diff --git a/Common/CreateFile.cpp b/Common/CreateFile.cpp
index 030a87725f..4649f6d054 100644
--- a/Common/CreateFile.cpp
+++ b/Common/CreateFile.cpp
@@ -135,8 +135,8 @@ static PixelBuffer *GetCompositePixelBuffer(GLenum format, GLenum type)
   openglWindow *newg = 0;
 
   if(CTX::instance()->print.width > 0 || CTX::instance()->print.height > 0){
-    GLint width = FlGui::instance()->getCurrentOpenglWindow()->w();
-    GLint height = FlGui::instance()->getCurrentOpenglWindow()->h();
+    GLint width = FlGui::instance()->getCurrentOpenglWindow()->pixel_w();
+    GLint height = FlGui::instance()->getCurrentOpenglWindow()->pixel_h();
     if(CTX::instance()->print.width <= 0){
       double w = width * CTX::instance()->print.height / (double)height;
       width = (int)w;
@@ -168,8 +168,8 @@ static PixelBuffer *GetCompositePixelBuffer(GLenum format, GLenum type)
 
   PixelBuffer *buffer;
   if(newg || !CTX::instance()->print.compositeWindows){
-    GLint width = FlGui::instance()->getCurrentOpenglWindow()->w();
-    GLint height = FlGui::instance()->getCurrentOpenglWindow()->h();
+    GLint width = FlGui::instance()->getCurrentOpenglWindow()->pixel_w();
+    GLint height = FlGui::instance()->getCurrentOpenglWindow()->pixel_h();
     buffer = new PixelBuffer(width, height, format, type);
     buffer->fill(CTX::instance()->batch);
   }
@@ -188,11 +188,11 @@ static PixelBuffer *GetCompositePixelBuffer(GLenum format, GLenum type)
     std::vector<PixelBuffer*> buffers;
     for(unsigned int i = 0; i < g->gl.size(); i++){
       openglWindow::setLastHandled(g->gl[i]);
-      buffer = new PixelBuffer(g->gl[i]->w(), g->gl[i]->h(), format, type);
+      buffer = new PixelBuffer(g->gl[i]->pixel_w(), g->gl[i]->pixel_h(), format, type);
       buffer->fill(CTX::instance()->batch);
       buffers.push_back(buffer);
-      ww = std::max(ww, g->gl[i]->x() + g->gl[i]->w());
-      hh = std::max(hh, g->gl[i]->y() + g->gl[i]->h());
+      ww = std::max(ww, g->gl[i]->x() + g->gl[i]->pixel_w());
+      hh = std::max(hh, g->gl[i]->y() + g->gl[i]->pixel_h());
     }
     buffer = new PixelBuffer(ww, hh, format, type);
     for(unsigned int i = 0; i < g->gl.size(); i++){
@@ -434,9 +434,9 @@ void CreateOutputFile(const std::string &fileName, int format,
         break;
       }
       std::string base = SplitFileName(name)[1];
-      GLint width = FlGui::instance()->getCurrentOpenglWindow()->w();
-      GLint height = FlGui::instance()->getCurrentOpenglWindow()->h();
-      GLint viewport[4] = {0, 0, width, height};
+      GLint width = FlGui::instance()->getCurrentOpenglWindow()->pixel_w();
+      GLint height = FlGui::instance()->getCurrentOpenglWindow()->pixel_h();
+      GLint pixel_viewport[4] = {0, 0, width, height};
 
       PixelBuffer buffer(width, height, GL_RGB, GL_FLOAT);
 
@@ -464,7 +464,7 @@ void CreateOutputFile(const std::string &fileName, int format,
       int res = GL2PS_OVERFLOW;
       while(res == GL2PS_OVERFLOW) {
         buffsize += 2048 * 2048;
-        gl2psBeginPage(base.c_str(), "Gmsh", viewport,
+        gl2psBeginPage(base.c_str(), "Gmsh", pixel_viewport,
                        psformat, pssort, psoptions, GL_RGBA, 0, NULL,
                        15, 20, 10, buffsize, fp, base.c_str());
         if(CTX::instance()->print.epsQuality == 0){
@@ -473,8 +473,8 @@ void CreateOutputFile(const std::string &fileName, int format,
           glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
           glMatrixMode(GL_PROJECTION);
           glLoadIdentity();
-          glOrtho((double)viewport[0], (double)viewport[2],
-                  (double)viewport[1], (double)viewport[3], -1., 1.);
+          glOrtho((double)pixel_viewport[0], (double)pixel_viewport[2],
+                  (double)pixel_viewport[1], (double)pixel_viewport[3], -1., 1.);
           glMatrixMode(GL_MODELVIEW);
           glLoadIdentity();
           glRasterPos2d(0, 0);
@@ -505,14 +505,14 @@ void CreateOutputFile(const std::string &fileName, int format,
         break;
       }
       std::string base = SplitFileName(name)[1];
-      GLint width = FlGui::instance()->getCurrentOpenglWindow()->w();
-      GLint height = FlGui::instance()->getCurrentOpenglWindow()->h();
-      GLint viewport[4] = {0, 0, width, height};
+      GLint width = FlGui::instance()->getCurrentOpenglWindow()->pixel_w();
+      GLint height = FlGui::instance()->getCurrentOpenglWindow()->pixel_h();
+      GLint pixel_viewport[4] = {0, 0, width, height};
       GLint buffsize = 0;
       int res = GL2PS_OVERFLOW;
       while(res == GL2PS_OVERFLOW) {
         buffsize += 2048 * 2048;
-        gl2psBeginPage(base.c_str(), "Gmsh", viewport,
+        gl2psBeginPage(base.c_str(), "Gmsh", pixel_viewport,
                        GL2PS_TEX, GL2PS_NO_SORT, GL2PS_NONE, GL_RGBA, 0, NULL,
                        0, 0, 0, buffsize, fp, base.c_str());
         int oldtext = CTX::instance()->print.text;
@@ -545,7 +545,10 @@ void CreateOutputFile(const std::string &fileName, int format,
       }
       PixelBuffer *buffer = GetCompositePixelBuffer(GL_RGB, GL_UNSIGNED_BYTE);
       drawContext *ctx = FlGui::instance()->getCurrentOpenglWindow()->getDrawContext();
-      print_pgf(name, num, cnt, buffer, ctx->r, ctx->viewport, ctx->proj, ctx->model);
+      GLint width = FlGui::instance()->getCurrentOpenglWindow()->pixel_w();
+      GLint height = FlGui::instance()->getCurrentOpenglWindow()->pixel_h();
+      GLint pixel_viewport[4] = {0, 0, width, height};
+      print_pgf(name, num, cnt, buffer, ctx->r, pixel_viewport, ctx->proj, ctx->model);
       delete buffer;
       // restore view
       if(restoreGeneralAxis) opt_general_axes(0, GMSH_SET| GMSH_GUI, 1);
diff --git a/Fltk/FlGui.cpp b/Fltk/FlGui.cpp
index cbbe33eb18..cc80c9f9ab 100644
--- a/Fltk/FlGui.cpp
+++ b/Fltk/FlGui.cpp
@@ -269,8 +269,10 @@ FlGui::FlGui(int argc, char **argv)
   Fl_Tooltip::color(FL_LIGHT2);
 #endif
 
-  // FIXME RETINA
-  //Fl::use_high_res_GL(1);
+  // use retina resolution if available
+#if (FL_MAJOR_VERSION == 1) && (FL_MINOR_VERSION == 3) && (FL_PATCH_VERSION >= 4)
+  Fl::use_high_res_GL(1);
+#endif
 
   // register image formats not in core fltk library (jpeg/png)
   fl_register_images();
diff --git a/Fltk/graphicWindow.cpp b/Fltk/graphicWindow.cpp
index 29bc0b5725..bff019d853 100644
--- a/Fltk/graphicWindow.cpp
+++ b/Fltk/graphicWindow.cpp
@@ -3257,11 +3257,13 @@ bool graphicWindow::split(openglWindow *g, char how)
     g2->mode(g->mode());
 
     gl.push_back(g2);
-    _tile->add(g2);
-    g2->show();
 
     g->resize(x1, y1, w1, h1);
     g2->resize(x2, y2, w2, h2);
+
+    _tile->add(g2);
+
+    g2->show();
   }
   return true;
 }
diff --git a/Fltk/openglWindow.cpp b/Fltk/openglWindow.cpp
index aac3a42f82..bdaa482a9d 100644
--- a/Fltk/openglWindow.cpp
+++ b/Fltk/openglWindow.cpp
@@ -157,12 +157,7 @@ void openglWindow::draw()
   _ctx->viewport[1] = 0;
   _ctx->viewport[2] = w();
   _ctx->viewport[3] = h();
-  glViewport(_ctx->viewport[0], _ctx->viewport[1],
-             _ctx->viewport[2], _ctx->viewport[3]);
-
-  // FIXME RETINA
-  //glViewport(_ctx->viewport[0], _ctx->viewport[1],
-  //           2*_ctx->viewport[2], 2*_ctx->viewport[3]);
+  glViewport(0, 0, pixel_w(), pixel_h());
 
   if(lassoMode) {
     // draw the zoom or selection lasso on top of the current scene (without
@@ -245,12 +240,12 @@ void openglWindow::draw()
     if(CTX::instance()->camera && !CTX::instance()->stereo){
       Camera *cam = &(_ctx->camera);
       if (!cam->on) cam->init();
-      cam->giveViewportDimension(_ctx->viewport[2],_ctx->viewport[3]);
+      cam->giveViewportDimension(_ctx->viewport[2], _ctx->viewport[3]);
       glMatrixMode(GL_PROJECTION);
       glLoadIdentity();
 
       glFrustum(cam->glFleft, cam->glFright, cam->glFbottom,
-                cam->glFtop, cam->glFnear , cam->glFfar*cam->Lc );
+                cam->glFtop, cam->glFnear, cam->glFfar*cam->Lc);
 
       glMatrixMode(GL_MODELVIEW);
       glLoadIdentity();
@@ -676,6 +671,29 @@ int openglWindow::handle(int event)
   }
 }
 
+int openglWindow::pixel_w()
+{
+#if (FL_MAJOR_VERSION == 1) && (FL_MINOR_VERSION == 3) && (FL_PATCH_VERSION >= 4)
+  return Fl_Gl_Window::pixel_w();
+#else
+  return w();
+#endif
+}
+
+int openglWindow::pixel_h()
+{
+#if (FL_MAJOR_VERSION == 1) && (FL_MINOR_VERSION == 3) && (FL_PATCH_VERSION >= 4)
+  return Fl_Gl_Window::pixel_h();
+#else
+  return h();
+#endif
+}
+
+bool openglWindow::retina()
+{
+  return pixel_w() > w();
+}
+
 bool openglWindow::_select(int type, bool multiple, bool mesh,
                            int x, int y, int w, int h,
                            std::vector<GVertex*> &vertices,
diff --git a/Fltk/openglWindow.h b/Fltk/openglWindow.h
index eb1e51e2a6..9d2ad23688 100644
--- a/Fltk/openglWindow.h
+++ b/Fltk/openglWindow.h
@@ -40,6 +40,9 @@ class openglWindow : public Fl_Gl_Window {
   void draw();
   int handle(int);
  public:
+  int pixel_w();
+  int pixel_h();
+  bool retina();
   time_t  rawtime,  prev_rawtime;
   double response_frequency;
   bool addPointMode, lassoMode, selectionMode;
diff --git a/Graphics/drawScales.cpp b/Graphics/drawScales.cpp
index 386704c158..ef9a304c4f 100644
--- a/Graphics/drawScales.cpp
+++ b/Graphics/drawScales.cpp
@@ -10,7 +10,7 @@
 #include "Context.h"
 #include "gl2ps.h"
 
-static void drawScaleBar(PView *p, double xmin, double ymin, double width, 
+static void drawScaleBar(PView *p, double xmin, double ymin, double width,
                          double height, double tic, int horizontal)
 {
   PViewOptions *opt = p->getOptions();
@@ -91,7 +91,7 @@ static void drawScaleValues(drawContext *ctx, PView *p, double xmin, double ymin
   drawContext::global()->setFont(CTX::instance()->glFontEnum,
                                  CTX::instance()->glFontSize);
   double font_h = drawContext::global()->getStringHeight(); // total font height
-  double font_a = drawContext::global()->getStringHeight() - 
+  double font_a = drawContext::global()->getStringHeight() -
     drawContext::global()->getStringDescent(); // height above ref pt
 
   char label[1024];
@@ -153,19 +153,19 @@ static void drawScaleValues(drawContext *ctx, PView *p, double xmin, double ymin
   }
 }
 
-static void drawScaleLabel(drawContext *ctx, PView *p, double xmin, double ymin, 
+static void drawScaleLabel(drawContext *ctx, PView *p, double xmin, double ymin,
                            double width, double height, double tic, int horizontal)
 {
   PViewOptions *opt = p->getOptions();
   PViewData *data;
-  
+
   // requested by Laurent: but is this really what we should be doing?
   if(opt->externalViewIndex >= 0 && opt->externalViewIndex < (int)PView::list.size())
     data = PView::list[opt->externalViewIndex]->getData();
   else
     data = p->getData();
 
-  drawContext::global()->setFont(CTX::instance()->glFontEnum, 
+  drawContext::global()->setFont(CTX::instance()->glFontEnum,
                                  CTX::instance()->glFontSize);
   double font_h = drawContext::global()->getStringHeight();
 
@@ -178,22 +178,22 @@ static void drawScaleLabel(drawContext *ctx, PView *p, double xmin, double ymin,
     sprintf(label, "%s (%s)", data->getName().c_str(), tmp);
   }
   else if((opt->showTime == 3 && nt > 1) || opt->showTime == 4){
-    sprintf(label, "%s (%d/%d)", data->getName().c_str(), opt->timeStep, 
+    sprintf(label, "%s (%d/%d)", data->getName().c_str(), opt->timeStep,
             data->getNumTimeSteps() - 1);
   }
   else
     sprintf(label, "%s", data->getName().c_str());
- 
+
   if(horizontal){
     glRasterPos2d(xmin + width / 2., ymin + height + tic + 1.4 * font_h);
-    ctx->drawString(label, CTX::instance()->glFontTitle, 
+    ctx->drawString(label, CTX::instance()->glFontTitle,
                     CTX::instance()->glFontEnumTitle,
                     CTX::instance()->glFontSizeTitle, 1);
   }
   else{
     glRasterPos2d(xmin, ymin - 2 * font_h);
-    ctx->drawString(label, CTX::instance()->glFontTitle, 
-                    CTX::instance()->glFontEnumTitle, 
+    ctx->drawString(label, CTX::instance()->glFontTitle,
+                    CTX::instance()->glFontEnumTitle,
                     CTX::instance()->glFontSizeTitle, 0);
   }
 }
@@ -233,14 +233,14 @@ void drawContext::drawScales()
   for(unsigned int i = 0; i < PView::list.size(); i++){
     PViewData *data = PView::list[i]->getData();
     PViewOptions *opt = PView::list[i]->getOptions();
-    if(!data->getDirty() && opt->visible && opt->showScale && 
+    if(!data->getDirty() && opt->visible && opt->showScale &&
        opt->type == PViewOptions::Plot3D && data->getNumElements() &&
        isVisible(PView::list[i]))
       scales.push_back(PView::list[i]);
   }
   if(scales.empty()) return;
 
-  drawContext::global()->setFont(CTX::instance()->glFontEnum, 
+  drawContext::global()->setFont(CTX::instance()->glFontEnum,
                                  CTX::instance()->glFontSize);
   char label[1024];
   double maxw = 0.;
@@ -257,7 +257,7 @@ void drawContext::drawScales()
     PView *p = scales[i];
     PViewData *data = p->getData();
     PViewOptions *opt = p->getOptions();
-    
+
     if(!opt->autoPosition) {
       double w = opt->size[0], h = opt->size[1];
       double x = opt->position[0], y = opt->position[1] - h;
@@ -280,8 +280,8 @@ void drawContext::drawScales()
         if(w < 20.) w = 20.;
         double h = bar_size;
         double x = xc - (i % 2 ? -xsep / 1.5 : w + xsep / 1.5);
-        double y = viewport[1] + ysep + 
-          (i / 2) * (bar_size + tic + 
+        double y = viewport[1] + ysep +
+          (i / 2) * (bar_size + tic +
                      2 * drawContext::global()->getStringHeight() + ysep);
         drawScale(this, p, x, y, w, h, tic, 1);
       }
diff --git a/doc/CREDITS.txt b/doc/CREDITS.txt
index 4cf17e0a50..e69aa426b5 100644
--- a/doc/CREDITS.txt
+++ b/doc/CREDITS.txt
@@ -130,4 +130,5 @@ Van den Abeele, Simon Vun, Simon Corbin, Thomas De-Soza, Marcus Drosson, Antoine
 Dechaume, Jose Paulo Moitinho de Almeida, Thomas Pinchard, Corrado Chisari, Axel
 Hackbarth, Peter Wainwright, Jiri Hnidek, Thierry Thomas, Konstantinos Poulios,
 Laurent Van Miegroet, Shahrokh Ghavamian, Geordie McBain, Jose Paulo Moitinho de
-Almeida, Guillaume Demesy, Wendy Merks-Swolfs, Cosmin Stefan Deaconu, Nigel Nunn.
+Almeida, Guillaume Demesy, Wendy Merks-Swolfs, Cosmin Stefan Deaconu, Nigel
+Nunn, Serban Georgescu.
-- 
GitLab