ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

ftrandom.c
Go to the documentation of this file.
00001 /* Copyright (C) 2005, 2007, 2008 by George Williams */
00002 /*
00003  * Redistribution and use in source and binary forms, with or without
00004  * modification, are permitted provided that the following conditions are met:
00005 
00006  * Redistributions of source code must retain the above copyright notice, this
00007  * list of conditions and the following disclaimer.
00008 
00009  * Redistributions in binary form must reproduce the above copyright notice,
00010  * this list of conditions and the following disclaimer in the documentation
00011  * and/or other materials provided with the distribution.
00012 
00013  * The name of the author may not be used to endorse or promote products
00014  * derived from this software without specific prior written permission.
00015 
00016  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
00017  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00018  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
00019  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00020  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00021  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
00022  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
00023  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
00024  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
00025  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00026  */
00027 
00028 /* modified by Werner Lemberg <wl@gnu.org>       */
00029 /* This file is now part of the FreeType library */
00030 
00031 
00032 #include <stdio.h>
00033 #include <stdlib.h>
00034 #include <string.h>
00035 #include <strings.h>
00036 #include <sys/types.h>
00037 #include <sys/stat.h>
00038 #include <sys/wait.h>
00039 #include <unistd.h>
00040 #include <dirent.h>
00041 #include <math.h>
00042 #include <signal.h>
00043 #include <time.h>
00044 
00045 #include <ft2build.h>
00046 #include FT_FREETYPE_H
00047 #include FT_OUTLINE_H
00048 
00049 #define true     1
00050 #define false    0
00051 #define forever  for (;;)
00052 
00053 
00054   static int    check_outlines = false;
00055   static int    nohints        = false;
00056   static int    rasterize      = false;
00057   static char*  results_dir    = "results";
00058 
00059 #define GOOD_FONTS_DIR  "/home/wl/freetype-testfonts"
00060 
00061   static char*  default_dir_list[] =
00062   {
00063     GOOD_FONTS_DIR,
00064     NULL
00065   };
00066 
00067   static char*  default_ext_list[] =
00068   {
00069     "ttf",
00070     "otf",
00071     "ttc",
00072     "cid",
00073     "pfb",
00074     "pfa",
00075     "bdf",
00076     "pcf",
00077     "pfr",
00078     "fon",
00079     "otb",
00080     "cff",
00081     NULL
00082   };
00083 
00084   static int  error_count    = 1;
00085   static int  error_fraction = 0;
00086 
00087   static FT_F26Dot6  font_size = 12 * 64;
00088 
00089   static struct fontlist
00090   {
00091     char*         name;
00092     int           len;
00093     unsigned int  isbinary: 1;
00094     unsigned int  isascii: 1;
00095     unsigned int  ishex: 1;
00096 
00097   } *fontlist;
00098 
00099   static int  fcnt;
00100 
00101 
00102   static int
00103   FT_MoveTo( const FT_Vector  *to,
00104              void             *user )
00105   {
00106     return 0;
00107   }
00108 
00109 
00110   static int
00111   FT_LineTo( const FT_Vector  *to,
00112              void             *user )
00113   {
00114     return 0;
00115   }
00116 
00117 
00118   static int
00119   FT_ConicTo( const FT_Vector  *_cp,
00120               const FT_Vector  *to,
00121               void             *user )
00122   {
00123     return 0;
00124   }
00125 
00126 
00127   static int
00128   FT_CubicTo( const FT_Vector  *cp1,
00129               const FT_Vector  *cp2,
00130               const FT_Vector  *to,
00131               void             *user )
00132   {
00133     return 0;
00134   }
00135 
00136 
00137   static FT_Outline_Funcs outlinefuncs =
00138   {
00139     FT_MoveTo,
00140     FT_LineTo,
00141     FT_ConicTo,
00142     FT_CubicTo,
00143     0, 0          /* No shift, no delta */
00144   };
00145 
00146 
00147   static void
00148   TestFace( FT_Face  face )
00149   {
00150     int  gid;
00151     int  load_flags = FT_LOAD_DEFAULT;
00152 
00153 
00154     if ( check_outlines         &&
00155          FT_IS_SCALABLE( face ) )
00156       load_flags = FT_LOAD_NO_BITMAP;
00157 
00158     if ( nohints )
00159       load_flags |= FT_LOAD_NO_HINTING;
00160 
00161     FT_Set_Char_Size( face, 0, font_size, 72, 72 );
00162 
00163     for ( gid = 0; gid < face->num_glyphs; ++gid )
00164     {
00165       if ( check_outlines         &&
00166            FT_IS_SCALABLE( face ) )
00167       {
00168         if ( !FT_Load_Glyph( face, gid, load_flags ) )
00169           FT_Outline_Decompose( &face->glyph->outline, &outlinefuncs, NULL );
00170       }
00171       else
00172         FT_Load_Glyph( face, gid, load_flags );
00173 
00174       if ( rasterize )
00175         FT_Render_Glyph( face->glyph, ft_render_mode_normal );
00176     }
00177 
00178     FT_Done_Face( face );
00179   }
00180 
00181 
00182   static void
00183   ExecuteTest( char*  testfont )
00184   {
00185     FT_Library  context;
00186     FT_Face     face;
00187     int         i, num;
00188 
00189 
00190     if ( FT_Init_FreeType( &context ) )
00191     {
00192       fprintf( stderr, "Can't initialize FreeType.\n" );
00193       exit( 1 );
00194     }
00195 
00196     if ( FT_New_Face( context, testfont, 0, &face ) )
00197     {
00198       /* The font is erroneous, so if this fails that's ok. */
00199       exit( 0 );
00200     }
00201 
00202     if ( face->num_faces == 1 )
00203       TestFace( face );
00204     else
00205     {
00206       num = face->num_faces;
00207       FT_Done_Face( face );
00208 
00209       for ( i = 0; i < num; ++i )
00210       {
00211         if ( !FT_New_Face( context, testfont, i, &face ) )
00212           TestFace( face );
00213       }
00214     }
00215 
00216     exit( 0 );
00217   }
00218 
00219 
00220   static int
00221   extmatch( char*   filename,
00222             char**  extensions )
00223   {
00224     int    i;
00225     char*  pt;
00226 
00227 
00228     if ( extensions == NULL )
00229       return true;
00230 
00231     pt = strrchr( filename, '.' );
00232     if ( pt == NULL )
00233       return false;
00234     if ( pt < strrchr( filename, '/' ) )
00235       return false;
00236 
00237     for ( i = 0; extensions[i] != NULL; ++i )
00238       if ( strcasecmp( pt + 1, extensions[i] ) == 0 ||
00239            strcasecmp( pt,     extensions[i] ) == 0 )
00240         return true;
00241 
00242     return false;
00243   }
00244 
00245 
00246   static void
00247   figurefiletype( struct fontlist*  item )
00248   {
00249     FILE*  foo;
00250 
00251 
00252     item->isbinary = item->isascii = item->ishex = false;
00253 
00254     foo = fopen( item->name, "rb" );
00255     if ( foo != NULL )
00256     {
00257       /* Try to guess the file type from the first few characters... */
00258       int  ch1 = getc( foo );
00259       int  ch2 = getc( foo );
00260       int  ch3 = getc( foo );
00261       int  ch4 = getc( foo );
00262 
00263 
00264       fclose( foo );
00265 
00266       if ( ( ch1 == 0   && ch2 == 1   && ch3 == 0   && ch4 == 0   ) ||
00267            ( ch1 == 'O' && ch2 == 'T' && ch3 == 'T' && ch4 == 'O' ) ||
00268            ( ch1 == 't' && ch2 == 'r' && ch3 == 'u' && ch4 == 'e' ) ||
00269            ( ch1 == 't' && ch2 == 't' && ch3 == 'c' && ch4 == 'f' ) )
00270       {
00271         /* ttf, otf, ttc files */
00272         item->isbinary = true;
00273       }
00274       else if ( ch1 == 0x80 && ch2 == '\01' )
00275       {
00276         /* PFB header */
00277         item->isbinary = true;
00278       }
00279       else if ( ch1 == '%' && ch2 == '!' )
00280       {
00281         /* Random PostScript */
00282         if ( strstr( item->name, ".pfa" ) != NULL ||
00283              strstr( item->name, ".PFA" ) != NULL )
00284           item->ishex = true;
00285         else
00286           item->isascii = true;
00287       }
00288       else if ( ch1 == 1 && ch2 == 0 && ch3 == 4 )
00289       {
00290         /* Bare CFF */
00291         item->isbinary = true;
00292       }
00293       else if ( ch1 == 'S' && ch2 == 'T' && ch3 == 'A' && ch4 == 'R' )
00294       {
00295         /* BDF */
00296         item->ishex = true;
00297       }
00298       else if ( ch1 == 'P' && ch2 == 'F' && ch3 == 'R' && ch4 == '0' )
00299       {
00300         /* PFR */
00301         item->isbinary = true;
00302       }
00303       else if ( ( ch1 == '\1' && ch2 == 'f' && ch3 == 'c' && ch4 == 'p' ) ||
00304                 ( ch1 == 'M'  && ch2 == 'Z' )                             )
00305       {
00306         /* Windows FON */
00307         item->isbinary = true;
00308       }
00309       else
00310       {
00311         fprintf( stderr,
00312                  "Can't recognize file type of `%s', assuming binary\n",
00313                  item->name );
00314         item->isbinary = true;
00315       }
00316     }
00317     else
00318     {
00319       fprintf( stderr, "Can't open `%s' for typing the file.\n",
00320                item->name );
00321       item->isbinary = true;
00322     }
00323   }
00324 
00325 
00326   static void
00327   FindFonts( char**  fontdirs,
00328              char**  extensions )
00329   {
00330     DIR*            examples;
00331     struct dirent*  ent;
00332 
00333     int             i, max;
00334     char            buffer[1025];
00335     struct stat     statb;
00336 
00337 
00338     max  = 0;
00339     fcnt = 0;
00340 
00341     for ( i = 0; fontdirs[i] != NULL; ++i )
00342     {
00343       examples = opendir( fontdirs[i] );
00344       if ( examples == NULL )
00345       {
00346         fprintf( stderr,
00347                  "Can't open example font directory `%s'\n",
00348                  fontdirs[i] );
00349         exit( 1 );
00350       }
00351 
00352       while ( ( ent = readdir( examples ) ) != NULL )
00353       {
00354         snprintf( buffer, sizeof ( buffer ),
00355                   "%s/%s", fontdirs[i], ent->d_name );
00356         if ( stat( buffer, &statb ) == -1 || S_ISDIR( statb.st_mode ) )
00357           continue;
00358         if ( extensions == NULL || extmatch( buffer, extensions ) )
00359         {
00360           if ( fcnt >= max )
00361           {
00362             max += 100;
00363             fontlist = realloc( fontlist, max * sizeof ( struct fontlist ) );
00364             if ( fontlist == NULL )
00365             {
00366               fprintf( stderr, "Can't allocate memory\n" );
00367               exit( 1 );
00368             }
00369           }
00370 
00371           fontlist[fcnt].name = strdup( buffer );
00372           fontlist[fcnt].len  = statb.st_size;
00373 
00374           figurefiletype( &fontlist[fcnt] );
00375           ++fcnt;
00376         }
00377       }
00378 
00379       closedir( examples );
00380     }
00381 
00382     if ( fcnt == 0 )
00383     {
00384       fprintf( stderr, "Can't find matching font files.\n" );
00385       exit( 1 );
00386     }
00387 
00388     fontlist[fcnt].name = NULL;
00389   }
00390 
00391 
00392   static int
00393   getErrorCnt( struct fontlist*  item )
00394   {
00395     if ( error_count == 0 && error_fraction == 0 )
00396       return 0;
00397 
00398     return error_count + ceil( error_fraction * item->len );
00399   }
00400 
00401 
00402   static int
00403   getRandom( int  low,
00404              int  high )
00405   {
00406     if ( low - high < 0x10000L )
00407       return low + ( ( random() >> 8 ) % ( high + 1 - low ) );
00408 
00409     return low + ( random() % ( high + 1 - low ) );
00410   }
00411 
00412 
00413   static int
00414   copyfont( struct fontlist*  item,
00415             char*             newfont )
00416   {
00417     static char  buffer[8096];
00418     FILE         *good, *new;
00419     int          len;
00420     int          i, err_cnt;
00421 
00422 
00423     good = fopen( item->name, "r" );
00424     if ( good == NULL )
00425     {
00426       fprintf( stderr, "Can't open `%s'\n", item->name );
00427       return false;
00428     }
00429 
00430     new = fopen( newfont, "w+" );
00431     if ( new == NULL )
00432     {
00433       fprintf( stderr, "Can't create temporary output file `%s'\n",
00434                newfont );
00435       exit( 1 );
00436     }
00437 
00438     while ( ( len = fread( buffer, 1, sizeof ( buffer ), good ) ) > 0 )
00439       fwrite( buffer, 1, len, new );
00440 
00441     fclose( good );
00442 
00443     err_cnt = getErrorCnt( item );
00444     for ( i = 0; i < err_cnt; ++i )
00445     {
00446       fseek( new, getRandom( 0, item->len - 1 ), SEEK_SET );
00447 
00448       if ( item->isbinary )
00449         putc( getRandom( 0, 0xff ), new );
00450       else if ( item->isascii )
00451         putc( getRandom( 0x20, 0x7e ), new );
00452       else
00453       {
00454         int  hex = getRandom( 0, 15 );
00455 
00456 
00457         if ( hex < 10 )
00458           hex += '0';
00459         else
00460           hex += 'A' - 10;
00461 
00462         putc( hex, new );
00463       }
00464     }
00465 
00466     if ( ferror( new ) )
00467     {
00468       fclose( new );
00469       unlink( newfont );
00470       return false;
00471     }
00472 
00473     fclose( new );
00474 
00475     return true;
00476   }
00477 
00478 
00479   static int  child_pid;
00480 
00481   static void
00482   abort_test( int  sig )
00483   {
00484     /* If a time-out happens, then kill the child */
00485     kill( child_pid, SIGFPE );
00486     write( 2, "Timeout... ", 11 );
00487   }
00488 
00489 
00490   static void
00491   do_test( void )
00492   {
00493     int         i        = getRandom( 0, fcnt - 1 );
00494     static int  test_num = 0;
00495     char        buffer[1024];
00496 
00497 
00498     sprintf( buffer, "%s/test%d", results_dir, test_num++ );
00499 
00500     if ( copyfont ( &fontlist[i], buffer ) )
00501     {
00502       signal( SIGALRM, abort_test );
00503       /* Anything that takes more than 20 seconds */
00504       /* to parse and/or rasterize is an error.   */
00505       alarm( 20 );
00506       if ( ( child_pid = fork() ) == 0 )
00507         ExecuteTest( buffer );
00508       else if ( child_pid != -1 )
00509       {
00510         int  status;
00511 
00512 
00513         waitpid( child_pid, &status, 0 );
00514         alarm( 0 );
00515         if ( WIFSIGNALED ( status ) )
00516           printf( "Error found in file `%s'\n", buffer );
00517         else
00518           unlink( buffer );
00519       }
00520       else
00521       {
00522         fprintf( stderr, "Can't fork test case.\n" );
00523         exit( 1 );
00524       }
00525       alarm( 0 );
00526     }
00527   }
00528 
00529 
00530   static void
00531   usage( FILE*  out,
00532          char*  name )
00533   {
00534     fprintf( out, "%s [options] -- Generate random erroneous fonts\n"
00535                   "  and attempt to parse them with FreeType.\n\n", name );
00536 
00537     fprintf( out, "  --all                    All non-directory files are assumed to be fonts.\n" );
00538     fprintf( out, "  --check-outlines         Make sure we can parse the outlines of each glyph.\n" );
00539     fprintf( out, "  --dir <path>             Append <path> to list of font search directories.\n" );
00540     fprintf( out, "  --error-count <cnt>      Introduce <cnt> single byte errors into each font.\n" );
00541     fprintf( out, "  --error-fraction <frac>  Introduce <frac>*filesize single byte errors\n"
00542                   "                           into each font.\n" );
00543     fprintf( out, "  --ext <ext>              Add <ext> to list of extensions indicating fonts.\n" );
00544     fprintf( out, "  --help                   Print this.\n" );
00545     fprintf( out, "  --nohints                Turn off hinting.\n" );
00546     fprintf( out, "  --rasterize              Attempt to rasterize each glyph.\n" );
00547     fprintf( out, "  --results <dir>          Directory in which to place the test fonts.\n" );
00548     fprintf( out, "  --size <float>           Use the given font size for the tests.\n" );
00549     fprintf( out, "  --test <file>            Run a single test on an already existing file.\n" );
00550   }
00551 
00552 
00553   int
00554   main( int     argc,
00555         char**  argv )
00556   {
00557     char    **dirs, **exts;
00558     char    *pt, *end;
00559     int     dcnt = 0, ecnt = 0, rset = false, allexts = false;
00560     int     i;
00561     time_t  now;
00562     char*   testfile = NULL;
00563 
00564 
00565     dirs = calloc( argc + 1, sizeof ( char ** ) );
00566     exts = calloc( argc + 1, sizeof ( char ** ) );
00567 
00568     for ( i = 1; i < argc; ++i )
00569     {
00570       pt = argv[i];
00571       if ( pt[0] == '-' && pt[1] == '-' )
00572         ++pt;
00573 
00574       if ( strcmp( pt, "-all" ) == 0 )
00575         allexts = true;
00576       else if ( strcmp( pt, "-check-outlines" ) == 0 )
00577         check_outlines = true;
00578       else if ( strcmp( pt, "-dir" ) == 0 )
00579         dirs[dcnt++] = argv[++i];
00580       else if ( strcmp( pt, "-error-count" ) == 0 )
00581       {
00582         if ( !rset )
00583           error_fraction = 0;
00584         rset = true;
00585         error_count = strtol( argv[++i], &end, 10 );
00586         if ( *end != '\0' )
00587         {
00588           fprintf( stderr, "Bad value for error-count: %s\n", argv[i] );
00589           exit( 1 );
00590         }
00591       }
00592       else if ( strcmp( pt, "-error-fraction" ) == 0 )
00593       {
00594         if ( !rset )
00595           error_count = 0;
00596         rset = true;
00597         error_fraction = strtod( argv[++i], &end );
00598         if ( *end != '\0' )
00599         {
00600           fprintf( stderr, "Bad value for error-fraction: %s\n", argv[i] );
00601           exit( 1 );
00602         }
00603       }
00604       else if ( strcmp( pt, "-ext" ) == 0 )
00605         exts[ecnt++] = argv[++i];
00606       else if ( strcmp( pt, "-help" ) == 0 )
00607       {
00608         usage( stdout, argv[0] );
00609         exit( 0 );
00610       }
00611       else if ( strcmp( pt, "-nohints" ) == 0 )
00612         nohints = true;
00613       else if ( strcmp( pt, "-rasterize" ) == 0 )
00614         rasterize = true;
00615       else if ( strcmp( pt, "-results" ) == 0 )
00616         results_dir = argv[++i];
00617       else if ( strcmp( pt, "-size" ) == 0 )
00618       {
00619         font_size = (FT_F26Dot6)( strtod( argv[++i], &end ) * 64 );
00620         if ( *end != '\0' || font_size < 64 )
00621         {
00622           fprintf( stderr, "Bad value for size: %s\n", argv[i] );
00623           exit( 1 );
00624         }
00625       }
00626       else if ( strcmp( pt, "-test" ) == 0 )
00627         testfile = argv[++i];
00628       else
00629       {
00630         usage( stderr, argv[0] );
00631         exit( 1 );
00632       }
00633     }
00634 
00635     if ( allexts )
00636       exts = NULL;
00637     else if ( ecnt == 0 )
00638       exts = default_ext_list;
00639 
00640     if ( dcnt == 0 )
00641       dirs = default_dir_list;
00642 
00643     if ( testfile != NULL )
00644       ExecuteTest( testfile );         /* This should never return */
00645 
00646     time( &now );
00647     srandom( now );
00648 
00649     FindFonts( dirs, exts );
00650     mkdir( results_dir, 0755 );
00651 
00652     forever
00653       do_test();
00654 
00655     return 0;
00656   }
00657 
00658 
00659 /* EOF */

Generated on Sat May 26 2012 04:32:57 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.