1 #include "XFireworksP.h"
2 
3 #include <signal.h>
4 
5 #include "etc.h"
6 #include "Piece.h"
7 #include "AfterImage.h"
8 
9 #include "xfireworks_conf.h"
10 
11 /*===========================================================================*/
12 /* �����ǻ��Ѥ���ؿ�                                                        */
13 /*===========================================================================*/
14 
15 /*---------------------------------------------------------------------------*/
16 /* ����ե�����졼������ѤΥե������õ����̵����Хǥե���ȤΥǡ�����    */
17 /* �ɤ߹��ࡥ                                                                */
18 /*---------------------------------------------------------------------------*/
19 
Stream_CreateFromFileOrCharacters(char * dirname,char * filename,char * default_xfireworks_conf)20 static Stream Stream_CreateFromFileOrCharacters(char * dirname,
21 						char * filename,
22 						char * default_xfireworks_conf)
23 {
24   Stream stream;
25   char * work;
26 
27   stream = Stream_CreateFromFile(filename);
28   if (stream != NULL) return (stream);
29 
30   /* dirname �� "" ���ä��Ȥ��ˡ�./[filename] �Τ褦�ʥե������ */
31   /* Ĵ�٤�Τǡ�1 �ǤϤʤ� 3 ��ä��Ƥ��롥                     */
32   work = (char *)malloc(sizeof(char)
33 			* (StringLen(dirname) + StringLen(filename) + 3));
34 
35   StringCpy(work, "./");
36   StringCat(work, filename);
37 
38   stream = Stream_CreateFromFile(work);
39   if (stream != NULL) goto stream_return;
40 
41   StringCpy(work, dirname);
42   StringCat(work, "/");
43   StringCat(work, filename);
44 
45   stream = Stream_CreateFromFile(work);
46   if (stream != NULL) goto stream_return;
47 
48   stream = Stream_CreateFromCharacters(default_xfireworks_conf);
49 
50 stream_return:
51 
52   free(work);
53   return (stream);
54 }
55 
56 /*===========================================================================*/
57 /* ���֥������Ȥ������Ⱥ��                                                  */
58 /*===========================================================================*/
59 
60 /*---------------------------------------------------------------------------*/
61 /* ���֥������Ȥ�����                                                        */
62 /*---------------------------------------------------------------------------*/
63 
XFireworks_Create(char * display_name,int direct_draw,char * background_color,char * dirname,char * filename,int studying_flag,int cache_flag,int cache_size,int hash_number,int fine,int gradation,int probability_magnification,int size_magnification,int air_magnification,int gravity_magnification,int transmission_magnification,int after_image_magnification,int color_length_magnification,int next_power_magnification,int next_number_magnification)64 XFireworks XFireworks_Create(char * display_name,
65 			     int direct_draw,
66 			     char * background_color,
67 			     char * dirname,
68 			     char * filename,
69 			     int studying_flag,
70 			     int cache_flag,
71 			     int cache_size,
72 			     int hash_number,
73 			     int fine,
74 			     int gradation,
75 			     int probability_magnification,
76 			     int size_magnification,
77 			     int air_magnification,
78 			     int gravity_magnification,
79 			     int transmission_magnification,
80 			     int after_image_magnification,
81 			     int color_length_magnification,
82 			     int next_power_magnification,
83 			     int next_number_magnification)
84 {
85   XFireworks xfireworks;
86   Stream stream;
87   ColorGC color_gc;
88 
89   xfireworks = (XFireworks)malloc(sizeof(_XFireworks));
90   if (!xfireworks) Error("XFireworks_Create", "Cannot allocate mamory");
91 
92   /* �������� */
93   InitializeRand();
94 
95   /* �ǥ����ץ쥤����� */
96   xfireworks->disp = Disp_Create(display_name, direct_draw);
97 
98   /* GC�Υǡ����١�������� */
99   xfireworks->color_gc_database = ColorGCDatabase_Create(xfireworks->disp,
100 							 studying_flag,
101 							 cache_flag,
102 							 cache_size,
103 							 hash_number,
104 							 background_color,
105 							 gradation);
106 
107   /* �ǥ����ץ쥤�Υ��ꥢ */
108   color_gc =
109     ColorGCDatabase_GetBackgroundColorGC(xfireworks->color_gc_database);
110   if (!direct_draw)
111     Disp_ClearPixmap(xfireworks->disp, ColorGC_GetGC(color_gc));
112   Disp_ClearDisplay(xfireworks->disp, ColorGC_GetPixel(color_gc));
113 
114   /* PieceClass ���ɤ߹��� */
115   stream =
116     Stream_CreateFromFileOrCharacters(dirname, filename,
117 				      default_xfireworks_conf);
118   xfireworks->piece_class_list =
119     PieceClassList_CreateFromStream(xfireworks->disp,
120 				    xfireworks->color_gc_database,
121 				    stream,
122 				    fine,
123 				    probability_magnification,
124 				    size_magnification,
125 				    air_magnification,
126 				    gravity_magnification,
127 				    transmission_magnification,
128 				    after_image_magnification,
129 				    color_length_magnification,
130 				    next_power_magnification,
131 				    next_number_magnification);
132   Stream_Destroy(stream);
133 
134   xfireworks->pieces_list            = ObjList_Create();
135   xfireworks->free_pieces_list       = ObjList_Create();
136   xfireworks->after_images_list      = ObjList_Create();
137   xfireworks->free_after_images_list = ObjList_Create();
138 
139   /* �ϥå����������ɽ��(���塼�˥���) */
140 #ifdef OUTPUT_HASH_STATUS
141   ColorGCDatabase_OutputHashStatus(xfireworks->color_gc_database);
142 #endif
143 
144   xfireworks->calculator = Calculator_Create(CALCULATOR_DEFAULT_DEGREE);
145 
146   return (xfireworks);
147 }
148 
149 /*---------------------------------------------------------------------------*/
150 /* ���֥������Ȥκ��                                                        */
151 /*---------------------------------------------------------------------------*/
152 
XFireworks_Destroy(XFireworks xfireworks)153 XFireworks XFireworks_Destroy(XFireworks xfireworks)
154 {
155   ColorGC color_gc;
156 
157   if (!xfireworks) return (NULL);
158 
159   /* �ǥ����ץ쥤�Υ��ꥢ */
160   color_gc =
161     ColorGCDatabase_GetBackgroundColorGC(xfireworks->color_gc_database);
162   Disp_ClearDisplay(xfireworks->disp, ColorGC_GetPixel(color_gc));
163 
164   if (xfireworks->calculator) Calculator_Destroy(xfireworks->calculator);
165 
166   if (xfireworks->free_after_images_list)
167     ObjList_Destroy(xfireworks->free_after_images_list);
168   if (xfireworks->after_images_list)
169     ObjList_Destroy(xfireworks->after_images_list);
170   if (xfireworks->free_pieces_list)
171     ObjList_Destroy(xfireworks->free_pieces_list);
172   if (xfireworks->pieces_list)
173     ObjList_Destroy(xfireworks->pieces_list);
174 
175   if (xfireworks->piece_class_list)
176     ObjList_Destroy(xfireworks->piece_class_list);
177 
178   if (xfireworks->color_gc_database)
179     ColorGCDatabase_Destroy(xfireworks->color_gc_database);
180   if (xfireworks->disp) Disp_Destroy(xfireworks->disp);
181 
182   free(xfireworks);
183 
184   return (NULL);
185 }
186 
187 /*===========================================================================*/
188 /* �ֲФΥ�������                                                            */
189 /*===========================================================================*/
190 
191 /*---------------------------------------------------------------------------*/
192 /* PieceClass ��ɽ��(�ǥХå���)                                             */
193 /*---------------------------------------------------------------------------*/
194 
XFireworks_DrawAllPieceClasses(XFireworks xfireworks)195 static int XFireworks_DrawAllPieceClasses(XFireworks xfireworks)
196 {
197   PieceClass piece_class;
198   ObjList gc_list_list;
199   ObjList gc_list;
200   ObjListData a, b, c;
201   GC gc;
202 
203   int x, y;
204 
205   x = 10;
206   y = 10;
207 
208   for (a = ObjList_GetStart(xfireworks->piece_class_list);
209        !ObjList_IsEndEdge(xfireworks->piece_class_list, a);
210        a = ObjListData_GetNext(a)) {
211     piece_class = (PieceClass)ObjListData_GetObj(a);
212     gc_list_list = PieceClass_GetGCListList(piece_class);
213 
214     for (b = ObjList_GetStart(gc_list_list);
215 	 !ObjList_IsEndEdge(gc_list_list, b);
216 	 b = ObjListData_GetNext(b)) {
217 
218       gc_list = ObjListData_GetObj(b);
219 
220       x = 10;
221       for (c = ObjList_GetStart(gc_list);
222 	   !ObjList_IsEndEdge(gc_list, c);
223 	   c = ObjListData_GetNext(c)) {
224 	gc = ColorGC_GetGC(ObjListData_GetObj(c));
225 	Disp_DrawFilledCircle(xfireworks->disp, gc, x, y, 5);
226 	Disp_Flush(xfireworks->disp);
227 	x += 10;
228       }
229       y += 10;
230     }
231   }
232   return (0);
233 }
234 
235 /*---------------------------------------------------------------------------*/
236 /* �����ʥ����                                                              */
237 /*---------------------------------------------------------------------------*/
238 
239 static int end_flag;
240 
InterruptTrap(int n)241 static void InterruptTrap(int n)
242 {
243   end_flag = 1;
244 }
245 
246 /*---------------------------------------------------------------------------*/
247 /* ̤���Ѥ� Pieces �Υꥹ�Ȥ��顤�Ȥ��� Pieces ���֥������Ȥ�������        */
248 /* ��������롥���Ĥ���ʤ��ä����ˤϡ�create ���롥                       */
249 /*---------------------------------------------------------------------------*/
250 
SearchOrCreateUsablePieces(XFireworks xfireworks,PieceClass piece_class,double power,int number,int n,XArc * positions,double * z,double * vx,double * vy,double * vz,int x_min,int y_min,int x_max,int y_max)251 static int SearchOrCreateUsablePieces(XFireworks xfireworks,
252 				      PieceClass piece_class, double power,
253 				      int number, int n,
254 				      XArc * positions, double * z,
255 				      double * vx, double * vy, double * vz,
256 				      int x_min, int y_min,
257 				      int x_max, int y_max)
258 {
259   Pieces pieces;
260   ObjListData current;
261 
262   for (current = ObjList_GetStart(xfireworks->free_pieces_list);
263        !ObjList_IsEndEdge(xfireworks->free_pieces_list, current);
264        current = ObjListData_GetNext(current)) {
265     pieces = (Pieces)ObjListData_GetObj(current);
266     if (Pieces_GetArraySize(pieces) >= number * n) {
267       Pieces_Initialize(pieces, piece_class, power, number, n,
268 			positions, z, vx, vy, vz,
269 			x_min, y_min, x_max, y_max,
270 			xfireworks->calculator);
271       ObjList_MoveObjToEndOfOtherList(xfireworks->free_pieces_list, current,
272 				      xfireworks->pieces_list);
273       return (0);
274     }
275   }
276 
277   /* ���ѤǤ��� Pieces ���֥������Ȥ�̵���ä��顤�������������� */
278   pieces = Pieces_Create(piece_class, power, number, n,
279 			 positions, z, vx, vy, vz, x_min, y_min, x_max, y_max,
280 			 xfireworks->calculator);
281   if (pieces == NULL) return (0);
282   ObjList_InsertObjToEnd(xfireworks->pieces_list, pieces,
283 			 (ObjDestructor)Pieces_Destroy);
284 
285   return (1);
286 }
287 
288 /*---------------------------------------------------------------------------*/
289 /* ̤���Ѥ� AfterImages �Υꥹ�Ȥ��顤�Ȥ��� AfterImages ���֥������Ȥ�      */
290 /* ����������������롥���Ĥ���ʤ��ä����ˤϡ�create ���롥               */
291 /*---------------------------------------------------------------------------*/
292 
SearchOrCreateUsableAfterImages(XFireworks xfireworks,int number,XArc * positions,int x_min,int y_min,int x_max,int y_max,ObjList list)293 static int SearchOrCreateUsableAfterImages(XFireworks xfireworks,
294 					   int number,
295 					   XArc * positions,
296 					   int x_min, int y_min,
297 					   int x_max, int y_max,
298 					   ObjList list)
299 {
300   AfterImages after_images;
301   ObjListData current;
302 
303   for (current = ObjList_GetStart(xfireworks->free_after_images_list);
304        !ObjList_IsEndEdge(xfireworks->free_after_images_list, current);
305        current = ObjListData_GetNext(current)) {
306     after_images = (AfterImages)ObjListData_GetObj(current);
307     if (AfterImages_GetArraySize(after_images) >= number) {
308       AfterImages_Initialize(after_images, number, positions,
309 			     x_min, y_min, x_max, y_max, list);
310       ObjList_MoveObjToEndOfOtherList(xfireworks->free_after_images_list,
311 				      current,
312 				      xfireworks->after_images_list);
313       return (0);
314     }
315   }
316 
317   /* ���ѤǤ��� AfterImages ���֥������Ȥ�̵���ä��顤�������������� */
318   after_images = AfterImages_Create(number, positions,
319 				    x_min, y_min, x_max, y_max, list);
320   if (after_images == NULL) return (0);
321   ObjList_InsertObjToEnd(xfireworks->after_images_list, after_images,
322 			 (ObjDestructor)AfterImages_Destroy);
323 
324   return (1);
325 }
326 
327 /*---------------------------------------------------------------------------*/
328 /* �ֲФΥ�������                                                            */
329 /*---------------------------------------------------------------------------*/
330 
XFireworks_Start(XFireworks xfireworks,int pieces_max_number,int wait_time)331 int XFireworks_Start(XFireworks xfireworks,
332 		     int pieces_max_number,
333 		     int wait_time)
334 {
335   PieceClass piece_class;
336   PieceNext piece_next;
337   Pieces pieces;
338   Pieces pieces2;
339   ObjList next_list;
340   ObjListData current;
341   ObjListData current2;
342   AfterImages after_images;
343   XArc position;
344   double z, vx, vy, vz;
345   GC gc;
346   int ret;
347 
348 #if 0
349   XFireworks_DrawAllPieceClasses(xfireworks);
350   while(1) { /* None */ }
351 #endif
352 
353   end_flag = 0;
354   signal(SIGINT , InterruptTrap);
355   signal(SIGTERM, InterruptTrap);
356 
357   while (end_flag == 0) {
358 
359     /* ������ Pieces ������ */
360     if (ObjList_GetLength(xfireworks->pieces_list) < pieces_max_number) {
361 
362       for (current = ObjList_GetStart(xfireworks->piece_class_list);
363 	   !ObjList_IsEndEdge(xfireworks->piece_class_list, current);
364 	   current = ObjListData_GetNext(current)) {
365 	piece_class = (PieceClass)ObjListData_GetObj(current);
366 	if (PieceClass_GetProbability(piece_class) > 0.0) {
367 	  if (PieceClass_GetProbability(piece_class) > DoubleRand(100.0)) {
368 	    position.x = (double)Rand(Disp_GetWidth( xfireworks->disp));
369 	    position.y = (double)Rand(Disp_GetHeight(xfireworks->disp));
370 	    position.width  = PieceClass_GetSize(piece_class);
371 	    position.height = PieceClass_GetSize(piece_class);
372 	    position.angle1 = 0;
373 	    position.angle2 = 360*64;
374 	    z = DoubleRand(400.0) - 200.0;
375 	    vx = 0.0;
376 	    vy = 0.0;
377 	    vz = 0.0;
378 	    position.y -= Disp_GetHeight(xfireworks->disp) * 0.25;
379 
380 	    SearchOrCreateUsablePieces(xfireworks,
381 				       piece_class, 0.0, 1, 1,
382 				       &position, &z, &vx, &vy, &vz,
383 				       0, 0,
384 				       Disp_GetWidth( xfireworks->disp) - 1,
385 				       Disp_GetHeight(xfireworks->disp) - 1);
386 	  }
387 	}
388       }
389     }
390 
391     /* Pieces �ν��� */
392     for (current = ObjList_GetStart(xfireworks->pieces_list);
393 	 !ObjList_IsEndEdge(xfireworks->pieces_list, current);
394 	 current = ObjListData_GetNext(current)) {
395 
396       pieces = (Pieces)ObjListData_GetObj(current);
397       piece_class = Pieces_GetPieceClass(pieces);
398 
399       ret = Pieces_Move(pieces, 0, 0,
400 			Disp_GetWidth( xfireworks->disp) - 1,
401 			Disp_GetHeight(xfireworks->disp) - 1,
402 			Disp_GetWidth( xfireworks->disp));
403       if (ret) { /* dz���Ԥ������ */
404 	next_list = PieceClass_GetNextList(piece_class);
405 	if ((Pieces_GetNumber(pieces) > 0) && (next_list != NULL)) {
406 	  for (current2 = ObjList_GetStart(next_list);
407 	       !ObjList_IsEndEdge(next_list, current2);
408 	       current2 = ObjListData_GetNext(current2)) {
409 	    piece_next = (PieceNext)ObjListData_GetObj(current2);
410 
411 	    SearchOrCreateUsablePieces(xfireworks,
412 				       PieceNext_GetPieceClass(piece_next),
413 				       PieceNext_GetPower(piece_next),
414 				       PieceNext_GetNumber(piece_next),
415 				       Pieces_GetNumber(pieces),
416 				       Pieces_GetPositions(pieces),
417 				       Pieces_GetZ(pieces),
418 				       Pieces_GetVx(pieces),
419 				       Pieces_GetVy(pieces),
420 				       Pieces_GetVz(pieces),
421 				       0, 0,
422 				       Disp_GetWidth( xfireworks->disp) - 1,
423 				       Disp_GetHeight(xfireworks->disp) - 1);
424 	  }
425 	}
426 	current2 = ObjListData_GetPrev(current);
427 	ObjList_MoveObjToStartOfOtherList(xfireworks->pieces_list,
428 					  current,
429 					  xfireworks->free_pieces_list);
430 	current = current2;
431       } else {
432 	SearchOrCreateUsableAfterImages(xfireworks,
433 					Pieces_GetNumber(pieces),
434 					Pieces_GetPositions(pieces),
435 					0, 0,
436 					Disp_GetWidth( xfireworks->disp) - 1,
437 					Disp_GetHeight(xfireworks->disp) - 1,
438 					Pieces_GetGCList(pieces));
439       }
440     }
441 
442     /* �����ν��� */
443     for (current = ObjList_GetStart(xfireworks->after_images_list);
444 	 !ObjList_IsEndEdge(xfireworks->after_images_list, current);
445 	 current = ObjListData_GetNext(current)) {
446       after_images = (AfterImages)ObjListData_GetObj(current);
447 
448       gc = AfterImages_GetGC(after_images);
449 
450       if (gc == NULL) {
451 	current2 = ObjListData_GetPrev(current);
452 	ObjList_MoveObjToStartOfOtherList(xfireworks->after_images_list,
453 					  current,
454 					  xfireworks->free_after_images_list);
455 	current = current2;
456       } else {
457 	if (AfterImages_GetNumber(after_images) > 0)
458 	  Disp_DrawFilledCircles(xfireworks->disp, gc,
459 				 AfterImages_GetArcs(after_images),
460 				 AfterImages_GetNumber(after_images));
461 
462 	/* X �����Ф�Ϣ³����٤�Ϳ���ʤ�����Υ������� */
463 #if 0
464 	usleep(10);
465 #endif
466       }
467     }
468 
469     /* X�����Ф˻Ż����Ƥ�餤��     */
470     /* X�����Ф��Ż���λ����Τ��Ԥ� */
471     Disp_Sync(xfireworks->disp);
472 
473     /* usleep() �� Disp_Sync() �θ���֤����ȡ�                   */
474     /* (Disp_Sync() �Ǥ�X�����ФλŻ���λ�Ԥ��ǥ֥�å�����Τǡ� */
475     /*  Disp_Sync() ������ usleep() ���֤��Ƥ⤢�ޤ��̣��̵��)   */
476     usleep(1000 + wait_time);
477   }
478 
479   return (0);
480 }
481 
482 /*****************************************************************************/
483 /* End of File.                                                              */
484 /*****************************************************************************/
485