source: golgotha/src/render/r1_font.cc @ 80

Last change on this file since 80 was 80, checked in by Sam Hocevar, 11 years ago
  • Adding the Golgotha source code. Not sure what's going to be interesting in there, but since it's all public domain, there's certainly stuff to pick up.
File size: 6.5 KB
Line 
1/********************************************************************** <BR>
2  This file is part of Crack dot Com's free source code release of
3  Golgotha. <a href="http://www.crack.com/golgotha_release"> <BR> for
4  information about compiling & licensing issues visit this URL</a>
5  <PRE> If that doesn't help, contact Jonathan Clark at
6  golgotha_source@usa.net (Subject should have "GOLG" in it)
7***********************************************************************/
8
9#include "r1_font.hh"
10#include "image/context.hh"
11#include "r1_api.hh"
12#include "tmanage.hh"
13#include "r1_clip.hh"
14
15static inline int i4_is_black(w32 c)
16{
17  if ((c&0xff000000)==0)
18    return 1;
19  else return 0;
20}
21
22static inline int i4_scanline_empty(i4_image_class *im, int y)
23{
24  for (int x=0; x<im->width(); x++) 
25    if (!i4_is_black(im->get_pixel(x,y)))
26      return 0;
27
28  return 1;
29}
30
31
32static inline int i4_colum_empty(i4_image_class *im, int x)
33{
34  for (int y=0; y<im->height(); y++)
35    if (!i4_is_black(im->get_pixel(x,y)))
36      return 0;
37
38  return 1;
39}
40
41
42static inline int i4_image_has_alpha(i4_image_class *im)
43{
44  for (int y=0; y<im->height(); y++)
45    for (int x=0; x<im->width(); x++)   
46    {
47      w32 cl=im->get_pixel(x,y);
48      if (cl>>24)
49        i4_warning("alpha %d", cl>>24);
50    }
51
52  return 1;
53}
54
55void r1_font_class::set_color(i4_color color)
56{
57  r=((color>>16)&0xff) * (1.0/255.0);
58  g=((color>>8)&0xff) * (1.0/255.0);
59  b=((color>>0)&0xff) * (1.0/255.0);
60}
61
62i4_bool r1_font_class::expand(i4_image_class *from,
63                           i4_image_class *to,
64                           int start_ch)
65{
66  int x=0, y=0;
67
68  int y_top=0, y_bottom=from->height()-1, x1=0,x2,i;
69
70  while (y_top<=y_bottom && i4_scanline_empty(from, y_top))
71    y_top++;
72
73  if (y_top==y_bottom-1)
74    i4_error("image is empty");
75
76  while (i4_scanline_empty(from, y_bottom))
77    y_bottom--;
78
79
80  for (i=0; i<256; i++)
81  {
82    pos[i].w=4;
83    pos[i].x=255;
84  }
85
86
87  int char_on=start_ch;
88
89  largest_h=y_bottom-y_top;
90
91  i4_draw_context_class context(0,0, to->width()-1, to->height()-1);
92  do
93  {
94    while (x1!=from->width() && i4_colum_empty(from, x1)) x1++;
95    if (x1<from->width())
96    {
97      x2=x1+1;
98      while (x2!=from->width() && !(i4_colum_empty(from, x2))) x2++;
99      int w=x2-x1+1;
100      if (w>longest_w)
101        longest_w=w;
102
103     
104      if (w+x>to->width())
105      {
106        y+=largest_h;
107        if (y>to->height())
108          return i4_F;
109        x=0;
110      }
111           
112      pos[char_on].x=x;
113      pos[char_on].y=y;
114      pos[char_on].w=w;
115      from->i4_image_class::put_part(to, x,y, x1,y_top, x2,y_bottom, context);
116
117      x+=w+1;
118
119      x1=x2+1;
120    }     
121    char_on++;
122  } while (x1<from->width() && char_on<255);
123
124 
125
126  texture=api->get_tmanager()->register_image(to);
127  xs=1.0/to->width();
128  ys=1.0/to->height();
129
130  return i4_T; 
131}
132
133
134
135r1_font_class::r1_font_class(r1_render_api_class *api, i4_image_class *im, int start_ch)
136  : api(api)
137{
138  memset(pos,0, sizeof(pos));
139
140  i4_image_class *to=i4_create_image(64, 64, i4_pal_man.default_32());
141
142  if (!expand(im, to, start_ch))
143  {
144    delete to;
145    to=i4_create_image(128, 128, i4_pal_man.default_32());
146    if (!expand(im, to, start_ch))
147    {
148      delete to;
149      to=i4_create_image(256, 256, i4_pal_man.default_32());
150      if (!expand(im, to, start_ch))
151        i4_error("r1_font does not fit on a 256x256 texture");
152    }   
153  }
154}
155
156
157void r1_font_class::put_character(i4_image_class *screen,
158                                  sw16 x, sw16 y,
159                                  const i4_char &c,
160                                  i4_draw_context_class &context)
161{
162  int ch=c.value();
163  if (pos[ch].x!=255)
164  {
165    r1_vert v[4];
166 
167    v[0].px=x;              v[0].py=y;
168    v[1].px=x+pos[ch].w;    v[1].py=y;
169    v[2].px=x+pos[ch].w;    v[2].py=y+largest_h;
170    v[3].px=x;              v[3].py=y+largest_h;
171 
172
173    float xp=pos[ch].x * xs;
174    float yp=pos[ch].y * ys;
175    float wp=pos[ch].w * xs;
176    float hp=largest_h * ys;
177
178    v[0].s=xp; v[0].t=yp;
179    v[1].s=xp+wp; v[1].t=yp;
180    v[2].s=xp+wp; v[2].t=yp+hp;
181    v[3].s=xp; v[3].t=yp+hp;
182
183
184    float w=1.0/r1_near_clip_z;
185    v[0].w=w; v[0].v.z=r1_near_clip_z;
186    v[1].w=w; v[1].v.z=r1_near_clip_z;
187    v[2].w=w; v[2].v.z=r1_near_clip_z;
188    v[3].w=w; v[3].v.z=r1_near_clip_z;
189
190    v[0].r=r; v[0].g=g; v[0].b=b;  v[0].a=1;
191    v[1].r=r; v[1].g=g; v[1].b=b;  v[1].a=1;
192    v[2].r=r; v[2].g=g; v[2].b=b;  v[2].a=1;
193    v[3].r=r; v[3].g=g; v[3].b=b;  v[3].a=1;
194
195    api->use_texture(texture, 256, 0);
196
197    i4_rect_list_class::area_iter cl=context.clip.list.begin();
198    for (; cl != context.clip.list.end(); ++cl)
199      if (x>=cl->x1 && y>=cl->y1 && v[1].px<=cl->x2 && v[2].py<=cl->y2)     
200        api->render_poly(4, v);
201  }
202}
203
204
205
206
207void r1_font_class::put_string(i4_image_class *screen,
208                               sw16 x, sw16 y,
209                               const i4_const_str &string,
210                               i4_draw_context_class &context)
211{
212  r1_vert v[4];
213  float w=1.0/r1_near_clip_z;
214  v[0].w=w; v[0].v.z=r1_near_clip_z;
215  v[1].w=w; v[1].v.z=r1_near_clip_z;
216  v[2].w=w; v[2].v.z=r1_near_clip_z;
217  v[3].w=w; v[3].v.z=r1_near_clip_z;
218
219  v[0].r=r; v[0].g=g; v[0].b=b;  v[0].a=1;
220  v[1].r=r; v[1].g=g; v[1].b=b;  v[1].a=1;
221  v[2].r=r; v[2].g=g; v[2].b=b;  v[2].a=1;
222  v[3].r=r; v[3].g=g; v[3].b=b;  v[3].a=1;
223
224  if (!string.null())
225  {
226    api->use_texture(texture, 256, 0);
227
228    for (i4_const_str::iterator p=string.begin(); p!=string.end(); ++p)
229    {     
230      int ch=p.get().value();
231      if (pos[ch].x!=255)
232      {   
233        i4_rect_list_class::area_iter cl=context.clip.list.begin();
234        for (; cl != context.clip.list.end(); ++cl)
235        { 
236          v[0].px=x;                  v[0].py=y;
237          v[1].px=x+pos[ch].w;        v[1].py=y;
238          v[2].px=x+pos[ch].w;        v[2].py=y+largest_h;
239          v[3].px=x;                  v[3].py=y+largest_h;   
240
241          float xp=pos[ch].x * xs;
242          float yp=pos[ch].y * ys;
243          float wp=pos[ch].w * xs;
244          float hp=largest_h * ys;
245
246
247          v[0].s=xp; v[0].t=yp;
248          v[1].s=xp+wp; v[1].t=yp;
249          v[2].s=xp+wp; v[2].t=yp+hp;
250          v[3].s=xp; v[3].t=yp+hp;
251
252          if (x>=cl->x1 && y>=cl->y1 && v[1].px<=cl->x2 && v[2].py<=cl->y2)
253            api->render_poly(4, v);
254        }
255      }
256
257
258      x+=pos[ch].w;
259    }
260  }
261}
262
Note: See TracBrowser for help on using the repository browser.