ecere/gfx/newFonts: Initial eC port of font engine by Alexis Naveros
[sdk] / ecere / src / gfx / newFonts / fontRenderer.ec
1 /* *****************************************************************************
2  * Original Version Copyright (c) 2007-2014 Alexis Naveros.
3  *
4  * Ecere Corporation has unlimited/unrestricted rights.
5  * *****************************************************************************/
6 import "Color"
7
8 #include <math.h>
9
10 #if defined(_GLES)
11    #define ES1_1
12 #else
13    //#define SHADERS
14 #endif
15
16 #if !defined(__ANDROID__) && !defined(__EMSCRIPTEN__) && !defined(__ODROID__)
17 #  if defined(SHADERS)
18 #     include "gl_core_3_3.h"
19 #  else
20 #     include "gl_compat_4_4.h"
21 #  endif
22 #endif
23
24 #include "cc.h"
25 #include "mm.h"
26
27 import "fontManager"
28 import "textureManager"
29 import "drawManager"
30
31 public class FontRenderer : FontManagerRenderer
32 {
33    DrawManager dm;
34    Texture texture;
35    int textureWidth, textureHeight;
36
37    int imagecount;
38    int imageAlloc;
39    DMImage *imageList;
40
41    ColorAlpha stateColor;
42    ColorAlpha stateCursorColor;
43    uint32 stateLayer;
44
45    imageAlloc = 512;
46    imageList = new DMImage[imageAlloc];
47
48    stateColor = white;
49    stateCursorColor = white;
50    stateLayer = DM_LAYER_ABOVE;
51
52 public:
53
54    property DrawManager drawManager { set { dm = value; } }
55
56    ~FontRenderer()
57    {
58       delete texture;
59       delete imageList;
60    }
61
62    bool createTexture( int width, int height )
63    {
64       IMGImage image
65       {
66          format = { width = width, height = height, type = grayScale, bytesPerPixel = 1, bytesPerLine = width };
67       };
68
69       delete texture;
70
71       texture = { 0 << DM_TEXTURE_ORDER_SHIFT };
72       texture.build(image, 0, 0.0, 0 );
73
74       textureWidth = width;
75       textureHeight = height;
76       return true;
77    }
78
79    int resizeTexture( int width, int height )
80    {
81      int retval;
82
83      // Reuse create to resize too.
84      delete imageList;
85      imagecount = 0;
86      imageAlloc = 512;
87      imageList = new DMImage[imageAlloc];
88
89      retval = createTexture( width, height );
90      return retval;
91    }
92
93    void updateTexture( int *rect, const byte* data )
94    {
95      if(texture)
96      {
97         int w = rect[2] - rect[0];
98         int h = rect[3] - rect[1];
99
100         glPushClientAttrib( GL_CLIENT_PIXEL_STORE_BIT );
101         glPushAttrib( GL_TEXTURE_BIT );
102         glBindTexture( GL_TEXTURE_2D, texture.glTex );
103         glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
104         glPixelStorei( GL_UNPACK_ROW_LENGTH, textureWidth );
105         glPixelStorei( GL_UNPACK_SKIP_PIXELS, rect[0] );
106         glPixelStorei( GL_UNPACK_SKIP_ROWS, rect[1] );
107         glTexSubImage2D( GL_TEXTURE_2D, 0, rect[0], rect[1], w, h, GL_RED, GL_UNSIGNED_BYTE, data );
108         glPopAttrib();
109         glPopClientAttrib();
110
111       #if 0
112         IMGImage image;
113         image.format.width = textureWidth;
114         image.format.height = textureHeight;
115         image.format.type = IMG_FORMAT_TYPE_GRAYSCALE;
116         image.format.bytesPerPixel = 1;
117         image.format.bytesPerLine = image.format.width * image.format.bytesPerPixel;
118         image.data = data;
119         imgWritePngFile( "zzz2.png", &image, 1.0 );
120       #endif
121      }
122    }
123
124    void flush( )
125    {
126       dm.flushImages( );
127    }
128
129    int registerImage( int offsetx, int offsety, int width, int height )
130    {
131       int imageindex = imagecount;
132       DMImage *image;
133
134       if( imagecount >= imageAlloc )
135       {
136          imageAlloc <<= 1;
137          imageList = renew imageList DMImage[imageAlloc];
138       }
139       imagecount++;
140
141       image = &imageList[ imageindex ];
142    #if 1
143       image->defineImage( texture, offsetx, offsety, width, height, 1, DM_PROGRAM_ALPHABLEND, stateLayer );
144    #else
145       image->defineImage( texture, offsetx, offsety, width, height, 1, DM_PROGRAM_NORMAL, stateLayer );
146    #endif
147
148       return imageindex;
149    }
150
151    void drawImage( int targetx, int targety, int imageindex )
152    {
153       DMImage *image = &imageList[ imageindex ];
154       dm.drawImage( image, targetx, targety, image->sizex, image->sizey, stateColor );
155    }
156
157    void drawImageCursor( int targetx, int targety, int imageindex )
158    {
159       DMImage *image = &imageList[ imageindex ];
160       dm.drawImage( image, targetx, targety, image->sizex, image->sizey, stateCursorColor );
161    }
162
163    void drawImageAlt( byte *texdata, int targetx, int targety, int offsetx, int offsety, int width, int height )
164    {
165
166    }
167
168    void drawImageFloat( float targetx, float targety, float angsin, float angcos, int imageindex )
169    {
170       DMImage *image = &imageList[ imageindex ];
171
172       /* 0.2588190451, 0.965925826289 */
173
174       dm.drawImageFloat( image, targetx, targety, (float)image->sizex, (float)image->sizey, angsin, angcos, stateColor );
175    }
176
177    void resetImages( )
178    {
179       imagecount = 0;
180    }
181
182    void setColor( ColorAlpha color )
183    {
184       stateColor = { color.a, { color.color.b, color.color.g, color.color.r } };
185    }
186
187    void setCursorColor( ColorAlpha color )
188    {
189       stateCursorColor = { color.a, { color.color.b, color.color.g, color.color.r } };
190    }
191
192    void setLayer( uint32 layerIndex )
193    {
194       stateLayer = layerIndex;
195    }
196 }