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