Ejemplo n.º 1
0
/* ----------------------------------------------------------------------------
   function:            cmap_getfontmatrix           author:       Eric Penfold
   creation date:       13-Aug-1997            last modification:   ##-###-####
   arguments:
     cmapdict (Input)
     fontid   (Input)
     matrix   (Output)

   description:
     Obtains the font matrix from the CMap to use with the specified
     descendant font.
     If no matrices are defined at all, or no matrix is defined for this
     fontid, then 'matrix' will be set to a null object.


     Returns FALSE if the object in the matrix array is not a valid matrix,
     or if the fontid is invalid (i.e. the matrix array has fewer entries);
     TRUE is otherwise returned.
---------------------------------------------------------------------------- */
Bool cmap_getfontmatrix(OBJECT *cmapdict, int32 fontid, OBJECT *matrix)
{
  OBJECT *cmap, *matblk;
  OMATRIX omat;

  /* Extract CMap */
  if ( oType(*cmapdict) != ODICTIONARY )
    return FAILURE(FALSE); /* Error - Invalid dictionary */

  cmap = fast_extract_hash_name(cmapdict, NAME_CodeMap);

  /* Extract matrix block */
  if ( oType(*cmap) != ODICTIONARY )
    return FAILURE(FALSE); /* Error - Invalid dictionary */

  matblk = fast_extract_hash_name(cmap, NAME_usematrixblock);

  if ( !matblk ) {
    object_store_null(matrix); /* No usematrix defined, use defaults */
  } else if ( oType(*matblk) != OARRAY ||
              theLen(*matblk) <= fontid ||
              !is_matrix(oArray(*matblk) + fontid, &omat) ) {
    return FAILURE(FALSE); /* usematrix definition is not valid (for this fontid) */
  } else
    Copy(matrix, oArray(*matblk) + fontid);

  return TRUE;
}
Ejemplo n.º 2
0
/*----------------------------------------------------------------------------*/
void gsc_rcbequiv_handle_detectop(OBJECT *key, OBJECT *value)
{
  int32 *equivlevel;
  EQUIVCOLOR *equivs;
  int32 len;
  OBJECT *olist;
  NAMECACHE *sepname;

  HQASSERT(key, "key NULL");
  HQASSERT(value, "value NULL");
  HQASSERT(oType(*key) == ONAME, "name expected");
  /* Currently should only get /spots from freehand */
  HQASSERT(oName(*key) == system_names + NAME_spots, "unexpected name");

  if ( oType(*value) != OARRAY &&
       oType(*value) != OPACKEDARRAY )
    return;

  len = theILen(value);

  if ( ! len )
    return;

  /* Got an array, does it look like we expect: contain arrays of length 6 */
  olist = oArray(*value);
  for ( key = olist + len ; olist < key; ++olist ) {
    int32 type = oType(*olist);
    if ( type != OARRAY && type != OPACKEDARRAY )
      return;
    if ( theILen(olist) != 6 )
      return;
  }
  olist -= len;

  /* The array looks like it might be a freehand spots array, so lets risk it
     as long as a higher priority method hasn't set these values already */
  rcbn_current_equiv_details(&equivlevel, &equivs);
  if ( (*equivlevel) >= GSC_EQUIV_LVL_FREEHANDSPOTS )
    return;

  /* Get real name of current sep */
  sepname = rcbn_sepnmActual(rcbn_iterate(NULL));
  if ( ! sepname )
    return;

  for ( /* key set above */ ; olist < key; ++olist ) {
    OBJECT *sublist = oArray(*olist);
    if ( oType(sublist[4]) != OSTRING )
      return;
    if ( sepname == cachename(oString(sublist[4]),
                              theLen(sublist[4])) &&
         read_colors_array(olist, *equivs) ) {
      *equivlevel = GSC_EQUIV_LVL_FREEHANDSPOTS;
      return;
    }
  }
}
Ejemplo n.º 3
0
Bool pdf_matrix( PDFCONTEXT *pdfc , OBJECT *theo)
{
  register OBJECT *olist ;
  PDFXCONTEXT *pdfxc ;
  int i ;

  PDF_CHECK_MC( pdfc ) ;
  PDF_GET_XC( pdfxc ) ;
  HQASSERT( theo , "theo NULL in pdf_matrix." ) ;

  if ( NULL == ( olist = ( OBJECT * )PDF_ALLOCOBJECT( pdfxc , 6 )))
    return error_handler( VMERROR ) ;

  theTags(*theo) = OARRAY | LITERAL | UNLIMITED ;
  SETGLOBJECTTO(*theo, FALSE) ;
  theLen(*theo) = 6 ;
  oArray(*theo) = olist ;

  for ( i=0; i<6; i++ ) {
    theTags( olist[i] ) = OREAL | LITERAL ;
    oReal(olist[i]) = (i % 3 == 0) ? 1.0f : 0.0f ;
  }

  return TRUE ;
}
Ejemplo n.º 4
0
Bool pdf_create_array( PDFCONTEXT *pdfc , int32 len , OBJECT *thearray )
{
  OBJECT *array ;
  PDFXCONTEXT *pdfxc ;

  PDF_CHECK_MC( pdfc ) ;
  PDF_GET_XC( pdfxc ) ;
  HQASSERT( thearray , "thearray NULL in pdf_create_array." ) ;

  if ( len < 0 )
    return error_handler( RANGECHECK ) ;
  if ( len > MAXPSARRAY )
    return error_handler( LIMITCHECK ) ;

  if ( len > 0 ) {
    array = PDF_ALLOCOBJECT( pdfxc, len ) ;
    if ( ! array )
      return error_handler( VMERROR ) ;
  }
  else
    array = NULL ;

  theTags(*thearray) = OARRAY | UNLIMITED | LITERAL ;
  SETGLOBJECTTO(*thearray, FALSE) ; /* array itself is local */
  theLen(*thearray) = ( uint16 )len ;
  oArray(*thearray) = array ;

  return TRUE ;
}
Ejemplo n.º 5
0
/*----------------------------------------------------------------------------*/
static Bool read_colors_array(OBJECT *arrayo, EQUIVCOLOR equivs)
{
  int32 i;

  if ( oType(*arrayo) != OARRAY &&
       oType(*arrayo) != OPACKEDARRAY )
    return FALSE;
  if ( theILen(arrayo) < 4 )
    return FALSE;

  arrayo = oArray(*arrayo);
  for ( i = 0 ; i < 4; ++i )
    if ( oType(arrayo[i]) != OINTEGER &&
         oType(arrayo[i]) != OREAL )
      return FALSE;

  for ( i = 0 ; i < 4; ++i ) {
    if ( oType(arrayo[i]) == OREAL )
      equivs[i] = oReal(arrayo[i]);
    else
      equivs[i] = (USERVALUE)oInteger(arrayo[i]);
  }

  return TRUE;
}
Ejemplo n.º 6
0
/* For xaforall, the execution stack contains:
      0 ONOTHING  len=size of this block (3 or 5)  oOp = xaforall
      1 OARRAY    len=elements left to deliver  oArray=next element to deliver
        or OEXTENDED  len=0  oArray = trampoline below
      2 OARRAY - the proc to run
   For long arrays:
      3 OARRAY    len=0  oArray = next element to deliver
      4 OINTEGER  len=0  oInteger = remaining elements
*/
Bool xaforall(ps_context_t *pscontext)
{
  register OBJECT *theo ;

  UNUSED_PARAM(ps_context_t *, pscontext) ;

  theo = stackindex( 1 , & executionstack ) ;

  if ( ! theXLen(*theo)) {
    npop( theLen(*theTop(executionstack)) , & executionstack ) ;
    return TRUE ;
  }

  if ( oType(*theo) == OEXTENDED ) {  /* Long arrays */

    if ( !push(oLongArray(*theo), &operandstack) )
      return FALSE ;

    if (--oLongArrayLen(*theo) == 0)
      oLongArray(*theo) = NULL ;
    else
      ++oLongArray(*theo) ;

  } else {  /* Normal arrays */

    if ( ! push(oArray(*theo) , & operandstack ))
      return FALSE ;

    if ( --theLen(*theo) == 0 )
      oArray(*theo) = NULL ;
    else
      ++oArray(*theo) ;
  }

  theo = stackindex( 2 , & executionstack ) ;
  if ( oExecutable(*theo) )
    return push( theo , & executionstack ) ;
  else
    return push( theo , & operandstack ) ;
}
Ejemplo n.º 7
0
//保存最高分到文件中
bool CGeneralManager::SaveHighScoreToFile()
{
	string strPath = FileUtils::getInstance()->getWritablePath() + string(HIGHSCORE_FILEPATH);
	string strContent = FileUtils::getInstance()->getStringFromFile(strPath);
	rapidjson::Document oDoc;
	oDoc.Parse<0>(strContent.c_str());
	if (oDoc.HasParseError() || oDoc.IsNull())
	{
		oDoc.SetObject();
		rapidjson::Document::AllocatorType& allocator = oDoc.GetAllocator();
		rapidjson::Value oArray(rapidjson::kArrayType);

		for (int i = 0; i < GAME_MAX; ++i)
		{
			oArray.PushBack(m_mapHighScore[i], allocator);
		}
		oDoc.AddMember("HighScore", oArray, allocator);
	}
	else
	{
		//更新数据
		for (rapidjson::SizeType i = 0; i < oDoc["HighScore"].Capacity(); i++)
		{
			if (oDoc["HighScore"][i].IsNull())
			{
				return false;
			}
			oDoc["HighScore"][i].SetInt(m_mapHighScore[i]);
		}
	}

	rapidjson::StringBuffer oBuffer;
	rapidjson::Writer<rapidjson::StringBuffer> oWriter(oBuffer);
	oDoc.Accept(oWriter);

	FILE* pFile = fopen(strPath.c_str(), "wb+");
	if (pFile == NULL)
	{
		log("Open File '%s' Failed.", strPath.c_str());
		return false;
	}

	fputs(oBuffer.GetString(), pFile);
	fclose(pFile);

	return true;
}
Ejemplo n.º 8
0
/* Set the current blend mode. This can be a single name (e.g. Normal), or an
 * array of names. The names are not validated - we don't really know what
 * blend modes are supported at this stage.
 */
