Add error processing for combine(U+2ffa).
[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 Xside, 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     //if its upper and bottom are flat\r
47     if(flg_boxL % 8 / 4 != 0) YsideLa++;\r
48     if(flg_boxL % 16 / 8 != 0) YsideLb++;\r
49         \r
50     //if its goes right-up\r
51         if(flg_boxL % 1024 / 512 == 0){\r
52             j = 0;\r
53                 buf = convertStroke(parts1->str, buf, &strokes);\r
54                 for(i = 0; i < strokes; i++) if(buf[i * 11 + 0] / 10 == 1) j++;\r
55             free(buf);\r
56             l = 0;\r
57             if(j != 0){\r
58                         YsideLb++;\r
59                 YnanameL++;\r
60                 }\r
61         }\r
62     YheightL = YheightL - (YsideLa + YsideLb) * 2 * kWidth;\r
63         \r
64         //left parts Y-axis processing #2\r
65     YsmallL = 0;\r
66         if(flg_boxL % 1024 / 512 == 0){\r
67                 YsmallL = 1;\r
68             if(flg_boxL % 16 / 8 != 0 && flg_boxL % 8 / 4 != 0 && tateL <= 4) YheightL = (double)YheightL * (max(0.65, tateL * 0.22));\r
69                 else if(flg_boxL % 16 / 8 != 0 && tateL <= 3) YheightL = (double)YheightL * 0.8;\r
70         else if(YnanameL != 0 && flg_boxL % 8 / 4 != 0 && tateL <= 4) YheightL = (double)YheightL * (max(0.65, tateL * 0.22));\r
71             else if(YnanameL != 0 && tateL <= 3) YheightL = (double)YheightL * 0.8;\r
72             else YsmallL = 0;\r
73         }\r
74         \r
75         //left parts Y-axis processing #3\r
76     DoDrawParts(parts1, pxL, prL, pyL, pryL);\r
77     DotsHeight(&dlyL, &dryL);\r
78     pryL = (double)YheightL / (dryL - dlyL);\r
79         \r
80     if(YsmallL != 0){\r
81         if(flg_boxL % 8 / 4 != 0) pyL = kBaseline - (double)pngWidth * 0.9 + 6 * kWidth - dlyL * pryL;\r
82         else pyL = kBaseline - (double)pngWidth * 0.9 + 2 * kWidth - dlyL * pryL;\r
83     }\r
84     else{\r
85         if(flg_boxL % 16 / 8 != 0 || YnanameL != 0) pyL = kBaseline - 2 * kWidth - dryL * pryL;\r
86         else pyL = kBaseline - dryL * pryL;\r
87     }\r
88         \r
89         //right parts Y-axis processing #1\r
90     if(flg_boxR % 8 / 4 != 0) YsideRa++;\r
91     if(flg_boxR % 16 / 8 != 0) YsideRb++;\r
92         \r
93     DoDrawParts(parts3, pxR, prR, pyR, pryR);\r
94         DotsHeight(&dlyR, &dryR);\r
95         \r
96         if(flg_boxR % 512 / 256 != 0 && flg_boxR % 1024 / 512 == 0){\r
97                 pryR = pngWidth * 0.9 * 0.8 / (dryR - dlyR);\r
98                 pyR = kBaseline - pngWidth * 0.9 + 6 * kWidth - dlyR * pryR;\r
99         }\r
100         else{\r
101                 pryR = ((double)pngWidth * 0.9 - (YsideRa + YsideRb) * 2 * kWidth) / (dryR - dlyR);\r
102                 pyR = kBaseline - dryR * pryR;\r
103                 if(flg_boxR % 16 / 8 != 0) pyR = pyR - 2 * kWidth;\r
104         }\r
105         \r
106         //calculate ratio\r
107         rL = yokoL;\r
108         rR = yokoR;\r
109         \r
110         if(flg_boxL % 2 / 1 != 0) rL = rL * 0.7;\r
111         if(flg_boxL % 4 / 2 != 0) rL = rL * 0.7;\r
112         if(flg_boxR % 2 / 1 != 0) rR = rR * 0.7;\r
113         if(flg_boxR % 4 / 2 != 0) rR = rR * 0.7;\r
114         \r
115         rL = pow(rL, 0.6);\r
116         rR = pow(rR, 0.6);\r
117         \r
118         rR = rR * 1.05;\r
119         \r
120         rTemp = rL + rR;\r
121         rL = rL / rTemp;\r
122         rR = rR / rTemp;\r
123         \r
124 //    if(r < 0.3) r = 0.3;\r
125 //    else if(r > 0.7) r = 0.7;\r
126         \r
127     prL = rL;\r
128     prR = rR;\r
129         \r
130         //calculate width of each parts #1\r
131         Xside = 0;\r
132     if(flg_boxL % 2 / 1 != 0) Xside++;\r
133     if(flg_boxR % 4 / 2 != 0) Xside++;\r
134         \r
135 //    DrawBox();\r
136 //    drawGlyph(parts1, 1);\r
137 //    DotsWidth(&lxL, &rxL);\r
138 //    DrawBox();\r
139 //    drawGlyph(parts3, 1);\r
140 //    DotsWidth(&lxR, &rxR);\r
141     PartsWidth(parts1, &lxL, &rxL);\r
142     PartsWidth(parts3, &lxR, &rxR);\r
143     g = 0;\r
144         \r
145         //calculate width of each parts #2\r
146 //    pxL = kWidth * 2 + (pngWidth - kWidth * 2 * 2) * prL * 0.5 - (lxL + rxL) / 2 * prL;\r
147 //    pxR = kWidth * 2 + (pngWidth - kWidth * 2 * 2) * prL + kWidth * 2 * 2 + (pngWidth - kWidth * 2 * 2) * prR * 0.5 - (lxR + rxR) / 2 * prR;\r
148     pxL = pngWidth * prL * 0.5 - (lxL + rxL) / 2 * prL;\r
149     pxR = pngWidth * prL + kWidth * 4 + pngWidth * prR * 0.5 - (lxR + rxR) / 2 * prR;\r
150         \r
151     DoDrawMixFont(parts1, pxL, prL, parts3, pxR, prR, pyL, pryL, pyR, pryR);\r
152         \r
153         //count dots for check crossing over\r
154         DotsHeight(&chk_y1, &chk_y2);\r
155         k = 0;\r
156         for(i = 0; i < pngWidth * 1.1; i++){\r
157                 for(j = chk_y1; j <= chk_y2; j++){\r
158                         if(kageCanvas[j][i] == 0) k++;\r
159                 }\r
160         }\r
161         l = k;\r
162         \r
163         //get close both parts\r
164         h = pxR;\r
165         while(k - l < kMixdot && g < kWidth * (kKasane + 4)){\r
166                 g = g + 2;\r
167                 f = pxR - g;\r
168         DoDrawMixFont(parts1, pxL, prL, parts3, f, prR, pyL, pryL, pyR, pryR);\r
169                 \r
170         l = 0;\r
171         for(i = 0; i < pngWidth * 1.1; i++){\r
172             for(j = chk_y1; j <= chk_y2; j++){\r
173                 if(kageCanvas[j][i] == 0) l++;\r
174             }\r
175         }\r
176     }\r
177     pxR = f;\r
178     if(flg_boxR % 256 / 128 != 0) pxR = pxR + kWidth * 12;\r
179     if(flg_boxR % 64 / 32 != 0) pxR = pxR + kWidth * 8;\r
180     else if(k - l > pngWidth * 0.4) pxR = pxR + kWidth * 5;\r
181     else pxR = pxR + kWidth * 3;\r
182         \r
183         //set results\r
184         result[0] = pxL;\r
185         result[1] = pyL;\r
186         result[2] = pxL + pngWidth * prL;\r
187         result[3] = pyL + pngWidth * pryL;\r
188         result[8] = pxR;\r
189         result[9] = pyR;\r
190         result[10] = pxR + pngWidth * prR;\r
191         result[11] = pyR + pngWidth * pryR;\r
192         \r
193         kShotai = tempShotai;\r
194 }\r
195 \r
196 void combineYoko3(const KGString *parts1, const KGString *parts2, const KGString *parts3, int *result){\r
197         //not yet\r
198 }\r
199 \r
200 void combineTate2(const KGString *parts1, const KGString *parts3, int *result){\r
201     int f, g, h, i, j, k, l;\r
202     int flg_boxL, flg_boxR;\r
203     int pxL, pxR, pyL, pyR;\r
204     double prL, prR, pryL, pryR, rL, rR, rTemp;\r
205     int lxL, rxL, lxR, rxR;\r
206     int lyL, ryL, lyR, ryR;\r
207     int dlxL, drxL, dlxR, drxR;\r
208     int chk_x1, chk_x2;\r
209     int mitsuL, mitsuR;\r
210     double yokoL, tateL, yokoR, tateR;\r
211         int *buf, strokes;\r
212         int tempShotai;\r
213         \r
214         //initialize\r
215     pxL = 0;\r
216     pyL = 0;\r
217     prL = 1.0;\r
218     pryL = 1.0;\r
219     pxR = 0;\r
220     pyR = 0;\r
221     prR = 1.0;\r
222     pryR = 1.0;\r
223         \r
224         tempShotai = kShotai;\r
225         kShotai = kGothic;\r
226         \r
227     CalcOptions(parts1, &mitsuL, &flg_boxL, &yokoL, &tateL);\r
228     CalcOptions(parts3, &mitsuR, &flg_boxR, &yokoR, &tateR);\r
229         \r
230         //calculate ratio\r
231         rL = tateL;\r
232         rR = tateR;\r
233         \r
234         if(flg_boxL % 8 / 4 != 0) rL = rL * 0.7;\r
235         if(flg_boxL % 16 / 8 != 0) rL = rL * 0.7;\r
236         if(flg_boxR % 8 / 4 != 0) rR = rR * 0.7;\r
237         if(flg_boxR % 16 / 8 != 0) rR = rR * 0.7;\r
238         \r
239         rL = pow(rL, 0.8);\r
240         rR = pow(rR, 0.8);\r
241         \r
242         rR = rR * 1.1;\r
243         \r
244         rTemp = rL + rR;\r
245         rL = rL / rTemp;\r
246         rR = rR / rTemp;\r
247         \r
248 //    if(r < 0.3) r = 0.3;\r
249 //    else if(r > 0.7) r = 0.7;\r
250         \r
251     pryL = rL;\r
252     pryR = rR;\r
253         \r
254         //calucurate size of X-axis\r
255     PartsWidth(parts1, &lxL, &rxL);\r
256     PartsWidth(parts3, &lxR, &rxR);\r
257     PartsHeight(parts1, &lyL, &ryL);\r
258     PartsHeight(parts3, &lyR, &ryR);\r
259         \r
260         //left parts\r
261     if(flg_boxL % 64 / 32 != 0){\r
262                 buf = convertStroke(parts1->str, buf, &strokes);\r
263                 for(i = 0; i < strokes; i++){\r
264                         if(buf[i * 11 + 0] == 0) j = buf[i * 11 + 4]; // center line\r
265         }\r
266         k = max(j - lxL, rxL - j);// k : distance from center line\r
267         prL = (kSize * 0.9 * 0.5) / k;\r
268         if(k == j - lxL) pxL = 0;\r
269         else pxL = kSize * 0.5 - j * prL;\r
270     }\r
271     else if(flg_boxL % 2 / 1 != 0 && flg_boxL % 4 / 2 != 0 && flg_boxL % 32 / 16 == 0){\r
272         prL = min(1.0, (double)yokoL * 0.1 + 0.5) - ((kWidth * 6) / (kSize * 0.9));\r
273         DoDrawParts(parts1, pxL, prL, pyL, pryL);\r
274         DotsWidth(&dlxL, &drxL);\r
275         pxL = (kSize / 2 - (dlxL + drxL) / 2);\r
276     }\r
277     else if(flg_boxL % 128 / 64 != 0){\r
278         prL = 0.77;\r
279         DoDrawParts(parts1, pxL, prL, pyL, pryL);\r
280         DotsWidth(&dlxL, &drxL);\r
281         pxL = (kSize / 2 - (dlxL + drxL) / 2);\r
282     }\r
283     else if(flg_boxL % 2 / 1 != 0 && flg_boxL % 32 / 16 == 0){\r
284         prL = (kSize * 0.9 - kWidth * 4) / (rxL - lxL);\r
285                 pxL = kWidth * 4;\r
286     }\r
287     else if(flg_boxL % 4 / 2 != 0 && flg_boxL % 32 / 16 == 0){\r
288         prL = (kSize * 0.9 - kWidth * 4) / (rxL - lxL);\r
289         pxL = (kSize*0.05+kWidth*2) - lxL * prL;\r
290     }\r
291         \r
292         //right parts\r
293     if(flg_boxR % 64 / 32 != 0){\r
294                 buf = convertStroke(parts3->str, buf, &strokes);\r
295                 for(i = 0; i < strokes; i++){\r
296                         if(buf[i * 11 + 0] == 0) j = buf[i * 11 + 4]; // center line\r
297         }\r
298         k = max(j - lxR, rxR - j);// k : distance from center line\r
299         prR = (kSize * 0.9 * 0.5) / k;\r
300         if(k == j - lxR) pxR = 0;\r
301                 else pxR = kSize * 0.5 - j * prR;\r
302         }\r
303         else if(flg_boxR % 2 / 1 != 0 && flg_boxR % 4 / 2 != 0 && flg_boxR % 32 / 16 == 0){\r
304                 prR = min(1.0, (double)yokoR * 0.1 + 0.5) - ((kWidth * 6) / (kSize * 0.9));\r
305                 DoDrawParts(parts3, pxR, prR, pyR, pryR);\r
306                 DotsWidth(&dlxR, &drxR);\r
307                 pxR = (kSize / 2 - (dlxR + drxR) / 2);\r
308         }\r
309         else if(flg_boxR % 128 / 64 != 0){\r
310                 prR = 0.77;\r
311                 DoDrawParts(parts3, pxR, prR, pyR, pryR);\r
312                 DotsWidth(&dlxR, &drxR);\r
313                 pxR = (kSize / 2 - (dlxR + drxR) / 2);\r
314         }\r
315         else if(flg_boxR % 2 / 1 != 0 && flg_boxR % 32 / 16 == 0){\r
316                 prR = (kSize * 0.9 - kWidth * 4) / (rxR - lxR);\r
317 //            pxR = width * 4;\r
318                 pxR = (kSize*0.05+kWidth*3) - lxR * prR;\r
319         }\r
320         else if(flg_boxR % 4 / 2 != 0 && flg_boxR % 32 / 16 == 0){\r
321                 prR = (kSize * 0.9 - kWidth * 4) / (rxR - lxR);\r
322 //            pxR = (size*0.05+width*2) - lxR * prR;\r
323                 pxR = (kSize*0.05+kWidth*1) - lxR * prR;\r
324         }\r
325         \r
326         g = 0;\r
327         \r
328         //calculate width of each parts\r
329         pyL = kWidth * 1.5 + (kSize - kWidth * 1.5 * 4) * pryL * 0.5 - (lyL + ryL) / 2 * pryL;\r
330         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
331         \r
332         DoDrawMixFont(parts1, pxL, prL, parts3, pxR, prR, pyL, pryL, pyR, pryR);\r
333         \r
334         //count dots for check crossing over\r
335         DotsWidth(&chk_x1, &chk_x2);\r
336         k = 0;\r
337         for(i = 0; i < pngWidth * 1.1; i++){\r
338                 for(j = chk_x1; j <= chk_x2; j++){\r
339                         if(kageCanvas[i][j] == 0) k++;\r
340                 }\r
341         }\r
342         l = k;\r
343         \r
344         //get close both parts\r
345         h = pyR;\r
346         while(k - l < kMixdot && g < kWidth * (kKasane + 4)){\r
347                 g = g + 2;\r
348                 f = pyR - g;\r
349         DoDrawMixFont(parts1, pxL, prL, parts3, pxR, prR, pyL, pryL, f, pryR);\r
350                 \r
351         l = 0;\r
352         for(i = 0; i < pngWidth * 1.1; i++){\r
353             for(j = chk_x1; j <= chk_x2; j++){\r
354                 if(kageCanvas[i][j] == 0) l++;\r
355             }\r
356         }\r
357     }\r
358     pyR = f;\r
359     if(k - l > pngWidth * 0.4) pyR = pyR + kWidth * 5;\r
360     else pyR = pyR + kWidth * 3;\r
361         \r
362         //set results\r
363         result[0] = pxL;\r
364         result[1] = pyL;\r
365         result[2] = pxL + pngWidth * prL;\r
366         result[3] = pyL + pngWidth * pryL;\r
367         result[8] = pxR;\r
368         result[9] = pyR;\r
369         result[10] = pxR + pngWidth * prR;\r
370         result[11] = pyR + pngWidth * pryR;\r
371         \r
372         kShotai = tempShotai;\r
373 }\r
374 \r
375 void combineTate3(const KGString *parts1, const KGString *parts2, const KGString *parts3, int *result){\r
376   //not yet\r
377 }\r
378 \r
379 void combineHame2(const KGString *parts1, const KGString *parts3, int *result){\r
380   int i, flag;\r
381   int *buf, strokes;\r
382 \r
383   flag = 0;\r
384 \r
385   //set results\r
386   result[0] = 0;\r
387   result[1] = 0;\r
388   result[2] = 200;\r
389   result[3] = 200;\r
390   buf = convertStroke(parts1->str, buf, &strokes);\r
391   for(i = 0; i < strokes; i++){\r
392     if(buf[i * 11 + 0] == 9){\r
393       result[8] = buf[i * 11 + 3];\r
394       result[9] = buf[i * 11 + 4];\r
395       result[10] = buf[i * 11 + 5];\r
396       result[11] = buf[i * 11 + 6];\r
397     }\r
398   }\r
399   if(flag == 0){ //error\r
400     result[8] = 50;\r
401     result[9] = 50;\r
402     result[10] = 150;\r
403     result[11] = 150;\r
404   }\r
405   //not yet\r
406 }\r