1 /*
2 * sactcg.c: CG����
3 *
4 * Copyright (C) 1997-1998 Masaki Chikama (Wren) <chikama@kasumi.ipl.mech.nagoya-u.ac.jp>
5 * 1998- <masaki-c@is.aist-nara.ac.jp>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 */
22 /* $Id: sactcg.c,v 1.2 2003/11/16 15:29:52 chikama Exp $ */
23
24 #include "config.h"
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <glib.h>
30
31 #include "portab.h"
32 #include "nact.h"
33 #include "system.h"
34 #include "ags.h"
35 #include "surface.h"
36 #include "ngraph.h"
37 #include "sactcg.h"
38
39 #define CGMAX 65536
40 static cginfo_t *cgs[CGMAX];
41
42 #include "sactcg_stretch.c"
43 #include "sactcg_blend.c"
44
45
46 #define spcg_assert_no(no) \
47 if ((no) > (CGMAX -1)) { \
48 WARNING("no is too large (should be %d < %d)\n", (no), CGMAX); \
49 return NG; \
50 } \
51
52
53 /*
54 cg���ɤ߹���
55
56 ������ֹ��CG���ե����뤫���ɤ߹�����ꡢ
57 CG_xxx�Ǻ�������CG�Ȥ���
58
59 @param no: �ɤ߹���CG�ֹ�
60 @param refinc: ���ȥ��������䤹���ɤ�����
61 sprite���黲�Ȥ����Ȥ������䤷��CG_xxx�������
62 ���Ȥ����Ȥ������䤵�ʤ���
63 */
scg_loadcg_no(int no,boolean refinc)64 cginfo_t *scg_loadcg_no(int no, boolean refinc) {
65 cginfo_t *i;
66
67 if (no >= (CGMAX -1)) {
68 WARNING("no is too large (should be %d < %d)\n", (no), CGMAX);
69 return NULL;
70 }
71
72 // ���Ǥ� ���ɤ���Ƥ��뤫��CG_xxx �Ǻ������ߤξ���
73 // ���ȥ��������䤹
74 if (cgs[no] != NULL) {
75 if (refinc) {
76 cgs[no]->refcnt++;
77 }
78 return cgs[no];
79 }
80
81 i = g_new(cginfo_t, 1);
82 i->type = CG_LINKED;
83 i->no = no;
84 i->refcnt = (refinc ? 1 : 0);
85 i->sf = sf_loadcg_no(no -1);
86 if (i->sf == NULL) {
87 WARNING("load fail (%d)\n", no -1);
88 g_free(i);
89 return NULL;
90 }
91
92 cgs[no] = i;
93
94 return i;
95 }
96
97 // ������礭�������ζ���� CG �����
scg_create(int wNumCG,int wWidth,int wHeight,int wR,int wG,int wB,int wBlendRate)98 int scg_create(int wNumCG, int wWidth, int wHeight, int wR, int wG, int wB, int wBlendRate) {
99 cginfo_t *i;
100
101 spcg_assert_no(wNumCG);
102
103 i = g_new(cginfo_t, 1);
104 i->type = CG_SET;
105 i->no = wNumCG;
106 i->refcnt = 1;
107 i->sf = sf_create_surface(wWidth, wHeight, sf0->depth);
108 gr_fill(i->sf, 0, 0, wWidth, wHeight, wR, wG, wB);
109 gr_fill_alpha_map(i->sf, 0, 0, wWidth, wHeight, wBlendRate);
110
111 // �⤷���˺���������Τ����ꡢ̤�����ξ��ϳ���
112 scg_free(wNumCG);
113
114 cgs[wNumCG] = i;
115
116 return OK;
117 }
118
119 // �����CG��ȿž������CG�����
scg_create_reverse(int wNumCG,int wNumSrcCG,int wReverseX,int wReverseY)120 int scg_create_reverse(int wNumCG, int wNumSrcCG, int wReverseX, int wReverseY) {
121 cginfo_t *i, *srccg;
122 surface_t *src;
123
124 spcg_assert_no(wNumCG);
125 spcg_assert_no(wNumSrcCG);
126
127 // ���ˤ���CG�� (LINKCG�ʤ��ɤ߹���)
128 if (NULL == (srccg = scg_loadcg_no(wNumSrcCG, FALSE))) {
129 return NG;
130 }
131
132 i = g_new(cginfo_t, 1);
133 i->type = CG_REVERSE;
134 i->no = wNumCG;
135 i->refcnt = 0;
136
137 src = srccg->sf;
138 i->sf = stretch(src, src->width, src->height, (wReverseX << 1) | wReverseY);
139 // �⤷���˺���������Τ����ꡢ̤�����ξ��ϳ���
140 scg_free(wNumCG);
141
142 cgs[wNumCG] = i;
143
144 return OK;
145 }
146
147 // �����CG�����/�̾�����CG�����
scg_create_stretch(int wNumCG,int wWidth,int wHeight,int wNumSrcCG)148 int scg_create_stretch(int wNumCG, int wWidth, int wHeight, int wNumSrcCG) {
149 cginfo_t *i, *srccg;
150 surface_t *src;
151
152 spcg_assert_no(wNumCG);
153 spcg_assert_no(wNumSrcCG);
154
155 // ���ˤ���CG�� (LINKCG�ʤ��ɤ߹���)
156 if (NULL == (srccg = scg_loadcg_no(wNumSrcCG, FALSE))) {
157 return NG;
158 }
159
160 i = g_new(cginfo_t, 1);
161 i->type = CG_STRETCH;
162 i->no = wNumCG;
163 i->refcnt = 0;
164
165 src = srccg->sf;
166 i->sf = stretch(src, wWidth, wHeight, 0);
167
168 // �⤷���˺���������Τ����ꡢ̤�����ξ��ϳ���
169 scg_free(wNumCG);
170
171 cgs[wNumCG] = i;
172
173 return OK;
174 }
175
176 // �١���CG�ξ�˥֥���CG��Ťͤ� CG �����
scg_create_blend(int wNumDstCG,int wNumBaseCG,int wX,int wY,int wNumBlendCG,int wAlphaMapMode)177 int scg_create_blend(int wNumDstCG, int wNumBaseCG, int wX, int wY, int wNumBlendCG, int wAlphaMapMode) {
178 cginfo_t *i, *basecg, *blendcg;
179
180 spcg_assert_no(wNumDstCG);
181 spcg_assert_no(wNumBaseCG);
182 spcg_assert_no(wNumBlendCG);
183
184 // ���ˤ���CG�� (LINKCG�ʤ��ɤ߹���)
185 basecg = scg_loadcg_no(wNumBaseCG, FALSE);
186 blendcg = scg_loadcg_no(wNumBlendCG, FALSE);
187 if (basecg == NULL || blendcg == NULL) return NG;
188
189 i = g_new(cginfo_t, 1);
190 i->type = CG_SET;
191 i->no = wNumDstCG;
192 i->refcnt = 0;
193
194 i->sf = blend(basecg->sf, wX , wY, blendcg->sf, wAlphaMapMode);
195
196 // �⤷���˺���������Τ����ꡢ̤�����ξ��ϳ���
197 scg_free(wNumDstCG);
198
199 cgs[wNumDstCG] = i;
200
201 return OK;
202 }
203
204 // �����ʸ�����CG�����
scg_create_text(int wNumCG,int wSize,int wR,int wG,int wB,char * cText)205 int scg_create_text(int wNumCG, int wSize, int wR, int wG, int wB, char *cText) {
206 cginfo_t *i;
207 agsurface_t *glyph;
208 FONT *font;
209
210 if (0) {
211 char *b = sjis2euc(cText);
212 WARNING("str = '%s'\n", b);
213 free(b);
214 }
215
216 spcg_assert_no(wNumCG);
217
218 // ����˽ФƤ����Τ��ʡ�
219 if (strlen(cText) == 0) return OK;
220
221 font = nact->ags.font;
222 font->sel_font(FONT_GOTHIC, wSize);
223
224 glyph = font->get_glyph(cText);
225 i = g_new(cginfo_t, 1);
226 i->type = CG_SET;
227 i->no = wNumCG;
228 i->refcnt = 0;
229
230 i->sf = sf_create_surface(glyph->width, wSize, nact->ags.dib->depth);
231 gr_fill(i->sf, 0, 0, glyph->width, wSize, wR, wG, wB);
232 gr_draw_amap(i->sf, 0, 0, glyph->pixel, glyph->width, wSize, glyph->bytes_per_line);
233
234 // �⤷���˺���������Τ����ꡢ̤�����ξ��ϳ���
235 scg_free(wNumCG);
236
237 cgs[wNumCG] = i;
238
239 return OK;
240 }
241
242 // ����ʸ�����CG�����
scg_create_textnum(int wNumCG,int wSize,int wR,int wG,int wB,int wFigs,int wZeroPadding,int wValue)243 int scg_create_textnum(int wNumCG, int wSize, int wR, int wG, int wB, int wFigs, int wZeroPadding, int wValue) {
244 cginfo_t *i;
245 agsurface_t *glyph;
246 FONT *font;
247 char s[256], ss[256];
248
249 spcg_assert_no(wNumCG);
250
251 if (wZeroPadding) {
252 char *sss = "%%0%dd";
253 sprintf(ss, sss, wFigs);
254 } else {
255 char *sss = "%%%dd";
256 sprintf(ss, sss, wFigs);
257 }
258 sprintf(s, ss, wValue);
259
260 font = nact->ags.font;
261 font->sel_font(FONT_GOTHIC, wSize);
262 glyph = font->get_glyph(s);
263
264 i = g_new(cginfo_t, 1);
265 i->type = CG_SET;
266 i->no = wNumCG;
267 i->refcnt = 0;
268 i->sf = sf_create_surface(glyph->width, wSize, nact->ags.dib->depth);
269 gr_fill(i->sf, 0, 0, glyph->width, wSize, wR, wG, wB);
270 gr_draw_amap(i->sf, 0, 0, glyph->pixel, glyph->width, wSize, glyph->bytes_per_line);
271
272 // �⤷���˺���������Τ����ꡢ̤�����ξ��ϳ���
273 scg_free(wNumCG);
274
275 cgs[wNumCG] = i;
276
277 return OK;
278 }
279
280 // CG��ʣ��
scg_copy(int wNumDstCG,int wNumSrcCG)281 int scg_copy(int wNumDstCG, int wNumSrcCG) {
282 cginfo_t *i, *srccg;
283
284 spcg_assert_no(wNumDstCG);
285 spcg_assert_no(wNumSrcCG);
286
287 // ���ˤ���CG�� (LINKCG�ʤ��ɤ߹���)
288 if (NULL == (srccg = scg_loadcg_no(wNumSrcCG, FALSE))) {
289 return NG;
290 }
291
292 i = g_new(cginfo_t, 1);
293 i->type = CG_SET;
294 i->no = wNumDstCG;
295 i->refcnt = 0;
296 i->sf = sf_dup(srccg->sf);
297
298 // �⤷���˺���������Τ����ꡢ̤�����ξ��ϳ���
299 scg_free(wNumDstCG);
300
301 cgs[wNumDstCG] = i;
302
303 return OK;
304 }
305
306 // CG�ΰ������ڤ�̤���CG�����
scg_cut(int wNumDstCG,int wNumSrcCG,int wX,int wY,int wWidth,int wHeight)307 int scg_cut(int wNumDstCG, int wNumSrcCG, int wX, int wY, int wWidth, int wHeight) {
308 cginfo_t *i, *srccg;
309 surface_t *dst, *src;
310
311 spcg_assert_no(wNumDstCG);
312 spcg_assert_no(wNumSrcCG);
313
314 // ���ˤ���CG�� (LINKCG�ʤ��ɤ߹���)
315 if (NULL == (srccg = scg_loadcg_no(wNumSrcCG, FALSE))) {
316 return NG;
317 }
318
319 i = g_new(cginfo_t, 1);
320 i->type = CG_SET;
321 i->no = wNumDstCG;
322 i->refcnt = 0;
323
324 src = srccg->sf;
325 if (src->has_alpha) {
326 dst = sf_create_surface(wWidth, wHeight, src->depth);
327 } else {
328 dst = sf_create_pixel(wWidth, wHeight, src->depth);
329 }
330 if (src->has_pixel) {
331 gr_copy(dst, 0, 0, src, wX, wY, wWidth, wHeight);
332 }
333 if (src->has_alpha) {
334 gr_copy_alpha_map(dst, 0, 0, src, wX, wY, wWidth, wHeight);
335 }
336
337 i->sf = dst;
338
339 // �⤷���˺���������Τ����ꡢ̤�����ξ��ϳ���
340 scg_free(wNumDstCG);
341
342 cgs[wNumDstCG] = i;
343
344 return OK;
345 }
346
347 // ����CG�ΰ������ڤ�̤���CG�����
scg_partcopy(int wNumDstCG,int wNumSrcCG,int wX,int wY,int wWidth,int wHeight)348 int scg_partcopy(int wNumDstCG, int wNumSrcCG, int wX, int wY, int wWidth, int wHeight) {
349 cginfo_t *i, *srccg;
350 surface_t *dst, *src;
351
352 spcg_assert_no(wNumDstCG);
353 spcg_assert_no(wNumSrcCG);
354
355 // ���ˤ���CG�� (LINKCG�ʤ��ɤ߹���)
356 if (NULL == (srccg = scg_loadcg_no(wNumSrcCG, FALSE))) {
357 return NG;
358 }
359
360 i = g_new(cginfo_t, 1);
361 i->type = CG_SET;
362 i->no = wNumDstCG;
363 i->refcnt = 0;
364
365 src = srccg->sf;
366 if (src->has_alpha) {
367 dst = sf_create_surface(src->width, src->height, src->depth);
368 gr_fill_alpha_map(dst, 0, 0, src->width, src->height, 255);
369 } else {
370 dst = sf_create_pixel(src->width, src->height, src->depth);
371 }
372
373 if (src->has_pixel) {
374 gr_copy(dst, wX, wY, src, wX, wY, wWidth, wHeight);
375 }
376 if (src->has_alpha) {
377 gr_copy_alpha_map(dst, wX, wY, src, wX, wY, wWidth, wHeight);
378 }
379
380 i->sf = dst;
381
382 // �⤷���˺���������Τ����ꡢ̤�����ξ��ϳ���
383 scg_free(wNumDstCG);
384
385 cgs[wNumDstCG] = i;
386
387 return OK;
388 }
389
390 // ���Ƥ�CG�γ���
scg_freeall()391 int scg_freeall() {
392 int i;
393
394 for (i = 1; i < CGMAX; i++) {
395 scg_free(i);
396 }
397 return OK;
398 }
399
400 /**
401 * ������ֹ�� CG �֥������ȥꥹ�Ȥ���ä������֥������Ȥ��ɤ�����⻲��
402 * ����Ƥ��ʤ�(���ȿ���0��)���Τߡ����֥������Ȥ���
403 */
scg_free(int no)404 int scg_free(int no) {
405 cginfo_t *cg;
406
407 spcg_assert_no(no);
408
409 if (NULL == (cg = cgs[no])) return NG;
410
411 // ���ȿ���0�λ��Τߥ��֥������Ȥ���
412 if (cg->refcnt == 0) {
413 scg_free_cgobj(cg);
414 }
415
416 // �ֹ�Ǿä����Ȥ��ϥ��֥������Ȥ���������ʤ��Ƥ�
417 // ���֥������ȥꥹ�Ȥ�����
418 cgs[no] = NULL;
419
420 return OK;
421 }
422
423 /**
424 * CG ���֥������Ȥγ���
425 */
scg_free_cgobj(cginfo_t * cg)426 int scg_free_cgobj(cginfo_t *cg) {
427 if (cg == NULL) return NG;
428
429 (cg->refcnt)--;
430 // ¾�Ǥޤ����Ȥ��Ƥ���г������ʤ�
431 if (cg->refcnt > 0) {
432 return NG;
433 }
434
435 // CG���Τγ���
436 if (cg->sf) {
437 sf_free(cg->sf);
438 }
439
440 // ������륪�֥������ȤȤ��Ƥ��륪�֥������ȥꥹ�Ȥ���
441 if (cg == cgs[cg->no]) {
442 cgs[cg->no] = NULL;
443 }
444
445 g_free(cg);
446
447 return OK;
448 }
449
450 // CG�������
scg_querytype(int wNumCG,int * ret)451 int scg_querytype(int wNumCG, int *ret) {
452 if (wNumCG >= (CGMAX -1)) goto errexit;
453 if (cgs[wNumCG] == NULL) goto errexit;
454
455 *ret = cgs[wNumCG]->type;
456
457 return OK;
458
459 errexit:
460 *ret = CG_NOTUSED;
461 return NG;
462 }
463
464 // CG���礭�������
scg_querysize(int wNumCG,int * w,int * h)465 int scg_querysize(int wNumCG, int *w, int *h) {
466 if (wNumCG >= (CGMAX -1)) goto errexit;
467 if (cgs[wNumCG] == NULL) goto errexit;
468 if (cgs[wNumCG]->sf == NULL) goto errexit;
469
470 *w = cgs[wNumCG]->sf->width;
471 *h = cgs[wNumCG]->sf->height;
472
473 return OK;
474
475 errexit:
476 *w = *h = 0;
477 return NG;
478 }
479
480 // CG��BPP�����
scg_querybpp(int wNumCG,int * ret)481 int scg_querybpp(int wNumCG, int *ret) {
482 if (wNumCG >= (CGMAX -1)) goto errexit;
483 if (cgs[wNumCG] == NULL) goto errexit;
484 if (cgs[wNumCG]->sf == NULL) goto errexit;
485
486 *ret = cgs[wNumCG]->sf->depth;
487
488 return OK;
489
490 errexit:
491 *ret = 0;
492 return NG;
493 }
494
495 // CG�� alphamap ��¸�ߤ��뤫�����
scg_existalphamap(int wNumCG,int * ret)496 int scg_existalphamap(int wNumCG, int *ret) {
497 if (wNumCG >= (CGMAX -1)) goto errexit;
498 if (cgs[wNumCG] == NULL) goto errexit;
499 if (cgs[wNumCG]->sf == NULL) goto errexit;
500
501 *ret = cgs[wNumCG]->sf->has_alpha ? 1 : 0;
502
503 errexit:
504 *ret = 0;
505 return NG;
506 }
507