Changeset 512

Show
Ignore:
Timestamp:
02/16/08 17:53:55 (8 months ago)
Author:
krobillard
Message:

font! can now be made from a raster! & binary!.
Re-wrote TexFont? to simplify storage.
'to now works for custom datatypes.
Added .t
if/ now requires selector.
Can make vector! (int) from binary!
Can load PNG from binary!
Added FindThuneGL.cmake

Location:
trunk/thune
Files:
1 added
20 modified

Legend:

Unmodified
Added
Removed
  • trunk/thune/boot.c

    r510 r512  
    8989  "[reduce [first to-text console.out] iter] proc :prin.pack  ;(val -- )\n" 
    9090  "[reduce to-text console.out eol console.out] proc :print   ;(val -- )\n" 
     91  "[dup .] proc :.t\n" 
    9192  "[error! swap make throw] proc :error\n" 
    9293  "[swap context bind proc] proc :proc.env      ;(env body -- proc)\n" 
  • trunk/thune/doc/FindThune.cmake

    r478 r512  
    11FIND_PATH(THUNE_INCLUDE_DIR urlan.h /usr/include /usr/local/include) 
    22 
    3 FIND_LIBRARY(THUNE_LIBRARY NAMES thune PATH /usr/lib /usr/local/lib)  
     3FIND_LIBRARY(THUNE_LIBRARY NAMES thune PATH /usr/lib64 /usr/local/lib64 /usr/lib /usr/local/lib)  
    44 
    55IF (THUNE_INCLUDE_DIR AND THUNE_LIBRARY) 
  • trunk/thune/doc/UserManual

    r510 r512  
    349349stack.level  ( -- level)        Returns depth of data stack. 
    350350===========  =================  ============================ 
     351 
     352 
     353Data Stack Helpers 
     354~~~~~~~~~~~~~~~~~~ 
     355 
     356===========  ======================  ============================ 
     357Word         Stack Usage             Function 
     358===========  ======================  ============================ 
     359.t           (val -- val)            Show value on top of stack. 
     360===========  ======================  ============================ 
    351361 
    352362 
  • trunk/thune/eval.c

    r511 r512  
    13201320            } 
    13211321            break; 
     1322    } 
     1323 
     1324    if( ur_type(val) >= UT_BI_COUNT ) 
     1325    { 
     1326        UCall func = ut->env->customDT[ ur_type(val) - UT_BI_COUNT ].toType; 
     1327        func( ut, tos ); 
     1328        return; 
    13221329    } 
    13231330 
  • trunk/thune/files.c

    r510 r512  
    753753    char* cpB; 
    754754 
    755     if( ! ur_binarySlice( ut, tos, &cpA, &cpB ) || (cpA == 0) ) 
     755    if( ! ur_binarySlice( ut, tos, &cpA, &cpB ) ) 
     756    { 
     757        ur_throwErr( UR_ERR_DATATYPE, "decompress expected binary!" ); 
     758        return; 
     759    } 
     760    if( cpA == 0 ) 
    756761        return; 
    757762 
  • trunk/thune/gl/TexFont.c

    r352 r512  
    2121 
    2222 
    23 #define KERN      1 
    2423//#define DUMP      1 
    2524 
    26 #define FT_PIXELS(x)  (x >> 6) 
    27  
    28  
    29 #ifdef KERN 
    30 typedef struct 
    31 { 
    32     uint32_t avail; 
    33     uint32_t used; 
    34     char* ptr; 
    35 } 
    36 Array; 
    37  
    38  
    39 static void arrayReserve( Array* arr, size_t nsize ) 
    40 { 
    41     if( nsize > arr->avail ) 
    42     { 
    43         size_t count; 
    44  
    45         count = arr->avail * 2; 
    46         if( count < nsize ) 
    47             count = (nsize < 8) ? 8 : nsize; 
    48  
    49         arr->ptr = (char*) realloc( arr->ptr, count ); 
    50         assert( arr->ptr ); 
    51     } 
    52 } 
    53 #endif 
     25#define FT_PIXELS(x)    (x >> 6) 
     26 
     27#define GLYPHS(tf)      ((TexGlyphInfo*) (tf + 1)) 
     28#define TABLE(tf)       (((uint16_t*) tf) + tf->table_offset) 
     29#define KERN(tf)        (((int16_t*) tf) + tf->kern_offset) 
    5430 
    5531 
    5632//---------------------------------------------------------------------------- 
    57  
    58  
    59 void txf_init( TexFont* txf, int w, int h ) 
    60 { 
    61     txf->tex_width  = w; 
    62     txf->tex_height = h; 
    63     txf->tgi        = 0; 
    64     txf->table      = 0; 
    65     txf->kerning    = 0; 
    66 } 
    67  
    68  
    69 void txf_free( TexFont* txf ) 
    70 { 
    71 #define FREE(n) if(n) { free(n); n=0; } 
    72  
    73     FREE( txf->tgi ) 
    74     FREE( txf->table ) 
    75     FREE( txf->kerning ) 
    76 } 
    77  
    78  
    79 void txf_setGlyphCount( TexFont* txf, int n ) 
    80 { 
    81     if( txf->tgi ) 
    82         free( txf->tgi ); 
    83     txf->tgi = (TexGlyphInfo*) malloc( sizeof(TexGlyphInfo) * n ); 
    84     txf->num_glyphs = n; 
    85 } 
    86  
    87  
    88 /** 
    89   Build glyph lookup table. 
    90 */ 
    91 static void _buildGlyphTable( TexFont* txf ) 
    92 { 
    93     int min_glyph; 
    94     int max_glyph; 
    95     TexGlyphInfo* it; 
    96     TexGlyphInfo* end; 
    97  
    98     //assert( txf->num_glyphs ); 
    99  
    100     // Find high & low glyph. 
    101     min_glyph = txf->tgi[0].c; 
    102     max_glyph = txf->tgi[0].c; 
    103  
    104     it  = txf->tgi; 
    105     end = it + txf->num_glyphs; 
    106  
    107     while( it != end ) 
    108     { 
    109         if( it->c < min_glyph ) 
    110             min_glyph = it->c; 
    111         if( it->c > max_glyph ) 
    112             max_glyph = it->c; 
    113         ++it; 
    114     } 
    115  
    116     txf->min_glyph  = min_glyph; 
    117     txf->table_size = max_glyph - min_glyph + 1; 
    118  
    119     // Allocate table. 
    120     if( txf->table ) 
    121         free( txf->table ); 
    122     txf->table = (TexGlyphInfo**) 
    123                  malloc( sizeof(TexGlyphInfo*) * txf->table_size ); 
    124  
    125     // Fill table. 
    126     memset( txf->table, 0, sizeof(TexGlyphInfo*) * txf->table_size ); 
    127  
    128     it = txf->tgi; 
    129     while( it != end ) 
    130     { 
    131         txf->table[ it->c - txf->min_glyph ] = it; 
    132         ++it; 
    133     } 
    134 } 
    13533 
    13634 
     
    14038  uppercase not available (and vice versa). 
    14139*/ 
    142 TexGlyphInfo* txf_glyph( const TexFont* txf, int c ) 
    143 { 
    144     TexGlyphInfo* tgi; 
    145     int max_glyph = txf->min_glyph + txf->table_size; 
    146  
    147     if( (c >= txf->min_glyph) && (c < max_glyph) ) 
    148     { 
    149         tgi = txf->table[c - txf->min_glyph]; 
    150         if( tgi ) 
    151             return tgi; 
     40TexGlyphInfo* txf_glyph( const TexFont* tf, int c ) 
     41{ 
     42    uint16_t n; 
     43    uint16_t* table = TABLE(tf); 
     44    int min_glyph = tf->min_glyph; 
     45    int max_glyph = min_glyph + tf->table_size; 
     46 
     47    if( (c >= min_glyph) && (c < max_glyph) ) 
     48    { 
     49        n = table[ c - min_glyph ]; 
     50        if( n < 0xffff ) 
     51            return GLYPHS(tf) + n; 
    15252 
    15353        if( (c >= 'a') && (c <= 'z') ) 
    15454        { 
    15555            c -= 'a' - 'A';     // toupper 
    156  
    157             if( (c >= txf->min_glyph) && (c < max_glyph) ) 
    158             { 
    159                 return txf->table[c - txf->min_glyph]; 
    160             } 
     56            if( (c >= min_glyph) && (c < max_glyph) ) 
     57                return GLYPHS(tf) + table[ c - min_glyph ]; 
    16158        } 
    16259        else if( (c >= 'A') && (c <= 'Z') ) 
    16360        { 
    16461            c += 'a' - 'A';     // tolower 
    165  
    166             if( (c >= txf->min_glyph) && (c < max_glyph) ) 
    167             { 
    168                 return txf->table[c - txf->min_glyph]; 
    169             } 
    170         } 
    171     } 
    172  
     62            if( (c >= min_glyph) && (c < max_glyph) ) 
     63                return GLYPHS(tf) + table[ c - min_glyph ]; 
     64        } 
     65    } 
    17366    return 0; 
    17467} 
    17568 
    17669 
    177 int txf_kerning( const TexFont* txf, const TexGlyphInfo* left, 
    178                                      const TexGlyphInfo* right ) 
    179 { 
    180 #ifdef KERN 
    181     unsigned char* table;  
     70int txf_kerning( const TexFont* tf, const TexGlyphInfo* left, 
     71                                    const TexGlyphInfo* right ) 
     72{ 
     73    const int16_t* table;  
    18274    if( left->kern_index > -1 ) 
    18375    { 
    184         table = txf->kerning + left->kern_index; 
     76        table = KERN(tf) + left->kern_index; 
    18577        while( *table ) 
    18678        { 
     
    19183            */ 
    19284            if( right->c == *table ) 
    193                 return ((char*) table)[1]; 
    194             ++table; 
    195         } 
    196     } 
    197 #else 
    198     (void) txf; 
    199     (void) left; 
    200     (void) right; 
    201 #endif 
     85                return table[1]; 
     86            table += 2; 
     87        } 
     88    } 
    20289    return 0; 
    20390} 
    20491 
    20592 
     93static void swap16( uint16_t* it, uint16_t* end ) 
     94{ 
     95    uint8_t* bp; 
     96    while( it != end ) 
     97    { 
     98        bp = (uint8_t*) it; 
     99        *it++ = (bp[0] << 8) | bp[1]; 
     100    } 
     101} 
     102 
     103 
     104/** 
     105  Swap endianess of TexFont data if not native. 
     106*/ 
     107void txf_swap( TexFont* tf ) 
     108{ 
     109    if( tf && (tf->glyph_offset == (sizeof(TexFont) << 8))  ) 
     110    { 
     111        TexGlyphInfo* tgi; 
     112        TexGlyphInfo* end; 
     113        uint16_t* it; 
     114 
     115        it = &tf->glyph_offset; 
     116        swap16( it, it + (sizeof(TexFont) / sizeof(uint16_t)) ); 
     117 
     118        tgi = GLYPHS(tf); 
     119        end = tgi + tf->glyph_count; 
     120        while( tgi != end ) 
     121        { 
     122            it = &tgi->c; 
     123            swap16( it, it + 4 ); 
     124            ++tgi; 
     125        } 
     126 
     127        it = TABLE(tf); 
     128        swap16( it, it + tf->table_size ); 
     129 
     130        it = (uint16_t*) KERN(tf); 
     131        swap16( it, it + tf->kern_size ); 
     132    } 
     133} 
     134 
     135 
    206136//---------------------------------------------------------------------------- 
    207137 
    208138 
    209139#if DUMP 
    210 void dumpCharMaps( FT_Face face ) 
     140static void dumpCharMaps( FT_Face face ) 
    211141{ 
    212142    FT_CharMap charmap; 
     
    230160 
    231161 
    232 void blitGlyphToBitmap( FT_Bitmap* src, FT_Bitmap* dst, int x, int y ) 
     162static void blitGlyphToBitmap( FT_Bitmap* src, FT_Bitmap* dst, int x, int y ) 
    233163{ 
    234164    unsigned char* s; 
     
    285215 
    286216 
    287 #ifdef KERN 
    288217/* 
    289218   Returns index into table or -1 if there is no kerning for left_glyph. 
    290219*/ 
    291 static int _loadKerning( Array* table, FT_Face face, FT_UInt left_glyph, 
     220static int _loadKerning( TexFont* tf, int space, 
     221                         FT_Face face, FT_UInt left_glyph, 
    292222                         const char* codes ) 
    293223{ 
     
    295225    FT_UInt right_glyph; 
    296226    const char* ci; 
    297     char* entry; 
    298     uint32_t start = table->used; 
    299  
    300     ci = codes; 
     227    int16_t* ktable = KERN(tf); 
     228    int16_t* entry; 
     229    uint32_t start = tf->kern_size; 
     230 
    301231    for( ci = codes; *ci != '\0'; ++ci ) 
    302232    { 
     
    309239                        //FT_KERNING_UNFITTED, FT_KERNING_UNSCALED 
    310240                        &kern ); 
    311         if( kern.x || kern.y ) 
    312         { 
    313           //printf(" %c %ld %ld\n", *ci, FT_PIXELS(kern.x), FT_PIXELS(kern.y)); 
    314  
    315             arrayReserve( table, table->used + 3 ); 
    316             entry = table->ptr + table->used; 
    317             table->used += 2; 
    318  
    319             // NOTE: kern.y is ignored since is it almost always zero. 
     241 
     242        // NOTE: kern.y is ignored since is it almost always zero. 
     243        if( kern.x /*|| kern.y*/ ) 
     244        { 
     245#ifdef DUMP 
     246            printf(" %c %ld %ld\n", *ci, FT_PIXELS(kern.x), FT_PIXELS(kern.y)); 
     247#endif 
     248            if( space < 3 ) 
     249            { 
     250                ktable[ tf->kern_size ] = 0; 
     251                fprintf( stderr, "txf_build: Kerning table full\n" ); 
     252                return -1; 
     253            } 
     254 
     255            entry = ktable + tf->kern_size; 
     256            tf->kern_size += 2; 
     257            space -= 2; 
     258 
    320259            entry[0] = *ci; 
    321260            entry[1] = FT_PIXELS(kern.x); 
     
    323262    } 
    324263 
    325     if( table->used > start ) 
     264    if( tf->kern_size > start ) 
    326265    { 
    327266        // Terminate entries. 
    328         table->ptr[ table->used ] = 0; 
    329         ++table->used; 
    330  
     267        ktable[ tf->kern_size ] = 0; 
     268        ++tf->kern_size; 
    331269        return start; 
    332270    } 
     
    334272    return -1; 
    335273} 
    336 #endif 
    337274 
    338275 
    339276/** 
    340   Returns number of glyphs added or zero if fails. 
     277  Returns TexFont pointer or zero if fails. 
    341278*/ 
    342 int txf_build( TexFont* txf, const char* file, 
    343                const char* codes, FT_Bitmap* img, int psize, int gap, 
    344                int asBitmap ) 
     279TexFont* txf_build( const char* file, const char* codes, 
     280                    FT_Bitmap* img, int psize, int gap, int antialias ) 
    345281{ 
    346282    FT_Library library; 
     
    351287    FT_F26Dot6 start_x; 
    352288    FT_F26Dot6 step_y; 
    353     FT_F26Dot6 x, y; 
    354 #ifdef KERN 
    355     Array kern; 
    356 #endif 
     289    int x, y; 
     290    int nextX; 
     291    int glyph_index; 
     292    int gmin, gmax; 
     293    int ch; 
     294    int kern_space; 
    357295    const char* ci; 
    358     int count = 0; 
     296    uint16_t* table; 
     297    TexGlyphInfo* tgi; 
     298    TexFont* txf = 0; 
     299    int count; 
    359300    int loadFailed = 0; 
    360301 
     
    362303    error = FT_Init_FreeType( &library ); 
    363304    if( error ) 
    364     { 
    365305        return 0; 
    366     } 
    367306 
    368307    error = FT_New_Face( library, file, 0, &face ); 
    369308    if( error ) 
    370     { 
    371         return 0; 
    372     } 
     309        goto cleanup_lib; 
    373310 
    374311 
    375312#if DUMP 
    376313#define EM_PIX(n)   n,FT_PIXELS(n) 
    377         printf( "FT_Face [\n" ); 
    378         printf( "  family_name:  \"%s\"\n", face->family_name ); 
    379         printf( "  style_name:   \"%s\"\n", face->style_name ); 
    380         printf( "  num_glyphs:   %ld\n",    face->num_glyphs ); 
    381         printf( "  units_per_EM: %d (%d)\n", EM_PIX(face->units_per_EM) ); 
    382         printf( "  ascender:     %d (%d)\n", EM_PIX(face->ascender) ); 
    383         printf( "  descender:    %d (%d)\n", EM_PIX(face->descender) ); 
    384         printf( "  height:       %d (%d)\n", EM_PIX(face->height) ); 
    385         dumpCharMaps( face ); 
    386         printf( "]\n" ); 
     314    printf( "FT_Face [\n" ); 
     315    printf( "  family_name:  \"%s\"\n", face->family_name ); 
     316    printf( "  style_name:   \"%s\"\n", face->style_name ); 
     317    printf( "  num_glyphs:   %ld\n",    face->num_glyphs ); 
     318    printf( "  units_per_EM: %d (%d)\n", EM_PIX(face->units_per_EM) ); 
     319    printf( "  ascender:     %d (%d)\n", EM_PIX(face->ascender) ); 
     320    printf( "  descender:    %d (%d)\n", EM_PIX(face->descender) ); 
     321    printf( "  height:       %d (%d)\n", EM_PIX(face->height) ); 
     322    dumpCharMaps( face ); 
     323    printf( "]\n" ); 
    387324#endif 
    388325 
     
    390327    error = FT_Set_Pixel_Sizes( face, psize, psize ); 
    391328    if( error ) 
    392     { 
    393         return 0; 
    394     } 
    395  
    396 #ifdef KERN 
    397     kern.ptr   = 0; 
    398     kern.avail = 0; 
    399     kern.used  = 0; 
    400 #endif 
     329        goto cleanup; 
    401330 
    402331    glyph = face->glyph; 
     
    404333 
    405334 
    406     txf_setGlyphCount( txf, face->num_glyphs ); 
     335    // Count glyphs and find the high & low. 
     336    gmin = 0xffff; 
     337    gmax = 0; 
     338    ci = codes; 
     339    while( *ci ) 
     340    { 
     341        ch = *ci++; 
     342        if( ch < gmin ) 
     343            gmin = ch; 
     344        if( ch > gmax ) 
     345            gmax = ch; 
     346    } 
     347    count = ci - codes; 
     348 
     349 
     350    // Most glyphs have no kerning adjustment, and those with it have only 
     351    // a handful (at least at small font sizes). 
     352    kern_space = count * 5;     // 5 = 2 glyphs + terminator 
     353 
     354    txf = (TexFont*) malloc(  sizeof(TexFont) + 
     355                             (sizeof(TexGlyphInfo) * count) + 
     356                             (sizeof(uint16_t) * (gmax - gmin + 1)) + 
     357                             (sizeof(int16_t) * kern_space) ); 
     358 
     359    txf->glyph_offset = sizeof(TexFont); 
     360    txf->glyph_count  = count; 
     361    txf->table_offset = (txf->glyph_offset + (sizeof(TexGlyphInfo) * count)) 
     362                            / sizeof(uint16_t); 
     363    txf->table_size   = gmax - gmin + 1; 
     364    txf->kern_offset  = txf->table_offset + txf->table_size; 
     365    txf->kern_size    = 0; 
     366 
    407367    //txf.max_ascent  = size->metrics.y_ppem; 
    408368    txf->max_ascent  =  face->ascender  * psize / face->units_per_EM; 
    409369    txf->max_descent = -face->descender * psize / face->units_per_EM; 
    410370 
    411  
    412     /* Clear bitmap */ 
     371    txf->min_glyph   = gmin; 
     372    txf->tex_width   = img->pitch; 
     373    txf->tex_height  = img->rows; 
     374 
     375    table = TABLE(txf); 
     376    memset( table, 0xff, sizeof(uint16_t) * txf->table_size ); 
     377 
     378 
     379    // Clear bitmap. 
    413380    memset( img->buffer, 0, img->rows * img->pitch ); 
    414381 
     
    420387    y = step_y; 
    421388 
     389    count = 0; 
     390    tgi = GLYPHS(txf); 
    422391    ci = codes; 
    423     for( ci = codes; *ci != '\0'; ++ci ) 
    424     { 
    425         int glyph_index = FT_Get_Char_Index( face, *ci ); 
     392    while( *ci ) 
     393    { 
     394        ch = *ci++; 
     395 
     396        glyph_index = FT_Get_Char_Index( face, ch ); 
    426397        if( glyph_index == 0 ) 
    427398        { 
    428             printf( "Code 0x%x (%c) is undefined\n", (int) *ci, (char) *ci ); 
     399            fprintf( stderr, "txf_build: Code 0x%x (%c) is undefined\n", 
     400                     ch, (char) ch ); 
    429401            continue; 
    430402        } 
    431403 
    432404        error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT ); 
    433         if( ! error ) 
    434         { 
    435             TexGlyphInfo* tgi; 
    436             int nextX = x + FT_PIXELS(glyph->metrics.width) + gap; 
    437  
    438             if( nextX > img->width ) 
     405        if( error ) 
     406        { 
     407            ++loadFailed; 
     408            continue; 
     409        } 
     410 
     411        nextX = x + FT_PIXELS(glyph->metrics.width) + gap; 
     412 
     413        if( nextX > img->width ) 
     414        { 
     415            x  = start_x; 
     416            y += step_y; 
     417 
     418            //if( (y + step_y) >= img->rows ) 
     419            if( y >= img->rows ) 
    439420            { 
    440                 x  = start_x; 
    441                 y += step_y; 
    442  
    443                 //if( (y + step_y) >= img->rows ) 
    444                 if( y >= img->rows ) 
    445                 { 
    446                     fprintf(stderr, "** Texture too small\n"); 
    447                     break; 
    448                 } 
    449  
    450                 nextX = x + FT_PIXELS(glyph->metrics.width) + gap; 
     421                fprintf( stderr, "txf_build: Texture too small\n" ); 
     422                break; 
    451423            } 
    452424 
    453             _renderGlyph( img, glyph, x, y, ! asBitmap ); 
    454  
    455             tgi = txf->tgi + count; 
    456             count++; 
    457  
    458             tgi->c       = *ci; 
    459             tgi->width   = FT_PIXELS(glyph->metrics.width); 
    460             tgi->height  = FT_PIXELS(glyph->metrics.height); 
    461             tgi->xoffset = FT_PIXELS(glyph->metrics.horiBearingX); 
    462             tgi->yoffset = FT_PIXELS(glyph->metrics.horiBearingY) - tgi->height; 
    463             tgi->advance = FT_PIXELS(glyph->metrics.horiAdvance); 
    464             tgi->x       = x /*+ tgi->xoffset*/; 
    465             tgi->y       = img->rows - y + tgi->yoffset; 
     425            nextX = x + FT_PIXELS(glyph->metrics.width) + gap; 
     426        } 
     427 
     428        _renderGlyph( img, glyph, x, y, antialias ); 
     429 
     430        tgi->c       = ch; 
     431        tgi->width   = FT_PIXELS(glyph->metrics.width); 
     432        tgi->height  = FT_PIXELS(glyph->metrics.height); 
     433        tgi->xoffset = FT_PIXELS(glyph->metrics.horiBearingX); 
     434        tgi->yoffset = FT_PIXELS(glyph->metrics.horiBearingY) - tgi->height; 
     435        tgi->advance = FT_PIXELS(glyph->metrics.horiAdvance); 
     436        tgi->x       = x /*+ tgi->xoffset*/; 
     437        tgi->y       = img->rows - y + tgi->yoffset; 
     438 
     439#ifdef DUMP 
     440            printf( "Glyph %c %d,%d %d,%d %d %d,%d\n", ch, 
     441                    tgi->width, tgi->height, 
     442                    tgi->xoffset, tgi->yoffset, 
     443                    tgi->advance, tgi->x, tgi->y ); 
     444#endif 
     445 
     446        table[ ch - txf->min_glyph ] = count++; 
     447 
     448        if( FT_HAS_KERNING( face ) ) 
     449        { 
     450#ifdef DUMP 
     451            printf( "Kern %c\n", ch ); 
     452#endif 
     453            tgi->kern_index = _loadKerning( txf, 
     454                                            kern_space - txf->kern_size, 
     455                                            face, glyph_index, codes ); 
     456        } 
     457        else 
     458        { 
    466459            tgi->kern_index = -1; 
    467  
    468 #ifdef KERN 
    469             if( FT_HAS_KERNING( face ) ) 
    470             { 
    471                 //printf( "KR Kern %c\n", *ci ); 
    472                 tgi->kern_index = _loadKerning(&kern, face, glyph_index, codes); 
    473             } 
    474 #endif 
    475  
    476             x = nextX; 
    477         }