////////////////////////////////////////////////////////
//
// GEM - Graphics Environment for Multimedia
//
// mark@danks.org
//
// Implementation file
//
//    Copyright (c) 1997-1999 Mark Danks.
//    For information on usage and redistribution, and for a DISCLAIMER OF ALL
//    WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
//
/////////////////////////////////////////////////////////

#include "pix_renderaa.h"
#include "Base/GemPixUtil.h"

CPPEXTERN_NEW_WITH_GIMME(pix_renderaa)

/////////////////////////////////////////////////////////
//
// pix_renderaa
//
/////////////////////////////////////////////////////////
// Constructor
//
/////////////////////////////////////////////////////////
pix_renderaa :: pix_renderaa(int argc, t_atom *argv) :
  m_textureQuality(GL_LINEAR),
  m_textureObj(NULL),
  m_fontname(NULL)
{
  int width, height;
  width = (int)  atom_getfloatarg(0,argc,argv);
  height = (int) atom_getfloatarg(1,argc,argv);
  m_fontname = atom_getsymbolarg(2,argc,argv);

  if (m_fontname == &s_)
    m_fontname = gensym("default.txf");
  if (width == 0)
    width = 80;
  
  if (height == 0)
   height = 25;
}

/////////////////////////////////////////////////////////
// Destructor
//
/////////////////////////////////////////////////////////
pix_renderaa :: ~pix_renderaa()
{ }

/////////////////////////////////////////////////////////
// setUpTextureState
//
/////////////////////////////////////////////////////////
void pix_renderaa :: setUpTextureState()
{
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, m_textureQuality);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_textureQuality);
    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}

/////////////////////////////////////////////////////////
// render
//
/////////////////////////////////////////////////////////
void pix_renderaa :: render(GemState *state)
{
  int width, ascent, descent;
  int i;

  if (!state->image) return;

  unsigned char* data = state->image->image.data;
  int charwidth = state->image->image.xsize;
  int charheight = state->image->image.ysize;

  if ( !state->image || (!m_textureObj)) return;
  
  state->texture = 1;

  glPushMatrix();
  glEnable(GL_TEXTURE_2D);

#if 0
  glAlphaFunc(GL_GEQUAL, 0.0625);
  glEnable(GL_ALPHA_TEST);
  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
#endif

#if 0
  glEnable(GL_POLYGON_OFFSET_EXT);
  glPolygonOffset(0.0, -3);
#endif

  txfEstablishTexture(m_textureObj, 0, GL_TRUE);
  
  txfGetStringMetrics(m_textureObj, (char*) data, charwidth-1,
		      &width, &ascent, &descent);

  glTranslatef(-1.0, 0.0, 0.1);
  glScalef(0.01, 0.01, 0.01);


  for (i = 0; i < charwidth*charheight; i++) {
    if ((i%charwidth == 0)) {
      glTranslatef(-1*width,(ascent+descent),0.0);
    }
    else
      txfRenderGlyph(m_textureObj, data[i]);
  }

  glDisable(GL_TEXTURE_2D);

#if 0
  glDisable(GL_BLEND);
  glDisable(GL_ALPHA_TEST);
  glDisable(GL_POLYGON_OFFSET_EXT);
#endif

  glPopMatrix();
}

/////////////////////////////////////////////////////////
// postrender
//
/////////////////////////////////////////////////////////
void pix_renderaa :: postrender(GemState *state)
{
  glDisable(GL_TEXTURE_2D);
}

/////////////////////////////////////////////////////////
// startRendering
//
/////////////////////////////////////////////////////////
void pix_renderaa :: startRendering()
{
  
  m_textureObj = txfLoadFont(m_fontname->s_name);

  if (!m_textureObj)
    {
      error("GEM: pix_renderaa: Unable to allocate texture object");
      return;
    }
}

/////////////////////////////////////////////////////////
// stopRendering
//
/////////////////////////////////////////////////////////
void pix_renderaa :: stopRendering()
{

}

/////////////////////////////////////////////////////////
// textureQuality
//
/////////////////////////////////////////////////////////
void pix_renderaa :: textureQuality(int type)
{
    if (type)
        m_textureQuality = GL_LINEAR;
    else
        m_textureQuality = GL_NEAREST;
    if (m_textureObj)
    {
#ifdef GL_VERSION_1_1
      //        glBindTexture(GL_TEXTURE_2D, m_textureObj);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, m_textureQuality);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_textureQuality);
#elif GL_EXT_texture_object
	//        glBindTextureEXT(GL_TEXTURE_2D, m_textureObj);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, m_textureQuality);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_textureQuality);
#else
#endif
    }
	setModified();
}

/////////////////////////////////////////////////////////
// static member functions
//
/////////////////////////////////////////////////////////
void pix_renderaa :: obj_setupCallback(t_class *classPtr)
{
    class_addmethod(classPtr, (t_method)&pix_renderaa::textureMessCallback,
    	    gensym("quality"), A_FLOAT, A_NULL);
    class_addmethod(classPtr, (t_method)&pix_renderaa::fontMessCallback,
    	    gensym("font"), A_SYMBOL, A_NULL);
}

void pix_renderaa :: textureMessCallback(void *data, t_floatarg quality)
{
    GetMyClass(data)->textureQuality((int)quality);
}
