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;
18 double yokoL, tateL, yokoR, tateR;
21 int bodyline1[pngWidth], bodyline2[pngWidth];
40 YheightL = pngWidth * 0.9;
45 CalcOptions(parts1, &mitsuL, &flg_boxL, &yokoL, &tateL);
46 CalcOptions(parts3, &mitsuR, &flg_boxR, &yokoR, &tateR);
48 //get thin when the left parts is radical
49 if(flg_boxL & FLAG_RADICAL_LEFT) yokoL = yokoL / 2;
51 //left parts Y-axis processing #1
53 //if its upper and bottom are flat
54 if(flg_boxL & FLAG_FLAT_TOP) YsideLa++;
55 if(flg_boxL & FLAG_FLAT_BOTTOM) YsideLb++;
57 //if its goes right-up
59 buf = convertStroke(parts1->str, buf, &strokes);
60 for(i = 0; i < strokes; i++){
61 if(buf[i * 11 + 0] / 10 == 1){
71 YheightL = YheightL - (YsideLa + YsideLb) * 2 * kWidth;
73 //left parts Y-axis processing #2
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;
88 //left parts Y-axis processing #3
89 DoDrawParts(parts1, pxL, prL, pyL, pryL);
90 DotsHeight(&dlyL, &dryL);
91 pryL = (double)YheightL / (dryL - dlyL);
94 if(flg_boxL & FLAG_FLAT_TOP){
95 pyL = kBaseline - (double)pngWidth * 0.9 + 6 * kWidth - dlyL * pryL;
97 pyL = kBaseline - (double)pngWidth * 0.9 + 2 * kWidth - dlyL * pryL;
100 if(flg_boxL & FLAG_FLAT_BOTTOM || YnanameL != 0){
101 pyL = kBaseline - 2 * kWidth - dryL * pryL;
103 pyL = kBaseline - dryL * pryL;
107 //right parts Y-axis processing #1
108 if(flg_boxR & FLAG_FLAT_TOP) YsideRa++;
109 if(flg_boxR & FLAG_FLAT_BOTTOM) YsideRb++;
111 DoDrawParts(parts3, pxR, prR, pyR, pryR);
112 DotsHeight(&dlyR, &dryR);
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;
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;
142 pxR = pngWidth * prL;
144 //scan body line of left parts
145 DoDrawParts(parts1, pxL, prL, pyL, pryL);
146 for(i = 0; i < pngWidth; i++){
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){
158 kageCanvas[i + 7][j] == 0 ||
159 kageCanvas[i + 8][j] == 0 ||
160 kageCanvas[i + 9][j] == 0 ||
161 kageCanvas[i + 10][j] == 0){
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){
183 kageCanvas[i + 7][j] == 0 ||
184 kageCanvas[i + 8][j] == 0 ||
185 kageCanvas[i + 9][j] == 0 ||
186 kageCanvas[i + 10][j] == 0){
194 //calculate the most thin length of two parts and fix right parts
196 for(i = 0; i < pngWidth; i++){
197 if(bodyline2[i] - bodyline1[i] < k){
198 k = bodyline2[i] - bodyline1[i];
205 //calculate if the two are too close
207 for(i = 0; i < pngWidth; i++){
208 if((bodyline2[i] - bodyline1[i]) - k < kWidth * 2){ // must be seperate with shotai?
214 if(kShotai == kMincho){
219 complex = 1 / ((yokoL + yokoR) / 2);
220 if(tooclose > pngWidth * 0.25){
221 complex = complex * 1.5;
223 pxR = pxR + pow((complex * (double)k), 2.3);
228 result[2] = pxL + pngWidth * prL;
229 result[3] = pyL + pngWidth * pryL;
232 result[10] = pxR + pngWidth * prR;
233 result[11] = pyR + pngWidth * pryR;
235 kShotai = tempShotai;
238 void combineYoko3(const KGString *parts1, const KGString *parts2, const KGString *parts3, int *result){
240 KGString *tempString;
241 int tempResult[8], tempResult2[4];
242 int minx, miny, maxx, maxy, width, height, width2, height2;
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];
257 miny = min(result[1], result[9]);
259 maxy = max(result[3], result[11]);
261 height = maxy - miny;
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];
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);
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;
291 double yokoL, tateL, yokoR, tateR;
304 tempShotai = kShotai;
307 CalcOptions(parts1, &mitsuL, &flg_boxL, &yokoL, &tateL);
308 CalcOptions(parts3, &mitsuR, &flg_boxR, &yokoR, &tateR);
310 if(flg_boxL & FLAG_REPLACE_2FF1_TO_2FF5){
311 combineHame2((KGString *)parts1, (KGString *)parts3, (int *)result,
313 FLAG_SURROUND_RIGHT |
315 kShotai = tempShotai;
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;
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);
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);
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;
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;
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;
380 DoDrawMixFont(parts1, pxL, prL, parts3, pxR, prR, pyL, pryL, pyR, pryR);
382 //count dots for check crossing over
383 DotsWidth(&chk_x1, &chk_x2);
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++;
392 //get close both parts
394 while(k - l < kMixdot && g < kWidth * (kKasane + 4)){
397 DoDrawMixFont(parts1, pxL, prL, parts3, pxR, prR, pyL, pryL, f, pryR);
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++;
407 if(k - l > pngWidth * 0.4){
408 pyR = pyR + kWidth * 4;
410 pyR = pyR + kWidth * 2;
416 result[2] = pxL + pngWidth * prL;
417 result[3] = pyL + pngWidth * pryL;
420 result[10] = pxR + pngWidth * prR;
421 result[11] = pyR + pngWidth * pryR;
423 kShotai = tempShotai;
426 void combineTate3(const KGString *parts1, const KGString *parts2, const KGString *parts3, int *result){
428 KGString *tempString;
429 int tempResult[8], tempResult2[4];
430 int minx, miny, maxx, maxy, width, height, width2, height2;
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]);
449 height = maxy - miny;
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];
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);
469 void combineHame2(const KGString *parts1, const KGString *parts3, int *result, int surround){
476 CalcOptions(parts3, &mitsu, &flg_box, &yoko, &tate);
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;
491 result[8] += kWidth * 2;
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;
499 result[9] += kWidth * 2;
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;
507 result[10] -= kWidth * 2;
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;
515 result[11] -= kWidth * 2;
521 if(flag == 0){ //error