644 lines
15 KiB
C
Executable File
644 lines
15 KiB
C
Executable File
/** \file
|
|
* \brief GL Drawing functions.
|
|
*
|
|
* See Copyright Notice in "iup.h"
|
|
*/
|
|
|
|
#ifdef WIN32
|
|
#include <windows.h>
|
|
#endif
|
|
|
|
#if defined (__APPLE__) || defined (OSX)
|
|
#include <OpenGL/gl.h>
|
|
#else
|
|
#include <GL/gl.h>
|
|
#endif
|
|
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <math.h>
|
|
|
|
#include "iup.h"
|
|
|
|
#include "iup_assert.h"
|
|
#include "iup_object.h"
|
|
#include "iup_attrib.h"
|
|
#include "iup_str.h"
|
|
#include "iup_array.h"
|
|
#include "iup_image.h"
|
|
|
|
#include "iup_glcontrols.h"
|
|
#include "iup_glfont.h"
|
|
#include "iup_gldraw.h"
|
|
#include "iup_glicon.h"
|
|
#include "iup_glimage.h"
|
|
|
|
|
|
#define iupGLDrawCheckSwapCoord(_c1, _c2) { if (_c1 > _c2) { int t = _c2; _c2 = _c1; _c1 = t; } } /* make sure _c1 is smaller than _c2 */
|
|
|
|
void iupGLDrawLine(Ihandle* ih, int x1, int y1, int x2, int y2, float linewidth, const char* color, int active)
|
|
{
|
|
unsigned char r = 0, g = 0, b = 0, a = 255;
|
|
|
|
if (!color || linewidth == 0)
|
|
return;
|
|
|
|
iupStrToRGBA(color, &r, &g, &b, &a);
|
|
if (!active)
|
|
iupGLColorMakeInactive(&r, &g, &b);
|
|
|
|
glColor4ub(r, g, b, a);
|
|
|
|
glLineWidth(linewidth);
|
|
|
|
/* y is oriented top to bottom in IUP */
|
|
y1 = ih->currentheight - 1 - y1;
|
|
y2 = ih->currentheight - 1 - y2;
|
|
|
|
glBegin(GL_LINES);
|
|
glVertex2i(x1, y1);
|
|
glVertex2i(x2, y2);
|
|
glEnd();
|
|
}
|
|
|
|
void iupGLDrawFrameRect(Ihandle* ih, int xmin, int xmax, int ymin, int ymax, float linewidth, const char* color, int active, int title_x, int title_width, int title_height)
|
|
{
|
|
unsigned char r = 0, g = 0, b = 0, a = 255;
|
|
int d = 2;
|
|
|
|
if (!color || linewidth == 0 || xmin == xmax || ymin == ymax)
|
|
return;
|
|
|
|
iupGLDrawCheckSwapCoord(xmin, xmax);
|
|
iupGLDrawCheckSwapCoord(ymin, ymax);
|
|
|
|
iupStrToRGBA(color, &r, &g, &b, &a);
|
|
if (!active)
|
|
iupGLColorMakeInactive(&r, &g, &b);
|
|
|
|
glColor4ub(r, g, b, a);
|
|
|
|
glLineWidth(linewidth);
|
|
|
|
/* y is oriented top to bottom in IUP */
|
|
ymin = ih->currentheight - 1 - ymin;
|
|
ymax = ih->currentheight - 1 - ymax;
|
|
iupGLDrawCheckSwapCoord(ymin, ymax);
|
|
|
|
/* position frame title at left-center */
|
|
ymax -= title_height / 2;
|
|
|
|
glBegin(GL_LINE_STRIP);
|
|
|
|
glVertex2i(xmin + title_x + title_width, ymax);
|
|
|
|
glVertex2i(xmax - d, ymax);
|
|
glVertex2i(xmax, ymax - d);
|
|
|
|
glVertex2i(xmax, ymin + d);
|
|
glVertex2i(xmax - d, ymin);
|
|
|
|
glVertex2i(xmin + d, ymin);
|
|
glVertex2i(xmin, ymin + d);
|
|
|
|
glVertex2i(xmin, ymax - d);
|
|
glVertex2i(xmin + d, ymax);
|
|
|
|
glVertex2i(xmin + title_x, ymax);
|
|
|
|
glEnd();
|
|
}
|
|
|
|
void iupGLDrawRect(Ihandle* ih, int xmin, int xmax, int ymin, int ymax, float linewidth, const char* color, int active, int round)
|
|
{
|
|
unsigned char r = 0, g = 0, b = 0, a = 255;
|
|
|
|
if (!color || linewidth == 0 || xmin == xmax || ymin == ymax)
|
|
return;
|
|
|
|
iupGLDrawCheckSwapCoord(xmin, xmax);
|
|
iupGLDrawCheckSwapCoord(ymin, ymax);
|
|
|
|
iupStrToRGBA(color, &r, &g, &b, &a);
|
|
if (!active)
|
|
iupGLColorMakeInactive(&r, &g, &b);
|
|
|
|
glColor4ub(r, g, b, a);
|
|
|
|
glLineWidth(linewidth);
|
|
|
|
/* y is oriented top to bottom in IUP */
|
|
ymin = ih->currentheight - 1 - ymin;
|
|
ymax = ih->currentheight - 1 - ymax;
|
|
iupGLDrawCheckSwapCoord(ymin, ymax);
|
|
|
|
glBegin(GL_LINE_LOOP);
|
|
|
|
if (round)
|
|
{
|
|
int rd = 2;
|
|
|
|
glVertex2i(xmin, ymax-rd);
|
|
glVertex2i(xmin+rd, ymax);
|
|
|
|
glVertex2i(xmax-rd, ymax);
|
|
glVertex2i(xmax, ymax-rd);
|
|
|
|
glVertex2i(xmax, ymin+rd);
|
|
glVertex2i(xmax-rd, ymin);
|
|
|
|
glVertex2i(xmin+rd, ymin);
|
|
glVertex2i(xmin, ymin+rd);
|
|
}
|
|
else
|
|
{
|
|
glVertex2i(xmin, ymin);
|
|
glVertex2i(xmax, ymin);
|
|
glVertex2i(xmax, ymax);
|
|
glVertex2i(xmin, ymax);
|
|
}
|
|
|
|
glEnd();
|
|
}
|
|
|
|
static void iGLDrawBuildSmallCircle(int cx, int cy, int rd)
|
|
{
|
|
/* Reference: http://slabode.exofire.net/circle_draw.shtml
|
|
Copyright SiegeLord's Abode */
|
|
int i, num_segments = 16;
|
|
double theta = 2 * 3.1415926 / (double)num_segments;
|
|
double c = cos(theta); /* pre-calculate the sine and cosine */
|
|
double s = sin(theta);
|
|
double t, x, y;
|
|
|
|
x = rd; /* we start at angle = 0 */
|
|
y = 0;
|
|
|
|
for (i = 0; i < num_segments; i++)
|
|
{
|
|
glVertex2d(x + cx, y + cy);
|
|
|
|
/* apply the rotation matrix */
|
|
t = x;
|
|
x = c * x - s * y;
|
|
y = s * t + c * y;
|
|
}
|
|
}
|
|
|
|
void iupGLDrawSmallCircle(Ihandle* ih, int cx, int cy, int rd, float linewidth, const char* color, int active)
|
|
{
|
|
unsigned char r = 0, g = 0, b = 0, a = 255;
|
|
|
|
if (!color || linewidth == 0 || rd == 0)
|
|
return;
|
|
|
|
iupStrToRGBA(color, &r, &g, &b, &a);
|
|
if (!active)
|
|
iupGLColorMakeInactive(&r, &g, &b);
|
|
|
|
glColor4ub(r, g, b, a);
|
|
|
|
glLineWidth(linewidth);
|
|
|
|
/* y is oriented top to bottom in IUP */
|
|
cy = ih->currentheight - 1 - cy;
|
|
|
|
glBegin(GL_LINE_LOOP);
|
|
|
|
iGLDrawBuildSmallCircle(cx, cy, rd);
|
|
|
|
glEnd();
|
|
}
|
|
|
|
void iupGLDrawSmallDisc(Ihandle* ih, int cx, int cy, int rd, const char* color, int active)
|
|
{
|
|
unsigned char r = 0, g = 0, b = 0, a = 255;
|
|
|
|
if (!color || rd == 0)
|
|
return;
|
|
|
|
iupStrToRGBA(color, &r, &g, &b, &a);
|
|
if (!active)
|
|
iupGLColorMakeInactive(&r, &g, &b);
|
|
|
|
glColor4ub(r, g, b, a);
|
|
|
|
/* y is oriented top to bottom in IUP */
|
|
cy = ih->currentheight - 1 - cy;
|
|
|
|
glBegin(GL_POLYGON);
|
|
|
|
iGLDrawBuildSmallCircle(cx, cy, rd);
|
|
|
|
glEnd();
|
|
}
|
|
|
|
void iupGLDrawBox(Ihandle* ih, int xmin, int xmax, int ymin, int ymax, const char* color, int active)
|
|
{
|
|
unsigned char r = 0, g = 0, b = 0, a = 255;
|
|
int smooth;
|
|
|
|
if (!color || xmin == xmax || ymin == ymax)
|
|
return;
|
|
|
|
iupGLDrawCheckSwapCoord(xmin, xmax);
|
|
iupGLDrawCheckSwapCoord(ymin, ymax);
|
|
|
|
iupStrToRGBA(color, &r, &g, &b, &a);
|
|
if (!active)
|
|
iupGLColorMakeInactive(&r, &g, &b);
|
|
|
|
glColor4ub(r, g, b, a);
|
|
|
|
/* y is oriented top to bottom in IUP */
|
|
ymin = ih->currentheight - 1 - ymin;
|
|
ymax = ih->currentheight - 1 - ymax;
|
|
iupGLDrawCheckSwapCoord(ymin, ymax);
|
|
|
|
/* must disable polygon smooth or fill may get diagonal lines */
|
|
smooth = glIsEnabled(GL_POLYGON_SMOOTH);
|
|
if (smooth) glDisable(GL_POLYGON_SMOOTH);
|
|
glBegin(GL_QUADS);
|
|
glVertex2i(xmin, ymin);
|
|
glVertex2i(xmax+1, ymin); /* fill the last pixel */
|
|
glVertex2i(xmax+1, ymax+1);
|
|
glVertex2i(xmin, ymax+1);
|
|
glEnd();
|
|
if (smooth) glEnable(GL_POLYGON_SMOOTH);
|
|
}
|
|
|
|
void iupGLDrawPolygon(Ihandle* ih, const int* points, int count, const char* color, int active)
|
|
{
|
|
unsigned char r = 0, g = 0, b = 0, a = 255;
|
|
int i, x, y;
|
|
|
|
if (!color || count < 3)
|
|
return;
|
|
|
|
iupStrToRGBA(color, &r, &g, &b, &a);
|
|
if (!active)
|
|
iupGLColorMakeInactive(&r, &g, &b);
|
|
|
|
glColor4ub(r, g, b, a);
|
|
|
|
glBegin(GL_POLYGON);
|
|
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
x = points[2 * i + 0];
|
|
y = points[2 * i + 1];
|
|
|
|
/* y is oriented top to bottom in IUP */
|
|
y = ih->currentheight - 1 - y;
|
|
|
|
glVertex2i(x, y);
|
|
}
|
|
|
|
glEnd();
|
|
}
|
|
|
|
void iupGLDrawPolyline(Ihandle* ih, const int* points, int count, float linewidth, const char* color, int active, int loop)
|
|
{
|
|
unsigned char r = 0, g = 0, b = 0, a = 255;
|
|
int i, x, y;
|
|
|
|
if (!color || count < 3)
|
|
return;
|
|
|
|
iupStrToRGBA(color, &r, &g, &b, &a);
|
|
if (!active)
|
|
iupGLColorMakeInactive(&r, &g, &b);
|
|
|
|
glColor4ub(r, g, b, a);
|
|
|
|
glLineWidth(linewidth);
|
|
|
|
if (loop)
|
|
glBegin(GL_LINE_LOOP);
|
|
else
|
|
glBegin(GL_LINE_STRIP);
|
|
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
x = points[2 * i + 0];
|
|
y = points[2 * i + 1];
|
|
|
|
/* y is oriented top to bottom in IUP */
|
|
y = ih->currentheight - 1 - y;
|
|
|
|
glVertex2i(x, y);
|
|
}
|
|
|
|
glEnd();
|
|
}
|
|
|
|
void iupGLDrawArrow(Ihandle *ih, int x, int y, int size, const char* color, int active, int dir)
|
|
{
|
|
int points[6];
|
|
|
|
int off1 = iupRound((double)size * 0.13);
|
|
int off2 = iupRound((double)size * 0.87);
|
|
int half = size / 2;
|
|
|
|
switch (dir)
|
|
{
|
|
case IUPGL_ARROW_LEFT: /* arrow points left */
|
|
points[0] = x + off2;
|
|
points[1] = y;
|
|
points[2] = x + off2;
|
|
points[3] = y + size;
|
|
points[4] = x + off1;
|
|
points[5] = y + half;
|
|
break;
|
|
case IUPGL_ARROW_TOP: /* arrow points top */
|
|
points[0] = x;
|
|
points[1] = y + off2;
|
|
points[2] = x + size;
|
|
points[3] = y + off2;
|
|
points[4] = x + half;
|
|
points[5] = y + off1;
|
|
break;
|
|
case IUPGL_ARROW_RIGHT: /* arrow points right */
|
|
points[0] = x + off1;
|
|
points[1] = y;
|
|
points[2] = x + off1;
|
|
points[3] = y + size;
|
|
points[4] = x + size - off1;
|
|
points[5] = y + half;
|
|
break;
|
|
case IUPGL_ARROW_BOTTOM: /* arrow points bottom */
|
|
points[0] = x;
|
|
points[1] = y + off1;
|
|
points[2] = x + size;
|
|
points[3] = y + off1;
|
|
points[4] = x + half;
|
|
points[5] = y + size - off1;
|
|
break;
|
|
}
|
|
|
|
iupGLDrawPolygon(ih, points, 3, color, active);
|
|
iupGLDrawPolyline(ih, points, 3, 1, color, active, 1);
|
|
}
|
|
|
|
static int iGLIsOpenGL2orMore(void)
|
|
{
|
|
const char* glversion = (const char*)glGetString(GL_VERSION);
|
|
int major = 1, minor = 0;
|
|
iupStrToIntInt(glversion, &major, &minor, '.');
|
|
if (major > 1)
|
|
return 1;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
static int iGLDestroyTexture_CB(Ihandle* image)
|
|
{
|
|
GLuint texture = (GLuint)iupAttribGetInt(image, "GL_TEXTURE");
|
|
if (texture)
|
|
glDeleteTextures(1, &texture);
|
|
|
|
texture = (GLuint)iupAttribGetInt(image, "GL_TEXTURE_INACTIVE");
|
|
if (texture)
|
|
glDeleteTextures(1, &texture);
|
|
|
|
return IUP_DEFAULT;
|
|
}
|
|
|
|
static GLuint iGLDrawGenTexture(Ihandle* ih, Ihandle* image, int active)
|
|
{
|
|
GLuint texture;
|
|
const char *texture_name = "GL_TEXTURE";
|
|
int make_inactive = !active && iupAttribGetInt(ih, "MAKEINACTIVE");
|
|
if (make_inactive)
|
|
texture_name = "GL_TEXTURE_INACTIVE";
|
|
|
|
texture = (GLuint)iupAttribGetInt(image, texture_name);
|
|
if (texture)
|
|
return texture;
|
|
else
|
|
{
|
|
unsigned char* gldata = iupGLImageGetData(image, 1);
|
|
int depth = iupAttribGetInt(image, "GL_DEPTH");
|
|
int format = GL_RGB;
|
|
if (depth == 4)
|
|
format = GL_RGBA;
|
|
|
|
glGenTextures(1, &texture);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, texture);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, format, image->currentwidth, image->currentheight, 0, format, GL_UNSIGNED_BYTE, gldata);
|
|
|
|
iupAttribSetInt(image, texture_name, (int)texture);
|
|
IupSetCallback(image, "DESTROY_CB", iGLDestroyTexture_CB);
|
|
|
|
return texture;
|
|
}
|
|
}
|
|
|
|
static void iGLDrawImage(Ihandle* ih, int xmin, int xmax, int ymin, int ymax, Ihandle* image, int active)
|
|
{
|
|
if (iGLIsOpenGL2orMore())
|
|
{
|
|
GLuint texture = iGLDrawGenTexture(ih, image, active);
|
|
if (texture)
|
|
{
|
|
int smooth = glIsEnabled(GL_POLYGON_SMOOTH);
|
|
if (smooth) glDisable(GL_POLYGON_SMOOTH);
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, texture);
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
|
|
|
/* y is oriented top to bottom in IUP */
|
|
ymin = ih->currentheight - 1 - ymin;
|
|
ymax = ih->currentheight - 1 - ymax;
|
|
iupGLDrawCheckSwapCoord(ymin, ymax);
|
|
|
|
glBegin(GL_QUADS);
|
|
glTexCoord2d(0.0, 0.0); glVertex2d(xmin, ymin);
|
|
glTexCoord2d(1.0, 0.0); glVertex2d(xmax + 0.375, ymin);
|
|
glTexCoord2d(1.0, 1.0); glVertex2d(xmax + 0.375, ymax + 0.375);
|
|
glTexCoord2d(0.0, 1.0); glVertex2d(xmin, ymax + 0.375);
|
|
glEnd();
|
|
|
|
glDisable(GL_TEXTURE_2D);
|
|
if (smooth) glEnable(GL_POLYGON_SMOOTH);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* glDrawPixels is not affected by transformations.
|
|
glRasterPos2i will be clipped if outside the canvas
|
|
and the image will not be drawn.
|
|
So we will avoid these two functions and use textures by default. */
|
|
int rw = xmax - xmin + 1;
|
|
int rh = ymax - ymin + 1;
|
|
unsigned char* gldata = iupGLImageGetData(image, active);
|
|
int depth = iupAttribGetInt(image, "GL_DEPTH");
|
|
int format = GL_RGB;
|
|
if (depth == 4)
|
|
format = GL_RGBA;
|
|
|
|
/* y is at image bottom and oriented bottom to top in OpenGL */
|
|
ymin = ymax;
|
|
|
|
/* y is oriented top to bottom in IUP */
|
|
ymin = ih->currentheight - 1 - ymin;
|
|
|
|
if (image->currentwidth != rw || image->currentheight != rh)
|
|
glPixelZoom((GLfloat)rw / (GLfloat)image->currentwidth, (GLfloat)rh / (GLfloat)image->currentheight);
|
|
|
|
glRasterPos2i(xmin, ymin);
|
|
glDrawPixels(image->currentwidth, image->currentheight, format, GL_UNSIGNED_BYTE, gldata);
|
|
|
|
if (image->currentwidth != rw || image->currentheight != rh)
|
|
glPixelZoom(1.0f, 1.0f);
|
|
}
|
|
}
|
|
|
|
void iupGLDrawIconImageZoom(Ihandle *ih, int xmin, int xmax, int ymin, int ymax, const char* baseattrib, const char* imagename, int active)
|
|
{
|
|
Ihandle* image;
|
|
|
|
if (xmin == xmax || ymin == ymax)
|
|
return;
|
|
|
|
image = iupGLIconGetImageHandle(ih, baseattrib, imagename, active);
|
|
if (image)
|
|
iGLDrawImage(ih, xmin, xmax, ymin, ymax, image, active);
|
|
}
|
|
|
|
void iupGLDrawIconImage(Ihandle* ih, int x, int y, const char* baseattrib, const char* imagename, int active)
|
|
{
|
|
Ihandle* image = iupGLIconGetImageHandle(ih, baseattrib, imagename, active);
|
|
if (image)
|
|
iGLDrawImage(ih, x, x + image->currentwidth - 1, y, y + image->currentheight - 1, image, active);
|
|
}
|
|
|
|
static void iGLDrawText(Ihandle* ih, const char* str, int max_len, int x, int y)
|
|
{
|
|
int len, cur_len, lineheight, ascent, baseline;
|
|
const char *nextstr;
|
|
const char *curstr = str;
|
|
int underline = iupAttribGetInt(ih, "UNDERLINE");
|
|
|
|
iupGLFontGetDim(ih, NULL, &lineheight, &ascent, NULL);
|
|
baseline = lineheight - ascent;
|
|
|
|
/* y is at text baseline and oriented bottom to top in OpenGL */
|
|
y = y + lineheight - baseline; /* move to baseline */
|
|
|
|
/* y is oriented top to bottom in IUP */
|
|
y = ih->currentheight - 1 - y;
|
|
|
|
if (underline)
|
|
glLineWidth(1.0f);
|
|
|
|
glPushMatrix();
|
|
glTranslated((double)x, (double)y, 0.0);
|
|
|
|
do
|
|
{
|
|
nextstr = iupStrNextLine(curstr, &len);
|
|
if (len)
|
|
{
|
|
if (max_len > 0)
|
|
{
|
|
if (nextstr)
|
|
cur_len = (int)(nextstr - str);
|
|
else
|
|
cur_len = (int)(curstr - str) + len;
|
|
if (cur_len > max_len)
|
|
{
|
|
len -= cur_len - max_len;
|
|
if (len < 0)
|
|
break;
|
|
nextstr = NULL;
|
|
}
|
|
}
|
|
|
|
iupGLFontRenderString(ih, curstr, len);
|
|
|
|
if (underline)
|
|
{
|
|
int width = iupGLFontGetStringWidth(ih, curstr, len);
|
|
glBegin(GL_LINES);
|
|
glVertex2i(0, -2);
|
|
glVertex2i(width - 1, -2);
|
|
glEnd();
|
|
}
|
|
}
|
|
|
|
glTranslated(0.0, (double)-lineheight, 0.0);
|
|
|
|
curstr = nextstr;
|
|
} while (nextstr && *nextstr);
|
|
|
|
glPopMatrix();
|
|
}
|
|
|
|
void iupGLDrawMultilineText(Ihandle* ih, int x, int y, const char* str, const char* color, int active)
|
|
{
|
|
unsigned char r = 0, g = 0, b = 0, a = 255;
|
|
|
|
if (!color || !str)
|
|
return;
|
|
|
|
iupStrToRGBA(color, &r, &g, &b, &a);
|
|
if (!active)
|
|
iupGLColorMakeInactive(&r, &g, &b);
|
|
|
|
glColor4ub(r, g, b, a);
|
|
|
|
if (str[0])
|
|
iGLDrawText(ih, str, -1, x, y);
|
|
}
|
|
|
|
|
|
/***************************************************************/
|
|
/* Utilities */
|
|
|
|
void IupGLDrawImage(Ihandle* ih, const char* name, int x, int y, int active)
|
|
{
|
|
iupASSERT(iupObjectCheck(ih));
|
|
if (!iupObjectCheck(ih))
|
|
return;
|
|
|
|
iupGLDrawIconImage(ih, x, y, NULL, name, active);
|
|
}
|
|
|
|
void IupGLDrawText(Ihandle* ih, const char* str, int len, int x, int y)
|
|
{
|
|
iupASSERT(iupObjectCheck(ih));
|
|
if (!iupObjectCheck(ih))
|
|
return;
|
|
|
|
if (!str || str[0] == 0)
|
|
return;
|
|
|
|
iGLDrawText(ih, str, len, x, y);
|
|
}
|
|
|
|
void IupGLDrawGetTextSize(Ihandle* ih, const char* str, int *w, int *h)
|
|
{
|
|
iupASSERT(iupObjectCheck(ih));
|
|
if (!iupObjectCheck(ih))
|
|
return;
|
|
|
|
iupGLFontGetMultiLineStringSize(ih, str, w, h);
|
|
}
|
|
|
|
void IupGLDrawGetImageInfo(const char* name, int *w, int *h, int *bpp)
|
|
{
|
|
iupASSERT(name);
|
|
if (!name)
|
|
return;
|
|
|
|
iupGLImageGetInfo(name, w, h, bpp);
|
|
}
|