/* ---------------------------------------------------------------------- */ Bool xsforall(ps_context_t *pscontext) { register OBJECT *theo ; UNUSED_PARAM(ps_context_t *, pscontext) ; theo = stackindex( 1 , & executionstack ) ; if ( ! theLen(*theo)) { npop( 3 , & executionstack ) ; return TRUE ; } if ( ! stack_push_integer(( int32 )*oString(*theo), &operandstack) ) return FALSE ; if ( --theLen(*theo) == 0 ) oString(*theo) = NULL ; else ++oString(*theo) ; theo = stackindex( 2 , & executionstack ) ; if ( oExecutable(*theo) ) return push( theo , & executionstack ) ; else return push( theo , & operandstack ) ; }
Bool xml_map_namespace(const xmlGIStr *from_uri, const xmlGIStr **to_uri) { XMLExecContext *p_xmlexec_context; OBJECT *theo ; HQASSERT(from_uri != NULL, "from_uri is NULL") ; HQASSERT(to_uri != NULL, "to_uri is NULL") ; p_xmlexec_context = SLL_GET_HEAD(&xml_context.sls_contexts, XMLExecContext, sll); HQASSERT(p_xmlexec_context != NULL, "p_xmlexec_context is NULL") ; oName(nnewobj) = (NAMECACHE *)&(from_uri->name) ; if ( (theo = p_xmlexec_context->map_uri_data) == NULL || (theo = extract_hash(theo, &nnewobj)) == NULL ) { *to_uri = from_uri ; /* No mapping possible or present. */ return TRUE ; } switch ( oType(*theo) ) { case ONAME: *to_uri = (xmlGIStr *)oName(*theo) ; return TRUE ; case OSTRING: if ( intern_create(to_uri, oString(*theo), theLen(*theo)) ) return TRUE ; /*@fallthrough@*/ default: break ; } return error_handler(UNDEFINED) ; }
Bool pdf_create_string( PDFCONTEXT *pdfc , int32 len , OBJECT *thestring ) { uint8 *string ; PDFXCONTEXT *pdfxc ; PDF_CHECK_MC( pdfc ) ; PDF_GET_XC( pdfxc ) ; HQASSERT( thestring , "thestring NULL in pdf_create_string." ) ; if ( len < 0 ) return error_handler( RANGECHECK ) ; if ( len > MAXPSSTRING ) return error_handler( LIMITCHECK ) ; if ( len > 0 ) { string = PDF_ALLOCSTRING( pdfxc, len ) ; if ( ! string ) return error_handler( VMERROR ) ; } else string = NULL ; theTags(*thestring) = OSTRING | UNLIMITED | LITERAL ; SETGLOBJECTTO(*thestring, FALSE) ; /* string itself is local */ theLen(*thestring) = ( uint16 )len ; oString(*thestring) = string ; return TRUE ; }
/** * \brief Open a config file with appriopiate flags. * * \param[in] pt * XPS PrintTicket handler * \param[in] file_type * Type of config file, either \c "S" or \c "E". * \param[in] open_flags * Flags to open file on device with. * \param[in] ps_flags * PS opten flags (should be equivalent of \c open_flags) * \param[out] ofile * Pointer to returned PS file object. * * \returns * \c TRUE if opened the config file, else \c FALSE. */ static Bool pt_open_config_file( /*@in@*/ /*@notnull@*/ XPS_PT* pt, /*@in@*/ /*@notnull@*/ uint8* file_type, int32 open_flags, int32 ps_flags, /*@out@*/ /*@notnull@*/ OBJECT* ofile) { uint8 pt_filename[LONGESTDEVICENAME + 16]; static uint8* pt_scope[] = { NULL, (uint8*)"J", (uint8*)"D", (uint8*)"P" }; HQASSERT((pt != NULL), "pt_open_config_file: state pointer NULL"); HQASSERT((file_type != NULL), "pt_open_config_file: file type NULL"); HQASSERT((ofile != NULL), "pt_open_config_file: pointer to returned OBJECT NULL"); /* Create PT device filename based on scope and start/end type */ swcopyf(pt_filename, (uint8*)"%%%s%%%s%s", theIDevName(pt->device), pt_scope[pt->scope], file_type); oString(snewobj) = pt_filename; theLen(snewobj) = CAST_UNSIGNED_TO_UINT16(strlen((char*)pt_filename)); return file_open(&snewobj, open_flags, ps_flags, FALSE, 0, ofile) ; } /* pt_open_config_file */
Bool open_file_from_psdev_uri( hqn_uri_t *uri, OBJECT *ofile, Bool implicit_close_file) { uint8 *ps_filename; uint32 ps_filename_len ; OBJECT ostr_filename ; Bool status ; HQASSERT(uri != NULL, "uri is NULL") ; if (! psdev_uri_to_ps_filename(uri, &ps_filename, &ps_filename_len)) return FALSE ; if (ps_filename_len > LONGESTFILENAME) { mm_free_with_header(mm_xml_pool, ps_filename) ; return error_handler(LIMITCHECK) ; } theTags(ostr_filename) = OSTRING|UNLIMITED|LITERAL ; theLen(ostr_filename) = CAST_TO_UINT16(ps_filename_len) ; oString(ostr_filename) = ps_filename ; if (implicit_close_file) { status = file_open(&ostr_filename, SW_RDONLY, READ_FLAG, FALSE, 0, ofile) ; } else { status = xml_file_open(&ostr_filename, ofile) ; } mm_free_with_header(mm_xml_pool, ps_filename) ; return status ; }
/* Do a file stat for a psdev uri. */ Bool stat_from_psdev_uri( /*@in@*/ /*@notnull@*/ hqn_uri_t* uri, /*@out@*/ /*@notnull@*/ Bool* exists, /*@out@*/ /*@notnull@*/ STAT* stat) { uint8 *ps_filename; uint32 ps_filename_len ; int32 status; /* Create PS filename from URI */ if ( !psdev_uri_to_ps_filename(uri, &ps_filename, &ps_filename_len) ) { return(FALSE); } /* Stat the PS filename */ oString(snewobj) = ps_filename; theLen(snewobj) = CAST_TO_UINT16(ps_filename_len); status = file_stat(&snewobj, exists, stat); /* Must free memory used for ps filename */ mm_free_with_header(mm_xml_pool, ps_filename); return(status); } /* stat_from_psdev_uri */
/*----------------------------------------------------------------------------*/ 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; } } }
/* ---------------------------------------------------------------------------- function: cmap_lookup() author: Eric Penfold creation date: 10-Jul-1997 last modification: ##-###-#### arguments: lots description: Top level Lookup function to return char id/cid for input data On input, the charsel object 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. This can happen if the input str does not start with a valid character code (i.e. within any of the defined codespace ranges). stringo should a pointer to the string to parse -> this pointer will be incremented by the number of bytes which were used for the cmap lookup, and the len parameter will be decremented by this number. Characters may still be consumed if no matching or valid mapping exists. Returns FALSE on error. ---------------------------------------------------------------------------- */ Bool cmap_lookup(OBJECT *cmapdict, OBJECT *stringo, int32 *fontid, OBJECT *charsel) { OBJECT mapstring = OBJECT_NOTVM_NOTHING, *cmap; uint8 mapcode[CMAP_MAX_CODESPACE_LEN]; static NAMETYPEMATCH codemapmatch[] = { /* Use the enum below to index this match */ { NAME_codespacerangeblock, 1, { OARRAY }}, { NAME_mappingblock, 1, { OARRAY }}, { NAME_notdefrangeblock | OOPTIONAL, 1, { OARRAY }}, DUMMY_END_MATCH } ; enum { codemapmatch_codespacerangeblock, codemapmatch_mappingblock, codemapmatch_notdefrangeblock } ; if ( oType(*cmapdict) != ODICTIONARY ) return error_handler(TYPECHECK) ; cmap = fast_extract_hash_name(cmapdict, NAME_CodeMap); if ( !cmap ) return error_handler(TYPECHECK); if (!dictmatch(cmap, codemapmatch)) return FALSE; theTags(mapstring) = OSTRING | LITERAL | UNLIMITED ; theLen(mapstring) = CMAP_MAX_CODESPACE_LEN ; oString(mapstring) = mapcode ; if (!cmap_codeget(codemapmatch[codemapmatch_codespacerangeblock].result, stringo, &mapstring)) return FALSE; if ( theLen(mapstring) == 0 ) { /* Invalid char string */ object_store_null(charsel) ; return TRUE ; } if ( !cmap_cidlookup_local(codemapmatch[codemapmatch_mappingblock].result, &mapstring, fontid, charsel) ) return FALSE ; if ( oType(*charsel) != ONULL ) /* Found a character mapping */ return TRUE ; theTags(*charsel) = OINTEGER | LITERAL; /* Notdef mapping must be CID */ return cmap_notdeflookup_local(codemapmatch[codemapmatch_notdefrangeblock].result, &mapstring, fontid, charsel); }
/* If a character is on disk, pull it into the CID data cache. */ static Bool cid0_begin_char(FONTinfo *fontInfo, charcontext_t *context) { CID0_CACHE *cid_font ; HQASSERT(fontInfo, "No font info") ; HQASSERT(context, "No character context") ; HQASSERT(theIFontType(fontInfo) == CIDFONTTYPE0, "Not in a CID Type 0") ; HQASSERT(context->chartype == CHAR_Type1 || context->chartype == CHAR_Type2, "Not a Type 1/2 charstring") ; if ( (cid_font = cid0_set_font(fontInfo)) == NULL ) return FALSE ; VERIFY_OBJECT(cid_font, CID0_CACHE_NAME) ; if ( (cid_font->font_data = fontdata_open(cid_font->source, cid_font->fdmethods)) == NULL ) return FALSE ; if ( oType(context->definition) == ONULL ) { /* cid0_lookup_char creates a special ONULL object containing an integer offset and a length. This is now converted into a string by opening a fontdata frame. */ if ( (oString(context->definition) = fontdata_frame(cid_font->font_data, cid_font->offset + oInteger(context->definition), theLen(context->definition), sizeof(uint8))) == NULL ) { fontdata_close(&cid_font->font_data) ; return FALSE ; } theTags(context->definition) = OSTRING | LITERAL | READ_ONLY ; } HQASSERT(oType(context->definition) == OSTRING, "Definition of CID character is wrong type") ; context->methods = &cid_font->cid0methods ; /* cid0_get_info is based on ps1_get_info, which uses the fontInfo to extract information. Save the current font info between begin_char and end_char; this means we cannot call CID0 fonts recursively. */ HQASSERT(cid_font->fontInfo == NULL, "Should not call CID0 recursively.") ; cid_font->fontInfo = fontInfo ; return TRUE ; }
static void current_jobname(corejob_t *job) { OBJECT* statusdict; OBJECT* jobname; /* Extract jobname from statusdict for now */ statusdict = fast_extract_hash_name(&systemdict, NAME_statusdict); jobname = fast_extract_hash_name(statusdict, NAME_jobname); if (oType(*jobname) == OSTRING && theLen(*jobname) > 0 ) { corejob_name(job, oString(*jobname), theLen(*jobname)); } else { corejob_name(job, NAME_AND_LENGTH("UnSpecified JobName")); } }
/** Preserve the blob data if possible by storing the filename in a global string. */ static OBJECT *blobdata_file_restored(const OBJECT *file, blobdata_private_t *data, int32 savelevel) { DEVICELIST *dev ; FILELIST *flptr ; UNUSED_PARAM(blobdata_private_t *, data) ; HQASSERT(file, "No blob data source") ; VERIFY_OBJECT(data, BLOBDATA_PRIVATE_NAME) ; if ( NUMBERSAVES(savelevel) > MAXGLOBALSAVELEVEL && oType(*file) == OFILE && (flptr = oFile(*file)) != NULL && (dev = theIDeviceList(flptr)) != NULL ) { int32 devlen = strlen_int32((char *)theIDevName(dev)) ; int32 length = devlen + theINLen(flptr) + 2 ; OBJECT *string ; /* We're in a local save levels. We can re-use the file if it is a real device file. Store the full filename (including device name) in global memory. */ if ( (string = get_gomemory(1)) != NULL ) { uint8 *smem ; if ( (smem = get_gsmemory(length)) != NULL ) { smem[0] = '%' ; HqMemCpy(smem + 1, theIDevName(dev), devlen) ; smem[devlen + 1] = '%' ; if ( theINLen(flptr) ) HqMemCpy(smem + devlen + 2, theICList(flptr), theINLen(flptr)) ; oString(*string) = smem ; theTags(*string) = OSTRING | LITERAL | READ_ONLY ; theLen(*string) = CAST_UNSIGNED_TO_UINT16(length); SETGLOBJECTTO(*string, TRUE) ; return string ; } /* Got object memory, but no string memory. Forget the global object, it will get restored soon enough. */ theTags(*string) = ONULL ; } } /* Forget about it, we can't save the data any more */ return NULL ; }
Bool pdf_buildstring( PDFCONTEXT *pdfc , uint8 *string , OBJECT *theo ) { int32 len ; HQASSERT( string , "string NULL in pdf_buildstring." ) ; HQASSERT( theo , "theo NULL in pdf_buildstring." ) ; len = strlen_int32( ( char * )string ) ; if ( ! pdf_create_string( pdfc , len , theo )) return FALSE ; HqMemCpy(oString(*theo) , string , len ) ; return TRUE ; }
static Bool runOPI(Bool *rendered) { /* try to ensure that operand stack does not accumulate junk, whether opi * is run or not. Stack clean up in error case is in Postscript, as we * cannot be 100% sure of state stack is in, when error occurs. */ char *runOPI = "mark exch /HqnOPI /ProcSet resourcestatus {\n" " pop pop\n" " <<>> /HqnOPI /ProcSet findresource /HqnOPIimage get exec\n" " { cleartomark true } { cleartomark false } ifelse " "} {\n" " cleartomark false\n" "} ifelse"; OBJECT obj = OBJECT_NOTVM_NOTHING ; theTags( obj ) = OSTRING | EXECUTABLE | READ_ONLY ; theLen ( obj ) = strlen_uint16( runOPI ) ; oString( obj ) = ( uint8 * )runOPI ; execStackSizeNotChanged = FALSE ; *rendered = FALSE ; if ( push( & obj , & executionstack )) { if ( interpreter( 1 , NULL )) { if ( theStackSize( operandstack ) > EMPTY_STACK ) { OBJECT *theo = theTop( operandstack ) ; if ( oType( *theo ) != OBOOLEAN ) return error_handler( TYPECHECK ) ; *rendered = oBool( *theo ) ; pop( & operandstack ) ; } else return error_handler( STACKUNDERFLOW ) ; } else return FALSE; } return TRUE ; }
/** Match the same underlying file, and device files with the same name. */ static Bool blobdata_file_same(const OBJECT *newo, const OBJECT *cached) { FILELIST *newflptr ; HQASSERT(newo && cached, "Objects missing for file comparison") ; HQASSERT(oType(*newo) == OFILE, "Blob data source is not a file") ; HQASSERT(oType(*cached) == OFILE || oType(*cached) == OSTRING, "Blob data source is not a file or a filename") ; newflptr = oFile(*newo) ; HQASSERT(newflptr, "No filelist in file object") ; /* Object identity has already been checked. The file is the same if: 1) The file pointers are the same 2) The file names and devices of the files are the same 3) The file name and device of the new file match a filename */ if ( oType(*cached) == OFILE ) { FILELIST *oldflptr = oFile(*cached) ; if ( oldflptr == newflptr ) return TRUE ; if ( theIDeviceList(oldflptr) != NULL && theIDeviceList(oldflptr) == theIDeviceList(newflptr) && HqMemCmp(theICList(oldflptr), theINLen(oldflptr), theICList(newflptr), theINLen(newflptr)) == 0 ) return TRUE ; } else if ( oType(*cached) == OSTRING ) { if ( theIDeviceList(newflptr) != NULL ) { uint8 *filename, *devicename ; /* file_open stores the filename in a FILELIST as a C-string (zero terminated), so we can use strcmp to compare it. */ if ( parse_filename(oString(*cached), theLen(*cached), &devicename, &filename) == DEVICEANDFILE && strcmp((const char *)theIDevName(theIDeviceList(newflptr)), (const char *)devicename) == 0 && strcmp((const char *)theICList(newflptr), (const char *)filename) == 0 ) return TRUE ; } } return FALSE ; }
static Bool obFontDecodeBuffer(FILELIST *filter, int32 *ret_bytes) { uint8 *ptr,*obs; FILELIST *uflptr; int32 count, c, i; HQASSERT(filter, "filter NULL in obFontDecodeBuffer."); uflptr = theIUnderFile(filter); obs = ptr = theIBuffer(filter); HQASSERT(uflptr, "uflptr NULL in obFontDecodeBuffer."); HQASSERT(ptr, "ptr NULL in obFontDecodeBuffer."); count = 0; for (i=0; i < OBFONTBUFFSIZE; i++) { if ( (c=Getc(uflptr)) == EOF ) { count=-count; break; } else { *ptr++ = (uint8) c; count++; } } if ( count && theIFilterPrivate(filter) ) { /* first fill of the buffer, so deobfuscate the first 32 bytes */ int32 i,j=0; uint8 * string = oString(*(OBJECT*)theIFilterPrivate(filter)); int32 ext = theLen(*(OBJECT*)theIFilterPrivate(filter)) ; while ( ext > 0 && string[--ext] != '.' ) EMPTY_STATEMENT() ; for ( i = 0; i < 32; ++i ) { uint8 l; if ( i % 16 == 0 ) j=ext; l = get_prev_hex_digit(string, &j); obs[i] ^= ( get_prev_hex_digit(string, &j)<<4 | l); } theIFilterPrivate(filter) = 0; } *ret_bytes = count; return TRUE; }
void pdf_destroy_string( PDFCONTEXT *pdfc , int32 len , OBJECT *thestring ) { PDF_CHECK_MC( pdfc ) ; HQASSERT( len >=0 , "len must be positive" ) ; HQASSERT( thestring != NULL , "thestring NULL in pdf_destroy_string" ) ; HQASSERT( oType(*thestring) == OSTRING , "Non-string passed into pdf_destroy_string" ) ; if ( len != 0 ) { PDFXCONTEXT *pdfxc ; uint8 *string ; PDF_GET_XC( pdfxc ) ; string = oString(*thestring) ; HQASSERT( string != NULL , "string NULL in pdf_destroy_string." ) ; PDF_FREESTRING( pdfxc, string , len ) ; } theTags(*thestring) = ONOTHING ; }
/* Send FixedPage media information to the PT device. */ Bool pt_page_details( /*@in@*/ /*@notnull@*/ XPS_PT* pt, double width, double height, /*@in@*/ /*@notnull@*/ RECTANGLE* bleedbox, /*@in@*/ /*@notnull@*/ RECTANGLE* contentbox) { Bool success; OBJECT dev_file = OBJECT_NOTVM_NOTHING; uint8 pt_filename[LONGESTDEVICENAME + 16]; uint8 buffer[16384]; HQASSERT((pt != NULL), "pt_config_end: pt pointer NULL"); HQASSERT((bleedbox != NULL), "pt_config_end: bleedbox pointer NULL"); HQASSERT((contentbox != NULL), "pt_config_end: contentbox pointer NULL"); HQASSERT((pt->scope == PT_SCOPE_PAGE), "pt_config_end: sending media details at wrong scope level"); /* Catch absence of any PT device */ if ( pt->device == NULL ) { /* Cache the page size for minimal page config PS */ pt->width = width; pt->height = height; return TRUE ; } /* Create XML of fixedpage details */ swcopyf(buffer, (uint8*)"<?xml version=\"1.0\" encoding=\"utf-8\"?>" "<PageDetails xmlns=\"http://schemas.globalgraphics.com/xps/2005/03/pagedetails\">" " <Page Size=\"%f,%f\" BleedBox=\"%f,%f,%f,%f\" ContentBox=\"%f,%f,%f,%f\"/>" "</PageDetails>", width, height, bleedbox->x, bleedbox->y, bleedbox->w, bleedbox->h, contentbox->x, contentbox->y, contentbox->w, contentbox->h); /* Generate name of fixedpage details file on PT device */ swcopyf(pt_filename, (uint8*)"%%%s%%PD", theIDevName(pt->device)); oString(snewobj) = pt_filename; theLen(snewobj) = CAST_UNSIGNED_TO_UINT16(strlen((char*)pt_filename)); if ( !file_open(&snewobj, SW_WRONLY, WRITE_FLAG, FALSE, 0, &dev_file) ) { return FALSE ; } /* Copy XML in buffer to PT device */ success = file_write(oFile(dev_file), buffer, strlen_int32((char*)buffer)); success = file_close(&dev_file) && success; if ( !success ) { /* The XML error handler needs a file name, but there is no externally * visible file for the page details XML. So the following is a made up * name to uniquely locate the source of the XML that caused the error. */ #define PAGE_DETAILS_NAME "Internal:PageDetails.xml" (void)pt_error_handler(pt, STRING_AND_LENGTH(PAGE_DETAILS_NAME)); } return success ; } /* pt_page_details */
/* 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 ; }
/* 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 ; }
/** Lazily open the file the first time we need to check availability of a buffer. */ static Bool blobdata_file_lazy(const OBJECT *file, blobdata_private_t *data) { uint8 *filename ; DEVICELIST *dev ; DEVICE_FILEDESCRIPTOR fhandle ; HQASSERT(file, "No blob data source") ; HQASSERT(oType(*file) == OFILE || oType(*file) == OSTRING, "Blob data source is not a file or a filename") ; VERIFY_OBJECT(data, BLOBDATA_PRIVATE_NAME) ; HQASSERT(!data->isopen && data->dev == NULL && data->fhandle < 0, "Blob data file has been opened already") ; /* If the data source is an open filter, there is nothing to do. If it is a closed device file, re-open it. We'll use the device interface for all device files so that we can test if they are encrypted. */ if ( oType(*file) == OFILE ) { FILELIST *flptr = oFile(*file) ; HQASSERT(flptr, "No filelist in file object") ; /* If the file is closed, but is not a real device file, we can't use it */ if ( (dev = theIDeviceList(flptr)) == NULL ) { /* If the file is open, mark it so. Open file/filter uses file operators. */ if ( isIOpenFileFilter(file, flptr) ) { if ( (data->mode & (SW_RDONLY|SW_RDWR)) != 0 && !isIInputFile(flptr) ) return error_handler(INVALIDACCESS) ; if ( (data->mode & (SW_WRONLY|SW_RDWR)) != 0 && !isIOutputFile(flptr) ) return error_handler(INVALIDACCESS) ; data->isopen = TRUE ; return TRUE ; } return error_handler(UNDEFINEDFILENAME) ; } filename = theICList(flptr) ; } else if ( oType(*file) == OSTRING ) { uint8 *devicename ; if ( parse_filename(oString(*file), theLen(*file), &devicename, &filename) != DEVICEANDFILE ) return error_handler(UNDEFINEDFILENAME) ; /* Fully specified name */ if ( NULL == (dev = find_device(devicename)) ) return error_handler(UNDEFINEDFILENAME) ; } else return error_handler(TYPECHECK) ; /* The device on which the file resides must be enabled and must be able to accept filenames. */ if ( ! isDeviceEnabled(dev) || !isDeviceRelative(dev) ) return error_handler(UNDEFINEDFILENAME) ; if ( (fhandle = (*theIOpenFile(dev))(dev, filename, data->mode)) < 0 ) return device_error_handler(dev); /* Check hqxcrypt status every time the blob is opened. This is required to setup the hqxcrypt tables. Do this now, while the pointer is still at zero. This reads data from the start of the file. Note that the name hqxfont_test is a bit of a misnomer, this is the same test used for other HQX-encrypted files. */ if ( hqxfont_test(fhandle, dev) ) { data->encrypted = FALSE; data->hqxoffset = 0 ; data->hqxtail = 0 ; } else { /* it is a hqx encrypted blob */ data->encrypted = TRUE; data->hqxoffset = hqxdatastart ; /* Initialisation vector */ data->hqxtail = hqxdataextra ; } data->dev = dev ; data->fhandle = fhandle ; data->isopen = TRUE ; return TRUE ; }
/* ---------------------------------------------------------------------------- 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; }
/* ---------------------------------------------------------------------------- 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; }
/* 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!" ) ; }
OGRErr BAGDataset::ParseWKTFromXML( const char *pszISOXML ) { OGRSpatialReference oSRS; CPLXMLNode *psRoot = CPLParseXMLString( pszISOXML ); OGRErr eOGRErr = OGRERR_FAILURE; if( psRoot == NULL ) return eOGRErr; CPLStripXMLNamespace( psRoot, NULL, TRUE ); CPLXMLNode *psRSI = CPLSearchXMLNode( psRoot, "=referenceSystemInfo" ); if( psRSI == NULL ) { CPLError( CE_Failure, CPLE_AppDefined, "Unable to find <referenceSystemInfo> in metadata." ); CPLDestroyXMLNode( psRoot ); return eOGRErr; } oSRS.Clear(); const char *pszSRCodeString = CPLGetXMLValue( psRSI, "MD_ReferenceSystem.referenceSystemIdentifier.RS_Identifier.code.CharacterString", NULL ); if( pszSRCodeString == NULL ) { CPLDebug("BAG", "Unable to find /MI_Metadata/referenceSystemInfo[1]/MD_ReferenceSystem[1]/referenceSystemIdentifier[1]/RS_Identifier[1]/code[1]/CharacterString[1] in metadata." ); CPLDestroyXMLNode( psRoot ); return eOGRErr; } const char *pszSRCodeSpace = CPLGetXMLValue( psRSI, "MD_ReferenceSystem.referenceSystemIdentifier.RS_Identifier.codeSpace.CharacterString", "" ); if( !EQUAL( pszSRCodeSpace, "WKT" ) ) { CPLError( CE_Failure, CPLE_AppDefined, "Spatial reference string is not in WKT." ); CPLDestroyXMLNode( psRoot ); return eOGRErr; } char* pszWKT = const_cast< char* >( pszSRCodeString ); if( oSRS.importFromWkt( &pszWKT ) != OGRERR_NONE ) { CPLError( CE_Failure, CPLE_AppDefined, "Failed parsing WKT string \"%s\".", pszSRCodeString ); CPLDestroyXMLNode( psRoot ); return eOGRErr; } oSRS.exportToWkt( &pszProjection ); eOGRErr = OGRERR_NONE; psRSI = CPLSearchXMLNode( psRSI->psNext, "=referenceSystemInfo" ); if( psRSI == NULL ) { CPLError( CE_Failure, CPLE_AppDefined, "Unable to find second instance of <referenceSystemInfo> in metadata." ); CPLDestroyXMLNode( psRoot ); return eOGRErr; } pszSRCodeString = CPLGetXMLValue( psRSI, "MD_ReferenceSystem.referenceSystemIdentifier.RS_Identifier.code.CharacterString", NULL ); if( pszSRCodeString == NULL ) { CPLError( CE_Failure, CPLE_AppDefined, "Unable to find /MI_Metadata/referenceSystemInfo[2]/MD_ReferenceSystem[1]/referenceSystemIdentifier[1]/RS_Identifier[1]/code[1]/CharacterString[1] in metadata." ); CPLDestroyXMLNode( psRoot ); return eOGRErr; } pszSRCodeSpace = CPLGetXMLValue( psRSI, "MD_ReferenceSystem.referenceSystemIdentifier.RS_Identifier.codeSpace.CharacterString", "" ); if( !EQUAL( pszSRCodeSpace, "WKT" ) ) { CPLError( CE_Failure, CPLE_AppDefined, "Spatial reference string is not in WKT." ); CPLDestroyXMLNode( psRoot ); return eOGRErr; } if( EQUALN(pszSRCodeString, "VERTCS", 6 ) ) { CPLString oString( pszProjection ); oString += ","; oString += pszSRCodeString; if ( pszProjection ) CPLFree( pszProjection ); pszProjection = CPLStrdup( oString ); } CPLDestroyXMLNode( psRoot ); return eOGRErr; }
/* ---------------------------------------------------------------------------- function: search_() author: Andrew Cave creation date: 09-Oct-1987 last modification: ##-###-#### arguments: none. description: See PostScript reference manual page 211. ---------------------------------------------------------------------------- */ Bool search_(ps_context_t *pscontext) { int32 postsize , matchsize , presize ; OBJECT *o1 , *o2 ; uint8 *str ; uint8 tags1 , tags2 ; uint8 *seek ; int32 stringsize ; OBJECT newobject = OBJECT_NOTVM_NOTHING ; UNUSED_PARAM(ps_context_t *, pscontext) ; if ( theStackSize( operandstack ) < 1 ) return error_handler( STACKUNDERFLOW ) ; /* Check types. */ o1 = stackindex( 1 , & operandstack ) ; o2 = theTop( operandstack ) ; tags1 = theTags(*o1) ; tags2 = theTags(*o2) ; if ( oType(*o1) != OSTRING || oType(*o2) != OSTRING ) return error_handler( TYPECHECK ) ; /* Check access requirements. */ if ( (!oCanRead(*o1) && !object_access_override(o1)) || (!oCanRead(*o2) && !object_access_override(o2)) ) return error_handler( INVALIDACCESS ) ; /* Extract the location of seek & string, and their lengths. */ seek = oString(*o2) ; str = oString(*o1) ; matchsize = theLen(*o2) ; stringsize = theLen(*o1) ; /* Remove the trivial cases. */ if ( stringsize == 0 ) { Copy(o2, &fnewobj) ; return TRUE ; } if ( matchsize == 0 ) { theTags( newobject ) = tags1 ; theLen( newobject ) = 0 ; oString( newobject ) = NULL ; SETGLOBJECTTO(newobject, oGlobalValue(*o1)); if ( ! push2(&newobject, &tnewobj, &operandstack) ) return FALSE ; theTags(*o2) = tags1 ; SETGLOBJECTTO(*o2, oGlobalValue(*o1)); return TRUE ; } postsize = stringsize - matchsize ; presize = 0 ; /* Compare sub-strings of string (of length match_size) with seek, until no sub-string left that is that long, or have found match. */ while ( postsize >= 0 ) { /* If matched up sub-string, then setup post, match & pre. */ if ( ! HqMemCmp( & str[ presize ] , matchsize , seek , matchsize )) { theTags( newobject ) = tags1 ; theLen( newobject ) = ( uint16 )presize ; oString( newobject ) = ( presize != 0 ? str : NULL ) ; SETGLOBJECTTO(newobject, oGlobalValue(*o1)); if ( ! push2(&newobject, &tnewobj, &operandstack) ) return FALSE ; theTags(*o2) = tags1 ; theLen(*o2) = ( uint16 )matchsize ; oString(*o2) = str + presize ; SETGLOBJECTTO(*o2, oGlobalValue(*o1)); theLen(*o1) = ( uint16 )postsize ; oString(*o1) = ( postsize != 0 ? str + presize + matchsize : NULL ) ; return TRUE ; } /* Otherwise look at next sub-string. */ ++presize ; --postsize ; } /* No match occurred, so push the boolean false. */ Copy(o2, &fnewobj) ; return TRUE ; }
/* ---------------------------------------------------------------------------- function: filter_() author: Paul Attridge creation date: 26-Jun-1991 last modification: ##-###-#### arguments: none . description: See PostScript reference manual second edition page 416. ---------------------------------------------------------------------------- */ Bool filter_(ps_context_t *pscontext) { FILELIST *flptr ; OBJECT nameo = OBJECT_NOTVM_NOTHING ; OBJECT fileo = OBJECT_NOTVM_NOTHING ; uint8 *filter_name ; int32 name_length ; int32 find_error ; #if defined( ASSERT_BUILD ) int32 stack_size ; #endif UNUSED_PARAM(ps_context_t *, pscontext) ; if ( theStackSize( operandstack ) < 1 ) return error_handler( STACKUNDERFLOW ) ; Copy(&nameo, theTop(operandstack)) ; if ( oType(nameo) == ONAME ) { filter_name = theICList(oName(nameo)) ; name_length = theINLen(oName(nameo)) ; } else if ( oType(nameo) == OSTRING ) { /* undocumented - but they allow strings as an argument */ filter_name = oString(nameo) ; name_length = theLen(nameo) ; } else return error_handler( TYPECHECK ) ; /* find the filter name in the external or standard filter table */ flptr = filter_external_find(filter_name, name_length, &find_error, TRUE) ; if ( flptr == NULL ) { if ( find_error != NOT_AN_ERROR) return error_handler( find_error ); flptr = filter_standard_find(filter_name, name_length) ; if ( flptr == NULL ) return error_handler( UNDEFINED ) ; } /* sanity check */ HQASSERT(isIFilter(flptr), "Not a filter") ; /* Create our own copy of this filter - reusing a previous (dead) one if * possible; otherwise will actually alloc a new one. */ pop(&operandstack) ; /* Don't want name on stack during filter init */ #if defined( ASSERT_BUILD ) /* The init routine removes the arguments it needs, including the underlying source/target from the stack. Check that it actually did remove something. */ stack_size = theStackSize(operandstack) ; #endif if ( ! filter_create_object(flptr, &fileo, NULL, &operandstack) ) { (void)push(&nameo, &operandstack) ; /* Restore name for error reporting */ return FALSE ; } HQASSERT(theStackSize(operandstack) <= stack_size - 1, "Filter init routine should have removed underlying source/target") ; return push(&fileo, &operandstack) ; }
/* ---------------------------------------------------------------------------- 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 */ }
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 ; }
/* ---------------------------------------------------------------------------- function: anchorsearch_() author: Andrew Cave creation date: 09-Oct-1987 last modification: ##-###-#### arguments: none. description: See PostScript reference manual page 116. ---------------------------------------------------------------------------- */ Bool anchorsearch_(ps_context_t *pscontext) { int32 stringsize , postsize , matchsize ; OBJECT *o1 , *o2 ; uint8 tags1 , tags2 ; uint8 *str , *seek ; UNUSED_PARAM(ps_context_t *, pscontext) ; if ( theStackSize( operandstack ) < 1 ) return error_handler( STACKUNDERFLOW ) ; /* Check types. */ o1 = stackindex( 1 , & operandstack ) ; o2 = theTop( operandstack ) ; tags1 = theTags(*o1) ; tags2 = theTags(*o2) ; if ( oType(*o1) != OSTRING || oType(*o2) != OSTRING ) return error_handler( TYPECHECK ) ; /* Check access requirements. */ if ( (!oCanRead(*o1) && !object_access_override(o1)) || (!oCanRead(*o2) && !object_access_override(o2)) ) return error_handler( INVALIDACCESS ) ; /* Extract the locations of seek & string, and their lengths.*/ seek = oString(*o2) ; str = oString(*o1) ; matchsize = theLen(*o2) ; stringsize = theLen(*o1) ; /* Remove the trivial cases. */ postsize = stringsize - matchsize ; if ( postsize < 0 ) { Copy(o2, &fnewobj) ; return TRUE ; } if ( matchsize == 0 ) { if ( ! push( & tnewobj , & operandstack )) return FALSE ; theTags(*o2) = tags1 ; SETGLOBJECTTO(*o2, oGlobalValue(*o1)); return TRUE ; } /* Compare initial sub-string of string (of length match_size) with seek. If initial sub-string matches, then setup post & match, and boolean true. */ if ( HqMemCmp( str , matchsize , seek , matchsize) == 0 ) { if ( ! push( & tnewobj , & operandstack )) return FALSE ; theTags(*o2) = tags1 ; theLen(*o2) = ( uint16 )matchsize ; oString(*o2) = str ; SETGLOBJECTTO(*o2, oGlobalValue(*o1)); theLen(*o1) = ( uint16 )postsize ; oString(*o1) = ( postsize != 0 ? str + matchsize : NULL ) ; return TRUE ; } /* Else no match occurred, so push boolean false. */ Copy(o2, &fnewobj) ; return TRUE ; }
Bool externalfilter_(ps_context_t *pscontext) { OBJECT *o1, *o2 ; int32 dev_number, name_length ; uint8 *filter_name ; UNUSED_PARAM(ps_context_t *, pscontext) ; HQTRACE( debug_filters , ( "Welcome to externalfilter" )) ; /* externalfilter is always called with two args on the stack, even if the second one isn't used */ if ( theStackSize( operandstack ) < 1 ) return error_handler( STACKUNDERFLOW ) ; o1 = theTop( operandstack ) ; /* integer code or dictionary */ switch ( oType(*o1) ) { case OINTEGER: dev_number = oInteger(*o1); break ; case ODICTIONARY: o2 = stackindex( 1, &operandstack ) ; /* filter name */ return filter_external_define( o1 , o2 ); /* device to be added */ default: return error_handler(TYPECHECK) ; } if ( dev_number == -3 ) { /* resourceforall */ pop( &operandstack ) ; return filter_external_forall(&operandstack); } o2 = stackindex(1, &operandstack ) ; /* filter name */ switch ( oType(*o2) ) { case ONAME: filter_name = theICList(oName(*o2)) ; name_length = theINLen(oName(*o2)) ; break ; case OSTRING: /* undocumented - but they allow strings as an argument */ filter_name = oString(*o2) ; name_length = theLen(*o2) ; break ; default: return error_handler( TYPECHECK ) ; } switch ( dev_number ) { case -2: /* findresource */ if ( filter_external_exists(filter_name, name_length) ) { Copy(o1, &tnewobj) ; } else { Copy(o1, &fnewobj) ; } return TRUE ; case -1: /* undefineresource */ npop(2, &operandstack) ; return filter_external_undefine(filter_name, name_length); } return error_handler(RANGECHECK) ; }