import java.lang.*; import java.awt.*; import java.awt.event.*; import java.awt.image.*; import java.net.*; import java.applet.*; import java.util.*; final public class KanaTest extends Applet implements Runnable, KeyListener, MouseListener, ItemListener { boolean _fInit = false, _fError = false; Thread _thread = null; int _iCurrent = -1; boolean _fInfo = false; Choice _choiceFont; Hashtable _hashImg; FontMetrics _fm; int _iImgSize; int _cxString1, _cxString2, _iAscent, _iDescent; static Hashtable _hashRoman; static String _strKanaTable[]; static int _cKana = setupKana(); final static String _strWait = "Now loading images..."; final static String _strError = "Image load error!"; final static String _astrFonts[] = { "Gothic", "Kaisho", "MaruGothic", "Mincho", "Pop", "Textbook" }; String _strFont = "Textbook"; boolean _fKata = false; final static String _strConsonants = " kgsztdnhbpmyrw", _strVowels = "aiueo"; final static String _strhashRoman = "sya,sha,si,shi,syu,shu,syo,sho,zya,ja,zi,ji,zyu,ju,zyo,jo,tya,cha,ti,chi,tyu,chu,tyo,cho,tu,tsu,dya,ja,dyu,ju,dyo,jo,di,ji,du,zu,hu,fu,wi,i,we,e,wo,o,N,n,Q,(next consonant)"; final private static String getKanaHash(Hashtable hash, String strKana) { String strValue = (String)hash.get(strKana); return (strValue != null ? strValue : strKana); } final private static int setupKana() { _hashRoman = new Hashtable(); StringTokenizer st = new StringTokenizer(_strhashRoman, ","); while (st.hasMoreTokens()) { _hashRoman.put(st.nextToken(), st.nextToken()); } StringBuffer sb = new StringBuffer(); Vector vector = new Vector(); for (int iConsonant = 0; iConsonant < _strConsonants.length(); iConsonant++) { char cConsonant = _strConsonants.charAt(iConsonant); for (int iVowel = 0; iVowel < _strVowels.length(); iVowel++) { char cVowel = _strVowels.charAt(iVowel); if (!((cConsonant == 'y' && (cVowel == 'i' || cVowel == 'e')) || (cConsonant == 'w' && cVowel == 'u'))) { sb.setLength(0); if (cConsonant != ' ') { sb.append(cConsonant); } sb.append(cVowel); vector.addElement(sb.toString()); } } if (cConsonant != ' ' && cConsonant != 'y' && cConsonant != 'w') { for (int iVowel = 0; iVowel < _strVowels.length(); iVowel += 2) { sb.setLength(0); sb.append(cConsonant).append('y').append(_strVowels.charAt(iVowel)); vector.addElement(sb.toString()); } } } vector.addElement("N"); vector.addElement("Q"); int cKana = vector.size(); vector.copyInto(_strKanaTable = new String[cKana]); return cKana; } final public void init() { Color color = new Color(0xf2, 0xf0, 0xf5); setBackground(color); Choice choice = new Choice(); for (int iIndex = 0; iIndex < _astrFonts.length; iIndex++) { choice.addItem(_astrFonts[iIndex] + ", Hiragana"); choice.addItem(_astrFonts[iIndex] + ", Katakana"); } choice.select(_strFont + ", Hiragana"); choice.addItemListener(this); add(_choiceFont = choice); Font fontOld = getFont(), fontNew = new Font("serif", Font.BOLD, 32); setFont(fontNew); choice.setFont(fontOld); _fm = getFontMetrics(fontNew); _cxString1 = _fm.stringWidth(_strWait); _cxString2 = _fm.stringWidth(_strError); _iAscent = _fm.getMaxAscent(); _iDescent = _fm.getMaxDescent(); if (!_fInit && !_fError && _thread == null) { (_thread = new Thread(this)).start(); } addKeyListener(this); addMouseListener(this); } final public void start() { requestFocus(); } final public synchronized void doLayout() { if (_choiceFont != null) { Dimension dim = getSize(); int iWidth = dim.width, iHeight = dim.height; dim = _choiceFont.getPreferredSize(); _choiceFont.setBounds(0, 0, Math.min(iWidth / 2, dim.width), Math.min(iHeight / 4, dim.height)); } } final public void run() { try { Image image = getImage(getCodeBase(), _strFont.toLowerCase() + (_fKata ? "_k.gif" : ".gif")); MediaTracker media = new MediaTracker(this); media.addImage(image, 0); media.waitForAll(); if (media.isErrorAny()) { _fError = true; } else { int iImgSize = _iImgSize = image.getHeight(this), cImages = 0; ImageProducer imgprod = image.getSource(); _hashImg = new Hashtable(); StringBuffer sb = new StringBuffer(); for (int iConsonant = 0; iConsonant < _strConsonants.length(); iConsonant++) { char cConsonant = _strConsonants.charAt(iConsonant); for (int iVowel = 0; iVowel < _strVowels.length(); iVowel++) { char cVowel = _strVowels.charAt(iVowel); if (!((cConsonant == 'y' && (cVowel == 'i' || cVowel == 'e')) || (cConsonant == 'w' && cVowel == 'u'))) { sb.setLength(0); if (cConsonant != ' ') { sb.append(cConsonant); } _hashImg.put(sb.append(cVowel).toString(), createImage(new FilteredImageSource (imgprod, new CropImageFilter(cImages++ * iImgSize, 0, iImgSize, iImgSize)))); } } } for (int iAddition = 0; iAddition <= 4; iAddition++) { _hashImg.put(iAddition == 0 ? "N" : (iAddition == 1 ? "Q" : (iAddition == 2 ? "small ya" : (iAddition == 3 ? "small yu" : "small yo"))), createImage(new FilteredImageSource (imgprod, new CropImageFilter(cImages++ * iImgSize, 0, iImgSize, iImgSize)))); } if (_iCurrent < 0) { _iCurrent = random(); } _fInit = true; } } catch (Exception e) { _fError = true; } _thread = null; repaint(); } final public void paint(Graphics g) { Dimension dim = getSize(); int yOffset = dim.height / 4; int cx = dim.width, cy = dim.height - yOffset; int iAscent = _iAscent, iDescent = _iDescent; int yString = (cy + iAscent - iDescent) / 2 + yOffset; if (_fError) { g.drawString(_strError, (cx - _cxString2) / 2, yString); } else if (_fInit) { String strKana = _strKanaTable[_iCurrent], strNew; char acPhonemes[] = strKana.toCharArray(); int cPhonemes = acPhonemes.length, iVowelIndex = _strVowels.indexOf(acPhonemes[cPhonemes - 1]); int yImage = (cy - _iImgSize - _iAscent - _iDescent) / 2 + yOffset; if (cPhonemes <= 2) { // single kana; int xImage = (cx - _iImgSize) / 2; if (iVowelIndex < 0) { // N, Q; g.drawImage((Image)_hashImg.get(strKana), xImage, yImage, this); if (_fInfo) { strNew = getKanaHash(_hashRoman, strKana); g.drawString(strNew, xImage + (_iImgSize - _fm.stringWidth(strNew)) / 2, yImage + _iImgSize + _iAscent); } } else { // ordinary kana; if (!_fInfo) { g.drawImage((Image)_hashImg.get(strKana), xImage, yImage, this); } else { xImage -= _iImgSize * iVowelIndex; for (int iVowel = 0; iVowel < _strVowels.length(); iVowel++) { char cVowel = _strVowels.charAt(iVowel); acPhonemes[cPhonemes - 1] = cVowel; if ((acPhonemes[0] == 'y' && (cVowel == 'i' || cVowel == 'e')) || (acPhonemes[0] == 'w' && cVowel == 'u')) { strNew = String.valueOf(cVowel); } else { strNew = new String(acPhonemes); } g.drawImage((Image)_hashImg.get(strNew), xImage, yImage, this); strNew = getKanaHash(_hashRoman, strNew); g.drawString(strNew, xImage + (_iImgSize - _fm.stringWidth(strNew)) / 2, yImage + _iImgSize + _iAscent); xImage += _iImgSize; } } } } else { // double kana; int xImage = cx / 2 - (iVowelIndex + 1) * _iImgSize; Image image = (Image)_hashImg.get((new StringBuffer()) .append(acPhonemes[0]).append('i').toString()); for (int iVowel = 0; iVowel < _strVowels.length(); iVowel += 2) { if (_fInfo || iVowel == iVowelIndex) { char cVowel = _strVowels.charAt(iVowel); acPhonemes[2] = cVowel; g.drawImage(image, xImage, yImage, this); g.drawImage((Image)_hashImg.get("small y" + cVowel), xImage + _iImgSize, yImage, this); if (_fInfo) { strNew = getKanaHash(_hashRoman, new String(acPhonemes)); g.drawString(strNew, xImage + _iImgSize - _fm.stringWidth(strNew) / 2, yImage + _iImgSize + _iAscent); } } xImage += _iImgSize * 2; } } } else { g.drawString(_strWait, (cx - _cxString1) / 2, yString); } } final static int random() { return (int)(Math.random() * _cKana); } final void next() { if (_fInit) { if (_fInfo) { _iCurrent = random(); } _fInfo = !_fInfo; repaint(); } } final public void keyPressed(KeyEvent ke) { } final public void keyReleased(KeyEvent ke) { } final public void keyTyped(KeyEvent ke) { next(); } final public void mouseClicked(MouseEvent me) { } final public void mouseEntered(MouseEvent me) { } final public void mouseExited(MouseEvent me) { } final public void mousePressed(MouseEvent me) { requestFocus(); next(); } final public void mouseReleased(MouseEvent me) { } final public void itemStateChanged(ItemEvent ie) { String str = (String)ie.getItem(); int iIndex = str.indexOf(','); String strFont = str.substring(0, iIndex); boolean fKata = (str.charAt(iIndex + 2) == 'K'); if (fKata != _fKata || !strFont.equals(_strFont)) { _strFont = strFont; _fKata = fKata; if (_thread != null) { _thread.stop(); } _fInit = _fError = false; (_thread = new Thread(this)).start(); repaint(); } } }