0f4a297cb895581e56c296b65f0a13cbe5c45f2f
[chise/kage.git] / kagecgi / kagecomb.c
1 //kagecomb.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 combineYoko2(const KGString *parts1, const KGString *parts3, int *result){\r
9         int f, g, h, i, j, k, l;\r
10         int flg_boxL, flg_boxR;\r
11         int YsideLa, YsideLb, YsideRa, YsideRb, YheightL, YnanameL, YsmallL;\r
12         int pxL, pxR, pyL, pyR;\r
13         double prL, prR, pryL, pryR, rL, rR, rTemp;\r
14         int lxL, rxL, lxR, rxR;\r
15         int dlyL, dryL, dlyR, dryR;\r
16         int chk_y1, chk_y2;\r
17         int mitsuL, mitsuR;\r
18         double yokoL, tateL, yokoR, tateR;\r
19         int *buf, strokes;\r
20         int tempShotai;\r
21         \r
22         //initialize\r
23         pxL = 0;\r
24         pyL = 0;\r
25         prL = 1.0;\r
26         pryL = 1.0;\r
27         pxR = 0;\r
28         pyR = 0;\r
29         prR = 1.0;\r
30         pryR = 1.0;\r
31         \r
32         YsideLa = 0;\r
33         YsideLb = 0;\r
34         YsideRa = 0;\r
35         YsideRb = 0;\r
36         YnanameL = 0;\r
37         YheightL = pngWidth * 0.9;\r
38         \r
39         tempShotai = kShotai;\r
40         kShotai = kGothic;\r
41         \r
42         CalcOptions(parts1, &mitsuL, &flg_boxL, &yokoL, &tateL);\r
43         CalcOptions(parts3, &mitsuR, &flg_boxR, &yokoR, &tateR);\r
44         \r
45         //left parts Y-axis processing #1\r
46         
47         //if its upper and bottom are flat\r
48         if(flg_boxL & FLAG_FLAT_TOP) YsideLa++;\r
49         if(flg_boxL & FLAG_FLAT_BOTTOM) YsideLb++;\r
50         \r
51         //if its goes right-up\r
52         j = 0;\r
53         buf = convertStroke(parts1->str, buf, &strokes);\r
54         for(i = 0; i < strokes; i++){
55                 if(buf[i * 11 + 0] / 10 == 1){
56                         j++;
57                 }
58         }\r
59         free(buf);\r
60         l = 0;\r
61         if(j != 0){\r
62                 YsideLb++;\r
63                 YnanameL++;\r
64         }
65         YheightL = YheightL - (YsideLa + YsideLb) * 2 * kWidth;\r
66         \r
67         //left parts Y-axis processing #2\r
68         YsmallL = 0;\r
69         YsmallL = 1;\r
70         if(flg_boxL & FLAG_FLAT_TOP && flg_boxL & FLAG_FLAT_BOTTOM && tateL <= 4){
71                 YheightL = (double)YheightL * (max(0.65, tateL * 0.22));
72         } else if(flg_boxL & FLAG_FLAT_BOTTOM && tateL <= 3){
73                 YheightL = (double)YheightL * 0.8;
74         } else if(YnanameL != 0 && flg_boxL & FLAG_FLAT_TOP && tateL <= 4){
75                 YheightL = (double)YheightL * (max(0.65, tateL * 0.22));
76         } else if(YnanameL != 0 && tateL <= 3){
77                 YheightL = (double)YheightL * 0.8;
78         } else{
79                 YsmallL = 0;
80         }\r
81         \r
82         //left parts Y-axis processing #3\r
83         DoDrawParts(parts1, pxL, prL, pyL, pryL);\r
84         DotsHeight(&dlyL, &dryL);\r
85         pryL = (double)YheightL / (dryL - dlyL);\r
86         \r
87         if(YsmallL != 0){\r
88                 if(flg_boxL & FLAG_FLAT_TOP){
89                         pyL = kBaseline - (double)pngWidth * 0.9 + 6 * kWidth - dlyL * pryL;
90                 } else{
91                         pyL = kBaseline - (double)pngWidth * 0.9 + 2 * kWidth - dlyL * pryL;
92                 }\r
93         } else{\r
94                 if(flg_boxL & FLAG_FLAT_BOTTOM || YnanameL != 0){
95                         pyL = kBaseline - 2 * kWidth - dryL * pryL;
96                 } else{
97                         pyL = kBaseline - dryL * pryL;
98                 }\r
99         }\r
100         \r
101         //right parts Y-axis processing #1\r
102         if(flg_boxR & FLAG_FLAT_TOP) YsideRa++;\r
103         if(flg_boxR & FLAG_FLAT_BOTTOM) YsideRb++;\r
104         \r
105         DoDrawParts(parts3, pxR, prR, pyR, pryR);\r
106         DotsHeight(&dlyR, &dryR);\r
107         \r
108         pryR = ((double)pngWidth * 0.9 - (YsideRa + YsideRb) * 2 * kWidth) / (dryR - dlyR);\r
109         pyR = kBaseline - dryR * pryR;\r
110         if(flg_boxR & FLAG_FLAT_BOTTOM){
111                 pyR = pyR - 2 * kWidth;
112         }\r
113         \r
114         //calculate ratio\r
115         rL = yokoL;\r
116         rR = yokoR;\r
117         \r
118         if(flg_boxL & FLAG_FLAT_LEFT) rL = rL * 0.7;\r
119         if(flg_boxL & FLAG_FLAT_RIGHT) rL = rL * 0.7;\r
120         if(flg_boxR & FLAG_FLAT_LEFT) rR = rR * 0.7;\r
121         if(flg_boxR & FLAG_FLAT_RIGHT) rR = rR * 0.7;\r
122         \r
123         rL = pow(rL, 0.6);\r
124         rR = pow(rR, 0.6);\r
125         \r
126         rR = rR * 1.05;\r
127         \r
128         rTemp = rL + rR;\r
129         rL = rL / rTemp;\r
130         rR = rR / rTemp;\r
131         \r
132         prL = rL;\r
133         prR = rR;\r
134         \r
135         //calculate width of each parts #1\r
136         PartsWidth(parts1, &lxL, &rxL);\r
137         PartsWidth(parts3, &lxR, &rxR);\r
138         g = 0;\r
139         \r
140         //calculate width of each parts #2\r
141         pxL = 0;\r
142         pxR = pngWidth * prL;\r
143         \r
144         DoDrawMixFont(parts1, pxL, prL, parts3, pxR, prR, pyL, pryL, pyR, pryR);\r
145         \r
146         //count dots for check crossing over\r
147         DotsHeight(&chk_y1, &chk_y2);\r
148         k = 0;\r
149         for(i = 0; i < pngWidth * 1.1; i++){\r
150                 for(j = chk_y1; j <= chk_y2; j++){\r
151                         if(kageCanvas[j][i] == 0) k++;\r
152                 }\r
153         }\r
154         l = k;\r
155         \r
156         //get close both parts\r
157         h = pxR;\r
158         while(k - l < kMixdot && g < kWidth * 2 * kKasane * 2){\r
159                 g = g + 2;\r
160                 f = pxR - g;\r
161                 DoDrawMixFont(parts1, pxL, prL, parts3, f, prR, pyL, pryL, pyR, pryR);\r
162                 
163                 //FOR DEBUG\r
164                 //char fn[256];\r
165                 //FILE *fp;\r
166                 //snprintf(fn,sizeof(fn),"%03d.png",g);\r
167                 //fp = fopen(fn, "w");\r
168                 //writePng(pngWidth, pngHeight, kageCanvas, fp);\r
169                 //fclose(fp);\r
170                 \r
171                 l = 0;\r
172                 for(i = 0; i < pngWidth * 1.1; i++){\r
173                         for(j = chk_y1; j <= chk_y2; j++){\r
174                                 if(kageCanvas[j][i] == 0) l++;\r
175                         }\r
176                 }\r
177         }\r
178         pxR = f;\r
179         
180         if(flg_boxL & FLAG_FLAT_RIGHT && flg_boxR & FLAG_FLAT_LEFT){\r
181                 if(kShotai == kMincho){
182                         pxR = pxR + kMinWidthT * 2 * kKasane * 3 / 2;\r
183                 } else {
184                         pxR = pxR + kWidth * 2 * kKasane * 3 / 2;
185                 }\r
186         } else {
187                 pxR = pxR + kWidth * 2 * kKasane * 2 / 2;
188         }\r
189         \r
190         //set results\r
191         result[0] = pxL;\r
192         result[1] = pyL;\r
193         result[2] = pxL + pngWidth * prL;\r
194         result[3] = pyL + pngWidth * pryL;\r
195         result[8] = pxR;\r
196         result[9] = pyR;\r
197         result[10] = pxR + pngWidth * prR;\r
198         result[11] = pyR + pngWidth * pryR;\r
199         \r
200         kShotai = tempShotai;\r
201 }\r
202 \r
203 void combineYoko3(const KGString *parts1, const KGString *parts2, const KGString *parts3, int *result){\r
204         //temp.
205         KGString *tempString;
206         int tempResult[8], tempResult2[4];
207         int minx, miny, maxx, maxy, width, height, width2, height2;
208         
209         tempString = kg_string_new("");
210         combineYoko2(parts2, parts3, result);
211         addStrokeWithTransform(parts2, 1, result, tempString, 1);\r
212         addStrokeWithTransform(parts3, 3, result, tempString, 1);\r
213         tempResult[0] = result[0];
214         tempResult[1] = result[1];
215         tempResult[2] = result[2];
216         tempResult[3] = result[3];
217         tempResult[4] = result[8];
218         tempResult[5] = result[9];
219         tempResult[6] = result[10];
220         tempResult[7] = result[11];
221         minx = result[0];
222         miny = min(result[1], result[9]);
223         maxx = result[10];
224         maxy = max(result[3], result[11]);
225         width = maxx - minx;
226         height = maxy - miny;
227         
228         combineYoko2(parts1, tempString, result);
229         tempResult2[0] = result[8];
230         tempResult2[1] = result[9];
231         tempResult2[2] = result[10];
232         tempResult2[3] = result[11];
233         width2 = result[10] - result[8];
234         height2 = result[11] - result[9];
235         \r
236         result[4] = tempResult2[0] + (tempResult[0] - minx) * ((double)width2 / width); // always 0
237         result[5] = tempResult2[1] + (tempResult[1] - miny) * ((double)height2 / height);
238         result[6] = tempResult2[0] + (tempResult[2] - minx) * ((double)width2 / width);
239         result[7] = tempResult2[1] + (tempResult[3] - miny) * ((double)height2 / height);
240         result[8] = tempResult2[0] + (tempResult[4] - minx) * ((double)width2 / width);
241         result[9] = tempResult2[1] + (tempResult[5] - miny) * ((double)height2 / height);
242         result[10] = tempResult2[0] + (tempResult[6] - minx) * ((double)width2 / width);
243         result[11] = tempResult2[1] + (tempResult[7] - miny) * ((double)height2 / height);
244 }\r
245 \r
246 void combineTate2(const KGString *parts1, const KGString *parts3, int *result){\r
247         int f, g, h, i, j, k, l;\r
248         int flg_boxL, flg_boxR;\r
249         int pxL, pxR, pyL, pyR;\r
250         double prL, prR, pryL, pryR, rL, rR, rTemp;\r
251         int lxL, rxL, lxR, rxR;\r
252         int lyL, ryL, lyR, ryR;\r
253         int dlxL, drxL, dlxR, drxR;\r
254         int chk_x1, chk_x2;\r
255         int mitsuL, mitsuR;\r
256         double yokoL, tateL, yokoR, tateR;\r
257         int tempShotai;\r
258         \r
259         //initialize\r
260         pxL = 0;\r
261         pyL = 0;\r
262         prL = 1.0;\r
263         pryL = 1.0;\r
264         pxR = 0;\r
265         pyR = 0;\r
266         prR = 1.0;\r
267         pryR = 1.0;\r
268         \r
269         tempShotai = kShotai;\r
270         kShotai = kGothic;\r
271         \r
272         CalcOptions(parts1, &mitsuL, &flg_boxL, &yokoL, &tateL);\r
273         CalcOptions(parts3, &mitsuR, &flg_boxR, &yokoR, &tateR);\r
274         \r
275         //calculate ratio\r
276         rL = tateL;\r
277         rR = tateR;\r
278         \r
279         if(flg_boxL & FLAG_FLAT_TOP) rL = rL * 0.7;\r
280         if(flg_boxL & FLAG_FLAT_BOTTOM) rL = rL * 0.7;\r
281         if(flg_boxR & FLAG_FLAT_TOP) rR = rR * 0.7;\r
282         if(flg_boxR & FLAG_FLAT_BOTTOM) rR = rR * 0.7;\r
283         \r
284         rL = pow(rL, 0.8);\r
285         rR = pow(rR, 0.8);\r
286         \r
287         rR = rR * 1.1;\r
288         \r
289         rTemp = rL + rR;\r
290         rL = rL / rTemp;\r
291         rR = rR / rTemp;\r
292                 \r
293         pryL = rL;\r
294         pryR = rR;\r
295         \r
296         //calucurate size of X-axis\r
297         PartsWidth(parts1, &lxL, &rxL);\r
298         PartsWidth(parts3, &lxR, &rxR);\r
299         PartsHeight(parts1, &lyL, &ryL);\r
300         PartsHeight(parts3, &lyR, &ryR);\r
301         \r
302         //left parts\r
303         if(flg_boxL & FLAG_FLAT_LEFT && flg_boxL & FLAG_FLAT_RIGHT){\r
304                 prL = min(1.0, (double)yokoL * 0.1 + 0.5) - ((kWidth * 6) / (kSize * 0.9));\r
305                 DoDrawParts(parts1, pxL, prL, pyL, pryL);\r
306                 DotsWidth(&dlxL, &drxL);\r
307                 pxL = (kSize / 2 - (dlxL + drxL) / 2);\r
308         } else if(flg_boxL & FLAG_FLAT_LEFT){\r
309                 prL = (kSize * 0.9 - kWidth * 4) / (rxL - lxL);\r
310                 pxL = kWidth * 4;\r
311         } else if(flg_boxL & FLAG_FLAT_RIGHT){\r
312                 prL = (kSize * 0.9 - kWidth * 4) / (rxL - lxL);\r
313                 pxL = (kSize * 0.05 + kWidth * 2) - lxL * prL;\r
314         }\r
315         \r
316         //right parts\r
317         if(flg_boxR & FLAG_FLAT_LEFT && flg_boxR & FLAG_FLAT_RIGHT){\r
318                 prR = min(1.0, (double)yokoR * 0.1 + 0.5) - ((kWidth * 6) / (kSize * 0.9));\r
319                 DoDrawParts(parts3, pxR, prR, pyR, pryR);\r
320                 DotsWidth(&dlxR, &drxR);\r
321                 pxR = (kSize / 2 - (dlxR + drxR) / 2);\r
322         } else if(flg_boxR & FLAG_FLAT_LEFT){\r
323                 prR = (kSize * 0.9 - kWidth * 4) / (rxR - lxR);\r
324                 pxR = (kSize * 0.05 + kWidth * 3) - lxR * prR;\r
325         } else if(flg_boxR & FLAG_FLAT_RIGHT){\r
326                 prR = (kSize * 0.9 - kWidth * 4) / (rxR - lxR);\r
327                 pxR = (kSize * 0.05 + kWidth * 1) - lxR * prR;\r
328         }\r
329         \r
330         g = 0;\r
331         \r
332         //calculate width of each parts\r
333         pyL = kWidth * 1.5 + (kSize - kWidth * 1.5 * 4) * pryL * 0.5 - (lyL + ryL) / 2 * pryL;\r
334         pyR = kWidth * 1.5 + (kSize - kWidth * 1.5 * 4) * pryL + kWidth * 1.5 * 2 + (kSize - kWidth * 1.5 * 4) * pryR * 0.5 - (lyR + ryR) / 2 * pryR;\r
335         \r
336         DoDrawMixFont(parts1, pxL, prL, parts3, pxR, prR, pyL, pryL, pyR, pryR);\r
337         \r
338         //count dots for check crossing over\r
339         DotsWidth(&chk_x1, &chk_x2);\r
340         k = 0;\r
341         for(i = 0; i < pngWidth * 1.1; i++){\r
342                 for(j = chk_x1; j <= chk_x2; j++){\r
343                         if(kageCanvas[i][j] == 0) k++;\r
344                 }\r
345         }\r
346         l = k;\r
347         \r
348         //get close both parts\r
349         h = pyR;\r
350         while(k - l < kMixdot && g < kWidth * (kKasane + 4)){\r
351                 g = g + 2;\r
352                 f = pyR - g;\r
353                 DoDrawMixFont(parts1, pxL, prL, parts3, pxR, prR, pyL, pryL, f, pryR);\r
354                 \r
355                 l = 0;\r
356                 for(i = 0; i < pngWidth * 1.1; i++){\r
357                         for(j = chk_x1; j <= chk_x2; j++){\r
358                                 if(kageCanvas[i][j] == 0) l++;\r
359                         }\r
360                 }\r
361         }\r
362         pyR = f;\r
363         if(k - l > pngWidth * 0.4){
364                 pyR = pyR + kWidth * 4;
365         } else {
366                 pyR = pyR + kWidth * 2;\r
367         }
368         \r
369         //set results\r
370         result[0] = pxL;\r
371         result[1] = pyL;\r
372         result[2] = pxL + pngWidth * prL;\r
373         result[3] = pyL + pngWidth * pryL;\r
374         result[8] = pxR;\r
375         result[9] = pyR;\r
376         result[10] = pxR + pngWidth * prR;\r
377         result[11] = pyR + pngWidth * pryR;\r
378         \r
379         kShotai = tempShotai;\r
380 }\r
381 \r
382 void combineTate3(const KGString *parts1, const KGString *parts2, const KGString *parts3, int *result){\r
383         //temp.
384         //temp.
385         KGString *tempString;
386         int tempResult[8], tempResult2[4];
387         int minx, miny, maxx, maxy, width, height, width2, height2;
388         
389         tempString = kg_string_new("");
390         combineTate2(parts2, parts3, result);
391         addStrokeWithTransform(parts2, 1, result, tempString, 1);\r
392         addStrokeWithTransform(parts3, 3, result, tempString, 1);\r
393         tempResult[0] = result[0];
394         tempResult[1] = result[1];
395         tempResult[2] = result[2];
396         tempResult[3] = result[3];
397         tempResult[4] = result[8];
398         tempResult[5] = result[9];
399         tempResult[6] = result[10];
400         tempResult[7] = result[11];
401         minx = min(result[0], result[8]);
402         miny = min(result[1], result[9]);
403         maxx = max(result[2], result[10]);
404         maxy = max(result[3], result[11]);
405         width = maxx - minx;
406         height = maxy - miny;
407         
408         combineTate2(parts1, tempString, result);
409         tempResult2[0] = result[8];
410         tempResult2[1] = result[9];
411         tempResult2[2] = result[10];
412         tempResult2[3] = result[11];
413         width2 = result[10] - result[8];
414         height2 = result[11] - result[9];
415         \r
416         result[4] = tempResult2[0] + (tempResult[0] - minx) * ((double)width2 / width); // always 0
417         result[5] = tempResult2[1] + (tempResult[1] - miny) * ((double)height2 / height);
418         result[6] = tempResult2[0] + (tempResult[2] - minx) * ((double)width2 / width);
419         result[7] = tempResult2[1] + (tempResult[3] - miny) * ((double)height2 / height);
420         result[8] = tempResult2[0] + (tempResult[4] - minx) * ((double)width2 / width);
421         result[9] = tempResult2[1] + (tempResult[5] - miny) * ((double)height2 / height);
422         result[10] = tempResult2[0] + (tempResult[6] - minx) * ((double)width2 / width);
423         result[11] = tempResult2[1] + (tempResult[7] - miny) * ((double)height2 / height);
424 }\r
425 \r
426 void combineHame2(const KGString *parts1, const KGString *parts3, int *result){\r
427         int i, flag;\r
428         int *buf, strokes;
429         double yoko, tate;
430         int mitsu, flg_box;\r
431         \r
432         flag = 0;\r
433         CalcOptions(parts3, &mitsu, &flg_box, &yoko, &tate);\r
434         \r
435         //set results\r
436         result[0] = 0;\r
437         result[1] = 0;\r
438         result[2] = 200;\r
439         result[3] = 200;\r
440         buf = convertStroke(parts1->str, buf, &strokes);\r
441         for(i = 0; i < strokes; i++){\r
442                 if(buf[i * 11 + 0] == 9){\r
443                         result[8] = buf[i * 11 + 3];
444                         if(flg_box & FLAG_FLAT_LEFT) result[8] += kWidth * 4;\r
445                         result[9] = buf[i * 11 + 4];
446                         if(flg_box & FLAG_FLAT_TOP) result[9] += kWidth * 4;\r
447                         result[10] = buf[i * 11 + 5];\r
448                         if(flg_box & FLAG_FLAT_RIGHT) result[10] -= kWidth * 4;\r
449                         result[11] = buf[i * 11 + 6];
450                         if(flg_box & FLAG_FLAT_BOTTOM) result[11] -= kWidth * 4;\r
451                         flag = 1;\r
452                 }\r
453         }\r
454         if(flag == 0){ //error\r
455                 result[8] = 50;\r
456                 result[9] = 50;\r
457                 result[10] = 150;\r
458                 result[11] = 150;\r
459         }\r
460 }\r