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