FontPage.java
     1: //========================================================================================
     2: //  FontPage.java
     3: //    en:Font page
     4: //    ja:フォントページ
     5: //  Copyright (C) 2003-2017 Makoto Kamada
     6: //
     7: //  This file is part of the XEiJ (X68000 Emulator in Java).
     8: //  You can use, modify and redistribute the XEiJ if the conditions are met.
     9: //  Read the XEiJ License for more details.
    10: //  http://stdkmd.com/xeij/
    11: //========================================================================================
    12: 
    13: package xeij;
    14: 
    15: import java.awt.*;  //BasicStroke,BorderLayout,BoxLayout,Color,Component,Container,Cursor,Desktop,Dimension,Font,Frame,Graphics,Graphics2D,GraphicsDevice,GraphicsEnvironment,GridLayout,Image,Insets,Paint,Point,Rectangle,RenderingHints,Robot,Shape,Stroke,TexturePaint,Toolkit
    16: import java.awt.font.*;  //FontRenderContext,LineMetrics,TextLayout
    17: import java.awt.geom.*;  //AffineTransform,GeneralPath,Point2D,Rectangle2D
    18: import java.awt.image.*;  //BufferedImage,DataBuffer,DataBufferByte,DataBufferInt,IndexColorModel
    19: import java.lang.*;  //Boolean,Character,Class,Comparable,Double,Exception,Float,IllegalArgumentException,Integer,Long,Math,Number,Object,Runnable,SecurityException,String,StringBuilder,System
    20: import java.util.*;  //ArrayList,Arrays,Calendar,GregorianCalendar,HashMap,Map,Map.Entry,Timer,TimerTask,TreeMap
    21: 
    22: public class FontPage {
    23: 
    24:   //色
    25:   //  1dotあたり2bit使用する
    26:   //  bit0は背景の市松模様
    27:   //  bit1は文字の有無
    28:   private static final int FNP_COLOR_0 = 0x00;  //背景=黒,文字=なし
    29:   private static final int FNP_COLOR_1 = 0x33;  //背景=灰,文字=なし
    30:   private static final int FNP_COLOR_2 = 0xff;  //背景=黒,文字=あり
    31:   private static final int FNP_COLOR_3 = 0xff;  //背景=灰,文字=あり
    32:   private static final byte[] FNP_COLOR_BASE = new byte[] {
    33:     (byte) FNP_COLOR_0,
    34:     (byte) FNP_COLOR_1,
    35:     (byte) FNP_COLOR_2,
    36:     (byte) FNP_COLOR_3,
    37:   };
    38:   private static final Color[] FNP_COLOR_ARRAY = new Color[] {
    39:     new Color (FNP_COLOR_0, FNP_COLOR_0, FNP_COLOR_0),
    40:     new Color (FNP_COLOR_1, FNP_COLOR_1, FNP_COLOR_1),
    41:     new Color (FNP_COLOR_2, FNP_COLOR_2, FNP_COLOR_2),
    42:     new Color (FNP_COLOR_3, FNP_COLOR_3, FNP_COLOR_3),
    43:   };
    44:   //4bitのフォントデータ→4dotのパレットコード
    45:   private static final byte[][] FNP_PALET = {
    46:     //背景=黒黒黒黒
    47:     {
    48:       0b00_00_00_00,
    49:       0b00_00_00_10,
    50:       0b00_00_10_00,
    51:       0b00_00_10_10,
    52:       0b00_10_00_00,
    53:       0b00_10_00_10,
    54:       0b00_10_10_00,
    55:       0b00_10_10_10,
    56:       (byte) 0b10_00_00_00,
    57:       (byte) 0b10_00_00_10,
    58:       (byte) 0b10_00_10_00,
    59:       (byte) 0b10_00_10_10,
    60:       (byte) 0b10_10_00_00,
    61:       (byte) 0b10_10_00_10,
    62:       (byte) 0b10_10_10_00,
    63:       (byte) 0b10_10_10_10,
    64:     },
    65:     //背景=灰灰灰灰
    66:     {
    67:       0b01_01_01_01,
    68:       0b01_01_01_11,
    69:       0b01_01_11_01,
    70:       0b01_01_11_11,
    71:       0b01_11_01_01,
    72:       0b01_11_01_11,
    73:       0b01_11_11_01,
    74:       0b01_11_11_11,
    75:       (byte) 0b11_01_01_01,
    76:       (byte) 0b11_01_01_11,
    77:       (byte) 0b11_01_11_01,
    78:       (byte) 0b11_01_11_11,
    79:       (byte) 0b11_11_01_01,
    80:       (byte) 0b11_11_01_11,
    81:       (byte) 0b11_11_11_01,
    82:       (byte) 0b11_11_11_11,
    83:     },
    84:     //背景=黒黒灰灰
    85:     {
    86:       0b00_00_01_01,
    87:       0b00_00_01_11,
    88:       0b00_00_11_01,
    89:       0b00_00_11_11,
    90:       0b00_10_01_01,
    91:       0b00_10_01_11,
    92:       0b00_10_11_01,
    93:       0b00_10_11_11,
    94:       (byte) 0b10_00_01_01,
    95:       (byte) 0b10_00_01_11,
    96:       (byte) 0b10_00_11_01,
    97:       (byte) 0b10_00_11_11,
    98:       (byte) 0b10_10_01_01,
    99:       (byte) 0b10_10_01_11,
   100:       (byte) 0b10_10_11_01,
   101:       (byte) 0b10_10_11_11,
   102:     },
   103:     //背景=灰灰黒黒
   104:     {
   105:       0b01_01_00_00,
   106:       0b01_01_00_10,
   107:       0b01_01_10_00,
   108:       0b01_01_10_10,
   109:       0b01_11_00_00,
   110:       0b01_11_00_10,
   111:       0b01_11_10_00,
   112:       0b01_11_10_10,
   113:       (byte) 0b11_01_00_00,
   114:       (byte) 0b11_01_00_10,
   115:       (byte) 0b11_01_10_00,
   116:       (byte) 0b11_01_10_10,
   117:       (byte) 0b11_11_00_00,
   118:       (byte) 0b11_11_00_10,
   119:       (byte) 0b11_11_10_00,
   120:       (byte) 0b11_11_10_10,
   121:     },
   122:   };
   123:   //4dotのパレットコード→4bitのフォントデータ
   124:   private static final byte[] FNP_INV_PALET = new byte[256];
   125:   static {
   126:     for (int i = 0; i < 256; i++) {
   127:       FNP_INV_PALET[i] = (byte) (i >> 4 & 8 | i >> 3 & 4 | i >> 2 & 2 | i >> 1 & 1);  //0bP.Q.R.S. → 0b0000PQRS
   128:     }
   129:   }
   130: 
   131:   //インスタンスフィールド
   132:   public int fnpId;  //ID
   133:   public int fnpMask;  //マスク
   134:   public byte[] fnpDataMemory;  //フォントデータのメモリ
   135:   public int fnpDataAddress;  //フォントデータのアドレス
   136:   public boolean fnpReady;  //true=フォントデータが有効
   137:   public int fnpFontWidth;  //フォントの幅
   138:   public int fnpFontHeight;  //フォントの高さ
   139:   public int fnpType;  //種類。FNT_TYPE_ANKまたはFNT_TYPE_KNJまたはFNT_TYPE_PRN
   140:   public String fnpEn;  //ページの名前(英語)
   141:   public String fnpJa;  //ページの名前(日本語)
   142:   public String fnpImageName;  //イメージファイル名
   143:   public String fnpFontName;  //自動生成に使用したホストのフォント名
   144:   public int fnpCols;  //横方向の文字数
   145:   public int fnpRows;  //縦方向の文字数
   146:   public int fnpImageWidth;  //イメージの幅
   147:   public int fnpImageHeight;  //イメージの高さ
   148:   public int fnpImageOffset;  //イメージの1ラスタのバイト数
   149:   public int fnpDataOffset;  //フォントデータの1ラスタのバイト数
   150:   public BufferedImage fnpImageObject;  //イメージ
   151:   public byte[] fnpBitmap;  //ビットマップ
   152: 
   153:   //コンストラクタ
   154:   public FontPage (int id, int mask, byte[] dataMemory, int dataAddress, int fontWidth, int fontHeight, int type) {
   155:     fnpId = id;
   156:     fnpMask = mask;
   157:     fnpDataMemory = dataMemory;
   158:     fnpDataAddress = dataAddress;
   159:     fnpReady = false;
   160:     fnpFontWidth = fontWidth;
   161:     fnpFontHeight = fontHeight;
   162:     fnpType = type;
   163:     fnpEn = FontEditor.FNT_EN_ARRAY[id];
   164:     fnpJa = FontEditor.FNT_JA_ARRAY[id];
   165:     fnpImageName = FontEditor.FNT_FILE_ARRAY[id];
   166:     fnpFontName = null;
   167:     fnpCols = FontEditor.FNT_COLS_ARRAY[type];
   168:     fnpRows = FontEditor.FNT_ROWS_ARRAY[type];
   169:     fnpImageWidth = fontWidth * fnpCols;
   170:     fnpImageHeight = fontHeight * fnpRows;
   171:     fnpImageOffset = fnpImageWidth + 3 >> 2;
   172:     fnpDataOffset = fontWidth + 7 >> 3;
   173:     fnpImageObject = null;
   174:     fnpBitmap = null;
   175:   }
   176: 
   177:   public BufferedImage fnpGetImageObject () {
   178:     if (fnpImageObject == null) {
   179:       fnpMakeImage ();
   180:       fnpMemoryToImage ();
   181:     }
   182:     return fnpImageObject;
   183:   }
   184: 
   185:   private void fnpMakeImage () {
   186:     IndexColorModel m = new IndexColorModel (2, 4, FNP_COLOR_BASE, FNP_COLOR_BASE, FNP_COLOR_BASE);
   187:     fnpImageObject = new BufferedImage (fnpImageWidth, fnpImageHeight, BufferedImage.TYPE_BYTE_BINARY, m);
   188:     fnpBitmap = ((DataBufferByte) fnpImageObject.getRaster ().getDataBuffer ()).getData ();
   189:   }
   190: 
   191:   public byte[] fnpGetDataMemory () {
   192:     if (fnpDataMemory == null) {
   193:       fnpDataMemory = new byte[(fnpFontWidth + 7 >>> 3) * fnpFontHeight * fnpCols * fnpRows];
   194:     }
   195:     return fnpDataMemory;
   196:   }  //fnpGetDataMemory()
   197: 
   198:   public int fnpGetDataAddress () {
   199:     return fnpDataAddress;
   200:   }  //fnpGetDataAddress()
   201: 
   202: 
   203:   //d = fnpGetBit (col, row, x, y)
   204:   //  メモリから1ビットゲットする
   205:   private int fnpGetBit (int col, int row, int x, int y) {
   206:     y += (col + fnpCols * row) * fnpFontHeight;
   207:     y = fnpDataAddress + fnpDataOffset * y + (x >> 3);
   208:     x = ~x & 7;
   209:     return fnpDataMemory[y] >> x & 1;
   210:   }  //fnpGetBit(int,int,int,int)
   211: 
   212:   //fnpSetBit (col, row, x, y, d)
   213:   //  メモリに1ビットセットする
   214:   private void fnpSetBit (int col, int row, int x, int y, int d) {
   215:     y += (col + fnpCols * row) * fnpFontHeight;
   216:     y = fnpDataAddress + fnpDataOffset * y + (x >> 3);
   217:     x = ~x & 7;
   218:     fnpDataMemory[y] = (byte) (fnpDataMemory[y] & ~(1 << x) | (d & 1) << x);
   219:   }  //fnpSetBit(int,int,int,int,int)
   220: 
   221: 
   222:   //d = fnpGetDot (col, row, x, y)
   223:   //  イメージから1ドットゲットする
   224:   private int fnpGetDot (int col, int row, int x, int y) {
   225:     x += fnpFontWidth * col;
   226:     y += fnpFontHeight * row;
   227:     y = fnpImageOffset * y + (x >> 2);
   228:     x = (~x & 3) << 1;
   229:     return fnpBitmap[y] >> x + 1 & 1;
   230:   }  //fnpGetDot(int,int,int,int)
   231: 
   232:   //fnpSetDot (col, row, x, y, d)
   233:   //  イメージに1ドットセットする
   234:   private void fnpSetDot (int col, int row, int x, int y, int d) {
   235:     x += fnpFontWidth * col;
   236:     y += fnpFontHeight * row;
   237:     y = fnpImageOffset * y + (x >> 2);
   238:     x = (~x & 3) << 1;
   239:     fnpBitmap[y] = (byte) (fnpBitmap[y] & ~(3 << x) | ((d & 1) << 1 | (col ^ row) & 1) << x);
   240:   }  //fnpSetDot(int,int,int,int,int)
   241: 
   242: 
   243:   //fnpMemoryToImage ()
   244:   //  メモリからイメージへコピーする
   245:   public void fnpMemoryToImage () {
   246:     byte[] bitmap = fnpBitmap;
   247:     if (bitmap == null) {  //イメージがないときは何もしない
   248:       return;
   249:     }
   250:     byte[] m = fnpGetDataMemory ();
   251:     int a = fnpDataAddress;
   252:     //ROM1.0~ROM1.2のときはIPLROMにあるANK 6x12フォントをCGROMにコピーする
   253:     if (a == FontEditor.FNT_ADDRESS_ANK6X12 && FontEditor.fntANK6X12Address != 0) {
   254:       System.arraycopy (m, FontEditor.fntANK6X12Address, m, FontEditor.FNT_ADDRESS_ANK6X12, 1 * 12 * 254);
   255:     }
   256:     int o = fnpImageOffset;
   257:     int h = fnpFontHeight;
   258:     switch (fnpFontWidth) {
   259:     case 6:
   260:       for (int row = 0; row < fnpRows; row++) {
   261:         for (int col = 0; col < fnpCols; col += 2) {  //2文字ずつ変換する
   262:           //                                          偶数行   奇数行
   263:           byte[] palet0 = FNP_PALET[    row & 1];  //黒黒黒黒 灰灰灰灰
   264:           byte[] palet1 = FNP_PALET[2 | row & 1];  //黒黒灰灰 灰灰黒黒
   265:           byte[] palet2 = FNP_PALET[   ~row & 1];  //灰灰灰灰 黒黒黒黒
   266:           for (int y = 0; y < h; y++) {
   267:             int i = o * (h * row + y) + (6 * col >> 2);  //colは偶数
   268:             //    m[a]    m[a+h]
   269:             //  ABCDEF00 GHIJKL00
   270:             //          t
   271:             //  0000ABCD EFGHIJKL
   272:             //    b[i]    b[i+1]   b[i+2]
   273:             //  A.B.C.D. E.F.G.H. I.J.K.L.
   274:             int t = (m[a] & 253) << 4 | (m[a + h] & 253) >> 2;
   275:             bitmap[i    ] = palet0[t >>  8     ];  //0000ABCD → A.B.C.D.
   276:             bitmap[i + 1] = palet1[t >>  4 & 15];  //0000EFGH → E.F.G.H.
   277:             bitmap[i + 2] = palet2[t       & 15];  //0000IJKL → I.J.K.L.
   278:             a++;
   279:           }
   280:           a += h;
   281:         }
   282:       }
   283:       break;
   284:     case 8:
   285:       for (int row = 0; row < fnpRows; row++) {
   286:         for (int col = 0; col < fnpCols; col++) {
   287:           //                                            偶数マス 奇数マス
   288:           byte[] palet = FNP_PALET[(col ^ row) & 1];  //黒黒黒黒 灰灰灰灰
   289:           for (int y = 0; y < h; y++) {
   290:             int i = o * (h * row + y) + (8 >> 2) * col;
   291:             //    m[a]
   292:             //  ABCDEFGH
   293:             //     t
   294:             //  ABCDEFGH
   295:             //    b[i]    b[i+1]
   296:             //  A.B.C.D. E.F.G.H.
   297:             int t = m[a] & 255;
   298:             bitmap[i    ] = palet[t >>  4     ];
   299:             bitmap[i + 1] = palet[t       & 15];
   300:             a++;
   301:           }
   302:         }
   303:       }
   304:       break;
   305:     case 12:
   306:       for (int row = 0; row < fnpRows; row++) {
   307:         for (int col = 0; col < fnpCols; col++) {
   308:           //                                            偶数マス 奇数マス
   309:           byte[] palet = FNP_PALET[(col ^ row) & 1];  //黒黒黒黒 灰灰灰灰
   310:           for (int y = 0; y < h; y++) {
   311:             int i = o * (h * row + y) + (12 >> 2) * col;
   312:             //    m[a]    m[a+1]
   313:             //  ABCDEFGH IJKL0000
   314:             //          t
   315:             //  ABCDEFGH IJKL0000
   316:             //    b[i]    b[i+1]   b[i+2]
   317:             //  A.B.C.D. E.F.G.H. I.J.K.L.
   318:             int t = (char) (m[a] << 8 | m[a + 1] & 255);
   319:             bitmap[i    ] = palet[t >> 12     ];
   320:             bitmap[i + 1] = palet[t >>  8 & 15];
   321:             bitmap[i + 2] = palet[t >>  4 & 15];
   322:             a += 2;
   323:           }
   324:         }
   325:       }
   326:       break;
   327:     case 16:
   328:       for (int row = 0; row < fnpRows; row++) {
   329:         for (int col = 0; col < fnpCols; col++) {
   330:           //                                            偶数マス 奇数マス
   331:           byte[] palet = FNP_PALET[(col ^ row) & 1];  //黒黒黒黒 灰灰灰灰
   332:           for (int y = 0; y < h; y++) {
   333:             int i = o * (h * row + y) + (16 >> 2) * col;
   334:             //    m[a]    m[a+1]
   335:             //  ABCDEFGH IJKLMNOP
   336:             //          t
   337:             //  ABCDEFGH IJKLMNOP
   338:             //    b[i]    b[i+1]   b[i+2]   b[i+3]
   339:             //  A.B.C.D. E.F.G.H. I.J.K.L. M.N.O.P.
   340:             int t = (char) (m[a] << 8 | m[a + 1] & 255);
   341:             bitmap[i    ] = palet[t >> 12     ];
   342:             bitmap[i + 1] = palet[t >>  8 & 15];
   343:             bitmap[i + 2] = palet[t >>  4 & 15];
   344:             bitmap[i + 3] = palet[t       & 15];
   345:             a += 2;
   346:           }
   347:         }
   348:       }
   349:       break;
   350:     case 24:
   351:       for (int row = 0; row < fnpRows; row++) {
   352:         for (int col = 0; col < fnpCols; col++) {
   353:           //                                            偶数マス 奇数マス
   354:           byte[] palet = FNP_PALET[(col ^ row) & 1];  //黒黒黒黒 灰灰灰灰
   355:           for (int y = 0; y < h; y++) {
   356:             int i = o * (h * row + y) + (24 >> 2) * col;
   357:             //    m[a]    m[a+1]   m[a+2]
   358:             //  ABCDEFGH IJKLMNOP RSTUVWX
   359:             //              t
   360:             //  ABCDEFGH IJKLMNOP RSTUVWX
   361:             //    b[i]    b[i+1]   b[i+2]   b[i+3]   b[i+4]   b[i+5]
   362:             //  A.B.C.D. E.F.G.H. I.J.K.L. M.N.O.P. Q.R.S.T. U.V.W.X.
   363:             int t = (char) (m[a] << 8 | m[a + 1] & 255) << 8 | m[a + 2] & 255;
   364:             bitmap[i    ] = palet[t >> 20     ];
   365:             bitmap[i + 1] = palet[t >> 16 & 15];
   366:             bitmap[i + 2] = palet[t >> 12 & 15];
   367:             bitmap[i + 3] = palet[t >>  8 & 15];
   368:             bitmap[i + 4] = palet[t >>  4 & 15];
   369:             bitmap[i + 5] = palet[t       & 15];
   370:             a += 3;
   371:           }
   372:         }
   373:       }
   374:       break;
   375:     case 32:
   376:       for (int row = 0; row < fnpRows; row++) {
   377:         for (int col = 0; col < fnpCols; col++) {
   378:           //                                            偶数マス 奇数マス
   379:           byte[] palet = FNP_PALET[(col ^ row) & 1];  //黒黒黒黒 灰灰灰灰
   380:           for (int y = 0; y < h; y++) {
   381:             int i = o * (h * row + y) + (32 >> 2) * col;
   382:             int t = m[a] << 24 | (m[a + 1] & 255) << 16 | (char) (m[a + 2] << 8 | m[a + 3] & 255);
   383:             bitmap[i    ] = palet[t >>> 28     ];
   384:             bitmap[i + 1] = palet[t >>> 24 & 15];
   385:             bitmap[i + 2] = palet[t >>> 20 & 15];
   386:             bitmap[i + 3] = palet[t >>> 16 & 15];
   387:             bitmap[i + 4] = palet[t >>> 12 & 15];
   388:             bitmap[i + 5] = palet[t >>>  8 & 15];
   389:             bitmap[i + 6] = palet[t >>>  4 & 15];
   390:             bitmap[i + 7] = palet[t        & 15];
   391:             a += 4;
   392:           }
   393:         }
   394:       }
   395:       break;
   396:     case 48:
   397:       for (int row = 0; row < fnpRows; row++) {
   398:         for (int col = 0; col < fnpCols; col++) {
   399:           //                                            偶数マス 奇数マス
   400:           byte[] palet = FNP_PALET[(col ^ row) & 1];  //黒黒黒黒 灰灰灰灰
   401:           for (int y = 0; y < h; y++) {
   402:             int i = o * (h * row + y) + (48 >> 2) * col;
   403:             int t = m[a] << 24 | (m[a + 1] & 255) << 16 | (char) (m[a + 2] << 8 | m[a + 3] & 255);
   404:             bitmap[i     ] = palet[t >>> 28     ];
   405:             bitmap[i +  1] = palet[t >>> 24 & 15];
   406:             bitmap[i +  2] = palet[t >>> 20 & 15];
   407:             bitmap[i +  3] = palet[t >>> 16 & 15];
   408:             bitmap[i +  4] = palet[t >>> 12 & 15];
   409:             bitmap[i +  5] = palet[t >>>  8 & 15];
   410:             bitmap[i +  6] = palet[t >>>  4 & 15];
   411:             bitmap[i +  7] = palet[t        & 15];
   412:             t = (char) (m[a + 4] << 8 | m[a + 5] & 255);
   413:             bitmap[i +  8] = palet[t >>> 12 & 15];
   414:             bitmap[i +  9] = palet[t >>>  8 & 15];
   415:             bitmap[i + 10] = palet[t >>>  4 & 15];
   416:             bitmap[i + 11] = palet[t        & 15];
   417:             a += 6;
   418:           }
   419:         }
   420:       }
   421:       break;
   422:     default:
   423:       for (int row = 0; row < fnpRows; row++) {
   424:         for (int col = 0; col < fnpCols; col++) {
   425:           for (int y = 0; y < fnpFontHeight; y++) {
   426:             for (int x = 0; x < fnpFontWidth; x++) {
   427:               fnpSetDot (col, row, x, y, fnpGetBit (col, row, x, y));
   428:             }
   429:           }
   430:         }
   431:       }
   432:     }
   433:     fnpReady = true;  //フォントデータが有効
   434:   }
   435: 
   436:   //fnpImageToMemory ()
   437:   //  イメージからメモリへコピーする
   438:   private void fnpImageToMemory () {
   439:     byte[] bitmap = fnpBitmap;
   440:     if (bitmap == null) {  //イメージがないときは何もしない
   441:       return;
   442:     }
   443:     byte[] m = fnpGetDataMemory ();
   444:     int a = fnpDataAddress;
   445:     int o = fnpImageOffset;
   446:     int h = fnpFontHeight;
   447:     switch (fnpFontWidth) {
   448:     case 6:
   449:       for (int row = 0; row < fnpRows; row++) {
   450:         for (int col = 0; col < fnpCols; col += 2) {  //2文字ずつ変換する
   451:           for (int y = 0; y < h; y++) {
   452:             int i = o * (h * row + y) + (6 * col >> 2);
   453:             //    b[i]    b[i+1]   b[i+2]
   454:             //  A.B.C.D. E.F.G.H. I.J.K.L.
   455:             //              t
   456:             //  A.B.C.D. E.F.G.H. I.J.K.L.
   457:             //    m[a]    m[a+h]
   458:             //  ABCDEF00 GHIJKL00
   459:             int t = (char) (bitmap[i] << 8 | bitmap[i + 1] & 255) << 8 | bitmap[i + 2] & 255;
   460:             m[a    ] = (byte) (FNP_INV_PALET[t >> 16      ] << 4 |  //0000ABCD → ABCD0000
   461:                                FNP_INV_PALET[t >>  8 & 240]);       //E.F.0000 → 0000EF00
   462:             m[a + h] = (byte) (FNP_INV_PALET[t >>  4 & 255] << 4 |  //G.H.I.J. → GHIJ0000
   463:                                FNP_INV_PALET[t <<  4 & 240]);       //K.L.0000 → 0000KL00
   464:             a++;
   465:           }
   466:           a += h;
   467:         }
   468:       }
   469:       break;
   470:     case 8:
   471:       for (int row = 0; row < fnpRows; row++) {
   472:         for (int col = 0; col < fnpCols; col++) {
   473:           for (int y = 0; y < h; y++) {
   474:             int i = o * (h * row + y) + (8 >> 2) * col;
   475:             //    b[i]    b[i+1]
   476:             //  A.B.C.D. E.F.G.H.
   477:             //    m[a]
   478:             //  ABCDEFGH
   479:             m[a] = (byte) (FNP_INV_PALET[bitmap[i] & 255] << 4 | FNP_INV_PALET[bitmap[i + 1] & 255]);
   480:             a++;
   481:           }
   482:         }
   483:       }
   484:       break;
   485:     case 12:
   486:       for (int row = 0; row < fnpRows; row++) {
   487:         for (int col = 0; col < fnpCols; col++) {
   488:           for (int y = 0; y < h; y++) {
   489:             int i = o * (h * row + y) + (12 >> 2) * col;
   490:             //    b[i]    b[i+1]   b[i+2]
   491:             //  A.B.C.D. E.F.G.H. I.J.K.L.
   492:             //    m[a]    m[a+1]
   493:             //  ABCDEFGH IJKL0000
   494:             m[a    ] = (byte) (FNP_INV_PALET[bitmap[i    ] & 255] << 4 | FNP_INV_PALET[bitmap[i + 1] & 255]);
   495:             m[a + 1] = (byte) (FNP_INV_PALET[bitmap[i + 2] & 255] << 4);
   496:             a += 2;
   497:           }
   498:         }
   499:       }
   500:       break;
   501:     case 16:
   502:       for (int row = 0; row < fnpRows; row++) {
   503:         for (int col = 0; col < fnpCols; col++) {
   504:           for (int y = 0; y < h; y++) {
   505:             int i = o * (h * row + y) + (16 >> 2) * col;
   506:             //    b[i]    b[i+1]   b[i+2]   b[i+3]
   507:             //  A.B.C.D. E.F.G.H. I.J.K.L. M.N.O.P.
   508:             //    m[a]    m[a+1]
   509:             //  ABCDEFGH IJKLMNOP
   510:             m[a    ] = (byte) (FNP_INV_PALET[bitmap[i    ] & 255] << 4 | FNP_INV_PALET[bitmap[i + 1] & 255]);
   511:             m[a + 1] = (byte) (FNP_INV_PALET[bitmap[i + 2] & 255] << 4 | FNP_INV_PALET[bitmap[i + 3] & 255]);
   512:             a += 2;
   513:           }
   514:         }
   515:       }
   516:       break;
   517:     case 24:
   518:       for (int row = 0; row < fnpRows; row++) {
   519:         for (int col = 0; col < fnpCols; col++) {
   520:           for (int y = 0; y < h; y++) {
   521:             int i = o * (h * row + y) + (24 >> 2) * col;
   522:             //    b[i]    b[i+1]   b[i+2]   b[i+3]   b[i+4]   b[i+5]
   523:             //  A.B.C.D. E.F.G.H. I.J.K.L. M.N.O.P. Q.R.S.T. U.V.W.X.
   524:             //    m[a]    m[a+1]   m[a+2]
   525:             //  ABCDEFGH IJKLMNOP RSTUVWX
   526:             m[a    ] = (byte) (FNP_INV_PALET[bitmap[i    ] & 255] << 4 | FNP_INV_PALET[bitmap[i + 1] & 255]);
   527:             m[a + 1] = (byte) (FNP_INV_PALET[bitmap[i + 2] & 255] << 4 | FNP_INV_PALET[bitmap[i + 3] & 255]);
   528:             m[a + 2] = (byte) (FNP_INV_PALET[bitmap[i + 4] & 255] << 4 | FNP_INV_PALET[bitmap[i + 5] & 255]);
   529:             a += 3;
   530:           }
   531:         }
   532:       }
   533:       break;
   534:     case 32:
   535:       for (int row = 0; row < fnpRows; row++) {
   536:         for (int col = 0; col < fnpCols; col++) {
   537:           for (int y = 0; y < h; y++) {
   538:             int i = o * (h * row + y) + (32 >> 2) * col;
   539:             m[a    ] = (byte) (FNP_INV_PALET[bitmap[i    ] & 255] << 4 | FNP_INV_PALET[bitmap[i + 1] & 255]);
   540:             m[a + 1] = (byte) (FNP_INV_PALET[bitmap[i + 2] & 255] << 4 | FNP_INV_PALET[bitmap[i + 3] & 255]);
   541:             m[a + 2] = (byte) (FNP_INV_PALET[bitmap[i + 4] & 255] << 4 | FNP_INV_PALET[bitmap[i + 5] & 255]);
   542:             m[a + 3] = (byte) (FNP_INV_PALET[bitmap[i + 6] & 255] << 4 | FNP_INV_PALET[bitmap[i + 7] & 255]);
   543:             a += 4;
   544:           }
   545:         }
   546:       }
   547:       break;
   548:     case 48:
   549:       for (int row = 0; row < fnpRows; row++) {
   550:         for (int col = 0; col < fnpCols; col++) {
   551:           for (int y = 0; y < h; y++) {
   552:             int i = o * (h * row + y) + (48 >> 2) * col;
   553:             m[a    ] = (byte) (FNP_INV_PALET[bitmap[i     ] & 255] << 4 | FNP_INV_PALET[bitmap[i +  1] & 255]);
   554:             m[a + 1] = (byte) (FNP_INV_PALET[bitmap[i +  2] & 255] << 4 | FNP_INV_PALET[bitmap[i +  3] & 255]);
   555:             m[a + 2] = (byte) (FNP_INV_PALET[bitmap[i +  4] & 255] << 4 | FNP_INV_PALET[bitmap[i +  5] & 255]);
   556:             m[a + 3] = (byte) (FNP_INV_PALET[bitmap[i +  6] & 255] << 4 | FNP_INV_PALET[bitmap[i +  7] & 255]);
   557:             m[a + 4] = (byte) (FNP_INV_PALET[bitmap[i +  8] & 255] << 4 | FNP_INV_PALET[bitmap[i +  9] & 255]);
   558:             m[a + 5] = (byte) (FNP_INV_PALET[bitmap[i + 10] & 255] << 4 | FNP_INV_PALET[bitmap[i + 11] & 255]);
   559:             a += 6;
   560:           }
   561:         }
   562:       }
   563:       break;
   564:     default:
   565:       for (int row = 0; row < fnpRows; row++) {
   566:         for (int col = 0; col < fnpCols; col++) {
   567:           for (int y = 0; y < fnpFontHeight; y++) {
   568:             for (int x = 0; x < fnpFontWidth; x++) {
   569:               fnpSetBit (col, row, x, y, fnpGetDot (col, row, x, y));
   570:             }
   571:           }
   572:         }
   573:       }
   574:     }
   575:     //ROM1.0~ROM1.2のときはCGROMにあるANK 6x12フォントをIPLROMにコピーする
   576:     if (fnpDataAddress == FontEditor.FNT_ADDRESS_ANK6X12 && FontEditor.fntANK6X12Address != 0) {
   577:       System.arraycopy (m, FontEditor.FNT_ADDRESS_ANK6X12, m, FontEditor.fntANK6X12Address, 1 * 12 * 254);
   578:     }
   579:     fnpReady = true;  //フォントデータが有効
   580:   }
   581: 
   582:   //fnpGenerate (fontName)
   583:   //  ホストのフォントを使ってCGROMを作る
   584:   public void fnpGenerate (String fontName) {
   585:     //開始
   586:     XEiJ.prgMessage (Multilingual.mlnJapanese ?
   587:                      fontName + " を使って " + fnpFontWidth + "x" + fnpFontHeight + " " + (fnpType == FontEditor.FNT_TYPE_KNJ ? "漢字" : "ANK ") + "フォントを作ります" :
   588:                      "Creating " + fnpFontWidth + "x" + fnpFontHeight + " " + (fnpType == FontEditor.FNT_TYPE_KNJ ? "Kanji" : "ANK") + " font using " + fontName);
   589:     long startTime = System.currentTimeMillis ();
   590:     //フォント
   591:     fnpFontName = fontName;
   592:     Font font = new Font (fontName, Font.PLAIN, fnpFontHeight);
   593:     double fw = (double) fnpFontWidth;
   594:     double fh = (double) fnpFontHeight;
   595:     //文字テーブル
   596:     char[][] tableArray = FontEditor.FNT_TABLE_ARRAY_ARRAY[fnpId];
   597:     int numberOfTable = tableArray.length;  //文字のテーブルの数
   598:     int lastTableIndex = -1;  //最後に描いた文字の文字テーブルの番号
   599:     double px = 0.0;
   600:     double py = 0.0;
   601:     double pw = 0.0;
   602:     double ph = 0.0;
   603:     //イメージ
   604:     Graphics2D g2 = (Graphics2D) fnpGetImageObject ().getGraphics ();
   605:     FontRenderContext frc = g2.getFontRenderContext ();
   606:     //背景を黒で塗り潰す
   607:     byte[] bitmap = fnpBitmap;
   608:     Arrays.fill (bitmap, 0, fnpImageOffset * fnpImageHeight, (byte) 0);
   609:     //白い文字を描く
   610:     g2.setColor (FNP_COLOR_ARRAY[2]);
   611:     g2.setFont (font);
   612:     //アフィン変換を保存する
   613:     AffineTransform savedTransform = g2.getTransform ();
   614:     //クリッピング領域を保存する
   615:     Shape savedClip = g2.getClip ();
   616:     //行ループ
   617:     for (int row = 0; row < fnpRows; row++) {
   618:       int gy = fnpFontHeight * row;  //イメージ内y座標
   619:       //列ループ
   620:     col:
   621:       for (int col = 0; col < fnpCols; col++) {
   622:         int gx = fnpFontWidth * col;  //イメージ内x座標
   623:         //クリッピング領域を設定する
   624:         //  クリッピングしないと1ドットはみ出すことがある
   625:         g2.setClip (null);
   626:         g2.clipRect (gx, gy, fnpFontWidth, fnpFontHeight);
   627:         //描く文字を決める
   628:         //  最初の文字テーブルでは空白でも次の文字テーブルでは空白でない場合があるので、
   629:         //  空白が出てきても最後の文字テーブルまでループさせること
   630:         char[] table;  //選択したテーブル
   631:         String s;  //文字
   632:         char c;  //文字の先頭
   633:         int tableIndex = -1;  //文字テーブルの番号
   634:         do {
   635:           if (++tableIndex == numberOfTable) {  //どの文字テーブルの文字も描けない
   636:             continue col;
   637:           }
   638:           table = tableArray[tableIndex];
   639:           int i = col + fnpCols * row;
   640:           if (table[1] != '\0') {  //1文字構成
   641:             s = new String (table, i, 1);
   642:           } else {  //2文字構成
   643:             i <<= 1;
   644:             if (table[i + 1] == '\0') {  //1文字
   645:               s = new String (table, i, 1);
   646:             } else {  //2文字
   647:               s = new String (table, i, 2);
   648:             }
   649:           }
   650:           c = s.charAt (0);
   651:           //特殊記号を描く
   652:           int t;
   653:           switch (c) {
   654:           case '\u2571':  //U+2571  BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT
   655:             g2.setStroke (new BasicStroke ());
   656:             g2.drawLine (gx + fnpFontWidth - 1, gy, gx, gy + fnpFontHeight - 1);
   657:             continue col;
   658:           case '\u2572':  //U+2572  BOX DRAWINGS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT
   659:             g2.setStroke (new BasicStroke ());
   660:             g2.drawLine (gx, gy, gx + fnpFontWidth - 1, gy + fnpFontHeight - 1);
   661:             continue col;
   662:           case '\u2573':  //U+2573  BOX DRAWINGS LIGHT DIAGONAL CROSS
   663:             g2.setStroke (new BasicStroke ());
   664:             g2.drawLine (gx, gy, gx + fnpFontWidth - 1, gy + fnpFontHeight - 1);
   665:             g2.drawLine (gx + fnpFontWidth - 1, gy, gx, gy + fnpFontHeight - 1);
   666:             continue col;
   667:           case '\u2581':  //U+2581  LOWER ONE EIGHTH BLOCK
   668:             t = fnpFontHeight + 4 >> 3;
   669:             g2.fillRect (gx, gy + fnpFontHeight - t, fnpFontWidth, t);
   670:             continue col;
   671:           case '\u2582':  //U+2582  LOWER ONE QUARTER BLOCK
   672:             t = fnpFontHeight * 2 + 4 >> 3;
   673:             g2.fillRect (gx, gy + fnpFontHeight - t, fnpFontWidth, t);
   674:             continue col;
   675:           case '\u2583':  //U+2583  LOWER THREE EIGHTHS BLOCK
   676:             t = fnpFontHeight * 3 + 4 >> 3;
   677:             g2.fillRect (gx, gy + fnpFontHeight - t, fnpFontWidth, t);
   678:             continue col;
   679:           case '\u2584':  //U+2584  LOWER HALF BLOCK
   680:             t = fnpFontHeight * 4 + 4 >> 3;
   681:             g2.fillRect (gx, gy + fnpFontHeight - t, fnpFontWidth, t);
   682:             continue col;
   683:           case '\u2585':  //U+2585  LOWER FIVE EIGHTHS BLOCK
   684:             t = fnpFontHeight * 5 + 4 >> 3;
   685:             g2.fillRect (gx, gy + fnpFontHeight - t, fnpFontWidth, t);
   686:             continue col;
   687:           case '\u2586':  //U+2586  LOWER THREE QUARTERS BLOCK
   688:             t = fnpFontHeight * 6 + 4 >> 3;
   689:             g2.fillRect (gx, gy + fnpFontHeight - t, fnpFontWidth, t);
   690:             continue col;
   691:           case '\u2587':  //U+2587  LOWER SEVEN EIGHTHS BLOCK
   692:             t = fnpFontHeight * 7 + 4 >> 3;
   693:             g2.fillRect (gx, gy + fnpFontHeight - t, fnpFontWidth, t);
   694:             continue col;
   695:           case '\u2588':  //U+2588  FULL BLOCK
   696:             g2.fillRect (gx, gy, fnpFontWidth, fnpFontHeight);
   697:             continue col;
   698:           case '\u2589':  //U+2589  LEFT SEVEN EIGHTHS BLOCK
   699:             t = fnpFontWidth * 7 + 4 >> 3;
   700:             g2.fillRect (gx, gy, t, fnpFontHeight);
   701:             continue col;
   702:           case '\u258a':  //U+258A  LEFT THREE QUARTERS BLOCK
   703:             t = fnpFontWidth * 6 + 4 >> 3;
   704:             g2.fillRect (gx, gy, t, fnpFontHeight);
   705:             continue col;
   706:           case '\u258b':  //U+258B  LEFT FIVE EIGHTHS BLOCK
   707:             t = fnpFontWidth * 5 + 4 >> 3;
   708:             g2.fillRect (gx, gy, t, fnpFontHeight);
   709:             continue col;
   710:           case '\u258c':  //U+258C  LEFT HALF BLOCK
   711:             t = fnpFontWidth * 4 + 4 >> 3;
   712:             g2.fillRect (gx, gy, t, fnpFontHeight);
   713:             continue col;
   714:           case '\u258d':  //U+258D  LEFT THREE EIGHTHS BLOCK
   715:             t = fnpFontWidth * 3 + 4 >> 3;
   716:             g2.fillRect (gx, gy, t, fnpFontHeight);
   717:             continue col;
   718:           case '\u258e':  //U+258E  LEFT ONE QUARTER BLOCK
   719:             t = fnpFontWidth * 2 + 4 >> 3;
   720:             g2.fillRect (gx, gy, t, fnpFontHeight);
   721:             continue col;
   722:           case '\u258f':  //U+258F  LEFT ONE EIGHTH BLOCK
   723:             t = fnpFontWidth + 4 >> 3;
   724:             g2.fillRect (gx, gy, t, fnpFontHeight);
   725:             continue col;
   726:           case '\u2593':  //U+2593  DARK SHADE
   727:             for (int v = 0; v < fnpFontHeight; v++) {
   728:               for (int u = 0; u < fnpFontWidth; u++) {
   729:                 if (((u ^ v) & 1) == 0) {
   730:                   g2.fillRect (gx + u, gy + v, 1, 1);
   731:                 }
   732:               }
   733:             }
   734:             continue col;
   735:           case '\u2596':  //U+2596  QUADRANT LOWER LEFT
   736:             g2.fillRect (gx, gy + (fnpFontHeight >> 1), fnpFontWidth >> 1, fnpFontHeight >> 1);
   737:             continue col;
   738:           case '\u2597':  //U+2597  QUADRANT LOWER RIGHT
   739:             g2.fillRect (gx + (fnpFontWidth >> 1), gy + (fnpFontHeight >> 1), fnpFontWidth >> 1, fnpFontHeight >> 1);
   740:             continue col;
   741:           case '\u2598':  //U+2598  QUADRANT UPPER LEFT
   742:             g2.fillRect (gx, gy, fnpFontWidth >> 1, fnpFontHeight >> 1);
   743:             continue col;
   744:           case '\u259a':  //U+259A  QUADRANT UPPER LEFT AND LOWER RIGHT
   745:             g2.fillRect (gx, gy, fnpFontWidth >> 1, fnpFontHeight >> 1);
   746:             g2.fillRect (gx + (fnpFontWidth >> 1), gy + (fnpFontHeight >> 1), fnpFontWidth >> 1, fnpFontHeight >> 1);
   747:             continue col;
   748:           case '\u259d':  //U+259D  QUADRANT UPPER RIGHT
   749:             g2.fillRect (gx + (fnpFontWidth >> 1), gy, fnpFontWidth >> 1, fnpFontHeight >> 1);
   750:             continue col;
   751:           case '\u259e':  //U+259E  QUADRANT UPPER RIGHT AND LOWER LEFT
   752:             g2.fillRect (gx + (fnpFontWidth >> 1), gy, fnpFontWidth >> 1, fnpFontHeight >> 1);
   753:             g2.fillRect (gx, gy + (fnpFontHeight >> 1), fnpFontWidth >> 1, fnpFontHeight >> 1);
   754:             continue col;
   755: /*
   756:           case '\u25a1':  //U+25A1  WHITE SQUARE
   757:             g2.drawRect (gx, gy, fnpFontWidth - 1, fnpFontHeight - 1);
   758:             continue col;
   759: */
   760:           case '\u25e2':  //U+25E2  BLACK LOWER RIGHT TRIANGLE
   761:             g2.setStroke (new BasicStroke ());
   762:             if (fnpFontWidth <= fnpFontHeight) {  //縦長
   763:               for (int v = 0; v <= fnpFontHeight - 1; v++) {
   764:                 int u = v * (fnpFontWidth - 1) / (fnpFontHeight - 1);
   765:                 g2.drawLine (gx + fnpFontWidth - 1 - u, gy + v, gx + fnpFontWidth - 1, gy + v);  //横線
   766:               }
   767:             } else {  //横長
   768:               for (int u = 0; u <= fnpFontWidth - 1; u++) {
   769:                 int v = u * (fnpFontHeight - 1) / (fnpFontWidth - 1);
   770:                 g2.drawLine (gx + u, gy + fnpFontHeight - 1 - v, gx + u, gy + fnpFontHeight - 1);  //縦線
   771:               }
   772:             }
   773:             continue col;
   774:           case '\u25e3':  //U+25E3  BLACK LOWER LEFT TRIANGLE
   775:             g2.setStroke (new BasicStroke ());
   776:             if (fnpFontWidth <= fnpFontHeight) {  //縦長
   777:               for (int v = 0; v <= fnpFontHeight - 1; v++) {
   778:                 int u = v * (fnpFontWidth - 1) / (fnpFontHeight - 1);
   779:                 g2.drawLine (gx, gy + v, gx + u, gy + v);  //横線
   780:               }
   781:             } else {  //横長
   782:               for (int u = 0; u <= fnpFontWidth - 1; u++) {
   783:                 int v = u * (fnpFontHeight - 1) / (fnpFontWidth - 1);
   784:                 g2.drawLine (gx + u, gy + v, gx + u, gy + fnpFontHeight - 1);  //縦線
   785:               }
   786:             }
   787:             continue col;
   788:           }
   789:         } while (c == ' ' || c == ' ' || font.canDisplayUpTo (s) != -1);  //空白または描けないときは次の文字テーブルへ
   790:         //フォントの枠を決める
   791:         //  半角はFULL BLOCK、全角は罫線の十字のレクタングルを基準にする
   792:         if (lastTableIndex != tableIndex) {
   793:           lastTableIndex = tableIndex;
   794:           Rectangle2D p = new TextLayout (table[0] < 0x80 ? "\u2588" : "┼", font, g2.getFontRenderContext ()).getBounds ();
   795:           px = p.getX ();
   796:           py = p.getY ();
   797:           pw = p.getWidth ();
   798:           ph = p.getHeight ();
   799:         }
   800:         //今回の文字のレクタングルを求める
   801:         Rectangle2D q = new TextLayout (s, font, g2.getFontRenderContext ()).getBounds ();
   802:         double qx = q.getX ();
   803:         double qy = q.getY ();
   804:         double qw = q.getWidth ();
   805:         double qh = q.getHeight ();
   806:         //  x=sx*x+tx
   807:         //  y=sy*y+ty
   808:         double sx = 1.0;
   809:         double sy = 1.0;
   810:         double tx = 0.0;
   811:         double ty = 0.0;
   812:         //{px,py,pw,ph}から{0,0,pw,ph}へ移動する
   813:         //  x=(sx*x+tx)-px
   814:         //   =sx*x+(tx-px)
   815:         //  y=(sy*y+ty)-py
   816:         //   =sy*y+(ty-py)
   817:         qx -= px;
   818:         qy -= py;
   819:         tx -= px;
   820:         ty -= py;
   821:         //{qx,qy,qw,qh}が{0,0,pw,ph}に収まるようにする
   822:         //  既に収まっているときは中央になくても動かしてはならない
   823:         if (pw < qw) {  //幅が大きすぎるので水平方向に縮小してずらす
   824:           //  x=((sx*x+tx)-qx)*pw/qw
   825:           //   =sx*pw/qw*x+(tx-qx)*pw/qw
   826:           double r = pw / qw;
   827:           sx *= r;
   828:           tx = (tx - qx) * r;
   829:         } else if (qx < 0) {  //左にはみ出しているので右にずらす
   830:           //  x=(sx*x+tx)-qx
   831:           //   =sx*x+(tx-qx)
   832:           tx -= qx;
   833:         } else if (pw < qx + qw) {  //右にはみ出しているので左にずらす
   834:           //  x=(sx*x+tx)-(qx+qw-pw)
   835:           //   =sx*x+(tx-(qx+qw-pw))
   836:           tx -= qx + qw - pw;
   837:         }
   838:         if (ph < qh) {  //高さが大きすぎるので垂直方向に縮小してずらす
   839:           //  y=((sy*y+ty)-qy)*ph/qh
   840:           //   =sy*ph/qh*y+(ty-qy)*ph/qh
   841:           double r = ph / qh;
   842:           sy *= r;
   843:           ty = (ty - qy) * r;
   844:         } else if (qy < 0) {  //上にはみ出しているので下にずらす
   845:           //  y=(sy*y+ty)-qy
   846:           //   =sy*y+(ty-qy)
   847:           ty -= qy;
   848:         } else if (ph < qy + qh) {  //下にはみ出しているので上にずらす
   849:           //  y=(sy*y+ty)-(qy+qh-ph)
   850:           //   =sy*y+(ty-(qy+qh-ph))
   851:           ty -= qy + qh - ph;
   852:         }
   853:         //{0,0,pw,ph}を{fw*col,fh*row,fw,fh}に拡大してずらす
   854:         //  x=(sx*x+tx)*fw/pw+fw*col
   855:         //   =(sx*fw/pw)*x+(tx*fw/pw+fw*col)
   856:         //  y=(sy*y+ty)*fh/ph+fh*row
   857:         //   =(sy*fh/ph)*y+(ty*fh/ph+fh*row)
   858:         {
   859:           double r = fw / pw;
   860:           sx *= r;
   861:           tx = tx * r + fw * (double) col;
   862:         }
   863:         {
   864:           double r = fh / ph;
   865:           sy *= r;
   866:           ty = ty * r + fh * (double) row;
   867:         }
   868:         //アフィン変換を設定する
   869:         g2.translate (tx, ty);
   870:         g2.scale (sx, sy);
   871:         //フォントを描く
   872:         g2.drawString (s, 0, 0);
   873:         //アフィン変換を復元する
   874:         g2.setTransform (savedTransform);
   875:       }  //for col
   876:     }  //for row
   877:     //クリッピング領域を復元する
   878:     g2.setClip (savedClip);
   879:     //背景を市松模様に塗る
   880:     //  フォントが枠からはみ出していないか確認できる
   881:     int o = fnpImageOffset;
   882:     int w = fnpFontWidth;
   883:     int h = fnpFontHeight;
   884:     switch (fnpFontWidth) {
   885:     case 6:
   886:       for (int row = 0; row < fnpRows; row++) {
   887:         for (int col = 0; col < fnpCols; col += 2) {  //2文字ずつ変換する
   888:           //                                       偶数行   奇数行
   889:           byte p0 = FNP_PALET[    row & 1][0];  //黒黒黒黒 灰灰灰灰
   890:           byte p1 = FNP_PALET[2 | row & 1][0];  //黒黒灰灰 灰灰黒黒
   891:           byte p2 = FNP_PALET[   ~row & 1][0];  //灰灰灰灰 黒黒黒黒
   892:           for (int y = 0; y < h; y++) {
   893:             int i = o * (h * row + y) + (6 * col >> 2);
   894:             bitmap[i    ] |= p0;
   895:             bitmap[i + 1] |= p1;
   896:             bitmap[i + 2] |= p2;
   897:           }
   898:         }
   899:       }
   900:       break;
   901:     case 8:
   902:       for (int row = 0; row < fnpRows; row++) {
   903:         for (int col = 0; col < fnpCols; col++) {
   904:           //                                         偶数マス 奇数マス
   905:           byte p = FNP_PALET[(col ^ row) & 1][0];  //黒黒黒黒 灰灰灰灰
   906:           for (int y = 0; y < h; y++) {
   907:             int i = o * (h * row + y) + (8 >> 2) * col;
   908:             bitmap[i    ] |= p;
   909:             bitmap[i + 1] |= p;
   910:           }
   911:         }
   912:       }
   913:       break;
   914:     case 12:
   915:       for (int row = 0; row < fnpRows; row++) {
   916:         for (int col = 0; col < fnpCols; col++) {
   917:           //                                         偶数マス 奇数マス
   918:           byte p = FNP_PALET[(col ^ row) & 1][0];  //黒黒黒黒 灰灰灰灰
   919:           for (int y = 0; y < h; y++) {
   920:             int i = o * (h * row + y) + (12 >> 2) * col;
   921:             bitmap[i    ] |= p;
   922:             bitmap[i + 1] |= p;
   923:             bitmap[i + 2] |= p;
   924:           }
   925:         }
   926:       }
   927:       break;
   928:     case 16:
   929:       for (int row = 0; row < fnpRows; row++) {
   930:         for (int col = 0; col < fnpCols; col++) {
   931:           //                                         偶数マス 奇数マス
   932:           byte p = FNP_PALET[(col ^ row) & 1][0];  //黒黒黒黒 灰灰灰灰
   933:           for (int y = 0; y < h; y++) {
   934:             int i = o * (h * row + y) + (16 >> 2) * col;
   935:             bitmap[i    ] |= p;
   936:             bitmap[i + 1] |= p;
   937:             bitmap[i + 2] |= p;
   938:             bitmap[i + 3] |= p;
   939:           }
   940:         }
   941:       }
   942:       break;
   943:     case 24:
   944:       for (int row = 0; row < fnpRows; row++) {
   945:         for (int col = 0; col < fnpCols; col++) {
   946:           //                                         偶数マス 奇数マス
   947:           byte p = FNP_PALET[(col ^ row) & 1][0];  //黒黒黒黒 灰灰灰灰
   948:           for (int y = 0; y < h; y++) {
   949:             int i = o * (h * row + y) + (24 >> 2) * col;
   950:             bitmap[i    ] |= p;
   951:             bitmap[i + 1] |= p;
   952:             bitmap[i + 2] |= p;
   953:             bitmap[i + 3] |= p;
   954:             bitmap[i + 4] |= p;
   955:             bitmap[i + 5] |= p;
   956:           }
   957:         }
   958:       }
   959:       break;
   960:     case 32:
   961:       for (int row = 0; row < fnpRows; row++) {
   962:         for (int col = 0; col < fnpCols; col++) {
   963:           //                                         偶数マス 奇数マス
   964:           byte p = FNP_PALET[(col ^ row) & 1][0];  //黒黒黒黒 灰灰灰灰
   965:           for (int y = 0; y < h; y++) {
   966:             int i = o * (h * row + y) + (32 >> 2) * col;
   967:             bitmap[i    ] |= p;
   968:             bitmap[i + 1] |= p;
   969:             bitmap[i + 2] |= p;
   970:             bitmap[i + 3] |= p;
   971:             bitmap[i + 4] |= p;
   972:             bitmap[i + 5] |= p;
   973:             bitmap[i + 6] |= p;
   974:             bitmap[i + 7] |= p;
   975:           }
   976:         }
   977:       }
   978:       break;
   979:     case 48:
   980:       for (int row = 0; row < fnpRows; row++) {
   981:         for (int col = 0; col < fnpCols; col++) {
   982:           //                                         偶数マス 奇数マス
   983:           byte p = FNP_PALET[(col ^ row) & 1][0];  //黒黒黒黒 灰灰灰灰
   984:           for (int y = 0; y < h; y++) {
   985:             int i = o * (h * row + y) + (48 >> 2) * col;
   986:             bitmap[i     ] |= p;
   987:             bitmap[i +  1] |= p;
   988:             bitmap[i +  2] |= p;
   989:             bitmap[i +  3] |= p;
   990:             bitmap[i +  4] |= p;
   991:             bitmap[i +  5] |= p;
   992:             bitmap[i +  6] |= p;
   993:             bitmap[i +  7] |= p;
   994:             bitmap[i +  8] |= p;
   995:             bitmap[i +  9] |= p;
   996:             bitmap[i + 10] |= p;
   997:             bitmap[i + 11] |= p;
   998:           }
   999:         }
  1000:       }
  1001:       break;
  1002:     default:
  1003:       for (int row = 0; row < fnpRows; row++) {
  1004:         for (int col = 0; col < fnpCols; col++) {
  1005:           for (int y = 0; y < fnpFontHeight; y++) {
  1006:             for (int x = 0; x < fnpFontWidth; x++) {
  1007:               fnpSetDot (col, row, x, y, fnpGetDot (col, row, x, y));
  1008:             }
  1009:           }
  1010:         }
  1011:       }
  1012:     }
  1013:     //イメージからメモリへコピーする
  1014:     fnpImageToMemory ();
  1015:     //終了
  1016:     long elapsedTime = System.currentTimeMillis () - startTime;
  1017:     //if (1000L <= elapsedTime) {
  1018:     XEiJ.prgMessage (elapsedTime + "ms");
  1019:     //}
  1020:   }
  1021: 
  1022:   //fnpInputImage ()
  1023:   //  イメージファイルを読み込む
  1024:   //  画像ファイルをROMのデータに変換するだけでここでは表示および出力用のイメージは作らない
  1025:   //  画像ファイルのフォーマットの違いを吸収する必要がある
  1026:   //  初期化のときにも使う
  1027: 
  1028:   //fnpEditPixel (x, y, mode)
  1029:   //  イメージの指定されたピクセルを編集する。CGROMも更新する
  1030:   public void fnpEditPixel (int x, int y, int mode) {
  1031:     if (FontEditor.fntEditX == x && FontEditor.fntEditY == y) {
  1032:       return;
  1033:     }
  1034:     FontEditor.fntEditX = x;
  1035:     FontEditor.fntEditY = y;
  1036:     if (x < 0 || fnpImageWidth <= x ||
  1037:         y < 0 || fnpImageHeight <= y) {
  1038:       return;
  1039:     }
  1040:     int i = fnpImageOffset * y + (x >> 2);  //ビットマップのインデックス
  1041:     int m = 2 << ((~x & 3) << 1);  //ビットマップのマスク
  1042:     int col = x / fnpFontWidth;  //桁
  1043:     int row = y / fnpFontHeight;  //行
  1044:     x -= fnpFontWidth * col;  //フォント内のx座標
  1045:     y -= fnpFontHeight * row;  //フォント内のy座標
  1046:     int a = fnpDataAddress + fnpDataOffset * fnpFontHeight * (fnpCols * row + col) + fnpDataOffset * y + (x >> 3);  //フォントデータのアドレス
  1047:     int d = 1 << (~x & 7);  //フォントデータのマスク
  1048:     if (mode == FontEditor.FNT_MODE_PENCIL) {
  1049:       fnpBitmap[i] |= m;  //セット
  1050:       fnpDataMemory[a] |= d;  //セット
  1051:     } else if (mode == FontEditor.FNT_MODE_ERASER) {
  1052:       fnpBitmap[i] &= ~m;  //クリア
  1053:       fnpDataMemory[a] &= ~d;  //クリア
  1054:     } else {
  1055:       fnpBitmap[i] ^= m;  //反転
  1056:       fnpDataMemory[a] ^= d;  //反転
  1057:     }
  1058:     FontEditor.fntCanvas.repaint ();
  1059:   }
  1060: 
  1061:   //string = fnpStatusText (x, y)
  1062:   //  イメージの指定されたピクセルの情報を文字列で返す
  1063:   public String fnpStatusText (int x, int y) {
  1064:     if (x < 0 || fnpImageWidth <= x || y < 0 || fnpImageHeight <= y) {
  1065:       return "";
  1066:     }
  1067:     StringBuilder sb = new StringBuilder ();
  1068:     int col = x / fnpFontWidth;  //桁
  1069:     int row = y / fnpFontHeight;  //行
  1070:     x -= fnpFontWidth * col;  //フォント内のx座標
  1071:     y -= fnpFontHeight * row;  //フォント内のy座標
  1072:     int a = fnpDataAddress + fnpDataOffset * fnpFontHeight * (fnpCols * row + col) + fnpDataOffset * y + (x >> 3);  //フォントデータのアドレス
  1073:     int b = ~x & 7;  //フォントデータのビット位置
  1074:     XEiJ.fmtHex8 (sb.append (' '), a).append (':').append (b).append (' ').append (fnpDataMemory[a] >> b & 1);
  1075:     return sb.toString ();
  1076:   }
  1077: 
  1078: }  //class FontPage
  1079: 
  1080: 
  1081: