0001 import com.nttdocomo.ui.Canvas;
0002 import com.nttdocomo.ui.Dialog;
0003 import com.nttdocomo.ui.Display;
0004 import com.nttdocomo.ui.Font;
0005 import com.nttdocomo.ui.Graphics;
0006 import com.nttdocomo.ui.IApplication;
0007 import com.nttdocomo.ui.Image;
0008 import com.nttdocomo.ui.MediaImage;
0009 import com.nttdocomo.ui.MediaManager;
0010 import com.nttdocomo.ui.PhoneSystem;
0011
0012 // レジューム処理の動作確認用アプリ。問題が起きる版。
0013
0014 /**
0015 * @author mieki256
0016 */
0017 public class ResumeTest extends IApplication {
0018
0019 Main l_main = new Main();
0020
0021 public void start() {
0022
0023 Display.setCurrent(l_main);
0024 l_main.exec();
0025 }
0026
0027 public void resume() {
0028
0029 // 実処理クラスが復帰して、リジューム用処理が呼び出せるようになるまで繰り返す
0030 while (l_main == null) {
0031 Thread.yield();
0032 }
0033 l_main.resumeJobEnable = true;
0034 l_main.mcResume();
0035 }
0036 }
0037
0038 /**
0039 * 実処理
0040 *
0041 */
0042 final class Main extends Canvas {
0043
0044 /**
0045 * リジューム処理実行中フラグ
0046 */
0047 public boolean resumeJobEnable;
0048
0049 /**
0050 * ProcessEvent実行中フラグ
0051 */
0052 boolean processEventJobEnable;
0053
0054 /**
0055 * FPS。1秒間に何回画面を書き換えるか
0056 */
0057 static final int FPS = 25;
0058
0059 /**
0060 * 1ループのwait時間。FPSから算出。
0061 */
0062 static final int SLEEP_VALUE = 1000 / FPS;
0063
0064 /**
0065 * アプリ画面横幅
0066 */
0067 static final int SCREEN_W = 240;
0068
0069 /**
0070 * アプリ画面縦幅
0071 */
0072 static final int SCREEN_H = 240;
0073
0074 /**
0075 * リピートボタン情報
0076 */
0077 private int c_repbtn;
0078
0079 /**
0080 * トリガボタン情報
0081 */
0082 private int trgBtn;
0083
0084 /**
0085 * 割り込みにより記録されたボタン情報
0086 */
0087 private int keyBtnInterrupt;
0088
0089 /**
0090 * 一意の値(同時押しを無効)にしたトリガボタン情報
0091 */
0092 private int trgBtnUniq;
0093
0094 /**
0095 * キー情報取得をしない状態を指定するための時間カウンタ
0096 */
0097 private int keyNoCheckEnableCount;
0098
0099 /**
0100 * キートリガチェック時の待ちフレーム数。
0101 * <p>
0102 * 各シーンの切り替わり時などで、念のために、多少なりともwaitを入れてからトリガをチェックしている。
0103 * </p>
0104 */
0105 static final int KEY_CHK_WAITFRAME = 4;
0106
0107 // キーのビット情報
0108 static final int KB_UP = (1 << Display.KEY_UP) | (1 << Display.KEY_2);
0109 static final int KB_DOWN = (1 << Display.KEY_DOWN) | (1 << Display.KEY_8);
0110 static final int KB_LEFT = (1 << Display.KEY_LEFT) | (1 << Display.KEY_4);
0111 static final int KB_RIGHT = (1 << Display.KEY_RIGHT) | (1 << Display.KEY_6);
0112 static final int KB_SELECT = (1 << Display.KEY_SELECT) | (1 << Display.KEY_5);
0113 static final int KB_SOFT1 = (1 << Display.KEY_SOFT1);
0114 static final int KB_SOFT2 = (1 << Display.KEY_SOFT2);
0115
0116 /**
0117 * 画面描画に使う Graphics オブジェクト
0118 */
0119 private Graphics g = getGraphics();
0120
0121 private interface IG {
0122
0123 public int NUMBERIMG = 0;
0124 public int STATUS = 1;
0125 public int ICON = 2;
0126 public int BTNMARK = 3;
0127
0128 /**
0129 * 画像ファイル総数
0130 */
0131 public int IMAGE_MAX = 4;
0132 }
0133
0134 /**
0135 * 画像イメージ格納用
0136 */
0137 private Image[] img = new Image[IG.IMAGE_MAX];
0138
0139 /**
0140 * 画面描画に使う Font オブジェクト(システムフォント)
0141 */
0142 private Font m_font;
0143
0144 /**
0145 * システムフォント描画位置調整用(単位はドット)
0146 */
0147 private int stringH;
0148
0149 /**
0150 * システムフォント文字サイズ(単位はドット)
0151 */
0152 private int fontSize;
0153
0154 /**
0155 * メインループ用記録カウンタ:ループ処理開始時間
0156 */
0157 private long mainLoopStartTime;
0158
0159 /**
0160 * メインループ記録カウンタ:待ち時間
0161 */
0162 private int mainLoopWaitTime;
0163
0164 /**
0165 * フレームカウンタ
0166 */
0167 private int frameCounter = 0;
0168
0169 /**
0170 * リジューム時に待つ時間
0171 */
0172 static final int RESUME_WAIT_TIME = FPS;
0173
0174 /**
0175 * リジューム時の処理キャンセルタイマー
0176 */
0177 private int resumeWaitTimer;
0178
0179 /**
0180 * メインステップ変数
0181 */
0182 private int mainStep;
0183
0184 /**
0185 * シーンカウンタ変数
0186 */
0187 private int sceneStep;
0188
0189 // ----------------------------------------
0190
0191 /**
0192 * キー入力用ワークを全消去
0193 */
0194 private void clearAllKeyWork() {
0195
0196 clearKeyWork();
0197 keyNoCheckEnableCount = FPS / 4;
0198 }
0199
0200 /**
0201 * キー入力用ワークを消去(キー入力キャンセルタイマーはセットしない)
0202 */
0203 private void clearKeyWork() {
0204
0205 c_repbtn = 0;
0206 keyBtnInterrupt = 0;
0207 trgBtn = 0;
0208 trgBtnUniq = 0;
0209 }
0210
0211 /**
0212 * キー入力用ワークの内容を設定
0213 */
0214 private void setKeyWork(int key) {
0215
0216 int oldkey = c_repbtn;
0217 key |= keyBtnInterrupt;
0218 keyBtnInterrupt = 0;
0219 c_repbtn = key;
0220
0221 trgBtn = (oldkey ^ c_repbtn) & c_repbtn;
0222 trgBtnUniq = getKeyUniqBit(trgBtn);
0223 }
0224
0225 /**
0226 * リジューム関係のwaitカウンタを初期化
0227 */
0228 public void initResumeWaitWork() {
0229
0230 clearKeyWork();
0231 keyNoCheckEnableCount = RESUME_WAIT_TIME;
0232 resumeWaitTimer = RESUME_WAIT_TIME;
0233 }
0234
0235 /**
0236 * リジューム処理。
0237 * <ul>
0238 * <li>キーワークをクリアする。</li>
0239 * <li>サウンドを再開再生する。</li>
0240 * </ul>
0241 */
0242 public void mcResume() {
0243
0244 resumeJobEnable = true;
0245
0246 saveProcessHistory(ProcessKind.RESUME);
0247
0248 initResumeWaitWork();
0249
0250 // 本来ここにサウンド再開処理
0251
0252 // ログ描画
0253 drawLogInterrupt();
0254
0255 // キー入力がなくなるまで待つ
0256 do {
0257 try {
0258 Thread.sleep(SLEEP_VALUE);
0259 } catch (InterruptedException e) {
0260 }
0261 setKeyWork(getKeypadState());
0262 } while (c_repbtn != 0 || trgBtn != 0);
0263
0264 resumeJobEnable = false;
0265 }
0266
0267 // イベント通知処理
0268 public void processEvent(int a_type, int a_param) {
0269
0270 if (processEventJobEnable) return;
0271 processEventJobEnable = true;
0272
0273 if (a_type == Display.RESUME_VM_EVENT) {
0274 // リジューム時はワークをクリア
0275 saveProcessHistory(ProcessKind.EVENT);
0276 initResumeWaitWork();
0277 }
0278
0279 if (a_type == Display.KEY_PRESSED_EVENT) {
0280 // キーが押された
0281 if (keyNoCheckEnableCount <= 0) keyBtnInterrupt |= (0x01 << a_param);
0282 }
0283
0284 processEventJobEnable = false;
0285 }
0286
0287 // ----------------------------------------
0288
0289 /**
0290 * コンストラクタ
0291 */
0292 public Main() {
0293
0294 resumeJobEnable = true;
0295
0296 // 念のためにキーワークだけでもクリアしておく
0297 clearAllKeyWork();
0298 keyNoCheckEnableCount = RESUME_WAIT_TIME;
0299 }
0300
0301 // ----------------------------------------
0302
0303 /**
0304 * メイン処理担当
0305 */
0306 public void exec() {
0307
0308 // ----------------------------------------
0309 // ワーク初期化
0310
0311 resumeJobEnable = true;
0312 processEventJobEnable = false;
0313
0314 System.gc();
0315
0316 // バックライトON
0317 PhoneSystem.setAttribute(PhoneSystem.DEV_BACKLIGHT, PhoneSystem.ATTR_BACKLIGHT_ON);
0318
0319 g = getGraphics(); // グラフィック生成
0320
0321 // 画面全体クリア
0322 g.lock();
0323 g.setClip(0, 0, SCREEN_W, SCREEN_H);
0324 g.setColor(Graphics.getColorOfName(Graphics.WHITE));
0325 g.fillRect(0, 0, SCREEN_W, SCREEN_H);
0326 g.unlock(true);
0327
0328 // フォント設定
0329 m_font = Font.getFont(Font.SIZE_TINY); // フォントをTINYにする
0330 g.setFont(m_font); // フォントを設定
0331 stringH = m_font.getAscent() - m_font.getHeight();
0332 fontSize = m_font.getHeight();
0333
0334 // ボタン情報初期化
0335 clearAllKeyWork();
0336 keyNoCheckEnableCount = FPS / 2;
0337
0338 System.gc();
0339
0340 loadImage();
0341
0342 System.gc();
0343
0344 // カウンター初期化
0345 mainLoopWaitTime = SLEEP_VALUE; // フレーム間隔
0346 resumeWaitTimer = 0;
0347 frameCounter = 0;
0348
0349 sceneStep = 0;
0350
0351 mainStep = 0;
0352
0353 initLogWork();
0354
0355 resumeJobEnable = false;
0356
0357 // ----------------------------------------
0358 // メインループ
0359
0360 while (true) {
0361
0362 saveProcessHistory(ProcessKind.LOOPSTART);
0363
0364 mainLoopStartTime = System.currentTimeMillis();
0365
0366 if (resumeJobEnable) {
0367 // リジューム中なら待つ
0368 try {
0369 Thread.sleep(SLEEP_VALUE);
0370 } catch (InterruptedException e) {
0371 }
0372 continue;
0373 }
0374
0375 // キーワーク設定
0376
0377 if (keyNoCheckEnableCount > 0 || resumeJobEnable) {
0378 // キー情報を取得しない処理
0379 int key = getKeypadState();
0380 key |= keyBtnInterrupt;
0381 clearKeyWork();
0382 if (!resumeJobEnable) {
0383 if (key == 0) keyNoCheckEnableCount--;
0384 }
0385 } else {
0386 // キー情報取得処理
0387 saveProcessHistory(ProcessKind.KEYSET);
0388 setKeyWork(getKeypadState());
0389 }
0390
0391 try {
0392
0393 if (!resumeJobEnable) {
0394 // リジューム処理終了待ちではないので、メイン処理を実行
0395
0396 if (resumeWaitTimer > 0) {
0397 // リジューム直後なので待つ
0398 resumeWaitTimer--;
0399 } else {
0400
0401 // メイン処理
0402 saveProcessHistory(ProcessKind.MAIN);
0403
0404 switch (mainStep) {
0405 case 0:
0406 // 起動時の入力待ち
0407
0408 // 描画
0409 saveProcessHistory(ProcessKind.DRAWSTART);
0410
0411 g.lock();
0412 g.setColor(Graphics.getColorOfName(Graphics.WHITE));
0413 g.fillRect(0, 0, SCREEN_W, SCREEN_H);
0414 g.setColor(Graphics.getColorOfName(Graphics.BLACK));
0415 printCenter("START [OK]", SCREEN_H / 2);
0416 g.unlock(true);
0417
0418 saveProcessHistory(ProcessKind.KEYCHECK);
0419
0420 if (trgBtnUniq == KB_SELECT) {
0421 mainStep++;
0422 }
0423
0424 break;
0425 case 1:
0426 setSoftKeyText("休止", "終了");
0427 setLogSaveEnable();
0428 mainStep++;
0429 break;
0430 case 2:
0431 // 処理経過を描画
0432 {
0433
0434 saveProcessHistory(ProcessKind.KEYCHECK);
0435
0436 if (trgBtnUniq == KB_SOFT1) {
0437 // 一時停止
0438 mainStep++;
0439 }
0440
0441 if (trgBtnUniq == KB_SOFT2) {
0442 // アプリ終了
0443 IApplication.getCurrentApp().terminate();
0444 }
0445
0446 if (trgBtnUniq == KB_SELECT) {
0447 sceneStep++;
0448 }
0449
0450 // 描画
0451 {
0452 saveProcessHistory(ProcessKind.DRAWSTART);
0453
0454 g.lock();
0455 g.setColor(Graphics.getColorOfName(Graphics.WHITE));
0456 g.fillRect(0, 0, SCREEN_W, SCREEN_H);
0457
0458 int x, y;
0459
0460 // アイコン描画
0461 x = SCREEN_W - 10;
0462 y = SCREEN_H - 10;
0463 int idx = frameCounter % 5;
0464 drawIcon(g, x, y, idx);
0465
0466 // ログを描画
0467 drawLog(g);
0468
0469 g.unlock(true);
0470 }
0471
0472 }
0473 break;
0474 case 3:
0475 setSoftKeyText("再開", "");
0476 saveProcessHistory(ProcessKind.PAUSESTART);
0477 setLogSaveDisable();
0478 mainStep++;
0479
0480 case 4:
0481 {
0482 // 描画
0483 {
0484 saveProcessHistory(ProcessKind.DRAWSTART);
0485
0486 g.lock();
0487 g.setColor(Graphics.getColorOfName(Graphics.WHITE));
0488 g.fillRect(0, 0, SCREEN_W, SCREEN_H);
0489
0490 // ログを描画
0491 drawLogHistory(g);
0492
0493 g.unlock(true);
0494 }
0495
0496 saveProcessHistory(ProcessKind.KEYCHECK);
0497
0498 if ((c_repbtn & (1 << Display.KEY_UP)) != 0) {
0499 decrementLogReadPointer();
0500 }
0501
0502 if ((c_repbtn & (1 << Display.KEY_DOWN)) != 0) {
0503 incrementLogReadPointer();
0504 }
0505
0506 if (trgBtnUniq == KB_SOFT1) {
0507 setSoftKeyText("休止", "終了");
0508 setLogSaveEnable();
0509 saveProcessHistory(ProcessKind.PAUSEEND);
0510 mainStep -= 2;
0511 }
0512 }
0513 break;
0514 }
0515
0516 }
0517
0518 }
0519
0520 // キューに溜まったサウンド再生・停止要求をこなす
0521 if (!resumeJobEnable) {
0522 // 本来ここでサウンド再生 or 停止処理
0523 }
0524
0525 saveProcessHistory(ProcessKind.MAIN_END);
0526
0527 if (!resumeJobEnable) {
0528 // リジューム中ではない
0529
0530 // バックライト操作
0531 if ((frameCounter % (3 * FPS)) == 0) {
0532 PhoneSystem.setAttribute(PhoneSystem.DEV_BACKLIGHT, PhoneSystem.ATTR_BACKLIGHT_ON);
0533 }
0534 }
0535
0536 if (resumeJobEnable) mainLoopStartTime = System.currentTimeMillis();
0537 System.gc();
0538 while (System.currentTimeMillis() < mainLoopStartTime + mainLoopWaitTime)
0539 Thread.yield();
0540
0541 frameCounter++;
0542
0543 } catch (Exception e) {
0544 String s = "情報:" + e + "\nmStep=" + mainStep;
0545 displayDialogMessage("エラー発生", s);
0546 IApplication.getCurrentApp().terminate();
0547 }
0548 saveProcessHistory(ProcessKind.LOOPEND);
0549 }
0550 }
0551
0552 // 画面描画
0553 public void paint(Graphics g) {
0554
0555 }
0556
0557 /**
0558 * ダイアログメッセージを表示する
0559 *
0560 * @param titleStr
0561 * ダイアログタイトル文字列
0562 * @param message
0563 * ダイアログメッセージ文字列
0564 */
0565 private void displayDialogMessage(String titleStr, String message) {
0566
0567 Dialog d = new Dialog(Dialog.DIALOG_ERROR, titleStr);
0568 d.setText(message);
0569 d.show();
0570 }
0571
0572 /**
0573 * キーの同時入力を避けるために一意の値にする
0574 *
0575 * @param keystatus
0576 * キー情報
0577 * @return 一意にしたキー情報
0578 */
0579 int getKeyUniqBit(int keystatus) {
0580
0581 int key = 0;
0582 if ((keystatus & KB_UP) != 0) {
0583 key = KB_UP;
0584 } else if ((keystatus & KB_DOWN) != 0) {
0585 key = KB_DOWN;
0586 } else if ((keystatus & KB_LEFT) != 0) {
0587 key = KB_LEFT;
0588 } else if ((keystatus & KB_RIGHT) != 0) {
0589 key = KB_RIGHT;
0590 } else if ((keystatus & KB_SELECT) != 0) {
0591 key = KB_SELECT;
0592 } else if ((keystatus & KB_SOFT1) != 0) {
0593 key = KB_SOFT1;
0594 } else if ((keystatus & KB_SOFT2) != 0) {
0595 key = KB_SOFT2;
0596 }
0597
0598 return key;
0599 }
0600
0601 /**
0602 * 割り込み時のログ描画
0603 */
0604 void drawLogInterrupt() {
0605
0606 g.lock();
0607 g.setColor(Graphics.getColorOfRGB(255, 227, 227));
0608 g.fillRect(0, 0, SCREEN_W, SCREEN_H);
0609
0610 // ログを描画
0611 drawLog(g);
0612
0613 g.unlock(true);
0614 }
0615
0616 // ----------------------------------------
0617 // 以降文字列描画系
0618
0619 /**
0620 * ベースライン調整を考慮した座標で文字列描画する
0621 *
0622 * @param s
0623 * 文字列
0624 * @param x
0625 * 描画位置 x
0626 * @param y
0627 * 描画位置 y
0628 */
0629 public void _drawString(String s, int x, int y) {
0630
0631 g.drawString(s, x, y + fontSize + stringH);
0632 }
0633
0634 /**
0635 * 文字列をセンタリング描画する。
0636 *
0637 * @param str
0638 * 文字列
0639 * @param y
0640 * 描画位置 y
0641 * @return 描画開始位置 x
0642 */
0643 int printCenter(String str, int y) {
0644
0645 int x = (SCREEN_W - m_font.stringWidth(str)) / 2;
0646 g.drawString(str, x, y + fontSize + stringH);
0647 return x;
0648 }
0649
0650 /**
0651 * 影つき文字列をセンタリング描画する。
0652 * <ul>
0653 * <li>fgcolor、shadowcolor には、Graphics.getColorOfName() か Graphics.getColorOfRGB() で値を渡す</li>
0654 * </ul>
0655 *
0656 * @param str
0657 * 文字列
0658 * @param y
0659 * 描画位置 y
0660 * @param fgcolor
0661 * 前景色
0662 * @param shadowcolor
0663 * 背景色
0664 */
0665 void printCenterWithShadow(String str, int y, int fgcolor, int shadowcolor) {
0666
0667 int x = (SCREEN_W - m_font.stringWidth(str)) / 2;
0668 printWithShadow(str, x, y, fgcolor, shadowcolor);
0669 }
0670
0671 /**
0672 * 影つき文字列を xy座標を指定して描画する。
0673 * <ul>
0674 * <li>fgcolor、bgcolor には、Graphics.getColorOfName() か Graphics.getColorOfRGB() で値を渡す</li>
0675 * </ul>
0676 *
0677 * @param str
0678 * 文字列
0679 * @param x
0680 * 描画位置 x
0681 * @param y
0682 * 描画位置 y
0683 * @param fgcolor
0684 * 前景色
0685 * @param shadowcolor
0686 * 影色
0687 */
0688 void printWithShadow(String str, int x, int y, int fgcolor, int shadowcolor) {
0689
0690 y += fontSize + stringH;
0691
0692 g.setColor(shadowcolor);
0693 g.drawString(str, x + 1, y + 1);
0694
0695 g.setColor(fgcolor);
0696 g.drawString(str, x, y);
0697 }
0698
0699 /**
0700 * 画像に基づく文字列表示メソッド処理指定用・ゼロの桁表示有効
0701 */
0702 static final boolean ZERO_DISP_ENABLE = true;
0703
0704 /**
0705 * 画像に基づく文字列表示メソッド処理指定用・ゼロの桁表示無効
0706 */
0707 static final boolean ZERO_DISP_DISABLE = false;
0708
0709 /**
0710 * 画像に基づく文字列表示メソッド処理指定用・数字の左詰め表示
0711 */
0712 static final boolean ALIGN_LEFT = true;
0713
0714 /**
0715 * 画像に基づく文字列表示メソッド処理指定用・数字の右詰め表示
0716 */
0717 static final boolean ALIGN_RIGHT = false;
0718
0719 /**
0720 * 画像に基づく文字列表示メソッド処理指定用・描画有効
0721 */
0722 static final boolean DRAW_ENABLE = true;
0723
0724 /**
0725 * 画像に基づく文字列表示メソッド処理指定用・描画をせずに横幅だけを取得する
0726 */
0727 static final boolean DRAW_DISABLE = false;
0728
0729 /**
0730 * フォント種類
0731 */
0732 private interface FontKind {
0733
0734 /**
0735 * 数字(小サイズ)
0736 */
0737 public int MICRO = 0;
0738
0739 }
0740
0741 /**
0742 * フォント種類に割り当てる、画像ナンバー、横幅、縦幅、スペーシングを列挙したテーブル
0743 */
0744 static final short[] ASCII_WH = {
0745 // Img_No, W, H, spacing
0746 IG.NUMBERIMG, 4, 6, 0, // 小
0747 };
0748
0749 static final int ASCII_WH_OFFSET = 4;
0750
0751 /**
0752 * 数値を描画
0753 *
0754 * @param g
0755 * Graphics クラス
0756 * @param num
0757 * 表示したい数値
0758 * @param keta
0759 * 桁
0760 * @param x
0761 * 表示位置 x
0762 * @param y
0763 * 表示位置 y
0764 * @param zerodisp
0765 * ZERO_DISP_ENABLE = ゼロで埋める / ZERO_DISP_DISABLE = ゼロで埋めない
0766 * @param alignleft
0767 * ALIGN_LEFT = 左詰 / ALIGN_RIGHT = 右詰
0768 * @param drawEnable
0769 * DRAW_ENABLE = 描画する / DRAW_DISABLE = 描画しない(横幅のみ取得)
0770 * @param kind
0771 * フォント種類 (FontKind を参照)
0772 * @return 描画されるであろう横幅
0773 */
0774 int drawNumberXSmall(Graphics g, long num, int keta, int x, int y, boolean zerodisp, boolean alignleft, boolean drawEnable, int kind) {
0775
0776 int string_w = 0; // 描画横幅記録用
0777
0778 int wadd = 0;
0779
0780 int n = kind * ASCII_WH_OFFSET;
0781 int ign = ASCII_WH[n++]; // 画像ナンバー
0782 int sw = ASCII_WH[n++]; // 1文字の横幅
0783 int sh = ASCII_WH[n++]; // 1文字の縦幅
0784 int xadd = ASCII_WH[n++]; // 1文字描くごとに補正する値
0785
0786 // 桁単位で計算するための値の初期値を求める
0787 int a = 1;
0788 int k = 1;
0789 while (k < keta) {
0790 a *= 10;
0791 k++;
0792 }
0793
0794 int w = sw;
0795 w += wadd;
0796
0797 // 桁の数だけループ
0798 for (int i = keta; i > 0; i--, a /= 10) {
0799 long nokori = num % a;
0800
0801 // m に、その桁の値を取り出す
0802 long m = num;
0803 if (m != 0) {
0804 m /= a;
0805 }
0806
0807 if (zerodisp || (int) m != 0 || i == 1) {
0808
0809 // 以下の条件のどれかに合致した場合、処理をする。
0810 // ・ゼロ表示が有効
0811 // ・その桁が 0 ではない
0812 // ・最後の桁
0813
0814 if (drawEnable) {
0815 int sx = (int) (m * sw);
0816 g.drawImage(img[ign], x, y, sx, 0, sw, sh);
0817 }
0818
0819 if (((int) m != 0 && !zerodisp) || i == 1) {
0820 // 以下の条件のどれかに合致した場合、それ以降はゼロ表示を有効にする。
0821 // ・その桁が0ではなく、かつ、ゼロ表示が無効
0822 // ・最後の桁
0823 zerodisp = true;
0824 }
0825 }
0826
0827 if (zerodisp || !alignleft) {
0828 x += (sw + xadd);
0829 string_w += (sw + xadd);
0830 }
0831 num = nokori;
0832 }
0833
0834 return string_w;
0835 }
0836
0837 /**
0838 * フォントの横幅を得る
0839 *
0840 * @param kind
0841 * フォント種類。FontKind を参照のこと。
0842 * @return 横幅ドット数
0843 */
0844 int getFontW(int kind) {
0845
0846 return ASCII_WH[(kind * ASCII_WH_OFFSET) + 1];
0847 }
0848
0849 /**
0850 * フォントの縦幅を得る
0851 *
0852 * @param kind
0853 * フォント種類。FontKind を参照のこと。
0854 * @return 縦幅ドット数
0855 */
0856 int getFontH(int kind) {
0857
0858 return ASCII_WH[(kind * ASCII_WH_OFFSET) + 2];
0859 }
0860
0861 /**
0862 * 画像読み込み(res/から)
0863 */
0864 private void loadImage() {
0865
0866 for (int i = 0; i < IG.IMAGE_MAX; i++) {
0867 String fn = Integer.toString(i) + ".gif";
0868 MediaImage tempImg = MediaManager.getImage("resource:///" + fn);
0869 try {
0870 tempImg.use();
0871 } catch (Exception e) {
0872 }
0873 img[i] = tempImg.getImage();
0874 }
0875 }
0876
0877 /**
0878 * ステータス画像の縦幅
0879 */
0880 private final static int STATUS_IMG_H = 6;
0881
0882 /**
0883 * ステータス画像を描画
0884 *
0885 * @param g
0886 * Graphics
0887 * @param x
0888 * 描画位置 x
0889 * @param y
0890 * 描画位置 y
0891 * @param kind
0892 * ステータス画像種類
0893 * @return 描画した幅
0894 */
0895 private int drawStatus(Graphics g, int x, int y, int kind) {
0896
0897 int imgLen = ProcessKind.LENGTH;
0898 int ign = IG.STATUS;
0899 int w = img[ign].getWidth();
0900 int h = img[ign].getHeight();
0901 h /= imgLen;
0902 int sy = h * kind;
0903
0904 if (kind == ProcessKind.SCENE) {
0905 w = 16;
0906 }
0907
0908 if (kind == ProcessKind.STEP) {
0909 w = 14;
0910 }
0911
0912 g.drawImage(img[ign], x, y, 0, sy, w, h);
0913
0914 return w;
0915 }
0916
0917 /**
0918 * アイコン画像を描画
0919 *
0920 * @param g
0921 * Graphics
0922 * @param x
0923 * 描画位置 x
0924 * @param y
0925 * 描画位置 y
0926 * @param indexNumber
0927 * パターンナンバー
0928 */
0929 private void drawIcon(Graphics g, int x, int y, int indexNumber) {
0930
0931 final int imgLen = 5;
0932 if (indexNumber >= imgLen) return;
0933
0934 int ign = IG.ICON;
0935 int w = img[ign].getWidth();
0936 int h = img[ign].getHeight();
0937 w /= imgLen;
0938 int sx = w * indexNumber;
0939 g.drawImage(img[ign], x, y, sx, 0, w, h);
0940 }
0941
0942 /**
0943 * ビットパターンを画像で描画
0944 *
0945 * @param g
0946 * Graphics
0947 * @param x
0948 * 描画位置 x
0949 * @param y
0950 * 描画位置 y
0951 * @param bitPattern
0952 * 描画したい値(32bit)
0953 */
0954 private int drawBitPattern(Graphics g, int x, int y, int bitPattern) {
0955
0956 int ign = IG.BTNMARK;
0957 int w = img[ign].getWidth();
0958 int h = img[ign].getHeight();
0959 w /= 2;
0960 int dx = x + (w * (32 - 1));
0961 int allw = 0;
0962 for (int i = 0; i < 32; i++) {
0963 int fg = bitPattern & 0x01;
0964 int sx = w * fg;
0965 g.drawImage(img[ign], dx, y, sx, 0, w, h);
0966 dx -= w;
0967 bitPattern >>= 1;
0968 allw += w;
0969 }
0970
0971 return allw;
0972 }
0973
0974 /**
0975 * ソフトキーのラベルを設定する
0976 *
0977 * @param labelStrLeft
0978 * ソフトキー1ラベル
0979 * @param labelStrRight
0980 * ソフトキー2ラベル
0981 */
0982 private void setSoftKeyText(String labelStrLeft, String labelStrRight) {
0983
0984 String l1;
0985 String l2;
0986
0987 l1 = labelStrLeft;
0988 if (l1 == null) l1 = "";
0989
0990 l2 = labelStrRight;
0991 if (l2 == null) l2 = "";
0992
0993 setSoftLabel(SOFT_KEY_1, l1);
0994 setSoftLabel(SOFT_KEY_2, l2);
0995 }
0996
0997 /**
0998 * ログを取る際の処理種類
0999 */
1000 public interface ProcessKind {
1001
1002 public int LOOPSTART = 0;
1003 public int LOOPEND = 1;
1004 public int KEYSET = 2;
1005 public int MAIN = 3;
1006 public int MAIN_END = 4;
1007 public int RESUME = 5;
1008 public int EVENT = 6;
1009 public int SCENE = 7;
1010 public int PAUSESTART = 8;
1011 public int PAUSEEND = 9;
1012 public int KEYCHECK = 10;
1013 public int DRAWSTART = 11;
1014 public int STEP = 12;
1015 public int LENGTH = 13;
1016 }
1017
1018 /**
1019 * ログワーク最大数
1020 */
1021 private static final int LOG_MAX = 8192;
1022
1023 /**
1024 * 処理種類ログワーク
1025 */
1026 private int[] logStatus = new int[LOG_MAX];
1027
1028 /**
1029 * キー情報ログワーク
1030 */
1031 private int[] logBitPattern = new int[LOG_MAX];
1032
1033 /**
1034 * シーンカウンタログワーク
1035 */
1036 private int[] logScene = new int[LOG_MAX];
1037
1038 /**
1039 * フレームカウンタログワーク
1040 */
1041 private int[] logFrameCounter = new int[LOG_MAX];
1042
1043 /**
1044 * ログワーク書き込み用ポインタ
1045 */
1046 private int logWritePointer;
1047
1048 /**
1049 * ログワーク読み込み用ポインタ
1050 */
1051 private int logReadPointer;
1052
1053 /**
1054 * ログを取るかどうかのフラグ
1055 */
1056 private boolean logSaveEnable;
1057
1058 /**
1059 * 1画面あたりに表示するログの行数
1060 */
1061 private static final int LOG_LINE_PER_PAGE = SCREEN_H / STATUS_IMG_H;
1062
1063 /**
1064 * ログワーク初期化
1065 */
1066 private void initLogWork() {
1067
1068 for (int i = 0; i < LOG_MAX; i++) {
1069 logStatus[i] = -1;
1070 logBitPattern[i] = 0;
1071 }
1072
1073 logWritePointer = 0;
1074 logReadPointer = 0;
1075 setLogSaveDisable();
1076 }
1077
1078 /**
1079 * ログ記録を有効化
1080 */
1081 private void setLogSaveEnable() {
1082
1083 logSaveEnable = true;
1084 }
1085
1086 /**
1087 * ログ記録を無効化
1088 */
1089 private void setLogSaveDisable() {
1090
1091 logSaveEnable = false;
1092 }
1093
1094 /**
1095 * ログを記録
1096 *
1097 * @param kind
1098 * 記録する処理種類
1099 */
1100 public void saveProcessHistory(int kind) {
1101
1102 if (!logSaveEnable) return;
1103
1104 logStatus[logWritePointer] = kind;
1105 logBitPattern[logWritePointer] = trgBtnUniq;
1106 logScene[logWritePointer] = (mainStep * 1000) + (sceneStep % 1000);
1107 logFrameCounter[logWritePointer] = frameCounter;
1108
1109 logWritePointer++;
1110 if (logWritePointer >= LOG_MAX) logWritePointer = 0;
1111 }
1112
1113 /**
1114 * ログを画面に描画
1115 *
1116 * @param g
1117 * Graphics
1118 */
1119 private void drawLog(Graphics g) {
1120
1121 int dx = 0;
1122 int dy = SCREEN_H - STATUS_IMG_H;
1123
1124 int idx = logWritePointer;
1125 for (int i = 0; i < LOG_LINE_PER_PAGE; i++) {
1126 idx--;
1127 if (idx < 0) idx += LOG_MAX;
1128
1129 int status = logStatus[idx];
1130 int bitpat = logBitPattern[idx];
1131 int scene = logScene[idx];
1132 int fcount = logFrameCounter[idx];
1133
1134 if (status >= 0) {
1135 drawLogOneLine(g, dx, dy, status, bitpat, scene, fcount);
1136 dx = 0;
1137 dy -= STATUS_IMG_H;
1138 }
1139 }
1140
1141 logReadPointer = idx;
1142 }
1143
1144 /**
1145 * ログを画面に描画(履歴表示時)
1146 *
1147 * @param g
1148 * Graphics
1149 */
1150 private void drawLogHistory(Graphics g) {
1151
1152 int dx = 0;
1153 int dy = 0;
1154
1155 int idx = logReadPointer;
1156 for (int i = 0; i < LOG_LINE_PER_PAGE; i++) {
1157 int status = logStatus[idx];
1158 int bitpat = logBitPattern[idx];
1159 int scene = logScene[idx];
1160 int fcount = logFrameCounter[idx];
1161
1162 if (status >= 0) {
1163 drawLogOneLine(g, dx, dy, status, bitpat, scene, fcount);
1164 }
1165
1166 dx = 0;
1167 dy += STATUS_IMG_H;
1168
1169 idx++;
1170 if (idx >= LOG_MAX) idx = 0;
1171 }
1172 }
1173
1174 /**
1175 * ログ読み込みポインタを+1する
1176 */
1177 private void incrementLogReadPointer() {
1178
1179 int checkIdx = logWritePointer - LOG_LINE_PER_PAGE + 1;
1180 if (checkIdx < 0) checkIdx += LOG_MAX;
1181
1182 int idx = logReadPointer;
1183 idx++;
1184 if (idx >= LOG_MAX) idx = 0;
1185
1186 if (idx != checkIdx) {
1187 logReadPointer = idx;
1188 // System.out.println("WP="+logWritePointer+" RP="+logReadPointer);
1189 }
1190 }
1191
1192 /**
1193 * ログ読み込みポインタを-1する
1194 */
1195 private void decrementLogReadPointer() {
1196
1197 int checkIdx = logWritePointer - 1;
1198 if (checkIdx < 0) checkIdx += LOG_MAX;
1199
1200 int idx = logReadPointer;
1201 idx--;
1202 if (idx < 0) idx += LOG_MAX;
1203
1204 if (idx != checkIdx) {
1205 logReadPointer = idx;
1206 // System.out.println("WP="+logWritePointer+" RP="+logReadPointer);
1207 }
1208 }
1209
1210 /**
1211 * ログ一行分を画面に描画
1212 *
1213 * @param g
1214 * Graphics
1215 * @param x
1216 * 描画位置 x
1217 * @param y
1218 * 描画位置 y
1219 * @param status
1220 * 描画する処理種類
1221 * @param bitpat
1222 * 描画するビットパターン値
1223 * @param scene
1224 * 描画するシーンカウンタ値
1225 * @param fcount
1226 * 描画するカウンタ値
1227 */
1228 private void drawLogOneLine(Graphics g, int x, int y, int status, int bitpat, int scene, int fcount) {
1229
1230 int cnt_a = (scene != 0) ? (scene / 1000) : 0;
1231 int cnt_b = (scene % 1000);
1232
1233 int w;
1234 w = drawNumberXSmall(g, fcount, 8, x, y, ZERO_DISP_ENABLE, ALIGN_LEFT, DRAW_ENABLE, FontKind.MICRO);
1235 x += w;
1236 x += 2;
1237
1238 w = drawStatus(g, x, y, status);
1239 x += w;
1240 x += 2;
1241
1242 w = drawStatus(g, x, y, ProcessKind.SCENE);
1243 x += w;
1244 w = drawNumberXSmall(g, cnt_b, 3, x, y, ZERO_DISP_ENABLE, ALIGN_LEFT, DRAW_ENABLE, FontKind.MICRO);
1245 x += w;
1246 x += 2;
1247
1248 w = drawBitPattern(g, x, y, bitpat);
1249 x += w;
1250
1251 w = drawStatus(g, x, y, ProcessKind.STEP);
1252 x += w;
1253 w = drawNumberXSmall(g, cnt_a, 1, x, y, ZERO_DISP_ENABLE, ALIGN_LEFT, DRAW_ENABLE, FontKind.MICRO);
1254 x += w;
1255 x += 2;
1256
1257 x = 0;
1258 y -= STATUS_IMG_H;
1259 }
1260 }
|