Android 上的 定位字元(tab) —— 一個神奇的字元 (cocos2dx crash)

來源:互聯網
上載者:User

今天測試發現了遊戲的一個問題,系統郵件,如果發了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了。<喎?http://www.bkjia.com/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。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.