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 |
|
---|
15 | static inline int i4_is_black(w32 c)
|
---|
16 | {
|
---|
17 | if ((c&0xff000000)==0)
|
---|
18 | return 1;
|
---|
19 | else return 0;
|
---|
20 | }
|
---|
21 |
|
---|
22 | static 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 |
|
---|
32 | static 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 |
|
---|
42 | static 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 |
|
---|
55 | void 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 |
|
---|
62 | i4_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 |
|
---|
135 | r1_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 |
|
---|
157 | void 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 |
|
---|
207 | void 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 |
|
---|