Bool pdf_setBlendMode(PDFCONTEXT* pdfc, OBJECT object)
{
  PDF_CHECK_MC(pdfc);

  /* Resolve any indirect references */
  if (!pdf_resolvexrefs(pdfc, &object)) {
    return FAILURE(FALSE) ;
  }

  /* Validate the type of the parameter - it must be a name or name array */
  switch (oType(object)) {

    case OARRAY:
    case OPACKEDARRAY:

      if (theLen(object) <= 0) {
        return error_handler(RANGECHECK) ;
      }
      else {
        int32 i;
        OBJECT *list = oArray(object);

        /* Ensure that each object in the array is a name */
        for (i = 0; i < theLen(object); i ++) {
          if (oType(list[i]) != ONAME) {
            return error_handler(TYPECHECK) ;
          }
        }
      }
      break;

    case ONAME:
      /* A name is ok */
      break;

    default:
      /* Any other type is unacceptable */
      return error_handler(TYPECHECK) ;
  }

  tsSetBlendMode(gsTranState(gstateptr), object, gstateptr->colorInfo);
  return TRUE;
}
Ejemplo n.º 9
0
/** check_colorants_dictionary takes a DeviceN colorspace and
    returns a pointer to the Colorants dictionary if there is one. */
static Bool check_colorants_dictionary(
  /*@notnull@*/                        const OBJECT *PSColorSpace,
  /*@notnull@*/ /*@out@*/              OBJECT **colorantsDict)
{
  OBJECT* theo;
  int32 len;

  *colorantsDict = NULL;

  theo = oArray(*PSColorSpace) ;  /* DeviceN array */

  /* Ignore non-DeviceN color spaces */
  if (oName(*theo) != system_names + NAME_DeviceN)
    return TRUE;

  HQASSERT(colorantsDict != NULL,
           "null colorants dictionary pointer" );

  *colorantsDict = NULL;

  len = theILen( PSColorSpace );

  if (len == 5) {
    /* we should have an attributes dictionary */

    theo += 4 ;         /* attributes dict */

    if ( oType(*theo) != ODICTIONARY ) {
      return error_handler( TYPECHECK );
    }

    *colorantsDict = fast_extract_hash_name(theo, NAME_Colorants);

    /* if simply not found, ignore the fact */
    if (*colorantsDict != NULL) {
      if ( oType(**colorantsDict) != ODICTIONARY ) {
        return error_handler( TYPECHECK );
      }
    }
  }
  return TRUE;
}
Ejemplo n.º 10
0
static Bool cid0_select_subfont(FONTinfo *fontInfo,
                                 charcontext_t *context)
{
  OBJECT *fdict, *theo ;

  HQASSERT(fontInfo, "No font info") ;
  HQASSERT(context, "No context") ;

  HQASSERT(theIFontType(fontInfo) == CIDFONTTYPE0, "Not in a CID Type 0") ;

  /* Now we've got the font number, check that it's within the bounds of the
     FDArray and have a go at setting the fontinfo */

  /* Extract the FD_Array. */
  theo = fast_extract_hash_name(&theMyFont(*fontInfo), NAME_FDArray);
  if ( !theo )
    return error_handler(INVALIDFONT);

  if ( oType(*theo) != OARRAY &&
       oType(*theo) != OPACKEDARRAY )
    return error_handler(INVALIDFONT);

  if ( theFDIndex(*fontInfo) >= theLen(*theo) )
    return error_handler(INVALIDFONT);

  /* And finally get our hands on the font dictionary */
  fdict = oArray(*theo) + theFDIndex(*fontInfo) ;
  if ( oType(*fdict) != ODICTIONARY )
    return error_handler(INVALIDFONT);

  /* Then do the necessary for the sub-dictionary. Currently, this
     concatenates the sub fonts matrix onto the font matrix, and sets the
     charstring type. */
  if ( !set_cid_subfont(fontInfo, fdict) )
    return FALSE ;

  context->chartype = CHAR_Type1 ;

  return TRUE ;
}
Ejemplo n.º 11
0
void pdf_destroy_array( PDFCONTEXT *pdfc , int32 len , OBJECT *thearray )
{
  PDF_CHECK_MC( pdfc ) ;
  HQASSERT( len >=0 , "len must be positive" ) ;
  HQASSERT( thearray != NULL , "thearray NULL in pdf_destroy_array" ) ;
  HQASSERT( oType(*thearray) == OARRAY ||
            oType(*thearray) == OPACKEDARRAY ,
            "Non-array passed into pdf_destroy_array" ) ;

  if ( len != 0 )
  {
    PDFXCONTEXT *pdfxc ;
    OBJECT *array ;

    PDF_GET_XC( pdfxc ) ;

    array = oArray(*thearray) ;
    HQASSERT( array != NULL , "array NULL in pdf_destroy_array" ) ;

    PDF_FREEOBJECT( pdfxc, array , len ) ;
  }
  theTags(*thearray) = ONOTHING ;
}
Ejemplo n.º 12
0
/** pdf_createfilterlist
 *
 * Call this to layer filters on top of an existing file or filter.
 *
 * Pass the existing file or filter in "file".
 * (This gets changed to be the topmost newly-added filter).
 *
 * Pass the name or array of names of the desired filter-types in "theo".
 *
 * Pass the filter-parameters or array of filter-parameters in "parms".
 *
 * Pass flag indicating if each filter-parameter dictionary needs
 * a deep copy to a new object before creating the filter in.
 * "copyparms".
 *
 * Pass whether the close source/target flag should be set (for
 * non-StreamDecode filters) in the "cst" flag.
 *
 * Returns:
 * The "*file" object is overwritten with the topmost newly-added filter.
 *
 * **** Note: Used for PDF Out as well as PDF input ***
 */
Bool pdf_createfilterlist( PDFCONTEXT *pdfc , OBJECT *file , OBJECT *theo ,
                           OBJECT *parms, Bool copyparms, int32 cst )
{
  HQASSERT( pdfc , "pdfc NULL in pdf_createfilterlist" ) ;
  HQASSERT( file , "file NULL in pdf_createfilterlist" ) ;
  HQASSERT( oType(*file) == OFILE ,
            "file not a file in pdf_createfilterlist" ) ;

  if ( theo != NULL ) {
    OBJECT null = OBJECT_NOTVM_NULL ;
    OBJECT dict = OBJECT_NOTVM_NOTHING ;

    if ( oType(*theo) == ONAME ) {
      if ( ! parms )
        parms = ( & null ) ;
      else {
        if ( oType(*parms) == OARRAY || oType(*parms) == OPACKEDARRAY ) {
          if ( theLen(*parms) != 1 )
            return error_handler( TYPECHECK ) ;
          parms = oArray(*parms) ;
        }
      }

      Copy( & dict, parms ) ;
      if ( copyparms ) {
        if ( ! pdf_copyobject( pdfc, parms, & dict ) )
          return FALSE ;
        if ( ! pdf_resolvexrefs( pdfc , &dict) )
          return FALSE ;
      }

      if ( !pdf_createfilter( pdfc , file , theo , & dict , cst ) )
        return FALSE ;
    }
    else {
      int32 i ;
      int32 len ;
      int32 isarray ;
      OBJECT *olistn , *olista ;

      HQASSERT(oType(*theo) == OARRAY || oType(*theo) == OPACKEDARRAY,
               "only know about names & arrays" ) ;
      if ( ! parms )
        parms = ( & null ) ;
      else {
        if ( oType(*parms) == ODICTIONARY )
          return error_handler( TYPECHECK ) ;
        if ( (oType(*parms) == OARRAY || oType(*parms) == OPACKEDARRAY)
             && theLen(*theo) != theLen(*parms) )
          return error_handler( RANGECHECK ) ;
      }
      olistn = oArray(*theo) ;
      isarray = FALSE ;
      olista = parms ;
      if ( oType(*parms) == OARRAY || oType(*parms) == OPACKEDARRAY ) {
        isarray = TRUE ;
        olista = oArray(*parms) ;
      }
      len = theLen(*theo) ;
      for ( i = 0 ; i < len ; ++i ) {
        theo = olistn ;
        if ( oType(*theo) == OINDIRECT ) {
          if ( ! pdf_lookupxref(pdfc, &theo, oXRefID(*theo),
                                theGen(*theo), FALSE) )
            return FALSE ;
          if ( theo == NULL )
            return error_handler( UNDEFINEDRESOURCE ) ;
        }
        if ( oType(*theo) != ONAME )
          return error_handler( TYPECHECK ) ;

        parms = olista ;
        if ( oType(*parms) == OINDIRECT ) {
          if ( ! pdf_lookupxref(pdfc, &parms, oXRefID(*parms),
                                theGen(*parms), FALSE) )
            return FALSE ;
          if ( parms == NULL )
            return error_handler( UNDEFINEDRESOURCE ) ;
        }
        if ( oType(*parms) != ONULL && oType(*parms) != ODICTIONARY )
          return error_handler( TYPECHECK ) ;

        Copy( & dict, parms ) ;
        if ( copyparms ) {
          if ( ! pdf_copyobject( pdfc, parms, & dict ) )
            return FALSE ;
          if ( ! pdf_resolvexrefs( pdfc , &dict) )
            return FALSE ;
        }

        if ( !pdf_createfilter( pdfc , file , theo , & dict , cst ) )
          return FALSE ;

        ++olistn ;
        if ( isarray )
          ++olista ;
      }
    }
  }

  return TRUE;
}
Ejemplo n.º 13
0
/** Internal routine for recursively setting cache lastAccessId
    values. */
