#include "Utility.h" #include "ui/CocosGUI.h" #if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) #include "iconv.h" #endif #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) #include "android/jni/JniHelper.h" #endif #include "Helps.h" ////////////////////////////////////////////////////////////////////////// /** * 计算utf8字符串长度 * @param utf8 utf8字符串 * @return 字符串长度 */ int utf8_len(const char *utf8) { int i = 0, j = 0; while (utf8[i]) { if ((utf8[i] & 0xc0) != 0x80) j++; i++; } return j; } int utf8_cmp(const char* str1, const char* str2) { unsigned int len1=(unsigned int)strlen((char*)str1); unsigned int len2=(unsigned int)strlen((char*)str2); unsigned int len = (len1 len2) ret = 1; else if(len1 < len2) ret = -1; } return ret; } /** * 计算ucs2字符串长度 * @param ucs2 ucs2字符串 * @return 字符串长度 */ int ucs2_len(const unsigned short* ucs2) { int i = 0; while (ucs2[i] != 0) { char c0 = ucs2[i]&0xff; char c1 = ucs2[i]>>8&0xff; if (c0 == '\0' && c1 == '\0') break; ++i; } return i; } ///////////////////////////////////////////////////////////////////////////// int code_convert(const char *from_charset, const char *to_charset, const char *inbuf, size_t inlen, char *outbuf, size_t outlen) { #if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) const UINT CP_GBK = 936; int wlen = MultiByteToWideChar(CP_GBK, 0, inbuf, inlen, NULL, 0); if (wlen <= 0) return -1; wchar_t* wbuf = new wchar_t[wlen + 1]; MultiByteToWideChar(CP_GBK, 0, inbuf, inlen, wbuf, wlen); wbuf[wlen] = 0; int ulen = WideCharToMultiByte(CP_UTF8, 0, wbuf, wlen, NULL, 0, NULL, NULL); if (ulen <= 0 || ulen >= (int)outlen) { delete[] wbuf; return -1; } memset(outbuf, 0, outlen); WideCharToMultiByte(CP_UTF8, 0, wbuf, wlen, outbuf, ulen, NULL, NULL); delete[] wbuf; return 0; #endif #if (CC_TARGET_PLATFORM != CC_PLATFORM_WIN32) // Android: use JNI to convert GBK -> UTF-8 via Java charset memset(outbuf, 0, outlen); if (strcmp(from_charset, "gbk") == 0 || strcmp(from_charset, "GBK") == 0) { cocos2d::JniMethodInfo minfo; if (cocos2d::JniHelper::getStaticMethodInfo(minfo, "com/jxkh/queyi/Native", "convertGbkToUtf8", "([B)Ljava/lang/String;")) { jbyteArray jBytes = minfo.env->NewByteArray(inlen); minfo.env->SetByteArrayRegion(jBytes, 0, inlen, (const jbyte*)inbuf); jstring jResult = (jstring)minfo.env->CallStaticObjectMethod(minfo.classID, minfo.methodID, jBytes); if (jResult) { const char* utf8Str = minfo.env->GetStringUTFChars(jResult, NULL); size_t utf8Len = strlen(utf8Str); if (utf8Len < outlen) { memcpy(outbuf, utf8Str, utf8Len); } minfo.env->ReleaseStringUTFChars(jResult, utf8Str); minfo.env->DeleteLocalRef(jResult); } minfo.env->DeleteLocalRef(jBytes); minfo.env->DeleteLocalRef(minfo.classID); return 0; } } // Fallback: direct copy size_t copyLen = (inlen < outlen) ? inlen : outlen - 1; memcpy(outbuf, inbuf, copyLen); return 0; #endif return 0; } namespace utility { /** * 计算utf8字符串长度 * @param utf8 utf8字符串 * @return 字符串长度 */ int utf8_len(std::string utf8) { return strlen(utf8.c_str()); } int IsTextUTF8(const char* str,unsigned int length) { return 0; unsigned int i; unsigned long nBytes=0;//UFT8可用1-6个字节编码,ASCII用一个字节 unsigned char chr; int bAllAscii=1; //如果全部都是ASCII, 说明不是UTF-8 for(i=0;i=0x80) { if(chr>=0xFC&&chr<=0xFD) nBytes=6; else if(chr>=0xF8) nBytes=5; else if(chr>=0xF0) nBytes=4; else if(chr>=0xE0) nBytes=3; else if(chr>=0xC0) nBytes=2; else { return 0; } nBytes--; } } else //多字节符的非首字节,应为 10xxxxxx { if( (chr&0xC0) != 0x80 ) { return 0; } nBytes--; } } if( nBytes > 0 ) //违返规则 { return 0; } if( bAllAscii ) //如果全部都是ASCII, 说明不是UTF-8 { return 0; } return 1; } static bool isValidUtf8(const char* data, size_t len) { const unsigned char* p = (const unsigned char*)data; bool hasMultiByte = false; size_t i = 0; while (i < len) { if (p[i] <= 0x7F) { i++; continue; } hasMultiByte = true; int seqLen = 0; if ((p[i] & 0xE0) == 0xC0) seqLen = 2; else if ((p[i] & 0xF0) == 0xE0) seqLen = 3; else if ((p[i] & 0xF8) == 0xF0) seqLen = 4; else return false; if (i + seqLen > len) return false; for (int j = 1; j < seqLen; j++) { if ((p[i + j] & 0xC0) != 0x80) return false; } i += seqLen; } return hasMultiByte; } std::string a_u8(std::string gbk) { size_t inlen = strlen(gbk.c_str()); if (inlen <= 0) { return std::string(); } if (isValidUtf8(gbk.c_str(), inlen)) { return gbk; } char * outbuf = new char[inlen * 4+2]; std::string strRet = gbk; if(code_convert("gbk", "utf-8", gbk.c_str(), inlen, outbuf, inlen * 4+2 ) == 0) { strRet = outbuf; } delete [] outbuf; return strRet; } std::string u8_a(std::string utf8) { size_t inlen = strlen(utf8.c_str()); if (inlen <= 0) { return ""; } char * outbuf = new char[inlen * 4+2]; std::string strRet = utf8; if(code_convert("utf-8", "gbk", utf8.c_str(), inlen, outbuf, inlen*4+2) == 0) { strRet = outbuf; } else { strRet = "Error"; } delete [] outbuf; return strRet; } /*gbk转为UTF16*/ std::string a2l(const char *inbuf) { size_t inlen = strlen(inbuf); std::string strRet; strRet.resize(inlen * 2 + 2); if (code_convert("gbk", "UTF-16LE", inbuf, inlen, &strRet[0], strRet.size())) return inbuf; return strRet; } /*utf16转为UTF8*/ std::string l2u(const char *inbuf) { size_t inlen = ucs2_len((const unsigned short*)&inbuf[0]); std::string strRet; strRet.resize(inlen * 2 + 2); if (code_convert("UTF-16LE", "utf-8", inbuf, inlen * 2, &strRet[0], strRet.size())) return inbuf; return strRet; } static std::string s_kDebugFileName = ""; static std::string s_kTime = ""; std::string getDebugFileName() { return utility::toString(cocos2d::FileUtils::getInstance()->getWritablePath(), s_kDebugFileName); } void mlog(const char * format, ...) { va_list args; va_start(args, format); const int iMaxLenght = 1024; char buf[iMaxLenght] = {0}; vsnprintf(buf, iMaxLenght - 3, format, args); strcat(buf, "\n"); strcat(buf, "\0"); std::string kStr = utility::toString(s_kTime, " ", buf); if (s_kDebugFileName != "") { std::string kPathTxt = getDebugFileName(); FILE* file = fopen(kPathTxt.c_str(), "rb+"); if (!file) { file = fopen(kPathTxt.c_str(), "wb+"); } if (file) { fseek(file, 0L, SEEK_END); fwrite(kStr.c_str(), sizeof(char), strlen(kStr.c_str()), file); fclose(file); } } cocos2d::log("%s", buf); va_end(args); } float fAbs(const float& fValue) { if (fValue < 0.f) { return -fValue; } return fValue; } Texture2D* getCircleHead(const std::string& strPath) { Sprite* pSprFace = Sprite::create(strPath); CC_ASSERT(pSprFace != nullptr); if (pSprFace == nullptr) pSprFace = Sprite::create("common/Img/head_img_male.png"); if (pSprFace == nullptr) return nullptr; pSprFace->setPosition(0, 0); pSprFace->setAnchorPoint(Vec2(0, 0)); pSprFace->setFlippedY(true); // 头像剪切 auto textureCache = Director::getInstance()->getTextureCache(); auto texMask = textureCache->addImage("Platform/lobby/head_mask.png"); CC_ASSERT(texMask != nullptr); Sprite* sprMask = Sprite::createWithTexture(texMask); CC_ASSERT(sprMask != nullptr); setSpriteScaleBySize(sprMask, pSprFace->getContentSize()); sprMask->setPosition(0, 0); sprMask->setAnchorPoint(Vec2(0, 0)); //sprMask->setPosition(pSprFace->getContentSize().width / 2, pSprFace->getContentSize().height/2); RenderTexture* target = RenderTexture::create(pSprFace->getContentSize().width, pSprFace->getContentSize().height); BlendFunc maskBlend; maskBlend.src = GL_ONE; maskBlend.dst = GL_ZERO; sprMask->setBlendFunc(maskBlend); BlendFunc flowerBlend; flowerBlend.src = GL_DST_ALPHA; flowerBlend.dst = GL_ZERO; pSprFace->setBlendFunc(flowerBlend); target->begin(); sprMask->visit(); pSprFace->visit(); target->end(); return target->getSprite()->getTexture(); } float getRotation(cocos2d::Vec2 kSrcPos, cocos2d::Vec2 kDestPoint) { cocos2d::Vec2 kDestTance = kDestPoint - kSrcPos; float fAngle = kDestTance.getAngle(); return (-fAngle*180.0f / 3.14f); } void setSpriteScaleBySize(cocos2d::Node* pSprite, cocos2d::Size kSize) { if (!pSprite) { return; } float fScaleX = kSize.width / (float)pSprite->getContentSize().width; float fScaleY = kSize.height / (float)pSprite->getContentSize().height; pSprite->setScaleX(fScaleX); pSprite->setScaleY(fScaleY); } void setImagic(cocos2d::Node* pNode, std::string kImagic, bool bSame, bool bCircle/*=false*/) { CCAssert(pNode, ""); cocos2d::Sprite* pImagic = dynamic_cast(pNode); ui::ImageView* pImageView = dynamic_cast(pNode); if (pImagic) { CCAssert(pImagic, ""); cocos2d::Size sz = pImagic->getContentSize(); float fx = pImagic->getScaleX()*sz.width; float fy = pImagic->getScaleY()*sz.height; if (bCircle) { Texture2D* pTex = getCircleHead(kImagic); pImagic->setTexture(pTex); } else { pImagic->setTexture(kImagic); } CCAssert(pImagic->getTexture(), kImagic.c_str()); if (bSame) { utility::setSpriteScaleBySize(pImagic, cocos2d::Size(fx, fy)); } } else if (pImageView) { CCAssert(pImageView, ""); cocos2d::Size sz = pImageView->getContentSize(); float fx = pImageView->getScaleX()*sz.width; float fy = pImageView->getScaleY()*sz.height; pImageView->loadTexture(kImagic); if (bSame) { utility::setSpriteScaleBySize(pImagic, cocos2d::Size(fx, fy)); } } } void setButtonImagic(cocos2d::Node* pNode, std::string kFile, int bAutoPress) { cocos2d::ui::Button *pButton = dynamic_cast(pNode); cocos2d::Size sz = pButton->getContentSize(); pButton->loadTextureNormal(kFile); if (bAutoPress) { cocos2d::ResourceData res = pButton->getNormalFile(); pButton->loadTexturePressed(res.file); cocos2d::ui::Scale9Sprite* btnRender = pButton->getRendererClicked(); btnRender->setColor(cocos2d::Color3B(150, 150, 150)); } float fx = pButton->getScaleX()*sz.width; float fy = pButton->getScaleY()*sz.height; utility::setSpriteScaleBySize(pButton, cocos2d::Size(fx, fy)); } void setButtonImagic(cocos2d::Node* pNode, std::string kName, std::string kFile, int bAutoPress) { setButtonImagic(pNode->getChildByName(kName), kFile, bAutoPress); } void StringReplace(std::string &strBase, std::string strSrc, std::string strDes, bool bReplaceAll) { std::string::size_type pos = 0; std::string::size_type srcLen = strSrc.size(); std::string::size_type desLen = strDes.size(); pos = strBase.find(strSrc, pos); while (pos != std::string::npos) { strBase.replace(pos, srcLen, strDes); pos = strBase.find(strSrc, (pos + desLen)); if (!bReplaceAll) { break; } } } //超出宽度用星号代替(参数:昵称,字体文件,字体大小,超出宽度) std::string getShortName(const std::string& strName, const std::string& strFont, float fFontSize, float fOverWidth) { size_t nCount = strName.size(); float fTotalWidth = 0.0f; for (int i = 0; i < nCount;) { std::string subStr = strName.substr(i, 1); bool bChinese = false; if ((subStr.c_str()[0] & 0x80) != 0) { subStr = strName.substr(i, 3); bChinese = true; i += 3; } else { i++; } auto tempLabel = cocos2d::Label::createWithSystemFont(subStr.c_str(), strFont, fFontSize); float tmpWidth = tempLabel->getContentSize().width; //tempLabel->autorelease(); fTotalWidth += tmpWidth; if (fTotalWidth >= fOverWidth) { return strName.substr(0, i - (bChinese ? 3 : 1)) + a_u8("…"); } } return strName; } std::string getShortName(const std::string& strName, int nFontNum) { size_t nCount = strName.size(); int nTempNum = 0; float fTotalWidth = 0.0f; for (int i = 0; i < nCount;) { std::string subStr = strName.substr(i, 1); bool bChinese = false; if ((subStr.c_str()[0] & 0x80) != 0) { bChinese = true; i += 3; nTempNum += 2; } else { i++; nTempNum++; } if (nTempNum > nFontNum) { return strName.substr(0, i - (bChinese ? 3 : 1)) + a_u8("…"); } } return strName; } std::string ScoreToString(SCORE lScore) { if (lScore > 0) { return StringUtils::format("+%d", lScore); } return StringUtils::format("%d", lScore); } std::string GetUserLevel(SCORE lGrade) { static std::string Levels[] = { "等级:雀蛋", "等级:雀仔", "等级:雀头", "等级:铜雀", "等级:银雀", "等级:金雀", "等级:雀王", "等级:雀皇", "等级:雀仙", "等级:雀圣", "等级:雀神" }; static SCORE lLevels[] = { 200, 500, 1000, 2000, 4000, 6000, 10000, 15000, 20000, 30000 }; int __ind = 0; for (__ind = 0; __ind < countarray(lLevels); __ind++) { if (lGrade < lLevels[__ind]) { break; } } if (__ind > countarray(Levels)) { __ind = countarray(Levels) - 1; } return Levels[__ind]; } std::string getIdentifyingCode(uint32 dwGameID) { time_t t = time(NULL); struct tm* tt = localtime(&t); char timeString[32] = { 0 }; sprintf(timeString, "wn%04d%02dmj%d", tt->tm_year + 1900, tt->tm_mon + 1, dwGameID); return Helps::MD5Encrypt(timeString); } }