1
   2import java.awt.*;
   3import java.awt.event.*;
   4import java.awt.geom.Rectangle2D;
   5import java.awt.image.BufferedImage;
   6import java.awt.image.Raster;
   7import java.io.*;
   8import java.text.*;
   9import java.util.Random;
  10
  11import javax.swing.*;
  12import javax.swing.text.AttributeSet;
  13import javax.swing.text.BadLocationException;
  14import javax.swing.text.PlainDocument;
  15
  16/**
  17 * <p>Some java utility functions.</p>
  18 * @author WangTong
  19 * @version 0.01
  20 */

  21public class WordsConvert {
  22    
  23    public static String DEFAULT_WORD_LINE        = "";
  24    public static String DEFAULT_WORD_BCGROUND    = " ";
  25    public static String BLANCK_STRING            = "";
  26    public static String[] GOOD_CHARS = {" """"""""""""""""""""","""""Ο"""
  27                                        """"""""""""}

  28    private static final Random random_ = new Random();
  29    
  30    /**
  31     * <p>After call this function, when you putdown ESCAPE button, the Window will be hide.</p>
  32     * @param compnemt RootPaneContainer (now can be JApplet, JDialog, JFrame, JInternalFrame, JWindow)
  33     * @return true if success, else return false.
  34     */

  35    public static boolean addKeyboardActionEscapExitHide(RootPaneContainer compnemt) {
  36        KeyStroke keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
  37        Action action = new AbstractAction(){
  38            private static final long serialVersionUID = -1527956543338809497L;
  39            public void actionPerformed(ActionEvent e) {
  40                Object obj = e.getSource();
  41                if (obj instanceof Component) {
  42                    Component comp = (Component)obj;
  43                    while (comp != null{
  44                        if (comp instanceof Window || comp instanceof JInternalFrame || comp instanceof JApplet) {
  45                            comp.setVisible(false);
  46                            break;
  47                        }

  48                        comp = comp.getParent();
  49                    }

  50                }

  51            }

  52        }
;
  53        return addKeyboardAction(compnemt, keyStroke, "DogActionMapKey_EscapExitHide", action, JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
  54    }

  55    
  56    /**
  57     * @see #addKeyboardAction(RootPaneContainer, KeyStroke, String, Action, int)
  58     */

  59    public static boolean addKeyboardAction(RootPaneContainer compnemt, KeyStroke keyStroke, Action action, int condition) {
  60        if (compnemt == null{
  61            return false;
  62        }

  63        JRootPane rootPane = compnemt.getRootPane();
  64        if (rootPane == null{
  65            return false;
  66        }

  67        String actionMapKey = "DogActionMapKey";
  68        ActionMap actionMap = rootPane.getActionMap();
  69        for (int i = 0; i < Integer.MAX_VALUE; i++{
  70            if (actionMap.get(actionMapKey + i) == null{
  71                actionMapKey += i;
  72                break;
  73            }

  74        }

  75        if (actionMapKey.equals("DogActionMapKey")) {
  76            return false;
  77        }

  78        return addKeyboardAction(compnemt, keyStroke, actionMapKey, action, condition);
  79    }

  80    
  81    /**
  82     * <p>快捷键.</p>
  83     * @param condition one of (JComponent.WHEN_FOCUSED | JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT | JComponent.WHEN_IN_FOCUSED_WINDOW)
  84     * @return true if success, else return false.
  85     */

  86    public static boolean addKeyboardAction(RootPaneContainer compnemt, KeyStroke keyStroke, String actionMapKey, Action action, int condition) {
  87        if (compnemt == null || keyStroke == null || actionMapKey == null || action == null{
  88            return false;
  89        }

  90        JRootPane rootPane = compnemt.getRootPane();
  91        if (rootPane != null{
  92            try {
  93                rootPane.getInputMap(condition).put(keyStroke, actionMapKey);
  94                rootPane.getActionMap().put(actionMapKey, action);
  95                return true;
  96            }
 catch (Exception e) {
  97                return false;
  98            }

  99        }

 100        return false;
 101    }

 102    
 103    /**
 104     * <p>This function will delete the no print control characters.</p>
 105     * @param Str
 106     * @return request string
 107     */

 108    public static String convertToWidthString(String Str) {
 109        return new String(convertToWidthChars(Str.toCharArray()));
 110    }

 111    
 112    /**
 113     * <p>This function will delete the no print control characters.</p>
 114     * @param chars
 115     * @return request string
 116     */

 117    public static char[] convertToWidthChars(char[] chars) {
 118        int oldLen = chars.length;
 119        char[] tem = new char[oldLen];
 120        int newLen = 0;
 121        char ch;
 122        for (int i = 0; i < oldLen; i++{
 123            ch = convertToWidthChar(chars[i]);
 124            if (ch != 0{
 125                tem[newLen] = ch;
 126                newLen++;
 127            }

 128        }

 129        char[] result = new char[newLen];
 130        System.arraycopy(tem, 0, result, 0, newLen);
 131        return result;
 132    }

 133    
 134    /**
 135     * <p>convert to width characters or GOOD_CHARS.</p>
 136     * @param ch
 137     * @return 0 if convert not OK; <br>
 138     *             not 0 if convert OK(GOOD_CHARS or the char's width is 12).
 139     */

 140    public static char convertToWidthChar(char ch) {
 141        if (ch < '\u0020' && ch >= '\u0000'{
 142            return (char)0;
 143        }

 144        if (ch >= '\u0020' && ch <= '\u007e'{
 145            ch = (char)(ch + 65248);
 146        }

 147        final FontMetrics fm = new BufferedImage(11, BufferedImage.TYPE_4BYTE_ABGR).getGraphics().getFontMetrics();
 148        if (fm.charWidth(ch) == 12 || isCharInGoodChars(ch)) {
 149            return ch;
 150        }

 151        return (char)0;
 152    }

 153    private static boolean isCharInGoodChars(char ch) {
 154        final String goodCharString = getGoodCharsInOneString();
 155        return goodCharString.indexOf(ch) >= 0;
 156    }

 157    private static String getGoodCharsInOneString() {
 158        StringBuffer bf = new StringBuffer();
 159        for (int i = 0; i < GOOD_CHARS.length; i++)
 160            if (GOOD_CHARS[i] != null)
 161                bf.append(GOOD_CHARS[i]);
 162        return bf.toString();
 163    }

 164    
 165    /**
 166     * <p>产生随机的全角字符串(从尽可能多的全角串中选取).</p>
 167     * @param len 要求产生的随机字符数量
 168     * @return 产生的随机全角字符串
 169     */

 170    public static String makeRandomWidthString(int len) {
 171        if (len <= 0{
 172            return BLANCK_STRING;
 173        }

 174        char[] chars = new char[len];
 175        char ch;
 176        for (int index = 0; index < len; index++{
 177            while((ch = convertToWidthChar((char)(Math.abs(random_.nextInt()) % 65536))) == 0{}
 178            chars[index] = ch;    
 179        }

 180        return new String(chars);
 181    }

 182    /**
 183     * <p>产生随机的全角字符串.</p>
 184     * @param len 要求产生的随机字符数量
 185     * @param type    0:从尽可能多的全角串中选取 {@link #makeRandomWidthString(int)}
 186     *                 1:从“半角英文字符对应的全角字符”中选取 {@link #makeRandomWidthStringA(int)}
 187     *                 2:从“汉字”中选取 {@link #makeRandomWidthStringB(int)}
 188     *                 3-……:从内部自定义字符中选取
 189     *                 如果type在以上范围外,type = type对以上的type类型总数取余
 190     * @return 产生的随机全角字符串
 191     */

 192    public static String makeRandomWidthString(int len, int type) {
 193        final String[] baseStrs = {
 194                //"ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩαβγδεζηθικλμνξοπρστυφχψωЁАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюяё",
 195                
 196                "㈠㈡㈢㈣㈤㈥㈦㈧㈨㈩①②③④⑤⑥⑦⑧⑨⑩⑴⑵⑶⑷⑸⑹⑺⑻⑼⑽⑾⑿⒀⒁⒂⒃⒄⒅⒆⒇⒈⒉⒊⒋⒌⒍⒎⒏⒐⒑⒒⒓⒔⒕⒖⒗⒘⒙⒚⒛ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪ" +
 197                "Ⅻⅰⅱⅲⅳⅴⅵⅶⅷⅸⅹ0123456789",
 198                
 199                "〃々〆〇〝〞〡〢〣〤〥〦〧〨〩ぁあぃいぅうぇえぉおかがきぎくぐけげこごさざしじすずせぜそぞただちぢっつづてでとどなにぬねのはばぱひびぴふぶぷへ" +
 200                "べぺほぼぽまみむめもゃやゅゆょよらりるれろゎわゐゑをん゛゜ゝゞァアィイゥウェエォオカガキギクグケゲコゴサザシジスズセゼソゾタダチヂッツヅテデト" +
 201                "ドナニヌネノハバパヒビピフブプヘベペホボポマミムメモャヤュユョヨラリルレロヮワヰヱヲンヴヵヶーヽヾㄅㄆㄇㄈㄉㄊㄋㄌㄍㄎㄏㄐㄑㄒㄓㄔㄕㄖㄗㄘㄙㄚ" +
 202                "ㄛㄜㄝㄞㄟㄠㄡㄢㄣㄤㄥㄦㄧㄨㄩ",
 203                
 204                "←↑→↓↖↗↘↙℡№℃℅℉※‰∈∏∑∕√∝∞∟∠∣∥∧∨∩∪∫∮∴∵∶∷∽‥…≈≌≒≠≡≤≥≦≧≮≯⊙⊥⊿⌒〇〈〉《》「」『』【】〒〓〔〕〖〗" +
 205                "㊣㎎㎏㎜㎝㎞㎡㏄㏎㏑㏒㏕",
 206                
 207                "▁▂▃▄▅▆▇█▉▊▋▌▍▎▏▓▔▕■□▲△▼▽◆◇○◎●◢◣◤◥★☆☉♀⊕♂",
 208                
 209                "─━│┃┄┅┆┇┈┉┊┋┌┍┎┏┐┑┒┓└┕┖┗┘┙┚┛├┝┞┟┠┡┢┣┤┥┦┧┨┩┪┫┬┭┮┯┰┱┲┳┴┵┶┷┸┹┺┻┼┽┾┿╀╁╂╃╄╅╆" +
 210                "╇╈╉╊╋═║╒╓╔╕╖╗╘╙╚╛╜╝╞╟╠╡╢╣╤╥╦╧╨╩╪╫╬╭╮╯╰╱╲╳"
 211        }
;
 212        final int maxType = baseStrs.length + 3;
 213        
 214        if (len <= 0{
 215            return BLANCK_STRING;
 216        }

 217        
 218        if (type == 0{
 219            return makeRandomWidthString(len);
 220        }
 else if (type == 1{
 221            return makeRandomWidthStringA(len);
 222        }
 else if (type == 2{
 223            return makeRandomWidthStringB(len);
 224        }
 else if (type > 2 && type < maxType){
 225            String baseStr = baseStrs[type - 3];
 226            int baseLen = baseStr.length();
 227            char[] chars = new char[len];
 228            for (int index = 0; index < len; index++{
 229                chars[index] = baseStr.charAt(Math.abs(random_.nextInt()) % baseLen);    
 230            }

 231            return new String(chars);
 232        }
 else {
 233            return makeRandomWidthString(len, Math.abs(type) % maxType);
 234        }

 235    }

 236    
 237    /**
 238     * <p>产生随机的全角字符串(从“半角英文字符对应的全角字符”中选取).</p>
 239     * @param len 要求产生的随机字符数量
 240     * @return 产生的随机全角字符串
 241     */

 242    public static String makeRandomWidthStringA(int len) {
 243        if (len <= 0{
 244            return BLANCK_STRING;
 245        }

 246        char[] chars = new char[len];
 247        char ch;
 248        for (int index = 0; index < len; index++{
 249            while((ch = convertToWidthChar((char)(Math.abs(random_.nextInt()) % 0x5f + 0x20))) == 0{}
 250            chars[index] = ch;    
 251        }

 252        return new String(chars);
 253    }

 254    
 255    /**
 256     * <p>产生随机的全角字符串(从“汉字”中选取).</p>
 257     * @param len 要求产生的随机字符数量
 258     * @return 产生的随机全角字符串
 259     */

 260    public static String makeRandomWidthStringB(int len) {
 261        if (len <= 0{
 262            return BLANCK_STRING;
 263        }

 264        char[] chars = new char[len];
 265        char ch;
 266        for (int index = 0; index < len; index++{
 267            while((ch = convertToWidthChar((char)(Math.abs(random_.nextInt()) % 0x51A6 + 0x4e00))) == 0{}
 268            chars[index] = ch;    
 269        }

 270        return new String(chars);
 271    }

 272    
 273    /**
 274     * <p>网上常见的'顶'由多个字组成的.</p>
 275     * 例如:
 276     * ◇◇◇◇◇◇█████████
 277     * ██████◇◇◇█◇◇◇◇◇
 278     * ◇◇◇█◇◇◇◇█◇◇◇◇◇◇
 279     * ◇◇◇█◇◇◇███████◇
 280     * ◇◇◇█◇◇◇█◇◇◇◇◇█◇
 281     * ◇◇◇█◇◇◇█◇◇█◇◇█◇
 282     * ◇◇◇█◇◇◇█◇◇█◇◇█◇
 283     * ◇◇◇█◇◇◇█◇◇█◇◇█◇
 284     * ◇◇◇█◇◇◇█◇◇█◇◇█◇
 285     * ◇◇◇█◇◇◇█◇◇█◇◇█◇
 286     * ◇◇◇█◇◇◇█◇◇█◇◇█◇
 287     * ◇◇◇█◇◇◇◇◇█◇█◇◇◇
 288     * ◇█◇█◇◇◇██◇◇◇█◇◇
 289     * ◇◇█◇◇██◇◇◇◇◇◇██
 290     * ◇◇◇◇◇◇◇◇◇◇◇◇◇◇█
 291     */

 292    public static void callConverCharToCharsFrame() {
 293        ConverCharToCharsFrame frame = new ConverCharToCharsFrame();
 294        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
 295        frame.setBounds(GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds());
 296        frame.show();
 297    }

 298    
 299    static class ConverCharToCharsFrame extends JFrame {
 300        
 301        private static final long serialVersionUID = -339180012836325806L;
 302        
 303        final int maxFontSize = 72;
 304        final int minFontSize = 12;
 305        final int defaultFontSize = 36;
 306        final int safeEdge = 2;
 307        
 308        boolean splitString = false;
 309        String splitMatch = BLANCK_STRING;
 310        
 311        final String[] Names = {"字线文本""背景文本""JTextArea_Front""JTextArea_Background"};
 312        final String[] charStrs = {"", DEFAULT_WORD_LINE, DEFAULT_WORD_BCGROUND, Integer.toString(defaultFontSize)};
 313        final String[][] chooseStrs = {GOOD_CHARS, GOOD_CHARS};
 314        final DecimalFormat df = new DecimalFormat("00");
 315        final MessageFormat mf = new MessageFormat("{0}  {1}");
 316        
 317        private JCheckBox[] checkBox_BoldItalic     = {new JCheckBox("加粗"), new JCheckBox("倾斜")};
 318        private JTextField[] textField                 = new JTextField[4];/*0被转字符 1字线文字 2背景文字 3字体大小*/
 319        private JComboBox[] comboBox_FrontBackWords = new JComboBox[2];
 320        private JComboBox comboBox_Font             = new JComboBox();
 321        private JTextArea textArea_AfterConvert     = new JTextArea();
 322        private BufferedImage image                 = new BufferedImage(11, BufferedImage.TYPE_BYTE_BINARY);//TYPE_BYTE_GRAY
 323        private JTextArea[] textArea_mordWords         = {new JTextArea(DEFAULT_WORD_LINE), new JTextArea(DEFAULT_WORD_BCGROUND)};
 324        private JCheckBox checkBox_swichModle         = new JCheckBox("切换文本模式");
 325        private JButton[] bigTextButton             = {new JButton("输入字线文本"), new JButton("输入背景文本")};
 326        private JButton convert                     = new JButton("转换");
 327        private JButton aboutBt                        = new JButton("程序说明");
 328        private JCheckBox checkBox_splitWords        = new JCheckBox("分割");
 329        private JTextField textField_splitStr        = new JTextField(4);
 330        chooseMoreTextDialog chooseMoreTextD;
 331        JDialog aboutDlg;
 332
 333        public ConverCharToCharsFrame() {
 334            super("Words Convert - 文字转字符字");
 335            JPanel panel = new JPanel();
 336            panel.setLayout(new BorderLayout());
 337            textArea_mordWords[0].setName("JTextArea_Front");
 338            textArea_mordWords[1].setName("JTextArea_Background");
 339            chooseMoreTextD = new chooseMoreTextDialog(this, textArea_mordWords, Names, "请输入或从文件读取文本");
 340            
 341            for (int i = 0; i < bigTextButton.length; i++{
 342                bigTextButton[i].addActionListener(new ActionListener(){
 343                    public void actionPerformed(ActionEvent e) {
 344                        chooseMoreTextD.show();
 345                    }

 346                }
);
 347                bigTextButton[i].setToolTipText("Ctrl ^ O");
 348                bigTextButton[i].setEnabled(false);
 349            }

 350            
 351            textArea_AfterConvert.setBorder(BorderFactory.createEmptyBorder(5555));
 352            textArea_AfterConvert.setAutoscrolls(true);
 353            textArea_AfterConvert.setLineWrap(false);
 354            JScrollPane scrollpanel = new JScrollPane(textArea_AfterConvert);
 355            scrollpanel.setBorder(BorderFactory.createEmptyBorder(0000));
 356            scrollpanel.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
 357            panel.add(scrollpanel, BorderLayout.CENTER);
 358            
 359            {
 360                try {
 361                    String[] fontNames = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
 362                    for (int i = 0; i < fontNames.length; i++{
 363                        comboBox_Font.addItem(fontNames[i]);
 364                    }

 365                }
 catch (Exception e) {
 366                    
 367                }

 368                for (int i = 0; i < comboBox_Font.getItemCount(); i++{
 369                    String item = comboBox_Font.getItemAt(i).toString();
 370                    if (item.equals("宋体"|| item.indexOf("楷体">= 0 || item.indexOf("黑体">= 0{
 371                        comboBox_Font.setSelectedIndex(i);
 372                        break;
 373                    }

 374                }

 375            }

 376            for (int i = 0; i < textField.length; i++{
 377                textField[i] = new JTextField(i == 0 ? 18 : 2);
 378                MyDocument document = new MyDocument();
 379                document.setMaxCharacters(i == 0 ? Integer.MAX_VALUE : i == 3 ? 2 : 1);
 380                textField[i].setDocument(document);
 381                textField[i].setText(charStrs[i]); 
 382            }

 383            textField[0].setToolTipText("Ctrl ^ W");
 384            textField[3].setToolTipText("Ctrl ^ S");
 385            for (int i = 0; i < comboBox_FrontBackWords.length; i++{
 386                comboBox_FrontBackWords[i] = new JComboBox();
 387                for (int j = 0; j < chooseStrs[i].length; j++{
 388                    comboBox_FrontBackWords[i].addItem(mf.format(new String[]{df.format(j + 1), chooseStrs[i][j]}));
 389                }

 390                comboBox_FrontBackWords[i].addActionListener(new ActionListener(){
 391                    public void actionPerformed(ActionEvent e) {
 392                        int index = 1;
 393                        if (e.getSource().equals(comboBox_FrontBackWords[0])) {
 394                            index = 0;
 395                        }

 396                        textField[index + 1].setText(chooseStrs[index][comboBox_FrontBackWords[index].getSelectedIndex()]);
 397                    }

 398                }
);
 399            }

 400            
 401    
 402            JPanel panelNorth = new JPanel();
 403            panelNorth.setLayout(new BoxLayout(panelNorth, BoxLayout.Y_AXIS));
 404            JPanel panelUp = new JPanel();
 405            panelUp.setLayout(new FlowLayout(FlowLayout.CENTER, 100));
 406            panelNorth.add(panelUp);
 407            JPanel panelDown = new JPanel();
 408            panelDown.setLayout(new FlowLayout(FlowLayout.CENTER, 100));
 409            panelNorth.add(panelDown);
 410            checkBox_swichModle.setToolTipText("Ctrl ^ M");
 411            panelDown.add(checkBox_swichModle);
 412            panelDown.add(bigTextButton[0]);
 413            panelDown.add(bigTextButton[1]);
 414            
 415            {
 416                JPanel panelOne = new JPanel();
 417                panelOne.add(new JLabel("被转字符:"));
 418                panelOne.add(textField[0]);
 419                panelOne.add(checkBox_splitWords);
 420                panelOne.add(textField_splitStr);
 421                panelUp.add(panelOne);
 422                
 423                panelOne = new JPanel();
 424                panelOne.add(new JLabel("字体:"));
 425                panelOne.add(comboBox_Font);
 426                panelOne.add(new JLabel("大小:"));
 427                panelOne.add(textField[3]);
 428                panelUp.add(panelOne);
 429                
 430                checkBox_BoldItalic[0].setSelected(true);
 431                checkBox_BoldItalic[0].setToolTipText("Ctrl ^ B");
 432                panelUp.add(checkBox_BoldItalic[0]);
 433                checkBox_BoldItalic[1].setToolTipText("Ctrl ^ I");
 434                panelUp.add(checkBox_BoldItalic[1]);
 435                
 436                panelOne = new JPanel();
 437                panelOne.add(new JLabel("字线文字"));
 438                panelOne.add(textField[1]);
 439                panelOne.add(comboBox_FrontBackWords[0]);
 440                panelOne.add(new JLabel("背景文字"));
 441                panelOne.add(textField[2]);
 442                panelOne.add(comboBox_FrontBackWords[1]);
 443                panelDown.add(panelOne);
 444                
 445                panelOne = new JPanel();
 446                convert.setToolTipText("Ctrl ^ T");
 447                aboutBt.setToolTipText("Ctrl ^ R");
 448                panelOne.add(convert);
 449                panelOne.add(aboutBt);
 450                panelDown.add(panelOne);
 451            }

 452    
 453            
 454            panel.add(panelNorth, BorderLayout.NORTH);
 455            
 456            ActionListener splitWordsListener =  new ActionListener(){
 457                public void actionPerformed(ActionEvent e) {
 458                    textField_splitStr.setEditable(checkBox_splitWords.isSelected());
 459                    textField_splitStr.setEnabled(checkBox_splitWords.isSelected());
 460                }

 461            }
;
 462            checkBox_splitWords.addActionListener(splitWordsListener);
 463            splitWordsListener.actionPerformed(null);
 464            
 465            ActionListener useMoreTextListener =  new ActionListener(){
 466                public void actionPerformed(ActionEvent e) {
 467                    swichModleActionPerformed(e);
 468                }

 469            }
;
 470            checkBox_swichModle.addActionListener(useMoreTextListener);
 471            
 472            ActionListener converActionListener = new ActionListener(){
 473                public void actionPerformed(ActionEvent e) {
 474                    converActionPerformed(e);
 475                }

 476            }
;
 477            convert.addActionListener(converActionListener);
 478            
 479            ActionListener aboutBtActionListener = new ActionListener() {
 480                public void actionPerformed (ActionEvent e) {
 481                    aboutActionPerformed(e);
 482                }

 483            }
;
 484            aboutBt.addActionListener(aboutBtActionListener);
 485            
 486            initQuicklyBoard();
 487            getContentPane().add(panel);
 488        }

 489        
 490        private void initQuicklyBoard() {
 491            Action actionKeySwichModle = new AbstractAction() {
 492                private static final long serialVersionUID = -3370149516576165837L;
 493                public void actionPerformed(ActionEvent e) {
 494                    checkBox_swichModle.setSelected(!checkBox_swichModle.isSelected());
 495                    swichModleActionPerformed(null);
 496                }

 497            }
;
 498            addKeyboardAction(this, KeyStroke.getKeyStroke(KeyEvent.VK_M, KeyEvent.CTRL_MASK), 
 499                    actionKeySwichModle, JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
 500            
 501            Action actionKeyConvert = new AbstractAction() {
 502                private static final long serialVersionUID = 5619078648434506648L;
 503                public void actionPerformed(ActionEvent e) {
 504                    converActionPerformed(null);
 505                }

 506            }
;
 507            addKeyboardAction(this, KeyStroke.getKeyStroke(KeyEvent.VK_T, KeyEvent.CTRL_MASK), 
 508                    actionKeyConvert, JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
 509            
 510            Action actionKeyAbout = new AbstractAction() {
 511                private static final long serialVersionUID = 4782763377700004755L;
 512                public void actionPerformed(ActionEvent e) {
 513                    aboutActionPerformed(null);
 514                }

 515            }
;
 516            addKeyboardAction(this, KeyStroke.getKeyStroke(KeyEvent.VK_R, KeyEvent.CTRL_MASK), 
 517                    actionKeyAbout, JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
 518            
 519            Action actionKeyBold = new AbstractAction() {
 520                private static final long serialVersionUID = 9153089956379463659L;
 521                public void actionPerformed(ActionEvent e) {
 522                    checkBox_BoldItalic[0].setSelected(!checkBox_BoldItalic[0].isSelected());
 523                }

 524            }
;
 525            addKeyboardAction(this, KeyStroke.getKeyStroke(KeyEvent.VK_B, KeyEvent.CTRL_MASK), 
 526                    actionKeyBold, JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
 527            
 528            Action actionKeyItalic = new AbstractAction() {
 529                private static final long serialVersionUID = 7413316504317095799L;
 530                public void actionPerformed(ActionEvent e) {
 531                    checkBox_BoldItalic[1].setSelected(!checkBox_BoldItalic[1].isSelected());
 532                }

 533            }
;
 534            addKeyboardAction(this, KeyStroke.getKeyStroke(KeyEvent.VK_I, KeyEvent.CTRL_MASK), 
 535                    actionKeyItalic, JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
 536            
 537            Action actionKeyInputMoreTextDialog = new AbstractAction() {
 538                private static final long serialVersionUID = 2389370838506184488L;
 539                public void actionPerformed(ActionEvent e) {
 540                    if (!checkBox_swichModle.isSelected()) {
 541                        checkBox_swichModle.setSelected(true);
 542                        swichModleActionPerformed(null);
 543                    }

 544                    chooseMoreTextD.show();
 545                }

 546            }
;
 547            addKeyboardAction(this, KeyStroke.getKeyStroke(KeyEvent.VK_O, KeyEvent.CTRL_MASK), 
 548                    actionKeyInputMoreTextDialog, JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
 549            
 550            Action actionKeySize = new AbstractAction() {
 551                private static final long serialVersionUID = 615986388877660304L;
 552                public void actionPerformed(ActionEvent e) {
 553                    textField[3].requestFocus(true);
 554                    textField[3].setSelectionStart(0);
 555                    textField[3].setSelectionEnd(textField[3].getText().length());
 556                }

 557            }
;
 558            addKeyboardAction(this, KeyStroke.getKeyStroke(KeyEvent.VK_S, KeyEvent.CTRL_MASK), 
 559                    actionKeySize, JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
 560            
 561            Action actionKeyBeiZhuanZiFu = new AbstractAction() {
 562                private static final long serialVersionUID = 615986388877660304L;
 563                public void actionPerformed(ActionEvent e) {
 564                    textField[0].requestFocus(true);
 565                    textField[0].setSelectionStart(0);
 566                    textField[0].setSelectionEnd(textField[0].getText().length());
 567                }

 568            }
;
 569            addKeyboardAction(this, KeyStroke.getKeyStroke(KeyEvent.VK_W, KeyEvent.CTRL_MASK), 
 570                    actionKeyBeiZhuanZiFu, JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
 571        }

 572        
 573        private void converActionPerformed(ActionEvent e) {
 574            String[] charBC = new String[]{DEFAULT_WORD_LINE, DEFAULT_WORD_BCGROUND};
 575            if (textField[0].getText().trim().equals(BLANCK_STRING)) {
 576                return;
 577            }

 578            if (textField[1].getText().trim().length() > 0{
 579                char ch = convertToWidthChar(textField[1].getText().trim().charAt(0));
 580                if (ch != 0{
 581                    charBC[0= new String(new char[]{ch});
 582                }

 583            }

 584            if (textField[2].getText().trim().length() > 0{
 585                char ch = convertToWidthChar(textField[2].getText().trim().charAt(0));
 586                if (ch != 0{
 587                    charBC[1= new String(new char[]{ch});
 588                }

 589            }

 590            
 591            splitString = checkBox_splitWords.isSelected();
 592            splitMatch = textField_splitStr.getText();
 593            
 594            boolean isMoreModle = checkBox_swichModle.isSelected();
 595            String[] moreModleStrs = new String[2];
 596            if (isMoreModle) {
 597                for (int i = 0; i < textArea_mordWords.length; i++{
 598                    moreModleStrs[i] = textArea_mordWords[i].getText();
 599                    if (moreModleStrs[i] == null || moreModleStrs[i].length() < 1{
 600                        moreModleStrs[i] = i == 0 ? DEFAULT_WORD_LINE : DEFAULT_WORD_BCGROUND;
 601                    }

 602                }

 603            }

 604            
 605            textArea_AfterConvert.setText(BLANCK_STRING);
 606            String[] charA;
 607            String textFromField = textField[0].getText();
 608            if (splitString) {
 609                charA = textFromField.split(splitMatch);
 610            }
 else {
 611                charA = new String[]{textFromField};
 612            }

 613            if (charA == null || charA.length <= 0{
 614                return;
 615            }

 616            Graphics g = image.getGraphics();
 617            String fontName = comboBox_Font.getSelectedItem().toString();
 618            int fontSize = defaultFontSize;
 619            try {
 620                fontSize = Integer.parseInt(textField[3].getText());
 621                if (fontSize < minFontSize) {
 622                    fontSize = minFontSize;
 623                }
 else if (fontSize > maxFontSize) {
 624                    fontSize = maxFontSize;
 625                }

 626            }
 catch (Exception exp) {
 627                fontSize = defaultFontSize;
 628            }

 629            int style = Font.PLAIN;
 630            if (checkBox_BoldItalic[0].isSelected()) {
 631                style |= Font.BOLD;
 632            }

 633            if (checkBox_BoldItalic[1].isSelected()) {
 634                style |= Font.ITALIC;
 635            }

 636
 637            int count0 = 0;
 638            int count1 = 0;
 639            StringBuffer bufferForArea = new StringBuffer();
 640            for (int indexChar = 0; indexChar < charA.length; indexChar++{
 641                if (charA[indexChar] == null || charA[indexChar].equals("")) {
 642                    continue;
 643                }

 644                Font font = new Font(fontName, style, fontSize);
 645                g.setFont(font);
 646                FontMetrics fm = g.getFontMetrics();
 647                //Rectangle2D rg2d = fm.getMaxCharBounds(g);
 648                Rectangle2D rg2d = fm.getStringBounds(charA[indexChar], g);
 649                int width = (int)Math.round(rg2d.getWidth()) + safeEdge * 2;
 650                int height = (int)Math.round(rg2d.getHeight()) + safeEdge * 2;
 651                int x0 = (int)Math.round(Math.abs(rg2d.getX())) + safeEdge;
 652                int y0 = (int)Math.round(Math.abs(rg2d.getY())) + safeEdge;
 653                image = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_BINARY);
 654                g = image.getGraphics();
 655                g.setFont(font);
 656                g.setColor(Color.WHITE);
 657                
 658                g.clearRect(00, width, height);
 659                g.drawString(charA[indexChar], x0, y0);
 660                
 661                int minX = Integer.MAX_VALUE;
 662                int minY = Integer.MAX_VALUE;
 663                int maxX = Integer.MIN_VALUE;
 664                int maxY = Integer.MIN_VALUE;
 665                
 666                ////start New Method
 667                Raster raster = image.getRaster();
 668                Rectangle rg = raster.getBounds();
 669                int[] pixels = null;
 670                pixels = raster.getPixels(rg.x, rg.y, rg.width, rg.height, pixels);
 671                for (int y = 0; y < rg.height; y++{
 672                    for (int x = 0; x < rg.width; x++{
 673                        if (pixels[rg.width * y + x] != 0{
 674                            if (minY == Integer.MAX_VALUE) {
 675                                minY = y;
 676                            }

 677                            maxY = y > maxY ? y : maxY;
 678                            minX = x < minX ? x : minX;
 679                            maxX = x > maxX ? x : maxX;
 680                        }

 681                    }

 682                }

 683
 684                if (charBC[0].trim().length() == 0 || charBC[0].equals(" ")) {
 685                    minX--;
 686                    minY--;
 687                    maxX++;
 688                    maxY++;
 689                }

 690                
 691                for (int y = minY; y <= maxY; y++{
 692                    for (int x = minX; x <= maxX; x++{
 693                        if (isMoreModle) {
 694                            if (pixels[rg.width * y + x] == 0{
 695                                bufferForArea.append(moreModleStrs[1].charAt(count1));
 696                                count1++;
 697                                if (count1 == moreModleStrs[1].length())
 698                                    count1 = 0;
 699                                
 700                            }
 else {
 701                                bufferForArea.append(moreModleStrs[0].charAt(count0));
 702                                count0++;
 703                                if (count0 == moreModleStrs[0].length())
 704                                    count0 = 0;
 705                            }

 706                        }
 else {
 707                            if (pixels[rg.width * y + x] == 0{
 708                                bufferForArea.append(charBC[1]);
 709                            }
 else {
 710                                bufferForArea.append(charBC[0]);
 711                            }

 712                        }

 713                    }

 714                    bufferForArea.append("\n");
 715                }

 716                ////end New Method
 717                
 718                
 719                /* ////Old Method (int charColorInt = -1; //FFFFFFFF)
 720                for (int y = 0; y < height; y++) {
 721                    for (int x = 0; x < width; x++) {
 722                        if (image.getRGB(x, y) == charColorInt) {
 723                            if (minY == Integer.MAX_VALUE) {
 724                                minY = y;
 725                            }
 726                            maxY = y > maxY ? y : maxY;
 727                            minX = x < minX ? x : minX;
 728                            maxX = x > maxX ? x : maxX;
 729                        }
 730                    }
 731                }
 732                if (charBC[0].trim().length() == 0 || charBC[0].equals(" ")) {
 733                    minX--;
 734                    minY--;
 735                    maxX++;
 736                    maxY++;
 737                }
 738                
 739                for (int y = minY; y <= maxY; y++) {
 740                    for (int x = minX; x <= maxX; x++) {
 741                        if (isMoreModle) {
 742                            if (image.getRGB(x, y) == charColorInt) {
 743                                bufferForArea.append(moreModleStrs[0].charAt(count0));
 744                                count0++;
 745                                if (count0 == moreModleStrs[0].length())
 746                                    count0 = 0;
 747                            } else {
 748                                bufferForArea.append(moreModleStrs[1].charAt(count1));
 749                                count1++;
 750                                if (count1 == moreModleStrs[1].length())
 751                                    count1 = 0;
 752                            }
 753                        } else {
 754                            if (image.getRGB(x, y) == charColorInt) {
 755                                bufferForArea.append(charBC[0]);
 756                            } else {
 757                                bufferForArea.append(charBC[1]);
 758                            }
 759                        }
 760                    }
 761                    bufferForArea.append("\n");
 762                }
 763                */

 764                if (indexChar != charA.length - 1{
 765                    bufferForArea.append("\n\n");
 766                }

 767            }

 768            textArea_AfterConvert.append(bufferForArea.toString());
 769            textArea_AfterConvert.setSelectionStart(0);
 770            textArea_AfterConvert.setSelectionEnd(textArea_AfterConvert.getText().length());
 771            textArea_AfterConvert.requestFocus();
 772        }

 773    
 774        private void aboutActionPerformed(ActionEvent e) {
 775            if (aboutDlg == null{
 776                aboutDlg = new JDialog(ConverCharToCharsFrame.this"关于本程序"true);
 777                aboutDlg.setSize(600550);
 778                aboutDlg.setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE);
 779                addKeyboardActionEscapExitHide(aboutDlg);
 780                {
 781                    JPanel panel = new JPanel();
 782                    panel.setLayout(new BorderLayout());
 783                    {
 784                        String textAbout = "<html><br>程序说明 ( 程序版本:1.0 )<br></html>";
 785                        JLabel label = new JLabel(textAbout);
 786                        label.setHorizontalAlignment(JLabel.CENTER);
 787                        panel.add(label, BorderLayout.NORTH);
 788                    }

 789                    {
 790                        JTextArea area = new JTextArea(2030);
 791                        String textAbout = 
 792                            "  “被转字符” :将要被转换成字符字的一个或多个字。\n\n" +
 793                            "  “分割”   :如果选中,后面的文本框可以输入分割串(默认情况将‘被转字符’分割为单字符),然后分行显示分割后的字符字。\n\n" +
 794                            "  “字体”   :转换后的字符字的字体。(“大小”、“加粗”及“倾斜”与此大同小异)\n\n" +
 795                            "  “文本模式” :如选中,字符字的字线文字与背景文字采用文本;如不选,则采用单个字符。\n\n" +
 796                            "  “字线文字” :“被转字符”的字符的线由什么文字组成。(“输入字线文本”与此相同)\n\n" +
 797                            "  “背景文字” :“被转字符”的字符的空白部分由什么文字组成。(“输入背景文本”与此相同)\n\n" +
 798                            "  “转换”   :根据前面设置好的选项,把“被转字符”转成字符字。\n\n" +
 799                            "  “如何复制” :选中要复制的文本,按下 “Ctrl ^ C” 就复制到剪贴板了。\n\n" +
 800                            "  Ctrl ^ W 被转字符\n" +
 801                            "  Ctrl ^ S 大小  Ctrl ^ B 加粗  Ctrl ^ I 倾斜\n" +
 802                            "  Ctrl ^ M 切换文本模式\n" +
 803                            "  Ctrl ^ O 打开文本对话框\n" +
 804                            "  Ctrl ^ T 转换\n" +
 805                            "  Ctrl ^ R 程序说明\n" +
 806                            "                       Make by 沉思的狗 2007-07-30";
 807                        area.setBorder(BorderFactory.createEmptyBorder(5555));
 808                        area.setText(textAbout);
 809                        area.setAutoscrolls(true);
 810                        area.setEditable(false);
 811                        area.setSelectedTextColor(Color.BLACK);
 812                        area.setSelectionColor(aboutDlg.getBackground());
 813                        area.setBackground(aboutDlg.getBackground());
 814                        area.setLineWrap(true);
 815                        JScrollPane scrollpanel = new JScrollPane(area);
 816                        scrollpanel.setBorder(BorderFactory.createEmptyBorder(0000));
 817                        scrollpanel.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
 818                        panel.add(scrollpanel, BorderLayout.CENTER);
 819                    }

 820                    aboutDlg.getContentPane().add(panel);
 821                }

 822
 823            }

 824            aboutDlg.setLocationRelativeTo(ConverCharToCharsFrame.this);
 825            aboutDlg.setResizable(false);
 826            aboutDlg.show();
 827            aboutDlg.toFront();
 828        }

 829
 830        private void swichModleActionPerformed(ActionEvent e) {
 831            boolean select = checkBox_swichModle.isSelected();
 832            bigTextButton[0].setEnabled(select);
 833            bigTextButton[1].setEnabled(select);
 834            
 835            textField[1].setEnabled(!select);
 836            textField[2].setEnabled(!select);
 837            comboBox_FrontBackWords[0].setEnabled(!select);
 838            comboBox_FrontBackWords[1].setEnabled(!select);
 839        }

 840    }

 841    
 842    static class MyDocument extends PlainDocument {
 843        private static final long serialVersionUID = -5666497024919910771L;
 844        private int maxCharacters_ = 128;
 845        public void setMaxCharacters(int maxChars) {
 846            maxCharacters_ = maxChars;
 847        }

 848        public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
 849            if (getLength() + str.length() > maxCharacters_) {
 850                return;
 851            }

 852            super.insertString(offs, str, a);
 853        }

 854    }

 855    
 856    static class chooseMoreTextDialog extends JDialog {
 857        private static final long serialVersionUID = 4327925741106920935L;
 858        private JTextArea[] textArea;
 859        private File choosingPath = null;
 860        private String[] defaultText_;
 861        private static final int READ_RANDOM_MAX_LEN = 500;
 862        private int count = 0;
 863        private JButton[] openFileBt;
 864        private JButton[] radomTextBt;
 865        private JButton[] clearTextBt;
 866        
 867        /**
 868         * <p>names != null area != null title != null
 869         *    names.length >= area.length.</p>
 870         */

 871        public chooseMoreTextDialog(JFrame parent, JTextArea[] area, String[] names, String title) {
 872            super(parent, true);
 873            setTitle(title);
 874            textArea = area;
 875            openFileBt = new JButton[textArea.length];
 876            radomTextBt = new JButton[textArea.length];
 877            clearTextBt = new JButton[textArea.length];
 878            defaultText_ = new String[textArea.length];
 879            
 880            ActionListener openFileBtActionListener = new ActionListener(){
 881                public void actionPerformed(ActionEvent e) {
 882                    int index = 0;
 883                    for (int i = 0; i < openFileBt.length; i++{
 884                        if (e.getSource().equals(openFileBt[i])) {
 885                            index = i;
 886                            break;
 887                        }

 888                    }

 889                    JFileChooser fileChooser = new JFileChooser(choosingPath);
 890                    fileChooser.setDialogTitle("请选择一个文件");
 891                    fileChooser.setVisible(true);
 892                    int ret = fileChooser.showOpenDialog(chooseMoreTextDialog.this);
 893                    if (ret == JFileChooser.APPROVE_OPTION) {
 894                        choosingPath = fileChooser.getCurrentDirectory();
 895                        File file = fileChooser.getSelectedFile();
 896                        try {
 897                            BufferedReader reader = new BufferedReader(new FileReader(file));
 898                            StringBuffer bf = new StringBuffer();
 899                            String line;
 900                            while (reader.ready()) {
 901                                if ((line = reader.readLine()) != null{
 902                                    bf.append(convertToWidthString(line.trim()));
 903                                }
 else {
 904                                    break;
 905                                }

 906                                if (bf.length() > READ_RANDOM_MAX_LEN) {
 907                                    break;
 908                                }

 909                            }

 910                            reader.close();
 911                            String text = bf.toString();
 912                            text = text.replaceAll(" ", BLANCK_STRING);
 913                            if (text.length() == 0{
 914                                text = defaultText_[index];
 915                            }

 916                            textArea[index].setText(text);
 917                        }
 catch (Exception exp) {
 918                            textArea[index].setText("READ※FILE※ERROR※");
 919                        }

 920                    }

 921                }

 922            }
;
 923            
 924            ActionListener radomTextBtActionListener = new ActionListener(){
 925                public void actionPerformed(ActionEvent e) {
 926
 927                    int index = 0;
 928                    for (int i = 0; i < radomTextBt.length; i++{
 929                        if (e.getSource().equals(radomTextBt[i])) {
 930                            index = i;
 931                            break;
 932                        }

 933                    }

 934                    if (count == Integer.MAX_VALUE - 1{
 935                        count = 0;
 936                    }

 937                    textArea[index].setText(makeRandomWidthString(READ_RANDOM_MAX_LEN, count++));
 938                }

 939            }
;
 940            
 941            ActionListener clearTextBtActionListener = new ActionListener(){
 942                public void actionPerformed(ActionEvent e) {
 943                    for (int i = 0; i < clearTextBt.length; i++{
 944                        if (e.getSource().equals(clearTextBt[i])) {
 945                            textArea[i].setText("");
 946                            break;
 947                        }

 948                    }

 949                }

 950            }
;
 951            
 952            JPanel mainPanel = new JPanel();
 953            mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.X_AXIS));
 954            for (int i = 0; i < textArea.length; i++{
 955                defaultText_[i] = textArea[i].getName().equals("JTextArea_Front"? DEFAULT_WORD_LINE : DEFAULT_WORD_BCGROUND;
 956                
 957                JPanel panel = new JPanel();
 958                panel.setLayout(new BorderLayout());
 959                panel.setBorder(BorderFactory.createEtchedBorder());
 960                
 961                JPanel panelNorth = new JPanel();
 962                panelNorth.setLayout(new BoxLayout(panelNorth, BoxLayout.Y_AXIS));
 963                {
 964                    JPanel panelNorthUP = new JPanel();
 965                    JLabel label = new JLabel(names[i]);
 966                    label.setFocusable(false);
 967                    panelNorthUP.add(label);
 968                    panelNorth.add(panelNorthUP);
 969                }

 970                {
 971                    openFileBt[i] = new JButton("打开文本文件");
 972                    radomTextBt[i] = new JButton("随机文本");
 973                    clearTextBt[i] = new JButton("清空");
 974                    openFileBt[i].addActionListener(openFileBtActionListener);
 975                    radomTextBt[i].addActionListener(radomTextBtActionListener);
 976                    clearTextBt[i].addActionListener(clearTextBtActionListener);
 977                    JPanel panelNorthDOWN = new JPanel();
 978                    panelNorthDOWN.add(openFileBt[i]);
 979                    panelNorthDOWN.add(radomTextBt[i]);
 980                    panelNorthDOWN.add(clearTextBt[i]);
 981                    panelNorth.add(panelNorthDOWN);
 982                }

 983                
 984                textArea[i].setBorder(BorderFactory.createEmptyBorder(5555));
 985                textArea[i].setAutoscrolls(true);
 986                textArea[i].setLineWrap(true);
 987                JScrollPane scrollpanel = new JScrollPane(textArea[i]);
 988                scrollpanel.setBorder(BorderFactory.createEmptyBorder(0000));
 989                scrollpanel.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
 990                scrollpanel.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
 991                
 992                panel.add(panelNorth, BorderLayout.NORTH);
 993                panel.add(scrollpanel, BorderLayout.CENTER);
 994                mainPanel.add(panel);
 995            }

 996            
 997            this.getContentPane().setLayout(new BorderLayout());
 998            this.getContentPane().add(mainPanel, BorderLayout.CENTER);
 999            
1000            this.setSize(600400);
1001            this.setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE);
1002            this.setResizable(false);
1003            addKeyboardActionEscapExitHide(this);
1004        }

1005        
1006        public void hide() {
1007            for (int index = 0; index < textArea.length; index++{
1008                String text = convertToWidthString(textArea[index].getText());
1009                text = text.replaceAll(" ", BLANCK_STRING);
1010                if (text.length() == 0{
1011                    text = defaultText_[index];
1012                }

1013                textArea[index].setText(text);
1014            }

1015            super.hide();
1016        }

1017    }

1018    
1019    public static void main(String[] args) {
1020        callConverCharToCharsFrame();
1021    }

1022}

1023