void *DataChunker::alloc(S32 size) { if (size > mChunkSize) { DataBlock * temp = (DataBlock*)dMalloc(DataChunker::PaddDBSize + size); AssertFatal(temp, "Malloc failed"); constructInPlace(temp); if (mCurBlock) { temp->next = mCurBlock->next; mCurBlock->next = temp; } else { mCurBlock = temp; temp->curIndex = mChunkSize; } return temp->getData(); } if(!mCurBlock || size + mCurBlock->curIndex > mChunkSize) { const U32 paddDBSize = (sizeof(DataBlock) + 3) & ~3; DataBlock *temp = (DataBlock*)dMalloc(paddDBSize+ mChunkSize); AssertFatal(temp, "Malloc failed"); constructInPlace(temp); temp->next = mCurBlock; mCurBlock = temp; } void *ret = mCurBlock->getData() + mCurBlock->curIndex; mCurBlock->curIndex += (size + 3) & ~3; // dword align return ret; }
bool PNGImage::Create(U32 width, U32 height, PNGImageType imageType) { mRead = true; mHeight = height; mWidth = width; mRowPointers = (png_bytep*) dMalloc(sizeof(png_bytep) * mHeight); unsigned int y = 0; for (y = 0; y < height; y++) mRowPointers[y] = (png_byte*) dMalloc(sizeof(png_bytep) * mWidth); if(imageType == PNGTYPE_RGBA) { mColorType = PNG_COLOR_TYPE_RGBA; mPNGImageType = PNGTYPE_RGBA; } else if(imageType == PNGTYPE_RGB) { mColorType = PNG_COLOR_TYPE_RGB; mPNGImageType = PNGTYPE_RGB; } else { mPNGImageType = PNGTYPE_UNKNOWN; } mBitDepth = 8; ClearImageData(); return true; }
ASMShaderParameter* ASMShader::getNamedParameter(StringTableEntry name) { for(U32 i = 0; i < mParameters.size(); i++) { if(dStricmp(mParameters[i]->mName, name) == 0) { return mParameters[i]; } } //No parameter... const char* paramString; ASMShaderParameter* param = NULL; paramString = dStrstr(mVertexSourceString, name); if(paramString) { param = new ASMShaderParameter; const char* openBracket = dStrstr(paramString, "["); const char* closeBracket = dStrstr(paramString, "]"); char* num = (char *)dMalloc((closeBracket - openBracket + 1) * sizeof(U8)); num = dStrncpy(num, openBracket + 1, (closeBracket - (openBracket + 1))); num[(closeBracket - (openBracket + 1))] = NULL; param->mName = StringTable->insert(name); param->mVertexId = dAtoi(num); const char* env = dStrstr(paramString, "program.env"); param->mVertexIsEnv = (env != NULL && env < openBracket); param->mFragmentId = -1; param->mFragmentIsEnv = false; mParameters.push_back(param); dFree(num); } paramString = dStrstr(mPixelSourceString, name); if(paramString) { if(!param) { param = new ASMShaderParameter; mParameters.push_back(param); param->mVertexId = -1; param->mVertexIsEnv = false; param->mName = StringTable->insert(name); } const char* openBracket = dStrstr(paramString, "["); const char* closeBracket = dStrstr(paramString, "]"); char* num = (char *)dMalloc((closeBracket - openBracket + 1) * sizeof(U8)); num = dStrncpy(num, openBracket + 1, (closeBracket - (openBracket + 1))); num[(closeBracket - (openBracket + 1))] = NULL; param->mFragmentId = dAtoi(num); const char* env = dStrstr(paramString, "program.env"); param->mFragmentIsEnv = (env != NULL && env < openBracket); dFree(num); } return param; }
//-------------------------------------- _StringTable::_StringTable() { buckets = (Node **) dMalloc(csm_stInitSize * sizeof(Node *)); for(U32 i = 0; i < csm_stInitSize; i++) { buckets[i] = 0; } numBuckets = csm_stInitSize; itemCount = 0; }
static dErr doMaterial(iMesh_Instance mesh,iBase_EntitySetHandle root) { static const char matSetName[] = "MAT_SET",matNumName[] = "MAT_NUM"; dMeshTag matSetTag,matNumTag; dMeshESH mat[2]; dMeshEH *ents; MeshListEH r=MLZ,v=MLZ; MeshListInt rvo=MLZ; MeshListReal x=MLZ; dReal fx,center[3],*matnum; dInt nents; dErr err; dFunctionBegin; iMesh_createTag(mesh,matSetName,1,iBase_INTEGER,&matSetTag,&err,sizeof(matSetName));dICHK(mesh,err); iMesh_createTag(mesh,matNumName,1,iBase_DOUBLE,&matNumTag,&err,sizeof(matNumName));dICHK(mesh,err); iMesh_getEntities(mesh,root,iBase_REGION,iMesh_ALL_TOPOLOGIES,MLREF(r),&err);dICHK(mesh,err); iMesh_getEntArrAdj(mesh,r.v,r.s,iBase_VERTEX,MLREF(v),MLREF(rvo),&err);dICHK(mesh,err); iMesh_getVtxArrCoords(mesh,v.v,v.s,iBase_INTERLEAVED,MLREF(x),&err);dICHK(mesh,err); err = dMalloc(r.s*sizeof(ents[0]),&ents);dCHK(err); err = dMalloc(r.s*sizeof(matnum[0]),&matnum);dCHK(err); for (dInt i=0; i<2; i++) { iMesh_createEntSet(mesh,0,&mat[i],&err);dICHK(mesh,err); iMesh_setEntSetData(mesh,mat[i],matSetTag,(char*)&i,sizeof(i),&err);dICHK(mesh,err); nents = 0; for (dInt j=0; j<r.s; j++) { dGeomVecMeanI(8,x.v+3*rvo.v[j],center); fx = sqrt(dGeomDotProd(center,center)); /* material 0 if inside the unit ball, else material 1 */ if (i == (fx < 1.0) ? 0 : 1) { ents[nents] = r.v[j]; matnum[nents] = 1.0 * i; nents++; } } iMesh_addEntArrToSet(mesh,ents,nents,mat[i],&err);dICHK(mesh,err); iMesh_setArrData(mesh,ents,nents,matNumTag,(char*)matnum,nents*(int)sizeof(matnum[0]),&err);dICHK(mesh,err); } err = dFree(ents);dCHK(err); err = dFree(matnum);dCHK(err); MeshListFree(r); MeshListFree(v); MeshListFree(rvo); MeshListFree(x); dFunctionReturn(0); }
MemFileData(MemFileSystem* fs, const Path& path) { mPath = path; mBufferSize = 1024; mFileSize = 0; mBuffer = dMalloc(mBufferSize); dMemset(mBuffer, 0, mBufferSize); mModified = Time::getCurrentTime(); mLastAccess = mModified; mFileSystem = fs; }
S32 PASCAL WinMain( HINSTANCE hInstance, HINSTANCE, LPSTR lpszCmdLine, S32) { #if 0 // Run a unit test. StandardMainLoop::initCore(); UnitTesting::TestRun tr; tr.test("Platform", true); #else Vector<char *> argv( __FILE__, __LINE__ ); char moduleName[256]; #ifdef TORQUE_UNICODE { TCHAR buf[ 256 ]; GetModuleFileNameW( NULL, buf, sizeof( buf ) ); convertUTF16toUTF8( buf, moduleName, sizeof( moduleName ) ); } #else GetModuleFileNameA(NULL, moduleName, sizeof(moduleName)); #endif argv.push_back(moduleName); for (const char* word,*ptr = lpszCmdLine; *ptr; ) { // Eat white space for (; dIsspace(*ptr) && *ptr; ptr++) ; // Pick out the next word for (word = ptr; !dIsspace(*ptr) && *ptr; ptr++) ; // Add the word to the argument list. if (*word) { S32 len = ptr - word; char *arg = (char *) dMalloc(len + 1); dStrncpy(arg, word, len); arg[len] = 0; argv.push_back(arg); } } winState.appInstance = hInstance; S32 retVal = run(argv.size(), (const char **) argv.address()); for(U32 j = 1; j < argv.size(); j++) dFree(argv[j]); return retVal; #endif }
void DecalManager::_allocBuffers( DecalInstance *inst ) { const S32 sizeClass = _getSizeClass( inst ); void* data; if ( sizeClass == -1 ) data = dMalloc( sizeof( DecalVertex ) * inst->mVertCount + sizeof( U16 ) * inst->mIndxCount ); else data = mChunkers[sizeClass]->alloc(); inst->mVerts = reinterpret_cast< DecalVertex* >( data ); data = (U8*)data + sizeof( DecalVertex ) * inst->mVertCount; inst->mIndices = reinterpret_cast< U16* >( data ); }
static dErr createUniformTags(iMesh_Instance mesh,iBase_EntitySetHandle root) { dMeshTag itag,rtag; MeshListEH ents=MLZ; int *idata; double *rdata; dErr err; dFunctionBegin; iMesh_getEntities(mesh,root,iBase_ALL_TYPES,iMesh_ALL_TOPOLOGIES,MLREF(ents),&err);dICHK(mesh,err); err = dMalloc(ents.s*sizeof(idata[0]),&idata);dCHK(err); err = dMalloc(ents.s*sizeof(rdata[0]),&rdata);dCHK(err); for (dInt i=0; i<ents.s; i++) { idata[i] = -i; rdata[i] = -1.0*i; } iMesh_createTag(mesh,"UNIFORM_INT",1,iBase_INTEGER,&itag,&err,sizeof("UNIFORM_INT"));dICHK(mesh,err); iMesh_createTag(mesh,"UNIFORM_REAL",1,iBase_DOUBLE,&rtag,&err,sizeof("UNIFORM_REAL"));dICHK(mesh,err); iMesh_setIntArrData(mesh,ents.v,ents.s,itag,idata,ents.s,&err);dICHK(mesh,err); iMesh_setDblArrData(mesh,ents.v,ents.s,rtag,rdata,ents.s,&err);dICHK(mesh,err); MeshListFree(ents); dFree(idata); dFree(rdata); dFunctionReturn(0); }
NetStringTable::NetStringTable() { firstFree = 1; firstValid = 1; table = (Entry *) dMalloc(sizeof(Entry) * InitialSize); size = InitialSize; for(U32 i = 0; i < InitialSize; i++) { table[i].next = i + 1; table[i].refCount = 0; table[i].scriptRefCount = 0; } table[InitialSize-1].next = InvalidEntry; for(U32 j = 0; j < HashTableSize; j++) hashTable[j] = 0; allocator = new DataChunker(DataChunkerSize); }
domCOLLADA* ColladaShapeLoader::readColladaFile(const String& path) { // Check if this file is already loaded into the database domCOLLADA* root = mDAE.getRoot(path.c_str()); if (root) return root; // Load the Collada file into memory FileStream colladaFile; U8 *data = NULL; if (colladaFile.open(path, FileStream::Read)) { U32 size = colladaFile.getStreamSize(); data = (U8*)dMalloc(size); colladaFile.read(size, data); } if (!data) { daeErrorHandler::get()->handleError(avar("Could not read %s into memory", path.c_str())); return NULL; } root = mDAE.openFromMemory(path.c_str(), (const char*)data); dFree(data); if (!root || !root->getLibrary_visual_scenes_array().getCount()) { daeErrorHandler::get()->handleError(avar("Could not parse %s", path.c_str())); return NULL; } // Fixup issues in the model ColladaUtils::applyConditioners(root); // Recursively load external DAE references //TSShapeLoader::updateProgress(TSShapeLoader::Load_ExternalRefs, "Loading external references..."); for (S32 iRef = 0; iRef < root->getDocument()->getReferencedDocuments().getCount(); iRef++) { String refPath = (daeString)root->getDocument()->getReferencedDocuments()[iRef]; if (refPath.endsWith(".dae") && !readColladaFile(refPath)) daeErrorHandler::get()->handleError(avar("Failed to load external reference: %s", refPath.c_str())); } return root; }
static dErr doGlobalNumber(iMesh_Instance mesh,iBase_EntitySetHandle root) { MeshListEH ents=MLZ; int owned,offset,*number; dMeshTag idTag; dErr err; dFunctionBegin; iMesh_getEntities(mesh,root,iBase_ALL_TYPES,iMesh_ALL_TOPOLOGIES,MLREF(ents),&err);dICHK(mesh,err); err = dMalloc(ents.s*sizeof(number[0]),&number);dCHK(err); owned = ents.s; offset = 0; for (int i=0; i<owned; i++) { number[i] = offset + i; } iMesh_createTag(mesh,"dohp_global_number",1,iBase_INTEGER,&idTag,&err,sizeof("dohp_global_number"));dICHK(mesh,err); iMesh_setIntArrData(mesh,ents.v,owned,idTag,number,owned,&err);dICHK(mesh,err); err = dFree(number);dCHK(err); MeshListFree(ents); dFunctionReturn(0); }
static dErr JakoGDALMemAddBand(GDALDatasetH dset,GDALDataType dtype,void *memory) { char buf[256] = {0},**bandoptions = NULL; int bytes,nx,ny; CPLErr cplerr; dErr err; dFunctionBegin; bytes = GDALGetDataTypeSize(dtype); nx = GDALGetRasterXSize(dset); ny = GDALGetRasterYSize(dset); err = dMalloc(nx*ny*bytes,(void**)memory);dCHK(err); // This is where the API moves from merely cumbersome to outright demeaning, like some twisted hazing ritual. CPLPrintPointer(buf,*(void**)memory,sizeof(buf)); bandoptions = CSLSetNameValue(bandoptions,"DATAPOINTER",buf); cplerr = GDALAddBand(dset,dtype,bandoptions);dCPLCHK(cplerr); CSLDestroy(bandoptions); dFunctionReturn(0); }
SimConsoleEvent::SimConsoleEvent(S32 argc, const char **argv, bool onObject) { mOnObject = onObject; mArgc = argc; U32 totalSize = 0; S32 i; for(i = 0; i < argc; i++) totalSize += dStrlen(argv[i]) + 1; totalSize += sizeof(char *) * argc; mArgv = (char **) dMalloc(totalSize); char *argBase = (char *) &mArgv[argc]; for(i = 0; i < argc; i++) { mArgv[i] = argBase; dStrcpy(mArgv[i], argv[i]); argBase += dStrlen(argv[i]) + 1; } }
static dErr doGlobalID(iMesh_Instance mesh,iBase_EntitySetHandle root) { MeshListEH ents=MLZ; MeshListInt type=MLZ; int count[4] = {0,0,0,0}; int owned,*number; dMeshTag idTag; dErr err; dFunctionBegin; iMesh_getEntities(mesh,root,iBase_ALL_TYPES,iMesh_ALL_TOPOLOGIES,MLREF(ents),&err);dICHK(mesh,err); iMesh_getEntArrType(mesh,ents.v,ents.s,MLREF(type),&err);dICHK(mesh,err); err = dMalloc(ents.s*sizeof(number[0]),&number);dCHK(err); owned = ents.s; for (int i=0; i<owned; i++) { number[i] = count[type.v[i]]++; } iMesh_getTagHandle(mesh,"GLOBAL_ID",&idTag,&err,sizeof("GLOBAL_ID"));dICHK(mesh,err); iMesh_setIntArrData(mesh,ents.v,owned,idTag,number,owned,&err);dICHK(mesh,err); err = dFree(number);dCHK(err); MeshListFree(ents); MeshListFree(type); dFunctionReturn(0); }
bool ATITShader::loadFragmentShaderFromFile(const char* fragPath) { char fileNameBufferPix[512]; Con::expandScriptFilename(fileNameBufferPix, sizeof(fileNameBufferPix), fragPath); const char* ps; Stream *p = ResourceManager->openStream(fileNameBufferPix); if(!p) { AssertWarn(false, avar("Failed to find ATIT fragment shader file: %s", fileNameBufferPix)); return false; } mPixelSourceStringLength = ResourceManager->getSize(fileNameBufferPix); mPixelSourceString = (char *)dMalloc((mPixelSourceStringLength + 1) * sizeof(U8)); p->read(mPixelSourceStringLength, mPixelSourceString); ResourceManager->closeStream(p); glEnable(GL_TEXT_FRAGMENT_SHADER_ATI); glGenProgramsARB(1, &mFragmentProgram); glBindProgramARB(GL_TEXT_FRAGMENT_SHADER_ATI, mFragmentProgram); glProgramStringARB(GL_TEXT_FRAGMENT_SHADER_ATI, GL_PROGRAM_FORMAT_ASCII_ARB, mPixelSourceStringLength, mPixelSourceString); #if defined(TORQUE_DEBUG) || defined(SHADER_MANAGER_DEBUG) const char* errorString = NULL; errorString = (const char*)glGetString(GL_PROGRAM_ERROR_STRING_ARB); Con::printf("Error string for %s is %s", fileNameBufferPix, errorString); if(errorString && errorString[0] != '\0') return false; #endif glDisable(GL_TEXT_FRAGMENT_SHADER_ATI); mFragFilepath = StringTable->insert(fileNameBufferPix); return true; }
void *a_Jpeg_new(DilloImage *Image, DilloUrl *url, int version) { my_source_mgr *src; DilloJpeg *jpeg = dMalloc(sizeof(*jpeg)); _MSG("a_Jpeg_new: jpeg=%p\n", jpeg); jpeg->Image = Image; jpeg->url = url; jpeg->version = version; jpeg->state = DILLO_JPEG_INIT; jpeg->Start_Ofs = 0; jpeg->Skip = 0; /* decompression step 1 (see libjpeg.doc) */ jpeg->cinfo.err = jpeg_std_error(&(jpeg->jerr.pub)); jpeg->jerr.pub.error_exit = Jpeg_errorexit; jpeg_create_decompress(&(jpeg->cinfo)); /* decompression step 2 (see libjpeg.doc) */ jpeg->cinfo.src = &jpeg->Src.pub; src = &jpeg->Src; src->pub.init_source = init_source; src->pub.fill_input_buffer = fill_input_buffer; src->pub.skip_input_data = skip_input_data; src->pub.resync_to_restart = jpeg_resync_to_restart;/* use default method */ src->pub.term_source = term_source; src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */ src->pub.next_input_byte = NULL;/* until buffer loaded */ src->jpeg = jpeg; /* decompression steps continue in write method */ return jpeg; }
S32 torque_winmain( HINSTANCE hInstance, HINSTANCE, LPSTR lpszCmdLine, S32) { Vector<char *> argv( __FILE__, __LINE__ ); char moduleName[256]; #ifdef TORQUE_UNICODE { TCHAR buf[ 256 ]; GetModuleFileNameW( NULL, buf, sizeof( buf ) ); convertUTF16toUTF8( buf, moduleName, sizeof( moduleName ) ); } #else GetModuleFileNameA(NULL, moduleName, sizeof(moduleName)); #endif argv.push_back(moduleName); for (const char* word,*ptr = lpszCmdLine; *ptr; ) { // Eat white space for (; dIsspace(*ptr) && *ptr; ptr++) ; // Test for quotes bool withinQuotes = dIsquote(*ptr); if (!withinQuotes) { // Pick out the next word for (word = ptr; !dIsspace(*ptr) && *ptr; ptr++) ; } else { // Advance past the first quote. We don't want to include it. ptr++; // Pick out the next quote for (word = ptr; !dIsquote(*ptr) && *ptr; ptr++) ; } // Add the word to the argument list. if (*word) { S32 len = ptr - word; char *arg = (char *) dMalloc(len + 1); dStrncpy(arg, word, len); arg[len] = 0; argv.push_back(arg); } // If we had a quote, skip past it for the next arg if (withinQuotes && *ptr) { ptr++; } } winState.appInstance = hInstance; S32 retVal = TorqueMain(argv.size(), (const char **) argv.address()); for(U32 j = 1; j < argv.size(); j++) dFree(argv[j]); return retVal; }
//----------------------------------------------------------------------------- // innerCreateTexture //----------------------------------------------------------------------------- // This just creates the texture, no info is actually loaded to it. We do that later. void GFXGLTextureManager::innerCreateTexture( GFXGLTextureObject *retTex, U32 height, U32 width, U32 depth, GFXFormat format, GFXTextureProfile *profile, U32 numMipLevels, bool forceMips) { // No 24 bit formats. They trigger various oddities because hardware (and Apple's drivers apparently...) don't natively support them. if(format == GFXFormatR8G8B8) format = GFXFormatR8G8B8A8; retTex->mFormat = format; retTex->mIsZombie = false; retTex->mIsNPoT2 = false; GLenum binding = ( (height == 1 || width == 1) && ( height != width ) ) ? GL_TEXTURE_1D : ( (depth == 0) ? GL_TEXTURE_2D : GL_TEXTURE_3D ); if((profile->testFlag(GFXTextureProfile::RenderTarget) || profile->testFlag(GFXTextureProfile::ZTarget)) && (!isPow2(width) || !isPow2(height)) && !depth) retTex->mIsNPoT2 = true; retTex->mBinding = binding; // Bind it PRESERVE_TEXTURE(binding); glBindTexture(retTex->getBinding(), retTex->getHandle()); // Create it // TODO: Reenable mipmaps on render targets when Apple fixes their drivers if(forceMips && !retTex->mIsNPoT2) { retTex->mMipLevels = numMipLevels > 1 ? numMipLevels : 0; } else if(profile->testFlag(GFXTextureProfile::NoMipmap) || profile->testFlag(GFXTextureProfile::RenderTarget) || numMipLevels == 1 || retTex->mIsNPoT2) { retTex->mMipLevels = 1; } else { retTex->mMipLevels = numMipLevels; } if(!retTex->mIsNPoT2) { if(!isPow2(width)) width = getNextPow2(width); if(!isPow2(height)) height = getNextPow2(height); if(depth && !isPow2(depth)) depth = getNextPow2(depth); } AssertFatal(GFXGLTextureInternalFormat[format] != GL_ZERO, "GFXGLTextureManager::innerCreateTexture - invalid internal format"); AssertFatal(GFXGLTextureFormat[format] != GL_ZERO, "GFXGLTextureManager::innerCreateTexture - invalid format"); AssertFatal(GFXGLTextureType[format] != GL_ZERO, "GFXGLTextureManager::innerCreateTexture - invalid type"); //calculate num mipmaps if(retTex->mMipLevels == 0) retTex->mMipLevels = getMaxMipmaps(width, height, 1); glTexParameteri(binding, GL_TEXTURE_MAX_LEVEL, retTex->mMipLevels-1 ); //If it wasn't for problems on amd drivers this next part could be really simplified and we wouldn't need to go through manually creating our //mipmap pyramid and instead just use glGenerateMipmap if(isCompressedFormat(format)) { AssertFatal(binding == GL_TEXTURE_2D, "GFXGLTextureManager::innerCreateTexture - Only compressed 2D textures are supported"); U32 tempWidth = width; U32 tempHeight = height; U32 size = getCompressedSurfaceSize(format,height,width); //Fill compressed images with 0's U8 *pTemp = (U8*)dMalloc(sizeof(U8)*size); dMemset(pTemp,0,size); for(U32 i=0; i< retTex->mMipLevels; i++) { tempWidth = getMax( U32(1), width >> i ); tempHeight = getMax( U32(1), height >> i ); size = getCompressedSurfaceSize(format,width,height,i); glCompressedTexImage2D(binding,i,GFXGLTextureInternalFormat[format],tempWidth,tempHeight,0,size,pTemp); } dFree(pTemp); } else { if(binding == GL_TEXTURE_2D)
static png_voidp pngRealMallocFn(png_structp /*png_ptr*/, png_size_t size) { AssertFatal( size <= U32_MAX, "Huge data." ); return (png_voidp)dMalloc( (U32)size ); }
void TerrainFile::_loadLegacy( FileStream &stream ) { // Some legacy constants. enum { MaterialGroups = 8, BlockSquareWidth = 256, }; const U32 sampleCount = BlockSquareWidth * BlockSquareWidth; mSize = BlockSquareWidth; // Load the heightmap. mHeightMap.setSize( sampleCount ); for ( U32 i=0; i < mHeightMap.size(); i++ ) stream.read( &mHeightMap[i] ); // Prior to version 7 we stored this weird material struct. const U32 MATERIAL_GROUP_MASK = 0x7; struct Material { enum Flags { Plain = 0, Rotate = 1, FlipX = 2, FlipXRotate = 3, FlipY = 4, FlipYRotate = 5, FlipXY = 6, FlipXYRotate = 7, RotateMask = 7, Empty = 8, Modified = BIT(7), // must not clobber TerrainFile::MATERIAL_GROUP_MASK bits! PersistMask = BIT(7) }; U8 flags; U8 index; }; // Temp locals for loading before we convert to the new // version 7+ format. U8 baseMaterialMap[sampleCount] = { 0 }; U8 *materialAlphaMap[MaterialGroups] = { 0 }; Material materialMap[BlockSquareWidth * BlockSquareWidth]; // read the material group map and flags... dMemset(materialMap, 0, sizeof(materialMap)); AssertFatal(!(Material::PersistMask & MATERIAL_GROUP_MASK), "Doh! We have flag clobberage..."); for (S32 j=0; j < sampleCount; j++) { U8 val; stream.read(&val); // baseMaterialMap[j] = val & MATERIAL_GROUP_MASK; materialMap[j].flags = val & Material::PersistMask; } // Load the material names. Vector<String> materials; for ( U32 i=0; i < MaterialGroups; i++ ) { String matName; stream.read( &matName ); if ( matName.isEmpty() ) continue; if ( mFileVersion > 3 && mFileVersion < 6 ) { // Between version 3 and 5 we store the texture file names // relative to the terrain file. We restore the full path // here so that we can create a TerrainMaterial from it. materials.push_back( Torque::Path::CompressPath( mFilePath.getRoot() + mFilePath.getPath() + '/' + matName ) ); } else materials.push_back( matName ); } if ( mFileVersion <= 3 ) { GFXTexHandle terrainMat; Torque::Path matRelPath; // Try to automatically fix up our material file names for (U32 i = 0; i < materials.size(); i++) { if ( materials[i].isEmpty() ) continue; terrainMat.set( materials[i], &GFXDefaultPersistentProfile, avar( "%s() - (line %d)", __FUNCTION__, __LINE__ ) ); if ( terrainMat ) continue; matRelPath = materials[i]; String path = matRelPath.getPath(); String::SizeType n = path.find( '/', 0, String::NoCase ); if ( n != String::NPos ) { matRelPath.setPath( String(Con::getVariable( "$defaultGame" )) + path.substr( n, path.length() - n ) ); terrainMat.set( matRelPath, &GFXDefaultPersistentProfile, avar( "%s() - (line %d)", __FUNCTION__, __LINE__ ) ); if ( terrainMat ) { materials[i] = matRelPath.getFullPath(); mNeedsResaving = true; } } } // for (U32 i = 0; i < TerrainBlock::MaterialGroups; i++) } // if ( mFileVersion <= 3 ) if ( mFileVersion == 1 ) { for( S32 j = 0; j < sampleCount; j++ ) { if ( materialAlphaMap[baseMaterialMap[j]] == NULL ) { materialAlphaMap[baseMaterialMap[j]] = new U8[sampleCount]; dMemset(materialAlphaMap[baseMaterialMap[j]], 0, sampleCount); } materialAlphaMap[baseMaterialMap[j]][j] = 255; } } else { for( S32 k=0; k < materials.size(); k++ ) { AssertFatal(materialAlphaMap[k] == NULL, "Bad assumption. There should be no alpha map at this point..."); materialAlphaMap[k] = new U8[sampleCount]; stream.read(sampleCount, materialAlphaMap[k]); } } // Throw away the old texture and heightfield scripts. if ( mFileVersion >= 3 ) { U32 len; stream.read(&len); char *textureScript = (char *)dMalloc(len + 1); stream.read(len, textureScript); dFree( textureScript ); stream.read(&len); char *heightfieldScript = (char *)dMalloc(len + 1); stream.read(len, heightfieldScript); dFree( heightfieldScript ); } // Load and throw away the old edge terrain paths. if ( mFileVersion >= 5 ) { stream.readSTString(true); stream.readSTString(true); } U32 layerCount = materials.size() - 1; // Ok... time to convert all this mess to the layer index map! for ( U32 i=0; i < sampleCount; i++ ) { // Find the greatest layer. U32 layer = 0; U32 lastValue = 0; for ( U32 k=0; k < MaterialGroups; k++ ) { if ( materialAlphaMap[k] && materialAlphaMap[k][i] > lastValue ) { layer = k; lastValue = materialAlphaMap[k][i]; } } // Set the layer index. mLayerMap[i] = getMin( layer, layerCount ); } // Cleanup. for ( U32 i=0; i < MaterialGroups; i++ ) delete [] materialAlphaMap[i]; // Force resaving on these old file versions. //mNeedsResaving = false; // Resolve the TerrainMaterial objects from the names. _resolveMaterials( materials ); }
static mng_ptr mngMallocFn(mng_size_t size) { mng_ptr data = dMalloc(size); return dMemset(data, 0, size); }
char* GFXGLShader::_handleIncludes( const Torque::Path& path, FileStream *s ) { // TODO: The #line pragma on GLSL takes something called a // "source-string-number" which it then never explains. // // Until i resolve this mystery i disabled this. // //String linePragma = String::ToString( "#line 1 \r\n"); //U32 linePragmaLen = linePragma.length(); U32 shaderLen = s->getStreamSize(); char* buffer = (char*)dMalloc(shaderLen + 1); //dStrncpy( buffer, linePragma.c_str(), linePragmaLen ); s->read(shaderLen, buffer); buffer[shaderLen] = 0; char* p = dStrstr(buffer, "#include"); while(p) { char* q = p; p += 8; if(dIsspace(*p)) { U32 n = 0; while(dIsspace(*p)) ++p; AssertFatal(*p == '"', "Bad #include directive"); ++p; static char includeFile[256]; while(*p != '"') { AssertFatal(*p != 0, "Bad #include directive"); includeFile[n++] = *p++; AssertFatal(n < sizeof(includeFile), "#include directive too long"); } ++p; includeFile[n] = 0; // First try it as a local file. Torque::Path includePath = Torque::Path::Join(path.getPath(), '/', includeFile); includePath = Torque::Path::CompressPath(includePath); FileStream includeStream; if ( !includeStream.open( includePath, Torque::FS::File::Read ) ) { // Try again assuming the path is absolute // and/or relative. includePath = String( includeFile ); includePath = Torque::Path::CompressPath(includePath); if ( !includeStream.open( includePath, Torque::FS::File::Read ) ) { AssertISV(false, avar("failed to open include '%s'.", includePath.getFullPath().c_str())); if ( smLogErrors ) Con::errorf( "GFXGLShader::_handleIncludes - Failed to open include '%s'.", includePath.getFullPath().c_str() ); // Fail... don't return the buffer. dFree(buffer); return NULL; } } char* includedText = _handleIncludes(includePath, &includeStream); // If a sub-include fails... cleanup and return. if ( !includedText ) { dFree(buffer); return NULL; } // TODO: Disabled till this is fixed correctly. // // Count the number of lines in the file // before the include. /* U32 includeLine = 0; { char* nl = dStrstr( buffer, "\n" ); while ( nl ) { includeLine++; nl = dStrstr( nl, "\n" ); if(nl) ++nl; } } */ String manip(buffer); manip.erase(q-buffer, p-q); String sItx(includedText); // TODO: Disabled till this is fixed correctly. // // Add a new line pragma to restore the proper // file and line number after the include. //sItx += String::ToString( "\r\n#line %d \r\n", includeLine ); dFree(includedText); manip.insert(q-buffer, sItx); char* manipBuf = dStrdup(manip.c_str()); p = manipBuf + (p - buffer); dFree(buffer); buffer = manipBuf; } p = dStrstr(p, "#include"); } return buffer; }
char *dStrdup_r(const char *src, const char *fileName, dsize_t lineNumber) { char *buffer = (char *) dMalloc(dStrlen(src) + 1); dStrcpy(buffer, src); return buffer; }
void PlatformFont::enumeratePlatformFonts( Vector< StringTableEntry >& fonts, UTF16* fontFamily ) { if( fontFamily ) { // Determine the font ID from the family name. ATSUFontID fontID; if( ATSUFindFontFromName( fontFamily, dStrlen( fontFamily ) * 2, kFontFamilyName, kFontMicrosoftPlatform, kFontNoScriptCode, kFontNoLanguageCode, &fontID ) != kATSUInvalidFontErr ) { // Get the number of fonts in the family. ItemCount numFonts; ATSUCountFontNames( fontID, &numFonts ); // Read out font names. U32 bufferSize = 512; char* buffer = ( char* ) dMalloc( bufferSize ); for( U32 i = 0; i < numFonts; ++ i ) { for( U32 n = 0; n < 2; ++ n ) { ByteCount actualNameLength; FontNameCode fontNameCode; FontPlatformCode fontPlatformCode; FontScriptCode fontScriptCode; FontLanguageCode fontLanguageCode; if( ATSUGetIndFontName( fontID, i, bufferSize - 2, buffer, &actualNameLength, &fontNameCode, &fontPlatformCode, &fontScriptCode, &fontLanguageCode ) == noErr ) { *( ( UTF16* ) &buffer[ actualNameLength ] ) = '\0'; char* utf8 = convertUTF16toUTF8( ( UTF16* ) buffer ); fonts.push_back( StringTable->insert( utf8 ) ); delete [] utf8; break; } // Allocate larger buffer. bufferSize = actualNameLength + 2; buffer = ( char* ) dRealloc( buffer, bufferSize ); } } dFree( buffer ); } } else { // Get the number of installed fonts. ItemCount numFonts; ATSUFontCount( &numFonts ); // Get all the font IDs. ATSUFontID* fontIDs = new ATSUFontID[ numFonts ]; if( ATSUGetFontIDs( fontIDs, numFonts, &numFonts ) == noErr ) { U32 bufferSize = 512; char* buffer = ( char* ) dMalloc( bufferSize ); // Read all family names. for( U32 i = 0; i < numFonts; ++ i ) { for( U32 n = 0; n < 2; ++ n ) { ByteCount actualNameLength; ItemCount fontIndex; OSStatus result = ATSUFindFontName( fontIDs[ i ], kFontFamilyName, kFontMicrosoftPlatform, kFontNoScriptCode, kFontNoLanguageCode, bufferSize - 2, buffer, &actualNameLength, &fontIndex ); if( result == kATSUNoFontNameErr ) break; else if( result == noErr ) { *( ( UTF16* ) &buffer[ actualNameLength ] ) = '\0'; char* utf8 = convertUTF16toUTF8( ( UTF16* ) buffer ); StringTableEntry name = StringTable->insert( utf8 ); delete [] utf8; // Avoid duplicates. bool duplicate = false; for( U32 i = 0, num = fonts.size(); i < num; ++ i ) if( fonts[ i ] == name ) { duplicate = true; break; } if( !duplicate ) fonts.push_back( name ); break; } // Allocate larger buffer. bufferSize = actualNameLength + 2; buffer = ( char* ) dRealloc( buffer, bufferSize ); } } dFree( buffer ); } delete [] fontIDs; } }
bool ATITShader::loadVertexShaderFromFile(const char* vertPath) { char fileNameBufferVert[512]; Con::expandScriptFilename(fileNameBufferVert, sizeof(fileNameBufferVert), vertPath); const char* vs; Stream *v = ResourceManager->openStream(fileNameBufferVert); if(!v) { AssertWarn(false, avar("Failed to find ATIT vertex shader file: %s", fileNameBufferVert)); return false; } mVertexSourceStringLength = ResourceManager->getSize(fileNameBufferVert); mVertexSourceString = (char *)dMalloc((mVertexSourceStringLength + 1) * sizeof(U8)); v->read(mVertexSourceStringLength, mVertexSourceString); ResourceManager->closeStream(v); glEnable(GL_VERTEX_PROGRAM_ARB); glGenProgramsARB(1, &mVertexProgram); glBindProgramARB(GL_VERTEX_PROGRAM_ARB, mVertexProgram); glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, mVertexSourceStringLength, mVertexSourceString); #if defined(TORQUE_DEBUG) || defined(SHADER_MANAGER_DEBUG) const char* errorString = NULL; errorString = (const char*)glGetString(GL_PROGRAM_ERROR_STRING_ARB); Con::printf("Error string for %s is %s", fileNameBufferVert, errorString); if(errorString && errorString[0] != '\0') return false; #endif #ifdef ATIT_SHADER_SHOW_STATS bool stats = Con::getBoolVariable("$pref::shaderManager::showASMStats"); if(stats) { GLint param; Con::printf("Stats for %s", fileNameBufferVert); glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_INSTRUCTIONS_ARB, ¶m); Con::printf("%i instructions", param); glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB, ¶m); Con::printf("%i native instructions", param); glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_TEMPORARIES_ARB, ¶m); Con::printf("%i temporaries", param); glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_NATIVE_TEMPORARIES_ARB, ¶m); Con::printf("%i native temporaries", param); glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_PARAMETERS_ARB, ¶m); Con::printf("%i parameters", param); glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_NATIVE_PARAMETERS_ARB, ¶m); Con::printf("%i native parameters", param); glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_ATTRIBS_ARB, ¶m); Con::printf("%i attribs", param); glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_NATIVE_ATTRIBS_ARB, ¶m); Con::printf("%i native attribs", param); glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_ADDRESS_REGISTERS_ARB, ¶m); Con::printf("%i address registers", param); glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB, ¶m); Con::printf("%i native address registers", param); glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB, ¶m); if(param) Con::printf("Program is under native limits!"); else Con::printf("Program exceeds native limits!"); } #endif glDisable(GL_VERTEX_PROGRAM_ARB); mVertexFilepath = StringTable->insert(fileNameBufferVert); return true; }
void PxCloth::_initClothMesh() { // Make sure we can change the world. mWorld->releaseWriteLock(); _releaseMesh(); // Must have at least 2 verts. mPatchVerts.x = getMax( 2, mPatchVerts.x ); mPatchVerts.y = getMax( 2, mPatchVerts.y ); // Generate a uniform cloth patch, // w and h are the width and height, // d is the distance between vertices. mNumVertices = mPatchVerts.x * mPatchVerts.y; mNumIndices = (mPatchVerts.x-1) * (mPatchVerts.y-1) * 2; NxClothMeshDesc desc; desc.numVertices = mNumVertices; desc.numTriangles = mNumIndices; desc.pointStrideBytes = sizeof(NxVec3); desc.triangleStrideBytes = 3*sizeof(NxU32); desc.points = (NxVec3*)dMalloc(sizeof(NxVec3)*desc.numVertices); desc.triangles = (NxU32*)dMalloc(sizeof(NxU32)*desc.numTriangles*3); desc.flags = 0; U32 i,j; NxVec3 *p = (NxVec3*)desc.points; F32 patchWidth = mPatchSize.x / (F32)( mPatchVerts.x - 1 ); F32 patchHeight = mPatchSize.y / (F32)( mPatchVerts.y - 1 ); for (i = 0; i < mPatchVerts.y; i++) { for (j = 0; j < mPatchVerts.x; j++) { p->set( patchWidth * j, 0.0f, patchHeight * i ); p++; } } NxU32 *id = (NxU32*)desc.triangles; for (i = 0; i < mPatchVerts.y-1; i++) { for (j = 0; j < mPatchVerts.x-1; j++) { NxU32 i0 = i * mPatchVerts.x + j; NxU32 i1 = i0 + 1; NxU32 i2 = i0 + mPatchVerts.x; NxU32 i3 = i2 + 1; if ( (j+i) % 2 ) { *id++ = i0; *id++ = i2; *id++ = i1; *id++ = i1; *id++ = i2; *id++ = i3; } else { *id++ = i0; *id++ = i2; *id++ = i3; *id++ = i0; *id++ = i3; *id++ = i1; } } } NxCookingInterface *cooker = PxWorld::getCooking(); cooker->NxInitCooking(); // Ok... cook the mesh! NxCookingParams params; params.targetPlatform = PLATFORM_PC; params.skinWidth = 0.01f; params.hintCollisionSpeed = false; cooker->NxSetCookingParams( params ); PxMemStream cooked; if ( cooker->NxCookClothMesh( desc, cooked ) ) { cooked.resetPosition(); mClothMesh = gPhysicsSDK->createClothMesh( cooked ); } cooker->NxCloseCooking(); NxVec3 *ppoints = (NxVec3*)desc.points; NxU32 *triangs = (NxU32*)desc.triangles; dFree( ppoints ); dFree( triangs ); if ( mClothMesh ) _initReceiveBuffers(); }
SimObject *SimObjectMemento::restore() const { // Make sure we have data to restore. if ( !mState ) return NULL; // TODO: We could potentially make this faster by // caching the CodeBlock generated from the string SimObject* object; if( !mIsDatablock ) { // Set the redefine behavior to automatically giving // the new objects unique names. This will restore the // old names if they are still available or give reasonable // approximations if not. const char* oldRedefineBehavior = Con::getVariable( "$Con::redefineBehavior" ); Con::setVariable( "$Con::redefineBehavior", "renameNew" ); // Read the object. const UTF8* result = Con::evaluate( mState ); // Restore the redefine behavior. Con::setVariable( "$Con::redefineBehavior", oldRedefineBehavior ); if ( !result || !result[ 0 ] ) return NULL; // Look up the object. U32 objectId = dAtoi( result ); object = Sim::findObject( objectId ); } else { String objectName = mObjectName; // For datablocks, it's getting a little complicated. Datablock definitions cannot be used // as expressions and thus we can't get to the datablock object we create by using the // Con::evaluate() return value. Instead, we need to rely on the object name. However, if // the name is already taken and needs to be changed, we need to manually do that. To complicate // this further, we cannot rely on automatic renaming since then we don't know by what name // the newly created object actually goes. So what we do is we alter the source text snapshot // and substitute a name in case the old object name is actually taken now. char* tempBuffer; if( !Sim::findObject( objectName ) ) tempBuffer = mState; else { String uniqueName = Sim::getUniqueName( objectName ); U32 uniqueNameLen = uniqueName.length(); char* pLeftParen = dStrchr( mState, '(' ); if( pLeftParen == NULL ) return NULL; U32 numCharsToLeftParen = pLeftParen - mState; tempBuffer = ( char* ) dMalloc( dStrlen( mState ) + uniqueNameLen + 1 ); dMemcpy( tempBuffer, mState, numCharsToLeftParen ); dMemcpy( &tempBuffer[ numCharsToLeftParen ], uniqueName, uniqueNameLen ); dStrcpy( &tempBuffer[ numCharsToLeftParen + uniqueNameLen ], &mState[ numCharsToLeftParen ] ); } Con::evaluate( tempBuffer ); if( tempBuffer != mState ) dFree( tempBuffer ); if( objectName == String::EmptyString ) return NULL; object = Sim::findObject( objectName ); } return object; }
bool PNGImage::Read(const char* filePath) { if(mRead == true || mWrite == true) CleanMemoryUsage(); /* open file and test for it being a png */ FILE *fp = fopen(filePath, "rb"); if (fp == NULL) { Con::printf("PNGImage::Read File %s could not be opened for reading.", filePath); return false; } dStrcpy(mReadFilePath, filePath); png_byte pngsig[PNGSIGSIZE]; fread((char*)pngsig, 1, PNGSIGSIZE, fp); if (png_sig_cmp(pngsig, 0, PNGSIGSIZE) != 0) { Con::printf("PNGImage::Read File %s is not recognized as a PNG file.", filePath); return false; } /* initialize stuff */ mPng = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (mPng == NULL) { Con::printf("PNGImage::Read png_create_read_struct failed."); return false; } mInfo = png_create_info_struct(mPng); if (mInfo == NULL) { png_destroy_read_struct(&mPng, NULL, NULL); Con::printf("PNGImage::Read png_create_info_struct failed."); return false; } if (setjmp(png_jmpbuf(mPng))) { png_destroy_read_struct(&mPng, NULL, NULL); Con::printf("PNGImage::Read Error during init_io."); return false; } png_init_io(mPng, fp); png_set_sig_bytes(mPng, 8); png_read_info(mPng, mInfo); // Obtain image information mWidth = png_get_image_width(mPng, mInfo); mHeight = png_get_image_height(mPng, mInfo); mColorType = png_get_color_type(mPng, mInfo); mBitDepth = png_get_bit_depth(mPng, mInfo); mRowPointers = (png_bytep*) dMalloc(sizeof(png_bytep) * mHeight); unsigned int y = 0; for (y = 0; y < mHeight; y++) mRowPointers[y] = (png_byte*) dMalloc(png_get_rowbytes(mPng,mInfo)); // Will read the actual png data into mRowPointers png_read_image(mPng, mRowPointers); fclose(fp); mRead = true; if(png_get_color_type(mPng, mInfo) == PNG_COLOR_TYPE_RGBA) mPNGImageType = PNGTYPE_RGBA; else if(png_get_color_type(mPng, mInfo) == PNG_COLOR_TYPE_RGB) mPNGImageType = PNGTYPE_RGB; else mPNGImageType = PNGTYPE_UNKNOWN; return true; }
/* * Receive and process new chunks of JPEG image data */ static void Jpeg_write(DilloJpeg *jpeg, void *Buf, uint_t BufSize) { DilloImgType type; uchar_t *linebuf; JSAMPLE *array[1]; int num_read; _MSG("Jpeg_write: (%p) Bytes in buff: %ld Ofs: %lu\n", jpeg, (long) BufSize, (ulong_t)jpeg->Start_Ofs); /* See if we are supposed to skip ahead. */ if (BufSize <= jpeg->Start_Ofs) return; /* Concatenate with the partial input, if any. */ jpeg->cinfo.src->next_input_byte = (uchar_t *)Buf + jpeg->Start_Ofs; jpeg->cinfo.src->bytes_in_buffer = BufSize - jpeg->Start_Ofs; jpeg->NewStart = BufSize; jpeg->Data = Buf; if (setjmp(jpeg->jerr.setjmp_buffer)) { /* If we get here, the JPEG code has signaled an error. */ jpeg->state = DILLO_JPEG_ERROR; } /* Process the bytes in the input buffer. */ if (jpeg->state == DILLO_JPEG_INIT) { /* decompression step 3 (see libjpeg.doc) */ if (jpeg_read_header(&(jpeg->cinfo), TRUE) != JPEG_SUSPENDED) { type = DILLO_IMG_TYPE_GRAY; if (jpeg->cinfo.num_components == 1) { type = DILLO_IMG_TYPE_GRAY; } else if (jpeg->cinfo.num_components == 3) { type = DILLO_IMG_TYPE_RGB; } else { MSG("4-component JPEG!\n"); if (jpeg->cinfo.jpeg_color_space == JCS_YCCK) MSG("YCCK. Are the colors wrong?\n"); if (!jpeg->cinfo.saw_Adobe_marker) MSG("No adobe marker! Is the image shown in reverse video?\n"); type = DILLO_IMG_TYPE_CMYK_INV; } /* * If a multiple-scan image is not completely in cache, * use progressive display, updating as it arrives. */ if (jpeg_has_multiple_scans(&jpeg->cinfo) && !(a_Capi_get_flags(jpeg->url) & CAPI_Completed)) jpeg->cinfo.buffered_image = TRUE; /* check max image size */ if (jpeg->cinfo.image_width <= 0 || jpeg->cinfo.image_height <= 0 || jpeg->cinfo.image_width > IMAGE_MAX_AREA / jpeg->cinfo.image_height) { MSG("Jpeg_write: suspicious image size request %u x %u\n", (uint_t)jpeg->cinfo.image_width, (uint_t)jpeg->cinfo.image_height); jpeg->state = DILLO_JPEG_ERROR; return; } a_Dicache_set_parms(jpeg->url, jpeg->version, jpeg->Image, (uint_t)jpeg->cinfo.image_width, (uint_t)jpeg->cinfo.image_height, type); /* decompression step 4 (see libjpeg.doc) */ jpeg->state = DILLO_JPEG_STARTING; } } if (jpeg->state == DILLO_JPEG_STARTING) { /* decompression step 5 (see libjpeg.doc) */ if (jpeg_start_decompress(&(jpeg->cinfo))) { jpeg->y = 0; jpeg->state = jpeg->cinfo.buffered_image ? DILLO_JPEG_READ_BEGIN_SCAN : DILLO_JPEG_READ_IN_SCAN; } } /* * A progressive jpeg contains multiple scans that can be used to display * an increasingly sharp image as it is being received. The reading of each * scan must be surrounded by jpeg_start_output()/jpeg_finish_output(). */ if (jpeg->state == DILLO_JPEG_READ_END_SCAN) { if (jpeg_finish_output(&jpeg->cinfo)) { if (jpeg_input_complete(&jpeg->cinfo)) { jpeg->state = DILLO_JPEG_DONE; } else { jpeg->state = DILLO_JPEG_READ_BEGIN_SCAN; } } } if (jpeg->state == DILLO_JPEG_READ_BEGIN_SCAN) { if (jpeg_start_output(&jpeg->cinfo, jpeg->cinfo.input_scan_number)) { a_Dicache_new_scan(jpeg->url, jpeg->version); jpeg->state = DILLO_JPEG_READ_IN_SCAN; } } if (jpeg->state == DILLO_JPEG_READ_IN_SCAN) { linebuf = dMalloc(jpeg->cinfo.image_width * jpeg->cinfo.num_components); array[0] = linebuf; while (1) { num_read = jpeg_read_scanlines(&(jpeg->cinfo), array, 1); if (num_read == 0) { /* out of input */ break; } a_Dicache_write(jpeg->url, jpeg->version, linebuf, jpeg->y); jpeg->y++; if (jpeg->y == jpeg->cinfo.image_height) { /* end of scan */ if (!jpeg->cinfo.buffered_image) { /* single scan */ jpeg->state = DILLO_JPEG_DONE; break; } else { jpeg->y = 0; if (jpeg_input_complete(&jpeg->cinfo)) { if (jpeg->cinfo.input_scan_number == jpeg->cinfo.output_scan_number) { jpeg->state = DILLO_JPEG_DONE; break; } else { /* one final loop through the scanlines */ jpeg_finish_output(&jpeg->cinfo); jpeg_start_output(&jpeg->cinfo, jpeg->cinfo.input_scan_number); continue; } } jpeg->state = DILLO_JPEG_READ_END_SCAN; if (!jpeg_finish_output(&jpeg->cinfo)) { /* out of input */ break; } else { if (jpeg_input_complete(&jpeg->cinfo)) { jpeg->state = DILLO_JPEG_DONE; break; } else { jpeg->state = DILLO_JPEG_READ_BEGIN_SCAN; } } if (!jpeg_start_output(&jpeg->cinfo, jpeg->cinfo.input_scan_number)) { /* out of input */ break; } a_Dicache_new_scan(jpeg->url, jpeg->version); jpeg->state = DILLO_JPEG_READ_IN_SCAN; } } } dFree(linebuf); } }