コード例 #1
0
PRIVATE int16 CopyOffsetDirectoryTables(CONST_TTFACC_FILEBUFFERINFO * pInputBufferInfo, 
                                       TTFACC_FILEBUFFERINFO * pOutputBufferInfo, 
                                       uint16 usFormat, 
                                       uint32 * pulNewOutOffset )
{
DIRECTORY *aDirectory;
DIRECTORY Directory;
OFFSET_TABLE OffsetTable;
DTTF_HEADER DttfHeader;
uint16 usnTables;
uint16 usnNewTables;
uint32 ulOffset;
uint32 ulDttfOffset;
uint16 usTableIdx;
uint16 usBytesRead;
uint16 usBytesWritten;
uint32 ulBytesWritten;
int16 errCode;

    ulDttfOffset = TTTableOffset( (TTFACC_FILEBUFFERINFO *)pInputBufferInfo, DTTF_TAG); /* check to see if one there already */
    if (ulDttfOffset != DIRECTORY_ERROR)
    {
        if ((errCode = ReadGeneric((TTFACC_FILEBUFFERINFO *) pInputBufferInfo, (uint8 *) &DttfHeader, SIZEOF_DTTF_HEADER, DTTF_HEADER_CONTROL, ulDttfOffset, &usBytesRead)) != NO_ERROR)
            return(errCode);
        if (DttfHeader.format != TTFDELTA_MERGE) /* only acceptable delta font at this time */
            return(ERR_INVALID_DELTA_FORMAT);
    }

    /* read offset table and determine number of existing tables */
    ulOffset = pInputBufferInfo->ulOffsetTableOffset;
    if ((errCode = ReadGeneric((TTFACC_FILEBUFFERINFO *) pInputBufferInfo, (uint8 *) &OffsetTable, SIZEOF_OFFSET_TABLE, OFFSET_TABLE_CONTROL, ulOffset, &usBytesRead)) != NO_ERROR)
        return(errCode);
    usnTables = OffsetTable.numTables;
    ulOffset += usBytesRead;
    /* Create a list of valid tables */

    aDirectory = (DIRECTORY *) Mem_Alloc((usnTables + (ulDttfOffset == 0)) * sizeof(DIRECTORY));    /* one extra for possible private table */
    if (aDirectory == NULL)
        return(ERR_MEM);
    

    /* sort directories by offset */

    for ( usTableIdx = usnNewTables = 0; usTableIdx < usnTables; usTableIdx++ )
    {
        errCode = ReadGeneric((TTFACC_FILEBUFFERINFO *)pInputBufferInfo, (uint8 *) &Directory, SIZEOF_DIRECTORY, DIRECTORY_CONTROL, ulOffset, &usBytesRead);
        ulOffset += usBytesRead;

        if (errCode != NO_ERROR)
        {
            Mem_Free(aDirectory);
            return errCode;
        }
        if (usFormat == TTFDELTA_DELTA) /* need to get rid of some of the tables */
        {
            switch(Directory.tag)/* only want to keep these */
            {
            /* tables sent each time */
            case HEAD_LONG_TAG:
            case MAXP_LONG_TAG:
            case HHEA_LONG_TAG:
            case VHEA_LONG_TAG:
                /* tables subsetted */
            case CMAP_LONG_TAG:
            case GLYF_LONG_TAG:
            case EBLC_LONG_TAG:
            case EBDT_LONG_TAG:
            case BLOC_LONG_TAG:
            case BDAT_LONG_TAG:
                /* tables compacted */
            case LTSH_LONG_TAG:
            case HMTX_LONG_TAG:
            case VMTX_LONG_TAG:
            case HDMX_LONG_TAG:
            case LOCA_LONG_TAG:
                /* private table - keep shell */
            case DTTF_LONG_TAG:
                break;
            default:  /* any others, just get rid of */
              continue; /* don't copy this over */
            }
        }

        /* empty out the entries */
        aDirectory[ usnNewTables ].length = 0;
        aDirectory[ usnNewTables ].offset = DIRECTORY_ERROR;
        aDirectory[ usnNewTables ].tag = Directory.tag; /* don't worry about the checksum */
        ++ usnNewTables;
    }
    /* add in dttf entry */
    if (ulDttfOffset == 0 && usFormat == TTFDELTA_SUBSET1 || usFormat == TTFDELTA_DELTA)
    {
        aDirectory[ usnNewTables].length = 0;
        aDirectory[ usnNewTables].offset = DIRECTORY_ERROR;
        aDirectory[ usnNewTables].tag = DTTF_LONG_TAG;
        ++usnNewTables;
        SortByTag( aDirectory, usnNewTables );    /* to insert the dttf table */
    }

    OffsetTable.numTables = usnNewTables; /* don't worry if other fields not ok, will be updated in compress tables */
    ulOffset = pOutputBufferInfo->ulOffsetTableOffset;
    errCode = WriteGeneric( pOutputBufferInfo, (uint8 *) &OffsetTable, SIZEOF_OFFSET_TABLE, OFFSET_TABLE_CONTROL, ulOffset, &usBytesWritten);
    /* write out the new directory info to the output buffer */
    ulOffset += usBytesWritten;
    if (errCode == NO_ERROR)
    {
        errCode = WriteGenericRepeat( pOutputBufferInfo, (uint8 *) aDirectory, DIRECTORY_CONTROL, ulOffset, &ulBytesWritten, usnNewTables, SIZEOF_DIRECTORY );
        if (errCode == NO_ERROR)
            *pulNewOutOffset = ulOffset+ulBytesWritten;  /* end of written to data */
    }
    Mem_Free(aDirectory);

    return(errCode);
}
コード例 #2
0
ファイル: modtable.cpp プロジェクト: JianwenSun/cc
int16 ModXmtxXhea( CONST_TTFACC_FILEBUFFERINFO * pInputBufferInfo,
                  TTFACC_FILEBUFFERINFO * pOutputBufferInfo, 
                  CONST uint8 *puchKeepGlyphList, 
                  CONST uint16 usGlyphListCount,
                  CONST uint16 usDttfGlyphIndexCount,
                  CONST uint16 usMaxGlyphIndexUsed,
                  BOOL isHmtx,
                  uint32 *pulNewOutOffset)
{                         

XHEA XHea;
uint16 i,j;
uint32 ulXmtxOffset;
uint32 ulXheaOffset;
uint32 ulCrntOffset;
LONGXMETRIC ZeroLongMetric;
LONGXMETRIC CurrLongMetric;
LONGXMETRIC *LongMetricsArray;
uint16 LongMetricSize;
int16 errCode;
uint16 usBytesRead;
uint16 usBytesWritten;
uint16 nNewLongMetrics;
uint32 ulBytesWritten;
const char * xmtx_tag;
const char * xhea_tag;

   /* determine number of long metrics in hmtx table */

    if (isHmtx)
    {
        xmtx_tag = HMTX_TAG;
        xhea_tag = HHEA_TAG;
        if ((ulXheaOffset = GetHHea( pOutputBufferInfo, (HHEA *) &XHea )) == 0L)
        { /* hasn't been copied yet */
            if ((errCode = CopyTableOver(pOutputBufferInfo, pInputBufferInfo, xhea_tag, pulNewOutOffset)) != NO_ERROR)
                return ERR_INVALID_HHEA;
            if ((ulXheaOffset = GetHHea( pOutputBufferInfo, (HHEA *) &XHea )) == 0L)
                return ERR_MISSING_HHEA;    /* required table */
        }
    }
    else
    {
        xmtx_tag = VMTX_TAG;
        xhea_tag = VHEA_TAG;
        ulXheaOffset = TTTableOffset( (TTFACC_FILEBUFFERINFO *)pInputBufferInfo, xhea_tag);
        ulXmtxOffset = TTTableOffset( (TTFACC_FILEBUFFERINFO *)pInputBufferInfo, xmtx_tag);
        if (ulXheaOffset != DIRECTORY_ERROR && ulXmtxOffset == DIRECTORY_ERROR)   /* this is bogus, get rid of the vhea table */
        {
            MarkTableForDeletion(pOutputBufferInfo, xhea_tag);  /* there is an entry in the output directory */
            return (NO_ERROR);
        } 

        if ((ulXheaOffset = GetVHea( pOutputBufferInfo, (VHEA *) &XHea )) == 0L)
        {
            if ((errCode = CopyTableOver(pOutputBufferInfo, pInputBufferInfo, xhea_tag, pulNewOutOffset)) != NO_ERROR)
            {
                if (errCode == ERR_FORMAT)
                    return NO_ERROR;    /* not required */
                else
                    return errCode;
            }
            if ((ulXheaOffset = GetVHea( pOutputBufferInfo, (VHEA *) &XHea )) == 0L)
                return ERR_MISSING_VHEA;    /* */
        }
    }


    if ((errCode = CopyTableOver(pOutputBufferInfo, pInputBufferInfo, xmtx_tag, pulNewOutOffset)) != NO_ERROR)
        return errCode;
    ulXmtxOffset = TTTableOffset( pOutputBufferInfo, xmtx_tag);

    if ((XHea.numLongMetrics == 0) || (XHea.numLongMetrics > usGlyphListCount))
        return ERR_INVALID_HHEA_OR_VHEA;        /* invalid values */
    
    if (ulXmtxOffset == DIRECTORY_ERROR )
        return ERR_MISSING_HMTX_OR_VMTX;        /* required table */
                                        
    ulCrntOffset = ulXmtxOffset;
    ZeroLongMetric.xsb = 0;
    ZeroLongMetric.advanceX = 0;
    LongMetricSize = GetGenericSize(LONGXMETRIC_CONTROL);

    if (usDttfGlyphIndexCount == 0)    /* not trying to make a compact table, just subsetting */
    {
    /* check to see if we will grow. We will grow with subsetting if our last good glyph index is beyond the current numLongMetrics */

        if ((XHea.numLongMetrics != usGlyphListCount) && /* if longmetrics is the same as number of glyphs, table won't be growing  */ 
            /* need for zero based to 1 base + 1 for the dummy 0 entry */
            (usMaxGlyphIndexUsed + 1 + 1 > XHea.numLongMetrics)) /* check if we may make the table grow */
            return (ERR_WOULD_GROW);
        nNewLongMetrics = min(usGlyphListCount, usMaxGlyphIndexUsed + 1 + 1);   /* + 1 again for dummy */
        /* process all the Long metrics (and perhaps some short when we won't be modifying the table */
        for (i = 0; i < nNewLongMetrics; ++i)
        {
            if (puchKeepGlyphList[i] == FALSE)/* else we don't want to keep this one, 0 metrics to write */
            {
                if ((errCode = WriteGeneric( pOutputBufferInfo, (uint8 *)&ZeroLongMetric, SIZEOF_LONGXMETRIC, LONGXMETRIC_CONTROL, ulCrntOffset, &usBytesWritten)) != NO_ERROR)
                    return (errCode);
            }
            ulCrntOffset += LongMetricSize;
        }
        /* write out short metrics of 0 for the rest of them*/
        for (i = nNewLongMetrics; i < usGlyphListCount; ++i)
        {
            if ((errCode = WriteWord(pOutputBufferInfo, 0, ulCrntOffset)) != NO_ERROR)
                return errCode;
            ulCrntOffset += sizeof (uint16);
        }
        ulBytesWritten = ulCrntOffset - ulXmtxOffset;
    }
    else  /* we want to make a compact table */
    {
    /* now collapse the table if we are in Compact form for Subsetting and Delta fonts */
    /* we will use an interrum table for simplification */
        ulCrntOffset = ulXmtxOffset;
        LongMetricsArray = (LONGXMETRIC *)Mem_Alloc(sizeof(LONGXMETRIC) * usDttfGlyphIndexCount);
        if (LongMetricsArray == NULL)
            return ERR_MEM;
        nNewLongMetrics = 0;
        for (i = 0, j= 0; i < XHea.numLongMetrics && j < usDttfGlyphIndexCount && errCode == NO_ERROR; ++i)  /* need to read and copy up the values */
        {
            if (puchKeepGlyphList[i]) /* if we want to keep the glyph, or its the last special one */
            {
                if ((errCode = ReadGeneric( pOutputBufferInfo, (uint8 *)&CurrLongMetric, SIZEOF_LONGXMETRIC, LONGXMETRIC_CONTROL, ulCrntOffset, &usBytesRead)) != NO_ERROR)
                    break;
                LongMetricsArray[j] = CurrLongMetric;
                ++j;
                ++nNewLongMetrics;
            }
            else if (i == XHea.numLongMetrics-1) /* its that special dummy "last" one, need AW value */
            {
                if ((errCode = ReadGeneric( pOutputBufferInfo, (uint8 *)&CurrLongMetric, SIZEOF_LONGXMETRIC, LONGXMETRIC_CONTROL, ulCrntOffset, &usBytesRead)) != NO_ERROR)
                    break;
                ++nNewLongMetrics; /* we will need an extra one, but guarenteed to be <= XHea.numLongMetrics */
            }
            ulCrntOffset += LongMetricSize;
        }
        if (errCode != NO_ERROR)
        {
            Mem_Free(LongMetricsArray);
            return errCode;
        }
        for (; i < usGlyphListCount && j < usDttfGlyphIndexCount; ++i) /* copy the xsb from the long metrics */
        {
            if (puchKeepGlyphList[i])
            {
                if ((errCode = ReadWord( pOutputBufferInfo, (uint16 *)&(CurrLongMetric.xsb), ulCrntOffset)) != NO_ERROR)
                    break;
                LongMetricsArray[j] = CurrLongMetric;
                ++j;
            }
            ulCrntOffset += sizeof(uint16);
        }
        if (errCode != NO_ERROR)
        {
            Mem_Free(LongMetricsArray);
            return errCode;
        }

        if (j != usDttfGlyphIndexCount)
        {
            Mem_Free(LongMetricsArray);
            return ERR_GENERIC;
        }
        /* first write out the long metrics */
        errCode = WriteGenericRepeat(pOutputBufferInfo,(uint8 *)LongMetricsArray, LONGXMETRIC_CONTROL,
                ulXmtxOffset,&ulBytesWritten, nNewLongMetrics, SIZEOF_LONGXMETRIC);
        /* then write out the short metrics */
        if (errCode == NO_ERROR)
        {
            ulCrntOffset = ulXmtxOffset + ulBytesWritten;
            for (i = nNewLongMetrics; i < usDttfGlyphIndexCount; ++i)
            {
                if ((errCode = WriteWord( pOutputBufferInfo, LongMetricsArray[i].xsb, ulCrntOffset)) != NO_ERROR)
                    break;
                ulCrntOffset += sizeof(uint16);
            }
        }
    
        Mem_Free(LongMetricsArray);
        if (errCode != NO_ERROR)
            return errCode;
        ulBytesWritten = ulCrntOffset - ulXmtxOffset;
    }
  
        /* write out our new, shorter length... cleanup comes later */
    errCode = UpdateDirEntry( pOutputBufferInfo, xmtx_tag, ulBytesWritten );

    if (errCode == NO_ERROR && nNewLongMetrics != XHea.numLongMetrics) 
    {
        XHea.numLongMetrics = nNewLongMetrics;      /* leave these alone if the hmtx table will remain the same */
        if ((errCode = WriteGeneric( pOutputBufferInfo, (uint8 *) &XHea, SIZEOF_XHEA, XHEA_CONTROL, ulXheaOffset, &usBytesWritten )) != NO_ERROR)
            return (errCode);
    }
    *pulNewOutOffset = ulCrntOffset;

    return errCode;
}
コード例 #3
0
ファイル: modglyf.cpp プロジェクト: JianwenSun/cc
int16 ModGlyfLocaAndHead( CONST_TTFACC_FILEBUFFERINFO * pInputBufferInfo, 
                         TTFACC_FILEBUFFERINFO * pOutputBufferInfo,
                         uint8 *puchKeepGlyphList, 
                         uint16 usGlyphCount,
                         uint32 *pCheckSumAdjustment,   /* this is returned to be saved with a subset1 or delta format font */
                         uint32 *pulNewOutOffset)
{

uint16 i;
uint16 usOffset;
uint16 usIdxToLocFmt;
uint16 usBytesWritten;
uint32 ulBytesWritten;
int16 errCode = NO_ERROR;
uint32 * aulLoca;
uint32 ulGlyphLength;
uint32 ulOutLoca;
uint32 ulGlyfOffset;
uint32 ulOutGlyfOffset;
uint32 ulOutGlyfDirectoryOffset;
uint32 ulHeadOffset;
uint32 ulOutLocaOffset;
uint32 ulOutLocaDirectoryOffset;
DIRECTORY LocaDirectory, GlyfDirectory;
HEAD Head;

/* allocate memory for and read loca table */

    aulLoca = (uint32 *)Mem_Alloc( (usGlyphCount + 1) * sizeof( uint32 ));
    if ( aulLoca == NULL )
        return ERR_MEM;

    if (GetLoca((TTFACC_FILEBUFFERINFO *)pInputBufferInfo, aulLoca, usGlyphCount + 1) == 0L)
    {
        Mem_Free(aulLoca);
        return ERR_INVALID_LOCA;
    }

    if ((ulHeadOffset = GetHead(pOutputBufferInfo, &Head)) == 0L)
    {
        /* copy over head table. will update below */
        if ((errCode = CopyTableOver(pOutputBufferInfo, pInputBufferInfo, HEAD_TAG, pulNewOutOffset))!=NO_ERROR)
        {
            Mem_Free(aulLoca);
            return errCode;
        }
        ulHeadOffset = GetHead(pOutputBufferInfo, &Head);
    }
    
    ulOutLoca     = 0L;
    ulGlyfOffset  = TTTableOffset( (TTFACC_FILEBUFFERINFO *)pInputBufferInfo, GLYF_TAG );
    if (ulGlyfOffset == DIRECTORY_ERROR) /* this should have been setup */
    {
        Mem_Free(aulLoca);
        return ERR_MISSING_GLYF; 
    }
    ulOutGlyfDirectoryOffset = GetTTDirectory( pOutputBufferInfo, GLYF_TAG, &GlyfDirectory); 
    /* make sure there is a directory entry */
    if (ulOutGlyfDirectoryOffset == DIRECTORY_ERROR) /* this should have been setup */
    {
        Mem_Free(aulLoca);
        return ERR_MISSING_GLYF; 
    }
    if (GlyfDirectory.offset == DIRECTORY_ERROR)
    {
        if ((errCode = ZeroLongWordAlign(pOutputBufferInfo, *pulNewOutOffset, pulNewOutOffset)) != NO_ERROR)
        {
            Mem_Free(aulLoca);
            return errCode;
        }
        GlyfDirectory.offset = *pulNewOutOffset;
    }

    ulOutGlyfOffset = GlyfDirectory.offset;

    /* go thru the glyf table, copying up the glyphs to be saved */
    for ( i = 0; i < usGlyphCount; i++ )
    {
        ulGlyphLength = 0L;
        if (puchKeepGlyphList[i])   /* we want to keep this one */
        {
            /* copy existing glyph data to new location */

            if ( aulLoca[ i ] < aulLoca[ i+1 ] )
                ulGlyphLength = aulLoca[ i+1 ] - aulLoca[ i ];

            if ( ulGlyphLength )
            {
                if ((errCode = CopyBlockOver( pOutputBufferInfo, pInputBufferInfo, ulOutGlyfOffset + ulOutLoca, 
                        ulGlyfOffset + aulLoca[ i ], ulGlyphLength )) != NO_ERROR)
                    break;
            }
        }
        assert((ulOutLoca & 1) != 1);
        aulLoca[ i ] = ulOutLoca;
        ulOutLoca += ulGlyphLength;
        if (ulOutLoca & 1)
        {       /* the glyph offset is on an odd-byte boundry. get ready for next time */
            if ((errCode = WriteByte( pOutputBufferInfo, 0, ulOutGlyfOffset + ulOutLoca)) != NO_ERROR)
                break;
            ++ulOutLoca;
        }
    }
    if (errCode == NO_ERROR)
    {
    /* The last loca entry is the end of the last glyph! */
        *pulNewOutOffset += ulOutLoca;
        aulLoca[ usGlyphCount ] = ulOutLoca;
        GlyfDirectory.length = ulOutLoca;
        errCode = WriteGeneric( pOutputBufferInfo, (uint8 *)&GlyfDirectory, SIZEOF_DIRECTORY, DIRECTORY_CONTROL, ulOutGlyfDirectoryOffset, &usBytesWritten );
    }

    if (errCode != NO_ERROR)
    {
        Mem_Free(aulLoca);
        return errCode;
    }

    /* write out the modified 'loca' table */
 
    ulOutLocaDirectoryOffset = GetTTDirectory( pOutputBufferInfo, LOCA_TAG, &LocaDirectory); 
    /* make sure there is a directory entry */
    if (ulOutLocaDirectoryOffset == DIRECTORY_ERROR) /* this should have been setup */
    {
        Mem_Free(aulLoca);
        return ERR_MISSING_LOCA;
    }

    if ((errCode = ZeroLongWordAlign(pOutputBufferInfo, *pulNewOutOffset, pulNewOutOffset)) != NO_ERROR)
    {
        Mem_Free(aulLoca);
        return errCode;
    }
    ulOutLocaOffset = LocaDirectory.offset = *pulNewOutOffset;  /* where to write the loca */

    /* Check to see what format to use */
    if (ulOutLoca <= 0x1FFFC)   /* maximum number stored here (0xFFFE * 2) Chosen as conservative value over 0xFFFF * 2 */
    {
        usIdxToLocFmt = SHORT_OFFSETS;
        for ( i = 0; i <= usGlyphCount; i++ )
        {
            assert((aulLoca[i] & 1) != 1);   /* can't have this, would be truncated */
            usOffset = (uint16) (aulLoca[ i ] / 2L);
            if ((errCode = WriteWord( pOutputBufferInfo,  usOffset, ulOutLocaOffset + i*sizeof(uint16) )) != NO_ERROR)
                break;
        }
        ulOutLoca = (uint32) (usGlyphCount+1) * sizeof(uint16);
    }
    else
    {
        usIdxToLocFmt = LONG_OFFSETS;
        errCode = WriteGenericRepeat(pOutputBufferInfo,  (uint8 *) aulLoca, LONG_CONTROL,ulOutLocaOffset,&ulBytesWritten,(uint16) (usGlyphCount+1), sizeof(uint32)); 
        ulOutLoca = ulBytesWritten;
    }

    if (errCode == NO_ERROR)
    {
        /* update the length, etc. for the loca table as well */

        LocaDirectory.length = ulOutLoca;
        *pulNewOutOffset += ulOutLoca;
        if ((errCode = WriteGeneric( pOutputBufferInfo, (uint8 *) &LocaDirectory, SIZEOF_DIRECTORY, DIRECTORY_CONTROL, ulOutLocaDirectoryOffset, &usBytesWritten )) == NO_ERROR)
        {
            *pCheckSumAdjustment = Head.checkSumAdjustment;/* for use by dttf table */
            Head.checkSumAdjustment = 0L;    /* needs to be 0 when setting the file checksum value */
            Head.indexToLocFormat = usIdxToLocFmt;
            errCode = WriteGeneric( pOutputBufferInfo, (uint8 *) &Head, SIZEOF_HEAD, HEAD_CONTROL, ulHeadOffset, &usBytesWritten);
        }
    }

    /* clean up */

    Mem_Free( aulLoca );
    return errCode;

}