// test filler to check engine output.. subpixel accuracy to make sure screen // clipping is perfect.. void LQ_POLY_FlatFill(LQ_TRIPOINT *p1, LQ_TRIPOINT *p2, LQ_TRIPOINT *p3, ubyte col) { LQ_TRIPOINT *p; LQ_EDGE left_edge, right_edge, edgeA, edgeB; int a, b, c, d; int iY1, iY2, iY3, y; int left_side_longest; int h1, h2, h3; float tmp, subpix, length; float h; float doozdx; ubyte *outbuf, *span; float *outzbuf, *spanz, *endspanz; int start, end; float z, endz; #define SWAP_POINT(a,b) {p=b; b=a; a=p;} // sort vertices in y order: if(p2->y < p1->y) SWAP_POINT(p1, p2) if(p3->y < p1->y) SWAP_POINT(p1, p3) if(p3->y < p2->y) SWAP_POINT(p2, p3) #undef SWAP_POINT // snap vertices on pixels: iY1 = ceil(p1->y); iY2 = ceil(p2->y); iY3 = ceil(p3->y); outbuf = active_surface + (iY1 * 320); outzbuf = zbuffer + (iY1 * 320); // calculate longest scanline: h1 = iY3 - iY1; h = p3->y - p1->y; if(!h1) return; tmp = (p2->y - p1->y) / h; length = ((p3->x - p1->x) * tmp) + (p1->x - p2->x); left_side_longest = (length <= 0); // calculate any deltas for moving across polygon: doozdx = (tmp * (p3->ooz - p1->ooz) + (p1->ooz - p2->ooz)) / length; // calculations for deltas on edge y3y1 edgeA.dx = (p3->x - p1->x) / h; subpix = iY1 - p1->y; edgeA.x = p1->x + edgeA.dx*subpix; if(left_side_longest) { left_edge = edgeA; left_edge.dooz = (p3->ooz - p1->ooz) / h; left_edge.ooz = p1->ooz + left_edge.dooz*subpix; } else right_edge = edgeA; // calculations for deltas on edge y2y1 h2 = iY2 - iY1; if(!h2) goto do_section_2; h = p2->y - p1->y; edgeB.dx = (p2->x - p1->x) / h; edgeB.x = p1->x + edgeB.dx*subpix; if(left_side_longest) right_edge = edgeB; else { left_edge = edgeB; left_edge.dooz = (p2->ooz - p1->ooz) / h; left_edge.ooz = p1->ooz + left_edge.dooz*subpix; } /////////////////////////////////////////////////// // // // SECTION 1: // // // /////////////////////////////////////////////////// for(y=0; y<h2; y++) { start = ceil(left_edge.x); end = ceil(right_edge.x); z = left_edge.ooz; span = outbuf + start; spanz = outzbuf + start; for(; start<end; start++) { if(z+LQ_frame>*spanz) { *span = col; *spanz = z+LQ_frame; } span++; spanz++; z += doozdx; } left_edge.x += left_edge.dx; left_edge.ooz += left_edge.dooz; right_edge.x += right_edge.dx; outbuf += 320; outzbuf += 320; } /////////////////////////////////////////////////// // // // SECTION 2: // // // /////////////////////////////////////////////////// do_section_2: h3 = iY3 - iY2; if(!h3) return; h = p3->y - p2->y; edgeB.dx = (p3->x - p2->x) / h; subpix = iY2 - p2->y; edgeB.x = p2->x + edgeB.dx*subpix; if(left_side_longest) right_edge = edgeB; else { left_edge = edgeB; left_edge.dooz = (p3->ooz - p2->ooz) / h; left_edge.ooz = p2->ooz + left_edge.dooz*subpix; } for(y=0; y<h3; y++) { start = ceil(left_edge.x); end = ceil(right_edge.x); z = left_edge.ooz; span = outbuf + start; spanz = outzbuf + start; for(; start<end; start++) { if(z+LQ_frame>*spanz) { *span = col; *spanz = z + LQ_frame; } span++; spanz++; z += doozdx; } left_edge.x += left_edge.dx; left_edge.ooz += left_edge.dooz; right_edge.x += right_edge.dx; outbuf += 320; outzbuf += 320; } }
OSErr SplitFileIfNeeded(FSRef * inFileReference,FSRef * inParentReference,FSCatalogInfo * inFileCatalogInfo,HFSUniStr255 * inFileName) { OSErr tErr; Boolean splitNeeded=FALSE; SInt16 tForkRefNum; UInt32 tResourceForkSize=0; static HFSUniStr255 sResourceForkName={0,{}}; Boolean hasResourceFork=FALSE; static UInt8 tPOSIXPath[PATH_MAX*2+1]; static UInt32 tPOSIXPathMaxLength=PATH_MAX*2; struct stat tFileStat; SInt16 tNewFileRefNum; if (sResourceForkName.length==0) { tErr=FSGetResourceForkName(&sResourceForkName); if (tErr!=noErr) { logerror("An error occurred when obtaining the ResourceFork name\n"); return -1; } } // 1. Check for the presence of a resource fork tErr=FSOpenFork(inFileReference,sResourceForkName.length,sResourceForkName.unicode,fsRdPerm,&tForkRefNum); if (tErr==noErr) { SInt64 tForkSize; // Get the size of the resource fork tErr=FSGetForkSize(tForkRefNum,&tForkSize); if (tErr!=noErr) { logerror("An error occurred on getting the resource fork size of a file or director\n"); FSCloseFork(tForkRefNum); return -1; } if (tForkSize>0xFFFFFFFF) { FSCloseFork(tForkRefNum); // AppleDouble File format does not support forks bigger than 2GB logerror("AppleDouble file format does not support forks bigger than 2 GB\n"); return -1; } tResourceForkSize=tForkSize; if (tForkSize>0) { hasResourceFork=TRUE; splitNeeded=TRUE; } else { FSCloseFork(tForkRefNum); } } else { switch(tErr) { case errFSForkNotFound: case eofErr: // No resource Fork tErr=noErr; break; default: logerror("Unable to open fork\n"); return -1; break; } } // 2. Check for the presence of FinderInfo or ExtFinderInfo if (splitNeeded==FALSE) { UInt32 * tUnsignedInt32Ptr; int i; // 1. We need to save the Folder(Ext) Info in the ._ file if there are any folder/finder or extend folder/finder info tUnsignedInt32Ptr= (UInt32 *) inFileCatalogInfo->finderInfo; for(i=0;i<4;i++) { if (tUnsignedInt32Ptr[i]!=0) { // We need to create a ._file splitNeeded=TRUE; break; } } if (splitNeeded==TRUE) // 01/02/07: Symbolic link looks like this { UInt32 tSymbolicLink; tSymbolicLink='s'; tSymbolicLink='l'+(tSymbolicLink<<8); tSymbolicLink='n'+(tSymbolicLink<<8); tSymbolicLink='k'+(tSymbolicLink<<8); if (tUnsignedInt32Ptr[0]==tSymbolicLink) { splitNeeded=FALSE; } } else { tUnsignedInt32Ptr= (UInt32 *) inFileCatalogInfo->extFinderInfo; for(i=0;i<4;i++) { if (tUnsignedInt32Ptr[i]!=0) { // We need to create a ._file splitNeeded=TRUE; break; } } } } // 3. Split if needed if (splitNeeded==TRUE) { FSRef tNewFileReference; HFSUniStr255 tNewFileName; // Get the absolute Posix Path Name tErr=FSRefMakePath(inFileReference,tPOSIXPath,tPOSIXPathMaxLength); if (tErr==noErr) { if (lstat((char *) tPOSIXPath,&tFileStat)==-1) { switch(errno) { case ENOENT: // A COMPLETER break; default: // A COMPLETER break; } tErr=-1; goto byebye; } } else { logerror("An error occurred when trying to get the absolute path of a file or directory\n"); tErr=-1; goto byebye; } if (gVerboseMode==TRUE) { printf(" splitting %s...\n",tPOSIXPath); } // Check that we do not explode the current limit for file names if (inFileName->length>gMaxFileNameLength) { // We do not have enough space to add the ._ prefix // The file name is too long // Write the error logerror("File name is too long. The maximum length allowed is %ld characters\n",gMaxFileNameLength+2); return -1; } tNewFileName.length=inFileName->length+2; tNewFileName.unicode[0]='.'; tNewFileName.unicode[1]='_'; BlockMoveData(inFileName->unicode,tNewFileName.unicode+2,inFileName->length*sizeof(UniChar)); // We need to create a ._file tryagain: tErr=FSCreateFileUnicode(inParentReference,tNewFileName.length,tNewFileName.unicode,0,NULL,&tNewFileReference,NULL); if (tErr!=noErr) { switch(tErr) { case bdNamErr: case fsmBadFFSNameErr: case errFSNameTooLong: // The file name is too long // Write the error logerror("File name is too long. The maximum length allowed is %ld characters\n",gMaxFileNameLength+2); break; case dskFulErr: logerror("Disk is full\n"); break; case errFSQuotaExceeded: logerror("Your quota are exceeded\n"); break; case dupFNErr: // The file already exists, we need to try to delete it before recreating it tErr=FSMakeFSRefUnicode(inParentReference,tNewFileName.length,tNewFileName.unicode,kTextEncodingDefaultFormat,&tNewFileReference); if (tErr==noErr) { // Delete the current ._file tErr=FSDeleteObject(&tNewFileReference); if (tErr==noErr) { goto tryagain; } else { // A COMPLETER } } else { // A COMPLETER } break; case afpVolLocked: // A COMPLETER break; default: // A COMPLETER break; } return -1; } tErr=FSOpenFork(&tNewFileReference,0,NULL,fsWrPerm,&tNewFileRefNum); if (tErr==noErr) { unsigned char tAppleDoubleMagicNumber[4]= {0x00,0x05,0x16,0x07}; unsigned char tAppleDoubleVersionNumber[4]={0x00,0x02,0x00,0x00}; unsigned char tAppleDoubleFiller[16]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; ByteCount tRequestCount; UInt16 tNumberOfEntries; UInt16 tSwappedNumberOfEntries; UInt32 tEntryID; UInt32 tEntryOffset; UInt32 tEntryLength; // Write the Magic Number tRequestCount=4; tErr=FSWriteFork(tNewFileRefNum,fsAtMark,0,tRequestCount,tAppleDoubleMagicNumber,NULL); if (tErr!=noErr) { goto writebail; } // Write the Version Number tRequestCount=4; tErr=FSWriteFork(tNewFileRefNum,fsAtMark,0,tRequestCount,tAppleDoubleVersionNumber,NULL); if (tErr!=noErr) { goto writebail; } // Write the Filler tRequestCount=16; tErr=FSWriteFork(tNewFileRefNum,fsAtMark,0,tRequestCount,tAppleDoubleFiller,NULL); if (tErr!=noErr) { goto writebail; } // Compute the Number of Entries tNumberOfEntries=0x0002; tSwappedNumberOfEntries=tNumberOfEntries; #ifdef __LITTLE_ENDIAN__ // Swap for Intel processor tSwappedNumberOfEntries=CFSwapInt16(tSwappedNumberOfEntries); #endif tRequestCount=2; tErr=FSWriteFork(tNewFileRefNum,fsAtMark,0,tRequestCount,&tSwappedNumberOfEntries,NULL); if (tErr!=noErr) { goto writebail; } // Write the Entries Descriptor // **** Finder Info tEntryID=0x00000009; // Finder Info ID tEntryOffset=0x0000001A+tNumberOfEntries*12; tEntryLength=0x00000020; // 32 bytes #ifdef __LITTLE_ENDIAN__ // Swap for Intel processor tEntryID=CFSwapInt32(tEntryID); tEntryOffset=CFSwapInt32(tEntryOffset); tEntryLength=CFSwapInt32(tEntryLength); #endif tRequestCount=4; tErr=FSWriteFork(tNewFileRefNum,fsAtMark,0,tRequestCount,&tEntryID,NULL); if (tErr!=noErr) { goto writebail; } tErr=FSWriteFork(tNewFileRefNum,fsAtMark,0,tRequestCount,&tEntryOffset,NULL); if (tErr!=noErr) { goto writebail; } tErr=FSWriteFork(tNewFileRefNum,fsAtMark,0,tRequestCount,&tEntryLength,NULL); if (tErr!=noErr) { goto writebail; } tEntryID=0x00000002; // Resource Fork ID tEntryOffset=0x00000052; if (hasResourceFork==TRUE) { // **** Finder Info tEntryLength=tResourceForkSize; // As you can see the AppleDouble format file is not ready for forks bigger than 2 GB } else { tEntryLength=0; } #ifdef __LITTLE_ENDIAN__ // Swap for Intel processor tEntryID=CFSwapInt32(tEntryID); tEntryOffset=CFSwapInt32(tEntryOffset); tEntryLength=CFSwapInt32(tEntryLength); #endif tRequestCount=4; tErr=FSWriteFork(tNewFileRefNum,fsAtMark,0,tRequestCount,&tEntryID,NULL); if (tErr!=noErr) { goto writebail; } tErr=FSWriteFork(tNewFileRefNum,fsAtMark,0,tRequestCount,&tEntryOffset,NULL); if (tErr!=noErr) { goto writebail; } tErr=FSWriteFork(tNewFileRefNum,fsAtMark,0,tRequestCount,&tEntryLength,NULL); if (tErr!=noErr) { goto writebail; } // Write the Entries // **** Write Finder Info #ifdef __LITTLE_ENDIAN__ // Intel Processors // Even though it's referenced as a bytes field in the File API, this is actually a structure we need to swap... if (inFileCatalogInfo->nodeFlags & kFSNodeIsDirectoryMask) { // It's a fragging folder FolderInfo * tFolderInfoStruct; ExtendedFolderInfo * tExtendedFolderInfoStruct; // Swap FolderInfo Structure tFolderInfoStruct=(FolderInfo *) inFileCatalogInfo->finderInfo; SWAP_RECT(tFolderInfoStruct->windowBounds); tFolderInfoStruct->finderFlags=CFSwapInt16(tFolderInfoStruct->finderFlags); SWAP_POINT(tFolderInfoStruct->location); tFolderInfoStruct->reservedField=CFSwapInt16(tFolderInfoStruct->reservedField); // Swap ExtendedFolderInfo Info Structure tExtendedFolderInfoStruct=(ExtendedFolderInfo *) inFileCatalogInfo->extFinderInfo; SWAP_POINT(tExtendedFolderInfoStruct->scrollPosition); tExtendedFolderInfoStruct->reserved1=CFSwapInt32(tExtendedFolderInfoStruct->reserved1); tExtendedFolderInfoStruct->extendedFinderFlags=CFSwapInt16(tExtendedFolderInfoStruct->extendedFinderFlags); tExtendedFolderInfoStruct->reserved2=CFSwapInt16(tExtendedFolderInfoStruct->reserved2); tExtendedFolderInfoStruct->putAwayFolderID=CFSwapInt32(tExtendedFolderInfoStruct->putAwayFolderID); } else { // I'm just a file, you know FileInfo * tFileInfoStruct; ExtendedFileInfo * tExtendedFileInfoStruct; // Swap FileInfo Structure tFileInfoStruct=(FileInfo *) inFileCatalogInfo->finderInfo; tFileInfoStruct->fileType=CFSwapInt32(tFileInfoStruct->fileType); tFileInfoStruct->fileCreator=CFSwapInt32(tFileInfoStruct->fileCreator); tFileInfoStruct->finderFlags=CFSwapInt16(tFileInfoStruct->finderFlags); SWAP_POINT(tFileInfoStruct->location); tFileInfoStruct->reservedField=CFSwapInt16(tFileInfoStruct->reservedField); // Swap ExtendedFileInfo Structure tExtendedFileInfoStruct=(ExtendedFileInfo *) inFileCatalogInfo->extFinderInfo; tExtendedFileInfoStruct->reserved1[0]=CFSwapInt16(tExtendedFileInfoStruct->reserved1[0]); tExtendedFileInfoStruct->reserved1[1]=CFSwapInt16(tExtendedFileInfoStruct->reserved1[1]); tExtendedFileInfoStruct->reserved1[2]=CFSwapInt16(tExtendedFileInfoStruct->reserved1[2]); tExtendedFileInfoStruct->reserved1[3]=CFSwapInt16(tExtendedFileInfoStruct->reserved1[3]); tExtendedFileInfoStruct->extendedFinderFlags=CFSwapInt16(tExtendedFileInfoStruct->extendedFinderFlags); tExtendedFileInfoStruct->reserved2=CFSwapInt16(tExtendedFileInfoStruct->reserved2); tExtendedFileInfoStruct->putAwayFolderID=CFSwapInt32(tExtendedFileInfoStruct->putAwayFolderID); } #endif tRequestCount=16; tErr=FSWriteFork(tNewFileRefNum,fsAtMark,0,tRequestCount,inFileCatalogInfo->finderInfo,NULL); if (tErr!=noErr) { goto writebail; } tErr=FSWriteFork(tNewFileRefNum,fsAtMark,0,tRequestCount,inFileCatalogInfo->extFinderInfo,NULL); if (tErr!=noErr) { goto writebail; } // **** Write Resource Fork? if (hasResourceFork==TRUE) { // We need to be clever and copy the Resource Fork by chunks to avoid using too much memory static UInt8 * tBuffer=NULL; static ByteCount tReadRequestCount=0; ByteCount tReadActualCount; OSErr tReadErr; #define GOLDIN_BUFFER_ONE_MEGABYTE_SIZE 1048576 if (tBuffer==NULL) { tReadRequestCount=GOLDIN_BUFFER_ONE_MEGABYTE_SIZE; do { tBuffer=(UInt8 *) malloc(tReadRequestCount*sizeof(UInt8)); tReadRequestCount/=2; } while (tBuffer==NULL && tReadRequestCount>1); if (tBuffer!=NULL && tReadRequestCount>1) { tReadRequestCount*=2; } else { // A COMPLETER } } do { tReadErr=FSReadFork(tForkRefNum, fsAtMark,0, tReadRequestCount, tBuffer, &tReadActualCount); if (tReadErr==noErr || tReadErr==eofErr) { tErr=FSWriteFork(tNewFileRefNum,fsAtMark,0,tReadActualCount,tBuffer,NULL); if (tErr!=noErr) { break; } } else { break; } } while (tReadErr!=eofErr); if (tReadErr!=eofErr) { // A problem occurred while reading the Resource Fork goto writebail; } else if (tErr!=noErr) { // A problem occurred while writing the Resource Fork Data to the AppleDouble file goto writebail; } } tErr=FSCloseFork(tNewFileRefNum); tErr=noErr; // Set the owner tErr=FSSetCatalogInfo(&tNewFileReference,kFSCatInfoPermissions,inFileCatalogInfo); if (tErr!=noErr) { //logerror("Permissions, owner and group could not be set for the AppleDouble file of %s\n",tPOSIXPath); tErr=-1; goto byebye; } } else { // A COMPLETER } // Close the Resource Fork if needed if (hasResourceFork==TRUE) { tErr=FSCloseFork(tForkRefNum); if (gStripResourceForks==TRUE && tErr==noErr) { // Strip the resource fork tErr=FSDeleteFork(inFileReference,sResourceForkName.length,sResourceForkName.unicode); if (tErr!=noErr) { switch(tErr) { case errFSForkNotFound: // This is not important tErr=noErr; break; default: // A COMPLETER break; } } } else { if (gStripResourceForks==TRUE && tErr!=noErr) { logerror("Resource Fork could not be stripped from %s\n",tPOSIXPath); // A COMPLETER } } } } return tErr; writebail: switch(tErr) { case dskFulErr: logerror("Disk is full\n"); break; case errFSQuotaExceeded: logerror("Your quota are exceeded\n"); break; default: logerror("An unknown error occurred while writing the AppleDouble file of %s\n",tPOSIXPath); break; } FSCloseFork(tNewFileRefNum); byebye: if (hasResourceFork==TRUE) { FSCloseFork(tForkRefNum); } return tErr; }