static Bool pdf_set_xref_last_access_recurse( PDFXCONTEXT *pdfxc ,
                                              OBJECT *theo , int32 pageId )
{
  HQASSERT( pdfxc , "pdfxc NULL in pdf_set_xref_last_access_recurse.\n" ) ;
  HQASSERT( theo , "theo NULL in pdf_set_xref_last_access_recurse.\n" ) ;

  if ( ++( pdfxc->recursion_depth ) > PDF_MAX_RECURSION_DEPTH )
    return error_handler( LIMITCHECK ) ;

  switch ( oType( *theo )) {
    case OARRAY:
    case OPACKEDARRAY:
      {
        int32 len = theLen(*theo) ;
        OBJECT *olist = oArray( *theo ) ;
        int32 i ;

        for ( i = 0 ; i < len ; i ++ ) {
          if ( ! pdf_set_xref_last_access_recurse( pdfxc , olist++ , pageId )) {
            return FALSE ;
          }
        }

        break ;
      }

    case ODICTIONARY:
      {
        PDF_XREF_LAST_ACCESS_PARAMS params ;

        params.pdfxc = pdfxc ;
        params.pageId = pageId ;
        params.isStreamDictionary = FALSE ;

        if ( ! walk_dictionary( theo , pdf_set_xref_last_access_dictwalkfn ,
                                & params )) {
          return FALSE ;
        }

        break ;
      }

    case OFILE:
      {
        OBJECT *dict = streamLookupDict( theo ) ;
        OBJECT *ind ;
        PDF_XREF_LAST_ACCESS_PARAMS params ;

        params.pdfxc = pdfxc ;
        params.pageId = pageId ;
        params.isStreamDictionary = TRUE ;

        if ( ! walk_dictionary( dict , pdf_set_xref_last_access_dictwalkfn ,
                                & params )) {
          return FALSE ;
        }

        ind = fast_extract_hash_name( dict , NAME_HqnCacheSlot ) ;
        if ( ind != NULL ) {
          XREFCACHE *cache ;
          int32 objnum ;

          HQASSERT( oType( *ind ) == OINTEGER ,
                    "Invalid cache slot telltale for stream" ) ;
          objnum = oInteger( *ind ) ;

          for ( cache = pdfxc->xrefcache[ objnum & (XREF_CACHE_SIZE-1)] ;
                cache != NULL ; cache = cache->xrefnxt ) {
            if ( cache->objnum == oInteger( *ind ) &&
                 cache->lastAccessId != pageId &&
                 ( cache->lastAccessId >= 0 || pageId < cache->lastAccessId )) {
              cache->lastAccessId = pageId ;
              break ;
            }
          }
        }
        break;
      }

    default:
      /* Nothing to do */
      break ;
  }

  pdfxc->recursion_depth -= 1 ;

  HQASSERT( pdfxc->recursion_depth >= 0 ,
            "Recursion depth went below zero!" ) ;

  return TRUE ;
}
Ejemplo n.º 14
0
/** Recursive implementation for pdf_resolvexrefs. 'resolveId' should be a
unique number, and will be used to mark each object that this function looks-up
via pdf_lookupxref_with_id(); if the same object is looked-up more than once,
it will only be recursively resolved the first time.
*/
static Bool pdf_resolvexrefs_internal( PDFCONTEXT *pdfc , OBJECT *theo )
{

  PDFXCONTEXT *pdfxc ;
  Bool alreadyResolved = FALSE ;

  PDF_CHECK_MC( pdfc ) ;
  PDF_GET_XC( pdfxc ) ;

  HQASSERT( pdfc , "pdfc NULL in pdf_resolvexrefs.\n" ) ;
  HQASSERT( theo , "theo NULL in pdf_resolvexrefs.\n" ) ;

  if ( ++( pdfxc->recursion_depth ) > PDF_MAX_RECURSION_DEPTH ) {
    return FAILURE( error_handler( LIMITCHECK )) ;
  }

  /* First do a lookup if one is needed */

  if ( oType( *theo ) == OINDIRECT ) {
    OBJECT *thex ;

    pdfxc->nestedObjnum[ pdfxc->lookup_depth ] = oXRefID( *theo ) ;
    pdfxc->lookup_depth++ ;

    if ( ! pdf_lookupxref_with_id( pdfc , & thex , oXRefID( *theo ) ,
                                   theGen(*theo) , FALSE ,
                                   &alreadyResolved )) {
      pdfxc->lookup_depth-- ;
      return FAILURE( FALSE ) ;
    }

    pdfxc->lookup_depth-- ;

    if ( thex == NULL ) {
      return FAILURE( error_handler( UNDEFINEDRESOURCE )) ;
    }

    if ( ! pdf_copyobject( pdfc , thex , theo ) ) {
      return FAILURE( FALSE ) ;
    }
  }

  if ( ! alreadyResolved ) {
    PdfResolveParams params ;

    params.pdfc = pdfc ;
    params.isStreamDictionary = FALSE ;

    /* Now see if the object we have is composite and needs walking */
    switch ( oType( *theo )) {
      case OARRAY:
      case OPACKEDARRAY:
      {
        int32 len = theLen(*theo) ;
        OBJECT *olist = oArray( *theo ) ;
        int32 i ;

        for ( i = 0 ; i < len ; i ++ ) {
          if ( ! pdf_resolvexrefs_internal( pdfc , olist++ )) {
            return FAILURE( FALSE ) ;
          }
        }

        break ;
      }

      case ODICTIONARY:
      {
        if ( ! walk_dictionary( theo , pdf_resxref_dictwalkfn,
                                ( void * )&params )) {
          return FAILURE( FALSE ) ;
        }

        break ;
      }

      case OFILE:
      {
        OBJECT* streamDictionary = streamLookupDict( theo ) ;
        params.isStreamDictionary = TRUE ;
        if ( oType( *streamDictionary ) == ODICTIONARY &&
             ! walk_dictionary( streamDictionary , pdf_resxref_dictwalkfn,
                                ( void * )&params )) {
          return FAILURE( FALSE ) ;
        }

        break;
      }

      default:
        /* Nothing to do */
        break ;
    }
  }

  pdfxc->recursion_depth -= 1 ;

  HQASSERT( pdfxc->recursion_depth >= 0 ,
            "Recursion depth went below zero!" ) ;

  return TRUE ;
}
Ejemplo n.º 15
0
/* CID Font Type 0 charstring definitions. Subroutines allow PostScript
   and lookup disk/string lookup. SEAC is supported. PS Type 1 get_info is
   used because font structure is shared. */
static Bool cid0_begin_subr(void *data, int32 subno, int32 global,
                             uint8 **subrstr, uint32 *subrlen)
{
  CID0_CACHE *cid_font = data ;

  UNUSED_PARAM(int32, global) ;

  HQASSERT(cid_font != NULL, "No CID font") ;
  HQASSERT(subrstr != NULL, "Nowhere for subr string") ;
  HQASSERT(subrlen != NULL, "Nowhere for subr length") ;
  HQASSERT(!global, "CID Type 0 does not support global subrs") ;

  /* Range check the subroutine number. */
  if ( subno < 0 || (uint32)subno >= cid_font->subrcount )
    return FAILURE(FALSE) ;

  /* PLRM3 relaxed the rules about Subrs to allow the old form as well
     as the shared form for CID Fonts */
  if ( cid_font->subrs ) {
    OBJECT *theo = cid_font->subrs ;

    HQASSERT(oType(*theo) == OARRAY || oType(*theo) == OPACKEDARRAY,
             "Subrs is not an array") ;
    HQASSERT(theLen(*theo) == cid_font->subrcount,
             "SubrCount does not match Subrs length") ;

    theo = &oArray(*theo)[subno] ;

    /* Type check the subroutine. */
    if (oType(*theo) != OSTRING )
      return FAILURE(FALSE) ;

    *subrstr = oString(*theo) ;
    *subrlen = theLen(*theo) ;
  } else { /* No Subrs, check the SubrMap */
    uint8 *frame, *mapdata ;
    uint32 offset1, offset2 ;

    HQASSERT(cid_font->font_data, "Font data is not open in CID subr") ;

    /* Read the start and end offsets of the subroutine from the subr map */
    if ( (frame = fontdata_frame(cid_font->font_data,
                                 cid_font->offset + cid_font->subrmapoffset + subno * cid_font->sdbytes,
                                 cid_font->sdbytes + cid_font->sdbytes,
                                 sizeof(uint8))) == NULL )
      return FALSE ;

    mapdata = frame ;
    offset1 = cidmap_offset(&mapdata, cid_font->sdbytes) ;
    offset2 = cidmap_offset(&mapdata, cid_font->sdbytes) ;

    if ( offset2 < offset1 )
      return error_handler(INVALIDFONT) ;

    /* Convert the offsets to a length, and open a frame for the subr */
    *subrlen = offset2 - offset1 ;
    if ( (*subrstr = fontdata_frame(cid_font->font_data,
                                    cid_font->offset + offset1,
                                    *subrlen,
                                    sizeof(uint8))) == NULL )
      return FALSE ;
  }

  return TRUE ;
}
Ejemplo n.º 16
0
/* Walk the CMap's mapping block, calling back the iterator function for each
   block in turn. This is used when constructing CIDMaps for CID Font Type 2
   (TrueType). */
