remove engine and glyphwiki from repogitry.
[chise/kage.git] / kagecgi / kagetool.c
1 //kagetool.c
2 //
3
4 #include "kage.h"
5 #include "kagecgi.h"
6 #include "sysdep.h"
7
8 void DotsWidth(int *dlx, int *drx){
9   int i, j;
10   
11   *dlx = 0;
12   *drx = 0;
13   for(i = 0; i < canvasWidth && *dlx == 0; i++){
14     for(j = 0; j < canvasHeight; j++){
15       if(kageCanvas[j][i] != kWhite){
16         *dlx = i;
17         break;
18       }
19     }
20   }
21   
22   for(i = canvasWidth - 1; i >= 0 && *drx == 0; i--){
23     for(j = 0; j < canvasHeight; j++){
24       if(kageCanvas[j][i] != kWhite){
25         *drx = i;
26         break;
27       }
28     }
29   }
30 }
31
32 void DotsHeight(int *dly, int *dry){
33   int i, j;
34   
35   *dly = 0;
36   *dry = 0;
37   for(j = 0; j < canvasHeight && *dly == 0; j++){
38     for(i = 0; i < canvasWidth; i++){
39       if(kageCanvas[j][i] != kWhite){
40         *dly = j;
41         break;
42       }
43     }
44   }
45   
46   for(j = canvasHeight - 1; j >= 0 && *dry == 0; j--){
47     for(i = 0; i < canvasWidth; i++){
48       if(kageCanvas[j][i] != kWhite){
49         *dry = j;
50         break;
51       }
52     }
53   }
54 }
55
56 void PartsWidth(const KGString *in, int *lx, int *rx){
57   int tempShotai;
58   DrawBox();
59   tempShotai = kShotai;
60   kShotai = kGothic;
61   drawGlyph(in, DRAW_GLYPH_MODE_WITHOUT_DECORATION);
62   kShotai = tempShotai;
63   DotsWidth(lx, rx);
64   /*
65     int i;
66         int *buf, strokes;
67         double t, x;
68         
69         *lx = 1000; *rx = 0;
70         buf = convertStroke(in->str, buf, &strokes);
71         
72     for(i = 0; i < strokes; i++){
73                 switch(buf[i * 11 + 0] % 10){
74                 
75                 case 0:
76                 case 9:
77                         break;
78                 case 1:
79                 if(*lx > buf[i * 11 + 3]) *lx = buf[i * 11 + 3];
80                         if(*rx < buf[i * 11 + 3]) *rx = buf[i * 11 + 3];
81                 if(*lx > buf[i * 11 + 5]) *lx = buf[i * 11 + 5];
82                 if(*rx < buf[i * 11 + 5]) *rx = buf[i * 11 + 5];
83                         break;
84                 case 2:
85                         for(t = 0; t <= 1; t = t + 0.05){
86                                 x = (1.0 - t) * (1.0 - t) * buf[i * 11 + 3] + 2.0 * t * (1.0 - t) * buf[i * 11 + 5] + t * t * buf[i * 11 + 7];
87                         if(*lx > x) *lx = x;
88                     if(*rx < x) *rx = x;
89                         }
90                         break;
91                 case 3:
92                 if(*lx > buf[i * 11 + 3]) *lx = buf[i * 11 + 3];
93                         if(*rx < buf[i * 11 + 3]) *rx = buf[i * 11 + 3];
94                 if(*lx > buf[i * 11 + 5]) *lx = buf[i * 11 + 5];
95                 if(*rx < buf[i * 11 + 5]) *rx = buf[i * 11 + 5];
96                 if(*lx > buf[i * 11 + 7]) *lx = buf[i * 11 + 7];
97             if(*rx < buf[i * 11 + 7]) *rx = buf[i * 11 + 7];
98                         break;
99                 case 6:
100                         for(t = 0; t < 1; t = t + 0.05){
101                                 x = (1.0 - t) * (1.0 - t) * (1.0 - t) * buf[i * 11 + 3] + 3.0 * t * (1.0 - t) * (1.0 - t) * buf[i * 11 + 5] + 3 * t * t * (1.0 - t) * buf[i * 11 + 7] + t * t * t * buf[i * 11 + 9];
102                         if(*lx > x) *lx = x;
103                     if(*rx < x) *rx = x;
104                         }
105                         break;
106                 case 7:
107                 if(*lx > buf[i * 11 + 3]) *lx = buf[i * 11 + 3];
108                         if(*rx < buf[i * 11 + 3]) *rx = buf[i * 11 + 3];
109                         for(t = 0; t < 1; t = t + 0.05){
110                                 x = (1.0 - t) * (1.0 - t) * buf[i * 11 + 5] + 2.0 * t * (1.0 - t) * buf[i * 11 + 7] + t * t * buf[i * 11 + 9];
111                         if(*lx > x) *lx = x;
112                     if(*rx < x) *rx = x;
113                         }
114                 }
115         }
116         free(buf);
117         */
118 }
119
120 void PartsHeight(const KGString *in, int *ly, int *ry){
121   int tempShotai;
122   DrawBox();
123   tempShotai = kShotai;
124   kShotai = kGothic;
125   drawGlyph(in, DRAW_GLYPH_MODE_WITHOUT_DECORATION);
126   kShotai = tempShotai;
127   DotsHeight(ly, ry);
128         /*
129     int i;
130         int *buf, strokes;
131         double t, y;
132         
133         *ly = 1000; *ry = 0;
134         buf = convertStroke(in->str, buf, &strokes);
135         
136     for(i = 0; i < strokes; i++){
137                 switch(buf[i * 11 + 0] % 10){
138                 
139                 case 0:
140                 case 9:
141                         break;
142                 case 1:
143                 if(*ly > buf[i * 11 + 4]) *ly = buf[i * 11 + 4];
144                         if(*ry < buf[i * 11 + 4]) *ry = buf[i * 11 + 4];
145                 if(*ly > buf[i * 11 + 6]) *ly = buf[i * 11 + 6];
146                 if(*ry < buf[i * 11 + 6]) *ry = buf[i * 11 + 6];
147                         break;
148                 case 2:
149                         for(t = 0; t <= 1; t = t + 0.05){
150                                 y = (1.0 - t) * (1.0 - t) * buf[i * 11 + 4] + 2.0 * t * (1.0 - t) * buf[i * 11 + 6] + t * t * buf[i * 11 + 8];
151                         if(*ly > y) *ly = y;
152                     if(*ry < y) *ry = y;
153                         }
154                         break;
155                 case 3:
156                 if(*ly > buf[i * 11 + 4]) *ly = buf[i * 11 + 4];
157                         if(*ry < buf[i * 11 + 4]) *ry = buf[i * 11 + 4];
158                 if(*ly > buf[i * 11 + 6]) *ly = buf[i * 11 + 6];
159                 if(*ry < buf[i * 11 + 6]) *ry = buf[i * 11 + 6];
160                 if(*ly > buf[i * 11 + 8]) *ly = buf[i * 11 + 8];
161             if(*ry < buf[i * 11 + 8]) *ry = buf[i * 11 + 8];
162                         break;
163                 case 6:
164                         for(t = 0; t < 1; t = t + 0.05){
165                                 y = (1.0 - t) * (1.0 - t) * (1.0 - t) * buf[i * 11 + 4] + 3.0 * t * (1.0 - t) * (1.0 - t) * buf[i * 11 + 6] + 3 * t * t * (1.0 - t) * buf[i * 11 + 8] + t * t * t * buf[i * 11 + 10];
166                         if(*ly > y) *ly = y;
167                     if(*ry < y) *ry = y;
168                         }
169                         break;
170                 case 7:
171                 if(*ly > buf[i * 11 + 4]) *ly = buf[i * 11 + 4];
172                         if(*ry < buf[i * 11 + 4]) *ry = buf[i * 11 + 4];
173                         for(t = 0; t < 1; t = t + 0.05){
174                                 y = (1.0 - t) * (1.0 - t) * buf[i * 11 + 6] + 2.0 * t * (1.0 - t) * buf[i * 11 + 8] + t * t * buf[i * 11 + 10];
175                         if(*ly > y) *ly = y;
176                     if(*ry < y) *ry = y;
177                         }
178                 }
179         }
180         free(buf);
181         */
182         /*
183     int i;
184         int *buf, strokes;
185         
186         buf = convertStroke(in->str, buf, &strokes);
187         *ly = 1000; *ry = 0;
188         
189     for(i = 0; i < strokes; i++){
190         if(buf[i * 11 + 0] % 10 == 0) continue;
191                 
192         if(*ly > buf[i * 11 + 4]) *ly = buf[i * 11 + 4];
193                 if(*ry < buf[i * 11 + 4]) *ry = buf[i * 11 + 4];
194         if(*ly > buf[i * 11 + 6]) *ly = buf[i * 11 + 6];
195         if(*ry < buf[i * 11 + 6]) *ry = buf[i * 11 + 6];
196                 
197         if(buf[i * 11 + 0] % 10 == 2 || buf[i * 11 + 0] % 10 == 3 || buf[i * 11 + 0] % 10 == 8){
198                 if(*ly > buf[i * 11 + 8]) *ly = buf[i * 11 + 8];
199             if(*ry < buf[i * 11 + 8]) *ry = buf[i * 11 + 8];
200                 }
201         if(buf[i * 11 + 0] % 10 == 4 || buf[i * 11 + 0] % 10 == 6 || buf[i * 11 + 0] % 10 == 7){
202                 if(*ly > buf[i * 11 + 10]) *ly = buf[i * 11 + 10];
203                 if(*ry < buf[i * 11 + 10]) *ry = buf[i * 11 + 10];
204         }
205         }
206         free(buf);
207         */
208 }
209
210 KGString * CalcSizes(const KGString *in, int mode){
211   int i, j, k, basewidth, one_lineX, one_lineY;
212   int dlx1, drx1, dly1, dry1;
213   int px1, py1;
214   double pr1, pry1;
215   
216   int mitsuT, flg_boxT, widthT, heightT;
217   double tateT, yokoT;
218   int cutx, cuty;
219   
220   int *buf, strokes;
221   int tf[12];
222   KGString *out;
223   
224   out = kg_string_new("");
225   basewidth = pngWidth * 0.9;
226   
227   if(mode == 0){
228     //temporary adjustment X-axis
229     PartsWidth(in, &dlx1, &drx1);
230     if(dlx1 == drx1){
231       pr1 = 1.0;
232       px1 = pngWidth / 2 - dlx1;
233       one_lineX = 1;
234     }
235     else{
236       pr1 = (double)basewidth/(drx1 - dlx1);
237       px1 = (pngWidth-basewidth)/2 - (double)(dlx1 * pr1);
238       one_lineX = 0;
239     }
240     
241     //temporary adjustment Y-axis
242     PartsHeight(in, &dly1, &dry1);
243     if(dly1 == dry1){
244       pry1 = 1.0;
245       py1 = pngWidth / 2 - dly1;
246       one_lineY = 1;
247     }
248     else{
249       pry1 = (double)basewidth/(dry1 - dly1);
250       py1 = (pngWidth-basewidth)/2 - (double)(dly1 * pry1);
251       one_lineY = 0;
252     }
253   }
254   else{
255     PartsWidth(in, &dlx1, &drx1);
256     PartsHeight(in, &dly1, &dry1);
257     
258     cutx = 0;
259     cuty = 0;
260     
261     CalcOptions(in, &mitsuT, &flg_boxT, &yokoT, &tateT);
262     
263     widthT = basewidth;
264     heightT = basewidth;
265     
266     if(flg_boxT % 2 / 1 != 0){
267       widthT = widthT - kWidth * 3;
268       cutx++;
269     }
270     if(flg_boxT % 4 / 2 != 0){
271       widthT = widthT - kWidth * 3;
272       cutx++;
273     }
274     if(flg_boxT % 8 / 4 != 0){
275       heightT = heightT - kWidth * 3;
276       cuty++;
277     }
278     if(flg_boxT % 16 / 8 != 0){
279       heightT = heightT - kWidth * 3;
280       cuty++;
281     }
282     
283     //especially get small the 'mouth'
284     if(mode == 2 && flg_boxT % 16 == 15){
285       widthT = widthT - kWidth * (max(0, 16 - (int)yokoT * 4));
286       heightT = heightT - kWidth * (max(0, 16 - (int)tateT * 4));
287     }
288     //'dot' as same as 'mouth'
289     if(mode == 2 && tateT == 1 && yokoT == 1){
290       widthT = pngWidth * 0.9 * 0.5;
291       heightT = pngWidth * 0.9 * 0.5;
292     }
293     
294     /*
295 if(flg_boxT % 64 / 32 != 0){
296             buf = convertStroke(in->str, buf, &strokes);
297             for(i = 0; i < strokes; i++){
298               if(buf[i * 11 + 0] == 0) j = buf[i * 11 + 4];// j : center line
299             }
300             free(buf);
301             k = max(j - dlx1, drx1 - j);// k : distance from center line
302             pr1 = (basewidth * 0.5) / k;
303             
304             if(k == j - dlx1) px1 = 0;
305             else px1 = pngWidth * 0.5 - j * pr1;
306           }
307         else
308 */
309           if(dlx1 == drx1){
310             pr1 = 1.0;
311             px1 = pngWidth / 2 - dlx1;
312           }
313           else{
314             pr1 = (double)widthT/(drx1 - dlx1);
315             px1 = pngWidth / 2 - (double)((dlx1 + drx1) / 2 * pr1);
316             if(flg_boxT % 2 / 1 != 0 && flg_boxT % 4 / 2 == 0) px1 = px1 + kWidth * 1.5;
317             if(flg_boxT % 2 / 1 == 0 && flg_boxT % 4 / 2 != 0) px1 = px1 - kWidth * 1.5;
318           }
319                 
320         if(dly1 == dry1){
321             pry1 = 1.0;
322             py1 = pngWidth / 2 - dly1;
323         }
324         else{
325             pry1 = (double)heightT/(dry1 - dly1);
326             py1 = pngWidth / 2 - (double)((dly1 + dry1) / 2 * pry1);
327             if(flg_boxT % 8 / 4 != 0 && flg_boxT % 16 / 8 == 0) py1 = py1 + kWidth * 1.5;
328             if(flg_boxT % 8 / 4 == 0 && flg_boxT % 16 / 8 != 0) py1 = py1 - kWidth * 1.5;
329         }
330         }
331         
332         //generate result
333         tf[0] = px1;
334         tf[1] = py1;
335         tf[2] = px1 + pr1 * 200;
336         tf[3] = py1 + pry1 * 200;
337         addStrokeWithTransform(in, 1, tf, out, 0);
338         return kg_string_new(out->str);
339 }
340
341 void DrawBox(){
342   int i, j;
343   
344   for(i = 0; i < canvasWidth; i++){
345     for(j = 0; j < canvasHeight; j++){
346       kageCanvas[j][i] = kWhite;
347     }
348   }
349 }
350
351 void CalcOptions(const KGString *in, int *mitsudo, int *flag, double *yoko, double *tate){
352     int i, j, k, l, flg;
353   int dlx1, drx1, dly1, dry1;
354   int kari, mode;
355   int tempShotai;
356   int *buf, strokes;
357   int value;
358   
359   *flag = 0;
360   
361   buf = convertStroke(in->str, buf, &strokes);
362   
363   //check left side (NEW)
364   value = 200;
365   for(i = 0; i < strokes; i++){
366     switch(buf[i * 11]){
367     case 6:
368     case 7:
369       if(buf[i * 11 + 9] < value){ value = buf[i * 11 + 9]; }
370     case 2:
371     case 12:
372     case 3:
373       if(buf[i * 11 + 7] < value){ value = buf[i * 11 + 7]; }
374     case 1:
375       if(buf[i * 11 + 5] < value){ value = buf[i * 11 + 5]; }
376       if(buf[i * 11 + 3] < value){ value = buf[i * 11 + 3]; }
377     }
378   }
379   for(i = 0; i < strokes; i++){
380     if((buf[i * 11] == 1 || buf[i * 11] == 3) && // stroke #1 and #3
381        buf[i * 11 + 3] == value &&
382        buf[i * 11 + 5] == value &&
383        (buf[i * 11 + 6] - buf[i * 11 + 4]) > pngWidth * 0.9 / 4){
384       *flag = *flag | FLAG_FLAT_LEFT;
385     }
386   }
387
388   //check right side (NEW)
389   value = 0;
390   for(i = 0; i < strokes; i++){
391     switch(buf[i * 11]){
392     case 6:
393     case 7:
394       if(buf[i * 11 + 9] > value){ value = buf[i * 11 + 9]; }
395     case 2:
396     case 12:
397     case 3:
398       if(buf[i * 11 + 7] > value){ value = buf[i * 11 + 7]; }
399     case 1:
400       if(buf[i * 11 + 5] > value){ value = buf[i * 11 + 5]; }
401       if(buf[i * 11 + 3] > value){ value = buf[i * 11 + 3]; }
402     }
403   }
404   for(i = 0; i < strokes; i++){
405     if(buf[i * 11] == 1 &&
406        buf[i * 11 + 3] == value &&
407        buf[i * 11 + 5] == value &&
408        (buf[i * 11 + 6] - buf[i * 11 + 4]) > pngWidth * 0.9 / 4){
409       *flag = *flag | FLAG_FLAT_RIGHT;
410     }
411   }
412   
413   //check upper side (NEW)
414   value = 200;
415   for(i = 0; i < strokes; i++){
416     switch(buf[i * 11]){
417     case 6:
418     case 7:
419       if(buf[i * 11 + 10] < value){ value = buf[i * 11 + 10]; }
420     case 2:
421     case 12:
422     case 3:
423       if(buf[i * 11 + 8] < value){ value = buf[i * 11 + 8]; }
424     case 1:
425       if(buf[i * 11 + 6] < value){ value = buf[i * 11 + 6]; }
426       if(buf[i * 11 + 4] < value){ value = buf[i * 11 + 4]; }
427     }
428   }
429   for(i = 0; i < strokes; i++){
430     if(buf[i * 11] == 1 &&
431        buf[i * 11 + 4] == value &&
432        buf[i * 11 + 6] == value &&
433        (buf[i * 11 + 5] - buf[i * 11 + 3]) > pngWidth * 0.9 / 4){
434       *flag = *flag | FLAG_FLAT_TOP;
435     }
436   }
437
438   //check bottom side (NEW)
439   value = 0;
440   for(i = 0; i < strokes; i++){
441     switch(buf[i * 11]){
442     case 6:
443     case 7:
444       if(buf[i * 11 + 10] > value){ value = buf[i * 11 + 10]; }
445     case 2:
446     case 12:
447     case 3:
448       if(buf[i * 11 + 8] > value){ value = buf[i * 11 + 8]; }
449     case 1:
450       if(buf[i * 11 + 6] > value){ value = buf[i * 11 + 6]; }
451       if(buf[i * 11 + 4] > value){ value = buf[i * 11 + 4]; }
452     }
453   }
454   for(i = 0; i < strokes; i++){
455     if(buf[i * 11] == 1 &&
456        buf[i * 11 + 4] == value &&
457        buf[i * 11 + 6] == value &&
458        (buf[i * 11 + 5] - buf[i * 11 + 3]) > pngWidth * 0.9 / 4){
459       *flag = *flag | FLAG_FLAT_BOTTOM;
460     }
461   }
462
463   DrawBox();
464   tempShotai = kShotai;
465   kShotai = kGothic;
466   drawGlyph(in, DRAW_GLYPH_MODE_WITHOUT_DECORATION);
467   kShotai = tempShotai;
468   DotsWidth(&dlx1, &drx1);
469   DotsHeight(&dly1, &dry1);
470   
471   //count black dots
472   *mitsudo = 0;
473   for(i = 0; i < pngHeight; i++){
474     for(j = 0; j < pngWidth; j++){
475       if(kageCanvas[i][j] != kWhite) *mitsudo += 1;
476     }
477   }
478   
479   //calculate X-axis complexity
480   *yoko = 0;
481   for(i = dly1; i <= dry1; i++){
482     mode = 0;
483     kari = 0;
484     for(j = dlx1; j <= drx1; j++){
485       if(kageCanvas[i][j] != kWhite &&
486          kageCanvas[i][j+1] != kWhite &&
487          kageCanvas[i][j+2] != kWhite){
488         if(mode == 0){
489           mode = 1;
490           kari++;
491         }
492       }
493       else if(mode == 1) mode = 0;
494     }
495     if(kari > *yoko) *yoko = kari;
496   }
497   
498   //calculate Y-axis complexity
499   *tate = 0;
500   for(i = dlx1; i <= drx1; i++){
501     mode = 0;
502     kari = 0;
503     for(j = dly1; j <= dry1; j++){
504       if(kageCanvas[j][i] != kWhite &&
505          kageCanvas[j+1][i] != kWhite &&
506          kageCanvas[j+2][i] != kWhite){
507         if(mode == 0){
508           mode = 1;
509           kari++;
510         }
511       }
512       else if(mode == 1) mode = 0;
513     }
514     if(kari > *tate) *tate = kari;
515   }
516   
517   //use user defined option if it exists
518   //buf = convertStroke(in->str, buf, &strokes);
519   for(i = 0; i < strokes; i++){
520     if(buf[i * 11 + 0] % 10 == 0){
521       if(buf[i * 11 + 1] != 0) *yoko = (double)(buf[i * 11 + 1]) * 0.1;
522       if(buf[i * 11 + 2] != 0) *tate = (double)(buf[i * 11 + 2]) * 0.1;
523       if(buf[i * 11 + 3] != 0) *flag = *flag + buf[i * 11 + 3];
524     }
525   }
526   free(buf);
527 }
528
529 void DoDrawParts(const KGString *in, const int lx1, const double rf1, const int ly1, const double rfy1){
530   int i;
531   int *buf, strokes;
532   
533   DrawBox();
534   buf = convertStroke(in->str, buf, &strokes);
535   for(i = 0; i < strokes; i++){
536     dfDrawFont(buf[i * 11 + 0],
537                buf[i * 11 + 1],
538                buf[i * 11 + 2],
539                buf[i * 11 + 3] * rf1 + lx1,
540                buf[i * 11 + 4] * rfy1 + ly1,
541                buf[i * 11 + 5] * rf1 + lx1,
542                buf[i * 11 + 6] * rfy1 + ly1,
543                buf[i * 11 + 7] * rf1 + lx1,
544                buf[i * 11 + 8] * rfy1 + ly1,
545                buf[i * 11 + 9] * rf1 + lx1,
546                buf[i * 11 + 10] * rfy1 + ly1);
547   }
548   free(buf);
549 }
550
551 void DoDrawMixFont(const KGString *in1,
552                    const int lx1,
553                    const double rf1,
554                    const KGString *in2,
555                    const int lx2,
556                    const double rf2,
557                    const int ly1,
558                    const double rfy1,
559                    const int ly2,
560                    const double rfy2){
561   int i;
562   int *buf, strokes;
563   
564   DrawBox();
565   buf = convertStroke(in1->str, buf, &strokes);
566   for(i = 0; i < strokes; i++){
567     dfDrawFont(buf[i * 11 + 0],
568                buf[i * 11 + 1],
569                buf[i * 11 + 2],
570                buf[i * 11 + 3] * rf1 + lx1,
571                buf[i * 11 + 4] * rfy1 + ly1,
572                buf[i * 11 + 5] * rf1 + lx1,
573                buf[i * 11 + 6] * rfy1 + ly1,
574                buf[i * 11 + 7] * rf1 + lx1,
575                buf[i * 11 + 8] * rfy1 + ly1,
576                buf[i * 11 + 9] * rf1 + lx1,
577                buf[i * 11 + 10] * rfy1 + ly1);
578   }
579   free(buf);
580   
581   buf = convertStroke(in2->str, buf, &strokes);
582   for(i = 0; i < strokes; i++){
583     dfDrawFont(buf[i * 11 + 0],
584                buf[i * 11 + 1],
585                buf[i * 11 + 2],
586                buf[i * 11 + 3] * rf2 + lx2,
587                buf[i * 11 + 4] * rfy2 + ly2,
588                buf[i * 11 + 5] * rf2 + lx2,
589                buf[i * 11 + 6] * rfy2 + ly2,
590                buf[i * 11 + 7] * rf2 + lx2,
591                buf[i * 11 + 8] * rfy2 + ly2,
592                buf[i * 11 + 9] * rf2 + lx2,
593                buf[i * 11 + 10] * rfy2 + ly2);
594   }
595   free(buf);
596 }
597