blob: 6d35479f6cf306d3dfcc01dcb33a05475a459dee [file] [log] [blame]
/*
* Copyright (C) 2005 David Turner
* Copyright (C) 2007 Trolltech ASA
* Copyright (C) 2007 Red Hat, Inc.
*
* This is part of HarfBuzz, an OpenType Layout engine library.
*
* Permission is hereby granted, without written agreement and without
* license or royalty fees, to use, copy, modify, and distribute this
* software and its documentation for any purpose, provided that the
* above copyright notice and the following two paragraphs appear in
* all copies of this software.
*
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* Red Hat Author(s): Behdad Esfahbod
*/
#include "harfbuzz-impl.h"
#include "harfbuzz-stream-private.h"
#include <stdlib.h>
#if 0
#include <stdio.h>
#define LOG(x) _hb_log x
static void
_hb_log( const char* format, ... )
{
va_list ap;
va_start( ap, format );
vfprintf( stderr, format, ap );
va_end( ap );
}
#else
#define LOG(x) do {} while (0)
#endif
/* only used internally */
static HB_Pointer
_hb_qalloc( HB_UInt size,
HB_Error *perror )
{
HB_Error error = 0;
HB_Pointer block = NULL;
if ( size > 0 )
{
block = malloc( size );
if ( !block )
error = ERR(HB_Err_Out_Of_Memory);
}
*perror = error;
return block;
}
#undef QALLOC /* just in case */
#define QALLOC(ptr,size) ( (ptr) = _hb_qalloc( (size), &error ), error != 0 )
HB_INTERNAL HB_Int
_hb_stream_pos( HB_Stream stream )
{
LOG(( "_hb_stream_pos() -> %ld\n", stream->pos ));
return stream->pos;
}
HB_INTERNAL HB_Error
_hb_stream_seek( HB_Stream stream,
HB_UInt pos )
{
HB_Error error = 0;
stream->pos = pos;
if ( stream->read )
{
if ( stream->read( stream, pos, NULL, 0 ) )
error = ERR(HB_Err_Read_Error);
}
else if ( pos > stream->size )
error = ERR(HB_Err_Read_Error);
LOG(( "_hb_stream_seek(%ld) -> 0x%04X\n", pos, error ));
return error;
}
HB_INTERNAL HB_Error
_hb_stream_frame_enter( HB_Stream stream,
HB_UInt count )
{
HB_Error error = HB_Err_Ok;
HB_UInt read_bytes;
if ( stream->read )
{
/* allocate the frame in memory */
if ( QALLOC( stream->base, count ) )
goto Exit;
/* read it */
read_bytes = stream->read( stream, stream->pos,
stream->base, count );
if ( read_bytes < count )
{
FREE( stream->base );
error = ERR(HB_Err_Read_Error);
}
stream->cursor = stream->base;
stream->limit = stream->cursor + count;
stream->pos += read_bytes;
}
else
{
/* check new position, watch for overflow */
if (HB_UNLIKELY (stream->pos + count > stream->size ||
stream->pos + count < stream->pos))
{
error = ERR(HB_Err_Read_Error);
goto Exit;
}
/* set cursor */
stream->cursor = stream->base + stream->pos;
stream->limit = stream->cursor + count;
stream->pos += count;
}
Exit:
LOG(( "_hb_stream_frame_enter(%ld) -> 0x%04X\n", count, error ));
return error;
}
HB_INTERNAL void
_hb_stream_frame_exit( HB_Stream stream )
{
if ( stream->read )
{
FREE( stream->base );
}
stream->cursor = NULL;
stream->limit = NULL;
LOG(( "_hb_stream_frame_exit()\n" ));
}
HB_INTERNAL HB_Error
_hb_font_goto_table( HB_Font font,
HB_UInt the_tag )
{
HB_Stream stream = font->stream;
HB_UInt offset = 0, sig;
HB_UInt count, nn;
HB_Error error;
LOG(( "_hb_font_goto_table( %p, %c%c%c%c, %p )\n",
font,
(int)((the_tag >> 24) & 0xFF),
(int)((the_tag >> 16) & 0xFF),
(int)((the_tag >> 8) & 0xFF),
(int)(the_tag & 0xFF),
stream ));
if ( !FT_IS_SFNT(font) )
{
LOG(( "not a SFNT font !!\n" ));
error = ERR(HB_Err_Invalid_Argument);
goto Exit;
}
/* parse the directory table directly, without using
* FreeType's built-in data structures
*/
if ( FILE_Seek( 0 ) || ACCESS_Frame( 4 ) )
goto Exit;
sig = GET_Tag4();
FORGET_Frame();
if ( sig == HB_MAKE_TAG( 't', 't', 'c', 'f' ) )
{
/* deal with TrueType collections */
LOG(( ">> This is a TrueType Collection\n" ));
if ( FILE_Seek( 12 + font->face_index*4 ) ||
ACCESS_Frame( 4 ) )
goto Exit;
offset = GET_ULong();
FORGET_Frame();
}
LOG(( "TrueType offset = %ld\n", offset ));
if ( FILE_Seek( offset+4 ) ||
ACCESS_Frame( 2 ) )
goto Exit;
count = GET_UShort();
FORGET_Frame();
if ( FILE_Seek( offset+12 ) ||
ACCESS_Frame( count*16 ) )
goto Exit;
for ( nn = 0; nn < count; nn++ )
{
HB_UInt tag = GET_ULong();
HB_UInt checksum = GET_ULong();
HB_UInt start = GET_ULong();
HB_UInt size = GET_ULong();
HB_UNUSED(checksum);
HB_UNUSED(size);
if ( tag == the_tag )
{
LOG(( "TrueType table (start: %ld) (size: %ld)\n", start, size ));
error = _hb_stream_seek( stream, start );
goto FoundIt;
}
}
error = HB_Err_Not_Covered;
FoundIt:
FORGET_Frame();
Exit:
LOG(( "TrueType error=%d\n", error ));
return error;
}
#undef QALLOC