Bool cmap_walk(OBJECT *cmap, cmap_iterator_fn iterator, void *data)
{
  OBJECT *mapping;
  int32 num_block;

  HQASSERT(cmap, "No CMap dictionary") ;
  HQASSERT(iterator, "No CMap iterator function") ;

  if ( oType(*cmap) != ODICTIONARY )
    return error_handler(TYPECHECK) ;

  cmap = fast_extract_hash_name(cmap, NAME_CodeMap);
  if ( !cmap )
    return error_handler(TYPECHECK);

  mapping = fast_extract_hash_name(cmap, NAME_mappingblock);
  if ( !mapping || oType(*mapping) != OARRAY )
    return error_handler(TYPECHECK);

  num_block = theLen(*mapping);
  if (num_block < 1)
    return error_handler(RANGECHECK);

  /* For each mapping definition block */
  for ( mapping = oArray(*mapping) ; (num_block -= 3) >= 0 ; mapping += 3 ) {
    int32 num_entry;
    OBJECT *rd_entry;
#if defined(ASSERT_BUILD)
    int32 fontid, map_type;

    /* Fontid and mapping type are in mapping[0] and mapping[1]. Neither of
       these are used for real; map_type is used for assertions. */
    HQASSERT(oType(mapping[0]) == OINTEGER,
             "CMap mapping fontid is not an integer") ;
    fontid = oInteger(mapping[0]);
    HQASSERT(oType(mapping[1]) == OINTEGER,
             "CMap mapping type is not an integer") ;
    map_type = oInteger(mapping[1]);
    HQASSERT(map_type == MAP_CID || map_type == MAP_BF,
             "Invalid CMap mapping type") ;
#endif

    /* For each entry in that block */
    HQASSERT(oType(mapping[2]) == OARRAY,
             "CMap mapping block list is not an array") ;
    num_entry = theLen(mapping[2]);
    for ( rd_entry = oArray(mapping[2]); --num_entry >= 0 ; ++rd_entry ) {
      OBJECT *rd_mbyte, mapsfrom = OBJECT_NOTVM_NOTHING,
        mapsto = OBJECT_NOTVM_NOTHING ;
      uint32 offset, rlen, bindex, eindex, dimensions;
      Bool more ;
      uint8 rcurr[CMAP_MAX_CODESPACE_LEN], rmap[CMAP_MAX_CODESPACE_LEN] ;
      uint8 *rstart, *rend ;

      HQASSERT(oType(*rd_entry) == OARRAY,
               "CMap mapping block entry is not an array") ;
      HQASSERT(theLen(*rd_entry) == 3,
               "CMap mapping block entry length is wrong") ;
      rd_mbyte = oArray(*rd_entry);
      HQASSERT(oType(rd_mbyte[0]) == OSTRING && oType(rd_mbyte[1]) == OSTRING,
               "CMap mapping range entry is not a string") ;
      HQASSERT(theLen(rd_mbyte[0]) == theLen(rd_mbyte[1]),
               "mapping range start/end are of different length" );
      dimensions = theLen(rd_mbyte[0]);
      HQASSERT(dimensions > 0 && dimensions <= CMAP_MAX_CODESPACE_LEN,
               "mapping range dimensions invalid" );

      rstart = oString(rd_mbyte[0]) ;
      rend = oString(rd_mbyte[1]) ;

      /* Make a copy of the range string; this will be modified to iterate
         over contiguous sub-ranges of the range. */
      OCopy(mapsfrom, rd_mbyte[0]) ;
      for (bindex = 0; bindex < dimensions; ++bindex) {
        rcurr[bindex] = rstart[bindex];
      }
      oString(mapsfrom) = rcurr ;

      /* The range may differ in more than one byte (a multidimensional
         range). We are going to pass contiguous ranges to the iterator
         function, so we will unpack multi-dimensional ranges to single
         dimensional ranges. The following code iterates over the range,
         selecting contiguous sub-ranges for each iteration. We can optimise
         the size of the sub-ranges selected by noting how many trailing
         bytes of the dimension strings cover the full byte range; these need
         never be changed in our iteration. */
      for ( eindex = dimensions, rlen = 1 ; --eindex > 0 ; ) {
        if ( rstart[eindex] != 0 || rend[eindex] != 0xff )
          break ;
        rlen <<= 8 ;
      }
      /* rlen is the length of the maximum contiguous span within the
         dimensions. eindex is the last dimension in the range strings that
         does not cover the full byte range. */
      rlen *= rend[eindex] - rstart[eindex] + 1 ;

      /* bindex is the first dimension in which there is a difference. If
         bindex and eindex are the same, the whole range is covered in one
         go. */
      for ( bindex = 0 ; bindex < eindex ; ++bindex ) {
        if ( rstart[bindex] != rend[bindex] )
          break ;
      }

      offset = 0 ;
      do {
        /* Set up the mapped value. */
        OCopy(mapsto, rd_mbyte[2]);
        switch ( oType(mapsto) ) {
        case OSTRING:
          HQASSERT(map_type == MAP_BF, "String mapping but not bf*") ;
          /* ToUnicode CMaps can have multiple Unicode character mappings for
             CIDs, longer than CMAP_MAX_CODESPACE_LEN. They will only map a
             single character to such a sequence, so we allow single
             mappings to use the string directly. */
          if ( eindex > bindex ) {
            uint32 dindex = 0, mindex = 0 ;

            HQASSERT(theLen(mapsto) <= CMAP_MAX_CODESPACE_LEN,
                     "String mapping too long") ;

            if ( dimensions < theLen(mapsto) ) {
              do {
                rmap[mindex] = oString(mapsto)[mindex] ;
                ++mindex ;
              } while ( dimensions + mindex < theLen(mapsto) ) ;
            } else if ( dimensions > theLen(mapsto) ) {
              do { /* Check that we're not stuffing too large a value */
                if ( rcurr[dindex] != rstart[dindex] )
                  return error_handler(RANGECHECK) ;
                ++dindex ;
              } while ( theLen(mapsto) + dindex < dimensions ) ;
            }

            /* Add offsets of current start to the base character code */
            while ( mindex < theLen(mapsto) ) {
              rmap[mindex] = (uint8)(oString(mapsto)[mindex] +
                                     rcurr[dindex] - rstart[dindex]);
              ++dindex, ++mindex ;
            }
            oString(mapsto) = rmap ;
          }
          break ;
        case OARRAY:
          HQASSERT(map_type == MAP_BF, "Array mapping but not bf*") ;
          HQASSERT(theLen(mapsto) >= offset + rlen,
                   "Array mapping does not cover range") ;
          theLen(mapsto) = CAST_TO_UINT16(rlen) ;
          oArray(mapsto) += offset ;
          break ;
        case ONAME:
          HQASSERT(map_type == MAP_BF, "Name mapping but not bf*") ;
          HQASSERT(rlen == 1, "Name mapping but not a single element") ;
          break ;
        case OINTEGER:
          HQASSERT(map_type == MAP_CID, "Integer mapping but not cid*") ;
          oInteger(mapsto) += offset ;
          break ;
        default:
          HQFAIL("Invalid mapping") ;
          break ;
        }

        if ( !(*iterator)(&mapsfrom, &mapsto, rlen, data) )
          return FALSE ;

        SwOftenUnsafe() ;

        /* We just dealt with the eindex dimension. Update the next dimension
           that is not done. */
        offset += rlen ;
        more = FALSE ;
        for ( bindex = eindex ; bindex-- > 0 ; ) {
          if ( rcurr[bindex] != rend[bindex] ) {
            rcurr[bindex]++ ;
            more = TRUE ;
            break ;
          } else
            rcurr[bindex] = rstart[bindex] ;
        }
      } while ( more ) ;
    }
  }

  return TRUE ;
}
Ejemplo n.º 17
0
Bool pdf_copyobject( PDFCONTEXT *pdfc , OBJECT *srcobj , OBJECT *destobj )
{
  int32 i ;
  int32 len ;
  uint8  *clist ;
  OBJECT *alist ;
  PDFXCONTEXT *pdfxc = NULL ;
  corecontext_t *corecontext ;

  if ( pdfc ) {
    PDF_CHECK_MC( pdfc ) ;
    PDF_GET_XC( pdfxc ) ;

    if ( ++( pdfxc->recursion_depth ) > PDF_MAX_RECURSION_DEPTH )
      return error_handler( LIMITCHECK ) ;

    corecontext = pdfxc->corecontext ;
  } else {
    corecontext = get_core_context() ;
  }

  HQASSERT( srcobj , "srcobj NULL in pdf_copyobject." ) ;
  HQASSERT( destobj , "destobj NULL in pdf_copyobject." ) ;
  HQASSERT( srcobj != destobj , "srcobj == destobj in pdf_copyobject." ) ;

  switch ( oXType(*srcobj) ) {
  case OINTEGER:
  case OREAL:
  case OBOOLEAN:
  case ONULL:
  case ONAME:
  case OINDIRECT:
  case OOPERATOR:
  case OFILEOFFSET:
    Copy( destobj , srcobj ) ;
    break ;
  case ODICTIONARY: {
    PDF_COPYOBJ_DWFPARAMS params ;
    len = theLen(*srcobj);

    if ( pdfxc ) {
      if ( ! pdf_create_dictionary( pdfc , len , destobj ))
        return FALSE ;
    }
    else {
      if ( ! ps_dictionary(destobj, len))
        return FALSE ;
    }

    params.pdfc = pdfc ;
    params.destdict = destobj ;

    if ( !walk_dictionary( srcobj ,
                           pdf_copyobj_dictwalkfn ,
                           ( void * )& params )) {
      if ( pdfxc ) {
        /* Use macro to avoid VC6sp5 compiler optimisation bug */
        PDF_DESTROY_DICTIONARY(pdfxc, len, destobj, corecontext);
      }

      /* Rely on restore, I s'pose */
      return FALSE ;
    }
    break ;
  }
  case OSTRING:
    Copy( destobj , srcobj ) ;
    len = theLen(*srcobj) ;
    clist = oString(*srcobj) ;
    if ( len ) {
      if ( pdfxc ) {
        if ( !pdf_create_string(pdfc, len, destobj) )
          return FALSE ;
        HqMemCpy(oString(*destobj) , clist , len ) ;
      } else {
        if ( !ps_string(destobj, clist, len) )
          return error_handler( VMERROR ) ;
      }
    }
    break ;
  case OARRAY:
  case OPACKEDARRAY:
    Copy( destobj , srcobj ) ;
    len = theLen(*srcobj) ;
    if ( len ) {
      OBJECT *destalist ;
      alist = oArray(*srcobj) ;
      if ( pdfxc ) {
        destalist = PDF_ALLOCOBJECT( pdfxc , len ) ;
      } else
        destalist = get_omemory( len ) ;
      if ( !destalist )
        return error_handler( VMERROR ) ;
      oArray(*destobj) = destalist ;
      if ( pdfxc == NULL )
        SETGLOBJECT(*destobj, corecontext) ;
      for ( i = len ; i > 0 ; --i, ++alist, ++destalist ) {
        if ( !pdf_copyobject( pdfc , alist , destalist )) {
          if ( pdfxc ) {
            PDF_FREEOBJECT( pdfxc, oArray(*destobj) , len ) ;
            Copy(destobj, &onull);
          }
          else {
            /* Rely on restore, I s'pose */
          }
          return FALSE ;
        }
      }
    }
    break ;
  case OLONGARRAY:
  case OLONGPACKEDARRAY:
    {
      OBJECT *destalist ;
      Copy( destobj , srcobj ) ;
      len = oLongArrayLen(*srcobj) ; /* always > 65535 */
      if ( pdfxc ) {
        destalist = PDF_ALLOCOBJECT( pdfxc , len + 2 ) ;
      } else
        destalist = get_omemory( len + 2 ) ;
      if ( !destalist )
        return error_handler( VMERROR ) ;

      alist = oArray(*srcobj) ;       /* The old trampoline */
      oArray(*destobj) = destalist ;  /* The new trampoline */
      Copy(destalist++, alist++) ;    /* Length */
      Copy(destalist, alist) ;        /* array ptr */

      oArray(*destalist) = destalist + 1 ;
      destalist += 1 ;
      alist = oArray(*alist) ;

      if ( pdfxc == NULL ) {
        SETGLOBJECT(*destobj, corecontext) ;
        SETGLOBJECT(*(destalist-2), corecontext) ;
        SETGLOBJECT(*(destalist-1), corecontext) ;
      }
      for ( i = len ; i > 0 ; --i, ++alist, ++destalist ) {
        if ( !pdf_copyobject( pdfc , alist , destalist )) {
          if ( pdfxc ) {
            PDF_FREEOBJECT( pdfxc, oArray(*destobj) , len + 2 ) ;
            Copy(destobj, &onull);
          }
          else {
            /* Rely on restore, I s'pose */
          }
          return FALSE ;
        }
      }
    }
    break ;
  case OFILE:
    {
      PDFXCONTEXT *streamxc ;

      /* Streams are different to other objects: we don't deep copy
         them but rather mark them as being used on this page. */

      if ( ! pdf_find_execution_context( theIPDFContextID( oFile( *srcobj )) ,
                                         pdfin_xcontext_base ,
                                         & streamxc )) {
        /* Note that if we ever revive pdfout, we'd have to check
           pdfout_xcontext_base here too. */
        HQFAIL( "Couldn't find stream execution context" ) ;
        return FALSE ;
      }
      HQASSERT( streamxc != NULL , "Null context" ) ;

      if ( ! pdf_xrefexplicitaccess_stream( streamxc , srcobj , FALSE )) {
        return FALSE ;
      }
      Copy( destobj , srcobj ) ;
    }
    break ;
  default:
    HQFAIL( "Trying to copy an unsupported/undefined pdf object type." ) ;
  }

  if ( pdfxc ) {
    pdfxc->recursion_depth -= 1 ;

    HQASSERT( pdfxc->recursion_depth >= 0 ,
              "Recursion depth went below zero!" ) ;
  }

  return TRUE ;
}
Ejemplo n.º 18
0
/* ----------------------------------------------------------------------------
   function:            cmap_notdeflookup_local()    author:       Eric Penfold
   creation date:       10-Jul-1997            last modification:   07-Aug-1997
   arguments:
     notdef  (Input)
     code    (Input)
     code length (Input)
     fontid  (Output)
     cid     (Output)
   description:

   Internal lookup function to obtain notdef character selector for input
   character code. If no notdef is defined for this code then the default of
   CID 0 is used (with default font 0).

   Returns FALSE on error. Sets fontid to -1 if no mapping could be performed.
---------------------------------------------------------------------------- */
static Bool cmap_notdeflookup_local(OBJECT *notdef, OBJECT *codestr,
                                    int32 *fontid, OBJECT *charsel)
{
  int32   num_block;
  int32   num_entry;
  int32   idx_block;
  int32   idx_entry;
  OBJECT *rd_block;
  OBJECT *rd_entry;
  uint8  *code ;

  HQASSERT(charsel, "No character selector parameter") ;
  HQASSERT(fontid, "No font number parameter") ;
  HQASSERT(codestr, "No character code string parameter") ;

  if ( notdef == NULL || theLen(*notdef) == 0 ) {
    /* Optional notdefrangeblock dict entry is empty */
    object_store_null(charsel) ;
    return TRUE;
  }

  code = oString(*codestr) ;

  /* For each mapping definition block */
  num_block = theLen(*notdef);
  for (idx_block = 0; idx_block < num_block; idx_block+=2) {
    rd_block = oArray(*notdef) + idx_block + 1;

    /* Extract fontid */
    *fontid = oInteger(rd_block[-1]);

    /* For each entry in that block */
    num_entry = theLen(*rd_block);
    for (idx_entry = 0; idx_entry < num_entry; idx_entry++) {
      OBJECT *rd_mbyte;
      int32   idx_byte;
      int32   len_entry;
      uint8  *rstart;
      uint8  *rend;
      uint8  *inbyte;

      rd_entry  = oArray(*rd_block) + idx_entry;
      rd_mbyte  = oArray(*rd_entry);
      HQASSERT( theLen(*rd_mbyte) == theLen(rd_mbyte[1]),
                "mapping range start/end are of different length" );
      len_entry = theLen(*rd_mbyte);

      /* If the range is of a different dimension to the code, then skip */
      if (len_entry != theLen(*codestr))
        continue;

      /* Extract range_start and range_end */
      rstart = oString(rd_mbyte[0]);
      rend   = oString(rd_mbyte[1]);
      inbyte = code;

      /* Process each byte of the range */
      for (idx_byte = 0; idx_byte < len_entry; idx_byte++) {
        if (*inbyte < *rstart)
          break; /* Below range start */
        if (*inbyte > *rend)
          break; /* Above range end */

        /* Next range start/end bytes */
        rstart++;
        rend++;
        inbyte++;
      }

      if (idx_byte == len_entry) { /* Stop after first match */
        OBJECT *base = rd_mbyte + 2;

        /* Process third parameter (notdef base character) */
        if ( oType(*base) == OINTEGER ) {
          object_store_integer(charsel, oInteger(*base)); /* Don't offset */
        } else
          return error_handler(TYPECHECK);
        return TRUE;
      }
    }
  }

  /* Didn't obtain a notdef mapping result */
  object_store_null(charsel) ;
  return TRUE;
}
Ejemplo n.º 19
0
/* ----------------------------------------------------------------------------
   function:            forall_()          author:              Andrew Cave
   creation date:       22-Oct-1987        last modification:   ##-###-####
   arguments:           none .
   description:

   See PostScript reference manual page 161.

---------------------------------------------------------------------------- */
Bool forall_(ps_context_t *pscontext)
{
  int32 which, number, type ;
  OBJECT *o1, *o2, *accessobj ;

  UNUSED_PARAM(ps_context_t *, pscontext) ;

  if ( theStackSize( operandstack ) < 1 )
    return error_handler( STACKUNDERFLOW ) ;

  o2 = theTop( operandstack ) ;
  switch ( oType(*o2) ) {
  case OARRAY :
  case OPACKEDARRAY :
    break ;
  default:
    return error_handler( TYPECHECK ) ;
  }
  number = 3 ;
  accessobj = o1 = stackindex(1, &operandstack) ;
  type = oXType(*o1) ;

  switch ( type ) {

  case ODICTIONARY :
    accessobj = oDict(*o1) ;
    oInteger(inewobj) = DICT_ALLOC_LEN(accessobj);
    if ( ! push( & inewobj , & executionstack ))
      return FALSE ;
    which = NAME_xdforall ;
    ++number ;
    break ;
  case OSTRING :
    which = NAME_xsforall ;
    break ;
  case OLONGSTRING :
    oInteger(inewobj) = 0 ;
    if ( ! push( & inewobj , & executionstack ))
      return FALSE ;
    which = NAME_xlsforall ;
    ++number ;
    break ;
  case OLONGARRAY :
  case OLONGPACKEDARRAY :
    /* The trampoline must be pushed too, as it is modified by xaforall */
    if ( ! push( oArray(*o1)   , & executionstack ) || /* length */
         ! push( oArray(*o1)+1 , & executionstack ))   /* subarray */
      return FALSE ;
    number+=2;
    /* drop through */
  case OARRAY :
  case OPACKEDARRAY :
    which = NAME_xaforall ;
    break ;
  default:
    return error_handler( TYPECHECK ) ;
  }
  if ( (!oCanRead(*accessobj) && !object_access_override(accessobj)) ||
       (!oCanExec(*o2) && !object_access_override(o2)) ) {
    while ( number-- > 3 )
      pop( & executionstack ) ;
    return error_handler( INVALIDACCESS ) ;
  }
  if ( ! push( o2 , & executionstack ))
    return FALSE ;
  if ( ! push( o1 , & executionstack ))
    return FALSE ;

  switch ( type ) {
    case OLONGARRAY:
    case OLONGPACKEDARRAY:
      /* point the pushed OEXTENDED at the pushed trampoline below it */
      o1 = theTop(executionstack) ;
      oArray(*o1) = stackindex( 3 , & executionstack ) ;
      break ;
  }

  if ( ! xsetup_operator( which , number ))
    return FALSE ;

  npop( 2 , & operandstack ) ;

  return TRUE ;
}
Ejemplo n.º 20
0
/* Free the given object. Safe for simple objects, just
 * does nothing. Be careful when building compound objects
 * that will be freed with this routine - don't doubly
 * reference a child compound object!
 */
