Exemple #1
0
static fz_error
parseTTF(fz_stream *file, int offset, int index, char *path, pdf_xref *xref)
{
	fz_error err = fz_okay;

	TT_OFFSET_TABLE ttOffsetTable;
	TT_TABLE_DIRECTORY tblDir;
	TT_NAME_TABLE_HEADER ttNTHeader;
	TT_NAME_RECORD ttRecord;

	char szPSName[MAX_FACENAME] = { 0 }, szTTName[MAX_FACENAME] = { 0 }, szStyle[MAX_FACENAME] = { 0 };
	int i, count, tblOffset;

	fz_seek(file,offset,0);
	err = safe_read(file, (char *)&ttOffsetTable, sizeof(TT_OFFSET_TABLE));
	if (err) return err;

	// check if this is a TrueType font of version 1.0 or an OpenType font
	if (BEtoHl(ttOffsetTable.uVersion) != TTC_VERSION1 && ttOffsetTable.uVersion != TTAG_OTTO)
		return fz_error_make(file->ctx, "fonterror : invalid font version");

	// determine the name table's offset by iterating through the offset table
	count = BEtoHs(ttOffsetTable.uNumOfTables);
	for (i = 0; i < count; i++)
	{
		err = safe_read(file, (char *)&tblDir, sizeof(TT_TABLE_DIRECTORY));
		if (err) return err;
		if (!tblDir.uTag || BEtoHl(tblDir.uTag) == TTAG_name)
			break;
	}
	if (count == i || !tblDir.uTag)
		return fz_error_make(file->ctx, "fonterror : nameless font");
	tblOffset = BEtoHl(tblDir.uOffset);

	// read the 'name' table for record count and offsets
	fz_seek(file, tblOffset, 0);
	err = safe_read(file, (char *)&ttNTHeader, sizeof(TT_NAME_TABLE_HEADER));
	if (err) return err;
	offset = tblOffset + sizeof(TT_NAME_TABLE_HEADER);
	tblOffset += BEtoHs(ttNTHeader.uStorageOffset);

	// read through the strings for PostScript name and font family
	count = BEtoHs(ttNTHeader.uNRCount);
	for (i = 0; i < count; i++)
	{
		short nameId;

		fz_seek(file, offset + i * sizeof(TT_NAME_RECORD), 0);
		err = safe_read(file, (char *)&ttRecord, sizeof(TT_NAME_RECORD));
		if (err) return err;

		// ignore non-English strings
		if (ttRecord.uLanguageID && BEtoHs(ttRecord.uLanguageID) != TT_MS_LANGID_ENGLISH_UNITED_STATES)
			continue;
		// ignore names other than font (sub)family and PostScript name
		nameId = BEtoHs(ttRecord.uNameID);
		if (TT_NAME_ID_FONT_FAMILY == nameId)
			err = pdf_read_ttf_string(file, tblOffset, &ttRecord, szTTName, MAX_FACENAME);
		else if (TT_NAME_ID_FONT_SUBFAMILY == nameId)
			err = pdf_read_ttf_string(file, tblOffset, &ttRecord, szStyle, MAX_FACENAME);
		else if (TT_NAME_ID_PS_NAME == nameId)
			err = pdf_read_ttf_string(file, tblOffset, &ttRecord, szPSName, MAX_FACENAME);
		if (err) fz_error_handle(file->ctx, err, "ignoring face name decoding fonterror");
	}

	// TODO: is there a better way to distinguish Arial Caps from Arial proper?
	// cf. http://code.google.com/p/sumatrapdf/issues/detail?id=1290
	if (!strcmp(szPSName, "ArialMT") && (strstr(path, "caps") || strstr(path, "Caps")))
		return fz_error_make(file->ctx, "ignore %s, as it can't be distinguished from Arial,Regular", path);

	if (szPSName[0])
	{
		err = insertmapping(xref->ctx, xref->win_fontlist, szPSName, path, index);
		if (err) return err;
	}
	if (szTTName[0])
	{
		// derive a PostScript-like name and add it, if it's different from the font's
		// included PostScript name; cf. http://code.google.com/p/sumatrapdf/issues/detail?id=376

		// append the font's subfamily, unless it's a Regular font
		if (szStyle[0] && _stricmp(szStyle, "Regular") != 0)
		{
			fz_strlcat(szTTName, "-", MAX_FACENAME);
			fz_strlcat(szTTName, szStyle, MAX_FACENAME);
		}
		removespaces(szTTName);
		// compare the two names before adding this one
		if (lookupcompare(szTTName, szPSName))
		{
			err = insertmapping(xref->ctx, xref->win_fontlist, szTTName, path, index);
			if (err) return err;
		}
	}
	return fz_okay;
}
static fz_error *
parseTTF(fz_stream *file, int offset, int index, char *path)
{
	fz_error *err = nil;
	int byteread;

	TT_OFFSET_TABLE ttOffsetTable;
	TT_TABLE_DIRECTORY tblDir;
	TT_NAME_TABLE_HEADER ttNTHeader;
	TT_NAME_RECORD ttRecord;

	char szTemp[4096];
	int found;
	int i;

	fz_seek(file,offset,0);
	SAFE_FZ_READ(file, &ttOffsetTable, sizeof(TT_OFFSET_TABLE));

	ttOffsetTable.uNumOfTables = SWAPWORD(ttOffsetTable.uNumOfTables);
	ttOffsetTable.uMajorVersion = SWAPWORD(ttOffsetTable.uMajorVersion);
	ttOffsetTable.uMinorVersion = SWAPWORD(ttOffsetTable.uMinorVersion);

	//check is this is a true type font and the version is 1.0
	if(ttOffsetTable.uMajorVersion != 1 || ttOffsetTable.uMinorVersion != 0)
		return fz_throw("fonterror : invalid font version");

	found = 0;
	
	for(i = 0; i< ttOffsetTable.uNumOfTables; i++)
	{
		SAFE_FZ_READ(file,&tblDir,sizeof(TT_TABLE_DIRECTORY));

		memcpy(szTemp, tblDir.szTag, 4);
		szTemp[4] = 0;

		if (stricmp(szTemp, "name") == 0)
		{
			found = 1;
			tblDir.uLength = SWAPLONG(tblDir.uLength);
			tblDir.uOffset = SWAPLONG(tblDir.uOffset);
			break;
		}
		else if (szTemp[0] == 0)
		{
			break;
		}
	}

	if (found)
	{
		fz_seek(file,tblDir.uOffset,0);

		SAFE_FZ_READ(file,&ttNTHeader,sizeof(TT_NAME_TABLE_HEADER));

		ttNTHeader.uNRCount = SWAPWORD(ttNTHeader.uNRCount);
		ttNTHeader.uStorageOffset = SWAPWORD(ttNTHeader.uStorageOffset);

		offset = tblDir.uOffset + sizeof(TT_NAME_TABLE_HEADER);

		for(i = 0; i < ttNTHeader.uNRCount && err == nil; ++i)
		{
			fz_seek(file, offset + sizeof(TT_NAME_RECORD)*i, 0);
			SAFE_FZ_READ(file,&ttRecord,sizeof(TT_NAME_RECORD));

			ttRecord.uNameID = SWAPWORD(ttRecord.uNameID);
			ttRecord.uLanguageID = SWAPWORD(ttRecord.uLanguageID);

			// Full Name
			if(ttRecord.uNameID == 6)
			{
				ttRecord.uPlatformID = SWAPWORD(ttRecord.uPlatformID);
				ttRecord.uEncodingID = SWAPWORD(ttRecord.uEncodingID);
				ttRecord.uStringLength = SWAPWORD(ttRecord.uStringLength);
				ttRecord.uStringOffset = SWAPWORD(ttRecord.uStringOffset);

				fz_seek(file, tblDir.uOffset + ttRecord.uStringOffset + ttNTHeader.uStorageOffset, 0);
				SAFE_FZ_READ(file, szTemp, ttRecord.uStringLength);

				switch(ttRecord.uPlatformID)
				{
				case PLATFORM_UNICODE:
					err = decodeunicodeplatform(szTemp, ttRecord.uStringLength, 
						szTemp, sizeof(szTemp), ttRecord.uEncodingID);
					break;
				case PLATFORM_MACINTOSH:
					err = decodemacintoshplatform(szTemp, ttRecord.uStringLength, 
						szTemp, sizeof(szTemp), ttRecord.uEncodingID);
					break;
				case PLATFORM_ISO:
					err = fz_throw("fonterror : unsupported platform");
					break;
				case PLATFORM_MICROSOFT:
					err = decodemicrosoftplatform(szTemp, ttRecord.uStringLength,
						szTemp, sizeof(szTemp), ttRecord.uEncodingID);
					break;
				}

				if(err == nil)
					err = insertmapping(&fontlistMS, szTemp, path, index);
			}
		}
	}

cleanup:
	return err;
}