/* Copyright (C) 1992-1998 The Geometry Center * Copyright (C) 1998-2000 Stuart Levy, Tamara Munzner, Mark Phillips * * This file is part of Geomview. * * Geomview is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation; either version 2, or (at your option) * any later version. * * Geomview is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with Geomview; see the file COPYING. If not, write * to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, * USA, or visit http://www.gnu.org. */ #if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) #include "config.h" #endif static char copyright[] = "Copyright (C) 1992-1998 The Geometry Center\n\ Copyright (C) 1998-2000 Stuart Levy, Tamara Munzner, Mark Phillips"; /* * NOTES: * 1. mrti() assumes unsigned short is 2 bytes, MSB first * this may have to change for other architecture * 2. will it be possible to increase the encoded float array length * by "adding l" to create 256 aggregates of 3 or 4 floats each, as * opposed to 256 straight floats? (see appendix C, pg 163 of the * 'big' renderman manual) * 3. the name mrti should be changed to mgri (it sounds better) */ #include "mgribtoken.h" #include #include "mg.h" #include "mgribP.h" #include "mgrib.h" #ifdef test #include #endif #define BUFFERSIZE 1024*128 /* 128k buffer */ #define TMPSIZE 8192 #define SECTIONWIDTH 70 /* width of a section header */ #define STRINGDEF 0315 #define STRINGREF 0317 #define LNGSTRINGENCODE 0241 /* length follows, is unsigned short */ #define STRINGENCODE 0220 #define RIREQDEF 0314 #define RIREQREF 0246 #define FLOATARRAYDEF 0310 #define INTEGER 0201 /* unsigned short */ #define FLOAT 0244 void binary_token(int a1, va_list *alist); void ascii_token(int a1, va_list *alist); unsigned char *tokenbuffer=NULL; unsigned char *limit; unsigned char *ptr; /* following is the table: see mgribtoken.h (struct) for desc of fields */ static struct _table table[] = { {"", 0, 0, 0}, /* mr_NULL */ /* Ri Requests */ {"AttributeBegin", 14, 0, 0}, {"AttributeEnd", 12, 1, 0}, {"TransformBegin", 14, 2, 0}, {"TransformEnd", 12, 3, 0}, {"Identity", 8, 4, 0}, {"ConcatTransform", 15, 5, 0}, {"Surface", 7, 6, 0}, {"ShadingInterpolation", 20, 7, 0}, {"Color", 5, 8, 0}, {"Opacity", 7, 9, 0}, {"Polygon", 7, 10, 0}, {"PatchMesh", 9, 11, 0}, {"Format", 6, 12, 0}, {"Projection", 10, 13, 0}, {"Clipping", 8, 14, 0}, {"WorldBegin", 10, 15, 0}, {"WorldEnd", 8, 16, 0}, {"Display", 7, 17, 0}, {"ScreenWindow", 12, 19, 0}, {"LightSource", 11, 20, 0}, {"Sphere", 6, 21, 0}, {"Translate", 9, 22, 0}, {"Rotate", 6, 23, 0}, {"Cylinder", 8, 24, 0}, {"NuPatch", 7, 25, 0}, {"ShadingRate", 11, 26, 0}, {"Option", 6, 27, 0}, {"Illuminate", 10, 28, 0}, {"FrameBegin", 10, 29, 0}, {"FrameEnd", 8, 30, 0}, /* following are reserved - do not add */ /* or remove fields, just change them! */ {"", 0, 255, 0}, {"", 0, 255, 0}, {"", 0, 255, 0}, {"", 0, 255, 0}, {"", 0, 255, 0}, {"", 0, 255, 0}, {"", 0, 255, 0}, {"", 0, 255, 0}, {"", 0, 255, 0}, {"", 0, 255, 0}, {"", 0, 255, 0}, {"", 0, 255, 0}, {"", 0, 255, 0}, {"", 0, 255, 0}, {"", 0, 255, 0}, {"", 0, 255, 0}, {"", 0, 255, 0}, {"", 0, 255, 0}, {"", 0, 255, 0}, /* Strings - we start these out at position 50 */ {"P", 1, 0, 0}, {"N", 1, 1, 0}, {"Cs", 2, 2, 0}, {"Pw", 2, 3, 0}, {"Os", 2, 4, 0}, {"st", 2, 5, 0}, {"plastic", 7, 6, 0}, {"hplastic", 8, 7, 0}, {"eplastic", 8, 8, 0}, {"heplastic", 9, 9, 0}, {"constant", 8, 10, 0}, {"ambientlight", 12, 11, 0}, {"lightcolor", 10, 12, 0}, {"distantlight", 12, 13, 0}, {"intensity", 9, 14, 0}, {"file", 4, 15, 0}, {"rgb", 3, 16, 0}, {"rgba", 4, 17, 0}, {"Ka", 2, 18, 0}, {"Kd", 2, 19, 0}, {"Ks", 2, 20, 0}, {"specularcolor", 13, 21, 0}, {"roughness", 9, 22, 0}, {"fov", 3, 23, 0}, {"perspective", 11, 24, 0}, {"to", 2, 25, 0}, {"framebuffer", 11, 26, 0} }; /* initialize tokenbuffer */ void mrti_init() { if(tokenbuffer) free(tokenbuffer); tokenbuffer = (unsigned char *)malloc(BUFFERSIZE); tokenbuffer[0] = (char)0; limit = (unsigned char *)(tokenbuffer + BUFFERSIZE); ptr = tokenbuffer; } /* reset the ptr & tokenbuffer */ void mrti_reset() { ptr = tokenbuffer; tokenbuffer[0] = (char)0; } /* quick copy routine w/ ptr update */ void cat(unsigned char *s, char *a) { while((*(s++)=(*(a++)))) ptr++; } /* routine will check buffer for possible overun, will realloc if needed */ /* generally, "worst case" values should be passed to check_buffer */ void check_buffer(int length) { length += 8; if((unsigned char *)(ptr+length)>(unsigned char *)limit) { /* optinally check for maximum buffer allocation here */ long used = ptr - tokenbuffer; long avail = limit - tokenbuffer; /* Buffer grows exponentially, by factor of 1.5 each time */ do { avail += avail>>1; } while(used+length >= avail); tokenbuffer = (unsigned char *)realloc(tokenbuffer, avail); ptr = tokenbuffer + used; limit = tokenbuffer + avail; } } /* process variable size token list */ void mrti(int a1, ... ) { va_list alist; va_start(alist, a1); switch((int)(_mgribc->render_device & (RMD_BINARY|RMD_ASCII))) { case (int)RMD_BINARY: binary_token(a1, &alist); break; case (int)RMD_ASCII: ascii_token(a1, &alist); break; } va_end(alist); } /* return 1 when supplied token requires its own (ascii) line, 0 otherwise */ int line_initializer(int token) { /* THIS IS HACKISH - IT WILL CREATE A LINE FEED BEFORE */ /* IT CREATES THE NEW LINE, WHICH ISN'T ALWAYS GOOD!! */ if(token=mr_P && token<=mr_Os)) return 1; else return 0; } /* ASCII SUBPROCESSING */ void ascii_token(int token, va_list *alist) { int i; int count, number; int subsize; static int arraysize; static int expectSubArray=0; static char astring[128]; double nextfloat; /* va_arg converts floats to doubles */ float *floatptr; char *s; int len, add; do { if(expectSubArray && (token!=mr_subarray3)) { /* ERROR */ } /* check to see if we need to start a new line */ if(line_initializer(token) && *(ptr-1)!='\n') *(ptr++)='\n'; switch(token) { case mr_section: check_buffer(SECTIONWIDTH); /* should not exceed this */ s = va_arg(*alist, char*); len = strlen(s); if(len+3>SECTIONWIDTH) len = SECTIONWIDTH-3; /* 3 added characters */ *(ptr++)='\n'; cat(ptr,"# "); cat(ptr,s); cat(ptr," "); len = SECTIONWIDTH - 3 - len; while((len--)>0) *(ptr++)='*'; break; case mr_comment: s = va_arg(*alist, char*); len = strlen(s); check_buffer(len+2); cat(ptr,"# "); cat(ptr,s); break; case mr_header: s = va_arg(*alist, char*); len = strlen(s); check_buffer(len+2); cat(ptr,"##"); cat(ptr,s); break; case mr_nl: /* check for space */ check_buffer(2); if(*(ptr-1)==' ') ptr--; *(ptr++)='\n'; break; case mr_array: arraysize = va_arg(*alist, int); check_buffer(arraysize*16+4); /* how else can we do this? */ *(ptr++)='['; for(i=0;i 1 byte into an * arbitrary (unaligned) location. e.g. * *(unsigned short *)ptr = anUnsignedVariable * may be an illegal instruction. Therefore, macros which will copy these * values one byte at a time follow here and are used where needed. These * macros will work only with float sizes of 4 bytes (IEEE) & unsigned short * int sizes of 2 bytes */ #define COPYUSHORT( value ) *ptr++ = ((char *)&value)[0];\ *ptr++ = ((char *)&value)[1] #define COPYFLOAT( value ) *ptr++ = ((char *)&value)[0];\ *ptr++ = ((char *)&value)[1];\ *ptr++ = ((char *)&value)[2];\ *ptr++ = ((char *)&value)[3] void binary_token(int token, va_list *alist) { int i; static int expectSubArray=0; static int arraysize; float *floatptr; if(expectSubArray && (token!=mr_subarray3)) { /* ERROR */ } do { /* single '&' on next line changed to && by mbp Wed May 17 22:33:00 2000 */ if((token>=STRINGBASE) && (token