/** @file JSImage.cpp @brief @author James @version 1.0 @date 2014_11_17 */ //包含头文件 #include "JSImage.h" #include #ifndef WEBASM #include #include "../JSInterface/JSInterface.h" #include "../../JCScriptRuntime.h" #include #include #include "JSRuntime.h" #include #else #include "../../JCScrpitRuntimeWASM.h" #endif #include "../../JCConch.h" #include "../../JCSystemConfig.h" #include #include namespace laya { #ifndef WEBASM ADDJSCLSINFO(JSImage, JSObjNode); #endif JSImage::JSImage() { m_pImage = new JCImage(); m_nID = JCConch::s_pConchRender->m_pImageManager->getImageID(); #ifndef WEBASM m_pImage->setManager(JCConch::s_pConchRender->m_pFileResManager, JCConch::s_pConchRender->m_pImageManager); m_CallbackRef.reset(new int(1)); m_bComplete = false; m_pClsInfo = &JSImage::JSCLSINFO; m_nDownloadState = 0; #else m_pImage->setManager(JCConch::s_pConchRender->m_pAtlasManager, JCConch::s_pConchRender->m_pTextureManager, NULL, JCConch::s_pConchRender->m_pImageManager); #endif } JSImage::~JSImage() { #ifndef WEBASM m_pOnLoad.Reset(); m_pOnError.Reset(); m_pObj.Reset(); JCMemorySurvey::GetInstance()->releaseClass( "image",this ); #endif destroy(); } void JSImage::destroy() { if (m_pImage) { //通知渲染线程 deleteImageOnRenderThread(m_nID); } } void JSImage::releaseTexture() { if (m_pImage) { releaseImageOnRenderThread(m_nID); } } #ifndef WEBASM void JSImage::onLoaded(std::weak_ptr callbackref) { std::function pFunction = std::bind(&JSImage::onLoadedCallJSFunction,this, callbackref); JCScriptRuntime::s_JSRT->m_pPoster->postToJS(pFunction); } void JSImage::onError( int p_nError,std::weak_ptr callbackref ) { std::function pFunction = std::bind(&JSImage::onErrorCallJSFunction,this,p_nError, callbackref); JCScriptRuntime::s_JSRT->m_pPoster->postToJS( pFunction ); } void JSImage::onLoadedCallJSFunction(std::weak_ptr callbackref) { if (!callbackref.lock()) return; if (JCScriptRuntime::s_JSRT->m_bIsExit == true)return; if (!IsMyJsEnv()) return; if (GetWidth() <= 0 || GetHeight() <= 0|| m_pImage->m_kBitmapData.m_pImageData==NULL) { m_pOnError.Call(500); } else { int nMemSize = GetWidth() * GetHeight() * 4 + 272; AdjustAmountOfExternalAllocatedMemory(nMemSize); JCMemorySurvey::GetInstance()->newClass("image", 1024, this); m_pImage->m_sUrl = m_sUrl; //通知渲染线程 createImageOnRenderThread(m_nID, m_pImage); m_bComplete = true; m_pOnLoad.Call(); } } void JSImage::onErrorCallJSFunction( int p_nError,std::weak_ptr callbackref ) { if (!callbackref.lock())return; if (JCScriptRuntime::s_JSRT->m_bIsExit == true)return; if (!IsMyJsEnv())return; LOGW("download image file error! %s\n", m_sUrl.c_str()); m_pOnError.Call(p_nError); } bool JSImage::getComplete() { return m_bComplete; } void JSImage::SetOnload(JSValueAsParam p_pFunction ) { m_pOnLoad.set(onloadid,this,p_pFunction); } JsValue JSImage::GetOnload() { return m_pOnLoad.getJsObj(); } void JSImage::SetOnError(JSValueAsParam p_pFunction ) { m_pOnError.set(onerrorid,this,p_pFunction); } JsValue JSImage::GetOnError() { return m_pOnError.getJsObj(); } JsValue JSImage::getObj() { return m_pObj.getJsObj(); } void JSImage::setObj(JSValueAsParam obj) { m_pObj.set(objid,this,obj); } const char* JSImage::getSrc() { return m_sUrl.c_str(); } bool JSImage::syncRestoreResource() { //if (!m_pImage || !m_pImage->m_pImageFile ) return false; //return m_pImage->m_pImageFile->downloadImage(true); return false; } void JSImage::setSrc( const char* p_sSrc ) { if (!p_sSrc) return; m_sUrl = p_sSrc; std::weak_ptr cbref(m_CallbackRef); downloadImage( false ); } void JSImage::onDecodeEnd(BitmapData& p_bmp, std::weak_ptr& callbackref) { if (!callbackref.lock()) { if (p_bmp.m_pImageData) { delete[] p_bmp.m_pImageData; } return; } if (m_pImage && m_pImage->m_kBitmapData.m_pImageData) { m_pImage->m_kBitmapData.releaseData(); m_pImage->m_kBitmapData.m_pImageData = NULL; } m_pImage->m_kBitmapData = p_bmp; onLoaded(callbackref); } void JSImage::onDecodeEndDecThread(BitmapData p_bmp, std::weak_ptr& callbackref) { JCScriptRuntime::s_JSRT->m_pPoster->postToJS(std::bind(&JSImage::onDecodeEnd, this, p_bmp, callbackref)); } void JSImage::onDownloadOK(JCResStateDispatcher* p_pRes, bool p_bDecodeSync, std::weak_ptr& callbackref) { m_nDownloadState = 0; JCFileRes* pFileRes = (JCFileRes*)p_pRes; if (pFileRes->m_pBuffer.get()) { releaseThis(); //同步加载 if (p_bDecodeSync) { } else { imgDecodeCB cb = std::bind(&JSImage::onDecodeEndDecThread, this, std::placeholders::_1, callbackref); loadImageMemASync(pFileRes->m_pBuffer, pFileRes->m_nLength, cb); } } else { onDownloadError(p_pRes, 1, callbackref); } } void JSImage::onDownloadError(JCResStateDispatcher*, int e, std::weak_ptr& callbackref) { if (!callbackref.lock())return; releaseThis(); m_nDownloadState = 0; onError(e,callbackref); } bool JSImage::downloadImage(bool p_bSyncDecode) { if (m_nDownloadState == 1)return false; m_nDownloadState = 1; //TODO 要处理本地文件的情况 std::weak_ptr cbref(m_CallbackRef); JCFileRes* pRes = JCScriptRuntime::s_JSRT->m_pFileResMgr->getRes(m_sUrl); pRes->setOnReadyCB(std::bind(&JSImage::onDownloadOK, this, std::placeholders::_1, false, cbref)); pRes->setOnErrorCB(std::bind(&JSImage::onDownloadError, this, std::placeholders::_1, std::placeholders::_2, cbref)); retainThis(); return true; } int JSImage::GetWidth() { return m_pImage->getWidth(); } int JSImage::GetHeight() { return m_pImage->getHeight(); } void JSImage::setPremultiplyAlpha(bool bPremultiplyAlpha) { if (g_kSystemConfig.m_nThreadMODE == THREAD_MODE_DOUBLE) { JCScriptRuntime::s_JSRT->flushSharedCmdBuffer(); JCCommandEncoderBuffer* pCmd = JCScriptRuntime::s_JSRT->m_pRenderCmd; pCmd->append(LAYA_SET_PREMULTIPLY_ALPHA); pCmd->append(m_nID); pCmd->append((int)bPremultiplyAlpha); } else { JCImage* pImage = JCConch::s_pConchRender->m_pImageManager->getImage(m_nID); if (pImage) { pImage->setPremultiplyAlpha(bPremultiplyAlpha); } } } void JSImage::putBitmapDataJS(JSValueAsParam pArrayBuffer, int width, int height) { char* pArrayBufferPtr = NULL; int nABLen = 0; bool bIsArrayBuffer = extractJSAB(pArrayBuffer, pArrayBufferPtr, nABLen); if (bIsArrayBuffer) { if (nABLen >= width * height * 4) { putBitmapData(pArrayBufferPtr,width, height); } else { LOGE("JSImage::pushBitmapData array buffer size < width * height * 4"); } } else { LOGE("JSImage::pushBitmapData param is not an ArrayBuffer!"); } } static void deleter(char* p) { //不删除 JS保证在onDecodeEndDecThread前pArrayBuffer不垃圾回收 } void JSImage::putDataJS(JSValueAsParam pArrayBuffer) { char* pArrayBufferPtr = NULL; int nABLen = 0; bool bIsArrayBuffer = extractJSAB(pArrayBuffer, pArrayBufferPtr, nABLen); if (bIsArrayBuffer) { if (nABLen <= 0) return; //设置url的名字 char sCachePath[1024]; memset(sCachePath, 0, 1024); sprintf(sCachePath, "%s/%d.LayaBoxImg", JCConch::s_pConch->m_sCachePath.c_str(), m_nID); m_sUrl = sCachePath; std::weak_ptr cbref(m_CallbackRef); imgDecodeCB cb = std::bind(&JSImage::onDecodeEndDecThread, this, std::placeholders::_1, cbref); std::shared_ptr pBuffer(pArrayBufferPtr, deleter); loadImageMemASync(pBuffer, nABLen, cb); } else { LOGE("JSImage::putData param is not an ArrayBuffer!"); } } void JSImage::setBase64(char* base64) { if (!base64) return; //设置url的名字 char sCachePath[1024]; memset(sCachePath, 0, 1024); sprintf(sCachePath, "%s/%d.LayaBoxImg", JCConch::s_pConch->m_sCachePath.c_str(), m_nID); m_sUrl = sCachePath; std::weak_ptr cbref(m_CallbackRef); imgDecodeCB cb = std::bind(&JSImage::onDecodeEndDecThread, this, std::placeholders::_1, cbref); int length = 0; std::shared_ptr pBuffer(base64_decode((const unsigned char*)base64, strlen(base64), &length)); loadImageMemASync(pBuffer, length, cb); } void JSImage::putBitmapData(char* pData, int width, int height ) { if (m_pImage && m_pImage->m_kBitmapData.m_pImageData) { m_pImage->m_kBitmapData.releaseData(); m_pImage->m_kBitmapData.m_pImageData = NULL; } m_pImage->m_kBitmapData.m_nWidth = width; m_pImage->m_kBitmapData.m_nHeight = height; m_pImage->m_kBitmapData.m_pImageData = new char[width * height * 4]; memcpy(m_pImage->m_kBitmapData.m_pImageData, pData, width*height * 4); //设置url的名字 char sCachePath[1024]; memset(sCachePath, 0, 1024); sprintf(sCachePath,"%s/%d.LayaBoxImg", JCConch::s_pConch->m_sCachePath.c_str(),m_nID); //写入文件 writeFileSync1(sCachePath, pData, width*height * 4); m_sUrl = sCachePath; m_pImage->m_bPushBitmapData = true; onLoaded(m_CallbackRef); } JsValue JSImage::getImageData( int p_nX,int p_nY,int p_nW,int p_nH ) { if( m_bComplete == false ) return JSP_TO_JS_NULL; if( m_pImage == NULL ) return JSP_TO_JS_NULL; BitmapData* pImg = &(m_pImage->m_kBitmapData); if( pImg ) { if( p_nX < 0 || p_nY < 0 || p_nX >= pImg->m_nWidth || p_nY >= pImg->m_nHeight )return JSP_TO_JS_NULL; if( ( p_nX + p_nW ) > pImg->m_nWidth || ( p_nY + p_nH ) > pImg->m_nHeight )return JSP_TO_JS_NULL; if (pImg->m_pImageData != NULL || (pImg->m_pImageData == NULL && m_pImage->enableImage())) { if( p_nX == 0 && p_nY == 0 && p_nW == pImg->m_nWidth && p_nH == pImg->m_nHeight ) { return createJSAB( (char *)(pImg->m_pImageData),pImg->m_nWidth * pImg->m_nHeight * 4 ); } else { unsigned char* pTemp = (unsigned char *)(pImg->m_pImageData); int nSize = p_nH * p_nW * 4; int nDstLine = p_nW*4; int nSrcLine = pImg->m_nWidth*4; unsigned char* pBuffer = new unsigned char[nSize]; for( int i = 0; i < p_nH; i++ ) { memcpy(&pBuffer[nDstLine*i],&pTemp[nSrcLine*(i+p_nY)+p_nX*4],nDstLine); } return createJSAB( (char*)pBuffer,nSize ); } } } return JSP_TO_JS_NULL; } #endif void JSImage::setImageInfo(const char* sUrl, int w, int h) { #ifdef WEBASM if(sUrl)m_pImage->m_sUrl = sUrl; m_pImage->m_kBitmapData.m_nWidth = w; m_pImage->m_kBitmapData.m_nHeight = h; createImageOnRenderThread(m_nID, m_pImage); #endif } int JSImage::getImageID() { return m_nID; } #ifndef WEBASM void JSImage::exportJS() { JSP_CLASS("conchImage", JSImage); JSP_ADD_PROPERTY_RO(conchImgId, JSImage, getImageID); JSP_ADD_PROPERTY_RO(width, JSImage, GetWidth); JSP_ADD_PROPERTY_RO(height, JSImage, GetHeight); JSP_ADD_METHOD("setBase64", JSImage::setBase64); JSP_ADD_PROPERTY(src, JSImage, getSrc, setSrc); JSP_ADD_PROPERTY(_onload, JSImage, GetOnload, SetOnload); JSP_ADD_PROPERTY(onload, JSImage, GetOnload, SetOnload); JSP_ADD_PROPERTY(onerror, JSImage, GetOnError, SetOnError); JSP_ADD_PROPERTY(obj, JSImage, getObj, setObj); JSP_ADD_PROPERTY_RO(complete, JSImage, getComplete); JSP_ADD_METHOD("getImageID", JSImage::getImageID); JSP_ADD_METHOD("setSrc", JSImage::setSrc); JSP_ADD_METHOD("getImageData", JSImage::getImageData); JSP_ADD_METHOD("putBitmapData", JSImage::putBitmapDataJS); JSP_ADD_METHOD("putData", JSImage::putDataJS); JSP_ADD_METHOD("setPremultiplyAlpha", JSImage::setPremultiplyAlpha); JSP_ADD_METHOD("syncRestoreResource", JSImage::syncRestoreResource); JSP_ADD_METHOD("destroy", JSImage::destroy); JSP_INSTALL_CLASS("conchImage", JSImage); } #endif void JSImage::createImageOnRenderThread(int nID, JCImage* pImage) { if (g_kSystemConfig.m_nThreadMODE == THREAD_MODE_DOUBLE) { JCScriptRuntime::s_JSRT->flushSharedCmdBuffer(); JCCommandEncoderBuffer* pCmd = JCScriptRuntime::s_JSRT->m_pRenderCmd; pCmd->append(LAYA_CREATE_IMAGE_ON_RENDER_THREAD); pCmd->append(nID); pCmd->append((long)(pImage)); } else { JCConch::s_pConchRender->m_pImageManager->setImage(nID, pImage); } } void JSImage::deleteImageOnRenderThread(int nID) { JCCommandEncoderBuffer* pCmd = JCScriptRuntime::s_JSRT->m_pGCCmd; pCmd->append(LAYA_DELETE_IMAGE_ON_RENDER_THREAD); pCmd->append(nID); } void JSImage::releaseImageOnRenderThread(int nID) { JCCommandEncoderBuffer* pCmd = JCScriptRuntime::s_JSRT->m_pGCCmd; pCmd->append(LAYA_RELEASE_IMAGE_ON_RENDER_THREAD); pCmd->append(nID); } } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ //-----------------------------END FILE--------------------------------