fint parseGlyphData()

in modules/awt/src/main/native/fontlib/shared/ParsingTables.cpp [856:1127]


fint parseGlyphData(FILE* tt_file, const GlyphOffsets gO, ufshort numGlyphs, ufshort glyphIndex, TTCurve *curve, fshort* bRect, ffloat transform)
{
	uflong offset;
	Glyph_header glyphHeader;
	fshort numOfContours;
	ufshort *endPtsOfContours = NULL; 
	ufshort instructionLength;//instruction length in bytes
	ufchar* instructions = NULL;
	ufchar* flags = NULL;
	ufchar* xCoord = NULL; //pointer to array of X coordinates
	ufchar* yCoord = NULL; //pointer to array of Y coordinates
	ufchar* tmp = NULL;

	fint numPoints; // number of Points
	fint size, i, j, curLen;
	fint flagIndex = 0; 
	fint xCoordIndex = 0;
	fint yCoordIndex = 0;
	fint rep = 0;

	fshort xLength = 0; //length of array of X coordinates
	fshort yLength = 0; //length of array of Y coordinates
	ufchar curFlag = 0;

	if (glyphIndex >= numGlyphs)
	{
//		printf("debug info: glyphIndex out of range");
		glyphIndex = 0;
	}

	offset = gO.offsets[glyphIndex];
	if (offset == gO.offsets[glyphIndex+1])
	{
		curve->add(0,0, 1);
		return 0;
	}

	size = fseek(tt_file, offset, SEEK_SET);
	if (size != 0){
//		printf("Error executing fseek() for someone glyph.");
		return -1;
	}

	/* read 'Glyph_header' table */
	size = (fint)fread(&glyphHeader, sizeof(Glyph_header), 1, tt_file);
	if (size != 1){
//		printf("Error reading 'Glyph_header' table from file.");
		return -1;
	}

	glyphHeader.number_of_contours = wReverse(glyphHeader.number_of_contours);
	numOfContours = glyphHeader.number_of_contours;
	bRect[0] = (short)(wReverse(glyphHeader.xMin)*transform);
	bRect[1] = (short)(wReverse(glyphHeader.yMin)*transform);
	bRect[2] = (short)(wReverse(glyphHeader.xMax)*transform);
	bRect[3] = (short)(wReverse(glyphHeader.yMax)*transform);
	
	if (numOfContours > 0)
	{
		endPtsOfContours = new ufshort[numOfContours];
		size = (fint)fread(endPtsOfContours, sizeof(fshort),numOfContours,tt_file);
		if (size != numOfContours)
		{
//			printf("Error reading endPtsOfContours for someone glyph.");
			delete[] endPtsOfContours;
			return -1;
		}

		for (i=0; i<numOfContours; i++)
		{
			endPtsOfContours[i] = wReverse(endPtsOfContours[i]);
		}
		numPoints = endPtsOfContours[i-1] + 1;

		size = (fint)fread(&instructionLength,sizeof(fshort),1,tt_file);
		if (size != 1)
		{
//			printf("Error reading length of instructions./n");
			delete[] endPtsOfContours;
			return -1;
		}
		instructionLength = wReverse(instructionLength);

		instructions = new ufchar[instructionLength];
		size = (fint)fread(instructions,sizeof(ufchar),instructionLength,tt_file);
		if (size != instructionLength)
		{
//			printf("Error reading instructions./n");
			delete[] instructions;
			delete[] endPtsOfContours;
			return -1;
		}

		curLen=0;
		flags = NULL;

		for (i=0; i<numPoints; i++)
		{
            fint x_repeat = 0;
			fint y_repeat = 0;

			tmp = flags;
			curLen++;
			flags = new ufchar[curLen];
			memcpy(flags,tmp,curLen-1);
			delete[] tmp;
			size = (fint)fread(&(flags[curLen-1]),sizeof(ufchar),1,tt_file);
			if (size != 1)
			{
//                printf("Error reading array of flags from font file.\n");
				delete[] flags; 
				delete[] instructions;
				delete[] endPtsOfContours;
				return -1;
			}
            
			if ((flags[curLen-1] & X_POSITIVE) == X_POSITIVE ||
				(flags[curLen-1] & X_POSITIVE) == X_NEGATIVE)	
				x_repeat = 1;
			else if ((flags[curLen-1] & X_POSITIVE) == X_DWORD)
				x_repeat = 2;

			if ((flags[curLen-1] & Y_POSITIVE) == Y_POSITIVE ||
				(flags[curLen-1] & Y_POSITIVE) == Y_NEGATIVE)	
				y_repeat = 1;
			else if ((flags[curLen-1] & Y_POSITIVE) == Y_DWORD)
				y_repeat = 2;

			if(flags[curLen-1] & REPEAT)
			{
                tmp = flags;
				curLen++;
				flags = new ufchar[curLen];
				memcpy(flags,tmp,curLen-1);
				delete[] tmp;
				size=(fint)fread(&(flags[curLen-1]),sizeof(ufchar),1,tt_file);
				if (size != 1)
				{
//					printf("Error reading array of flags from font file.\n");
					delete[] flags;
					delete[] instructions;
					delete[] endPtsOfContours;
					return -1;
				}

                xLength += x_repeat*(flags[curLen-1] + 1);
				yLength += y_repeat*(flags[curLen-1] + 1);

				i += flags[curLen-1];

			} else
				xLength += x_repeat;
				yLength += y_repeat;
		}

        xCoord = new ufchar[xLength];
		yCoord = new ufchar[yLength];

		size = (fint)fread(xCoord,sizeof(ufchar),xLength,tt_file);
		if (size != xLength)
		{
//			printf("Error reading x-coordinate of glyph's point.\n");
			delete[] flags;
			delete[] instructions;
			delete[] endPtsOfContours;
            delete[] xCoord;
            delete[] yCoord;
			return -1;
		}

		size = (fint)fread(yCoord,sizeof(ufchar),yLength,tt_file);
		if (size != yLength)
		{
//			printf("Error reading coordinates of glyph points.\n");
			delete[] flags;
			delete[] instructions;
			delete[] endPtsOfContours;
            delete[] xCoord;
            delete[] yCoord;
			return -1;
		}
		
		i=0;
		rep=0;
		fint x=0, y=0;
		ffloat xFirstInContour,yFirstInContour;
		bool contBegin;

		for (j=0; j<numOfContours;j++)
		{
			fint repLim = endPtsOfContours[j];
			contBegin = 1;
			
			while(i<=repLim)
			{
                if (rep==0)
				{
					curFlag = flags[flagIndex];
					flagIndex++;
					rep = 1;

					if (curFlag & REPEAT)
					{
						rep += flags[flagIndex];
						flagIndex++;
					}
				}

				fint xChange = 0, yChange = 0;

				if ((curFlag & X_POSITIVE) == X_POSITIVE)
				{
					xChange = xCoord[xCoordIndex]; 
					xCoordIndex++;
				}else if ((curFlag & X_POSITIVE) == X_NEGATIVE)
				{
					xChange = -xCoord[xCoordIndex]; 
					xCoordIndex++;
				}else if ((curFlag & X_POSITIVE) == X_DWORD)
				{
					xChange = (fshort)((xCoord[xCoordIndex]<<8)+xCoord[xCoordIndex+1]);
					xCoordIndex+=2;
				}

				if ((curFlag & Y_POSITIVE) == Y_POSITIVE)
				{
					yChange = yCoord[yCoordIndex]; 
					yCoordIndex++;
				}else if ((curFlag & Y_POSITIVE) == Y_NEGATIVE)
				{
					yChange = -yCoord[yCoordIndex]; 
					yCoordIndex++;
				}else if ((curFlag & Y_POSITIVE) == Y_DWORD)
				{
					yChange = (fshort)((yCoord[yCoordIndex]<<8)+yCoord[yCoordIndex+1]);
					yCoordIndex+=2;
				}

				if((flagIndex >1) && !(curFlag & ON_CURVE ) && 
					((rep == 1) ? (!(flags[flagIndex-2] & ON_CURVE)) : (!(flags[flagIndex-3] & ON_CURVE))))
					curve->add((x+xChange/2)*transform,(y+yChange/2)*transform,FLAG_ONCURVE);


				x+=xChange;
				y+=yChange;

				if (contBegin)
				{
					curve->add(x*transform,y*transform, 1);
					xFirstInContour = x*transform;
					yFirstInContour = y*transform;

					contBegin = 0;
				} else 
                    curve->add(x*transform,y*transform, curFlag & ON_CURVE ? FLAG_ONCURVE : 0);

				rep--;
				i++;
			}
			curve->add(xFirstInContour,yFirstInContour,FLAG_ONCURVE);
		}
	}


	delete[] xCoord;
	delete[] yCoord;
	delete[] flags;
	delete[] endPtsOfContours;
	delete[] instructions;

	return 0;
}