|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T p
Length: 17958 (0x4626) Types: TextFile Names: »pxl.c«
└─⟦52210d11f⟧ Bits:30007239 EUUGD2: TeX 3 1992-12 └─⟦c319c2751⟧ »unix3.0/TeX3.0.tar.Z« └─⟦036c765ac⟧ └─⟦this⟧ »TeX3.0/MFcontrib/fonttool/pxl.c« └─⟦060c9c824⟧ Bits:30007080 DKUUG TeX 2/12/89 └─⟦this⟧ »./tex82/MFcontrib/fonttool/pxl.c« └─⟦52210d11f⟧ Bits:30007239 EUUGD2: TeX 3 1992-12 └─⟦63303ae94⟧ »unix3.14/TeX3.14.tar.Z« └─⟦c58930e5c⟧ └─⟦this⟧ »TeX3.14/MFcontrib/fonttool/pxl.c«
/* * File: * * pxl.c * * Author: * Brad Rullman * Department of Computer Science FR-35 * University of Washington * Seattle, Washington 98155 * email: ecola@cs.washington.edu * * Copyright @ March, 1987 - This program, or any subset of the functions * herein, is not to be redistributed, or used for personal or commercial * gain in the form of fame, fortune, or shorter working hours, without * the consent of the author. * * Function: * * A file of functions used to read/write a pxl description * to/from a pixrect structure. * (For a complete discussion of pxl files for TeX, I refer the * reader to "The Format of PXL Files" by David Fuchs, which * is probably included in the TeX distribution somewhere.) * * Contents: * * Public: * * OpenPxlFile Opens a pxl file. Only 1 open at a time. * ClosePxlFile Closes a pxl file. * ReadCharacter Reads a character into ViewSW and PaintSW. * WriteCharacter Writes a character into a pxl file. * * Private Internal: * * copyFile Copies one file to another. * getPXLData Returns the pxl directory data of a character. * setPXLData Sets the pxl directory data of a character. * readRaster Loads a pixrect with raster image of a char. * writeRaster Writes a char's raster image from a pixrect. */ #include "global.h" #include "pxl.h" #include <sys/param.h> static char inputFileName[MAXFILENAMLEN]; static char tempName[] = "/tmp/fonttool.XXXXXX"; static FILE *inputFile = NULL; /* stream pointer for font to be read */ static FILE *outputFile; /* stream pointer for the modified font */ /* * copyFile * * Input: * file1: source file. * file2: destination file. * Output: * none. * Action: * Reads from file1 starting at its current seek pointer position, * and writes to file2's current seek pointer position. Does not * reset pointers. */ static void copyFile(file1, file2) int file1, file2; { char buf[MAXBSIZE]; int n; for (;;) { n = fread(buf, sizeof(*buf), sizeof(buf), file1); if (n == 0) { break; } if (n < 0) { AbortWithError("copyFile: Failed read\n."); } if (fwrite(buf, sizeof(*buf), n, file2) != n) { AbortWithError("copyFile: Failed write\n."); } } } /* * OpenPxlFile * * Input: * fileName: path of file to open. * Output: * An int. 1 = no errors. 0 = not a pxl file. -1 = couldn't open. * Action: * Trys to open the file passed in. The returned file descriptor is * saved in inputFile. Should only be called when the user selects * "Open Font" from the OptionSW. * */ int OpenPxlFile(fileName) char *fileName; { int firstWord; void ClosePxlFile(); if (inputFile != NULL) { ClosePxlFile(); } if ((inputFile = fopen(fileName, "r")) == NULL) { return(-1); } fread((int *)(&firstWord), sizeof(int), 1, inputFile); if (firstWord != PXLID) { ClosePxlFile(); return(0); } strcpy(inputFileName, fileName); outputFile = NULL; return(1); } /* * ClosePxlFile * * Input: * none. * Output: * none. * Action: * Closes the current pxl file. */ void ClosePxlFile() { fclose(inputFile); inputFile = NULL; /* Indicate no pxl file open */ } /* * getPXLData * * Input: * c : the ascii value of a character whose pxl data is required. * pxlData: a pointer to a PXLData structure. * Output: * none. * Action: * Reads the pxl file, filling in the data fields of the passed * PXLData structure. */ static void getPXLData(c, pxlData) int c; PXLDataPtr pxlData; { if ((c < 0) || (c > 127)) { AbortWithError("getPxlData: Bad ascii character.\n"); } /* * Seek to (-517 * 4) + (4*c * 4) from the end of the file, which is * start of font directory + 4 words * c * 4 bytesperword, * i.e. the start of the directory entry for character c. */ if (fseek(inputFile, ((-517 * 4) + (16 * c)), 2) == -1) { AbortWithError("getPxlData: Failed seek.\n"); } fread((short *)(&pxlData->width), sizeof(short), 1, inputFile); fread((short *)(&pxlData->height), sizeof(short), 1, inputFile); fread((short *)(&pxlData->xOffset), sizeof(short), 1, inputFile); fread((short *)(&pxlData->yOffset), sizeof(short), 1, inputFile); fread((int *)(&pxlData->rasterPtr), sizeof(int), 1, inputFile); pxlData->rasterPtr = pxlData->rasterPtr * sizeof(int); } /* * setPXLData * * Input: * c : the ascii value of a character. * pxlData: a pointer to a PXLData structure. * Output: * none. * Action: * Modifies outputFile file so that the font directory entry for * c is replaced by pxlData. */ static void setPXLData(c, pxlData) int c; PXLDataPtr pxlData; { if ((c < 0) || (c > 127)) { AbortWithError("setPxlData: Bad ascii character.\n"); } /* * Seek to (-517 * 4) + (4*c * 4) from the end of the file, which is * start of font directory + 4 words * c * 4 bytesperword, * i.e. the start of the directory entry for character c. */ if (fseek(outputFile, ((-517 * 4) + (16 * c)), 2) == -1) { AbortWithError("setPxlData: Failed seek.\n"); } #ifndef SUN AbortWithError("setPxlData: Error: Machine dependent code.\n"); #endif fwrite((short *)(&pxlData->width), sizeof(short), 1, outputFile); fwrite((short *)(&pxlData->height), sizeof(short), 1, outputFile); fwrite((short *)(&pxlData->xOffset), sizeof(short), 1, outputFile); fwrite((short *)(&pxlData->yOffset), sizeof(short), 1, outputFile); pxlData->rasterPtr = pxlData->rasterPtr / sizeof(int); fwrite((int *)(&pxlData->rasterPtr), sizeof(int), 1, outputFile); } /* * readRaster * * Input: * srcPR : pointer to the pixrect to load the character in. * x, y : pixrect coordinates at which to load the character. * pxlData : pointer to a structure containing pxl data for the character * in question. * Output: * none. * Action: * Reads the region defined by the character's bounding box into * the given pixrect at the given coordinates. Assumes that the * given pixrect is large enough to hold the character, otherwise * clipping takes place. * Notice that the raster image file is assumed to be big-endian, * that is for the 4 byte word starting at position 600, the most * significant 8 bits come at location 600, the next significant * 8 bits come at location 601, etc. */ static void readRaster(srcPR, x, y, pxlData) struct pixrect *srcPR; int x, y; PXLDataPtr pxlData; { int wordWidth; /* width of character raster, in words */ int rasterLen; /* length of char raster, in bytes */ struct pixrect *paddedPR; /* temporary pixrect */ struct mpr_data *memoryData;/* ptr to a pixrect's memory data */ wordWidth = ((int) (pxlData->width/32)) + ((pxlData->width % 32) != 0); paddedPR = mem_create((wordWidth*32), pxlData->height, (int) 1); /* * Read in the raster image. The raster image will require wordWidth * * height words of memory, where a word is 32 bits. This raster image * is flushed out with 0's so that each row is some multiple of 32 bits * long. */ fseek(inputFile, pxlData->rasterPtr, 0); rasterLen = wordWidth * pxlData->height * sizeof(int); memoryData = (struct mpr_data *) paddedPR->pr_data; if (fread((char *) memoryData->md_image, sizeof(char), rasterLen, inputFile) != rasterLen) { perror("readRaster"); AbortWithError("readRaster: Failed read.\n"); } /* * The pixrect is now loaded with the padded image of the character. * The final step is to cut this pixrect down to exact true size * and load it into the desired pixrect. */ pr_rop(srcPR, x, y, pxlData->width, pxlData->height, PIX_SRC, paddedPR, 0, 0); pr_destroy(paddedPR); /* No longer needed */ } /* * ReadCharacter * * Input: * c: a character to read. * Output: * none. * Action: * Reads the given character into the View and Paint subwindows. */ void ReadCharacter(c) int c; { PXLData charPxlData; int boxWithRefWidth, boxWithRefHeight; int neededViewSWWidth, neededViewSWHeight; int xLoad, yLoad; if (inputFile == NULL) { ShowMsg("***** Open a PXL file before loading a character. *****"); return; } if (RasterChanged) { ShowMsg("***** Load over existing raster? (Left \ confirms, right cancels.) *****"); if (!Confirm()) { return; } } ClearMsg(); RasterChanged = 0; SETCURSORWATCH; getPXLData(c, &charPxlData); /* * Find the bounding box that contains both the character and * its reference point, then adjust the size of the view subwindow * and related structures. */ boxWithRefWidth = MAX(charPxlData.width - charPxlData.xOffset, MAX(charPxlData.xOffset, charPxlData.width)); boxWithRefHeight = MAX(charPxlData.height - charPxlData.yOffset, MAX(charPxlData.yOffset, charPxlData.height)); neededViewSWWidth = MIN(MAXVIEWSWWIDTH, MAX(MINVIEWSWWIDTH, boxWithRefWidth + 2*MINVIEWSWMARGIN)); neededViewSWHeight = MIN(MAXVIEWSWHEIGHT, MAX(MINVIEWSWHEIGHT, boxWithRefHeight + 2*MINVIEWSWMARGIN)); if ( (ViewPR->pr_size.x != neededViewSWWidth) || (ViewPR->pr_size.y != neededViewSWHeight) ) { ResizePRs(neededViewSWWidth, neededViewSWHeight, 0); } /* * Find the ViewPR coordinates (xLoad, yLoad) that will correspond * to the origin of the character's bounding box when it is loaded. * We want the bounding box formed by the union of the character and * its reference point to be centered in the ViewPR. */ xLoad = MAX( (ViewPR->pr_size.x-boxWithRefWidth)/2 - charPxlData.xOffset, (ViewPR->pr_size.x-boxWithRefWidth)/2 ); yLoad = MAX( (ViewPR->pr_size.y-boxWithRefHeight)/2 - charPxlData.yOffset, (ViewPR->pr_size.y-boxWithRefHeight)/2 ); ReferenceXY.x = SCALEUP(xLoad + charPxlData.xOffset); ReferenceXY.y = SCALEUP(yLoad + charPxlData.yOffset); /* * Load the character into the ViewPR and display it. Note that if the * char's width and height are zero, then it is either not currently * present in the font or is "totally white"; in either case it has * no raster. */ CLEARPR(ViewPR); if ( (charPxlData.width > 0) && (charPxlData.height > 0) ) { readRaster(ViewPR, xLoad, yLoad, &charPxlData); } CLEARPR(PaintPR); DisplayPR(0, 0, ViewPR->pr_size.x, ViewPR->pr_size.y); COPYPR(ViewPR, UndoPR); SETCURSORNORMAL; } /* * writeRaster * * Input: * srcPR : pointer to the pixrect containing the character. * x, y : pixrect coordinates specifying the origin of * the character's bounding box. * oldPxlData: pointer to a structure containing pxl data for * the original character. * newPxlData: pointer to a structure containing pxl data for * the new character. * Output: * none. * Action: * Copies the current input file to the current output file, inserting * a raster description for the image in srcPR into the output file and * excluding the old raster for that character. * Notice that the raster image file is assumed to be big-endian, * that is for the 4 byte word starting at position 600, the most * significant 8 bits come at location 600, the next significant * 8 bits come at location 601, etc. */ static void writeRaster(srcPR, x, y, oldPxlData, newPxlData) struct pixrect *srcPR; int x, y; PXLDataPtr oldPxlData, newPxlData; { char copyBuf[MAXBSIZE]; int oldWordWidth, newWordWidth; int oldRasterLen, newRasterLen; int changeInByteLen; int numBufsToCopy, n; struct pixrect *paddedPR; register int c; int fontDirPtr; /* offset to font directory */ PXLData tempPxlData; struct mpr_data *memoryData; /* ptr to a pixrect's memory data */ /* * Initialize. */ oldWordWidth = ((int) (oldPxlData->width/32)) + ((oldPxlData->width % 32) != 0); oldRasterLen = oldWordWidth * oldPxlData->height * sizeof(int); newWordWidth = ((int) (newPxlData->width/32)) + ((newPxlData->width % 32) != 0); newRasterLen = newWordWidth * newPxlData->height * sizeof(int); /* * Write the raster image into a pixrect that is an integer number * of words wide. */ paddedPR = mem_create((newWordWidth * 32), newPxlData->height, 1); pr_rop(paddedPR, 0, 0, newPxlData->width, newPxlData->height, PIX_SRC, srcPR, x, y); /* * Copy the old file into the new file up to the point where a raster * is to be replaced. */ rewind(inputFile); rewind(outputFile); numBufsToCopy = oldPxlData->rasterPtr/sizeof(copyBuf) + 1; for (c = 0; c < numBufsToCopy; c++) { n = fread(copyBuf, sizeof(*copyBuf), sizeof(copyBuf), inputFile); if (n == 0) { AbortWithError("writeRaster: Failed read in file copy\n."); } if (fwrite(copyBuf, sizeof(*copyBuf), n, outputFile) != n) { AbortWithError("writeRaster: Failed write in file copy\n."); } } if (truncate(tempName, oldPxlData->rasterPtr) == -1) { AbortWithError("writeRaster: truncate failed.\n"); } /* * Write new raster info from the padded pixrect to the output file * at the old raster's position. */ #ifndef SUN AbortWithError("writeRaster: Error: Machine dependent code.\n"); #endif memoryData = (struct mpr_data *) paddedPR->pr_data; fseek(outputFile, oldPxlData->rasterPtr, 0); if (fwrite((char *) memoryData->md_image, sizeof(char), newRasterLen, outputFile) != newRasterLen) { AbortWithError("writeRaster: Failed write.\n"); } pr_destroy(paddedPR); /* * Copy the rest of the old file into the new file, omitting the * old raster. */ fseek(inputFile, oldPxlData->rasterPtr + oldRasterLen, 0); copyFile(inputFile, outputFile); /* * Fix-up the pointer to the start of the font directory by reading the * old one, adding the number of additional words that have been written, * and writing the new one back. */ fseek(outputFile, (int) (-FONTDIRPTR), 2); fread((int *)(&fontDirPtr), sizeof(int), 1, outputFile); changeInByteLen = newRasterLen - oldRasterLen; fontDirPtr += changeInByteLen/sizeof(int); fseek(outputFile, (int) (-FONTDIRPTR), 2); fwrite((int *)(&fontDirPtr), sizeof(int), 1, outputFile); /* * Fix-up all the affected character raster pointers in the font directory * by adding the change in the file's byte length. */ for (c = 0; c < 128; c++) { getPXLData(c, &tempPxlData); if (tempPxlData.rasterPtr > oldPxlData->rasterPtr) { tempPxlData.rasterPtr += changeInByteLen; setPXLData(c, &tempPxlData); } } } /* * WriteCharacter * * Input: * c: a character to read. * Output: * none. * Action: * Tries to write the raster image in the ViewPR out to the current * font's pxl file, replacing the existing one. */ void WriteCharacter(c) int c; { /* * (mindx,mindy) (maxdx, maxdy) define the bounding box of the "set" * pixels in the ViewPR. */ register int mindx, maxdx, mindy, maxdy; register int dx, dy; PXLData oldPxlData, newPxlData; char bakupFileName[MAXFILENAMLEN+4]; if (inputFile == NULL) { ShowMsg("***** Open a PXL file before saving a character. *****"); return; } ClearMsg(); RasterChanged = 0; SETCURSORWATCH; /* * If this is the first character written to this pxl file during this * session, rename the original input file to a ".bak" file and copy it * to a new file of the same name as the original. */ if (outputFile == NULL) { strcpy(bakupFileName, inputFileName); strcat(bakupFileName, ".bak"); rename(inputFileName, bakupFileName); outputFile = fopen(inputFileName, "w+"); if (outputFile == NULL) { AbortWithError("WriteCharacter: Couldn't create output file.\n"); } rewind(inputFile); copyFile(inputFile, outputFile); fclose(inputFile); inputFile = outputFile; } /* * Create a temporary file to write changes to. */ mktemp(tempName); outputFile = fopen(tempName, "w+"); if (outputFile == NULL) { AbortWithError("WriteCharacter: Couldn't create temporary file.\n"); } /* * Find the character's bounding box. */ mindx = ViewPR->pr_size.x; mindy = ViewPR->pr_size.y; maxdx = 0; maxdy = 0; for (dx = 0; dx < ViewPR->pr_size.x; dx++) { for (dy = 0; dy < ViewPR->pr_size.y; dy++) { if (pr_get(ViewPR, dx, dy)) { mindx = MIN(mindx, dx); maxdx = MAX(maxdx, dx); mindy = MIN(mindy, dy); maxdy = MAX(maxdy, dy); } } } /* * Initialize the character's new pxl data: the size of its bounding * box, the placement of the reference point (relative to the * top left corner of the bounding box), and the pointer to its raster. */ getPXLData(c, &oldPxlData); if ( (mindx == ViewPR->pr_size.x) && (mindy == ViewPR->pr_size.y) && (maxdx == 0) && (maxdy == 0) ) { /* new char is totally white */ newPxlData.width = 0; newPxlData.height = 0; newPxlData.xOffset = 0; newPxlData.yOffset = 0; newPxlData.rasterPtr = 0; } else { newPxlData.width = maxdx - mindx + 1; newPxlData.height = maxdy - mindy + 1; newPxlData.xOffset = SCALEDOWN(ReferenceXY.x) - mindx; newPxlData.yOffset = SCALEDOWN(ReferenceXY.y) - mindy; if (oldPxlData.rasterPtr != 0) { newPxlData.rasterPtr = oldPxlData.rasterPtr; } else { /* old char is totally white; make new raster first in file */ newPxlData.rasterPtr = oldPxlData.rasterPtr = sizeof(int); } } /* * Write out the character raster and its new pxl data. */ writeRaster(ViewPR, mindx, mindy, &oldPxlData, &newPxlData); setPXLData(c, &newPxlData); fclose(inputFile); if (rename(tempName, inputFileName) == -1) { AbortWithError("WriteCharacter: File rename failed\n"); } inputFile = outputFile; SETCURSORNORMAL; }