Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 上的 制表符(tab) —— 一個神奇的字符 (cocos2dx crash)

Android 上的 制表符(tab) —— 一個神奇的字符 (cocos2dx crash)

編輯:關於Android編程

今天測試發現了游戲的一個問題,系統郵件,如果發了tab,在android上一打開郵件內容就會crash。而且他們很確定是tab的問題。


憑我多個月的經驗(確實沒多年。。。)來看,從來沒聽說在android上會因為一個tab崩潰,而且如果有這個問題,肯定會有很多人遇到,估計早就吵翻天了,搜索了一下,什麼可用信息都沒有。

於是寫個測試工程測試了一下,分別在mac下和windows下,用文本編輯工具編輯了4個txt文檔,utf有bom和無bom,內容是“ tab abcd ”,發現都能正常顯示,也不會crash。如下:

    unsigned long fSize = 0;
    unsigned char *data = CCFileUtils::sharedFileUtils()->getFileData("tab.txt", "rb", &fSize);
    
    CCLabelTTF *label = CCLabelTTF::create((const char*)data, "abc", 30);
    label->setPosition(ccp(visibleSize.width/2, visibleSize.height/2));

    addChild(label);

然後開始怒跟代碼,發現工程中使用了一個自定義控件,是為了實現一個富文本框的功能。所謂富文本框就是能顯示各種顏色,能顯示url,有的東西還能點的那種。但是這個東西的實現,其中有一步,是把一個utf8字符串拆開,拆成單個字符,把每個字符的紋理做出來,然後來拼圖,拼成一個文本框。那麼tab肯定會被拆成單個字符,最後發現就是在生成這個tab的紋理的時候,crash了。堆棧如下:

\

順便科普一下labelTTF顯示的原理,大致就是,通過字體和字號,然後調用相應平台的api,生成一張圖(image),注意是一張圖啊,然後作為紋理,設置給一個精靈。從上面的堆棧來看,就是在生成這個image的時候crash了。<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHA+ICAgIMi7uvPV0rT6wuujrNTaQ0NUZXh0dXJlMkTPwtXStb3Jz8PmttHVu7XE1+6689K7sr2jrMjnz8KjujwvcD4KPHA+PC9wPgo8cHJlIGNsYXNzPQ=="brush:java;">bool CCTexture2D::initWithString(const char *text, const char *fontName, float fontSize, const CCSize& dimensions, CCTextAlignment hAlignment, CCVerticalTextAlignment vAlignment) { … … … … do { CCImage* pImage = new CCImage(); CC_BREAK_IF(NULL == pImage); bRet = pImage->initWithString(text, (int)dimensions.width, (int)dimensions.height, eAlign, fontName, (int)fontSize); CC_BREAK_IF(!bRet); bRet = initWithImage(pImage); CC_SAFE_RELEASE(pImage); } while (0); … … … … return bRet; } 這裡第一步是,new一個image出來,然後用文字去init這個image,然後再用這個image去init這個texture。我們接著看init這個image這裡,android下的代碼是這樣的:

bool CCImage::initWithString(
                               const char *    pText, 
                               int             nWidth/* = 0*/, 
                               int             nHeight/* = 0*/,
                               ETextAlign      eAlignMask/* = kAlignCenter*/,
                               const char *    pFontName/* = nil*/,
                               int             nSize/* = 0*/)
{
    bool bRet = false;

    do 
    {
        CC_BREAK_IF(! pText);
        
        BitmapDC &dc = sharedBitmapDC();
        CC_BREAK_IF(! dc.getBitmapFromJava(pText, nWidth, nHeight, eAlignMask, pFontName, nSize));

        m_pData = dc.m_pData;
        CC_BREAK_IF(! m_pData);

        m_nWidth    = (short)dc.m_nWidth;
        m_nHeight   = (short)dc.m_nHeight;
        m_bHasAlpha = true;
        m_bPreMulti = true;
        m_nBitsPerComponent = 8;

        bRet = true;
    } while (0);

    return bRet;
}
其中重點是getBitmapFromJava這個函數,如下

    bool getBitmapFromJava(const char *text, int nWidth, int nHeight, CCImage::ETextAlign eAlignMask, const char * pFontName, float fontSize)
    {
    	return  getBitmapFromJavaShadowStroke(	text, nWidth, nHeight, eAlignMask, pFontName, fontSize );
    }
從這裡就知道了,肯定是把文字,字體,字號這些東西,叫給java層,讓它們調用系統相關的東西,返回一個bitmap回來,然後就是下一步,把這個返回的image去初始化texture。但是不需要下一步了,因為到這就crash了,得到如下log:

\

從這個log看,大概意思就是java層在創建bitmap的時候,需要一個圖片的寬高,但是這個大小等於0了。

但是之前測試是可以顯示tab的,仔細想想,之前的測試有一個問題,就是之前的測試都是tab加其他字符的混合,這個地方因為富文本框的處理,是單個tab字符,那麼再用單個tab測試一下。果然就和上面一樣crash了。

再回到這個crash log本身,這個要生成的圖,就是寫了字的那個圖,那麼這個圖片的寬高應該取決於字符的內容和字符的大小,怎麼會是0呢。難道是因為tab在android上面會被自動忽略。馬上再寫個工程測試:

    unsigned long fSize = 0;
    unsigned char *data = CCFileUtils::sharedFileUtils()->getFileData("tab.txt", "rb", &fSize);
    
    CCLabelTTF *label = CCLabelTTF::create((const char*)data, "abc", 30);
    label->setPosition(ccp(visibleSize.width/2, visibleSize.height/2));

    CCLayerColor *col = CCLayerColor::create(ccc4(123, 255,0 , 255));
    col->setContentSize(label->getContentSize());
    col->ignoreAnchorPointForPosition(false);
    col->setAnchorPoint(ccp(0.5, 0.5));
    col->setPosition(ccp(label->getPosition().x,label->getPosition().y));
    addChild(col);

    addChild(label);

這個測試和之前那個的區別,主要在於在文字後面加了一個同大小的色塊,這樣我們就能看到紋理的實際范圍(早該如此,其實是開始2了沒想到。。。),果然發現不管如何加tab,tab都不會顯示,紋理的大小和不加tab的大小是一樣的。


如果在cocos2dx上是這樣,但是他最後會調用到android系統的java層去生成這個bitmap,說明這個不是cocos2dx的問題,那麼在android應用上,tab會不會被忽略呢,果斷開個工程再測試,如下:



        


    tabTest
    		Hello world!
    Settings


果然還是沒顯示tab,哈哈哈哈哈大哭,收工~~


總結:android系統會忽略tab,在cocos2dx裡面用CCLabelTTF的時候,如果文本內容只有一個tab字符,會crash。
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved