2020-09-30 17:12:29 +02:00

331 lines
8.6 KiB
C++

/***************************************************************************
*
* File Name: format2.cpp
*
* Copyright (C) 1993-1996 Hewlett-Packard Company.
* All rights reserved.
*
* 11311 Chinden Blvd.
* Boise, Idaho 83714
*
* This is a part of the HP JetAdmin Printer Utility
*
* This source code is only intended as a supplement for support and
* localization of HP JetAdmin by 3rd party Operating System vendors.
* Modification of source code cannot be made without the express written
* consent of Hewlett-Packard.
*
*
* Description:
*
* Author: Name
*
*
* Modification history:
*
* date initials change description
*
* mm-dd-yy MJB
*
*
*
*
*
*
***************************************************************************/
#include <pch_c.h>
#include <stdio.h>
#include <stdlib.h>
#include "tt.hpp"
#include "io.hpp"
#include "ttf2tte.hpp"
#include "ttread.hpp"
extern Io io;
typedef struct
{
unsigned short firstCode, entryCount;
short idDelta;
unsigned short idRangeOffset;
} subheader;
/**********************************************************************/
static ushort
computeFormat2numChars (ushort *subHeaderKeys, subheader *subHeaders)
{
ushort i, subh, charCt;
tt_boolean countedSubheader0;
if (AbortState == bTrue) return 0;
if ((subHeaderKeys == NULL) ||
(subHeaders == NULL))
{
SetAbortState;
return 0;
}
charCt = 0; countedSubheader0 = bFalse;
for (i = 0; i < 256; i++)
{
if (subHeaderKeys[i] == 0)
{
if (!countedSubheader0)
{
charCt += subHeaders[0].entryCount;
countedSubheader0 = bTrue;
}
}
else
{
subh = subHeaderKeys[i] / 8;
charCt += subHeaders[subh].entryCount;
}
}
return (charCt);
} // computeFormat2numChars
/**********************************************************************/
static ushort
getFormat2glyphIndex (ushort currentSubheader, ushort numSubheaders,
ushort idRangeOffset, short idDelta, ushort relativeCode,
ushort numGIAentries, ushort *glyphIndexArray)
{
ushort bytesToStartGIA, GIAindexOfFirstCode, valueGIAentry;
/*
idRangeOffset, within a given subheader, contains the relative offset
from itself to the glyphIndexArray entry for that subheader's firstCode.
There are 8 bytes per subheader and idRangeOffset occupies the last 2.
The offset from idRangeOffset to the beginning of glyphIndexArray is
2 + (8 * the number of subsequent subheaders)
number of subsequent subheaders = numSubheaders - currentSubheader - 1
*/
if (AbortState == bTrue) return 0;
if (glyphIndexArray == NULL)
{
SetAbortState;
return 0;
}
bytesToStartGIA = (8 * (numSubheaders - currentSubheader - 1)) + 2;
if (bytesToStartGIA > idRangeOffset)
{
SetAbortState;
return 0;
}
/* idRangeOffset = bytesToStartGIA + bytes from the start of glyphIndexArray
to the entry for currentSubheader's firstCode */
GIAindexOfFirstCode = (idRangeOffset - bytesToStartGIA) / 2;
if (GIAindexOfFirstCode + relativeCode > numGIAentries)
{
SetAbortState;
return 0;
}
valueGIAentry = glyphIndexArray [GIAindexOfFirstCode + relativeCode];
if (valueGIAentry == 0)
{
return (0);
}
else
{
return (idDelta + valueGIAentry);
}
} // getFormat2glyphIndex
/******************************************************************/
/*
Storage is allocated for these two in this function
but are free'd elsewhere in another file.
They are set to NULL if this function did not allocate them for
any reason.
*charcodes = new ushort[(*numChars)];
*glyphs = new ushort[(*numChars)];
*/
void parse_format2 (FILE *fp, ushort *numChars, ushort **charcodes,
ushort **glyphs)
{
ushort length, revision, i, *glyphIndexArray,
numSubheaders, numGIAentries, charCt, subh, j, nextGlyph;
subheader *subHeaders;
tt_boolean wroteSubheader0glyphs;
ushort *subHeaderKeys;
/*
Since these are allocated in here but freed elsewhere,
we need to indicate that we were unable to allocate
space or that our algorithm died before it got the
chance to allocate these.
Setting them to NULL is our clue to the caller that
it ain't there and need not be freed.
*/
if (charcodes != NULL)
{
*charcodes = NULL;
}
if (glyphs != NULL)
{
*glyphs = NULL;
}
if (AbortState == bTrue) return;
if ((fp == 0) ||
(numChars == NULL) ||
(charcodes == NULL) ||
(glyphs == NULL))
{
SetAbortState;
return;
}
length = io.ReadUShort(fp);
revision = io.ReadUShort(fp);
if (AbortState == bTrue) return; // the read failed
numSubheaders = 0;
subHeaderKeys = new ushort[256];
if (subHeaderKeys == NULL)
{
// out of memory
SetAbortState;
return;
}
for (i = 0; i < 256; i++)
{
subHeaderKeys[i] = io.ReadUShort(fp);
if (subHeaderKeys[i]/8 + 1 > numSubheaders)
numSubheaders = subHeaderKeys[i]/8 + 1;
}
if ((AbortState == bTrue) ||
(518 + (8 * numSubheaders) > length))
{
// format 2 subtable length too small for subheaders
delete [] subHeaderKeys;
SetAbortState;
return;
}
numGIAentries = (length - (518 + (8 * numSubheaders))) / 2;
subHeaders = new subheader[numSubheaders];
glyphIndexArray = new ushort[numGIAentries];
if ((subHeaders == NULL) || (glyphIndexArray == NULL))
{
// out of memory
delete [] subHeaderKeys;
SetAbortState;
return;
}
for (i = 0; i < numSubheaders; i++)
{
subHeaders[i].firstCode = io.ReadUShort(fp);
subHeaders[i].entryCount = io.ReadUShort(fp);
subHeaders[i].idDelta = io.ReadShort(fp);
subHeaders[i].idRangeOffset = io.ReadUShort(fp);
}
for (i = 0; i < numGIAentries; i++)
glyphIndexArray[i] = io.ReadUShort(fp);
*numChars = computeFormat2numChars (subHeaderKeys, subHeaders);
if (AbortState == bTrue)
{
delete [] subHeaderKeys;
delete [] subHeaders;
delete [] glyphIndexArray;
return;
}
*charcodes = new ushort[(*numChars)];
*glyphs = new ushort[(*numChars)];
if ((*charcodes == NULL) || (*glyphs == NULL))
{
// out of memory
SetAbortState;
delete [] subHeaderKeys;
delete [] subHeaders;
delete [] glyphIndexArray;
return;
}
/* fill in the charcodes and glyphs arrays */
wroteSubheader0glyphs = bFalse; charCt = 0;
for (i = 0; i < 256; i++)
{
if (subHeaderKeys[i] == 0)
{
if (bFalse == wroteSubheader0glyphs)
{
for (j = 0; j < subHeaders[0].entryCount; j++)
{
nextGlyph = getFormat2glyphIndex (0, numSubheaders,
subHeaders[0].idRangeOffset,
subHeaders[0].idDelta, j,
numGIAentries, glyphIndexArray);
if (nextGlyph != 0)
{
(*charcodes)[charCt] = subHeaders[0].firstCode + j;
(*glyphs)[charCt] = nextGlyph;
charCt ++;
}
}
wroteSubheader0glyphs = bTrue;
}
}
else // (subHeaderKeys[i] != 0
{
subh = subHeaderKeys[i] / 8;
for (j = 0; j < subHeaders[subh].entryCount; j++)
{
nextGlyph = getFormat2glyphIndex (subh, numSubheaders,
subHeaders[subh].idRangeOffset,
subHeaders[subh].idDelta, j,
numGIAentries, glyphIndexArray);
if (nextGlyph != 0)
{
(*charcodes)[charCt] = (256 * i) + subHeaders[subh].firstCode + j;
(*glyphs)[charCt] = nextGlyph;
charCt ++;
}
} // for (j = 0; j < subHeaders[subh].entryCount; j++)
} // (subHeaderKeys[i] != 0
} // for (i = 0; i < 256; i++)
/* modify numChars to account for removal of maps to glyph 0 */
*numChars = charCt;
/* subHeaders and glyphIndexArray no longer needed */
delete [] subHeaderKeys;
delete [] subHeaders;
delete [] glyphIndexArray;
} // parse_format2