#include "evas_gl_private.h"

void *
evas_gl_font_texture_new(void *context, RGBA_Font_Glyph *fg)
{
   Evas_Engine_GL_Context *gc = context;
   Evas_GL_Texture *tex;
   DATA8 *data;
   int w, h, j, nw;
   DATA8 *ndata;
   int fh;

   if (fg->ext_dat) return fg->ext_dat; // FIXME: one engine at a time can do this :(
   
   w = fg->glyph_out->bitmap.width;
   h = fg->glyph_out->bitmap.rows;
   if ((w == 0) || (h == 0)) return NULL;

   data = fg->glyph_out->bitmap.buffer;
   j = fg->glyph_out->bitmap.pitch;
   if (j < w) j = w;

   nw = ((w + 3) / 4) * 4;
   ndata = alloca(nw *h);
   if (!ndata) return NULL;
   if (fg->glyph_out->bitmap.num_grays == 256)
     {
	int x, y;
	DATA8 *p1, *p2;

	for (y = 0; y < h; y++)
	  {
	     p1 = data + (j * y);
	     p2 = ndata + (nw * y);
	     for (x = 0; x < w; x++)
	       {
		  *p2 = *p1;
		  p1++;
		  p2++;
	       }
	  }
     }
   else if (fg->glyph_out->bitmap.num_grays == 0)
     {
	DATA8 *tmpbuf = NULL, *dp, *tp, bits;
	int bi, bj, end;
	const DATA8 bitrepl[2] = {0x0, 0xff};
	
	tmpbuf = alloca(w);
	if (tmpbuf)
	  {
	     int x, y;
	     DATA8 *p1, *p2;
	     
	     for (y = 0; y < h; y++)
	       {
		  p1 = tmpbuf;
		  p2 = ndata + (nw * y);
		  tp = tmpbuf;
		  dp = data + (y * fg->glyph_out->bitmap.pitch);
		  for (bi = 0; bi < w; bi += 8)
		    {
		       bits = *dp;
		       if ((w - bi) < 8) end = w - bi;
		       else end = 8;
		       for (bj = 0; bj < end; bj++)
			 {
			    *tp = bitrepl[(bits >> (7 - bj)) & 0x1];
			    tp++;
			 }
		       dp++;
		    }
		  for (x = 0; x < w; x++)
		    {
		       *p2 = *p1;
		       p1++;
		       p2++;
		    }
	       }
	  }
     }
//   fh = h;
   fh = fg->fi->max_h;
   tex = evas_gl_common_texture_alpha_new(gc, ndata, w, h, fh);
   tex->sx1 = ((double)(tex->x)) / (double)tex->pt->w;
   tex->sy1 = ((double)(tex->y)) / (double)tex->pt->h;
   tex->sx2 = ((double)(tex->x + tex->w)) / (double)tex->pt->w;
   tex->sy2 = ((double)(tex->y + tex->h)) / (double)tex->pt->h;
   return tex;
}

void
evas_gl_font_texture_free(void *tex)
{
   if (!tex) return;
   evas_gl_common_texture_free(tex);
}