void pdf_freeobject_from_xc( PDFXCONTEXT *pdfxc , OBJECT *pdfobj )
{
  int32 i ;
  int32 len ;
  uint8  *clist ;
  OBJECT *alist ;
  Bool freed = TRUE ;

  HQASSERT( pdfobj , "pdfobj NULL in pdf_freeobject." ) ;

  if ( ++( pdfxc->recursion_depth ) > PDF_MAX_RECURSION_DEPTH )
    return ;

  switch ( oXType(*pdfobj) ) {
  case OINTEGER:
  case OREAL:
  case OBOOLEAN:
  case ONULL:
  case ONAME:
  case OINDIRECT:
  case OOPERATOR:
  case OFILEOFFSET:
    /* Nothing to free */
    break ;
  case ODICTIONARY: {
    corecontext_t *context = pdfxc->corecontext;
    OBJECT *dict;
    DPAIR *dp;
    int32 alloc_len;

    /* Free each of the values in the dictionary plus the dictionary itself. */
    len = theLen(*pdfobj) ;
    dict = oDict(*pdfobj); alloc_len = DICT_ALLOC_LEN(dict);
    if ( alloc_len == 0 && oType(dict[-1]) == ODICTIONARY ) {
      /* There's an extension, free the initial array, at original length */
      OBJECT *subdict = oDict(dict[-1]);
      uint16 sublen = theLen(dict[-1]);

      HQASSERT(theLen(*dict) == 0, "Initial array not empty");
      PDF_FREEOBJECT( pdfxc, dict-2, NDICTOBJECTS(len) );
      dict = subdict; len = sublen; alloc_len = DICT_ALLOC_LEN(dict);
    }
    for ( i = alloc_len, dp = (DPAIR*)(dict + 1) ; i > 0 ; --i, ++dp )
      if ( theTags( dp->key ) != ONOTHING ) {
        (void)dictwalk_destroy_dictionary( &dp->key, &dp->obj, context );
        pdf_freeobject_from_xc( pdfxc, &dp->obj );
      }
    PDF_FREEOBJECT( pdfxc, dict-2, NDICTOBJECTS(len) );
    break ; }
  case OSTRING:
    /* Free the string data. */
    len = theLen(*pdfobj) ;
    clist = oString(*pdfobj) ;
    if ( len ) {
      PDF_FREESTRING( pdfxc, clist , len ) ;
    }
    break ;
  case OLONGARRAY:
  case OLONGPACKEDARRAY:
    /* Free the array members */
    len = oLongArrayLen(*pdfobj) ;
    alist = oLongArray(*pdfobj) ;
    for ( i = len ; i > 0 ; --i , ++alist )
      pdf_freeobject_from_xc( pdfxc , alist ) ;
    /* Free the array and trampoline (one allocation - see pdf_scanarray) */
    alist = oArray(*pdfobj) ;
    PDF_FREEOBJECT( pdfxc , alist , len + 2 ) ;
    break ;
  case OARRAY:
  case OPACKEDARRAY:
    /* Free each of the objects in the array plus the array itself. */
    len = theLen(*pdfobj) ;
    if ( len ) {
      alist = oArray(*pdfobj) ;
      for ( i = len ; i > 0 ; --i , ++alist )
        pdf_freeobject_from_xc( pdfxc , alist ) ;
      len = theLen(*pdfobj) ;
      alist = oArray(*pdfobj) ;
      PDF_FREEOBJECT( pdfxc, alist , len ) ;
    }
    break ;
  case OFILE:
    /* The stream is to be marked as released. Even if this was the
       last live pointer to the stream, the xref cache entry shouldn't
       be freed straight away but rather stream frees are deferred. */
    pdf_xref_release_stream( pdfxc , pdfobj ) ;
    freed = FALSE ;
    break ;
  default:
    HQFAIL( "Unknown pdf object type." ) ;
  }

  if ( freed ) {
    theTags(*pdfobj) = ONOTHING ;
  }

  pdfxc->recursion_depth -= 1 ;

  HQASSERT( pdfxc->recursion_depth >= 0 ,
            "Recursion depth went below zero!" ) ;
}
Ejemplo n.º 21
0
/*----------------------------------------------------------------------------*/
static Bool named_colors_common(GS_COLORinfo *colorInfo,
                                NAMECACHE *sepname,
                                EQUIVCOLOR equivs,
                                Bool *foundEquivs,
                                COLORSPACE_ID outputSpaceId,
                                int32 equivColorType)
{
  OBJECT colorSpaceObj = OBJECT_NOTVM_NOTHING;
  OBJECT separationSpace[4];
  OBJECT tintTransform[1];
  STACK_POSITIONS stackPositions;

  /* Create a Separation colorspace for sepname that can be invoked to get
   * equivalent cmyk values from invoking the color chain. We only want to know
   * about equivalents from the current named color database, so deliberately
   * set the tint transform to an illegal procedure that will cause an error
   * if an attempt were made to execute it in the event of sepname not being
   * found in the named color databases.
   * NB. This is a temporary color space that only exists for the duration of
   * this function. The color space MUST be restored in the client.
   */
  theTags(colorSpaceObj) = OARRAY | LITERAL | UNLIMITED;
  theLen(colorSpaceObj) = 4;
  oArray(colorSpaceObj) = separationSpace;

  object_store_name(object_slot_notvm(&separationSpace[0]), NAME_Separation, LITERAL);
  separationSpace[1] = onothing;         /* Struct copy to initialise slot properties */
  theTags(separationSpace[1]) = ONAME | LITERAL;
  oName(separationSpace[1]) = sepname;
  object_store_name(object_slot_notvm(&separationSpace[2]), NAME_DeviceGray, LITERAL);
  separationSpace[3] = onothing;         /* Struct copy to initialise slot properties */
  theTags(separationSpace[3]) = OARRAY | EXECUTABLE | EXECUTE_ONLY;
  theLen(separationSpace[3]) = 1;
  oArray(separationSpace[3]) = tintTransform;

  object_store_null(object_slot_notvm(&tintTransform[0]));  /* The illegal procedure */

  saveStackPositions(&stackPositions);

  /* Install as the current colorspace and invoke it. The colorspace will be
   * restored away by the client.
   * The color value required are the default solid for a Separation space.
   */
  if (!push(&colorSpaceObj, &operandstack) ||
      !gsc_setcolorspace(colorInfo, &operandstack, equivColorType))
    return FALSE;

  /* The color value required are the default solid for a Separation space. */
  if (!gsc_invokeChainTransform(colorInfo, equivColorType,
                                outputSpaceId, FALSE,
                                equivs)) {
    /* We didn't find sepname in these databases, so clear any error and roll the
     * stacks back to what they were.
     */
    error_clear();
    if ( !restoreStackPositions(&stackPositions, FALSE) )
      return error_handler(STACKUNDERFLOW) ;

    return TRUE ;
  }

  *foundEquivs = TRUE;
  return TRUE;
}
Ejemplo n.º 22
0
/* ----------------------------------------------------------------------------
   function:            execstack_()       author:              Andrew Cave
   creation date:       22-Oct-1987        last modification:   ##-###-####
   arguments:           none .
   description:

   See PostScript reference manual page 152.

---------------------------------------------------------------------------- */
Bool execstack_(ps_context_t *pscontext)
{
  register OBJECT *o1 ;
  int32 esize, realrun ;
  corecontext_t *corecontext = pscontext->corecontext ;

  if ( isEmpty( operandstack ))
    return error_handler( STACKUNDERFLOW ) ;

  o1 = theTop( operandstack ) ;
  switch ( oType(*o1) ) {
  case OARRAY :
  case OPACKEDARRAY :
    break ;
  default:
    return error_handler( TYPECHECK ) ;
  }
  if ( !oCanWrite(*o1) && !object_access_override(o1) )
    return error_handler( INVALIDACCESS ) ;

  esize = theStackSize( executionstack) ;
  if ( theLen(*o1) <= esize )
    return error_handler( RANGECHECK ) ;

  for ( realrun = 0 ; realrun <= 1 ; ++realrun ) {
    register OBJECT *olist = oArray(*o1) ;
    int32 glmode = oGlobalValue(*o1) ;
    int32 i, realcount = 0;          /* shuts lint up */
    Bool realtype = FALSE ;

    if ( realrun ) {
/* Check if saved. */
      if ( ! check_asave(olist, theLen(*o1), glmode, corecontext) )
        return FALSE ;
    }

/* Copy the elements of the execution stack into the array. */
    for ( i = 0, olist += esize ; i <= esize ; ++i, --olist ) {
      register OBJECT *theo = stackindex( i , & executionstack ) ;

      if ( realtype ) {

/* Check OBJECTS for illegal LOCAL --> GLOBAL */
        if ( glmode )
          if ( illegalLocalIntoGlobal(theo, corecontext) )
            return error_handler( INVALIDACCESS ) ;

        if ( realrun ) {
          Copy( olist , theo ) ;
        }
        ++realcount ;
        if ( realcount == 4 )
          realtype = FALSE ;
      }
      else {
        if ( realrun ) {
          theTags(*olist) = OOPERATOR | EXECUTABLE ;
          theLen(*olist) = 1 ;
        }
        switch ( oType(*theo) ) {
        case ONOTHING :
          if ( realrun ) {
            HQASSERT(theINameNumber(theIOpName(oOp(*theo))) >= 0 &&
                     theINameNumber(theIOpName(oOp(*theo))) < OPS_COUNTED ,
                     "execstack_ creating segv operator" ) ;
            oOp(*olist) = & system_ops[theINameNumber(theIOpName(oOp(*theo)))];
          }
          break ;
        case OMARK :
          if ( realrun )
            oOp(*olist) = & system_ops[NAME_stopped];
          break ;
        case ONULL :
          switch ( theLen(*theo)) {
          case ISINTERPRETEREXIT :
/* not the best of things to return, but what else? */
            if ( realrun )
              oOp(*olist) = & system_ops[NAME_exit];
            break;
          case ISPATHFORALL :
            realcount = 0 ;
            realtype = TRUE ;
            if ( realrun )
              oOp(*olist) = & system_ops[NAME_pathforall];
            break ;
          case ISPROCEDURE :
            /* No executed effect - flush is the only NOP I can think of */
            if ( realrun )
              oOp(*olist) = & system_ops[NAME_flush] ; /* or yield */
            break ;
          default:
            HQFAIL("Unknown ONULL variant found on execstack") ;
          }
          break ;
        default:
/* Check OBJECTS for illegal LOCAL --> GLOBAL */
          if ( glmode )
            if ( illegalLocalIntoGlobal(theo, corecontext) )
              return error_handler( INVALIDACCESS ) ;

          if ( realrun ) {
            Copy( olist , theo ) ;
          }
          break ;
        }
      }
    }
  }
/* Set up a new sub-array. */
  theLen(*o1) = CAST_SIGNED_TO_UINT16(esize + 1) ;
  return TRUE ;
}
Ejemplo n.º 23
0
/* ----------------------------------------------------------------------------
   function:            cmap_codeget()     author:              Eric Penfold
   creation date:       10-Jul-1997        last modification:   ##-###-####

   Extracts the cmap code from the 'show' string and writes into code string.
   If the input string 'str' can be matched to a defined codespace range,
   The number of matched bytes (length of code) is deducted from the len
   parameter, the str pointer is incremented by this number, and TRUE returned.

   TRUE is also returned if str is not within any defined codespace range
   (and the minimum length codespace will be consumed from the input str). In
   this case, the output string will have length zero.

   Bytes consumed from str as per PLRM3, p. 390
---------------------------------------------------------------------------- */
static Bool cmap_codeget(OBJECT *codespace, OBJECT *instr, OBJECT *codestr)
{
  int32 num_block;
  int32 num_entry;
  int32 idx_block;
  int32 idx_entry;
  OBJECT *rd_block;
  OBJECT *rd_entry;
  uint8 *str, *code ;

  int32 max_match = 0; /* max # bytes matched for defined codespace ranges */
  int32 min_csdim = CMAP_MAX_CODESPACE_LEN; /* shortest codespace (in bytes) */
  int32 i;

  HQASSERT(oType(*instr) == OSTRING, "Input string wrong type") ;
  HQASSERT(oType(*codestr) == OSTRING, "Output string wrong type") ;

  str = oString(*instr) ;
  code = oString(*codestr) ;
  HQASSERT(theLen(*codestr) >= CMAP_MAX_CODESPACE_LEN,
           "Not enough space in code string");

  HQASSERT(oType(*codespace) == OARRAY, "CMap codespace block is not an array") ;
  num_block = theLen(*codespace);
  if (num_block < 1)
    return error_handler( RANGECHECK );

  /* For each 'codespacerange definition block' */
  for (idx_block = 0; idx_block < num_block; idx_block++) {
    rd_block = oArray(*codespace) + idx_block;

    HQASSERT(oType(*rd_block) == OARRAY,
             "CMap codespace sub-block is not an array") ;
    num_entry = theLen(*rd_block);

    /* For each entry in that block */
    for (idx_entry = 0; idx_entry < num_entry; idx_entry++) {
      OBJECT *rd_mbyte;
      int32   len_entry;
      int32   idx_byte;
      uint8  *rstart;
      uint8  *rend;
      uint8  *inbyte;

      rd_entry  = oArray(*rd_block) + idx_entry;
      HQASSERT(oType(*rd_entry) == OARRAY,
               "CMap codespace entry pair is not an array") ;
      rd_mbyte  = oArray(*rd_entry);

      HQASSERT(oType(rd_mbyte[0]) == OSTRING && oType(rd_mbyte[1]) == OSTRING,
               "CMap codespace pair entry is not a string") ;
      HQASSERT(theLen(*rd_mbyte) == theLen(rd_mbyte[1]),
              "CMap codespace ranges of different lengths");
      HQASSERT(theLen(*rd_mbyte) <= CMAP_MAX_CODESPACE_LEN,
              "CMap range has more bytes than expected");

      len_entry = theLen(*rd_mbyte); /* == theLen(rd_mbyte[1]) [we hope!] */
      if (len_entry < min_csdim)
        min_csdim = len_entry;

      /* Extract range_start and range_end, and stream_start  */
      rstart = oString(rd_mbyte[0]);
      rend   = oString(rd_mbyte[1]);
      inbyte = str;

      /* Test each byte of input with corresp. bytes of range start/end */
      idx_byte = 0;
      do {
        if (idx_byte >= theLen(*instr))
          break; /* Too short */
        if (*inbyte < *rstart)
          break; /* Below range start */
        if (*inbyte > *rend)
          break; /* Above range end */

        /* All bytes of this entry were matched */
        if (++idx_byte == len_entry) {
          /* Copy matched bytes into output string 'code' */
          for (i = 0; i < len_entry; i++)
            code[i] = str[i];
          theLen(*codestr) = (uint16)len_entry;
          /* Consume bytes from str */
          theLen(*instr) = (uint16)(theLen(*instr) - len_entry);
          oString(*instr) += len_entry;
          return TRUE;
        }

        /* Next range start/end bytes */
        rstart++;
        rend++;
        inbyte++;
      } while (idx_byte <= len_entry);

      /* If any bytes matched, should consume # bytes of tested code range */
      if (idx_byte > 0)
        max_match = len_entry;
    }
  }

  /* If no bytes matched, then must consume # bytes of shortest cs range */
  if (max_match == 0)
    max_match = min_csdim;
  /* Don't consume more bytes than we have */
  if (max_match > theLen(*instr))
    max_match = theLen(*instr);

  theLen(*codestr) = 0 ;
  oString(*codestr) = NULL ;

  /* Consume bytes from str */
  theLen(*instr) = (uint16)(theLen(*instr) - max_match);
  oString(*instr) += max_match;

  return TRUE; /* But theLen(*codestr) == 0, so not valid */
}
Ejemplo n.º 24
0
/* ----------------------------------------------------------------------------
   function:            cmap_cidlookup_local()    author:          Eric Penfold
   creation date:       10-Jul-1997            last modification:   07-Aug-1997

   Internal lookup function to obtain character selector for input character
   code.

   On input, the charsel's string field must be of type OSTRING, with the
   clist ptr pointing to an area of memory which may be used to store the
   result of an basefont character code mapping (OSTRING mapping type - see
   below). The size of this memory (given by the 'len' field) must be at
   least CMAP_MAX_CODESPACE_LEN bytes.

   The fontid parameter will be updated with id of the font corresponding
   to the mapping

   The charsel object passed will be updated to reflect the mapping type:
      OINTEGER => mapped to a CID font CID
      OSTRING  => mapped to a basefont character code. This may refer to a
                  composite font (check font type using fontid) - in which
                  case this could be a multi-byte string.
      ONAME    => mapped to a glyph name
      ONULL    => no mapping

   Returns FALSE on error.
   ---------------------------------------------------------------------------- */
