1   package com.octo.captcha.component.image.textpaster.glyphsvisitor;
2   
3   import com.octo.captcha.component.image.textpaster.Glyphs;
4   
5   import java.awt.geom.Rectangle2D;
6   import java.awt.geom.Area;
7   
8   /***
9    * @author mag
10   * @Date 7 mars 2008
11   */
12  public class OverlapGlyphsUsingShapeVisitor extends OverlapGlyphsVisitor {
13      private double overlapPixels ;
14  
15     
16  
17      public OverlapGlyphsUsingShapeVisitor(double overlapPixels) {
18          super(0);
19          this.overlapPixels = overlapPixels;
20      }
21  
22      public void visit(Glyphs gv, Rectangle2D backroundBounds) {
23         
24  
25          
26  
27          for (int i = 1; i < gv.size(); i++) {
28              
29              
30               gv.translate(i, getSidingPosition(gv, i), 0);
31  
32              
33              if (mayGlyphsOverlapAtIndex(gv, i)) {
34                  
35                  double realPossibleOverlap = getMaximumPossibleOverlap(gv, i);
36                  double currentOverlapWidth = intersectAndGetOverlapWidth(gv, i);
37                  double currentOverlapStatus = currentOverlapWidth - realPossibleOverlap;
38                  double bestReacheadOverlapStatus = Math.abs(currentOverlapStatus);
39                 
40                  boolean stillOk=true;
41                 
42                  while (Math.abs(currentOverlapStatus) >= overlapPixels/10&&stillOk) {
43                      double step = currentOverlapStatus/2;
44                      
45                      gv.translate(i, step, 0);
46                      currentOverlapWidth = intersectAndGetOverlapWidth(gv, i);
47                      currentOverlapStatus = currentOverlapWidth-realPossibleOverlap;
48                      
49                      
50  
51  
52                      
53                      if(Math.abs(currentOverlapStatus)>=bestReacheadOverlapStatus&&(currentOverlapWidth!=0||gv.getMaxX(i-1)-gv.getMinX(i)>gv.getBoundsWidth(i-1))){
54                          
55                          
56                          if(currentOverlapWidth==0){
57                              
58                              gv.translate(i, getSidingPosition(gv, i), 0);
59                              
60                          }else{
61                              
62                              gv.translate(i, -step, 0);
63                             
64                          }
65                         
66                          stillOk=false;
67                      }
68                      bestReacheadOverlapStatus = Math.min(Math.abs(currentOverlapStatus),bestReacheadOverlapStatus);
69                  }
70              
71             }else{
72                  System.out.println("NOT POSSIBLE");
73              }
74  
75          }
76      }
77  
78      private double getSidingPosition(Glyphs gv, int i) {
79          return gv.getBoundsX(i-1)+gv.getBoundsWidth(i-1)-gv.getBoundsX(i)
80                      -Math.abs(gv.getRSB(i-1))
81                      -Math.abs(gv.getLSB(i));
82      }
83  
84      private double intersectAndGetOverlapWidth(Glyphs gv, int i) {
85          return getIntesection(gv, i).getBounds2D().getWidth();
86      }
87  
88      private Area getIntesection(Glyphs gv, int index) {
89          Area intersect = new Area(gv.getOutline(index - 1));
90          intersect.intersect(new Area(gv.getOutline(index)));
91          return intersect;
92      }
93  
94      private double getMaximumPossibleOverlap(Glyphs gv, int index) {
95          return Math.min(Math.min(overlapPixels, gv.getBoundsWidth(index)), gv.getBoundsWidth(index - 1));
96      }
97  
98      private boolean mayGlyphsOverlapAtIndex(Glyphs gv, int index) {
99      
100        return  gv.getMinY(index-1)> gv.getMaxY(index)||gv.getMinY(index)>gv.getMaxY(index-1);
101         
102     }
103 }