void
evas_gl_font_texture_draw(void *context, void *surface __UNUSED__, void *draw_context, RGBA_Font_Glyph *fg, int x, int y)
{
   Evas_Engine_GL_Context *gc = context;
   RGBA_Draw_Context *dc = draw_context;
   Evas_GL_Texture *tex;
   Cutout_Rects *rects;
   Cutout_Rect  *rct;
   int r, g, b, a;
   double ssx, ssy, ssw, ssh;
   int c, cx, cy, cw, ch;
   int i;
   int sx, sy, sw, sh;
   
   if (dc != gc->dc) return;
   tex = fg->ext_dat;
   if (!tex) return;
   a = (dc->col.col >> 24) & 0xff;
   if (a == 0) return;
   r = (dc->col.col >> 16) & 0xff;
   g = (dc->col.col >> 8 ) & 0xff;
   b = (dc->col.col      ) & 0xff;
   sx = 0; sy = 0; sw = tex->w, sh = tex->h;
   if ((!gc->dc->cutout.rects) 
//       || (gc->dc->cutout.active > 32)
       )
     {
        if (gc->dc->clip.use)
          {
             int nx, ny, nw, nh;
             
             nx = x; ny = y; nw = tex->w; nh = tex->h;
             RECTS_CLIP_TO_RECT(nx, ny, nw, nh,
                                gc->dc->clip.x, gc->dc->clip.y,
                                gc->dc->clip.w, gc->dc->clip.h);
             if ((nw < 1) || (nh < 1)) return;
             if ((nx == x) && (ny == y) && (nw == tex->w) && (nh == tex->h))
               {
                  evas_gl_common_context_font_push(gc, tex,
                                                   0.0, 0.0, 0.0, 0.0,
//                                                   sx, sy, sw, sh,
                                                   x, y, tex->w, tex->h,
                                                   r, g, b, a);
                  return;
               }
             ssx = (double)sx + ((double)(sw * (nx - x)) / (double)(tex->w));
             ssy = (double)sy + ((double)(sh * (ny - y)) / (double)(tex->h));
             ssw = ((double)sw * (double)(nw)) / (double)(tex->w);
             ssh = ((double)sh * (double)(nh)) / (double)(tex->h);
             evas_gl_common_context_font_push(gc, tex, 
                                              ssx, ssy, ssw, ssh,
                                              nx, ny, nw, nh,
                                              r, g, b, a);
          }
        else
          {
             evas_gl_common_context_font_push(gc, tex, 
                                              0.0, 0.0, 0.0, 0.0,
//                                              sx, sy, sw, sh,
                                              x, y, tex->w, tex->h,
                                              r, g, b, a);
          }
        return;
     }
   /* save out clip info */
   c = gc->dc->clip.use; cx = gc->dc->clip.x; cy = gc->dc->clip.y; cw = gc->dc->clip.w; ch = gc->dc->clip.h;
   evas_common_draw_context_clip_clip(gc->dc, 0, 0, gc->w, gc->h);
   evas_common_draw_context_clip_clip(gc->dc, x, y, tex->w, tex->h);
   /* our clip is 0 size.. abort */
   if ((gc->dc->clip.w <= 0) || (gc->dc->clip.h <= 0))
     {
        gc->dc->clip.use = c; gc->dc->clip.x = cx; gc->dc->clip.y = cy; gc->dc->clip.w = cw; gc->dc->clip.h = ch;
        return;
     }
   rects = evas_common_draw_context_apply_cutouts(dc);
   for (i = 0; i < rects->active; ++i)
     {
        int nx, ny, nw, nh;
        
        rct = rects->rects + i;
        nx = x; ny = y; nw = tex->w; nh = tex->h;
        RECTS_CLIP_TO_RECT(nx, ny, nw, nh, rct->x, rct->y, rct->w, rct->h);
        if ((nw < 1) || (nh < 1)) continue;
        if ((nx == x) && (ny == y) && (nw == tex->w) && (nh == tex->h))
          {
             evas_gl_common_context_font_push(gc, tex,
                                              0.0, 0.0, 0.0, 0.0,
//                                              sx, sy, sw, sh,
                                              x, y, tex->w, tex->h,
                                              r, g, b, a);
             continue;
          }
        ssx = (double)sx + ((double)(sw * (nx - x)) / (double)(tex->w));
        ssy = (double)sy + ((double)(sh * (ny - y)) / (double)(tex->h));
        ssw = ((double)sw * (double)(nw)) / (double)(tex->w);
        ssh = ((double)sh * (double)(nh)) / (double)(tex->h);
        evas_gl_common_context_font_push(gc, tex, 
                                         ssx, ssy, ssw, ssh,
                                         nx, ny, nw, nh,
                                         r, g, b, a);
     }
   evas_common_draw_context_apply_clear_cutouts(rects);
   /* restore clip info */
   gc->dc->clip.use = c; gc->dc->clip.x = cx; gc->dc->clip.y = cy; gc->dc->clip.w = cw; gc->dc->clip.h = ch;
}
