1 /****************************************************************************
2  *               pov_util.cpp
3  *
4  * This module implements misc utility functions.
5  *
6  * from Persistence of Vision(tm) Ray Tracer version 3.6.
7  * Copyright 1991-2003 Persistence of Vision Team
8  * Copyright 2003-2004 Persistence of Vision Raytracer Pty. Ltd.
9  *---------------------------------------------------------------------------
10  * NOTICE: This source code file is provided so that users may experiment
11  * with enhancements to POV-Ray and to port the software to platforms other
12  * than those supported by the POV-Ray developers. There are strict rules
13  * regarding how you are permitted to use this file. These rules are contained
14  * in the distribution and derivative versions licenses which should have been
15  * provided with this file.
16  *
17  * These licences may be found online, linked from the end-user license
18  * agreement that is located at http://www.povray.org/povlegal.html
19  *---------------------------------------------------------------------------
20  * This program is based on the popular DKB raytracer version 2.12.
21  * DKBTrace was originally written by David K. Buck.
22  * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
23  *---------------------------------------------------------------------------
24  *
25  *===========================================================================
26  * This file is part of MegaPOV, a modified and unofficial version of POV-Ray
27  * For more information on MegaPOV visit our website:
28  * http://megapov.inetart.net/
29  *===========================================================================
30  *
31  * $RCSfile: pov_util.cpp,v $
32  * $Revision: 1.13 $
33  * $Author: chris $
34  *
35  *****************************************************************************/
36 
37 #include <ctype.h>
38 #include <stdarg.h>
39 
40 #include "frame.h"
41 #include "pov_util.h"
42 #include "povray.h"
43 
44 BEGIN_POV_NAMESPACE
45 
46 /*
47 // not used right now
48 typedef struct
49 {
50   bool read_local;
51   bool read_global;
52   bool write_local;
53   bool write_global;
54 } POV_File_Restrictions;
55 
56 POV_File_Restrictions gPOV_File_Restrictions[POV_File_Unknown_Count] =
57 {
58   { false, false, false, false }, // POV_File_Unknown
59   { true,  true,  false, false }, // POV_File_Image_Targa
60   { true,  true,  false, false }, // POV_File_Image_PNG
61   { true,  true,  false, false }, // POV_File_Image_PPM
62   { true,  true,  false, false }, // POV_File_Image_PGM
63   { true,  true,  false, false }, // POV_File_Image_GIF
64   { true,  true,  false, false }, // POV_File_Image_IFF
65   { true,  true,  false, false }, // POV_File_Image_JPEG
66   { true,  true,  false, false }, // POV_File_Image_TIFF
67   { true,  true,  false, false }, // POV_File_Image_System
68   { true,  false, false, false }, // POV_File_Text_POV
69   { true,  false, false, false }, // POV_File_Text_INC
70   { true,  false, false, false }, // POV_File_Text_INI
71   { true,  true,  false, false }, // POV_File_Text_CSV
72   { true,  false, false, false }, // POV_File_Text_Stream
73   { true,  true,  false, false }, // POV_File_Text_User
74   { true,  true,  true,  false }, // POV_File_Data_DF3
75   { true,  true,  true,  true  }, // POV_File_Data_RCA
76   { true,  true,  true,  true  }, // POV_File_Data_LOG
77   { true,  false, true,  false }  // POV_File_Font_TTF
78 };
79 */
80 
81 
82 /*****************************************************************************
83 *
84 * FUNCTION
85 *
86 *   POV_Std_Split_Time
87 *
88 * INPUT
89 *
90 * OUTPUT
91 *
92 * RETURNS
93 *
94 * AUTHOR
95 *
96 *   POV-Ray Team
97 *
98 * DESCRIPTION
99 *
100 *   Split time into hours, minutes and seconds.
101 *
102 * CHANGES
103 *
104 *   Changed to use plain integer math. Will no longer operate correctly for
105 *   time differences longer than 6.8 years. [trf]
106 *
107 ******************************************************************************/
108 
POV_Std_Split_Time(DBL time_dif,unsigned int * hrs,unsigned int * mins,DBL * secs)109 void POV_Std_Split_Time(DBL time_dif, unsigned int *hrs, unsigned int *mins, DBL *secs)
110 {
111   int t = (int)(time_dif * 10.0);
112 
113   *hrs = t / 36000;
114 
115   *mins = (t / 600) % 60;
116 
117   *secs = ((DBL)(t % 600)) / 10.0;
118 }
119 
120 
121 
122 /*****************************************************************************
123 *
124 * FUNCTION
125 *
126 *   closest_power_of_2
127 *
128 * INPUT
129 *
130 *   theNumber - the value to determine closest power of 2 for.
131 *
132 * OUTPUT
133 *
134 * RETURNS
135 *
136 *   The closest power of two is returned, or zero if the
137 *   argument is less than or equal to zero.
138 *
139 * AUTHOR
140 *
141 *   Eduard Schwan
142 *
143 * DESCRIPTION
144 *
145 *   Decription: Find the highest positive power of 2 that is
146 *   less than or equal to the number passed.
147 *
148 *   Input  Output
149 *   -----  ------
150 *     0      0
151 *     1      1
152 *     2      2
153 *     3      2
154 *     8      8
155 *     9      8
156 *
157 * CHANGES
158 *
159 *   Aug 1994 : Created by Eduard.
160 *
161 ******************************************************************************/
162 
closest_power_of_2(unsigned theNumber)163 unsigned closest_power_of_2(unsigned theNumber)
164 {
165   int PowerOf2Counter;
166 
167   /* do not handle zero or negative numbers for now */
168 
169   if (theNumber <= 0)
170   {
171     return(0);
172   }
173 
174   /* count the number in question down as we count up a power of 2 */
175 
176   PowerOf2Counter = 1;
177 
178   while (theNumber > 1)
179   {
180     /* move our power of 2 counter bit up... */
181 
182     PowerOf2Counter <<= 1;
183 
184     /* and reduce our test number by a factor of 2 two */
185 
186     theNumber >>= 1;
187   }
188 
189   return(PowerOf2Counter);
190 }
191 
192 
193 
194 /*****************************************************************************
195 *
196 * FUNCTION
197 *   POVMSUtil_SetFormatString
198 *
199 * DESCRIPTION
200 *   Stores a string with format information in the given attribute.
201 *
202 * CHANGES
203 *   -
204 *
205 ******************************************************************************/
206 
POVMSUtil_SetFormatString(POVMSObjectPtr object,POVMSType key,const char * format,...)207 int POVMSUtil_SetFormatString(POVMSObjectPtr object, POVMSType key, const char *format, ...) // Note: Strings may not contain \0 characters codes!
208 {
209 	va_list marker;
210 	char buffer[1024];
211 
212 	va_start(marker, format);
213 	vsprintf(buffer, format, marker);
214 	va_end(marker);
215 
216 	return POVMSUtil_SetString(object, key, buffer);
217 }
218 
219 
220 /*****************************************************************************
221 *
222 * FUNCTION
223 *
224 *   New_Checked_IStream
225 *
226 * INPUT
227 *
228 * OUTPUT
229 *
230 * RETURNS
231 *
232 * AUTHOR
233 *
234 *   POV-Ray Team
235 *
236 * DESCRIPTION
237 *
238 * CHANGES
239 *
240 ******************************************************************************/
241 
New_Checked_IStream(char * filename,unsigned int stype)242 IStream *New_Checked_IStream(char *filename, unsigned int stype)
243 {
244 	if(POV_ALLOW_FILE_READ(filename, stype) == true)
245 		return New_IStream(filename, stype);
246 	return NULL;
247 }
248 
249 
250 /*****************************************************************************
251 *
252 * FUNCTION
253 *
254 *   New_Checked_OStream
255 *
256 * INPUT
257 *
258 * OUTPUT
259 *
260 * RETURNS
261 *
262 * AUTHOR
263 *
264 *   POV-Ray Team
265 *
266 * DESCRIPTION
267 *
268 * CHANGES
269 *
270 ******************************************************************************/
271 
New_Checked_OStream(char * filename,unsigned int stype,bool append)272 OStream *New_Checked_OStream(char *filename, unsigned int stype, bool append)
273 {
274 	if(POV_ALLOW_FILE_WRITE(filename, stype) == true)
275 		return New_OStream(filename, stype, append);
276 	return NULL;
277 }
278 
279 
280 /*****************************************************************************
281 *
282 * FUNCTION
283 *
284 *   Locate_File
285 *
286 * INPUT
287 *
288 * OUTPUT
289 *
290 * RETURNS
291 *
292 * AUTHOR
293 *
294 *   POV-Ray Team
295 *
296 * DESCRIPTION
297 *
298 *   Find a file in the search path.
299 *
300 * CHANGES
301 *
302 *   Apr 1996: Don't add trailing FILENAME_SEPARATOR if we are immediately
303 *             following DRIVE_SEPARATOR because of Amiga probs.  [AED]
304 *
305 ******************************************************************************/
306 
Locate_File(char * filename,unsigned int stype,char * buffer,bool err_flag)307 IStream *Locate_File(char *filename, unsigned int stype, char *buffer, bool err_flag)
308 {
309   IStream *result;
310   char *qualified_name = Locate_Filename(filename, stype, err_flag);
311 
312   if (qualified_name != NULL)
313   {
314     POV_GET_FULL_PATH(qualified_name, buffer);
315     result = New_Checked_IStream(qualified_name, stype);
316     delete[] qualified_name;
317   }
318   else
319   {
320     /* Any error was already reported in Locate_Filename(...) */
321     result = NULL;
322   }
323 
324   return result;
325 }
326 
327 /*****************************************************************************
328 *
329 * FUNCTION
330 *
331 *   Locate_Filename
332 *
333 * INPUT
334 *
335 * OUTPUT
336 *
337 * RETURNS
338 *  Fully expanded filename, including drive, path, ...
339 *
340 * AUTHOR
341 *
342 *   Alexander R. Enzmann
343 *
344 * DESCRIPTION
345 *
346 *   Find a file in the search path.
347 *
348 * CHANGES
349 *
350 *
351 ******************************************************************************/
352 
Locate_Filename(char * filename,unsigned int stype,bool err_flag)353 char *Locate_Filename(char *filename, unsigned int stype, bool err_flag)
354 {
355   int i,ii,l[4];
356   char pathname[FILE_NAME_LENGTH];
357   char file[FILE_NAME_LENGTH];
358   char file_x[4][FILE_NAME_LENGTH];
359   char *result = NULL;
360 
361   if (Has_Extension(filename))
362   {
363     for(i = 0; i < 4; i++)
364       l[i]=0;
365   }
366   else
367   {
368     for(i = 0; i < 4; i++)
369     {
370       if ((l[i] = strlen(gPOV_File_Extensions[stype].ext[i])) > 0)
371       {
372         strcpy(file_x[i], filename);
373         strcat(file_x[i], gPOV_File_Extensions[stype].ext[i]);
374       }
375     }
376   }
377 
378   /* Check the current directory first. */
379   for(i = 0; i < 4; i++)
380   {
381     /* Try appending the variations of the file extension */
382     if(l[i])
383     {
384       if (EXIST_FILE(file_x[i]) == true)
385       {
386         result = new char[strlen(file_x[i]) + 1];
387         POV_GET_FULL_PATH(file_x[i], result);
388         return result;
389       }
390     }
391   }
392   /* Try the filename without any modifications */
393   if (EXIST_FILE(filename) == true)
394   {
395     result = new char[strlen(filename) + 1];
396     POV_GET_FULL_PATH(filename, result);
397     return result;
398   }
399 
400   /* Walk through the library paths, trying with and without file extensions */
401   for (i = 0; i < opts.Library_Path_Index; i++)
402   {
403     strcpy(file, opts.Library_Paths[i]);
404     file[strlen(file)+1] = '\0';
405     if (file[strlen(file) - 1] != DRIVE_SEPARATOR)
406       file[strlen(file)] = FILENAME_SEPARATOR;
407 
408     for(ii = 0; ii < 4; ii++)
409     {
410       if(l[ii])
411       {
412         strcpy(pathname, file);
413         strcat(pathname, file_x[ii]);
414         if (EXIST_FILE(pathname) == true)
415         {
416           result = new char[strlen(pathname) + 1];
417           POV_GET_FULL_PATH(pathname, result);
418           return result;
419         }
420       }
421     }
422 
423     strcpy(pathname, file);
424     strcat(pathname, filename);
425     if (EXIST_FILE(pathname) == true)
426     {
427       result = new char[strlen(pathname) + 1];
428       POV_GET_FULL_PATH(pathname, result);
429       return result;
430     }
431   }
432 
433   // Allow system specific access of font files:
434   // Obviously this requires POV_NEW_ISTREAM
435   // to be platform specific as well! [trf]
436   if(stype == POV_File_Font_TTF)
437   {
438     if(EXIST_FONT_FILE(filename))
439     {
440        result = new char[strlen(filename) + 1];
441        strcpy(filename, result);
442        return result;
443     }
444   }
445 
446   if (err_flag)
447   {
448     if (l[0])
449       PossibleError("Could not find file '%s%s'",filename,gPOV_File_Extensions[stype].ext[0]);
450     else
451       PossibleError("Could not find file '%s'",filename);
452   }
453 
454   return NULL;
455 }
456 
457 END_POV_NAMESPACE
458