static Bool cmap_cidlookup_local(OBJECT *mapping, OBJECT *codestr,
                                 int32 *fontid, OBJECT *charsel)
{
  int32   num_block;
  int32   num_entry;
  int32   idx_block;
  int32   idx_entry;
  OBJECT *rd_block;
  OBJECT *rd_entry;
  uint8  *code ;

  HQASSERT(charsel && oType(*charsel) == OSTRING,
           "charsel parameter must be a string object");
  HQASSERT(codestr && oType(*codestr) == OSTRING,
           "codestr parameter must be a string object");

  code = oString(*codestr) ;

  HQASSERT(oType(*mapping) == OARRAY, "CMap mapping block is not an array") ;
  num_block = theLen(*mapping);
  if (num_block < 1)
    return error_handler(RANGECHECK);

  /* For each mapping definition block */
  for (idx_block = 0; idx_block < num_block; idx_block+=3) {
    int32 map_type;
    rd_block = oArray(*mapping) + idx_block + 2;

    /* Extract fontid and mapping type */
    HQASSERT(oType(rd_block[-2]) == OINTEGER,
             "CMap mapping fontid is not an integer") ;
    *fontid  = oInteger(rd_block[-2]);
    HQASSERT(oType(rd_block[-1]) == OINTEGER,
             "CMap mapping type is not an integer") ;
    map_type = oInteger(rd_block[-1]);
    HQASSERT(map_type == MAP_CID || map_type == MAP_BF,
             "Invalid CMap mapping type") ;

    /* For each entry in that block */
    HQASSERT(oType(*rd_block) == OARRAY,
             "CMap mapping sub-block is not an array") ;
    num_entry = theLen(*rd_block);
    for (idx_entry = 0; idx_entry < num_entry; idx_entry++) {
      OBJECT *rd_mbyte;
      int32   idx_byte;
      int32   len_entry;
      int32   offset_vector[CMAP_MAX_CODESPACE_LEN];
      uint8  *rstart;
      uint8  *rend;
      uint8  *inbyte;
      rd_entry  = oArray(*rd_block) + idx_entry;
      HQASSERT(oType(*rd_entry) == OARRAY,
               "CMap mapping block entry is not an array") ;
      rd_mbyte  = oArray(*rd_entry);
      HQASSERT(oType(rd_mbyte[0]) == OSTRING && oType(rd_mbyte[1]) == OSTRING,
               "CMap mapping range entry is not a string") ;
      HQASSERT( theLen(*rd_mbyte) == theLen(rd_mbyte[1]),
                "mapping range start/end are of different length" );
      len_entry = theLen(*rd_mbyte);

      /* If the range is of a different dimension to the code, then skip */
      if (len_entry != theLen(*codestr))
        continue;

      /* Extract range_start and range_end */
      rstart = oString(rd_mbyte[0]);
      rend   = oString(rd_mbyte[1]);
      inbyte = code;

      /* Process each byte of the range */
      for (idx_byte = 0; idx_byte < len_entry; idx_byte++) {
        if (*inbyte < *rstart)
          break; /* Below range start */
        if (*inbyte > *rend)
          break; /* Above range end */

        /* Build position vector for this mapping */
        *(offset_vector + idx_byte) = (*inbyte - *rstart);

        /* Next range start/end bytes */
        rstart++;
        rend++;
        inbyte++;
      }

      if (idx_byte == len_entry) { /* Stop after first match */
        int32 i, j;
        OBJECT *base = rd_mbyte + 2;

        /* Process third parameter, depending on mapping type */
        if ((map_type == MAP_BF) && oType(*base) == OSTRING) {
          /* character code */
          uint8 *baselist = oString(*base);
          int32 baselen = theLen(*base);

          /* Check that mem ptr passed in to store result */
          HQASSERT(oString(*charsel),
                   "char selector string clist field must be ptr to valid memory to store result");
          /* Check that string memory provided is large enough */
          if (baselen > theLen(*charsel)) {
            HQFAIL("Insufficient memory passed to store multi-byte string result");
            return error_handler(RANGECHECK);
          }
          theLen(*charsel) = (uint16)baselen;

          i = j = 0 ;

          if ( len_entry < baselen ) {
            do {
              oString(*charsel)[i] = baselist[i] ;
              ++i ;
            } while ( len_entry + i < baselen ) ;
          } else if ( len_entry > baselen ) {
            do { /* Check that we're not stuffing too large a value */
              if ( offset_vector[j] != 0 )
                return error_handler(RANGECHECK) ;
              ++j ;
            } while ( baselen + j < len_entry ) ;
          }

          /* Add our vector offset components to the base character code */
          while ( i < baselen ) {
            oString(*charsel)[i] = (uint8)(baselist[i] + offset_vector[j]);
            ++i, ++j ;
          }
        }
        else if ( map_type == MAP_BF && oType(*base) == ONAME ) {
          theTags(*charsel) = ONAME | LITERAL ;
          oName(*charsel) = oName(*base) ;
        }
        else {
          int32 res;
          /* This is the complex bit since mapping can be multibyte i.e
           * multidimensional.
           * Assuming: n bytes, In = input byte n
           *           Sn = Range start byte n, En = Range end byte n
           * Calculation is:
           *   1.  rvec = [I1-S1, I2-S2, ..., In-Sn]
           *   2.  rvec[i] *= Prod(j=i+1...n) (Ej-Sj+1)
           *   3.  result = offset + Sum(i=1...n) (rvec[i])
           *
           * Note that we use the offset_vector array from above which
           * contains a position vector from mapping start to our point
           * (i.e. =rvec of Calculation_Stage1)
           */
          /* 2 */
          rstart = oString(rd_mbyte[0]);
          rend   = oString(rd_mbyte[1]);
          for (i = 0; i < len_entry; i++) {
            for (j = i+1; j < len_entry; j++)
              *(offset_vector + i) *= *(rend + j) - *(rstart + j) + 1;
          }
          /* 3 */
          for (i = 0, res = 0; i < len_entry; i++)
            res += *(offset_vector + i);

          if (map_type == MAP_CID) { /* Offset by CID base */
            if ( oType(*base) == OINTEGER ) {
              object_store_integer(charsel, oInteger(*base) + res);
            } else
              return error_handler(TYPECHECK);
          } else if (map_type == MAP_BF) {
            if ( oType(*base) == OARRAY ) { /* => array of glyph names */
              theTags(*charsel) = ONAME | LITERAL ;
              oName(*charsel) = oName(oArray(*base)[res]);
            } else
              return error_handler(TYPECHECK);
          } else
            return error_handler(RANGECHECK);
        }
        return TRUE ;
      }
    }
  }

  /* No mapping made, but no error */
  object_store_null(charsel) ;
  return TRUE;
}
Ejemplo n.º 25
0
/* Validate the soft mask dictionary. The group dictionary is looked-up as part
of this validation - 'groupXObjDictionary', if not null, will be set to this
dictionary.
*/
static Bool validateSoftMaskDict(PDFCONTEXT* pdfc,
                                 OBJECT dictionary,
                                 OBJECT* groupXObjDictionary)
{
  Bool luminosity = FALSE;
  OBJECT* object;
  OBJECT groupXObj = OBJECT_NOTVM_NOTHING;
  OBJECT groupAttribs = OBJECT_NOTVM_NOTHING;
  int32 colorspaceDimension = 0;

  PDF_CHECK_MC(pdfc);
  HQASSERT(oType(dictionary) == ODICTIONARY,
           "validateSoftMaskDict - 'dictionary' is not a dictionary object");
  HQASSERT(groupXObjDictionary != NULL, "groupXObjDictionary is NULL");

  if (! pdf_dictmatch(pdfc, &dictionary, smaskDictmatch))
    return FAILURE(FALSE) ;

  /* Type must be 'Mask' if present */
  object = smaskDictmatch[smask_Type].result;
  if (object != NULL && oNameNumber(*object) != NAME_Mask)
    return error_handler(UNDEFINED) ;

  /* Subtype must be either 'Alpha' or 'Luminosity' */
  object = smaskDictmatch[smask_S].result;
  switch (oNameNumber(*object)) {
  case NAME_Luminosity:
    luminosity = TRUE;
    break;

  case NAME_Alpha:
    luminosity = FALSE;
    break;

  default:
    return error_handler(RANGECHECK) ;
  }

  /* Transparency group XObject - lookup and validate */
  if (! lookupGroup(pdfc, *smaskDictmatch[smask_G].result, &groupXObj,
                    &groupAttribs))
    return FAILURE(FALSE) ;

  *groupXObjDictionary = groupXObj;

  if (! pdf_validateGroupAttributes(pdfc, groupAttribs, luminosity,
                                    & colorspaceDimension))
    return FAILURE(FALSE) ;

  /* 'TR' (Transfer function) */
  if (smaskDictmatch[smask_TR].result != NULL) {
    /* Map the function. */
    if (! pdf_map_function(pdfc, smaskDictmatch[smask_TR].result))
      return FAILURE(FALSE) ;
  }

  /* Backdrop Color must be array of numbers with array length
     matching the dimension of the group color space */
  if (luminosity && smaskDictmatch[smask_BC].result != NULL) {
    int32 i;
    HQASSERT(colorspaceDimension >= 1 && colorspaceDimension <= 4,
             "dimension of a blend space expected to be 1 to 4");
    object = smaskDictmatch[smask_BC].result;
    if (theLen(*object) != colorspaceDimension)
      return error_handler(RANGECHECK) ;
    object = oArray(*object);
    for (i = 0; i < colorspaceDimension; ++i) {
      if (oType(object[i]) != OINTEGER && oType(object[i]) != OREAL)
        return error_handler(TYPECHECK) ;
    }
  }

  return pdf_resolvexrefs(pdfc, &dictionary);
}