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