/*---------------------------------------------------------------------------* Project: NintendoWare File: dev_DirectPrint.cpp Copyright (C)2009-2010 Nintendo Co., Ltd./HAL Laboratory, Inc. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Revision: 17997 $ *---------------------------------------------------------------------------*/ #include #ifdef NW_DEV_ENABLED #include #include #include namespace nw { namespace dev { namespace { //---------------------------------------------------------------------------- // ASCII文字変換テーブル // const int FONT_WIDTH = 6; // フォントの横幅 const int FONT_HEIGHT = 7; // フォントの高さ const int FONT_ROW = 5; // フォントデータサイズ const int TAB_WIDTH = 4; // タブ幅 enum { ASCII_w0 = 0, ASCII_w1 = 1, ASCII_w2 = 2, ASCII_w3 = 3, ASCII_w4 = 4, ASCII_w5 = 5, ASCII_w6 = 6, ASCII_w7 = 7, ASCII_w8 = 8, ASCII_w9 = 9, ASCII_wA = 10, ASCII_wB = 11, ASCII_wC = 12, ASCII_wD = 13, ASCII_wE = 14, ASCII_wF = 15, ASCII_wG = 16, ASCII_wH = 17, ASCII_wI = 18, ASCII_wJ = 19, ASCII_wK = 20, ASCII_wL = 21, ASCII_wM = 22, ASCII_wN = 23, ASCII_wO = 24, ASCII_wP = 25, ASCII_wQ = 26, ASCII_wR = 27, ASCII_wS = 28, ASCII_wT = 29, ASCII_wU = 30, ASCII_wV = 31, ASCII_wW = 32, ASCII_wX = 33, ASCII_wY = 34, ASCII_wZ = 35, ASCII_CN = 36, /* : */ ASCII_KS = 37, /* ( */ ASCII_KE = 38, /* ) */ ASCII_MI = 39, /* - */ ASCII_QT = 40, /* ? */ ASCII_EM = 41, /* ! */ ASCII_PL = 42, /* + */ ASCII_PA = 43, /* % */ ASCII_DT = 44, /* . */ ASCII_NO = 0xff, ASCII_SP = 0xff, ASCII_RET = 0xfe, ASCII_TAB = 0xfd, ASCII_DQ = 100, /* " */ ASCII_SH = 101, /* # */ ASCII_DL = 102, /* $ */ ASCII_AM = 103, /* & */ ASCII_AP = 104, /* ' */ ASCII_AS = 105, /* * */ ASCII_CO = 106, /* , */ ASCII_SL = 107, /* / */ ASCII_SM = 108, /* ; */ ASCII_LT = 109, /* < */ ASCII_EQ = 110, /* = */ ASCII_GT = 111, /* > */ ASCII_AT = 112, /* @ */ ASCII_QP1 = 113, /* [ */ ASCII_BS = 114, /* \ */ ASCII_QP2 = 115, /* ] */ ASCII_HT = 116, /* ^ */ ASCII_UB = 117, /* _ */ ASCII_WP1 = 118, /* { */ ASCII_VL = 119, /* | */ ASCII_WP2 = 120, /* } */ ASCII_TI = 121, /* ~ */ ASCII_FC = 122, /* facemark */ ASCII_lA = 125, /* a */ ASCII_lB = 126, /* b */ ASCII_lC = 127, /* c */ ASCII_lD = 128, /* d */ ASCII_lE = 129, /* e */ ASCII_lF = 130, /* f */ ASCII_lG = 131, /* g */ ASCII_lH = 132, /* h */ ASCII_lI = 133, /* i */ ASCII_lJ = 134, /* j */ ASCII_lK = 135, /* k */ ASCII_lL = 136, /* l */ ASCII_lM = 137, /* m */ ASCII_lN = 138, /* n */ ASCII_lO = 139, /* o */ ASCII_lP = 140, /* p */ ASCII_lQ = 141, /* q */ ASCII_lR = 142, /* r */ ASCII_lS = 143, /* s */ ASCII_lT = 144, /* t */ ASCII_lU = 145, /* u */ ASCII_lV = 146, /* v */ ASCII_lW = 147, /* w */ ASCII_lX = 148, /* x */ ASCII_lY = 149, /* y */ ASCII_lZ = 150, /* z */ ASCII_dummyEnd = 999 }; const u8 sAsciiTable[128] = { ASCII_FC, ASCII_FC, ASCII_FC, ASCII_FC, ASCII_FC, ASCII_FC, ASCII_FC, ASCII_FC, ASCII_FC, ASCII_TAB,ASCII_RET,ASCII_FC, ASCII_FC, ASCII_FC, ASCII_FC, ASCII_FC, /* 0x00 */ ASCII_NO, ASCII_NO, ASCII_NO, ASCII_NO, ASCII_NO, ASCII_NO, ASCII_NO, ASCII_NO, ASCII_NO, ASCII_NO, ASCII_NO, ASCII_NO, ASCII_NO, ASCII_NO, ASCII_NO, ASCII_NO, /* 0x10 */ ASCII_SP, ASCII_EM, ASCII_DQ, ASCII_SH, ASCII_DL, ASCII_PA, ASCII_AM, ASCII_AP, ASCII_KS, ASCII_KE, ASCII_AS, ASCII_PL, ASCII_CO, ASCII_MI, ASCII_DT, ASCII_SL, /* 0x20 */ ASCII_w0, ASCII_w1, ASCII_w2, ASCII_w3, ASCII_w4, ASCII_w5, ASCII_w6, ASCII_w7, ASCII_w8, ASCII_w9, ASCII_CN, ASCII_SM, ASCII_LT, ASCII_EQ, ASCII_GT, ASCII_QT, /* 0x30 */ ASCII_AT, ASCII_wA, ASCII_wB, ASCII_wC, ASCII_wD, ASCII_wE, ASCII_wF, ASCII_wG, ASCII_wH, ASCII_wI, ASCII_wJ, ASCII_wK, ASCII_wL, ASCII_wM, ASCII_wN, ASCII_wO, /* 0x40 */ ASCII_wP, ASCII_wQ, ASCII_wR, ASCII_wS, ASCII_wT, ASCII_wU, ASCII_wV, ASCII_wW, ASCII_wX, ASCII_wY, ASCII_wZ, ASCII_QP1, ASCII_BS,ASCII_QP2,ASCII_HT, ASCII_UB, /* 0x50 */ ASCII_NO, ASCII_lA, ASCII_lB, ASCII_lC, ASCII_lD, ASCII_lE, ASCII_lF, ASCII_lG, ASCII_lH, ASCII_lI, ASCII_lJ, ASCII_lK, ASCII_lL, ASCII_lM, ASCII_lN, ASCII_lO, /* 0x60 */ ASCII_lP, ASCII_lQ, ASCII_lR, ASCII_lS, ASCII_lT, ASCII_lU, ASCII_lV, ASCII_lW, ASCII_lX, ASCII_lY, ASCII_lZ, ASCII_WP1, ASCII_VL,ASCII_WP2,ASCII_TI, ASCII_FC, /* 0x70 */ }; //---------------------------------------------------------------------------- // ASCII文字フォントデータ // // ・FONT_ROW 数のフォントが1行ずつ u32 にパックされています。 // ・フォントデータは1ピクセルあたり1ビットです。 // ・最上位ビットは最初のフォントの左端のビットです。 // const u32 sFontData[64] = { 0x70871C30, 0x8988A250, 0x88808290, 0x88830C90, 0x888402F8, 0x88882210, 0x71CF9C10, 0xF9CF9C70, 0x8208A288, 0xF200A288, 0x0BC11C78, 0x0A222208, 0x8A222208, 0x71C21C70, 0x23C738F8, 0x5228A480, 0x8A282280, 0x8BC822F0, 0xFA282280, 0x8A28A480, 0x8BC738F8, 0xF9C89C08, 0x82288808, 0x82088808, 0xF2EF8808, 0x82288888, 0x82288888, 0x81C89C70, 0x8A08A270, 0x920DA288, 0xA20AB288, 0xC20AAA88, 0xA208A688, 0x9208A288, 0x8BE8A270, 0xF1CF1CF8, 0x8A28A220, 0x8A28A020, 0xF22F1C20, 0x82AA0220, 0x82492220, 0x81A89C20, 0x8A28A288, 0x8A28A288, 0x8A289488, 0x8A2A8850, 0x894A9420, 0x894AA220, 0x70852220, 0xF8011000, 0x08020800, 0x10840400, 0x20040470, 0x40840400, 0x80020800, 0xF8011000, 0x70800000, 0x88822200, 0x08820400, 0x108F8800, 0x20821000, 0x00022200, 0x20800020, 0x00000000, }; const u32 sFontData2[77] = { 0x51421820, 0x53e7a420, 0x014a2c40, 0x01471000, 0x0142aa00, 0x03eaa400, 0x01471a78, 0x00000000, 0x50008010, 0x20010820, 0xf8020040, 0x20420820, 0x50441010, 0x00880000, 0x00070e00, 0x01088840, 0x78898820, 0x004a8810, 0x788a8810, 0x01098808, 0x00040e04, 0x70800620, 0x11400820, 0x12200820, 0x10001020, 0x10000820, 0x100f8820, 0x70000620, 0x60070000, 0x110f82a0, 0x12aa8ae0, 0x084f92a0, 0x100fbe1c, 0x10089008, 0x60070808, // a-e 0x00000000, 0x02000200, 0x7a078270, 0x8bc81e88, 0x8a2822f8, 0x9a282280, 0x6bc79e78, // f-j 0x30000000, 0x48080810, 0x41e80000, 0x422f1830, 0xfbe88810, 0x40288890, 0x43c89c60, // k-o 0x81000000, 0x81000000, 0x990f3c70, 0xa10aa288, 0xe10aa288, 0xa10aa288, 0x98caa270, // p-t 0x00000000, 0x00000020, 0xf1ef1e20, 0x8a28a0f8, 0x8a281c20, 0xf1e80220, 0x80283c38, // u-y 0x00000000, 0x00000000, 0x8a28b688, 0x8a2a8888, 0x8a2a8878, 0x894a8808, 0x788536f0, // z 0x00000000, 0x00000000, 0xf8000000, 0x10000000, 0x20000000, 0x40000000, 0xf8000000, }; //! //! @brief 描画コンテキスト。 //! struct PixelWriterContext { //! ピクセルのアドレス計算の起点です。 u8* m_BufferBase; //! X座標にするアドレスの増分 int m_StrideX; //! Y座標に対するアドレスの増分 int m_StrideY; //! X座標の上限。 int m_LimitX; //! Y座標の上限。 int m_LimitY; //! ピクセルあたりのバイト数。 int m_PixelSize; //! バッファのフォーマットに変換された描画カラー。 u8 m_PixelColor[4]; }; //! //! @brief バッファへの描画クラス(抽象基底クラス)。 //! //! @details //! バッファのフォーマットに応じた具象クラスを導出します。 //! オブジェクトは状態を持ちません。 //! class PixelWriter { public: //! @brief 矩形領域を暗くします。 //! //! @param buffer フレームバッファ情報です。 //! @param direction 描画方向です。 //! @param x 矩形領域の位置(X方向成分)です。 //! @param y 矩形領域の位置(Y方向成分)です。 //! @param width 矩形領域の幅です。 //! @param height 矩形領域の高さです。 //! void Erase( const internal::FrameBufferInfo& buffer, DirectPrint::Direction direction, int x, int y, int width, int height) { // コンテキストの初期化 PixelWriterContext context; this->InitializeContext(context, buffer, ut::Color8::BLACK, direction); this->Erase(context, x, y, width, height); } //! @brief 文字列を描画します。 //! //! @param buffer フレームバッファ情報です。 //! @param direction 描画方向です。 //! @param color 描画色です。 //! @param x 描画開始位置(X方向成分)です。 //! @param y 描画開始位置(Y方向成分)です。 //! @param str 文字列です。 //! @param turnOver 行右端で折り返す場合には true を指定します。 //! @param backErase 背景を暗くする場合は true を指定します。 //! void DrawString( const internal::FrameBufferInfo& buffer, DirectPrint::Direction direction, ut::Color color, int x, int y, const char* str, bool turnOver, bool backErase) { NW_NULL_ASSERT(str); // コンテキストの初期化 PixelWriterContext context; this->InitializeContext(context, buffer, color, direction); this->DrawString(context, x, y, str, turnOver, backErase); } private: //! @brief コンテキストを初期化します。 //! //! @param context 初期化対象のコンテキストです。 //! @param buffer フレームバッファの情報です。 //! @param color 描画色です。 //! void InitializeContext( PixelWriterContext& context, const internal::FrameBufferInfo& buffer, ut::Color8 color, DirectPrint::Direction direction) { context.m_PixelSize = this->GetPixelSize(); this->MakePixel(context.m_PixelColor, color); switch (direction) { case DirectPrint::DIRECTION_VERTICAL: default: context.m_BufferBase = buffer.m_Address; context.m_StrideX = context.m_PixelSize; context.m_StrideY = context.m_PixelSize * buffer.m_Width; context.m_LimitX = buffer.m_Width; context.m_LimitY = buffer.m_Height; break; case DirectPrint::DIRECTION_HORIZONTAL: context.m_BufferBase = buffer.m_Address + context.m_PixelSize * (buffer.m_Width - 1); context.m_StrideX = context.m_PixelSize * buffer.m_Width; context.m_StrideY = -context.m_PixelSize; context.m_LimitX = buffer.m_Height; context.m_LimitY = buffer.m_Width; } } //! @brief ピクセルのアドレスを求めます。 //! //! @param context コンテキストです。 //! @param x X座標の値です。 //! @param y Y座標の値です。 //! //! @return //! ピクセルのアドレスを返します。 u8* GetPixelAddress(const PixelWriterContext& context, int x, int y) { return context.m_BufferBase + context.m_StrideX * x + context.m_StrideY * y; } //! @brief 矩形領域を暗くします。 //! //! @param context コンテキストです。 //! @param x 矩形領域の位置(X方向成分)です。 //! @param y 矩形領域の位置(Y方向成分)です。 //! @param width 矩形領域の幅です。 //! @param height 矩形領域の高さです。 //! void Erase( const PixelWriterContext& context, int x, int y, int width, int height) { // 開始点(X)をバッファ内にクリップする。 if (x < 0) { width += x; x = 0; } // 開始点(Y)をバッファ内にクリップする。 if (y < 0) { height += y; y = 0; } // バッファサイズをオーバーしている場合はクリップする(水平方向) int posEndX = ut::Max(0, ut::Min((int)context.m_LimitX, x + width)); width = posEndX - x; // バッファサイズをオーバーしている場合はクリップする(垂直方向) int posEndY = ut::Max(0, ut::Min((int)context.m_LimitY, y + height)); height = posEndY - y; // クリップの結果、消去範囲の面積が0になった場合は終了。 if (width <= 0 || height <= 0) { return; } // ---- 指定矩形を暗く for (int cnty = 0; cnty < height; ++cnty) { for (int cntx = 0; cntx < width; ++cntx) { u8* pixel = this->GetPixelAddress(context, x + cntx, y + cnty); this->ErasePixel(pixel); } } } //! @brief 文字列を描画します。 //! //! @param context コンテキストです。 //! @param x 描画開始位置(X方向成分)です。 //! @param y 描画開始位置(Y方向成分)です。 //! @param str 文字列です。 //! @param turnOver 行右端で折り返す場合には true を指定します。 //! @param backErase 背景を暗くする場合は true を指定します。 //! void DrawString( const PixelWriterContext& context, int x, int y, const char* str, bool turnOver, bool backErase) { int basePosX = x; while (*str != '\0') { if (backErase) { int len = this->StrLineWidth(str); this->Erase(context, x - FONT_WIDTH, y - 3, (len + 2) * FONT_WIDTH, FONT_HEIGHT + 3 + 3); } int width = (context.m_LimitX - x) / FONT_WIDTH; // 行末までの文字列を出力する。 str = this->DrawLine(context, x, y, str, width); y += (FONT_HEIGHT + 3); if (*str == '\n') { // 改行コードで終わった場合には次の行へ ++str; x = basePosX; } else if (*str != '\0') // 行の途中で折り返した場合 { ++str; if (! turnOver) { // 右端での折り返しがOFFであれば次の行までジャンプする。 if ((str = std::strchr(str, '\n')) == NULL) { return; } ++str; x = basePosX; } else { x = 0; } } } } //! @brief 文字列を1行分描画します。 //! //! @param context コンテキストです。 //! @param x 文字を描画する位置のX座標です。 //! @param y 文字を描画する位置のY座標です。 //! @param str 文字列へのポインタです。 //! @param width 1行あたりの最大文字数です。 //! //! @return 最後に出力もしくは判定をおこなった文字へのポインタを返します。 //! const char* DrawLine( const PixelWriterContext& context, int x, int y, const char* str, int width) { char c; // カレント文字 int code; // 内部文字コードへ変換した値 int cnt = 0; // 出力文字数のカウンタ NW_NULL_ASSERT(str); NW_ASSERT(width > 0); while ((c = *str) != '\0') { // 行の終端であれば終了 if (c == '\n' || c == '\0') { return str; } // ---- 表示コード code = sAsciiTable[c & 0x7f]; if (code == ASCII_TAB) // ---- タブ { int tab_size = TAB_WIDTH - (cnt & (TAB_WIDTH - 1)); x += FONT_WIDTH * tab_size; cnt += tab_size; } else // ---- 1文字出力 { // ---- 空白以外 if (code != ASCII_SP) { this->DrawChar(context, x, y, code); } x += FONT_WIDTH; ++cnt; } if (cnt >= width) { if (*(str + 1) == '\n') { // 終端が改行の場合には次へ ++str; } return str; } ++str; } return str; } //! @brief 文字を描画します。 //! //! @param context コンテキストです。 //! @param x 文字を描画する位置のX座標です。 //! @param y 文字を描画する位置のY座標です。 //! @param code 描画する文字コードです。 //! void DrawChar(const PixelWriterContext& context, int x, int y, int code) { int ncode = (code >= 100) ? (code - 100) : code; int fontx = (ncode % FONT_ROW) * FONT_WIDTH; int fonty = (ncode / FONT_ROW) * FONT_HEIGHT; const u32* fontLine = (code < 100) ? (sFontData + fonty) : (sFontData2 + fonty); // バッファ範囲から外れてる場合は出力しない if (x < 0 || context.m_LimitX <= x + FONT_WIDTH) { return; } if (y < 0 || context.m_LimitY <= y + FONT_HEIGHT) { return; } for (int cnty = 0; cnty < FONT_HEIGHT; cnty++) { u32 fontBits = (*fontLine++) << fontx; // フォントデータは左につめられてる。 // 左近傍のビットにアクセスできるように、1ビット余白を付加する。 fontBits = (fontBits & 0xfc000000) >> 1; for (int cntx = 0; cntx < FONT_WIDTH; cntx += 1) { u8* pixel = this->GetPixelAddress(context, x + cntx, y + cnty); if (fontBits & 0x40000000) { this->WritePixel(pixel, context.m_PixelColor); } fontBits <<= 1; } } } //! @brief 改行文字もしくは終端文字までの文字数を取得します。 //! //! @details //! タブ文字はスペースに展開されます。 //! //! @param str 文字列へのポインタです。 //! //! @return 文字数を返します。 //! int StrLineWidth(const char* str) { int len = 0; char c; NW_NULL_ASSERT(str); while (true) { c = *str++; if (c == '\0' || c == '\n') { return len; } if (c == '\t') { len = (len + TAB_WIDTH) & ~(TAB_WIDTH - 1); } else { ++len; } } } protected: virtual int GetPixelSize() const = 0; virtual void ErasePixel(u8* pixel) const = 0; virtual void MakePixel(u8 pixel[4], ut::Color color) const = 0; virtual void WritePixel(u8* dest, const u8 pixel[4]) const = 0; }; class PixelWriter_RGBA8 : public PixelWriter { virtual int GetPixelSize() const { return 4; } virtual void ErasePixel(u8* pixel) const { // アルファには手をつけない。 // TODO: 暗くする。 pixel[0] = 0; pixel[1] = 0; pixel[2] = 0; } virtual void MakePixel(u8 pixel[4], ut::Color color) const { pixel[0] = color.r; pixel[1] = color.g; pixel[2] = color.b; pixel[3] = 255; } virtual void WritePixel(u8* dest, const u8 pixel[4]) const { dest[0] = pixel[0]; dest[1] = pixel[1]; dest[2] = pixel[2]; dest[3] = pixel[3]; } }; class PixelWriter_RGB8 : public PixelWriter { virtual int GetPixelSize() const { return 3; } virtual void ErasePixel(u8* pixel) const { // TODO: 暗くする。 pixel[0] = 0; pixel[1] = 0; pixel[2] = 0; } virtual void MakePixel(u8 pixel[4], ut::Color color) const { pixel[0] = color.r; pixel[1] = color.g; pixel[2] = color.b; } virtual void WritePixel(u8* dest, const u8 pixel[4]) const { dest[0] = pixel[0]; dest[1] = pixel[1]; dest[2] = pixel[2]; } }; class PixelWriter_RGBA4 : public PixelWriter { virtual int GetPixelSize() const { return 2; } virtual void ErasePixel(u8* pixel) const { // アルファには手をつけない。 // TODO: 暗くする。 pixel[0] = 0; pixel[1] &= 0x0f; } virtual void MakePixel(u8 pixel[4], ut::Color color) const { u16 val = (color.r & 0xf0) << 8 | (color.g & 0xf0) << 4 | (color.b & 0xf0) | 0x0f; pixel[0] = static_cast((val >> 8) & 0xff); pixel[1] = static_cast((val >> 0) & 0xff); } virtual void WritePixel(u8* dest, const u8 pixel[4]) const { dest[0] = pixel[0]; dest[1] = pixel[1]; } }; class PixelWriter_RGB5A1 : public PixelWriter { virtual int GetPixelSize() const { return 2; } virtual void ErasePixel(u8* pixel) const { // アルファには手をつけない。 // TODO: 暗くする。 pixel[0] = 0; pixel[1] &= 0x01; } virtual void MakePixel(u8 pixel[4], ut::Color color) const { u16 val = (color.r & 0xf8) << 8 | (color.g & 0xf8) << 3 | (color.b & 0xf8) >> 2 | 0x01; pixel[0] = static_cast((val >> 8) & 0xff); pixel[1] = static_cast((val >> 0) & 0xff); } virtual void WritePixel(u8* dest, const u8 pixel[4]) const { dest[0] = pixel[0]; dest[1] = pixel[1]; } }; class PixelWriter_RGB565 : public PixelWriter { virtual int GetPixelSize() const { return 2; } virtual void ErasePixel(u8* pixel) const { // TODO: 暗くする。 pixel[0] = 0; pixel[1] &= 0x01; } virtual void MakePixel(u8 pixel[4], ut::Color color) const { u16 val = (color.r & 0xf8) << 8 | (color.g & 0xfc) << 3 | (color.b & 0xf8) >> 3; pixel[0] = static_cast((val >> 8) & 0xff); pixel[1] = static_cast((val >> 0) & 0xff); } virtual void WritePixel(u8* dest, const u8 pixel[4]) const { dest[0] = pixel[0]; dest[1] = pixel[1]; } }; //! @brief フォーマットに対応するPixelWriterを取得します。 //! //! @param format ピクセルのフォーマットです。 //! //! @return PixelWriterへの参照を返します。 //! PixelWriter& GetPixelWriter_(GLuint format) { switch (format) { case GL_RGBA8_OES: { static PixelWriter_RGBA8 pixelWriterRGBA8; return pixelWriterRGBA8; } case GL_RGB8_OES: { static PixelWriter_RGB8 pixelWriterRGB8; return pixelWriterRGB8; } case GL_RGBA4: { static PixelWriter_RGBA4 pixelWriterRGBA4; return pixelWriterRGBA4; } case GL_RGB5_A1: { static PixelWriter_RGB5A1 pixelWriterRGB5A1; return pixelWriterRGB5A1; } case GL_RGB565: { static PixelWriter_RGB565 pixelWriterRGB565; return pixelWriterRGB565; } default: NW_FATAL_ERROR("unexpected pixel format (0x%x).", format); return *(PixelWriter*)(-1); } } } // namespace {anonymous} DirectPrint::DirectPrint() : m_Initialized(false) { } DirectPrint::~DirectPrint() { if (m_Initialized) { this->Finalize(); } } void DirectPrint::Initialize() { if (this->m_Initialized) { return; } this->SetTargetBuffer(NULL, 0, 320, 240); this->SetColor(255, 255, 255); this->SetDirection(DIRECTION_VERTICAL); m_Initialized = true; } void DirectPrint::Finalize() { if (m_Initialized) { m_Initialized = false; } } bool DirectPrint::IsActive() const { return m_Initialized && m_Buffer.m_Address != NULL; } void DirectPrint::SetTargetBuffer( void* buffer, GLuint format, u16 width, u16 height) { m_Buffer.m_Address = static_cast(buffer); m_Buffer.m_Format = format; m_Buffer.m_Width = width; m_Buffer.m_Height = height; } void DirectPrint::SetTargetBuffer(void* buffer) { m_Buffer.m_Address = static_cast(buffer); } void DirectPrint::SetTargetActiveDisplayBuffer() { #ifdef NW_PLATFORM_CTR GLint address = 0; nngxGetDisplaybufferParameteri(NN_GX_DISPLAYBUFFER_ADDRESS, &address); NW_ASSERT(address != 0); GLint format = 0; nngxGetDisplaybufferParameteri(NN_GX_DISPLAYBUFFER_FORMAT, &address); GLint width = 0; nngxGetDisplaybufferParameteri(NN_GX_DISPLAYBUFFER_WIDTH, &address); GLint height = 0; nngxGetDisplaybufferParameteri(NN_GX_DISPLAYBUFFER_HEIGHT, &address); this->SetTargetBuffer( reinterpret_cast(address), format, static_cast(width), static_cast(height)); #else NW_FATAL_ERROR("unavailable."); #endif } void DirectPrint::StoreCache() { // ---- 書き換えたフレームバッファをフラッシュ // DCStoreRange(sFrameBufferInfo.frameMemory, sFrameBufferInfo.frameSize); // TODO: キャッシュのストア } void DirectPrint::Erase(int x, int y, int width, int height) { if (!this->IsActive()) { return; } PixelWriter& pixelWriter = GetPixelWriter_(m_Buffer.m_Format); pixelWriter.Erase(m_Buffer, m_Direction, x, y, width, height); } void DirectPrint::Printf(int x, int y, const char* format, ...) { std::va_list vargs; va_start(vargs, format); this->VPrintf(x, y, format, vargs, true, true); va_end(vargs); } void DirectPrint::Printf(int x, int y, bool turnOver, const char* format, ...) { std::va_list vargs; va_start(vargs, format); this->VPrintf(x, y, format, vargs, turnOver, true); va_end(vargs); } void DirectPrint::VPrintf( int x, int y, const char* format, std::va_list vargs, bool turnOver, bool backErase) { static const size_t BUFFER_SIZE = 256; char buffer[BUFFER_SIZE]; int length = ut::vsnprintf(buffer, BUFFER_SIZE, BUFFER_SIZE-1, format, vargs); if (length <= 0) { return; } this->DrawString(x, y, buffer, turnOver, backErase); } void DirectPrint::SetColor(ut::Color8 color) { m_Color = color; } void DirectPrint::SetColor(u8 r, u8 g, u8 b) { m_Color = ut::Color(r, g, b, 255 /* unused */); } ut::Color8 DirectPrint::GetColor() const { return m_Color; } void DirectPrint::SetDirection(Direction direction) { m_Direction = direction; } DirectPrint::Direction DirectPrint::GetDirection() const { return m_Direction; } void DirectPrint::DrawString( int x, int y, const char* str, bool turnOver, bool backErase) { NW_NULL_ASSERT(str); if (!this->IsActive()) { return; } PixelWriter& pixelWriter = GetPixelWriter_(m_Buffer.m_Format); pixelWriter.DrawString(m_Buffer, m_Direction, m_Color, x, y, str, turnOver, backErase); } } // namespace nw::dev } // namespace nw #endif