Fixed bug.(GET request detection)
[chise/kage.git] / kagecgi / kagetool.c
1 //kagetool.c\r
2 //\r
3 \r
4 #include "kage.h"\r
5 #include "kagecgi.h"\r
6 #include "sysdep.h"\r
7 \r
8 void DotsWidth(int *dlx, int *drx){\r
9         int i, j;\r
10         \r
11     *dlx = 0;\r
12     *drx = 0;\r
13     for(i = 0; i <= pngWidth && *dlx == 0; i++){\r
14                 for(j = 0; j <= pngHeight; j++){\r
15                         if(kageCanvas[j][i] == 0){\r
16                                 *dlx = i;\r
17                                 break;\r
18                         }\r
19                 }\r
20         }\r
21         \r
22         for(i = pngWidth; i >= 0 && *drx == 0; i--){\r
23                 for(j = 0; j <= pngHeight; j++){\r
24                         if(kageCanvas[j][i] == 0){\r
25                                 *drx = i;\r
26                                 break;\r
27                         }\r
28                 }\r
29         }\r
30 }\r
31 \r
32 void DotsHeight(int *dly, int *dry){\r
33     int i, j;\r
34         \r
35     *dly = 0;\r
36         *dry = 0;\r
37     for(j = 0; j <= pngHeight && *dly == 0; j++){\r
38         for(i = 0; i <= pngWidth; i++){\r
39             if(kageCanvas[j][i] == 0){\r
40                 *dly = j;\r
41                 break;\r
42             }\r
43         }\r
44     }\r
45         \r
46     for(j = pngHeight; j >= 0 && *dry == 0; j--){\r
47         for(i = 0; i <= pngWidth; i++){\r
48             if(kageCanvas[j][i] == 0){\r
49                 *dry = j;\r
50                 break;\r
51             }\r
52         }\r
53     }\r
54 }\r
55 \r
56 void PartsWidth(const GString *in, int *lx, int *rx){\r
57     int i;\r
58         int *buf, strokes;\r
59         \r
60         *lx = 1000; *rx = 0;\r
61         buf = convertStroke(in->str, buf, &strokes);\r
62         \r
63     for(i = 0; i < strokes; i++){\r
64         if(buf[i * 11 + 0] % 10 == 0) continue;\r
65                 \r
66         if(*lx > buf[i * 11 + 3]) *lx = buf[i * 11 + 3];\r
67                 if(*rx < buf[i * 11 + 3]) *rx = buf[i * 11 + 3];\r
68         if(*lx > buf[i * 11 + 5]) *lx = buf[i * 11 + 5];\r
69         if(*rx < buf[i * 11 + 5]) *rx = buf[i * 11 + 5];\r
70                 \r
71         if(buf[i * 11 + 0] % 10 == 2 || buf[i * 11 + 0] % 10 == 3 || buf[i * 11 + 0] % 10 == 8){\r
72                 if(*lx > buf[i * 11 + 7]) *lx = buf[i * 11 + 7];\r
73             if(*rx < buf[i * 11 + 7]) *rx = buf[i * 11 + 7];\r
74                 }\r
75         if(buf[i * 11 + 0] % 10 == 4 || buf[i * 11 + 0] % 10 == 6 || buf[i * 11 + 0] % 10 == 7){\r
76                 if(*lx > buf[i * 11 + 9]) *lx = buf[i * 11 + 9];\r
77                 if(*rx < buf[i * 11 + 9]) *rx = buf[i * 11 + 9];\r
78         }\r
79         }\r
80         free(buf);\r
81 }\r
82 \r
83 void PartsHeight(const GString *in, int *ly, int *ry){\r
84     int i;\r
85         int *buf, strokes;\r
86         \r
87         buf = convertStroke(in->str, buf, &strokes);\r
88         *ly = 1000; *ry = 0;\r
89         \r
90     for(i = 0; i < strokes; i++){\r
91         if(buf[i * 11 + 0] % 10 == 0) continue;\r
92                 \r
93         if(*ly > buf[i * 11 + 4]) *ly = buf[i * 11 + 4];\r
94                 if(*ry < buf[i * 11 + 4]) *ry = buf[i * 11 + 4];\r
95         if(*ly > buf[i * 11 + 6]) *ly = buf[i * 11 + 6];\r
96         if(*ry < buf[i * 11 + 6]) *ry = buf[i * 11 + 6];\r
97                 \r
98         if(buf[i * 11 + 0] % 10 == 2 || buf[i * 11 + 0] % 10 == 3 || buf[i * 11 + 0] % 10 == 8){\r
99                 if(*ly > buf[i * 11 + 8]) *ly = buf[i * 11 + 8];\r
100             if(*ry < buf[i * 11 + 8]) *ry = buf[i * 11 + 8];\r
101                 }\r
102         if(buf[i * 11 + 0] % 10 == 4 || buf[i * 11 + 0] % 10 == 6 || buf[i * 11 + 0] % 10 == 7){\r
103                 if(*ly > buf[i * 11 + 10]) *ly = buf[i * 11 + 10];\r
104                 if(*ry < buf[i * 11 + 10]) *ry = buf[i * 11 + 10];\r
105         }\r
106         }\r
107         free(buf);\r
108 }\r
109 \r
110 GString * CalcSizes(const GString *in, int mode){\r
111     int i, j, k, basewidth, one_lineX, one_lineY;\r
112     int dlx1, drx1, dly1, dry1;\r
113         int px1, py1;\r
114     double pr1, pry1;\r
115         \r
116     int mitsuT, flg_boxT, widthT, heightT;\r
117     double tateT, yokoT;\r
118     int cutx, cuty;\r
119         \r
120         int *buf, strokes;\r
121         int tf[12];\r
122         GString *out;\r
123         \r
124         out = g_string_new("");\r
125     basewidth = pngWidth * 0.9;\r
126         \r
127     if(mode == 0){\r
128         //temporary adjustment X-axis\r
129         PartsWidth(in, &dlx1, &drx1);\r
130         if(dlx1 == drx1){\r
131             pr1 = 1.0;\r
132             px1 = pngWidth / 2 - dlx1;\r
133             one_lineX = 1;\r
134         }\r
135         else{\r
136             pr1 = (double)basewidth/(drx1 - dlx1);\r
137             px1 = (pngWidth-basewidth)/2 - (double)(dlx1 * pr1);\r
138             one_lineX = 0;\r
139         }\r
140                 \r
141         //temporary adjustment Y-axis\r
142         PartsHeight(in, &dly1, &dry1);\r
143         if(dly1 == dry1){\r
144             pry1 = 1.0;\r
145             py1 = pngWidth / 2 - dly1;\r
146             one_lineY = 1;\r
147         }\r
148                 else{\r
149             pry1 = (double)basewidth/(dry1 - dly1);\r
150             py1 = (pngWidth-basewidth)/2 - (double)(dly1 * pry1);\r
151             one_lineY = 0;\r
152         }\r
153     }\r
154         else{\r
155         PartsWidth(in, &dlx1, &drx1);\r
156         PartsHeight(in, &dly1, &dry1);\r
157                 \r
158         cutx = 0;\r
159         cuty = 0;\r
160                 \r
161         CalcOptions(in, &mitsuT, &flg_boxT, &yokoT, &tateT);\r
162                 \r
163         widthT = basewidth;\r
164         heightT = basewidth;\r
165                 \r
166         if(flg_boxT % 2 / 1 != 0){\r
167             widthT = widthT - kWidth * 3;\r
168             cutx++;\r
169         }\r
170         if(flg_boxT % 4 / 2 != 0){\r
171             widthT = widthT - kWidth * 3;\r
172             cutx++;\r
173         }\r
174         if(flg_boxT % 8 / 4 != 0){\r
175             heightT = heightT - kWidth * 3;\r
176             cuty++;\r
177         }\r
178         if(flg_boxT % 16 / 8 != 0){\r
179             heightT = heightT - kWidth * 3;\r
180             cuty++;\r
181         }\r
182                 \r
183         //especially get small the 'mouth'\r
184         if(mode == 2 && flg_boxT % 16 == 15){\r
185             widthT = widthT - kWidth * (max(0, 16 - (int)yokoT * 4));\r
186             heightT = heightT - kWidth * (max(0, 16 - (int)tateT * 4));\r
187                 }\r
188         //'dot' as same as 'mouth'\r
189         if(mode == 2 && tateT == 1 && yokoT == 1){\r
190             widthT = pngWidth * 0.9 * 0.5;\r
191             heightT = pngWidth * 0.9 * 0.5;\r
192         }\r
193                 \r
194                 if(flg_boxT % 64 / 32 != 0){\r
195                         buf = convertStroke(in->str, buf, &strokes);\r
196                         for(i = 0; i < strokes; i++){\r
197                 if(buf[i * 11 + 0] == 0) j = buf[i * 11 + 4];// j : center line\r
198             }\r
199             free(buf);\r
200             k = max(j - dlx1, drx1 - j);// k : distance from center line\r
201             pr1 = (basewidth * 0.5) / k;\r
202                         \r
203             if(k == j - dlx1) px1 = 0;\r
204             else px1 = pngWidth * 0.5 - j * pr1;\r
205         }\r
206         else if(dlx1 == drx1){\r
207             pr1 = 1.0;\r
208             px1 = pngWidth / 2 - dlx1;\r
209         }\r
210         else{\r
211             pr1 = (double)widthT/(drx1 - dlx1);\r
212             px1 = pngWidth / 2 - (double)((dlx1 + drx1) / 2 * pr1);\r
213             if(flg_boxT % 2 / 1 != 0 && flg_boxT % 4 / 2 == 0) px1 = px1 + kWidth * 1.5;\r
214             if(flg_boxT % 2 / 1 == 0 && flg_boxT % 4 / 2 != 0) px1 = px1 - kWidth * 1.5;\r
215         }\r
216                 \r
217         if(dly1 == dry1){\r
218             pry1 = 1.0;\r
219             py1 = pngWidth / 2 - dly1;\r
220         }\r
221         else{\r
222             pry1 = (double)heightT/(dry1 - dly1);\r
223             py1 = pngWidth / 2 - (double)((dly1 + dry1) / 2 * pry1);\r
224             if(flg_boxT % 8 / 4 != 0 && flg_boxT % 16 / 8 == 0) py1 = py1 + kWidth * 1.5;\r
225             if(flg_boxT % 8 / 4 == 0 && flg_boxT % 16 / 8 != 0) py1 = py1 - kWidth * 1.5;\r
226         }\r
227         }\r
228         \r
229         //generate result\r
230         tf[0] = px1;\r
231         tf[1] = py1;\r
232         tf[2] = px1 + pr1 * 200;\r
233         tf[3] = py1 + pry1 * 200;\r
234         addStrokeWithTransform(in, 1, tf, out, 0);\r
235         return g_string_new(out->str);\r
236 }\r
237 \r
238 void DrawBox(){\r
239         int i, j;\r
240         \r
241         for(i = 0; i < canvasWidth; i++){\r
242                 for(j = 0; j < canvasHeight; j++){\r
243                         kageCanvas[j][i] = 0xFF;\r
244                 }\r
245         }\r
246 }\r
247 \r
248 void CalcOptions(const GString *in, int *mitsudo, int *flag, double *yoko, double *tate){\r
249     int i, j, k, l, flg;\r
250     int dlx1, drx1, dly1, dry1;\r
251     int kari, mode;\r
252         int tempShotai;\r
253         int *buf, strokes;\r
254         \r
255     *flag = 0;\r
256         \r
257     DrawBox();\r
258     tempShotai = kShotai;\r
259     kShotai = kGothic;\r
260     drawGlyph(in, 1);\r
261     kShotai = tempShotai;\r
262     DotsWidth(&dlx1, &drx1);\r
263     DotsHeight(&dly1, &dry1);\r
264         \r
265         //check left side\r
266     k = 0;\r
267     l = 0;\r
268     for(i = 0; i < pngWidth; i++){\r
269         flg = 0;\r
270         for(j = 0; j < kWidth; j++){\r
271             if(kageCanvas[i][dlx1 + j] == 0) flg = 1;\r
272         }\r
273         if(flg == 1){\r
274                 k++;\r
275         }\r
276         else{\r
277             if(k > l) l = k;\r
278             k = 0;\r
279         }\r
280     }\r
281     if(k > l) l = k;\r
282     \r
283     if(l > pngWidth * 0.9 / 4) *flag = *flag | 1;\r
284         \r
285     //check right side\r
286     k = 0;\r
287     l = 0;\r
288     for(i = 0; i < pngWidth; i++){\r
289         flg = 0;\r
290         for(j = 0; j < kWidth; j++){\r
291             if(kageCanvas[i][drx1 - j] == 0) flg = 1;\r
292         }\r
293         if(flg == 1) k++;\r
294         else{\r
295             if(k > l) l = k;\r
296             k = 0;\r
297         }\r
298     }\r
299     if(k > l) l = k;\r
300         \r
301     if(l > pngWidth * 0.9 / 4) *flag = *flag | 2;\r
302         \r
303     //check upper side\r
304     k = 0;\r
305     l = 0;\r
306     for(i = 0; i < pngWidth; i++){\r
307         flg = 0;\r
308                 for(j = 0; j < kWidth; j++){\r
309             if(kageCanvas[dly1 + j][i] == 0) flg = 1;\r
310         }\r
311         if(flg == 1) k++;\r
312         else{\r
313             if(k > l) l = k;\r
314             k = 0;\r
315         }\r
316     }\r
317     if(k > l) l = k;\r
318         \r
319     if(l > pngWidth * 0.9 / 4) *flag = *flag | 4;\r
320         \r
321     //check bottom side\r
322     k = 0;\r
323     l = 0;\r
324     for(i = 0; i < pngWidth; i++){\r
325         flg = 0;\r
326         for(j = 0; j < kWidth; j++){\r
327             if(kageCanvas[dry1 - j][i] == 0) flg = 1;\r
328         }\r
329         if(flg == 1) k++;\r
330         else{\r
331             if(k > l) l = k;\r
332             k = 0;\r
333         }\r
334     }\r
335     if(k > l) l = k;\r
336         \r
337     if(l > pngWidth * 0.9 / 4) *flag = *flag | 8;\r
338         \r
339     //count black dots\r
340     *mitsudo = 0;\r
341     for(i = 0; i < pngHeight; i++){\r
342         for(j = 0; j < pngWidth; j++){\r
343             if(kageCanvas[i][j] == 0) *mitsudo += 1;\r
344         }\r
345     }\r
346         \r
347     //calculate X-axis complexity\r
348     *yoko = 0;\r
349     for(i = dly1; i <= dry1; i++){\r
350         mode = 0;\r
351         kari = 0;\r
352         for(j = dlx1; j <= drx1; j++){\r
353                         if(kageCanvas[i][j] == 0 &&\r
354              kageCanvas[i][j+1] == 0 &&\r
355              kageCanvas[i][j+2] == 0){\r
356                 if(mode == 0){\r
357                     mode = 1;\r
358                     kari++;\r
359                 }\r
360             }\r
361             else if(mode == 1) mode = 0;\r
362         }\r
363         if(kari > *yoko) *yoko = kari;\r
364     }\r
365         \r
366     //calculate Y-axis complexity\r
367     *tate = 0;\r
368     for(i = dlx1; i <= drx1; i++){\r
369         mode = 0;\r
370         kari = 0;\r
371         for(j = dly1; j <= dry1; j++){\r
372             if(kageCanvas[j][i] == 0 &&\r
373              kageCanvas[j+1][i] == 0 &&\r
374              kageCanvas[j+2][i] == 0){\r
375                 if(mode == 0){\r
376                     mode = 1;\r
377                     kari++;\r
378                 }\r
379             }\r
380             else if(mode == 1) mode = 0;\r
381         }\r
382         if(kari > *tate) *tate = kari;\r
383     }\r
384         \r
385     //use user defined option if it exists\r
386         buf = convertStroke(in->str, buf, &strokes);\r
387         for(i = 0; i < strokes; i++){\r
388         if(buf[i * 11 + 0] % 10 == 0){\r
389             if(buf[i * 11 + 1] != 0) *yoko = (double)(buf[i * 11 + 1]) * 0.1;\r
390             if(buf[i * 11 + 2] != 0) *tate = (double)(buf[i * 11 + 2]) * 0.1;\r
391             if(buf[i * 11 + 3] != 0) *flag = *flag + buf[i * 11 + 3] * 16;\r
392         }\r
393     }\r
394     free(buf);\r
395 }\r
396 \r
397 void DoDrawParts(const GString *in, const int lx1, const double rf1, const int ly1, const double rfy1){\r
398     int i;\r
399         int *buf, strokes;\r
400         \r
401     DrawBox();\r
402         buf = convertStroke(in->str, buf, &strokes);\r
403         for(i = 0; i < strokes; i++){\r
404                 dfDrawFont(buf[i * 11 + 0],\r
405                  buf[i * 11 + 1],\r
406                  buf[i * 11 + 2],\r
407                  buf[i * 11 + 3] * rf1 + lx1,\r
408                  buf[i * 11 + 4] * rfy1 + ly1,\r
409                  buf[i * 11 + 5] * rf1 + lx1,\r
410                  buf[i * 11 + 6] * rfy1 + ly1,\r
411                  buf[i * 11 + 7] * rf1 + lx1,\r
412                  buf[i * 11 + 8] * rfy1 + ly1,\r
413                  buf[i * 11 + 9] * rf1 + lx1,\r
414                  buf[i * 11 + 10] * rfy1 + ly1);\r
415     }\r
416         free(buf);\r
417 }\r
418 \r
419 void DoDrawMixFont(const GString *in1,\r
420  const int lx1,\r
421  const double rf1,\r
422  const GString *in2,\r
423  const int lx2,\r
424  const double rf2,\r
425  const int ly1,\r
426  const double rfy1,\r
427  const int ly2,\r
428  const double rfy2){\r
429     int i;\r
430         int *buf, strokes;\r
431         \r
432         DrawBox();\r
433         buf = convertStroke(in1->str, buf, &strokes);\r
434         for(i = 0; i < strokes; i++){\r
435                 dfDrawFont(buf[i * 11 + 0],\r
436                  buf[i * 11 + 1],\r
437                  buf[i * 11 + 2],\r
438                  buf[i * 11 + 3] * rf1 + lx1,\r
439                  buf[i * 11 + 4] * rfy1 + ly1,\r
440                  buf[i * 11 + 5] * rf1 + lx1,\r
441                  buf[i * 11 + 6] * rfy1 + ly1,\r
442                  buf[i * 11 + 7] * rf1 + lx1,\r
443                  buf[i * 11 + 8] * rfy1 + ly1,\r
444                  buf[i * 11 + 9] * rf1 + lx1,\r
445                  buf[i * 11 + 10] * rfy1 + ly1);\r
446     }\r
447         free(buf);\r
448         \r
449         buf = convertStroke(in2->str, buf, &strokes);\r
450         for(i = 0; i < strokes; i++){\r
451                 dfDrawFont(buf[i * 11 + 0],\r
452                  buf[i * 11 + 1],\r
453                  buf[i * 11 + 2],\r
454                  buf[i * 11 + 3] * rf2 + lx2,\r
455                  buf[i * 11 + 4] * rfy2 + ly2,\r
456                  buf[i * 11 + 5] * rf2 + lx2,\r
457                  buf[i * 11 + 6] * rfy2 + ly2,\r
458                  buf[i * 11 + 7] * rf2 + lx2,\r
459                  buf[i * 11 + 8] * rfy2 + ly2,\r
460                  buf[i * 11 + 9] * rf2 + lx2,\r
461                  buf[i * 11 + 10] * rfy2 + ly2);\r
462     }\r
463         free(buf);\r
464 }\r
465 \r