remove engine and glyphwiki from repogitry.
[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] != kWhite) 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] != kWhite) l++;
403       }
404     }
405   }
406   pyR = f;
407 /*
408   if(k - l > pngWidth * 0.4){
409     pyR = pyR + kWidth * 4;
410   } else {
411     pyR = pyR + kWidth * 2;
412   }
413 */
414   if(flg_boxL & FLAG_FLAT_BOTTOM && flg_boxR & FLAG_FLAT_TOP){
415     pyR = pyR + kWidth * 4;
416   } else if(k - l > pngWidth * 0.4){
417     pyR = pyR + kWidth * 2;
418   } else {
419     pyR = pyR + kWidth;
420   }
421   
422   //set results
423   result[0] = pxL;
424   result[1] = pyL;
425   result[2] = pxL + pngWidth * prL;
426   result[3] = pyL + pngWidth * pryL;
427   result[8] = pxR;
428   result[9] = pyR;
429   result[10] = pxR + pngWidth * prR;
430   result[11] = pyR + pngWidth * pryR;
431   
432   kShotai = tempShotai;
433 }
434
435 void combineTate3(const KGString *parts1, const KGString *parts2, const KGString *parts3, int *result){
436   //temp.
437   KGString *tempString;
438   int tempResult[8], tempResult2[4];
439   int minx, miny, maxx, maxy, width, height, width2, height2;
440   
441   tempString = kg_string_new("");
442   combineTate2(parts2, parts3, result);
443   addStrokeWithTransform(parts2, 1, result, tempString, 1);
444   addStrokeWithTransform(parts3, 3, result, tempString, 1);
445   tempResult[0] = result[0];
446   tempResult[1] = result[1];
447   tempResult[2] = result[2];
448   tempResult[3] = result[3];
449   tempResult[4] = result[8];
450   tempResult[5] = result[9];
451   tempResult[6] = result[10];
452   tempResult[7] = result[11];
453   minx = min(result[0], result[8]);
454   miny = min(result[1], result[9]);
455   maxx = max(result[2], result[10]);
456   maxy = max(result[3], result[11]);
457   width = maxx - minx;
458   height = maxy - miny;
459   
460   combineTate2(parts1, tempString, result);
461   tempResult2[0] = result[8];
462   tempResult2[1] = result[9];
463   tempResult2[2] = result[10];
464   tempResult2[3] = result[11];
465   width2 = result[10] - result[8];
466   height2 = result[11] - result[9];
467   
468   result[4] = tempResult2[0] + (tempResult[0] - minx) * ((double)width2 / width); // always 0
469   result[5] = tempResult2[1] + (tempResult[1] - miny) * ((double)height2 / height);
470   result[6] = tempResult2[0] + (tempResult[2] - minx) * ((double)width2 / width);
471   result[7] = tempResult2[1] + (tempResult[3] - miny) * ((double)height2 / height);
472   result[8] = tempResult2[0] + (tempResult[4] - minx) * ((double)width2 / width);
473   result[9] = tempResult2[1] + (tempResult[5] - miny) * ((double)height2 / height);
474   result[10] = tempResult2[0] + (tempResult[6] - minx) * ((double)width2 / width);
475   result[11] = tempResult2[1] + (tempResult[7] - miny) * ((double)height2 / height);
476 }
477
478 void adjust(int *x, int *y, int x1, int y1, int x2, int y2, double ratio){
479   if(*x <= x1){
480     *x = 0 + *x * ratio;
481   } else if(x2 <= *x){
482     *x = pngWidth - (pngWidth - *x) * ratio;
483   }
484   if(*y <= y1){
485     *y = 0 + *y * ratio;
486   } else if(y2 <= *y){
487     *y = pngHeight - (pngHeight - *y) * ratio;
488   }
489 }
490
491 void combineHame2(KGString *parts1, KGString *parts3, int *result, int surround){
492   int i, flag;
493   int *buf, strokes;
494   double yoko, tate;
495   int mitsu, flg_box;
496   int x1, x2, y1, y2;
497   double ratio;
498   KGString *temp;
499   
500   CalcOptions(parts3, &mitsu, &flg_box, &yoko, &tate);
501   
502   if(yoko * tate > 12){
503     ratio = sqrt(12 / (yoko * tate));
504     temp = kg_string_new("");
505     buf = convertStroke(parts1->str, buf, &strokes);
506     for(i = 0; i < strokes; i++){
507       if(buf[i * 11] == 9){
508         x1 = buf[i * 11 + 3];
509         y1 = buf[i * 11 + 4];
510         x2 = buf[i * 11 + 5];
511         y2 = buf[i * 11 + 6];
512         i = strokes;
513       }
514     }
515     for(i = 0; i <strokes; i++){
516       switch(buf[i * 11]){
517       case 6:
518       case 7:
519         adjust(&buf[i * 11 + 9], &buf[i * 11 + 10], x1,y1,x2,y2, ratio);
520       case 2:
521       case 12:
522       case 3:
523         adjust(&buf[i * 11 + 7], &buf[i * 11 + 8], x1,y1,x2,y2, ratio);
524       case 1:
525       case 9:
526       case 8:
527       case 99:
528         adjust(&buf[i * 11 + 5], &buf[i * 11 + 6], x1,y1,x2,y2, ratio);
529         adjust(&buf[i * 11 + 3], &buf[i * 11 + 4], x1,y1,x2,y2, ratio);
530       }
531     }
532     convertArray(buf, temp, strokes, 0);
533     kg_string_assign(parts1, temp->str);
534   }
535   
536   flag = 0;
537   
538   //set results
539   result[0] = 0;
540   result[1] = 0;
541   result[2] = 200;
542   result[3] = 200;
543   buf = convertStroke(parts1->str, buf, &strokes);
544   for(i = 0; i < strokes; i++){
545     if(buf[i * 11 + 0] == 9){
546       result[8] = buf[i * 11 + 3];
547       if(flg_box & FLAG_FLAT_LEFT){
548         if(surround & FLAG_SURROUND_LEFT){
549           result[8] += kWidth * 4;
550         } else {
551           result[8] += kWidth * 2;
552         }
553       }
554       result[9] = buf[i * 11 + 4];
555       if(flg_box & FLAG_FLAT_TOP){
556         if(surround & FLAG_SURROUND_TOP){
557           result[9] += kWidth * 4;
558         } else {
559           result[9] += kWidth * 2;
560         }
561       }
562       result[10] = buf[i * 11 + 5];
563       if(flg_box & FLAG_FLAT_RIGHT){
564         if(surround & FLAG_SURROUND_RIGHT){
565           result[10] -= kWidth * 4;
566         } else {
567           result[10] -= kWidth * 2;
568         }
569       }
570       result[11] = buf[i * 11 + 6];
571       if(flg_box & FLAG_FLAT_BOTTOM){
572         if(surround & FLAG_SURROUND_BOTTOM){
573           result[11] -= kWidth * 4;
574         } else {
575           result[11] -= kWidth * 2;
576         }
577       }
578       flag = 1;
579     }
580   }
581   if(flag == 0){ //error
582     result[8] = 50;
583     result[9] = 50;
584     result[10] = 150;
585     result[11] = 150;
586   }
587 }