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