~ubuntu-branches/ubuntu/wily/qtbase-opensource-src/wily

« back to all changes in this revision

Viewing changes to src/3rdparty/freetype/src/pfr/pfrsbit.c

  • Committer: Package Import Robot
  • Author(s): Timo Jyrinki
  • Date: 2013-02-05 12:46:17 UTC
  • Revision ID: package-import@ubuntu.com-20130205124617-c8jouts182j002fx
Tags: upstream-5.0.1+dfsg
ImportĀ upstreamĀ versionĀ 5.0.1+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************/
 
2
/*                                                                         */
 
3
/*  pfrsbit.c                                                              */
 
4
/*                                                                         */
 
5
/*    FreeType PFR bitmap loader (body).                                   */
 
6
/*                                                                         */
 
7
/*  Copyright 2002, 2003, 2006 by                                          */
 
8
/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 
9
/*                                                                         */
 
10
/*  This file is part of the FreeType project, and may only be used,       */
 
11
/*  modified, and distributed under the terms of the FreeType project      */
 
12
/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
 
13
/*  this file you indicate that you have read the license and              */
 
14
/*  understand and accept it fully.                                        */
 
15
/*                                                                         */
 
16
/***************************************************************************/
 
17
 
 
18
 
 
19
#include "pfrsbit.h"
 
20
#include "pfrload.h"
 
21
#include FT_INTERNAL_DEBUG_H
 
22
#include FT_INTERNAL_STREAM_H
 
23
 
 
24
#include "pfrerror.h"
 
25
 
 
26
#undef  FT_COMPONENT
 
27
#define FT_COMPONENT  trace_pfr
 
28
 
 
29
 
 
30
  /*************************************************************************/
 
31
  /*************************************************************************/
 
32
  /*****                                                               *****/
 
33
  /*****                      PFR BIT WRITER                           *****/
 
34
  /*****                                                               *****/
 
35
  /*************************************************************************/
 
36
  /*************************************************************************/
 
37
 
 
38
  typedef struct  PFR_BitWriter_
 
39
  {
 
40
    FT_Byte*  line;      /* current line start                    */
 
41
    FT_Int    pitch;     /* line size in bytes                    */
 
42
    FT_Int    width;     /* width in pixels/bits                  */
 
43
    FT_Int    rows;      /* number of remaining rows to scan      */
 
44
    FT_Int    total;     /* total number of bits to draw          */
 
45
 
 
46
  } PFR_BitWriterRec, *PFR_BitWriter;
 
47
 
 
48
 
 
49
  static void
 
50
  pfr_bitwriter_init( PFR_BitWriter  writer,
 
51
                      FT_Bitmap*     target,
 
52
                      FT_Bool        decreasing )
 
53
  {
 
54
    writer->line   = target->buffer;
 
55
    writer->pitch  = target->pitch;
 
56
    writer->width  = target->width;
 
57
    writer->rows   = target->rows;
 
58
    writer->total  = writer->width * writer->rows;
 
59
 
 
60
    if ( !decreasing )
 
61
    {
 
62
      writer->line += writer->pitch * ( target->rows-1 );
 
63
      writer->pitch = -writer->pitch;
 
64
    }
 
65
  }
 
66
 
 
67
 
 
68
  static void
 
69
  pfr_bitwriter_decode_bytes( PFR_BitWriter  writer,
 
70
                              FT_Byte*       p,
 
71
                              FT_Byte*       limit )
 
72
  {
 
73
    FT_Int    n, reload;
 
74
    FT_Int    left = writer->width;
 
75
    FT_Byte*  cur  = writer->line;
 
76
    FT_UInt   mask = 0x80;
 
77
    FT_UInt   val  = 0;
 
78
    FT_UInt   c    = 0;
 
79
 
 
80
 
 
81
    n = (FT_Int)( limit - p ) * 8;
 
82
    if ( n > writer->total )
 
83
      n = writer->total;
 
84
 
 
85
    reload = n & 7;
 
86
 
 
87
    for ( ; n > 0; n-- )
 
88
    {
 
89
      if ( ( n & 7 ) == reload )
 
90
        val = *p++;
 
91
 
 
92
      if ( val & 0x80 )
 
93
        c |= mask;
 
94
 
 
95
      val  <<= 1;
 
96
      mask >>= 1;
 
97
 
 
98
      if ( --left <= 0 )
 
99
      {
 
100
        cur[0] = (FT_Byte)c;
 
101
        left   = writer->width;
 
102
        mask   = 0x80;
 
103
 
 
104
        writer->line += writer->pitch;
 
105
        cur           = writer->line;
 
106
        c             = 0;
 
107
      }
 
108
      else if ( mask == 0 )
 
109
      {
 
110
        cur[0] = (FT_Byte)c;
 
111
        mask   = 0x80;
 
112
        c      = 0;
 
113
        cur ++;
 
114
      }
 
115
    }
 
116
 
 
117
    if ( mask != 0x80 )
 
118
      cur[0] = (FT_Byte)c;
 
119
  }
 
120
 
 
121
 
 
122
  static void
 
123
  pfr_bitwriter_decode_rle1( PFR_BitWriter  writer,
 
124
                             FT_Byte*       p,
 
125
                             FT_Byte*       limit )
 
126
  {
 
127
    FT_Int    n, phase, count, counts[2], reload;
 
128
    FT_Int    left = writer->width;
 
129
    FT_Byte*  cur  = writer->line;
 
130
    FT_UInt   mask = 0x80;
 
131
    FT_UInt   c    = 0;
 
132
 
 
133
 
 
134
    n = writer->total;
 
135
 
 
136
    phase     = 1;
 
137
    counts[0] = 0;
 
138
    counts[1] = 0;
 
139
    count     = 0;
 
140
    reload    = 1;
 
141
 
 
142
    for ( ; n > 0; n-- )
 
143
    {
 
144
      if ( reload )
 
145
      {
 
146
        do
 
147
        {
 
148
          if ( phase )
 
149
          {
 
150
            FT_Int  v;
 
151
 
 
152
 
 
153
            if ( p >= limit )
 
154
              break;
 
155
 
 
156
            v         = *p++;
 
157
            counts[0] = v >> 4;
 
158
            counts[1] = v & 15;
 
159
            phase     = 0;
 
160
            count     = counts[0];
 
161
          }
 
162
          else
 
163
          {
 
164
            phase = 1;
 
165
            count = counts[1];
 
166
          }
 
167
 
 
168
        } while ( count == 0 );
 
169
      }
 
170
 
 
171
      if ( phase )
 
172
        c |= mask;
 
173
 
 
174
      mask >>= 1;
 
175
 
 
176
      if ( --left <= 0 )
 
177
      {
 
178
        cur[0] = (FT_Byte) c;
 
179
        left   = writer->width;
 
180
        mask   = 0x80;
 
181
 
 
182
        writer->line += writer->pitch;
 
183
        cur           = writer->line;
 
184
        c             = 0;
 
185
      }
 
186
      else if ( mask == 0 )
 
187
      {
 
188
        cur[0] = (FT_Byte)c;
 
189
        mask   = 0x80;
 
190
        c      = 0;
 
191
        cur ++;
 
192
      }
 
193
 
 
194
      reload = ( --count <= 0 );
 
195
    }
 
196
 
 
197
    if ( mask != 0x80 )
 
198
      cur[0] = (FT_Byte) c;
 
199
  }
 
200
 
 
201
 
 
202
  static void
 
203
  pfr_bitwriter_decode_rle2( PFR_BitWriter  writer,
 
204
                             FT_Byte*       p,
 
205
                             FT_Byte*       limit )
 
206
  {
 
207
    FT_Int    n, phase, count, reload;
 
208
    FT_Int    left = writer->width;
 
209
    FT_Byte*  cur  = writer->line;
 
210
    FT_UInt   mask = 0x80;
 
211
    FT_UInt   c    = 0;
 
212
 
 
213
 
 
214
    n = writer->total;
 
215
 
 
216
    phase  = 1;
 
217
    count  = 0;
 
218
    reload = 1;
 
219
 
 
220
    for ( ; n > 0; n-- )
 
221
    {
 
222
      if ( reload )
 
223
      {
 
224
        do
 
225
        {
 
226
          if ( p >= limit )
 
227
            break;
 
228
 
 
229
          count = *p++;
 
230
          phase = phase ^ 1;
 
231
 
 
232
        } while ( count == 0 );
 
233
      }
 
234
 
 
235
      if ( phase )
 
236
        c |= mask;
 
237
 
 
238
      mask >>= 1;
 
239
 
 
240
      if ( --left <= 0 )
 
241
      {
 
242
        cur[0] = (FT_Byte) c;
 
243
        c      = 0;
 
244
        mask   = 0x80;
 
245
        left   = writer->width;
 
246
 
 
247
        writer->line += writer->pitch;
 
248
        cur           = writer->line;
 
249
      }
 
250
      else if ( mask == 0 )
 
251
      {
 
252
        cur[0] = (FT_Byte)c;
 
253
        c      = 0;
 
254
        mask   = 0x80;
 
255
        cur ++;
 
256
      }
 
257
 
 
258
      reload = ( --count <= 0 );
 
259
    }
 
260
 
 
261
    if ( mask != 0x80 )
 
262
      cur[0] = (FT_Byte) c;
 
263
  }
 
264
 
 
265
 
 
266
  /*************************************************************************/
 
267
  /*************************************************************************/
 
268
  /*****                                                               *****/
 
269
  /*****                  BITMAP DATA DECODING                         *****/
 
270
  /*****                                                               *****/
 
271
  /*************************************************************************/
 
272
  /*************************************************************************/
 
273
 
 
274
  static void
 
275
  pfr_lookup_bitmap_data( FT_Byte*   base,
 
276
                          FT_Byte*   limit,
 
277
                          FT_UInt    count,
 
278
                          FT_UInt    flags,
 
279
                          FT_UInt    char_code,
 
280
                          FT_ULong*  found_offset,
 
281
                          FT_ULong*  found_size )
 
282
  {
 
283
    FT_UInt   left, right, char_len;
 
284
    FT_Bool   two = FT_BOOL( flags & 1 );
 
285
    FT_Byte*  buff;
 
286
 
 
287
 
 
288
    char_len = 4;
 
289
    if ( two )       char_len += 1;
 
290
    if ( flags & 2 ) char_len += 1;
 
291
    if ( flags & 4 ) char_len += 1;
 
292
 
 
293
    left  = 0;
 
294
    right = count;
 
295
 
 
296
    while ( left < right )
 
297
    {
 
298
      FT_UInt  middle, code;
 
299
 
 
300
 
 
301
      middle = ( left + right ) >> 1;
 
302
      buff   = base + middle * char_len;
 
303
 
 
304
      /* check that we are not outside of the table -- */
 
305
      /* this is possible with broken fonts...         */
 
306
      if ( buff + char_len > limit )
 
307
        goto Fail;
 
308
 
 
309
      if ( two )
 
310
        code = PFR_NEXT_USHORT( buff );
 
311
      else
 
312
        code = PFR_NEXT_BYTE( buff );
 
313
 
 
314
      if ( code == char_code )
 
315
        goto Found_It;
 
316
 
 
317
      if ( code < char_code )
 
318
        left = middle;
 
319
      else
 
320
        right = middle;
 
321
    }
 
322
 
 
323
  Fail:
 
324
    /* Not found */
 
325
    *found_size   = 0;
 
326
    *found_offset = 0;
 
327
    return;
 
328
 
 
329
  Found_It:
 
330
    if ( flags & 2 )
 
331
      *found_size = PFR_NEXT_USHORT( buff );
 
332
    else
 
333
      *found_size = PFR_NEXT_BYTE( buff );
 
334
 
 
335
    if ( flags & 4 )
 
336
      *found_offset = PFR_NEXT_ULONG( buff );
 
337
    else
 
338
      *found_offset = PFR_NEXT_USHORT( buff );
 
339
  }
 
340
 
 
341
 
 
342
  /* load bitmap metrics.  "*padvance" must be set to the default value */
 
343
  /* before calling this function...                                    */
 
344
  /*                                                                    */
 
345
  static FT_Error
 
346
  pfr_load_bitmap_metrics( FT_Byte**  pdata,
 
347
                           FT_Byte*   limit,
 
348
                           FT_Long    scaled_advance,
 
349
                           FT_Long   *axpos,
 
350
                           FT_Long   *aypos,
 
351
                           FT_UInt   *axsize,
 
352
                           FT_UInt   *aysize,
 
353
                           FT_Long   *aadvance,
 
354
                           FT_UInt   *aformat )
 
355
  {
 
356
    FT_Error  error = 0;
 
357
    FT_Byte   flags;
 
358
    FT_Char   b;
 
359
    FT_Byte*  p = *pdata;
 
360
    FT_Long   xpos, ypos, advance;
 
361
    FT_UInt   xsize, ysize;
 
362
 
 
363
 
 
364
    PFR_CHECK( 1 );
 
365
    flags = PFR_NEXT_BYTE( p );
 
366
 
 
367
    xpos    = 0;
 
368
    ypos    = 0;
 
369
    xsize   = 0;
 
370
    ysize   = 0;
 
371
    advance = 0;
 
372
 
 
373
    switch ( flags & 3 )
 
374
    {
 
375
    case 0:
 
376
      PFR_CHECK( 1 );
 
377
      b    = PFR_NEXT_INT8( p );
 
378
      xpos = b >> 4;
 
379
      ypos = ( (FT_Char)( b << 4 ) ) >> 4;
 
380
      break;
 
381
 
 
382
    case 1:
 
383
      PFR_CHECK( 2 );
 
384
      xpos = PFR_NEXT_INT8( p );
 
385
      ypos = PFR_NEXT_INT8( p );
 
386
      break;
 
387
 
 
388
    case 2:
 
389
      PFR_CHECK( 4 );
 
390
      xpos = PFR_NEXT_SHORT( p );
 
391
      ypos = PFR_NEXT_SHORT( p );
 
392
      break;
 
393
 
 
394
    case 3:
 
395
      PFR_CHECK( 6 );
 
396
      xpos = PFR_NEXT_LONG( p );
 
397
      ypos = PFR_NEXT_LONG( p );
 
398
      break;
 
399
 
 
400
    default:
 
401
      ;
 
402
    }
 
403
 
 
404
    flags >>= 2;
 
405
    switch ( flags & 3 )
 
406
    {
 
407
    case 0:
 
408
      /* blank image */
 
409
      xsize = 0;
 
410
      ysize = 0;
 
411
      break;
 
412
 
 
413
    case 1:
 
414
      PFR_CHECK( 1 );
 
415
      b     = PFR_NEXT_BYTE( p );
 
416
      xsize = ( b >> 4 ) & 0xF;
 
417
      ysize = b & 0xF;
 
418
      break;
 
419
 
 
420
    case 2:
 
421
      PFR_CHECK( 2 );
 
422
      xsize = PFR_NEXT_BYTE( p );
 
423
      ysize = PFR_NEXT_BYTE( p );
 
424
      break;
 
425
 
 
426
    case 3:
 
427
      PFR_CHECK( 4 );
 
428
      xsize = PFR_NEXT_USHORT( p );
 
429
      ysize = PFR_NEXT_USHORT( p );
 
430
      break;
 
431
 
 
432
    default:
 
433
      ;
 
434
    }
 
435
 
 
436
    flags >>= 2;
 
437
    switch ( flags & 3 )
 
438
    {
 
439
    case 0:
 
440
      advance = scaled_advance;
 
441
      break;
 
442
 
 
443
    case 1:
 
444
      PFR_CHECK( 1 );
 
445
      advance = PFR_NEXT_INT8( p ) << 8;
 
446
      break;
 
447
 
 
448
    case 2:
 
449
      PFR_CHECK( 2 );
 
450
      advance = PFR_NEXT_SHORT( p );
 
451
      break;
 
452
 
 
453
    case 3:
 
454
      PFR_CHECK( 3 );
 
455
      advance = PFR_NEXT_LONG( p );
 
456
      break;
 
457
 
 
458
    default:
 
459
      ;
 
460
    }
 
461
 
 
462
    *axpos    = xpos;
 
463
    *aypos    = ypos;
 
464
    *axsize   = xsize;
 
465
    *aysize   = ysize;
 
466
    *aadvance = advance;
 
467
    *aformat  = flags >> 2;
 
468
    *pdata    = p;
 
469
 
 
470
  Exit:
 
471
    return error;
 
472
 
 
473
  Too_Short:
 
474
    error = PFR_Err_Invalid_Table;
 
475
    FT_ERROR(( "pfr_load_bitmap_metrics: invalid glyph data\n" ));
 
476
    goto Exit;
 
477
  }
 
478
 
 
479
 
 
480
  static FT_Error
 
481
  pfr_load_bitmap_bits( FT_Byte*    p,
 
482
                        FT_Byte*    limit,
 
483
                        FT_UInt     format,
 
484
                        FT_Bool     decreasing,
 
485
                        FT_Bitmap*  target )
 
486
  {
 
487
    FT_Error          error = 0;
 
488
    PFR_BitWriterRec  writer;
 
489
 
 
490
 
 
491
    if ( target->rows > 0 && target->width > 0 )
 
492
    {
 
493
      pfr_bitwriter_init( &writer, target, decreasing );
 
494
 
 
495
      switch ( format )
 
496
      {
 
497
      case 0: /* packed bits */
 
498
        pfr_bitwriter_decode_bytes( &writer, p, limit );
 
499
        break;
 
500
 
 
501
      case 1: /* RLE1 */
 
502
        pfr_bitwriter_decode_rle1( &writer, p, limit );
 
503
        break;
 
504
 
 
505
      case 2: /* RLE2 */
 
506
        pfr_bitwriter_decode_rle2( &writer, p, limit );
 
507
        break;
 
508
 
 
509
      default:
 
510
        FT_ERROR(( "pfr_read_bitmap_data: invalid image type\n" ));
 
511
        error = PFR_Err_Invalid_File_Format;
 
512
      }
 
513
    }
 
514
 
 
515
    return error;
 
516
  }
 
517
 
 
518
 
 
519
  /*************************************************************************/
 
520
  /*************************************************************************/
 
521
  /*****                                                               *****/
 
522
  /*****                     BITMAP LOADING                            *****/
 
523
  /*****                                                               *****/
 
524
  /*************************************************************************/
 
525
  /*************************************************************************/
 
526
 
 
527
  FT_LOCAL( FT_Error )
 
528
  pfr_slot_load_bitmap( PFR_Slot  glyph,
 
529
                        PFR_Size  size,
 
530
                        FT_UInt   glyph_index )
 
531
  {
 
532
    FT_Error     error;
 
533
    PFR_Face     face   = (PFR_Face) glyph->root.face;
 
534
    FT_Stream    stream = face->root.stream;
 
535
    PFR_PhyFont  phys   = &face->phy_font;
 
536
    FT_ULong     gps_offset;
 
537
    FT_ULong     gps_size;
 
538
    PFR_Char     character;
 
539
    PFR_Strike   strike;
 
540
 
 
541
 
 
542
    character = &phys->chars[glyph_index];
 
543
 
 
544
    /* Look-up a bitmap strike corresponding to the current */
 
545
    /* character dimensions                                 */
 
546
    {
 
547
      FT_UInt  n;
 
548
 
 
549
 
 
550
      strike = phys->strikes;
 
551
      for ( n = 0; n < phys->num_strikes; n++ )
 
552
      {
 
553
        if ( strike->x_ppm == (FT_UInt)size->root.metrics.x_ppem &&
 
554
             strike->y_ppm == (FT_UInt)size->root.metrics.y_ppem )
 
555
        {
 
556
          goto Found_Strike;
 
557
        }
 
558
 
 
559
        strike++;
 
560
      }
 
561
 
 
562
      /* couldn't find it */
 
563
      return PFR_Err_Invalid_Argument;
 
564
    }
 
565
 
 
566
  Found_Strike:
 
567
 
 
568
    /* Now lookup the glyph's position within the file */
 
569
    {
 
570
      FT_UInt  char_len;
 
571
 
 
572
 
 
573
      char_len = 4;
 
574
      if ( strike->flags & 1 ) char_len += 1;
 
575
      if ( strike->flags & 2 ) char_len += 1;
 
576
      if ( strike->flags & 4 ) char_len += 1;
 
577
 
 
578
      /* Access data directly in the frame to speed lookups */
 
579
      if ( FT_STREAM_SEEK( phys->bct_offset + strike->bct_offset ) ||
 
580
           FT_FRAME_ENTER( char_len * strike->num_bitmaps )        )
 
581
        goto Exit;
 
582
 
 
583
      pfr_lookup_bitmap_data( stream->cursor,
 
584
                              stream->limit,
 
585
                              strike->num_bitmaps,
 
586
                              strike->flags,
 
587
                              character->char_code,
 
588
                              &gps_offset,
 
589
                              &gps_size );
 
590
 
 
591
      FT_FRAME_EXIT();
 
592
 
 
593
      if ( gps_size == 0 )
 
594
      {
 
595
        /* Could not find a bitmap program string for this glyph */
 
596
        error = PFR_Err_Invalid_Argument;
 
597
        goto Exit;
 
598
      }
 
599
    }
 
600
 
 
601
    /* get the bitmap metrics */
 
602
    {
 
603
      FT_Long   xpos, ypos, advance;
 
604
      FT_UInt   xsize, ysize, format;
 
605
      FT_Byte*  p;
 
606
 
 
607
 
 
608
      /* compute linear advance */
 
609
      advance = character->advance;
 
610
      if ( phys->metrics_resolution != phys->outline_resolution )
 
611
        advance = FT_MulDiv( advance,
 
612
                             phys->outline_resolution,
 
613
                             phys->metrics_resolution );
 
614
 
 
615
      glyph->root.linearHoriAdvance = advance;
 
616
 
 
617
      /* compute default advance, i.e., scaled advance.  This can be */
 
618
      /* overridden in the bitmap header of certain glyphs.          */
 
619
      advance = FT_MulDiv( (FT_Fixed)size->root.metrics.x_ppem << 8,
 
620
                           character->advance,
 
621
                           phys->metrics_resolution );
 
622
 
 
623
      if ( FT_STREAM_SEEK( face->header.gps_section_offset + gps_offset ) ||
 
624
           FT_FRAME_ENTER( gps_size )                                     )
 
625
        goto Exit;
 
626
 
 
627
      p     = stream->cursor;
 
628
      error = pfr_load_bitmap_metrics( &p, stream->limit,
 
629
                                       advance,
 
630
                                       &xpos, &ypos,
 
631
                                       &xsize, &ysize,
 
632
                                       &advance, &format );
 
633
      if ( !error )
 
634
      {
 
635
        glyph->root.format = FT_GLYPH_FORMAT_BITMAP;
 
636
 
 
637
        /* Set up glyph bitmap and metrics */
 
638
        glyph->root.bitmap.width      = (FT_Int)xsize;
 
639
        glyph->root.bitmap.rows       = (FT_Int)ysize;
 
640
        glyph->root.bitmap.pitch      = (FT_Long)( xsize + 7 ) >> 3;
 
641
        glyph->root.bitmap.pixel_mode = FT_PIXEL_MODE_MONO;
 
642
 
 
643
        glyph->root.metrics.width        = (FT_Long)xsize << 6;
 
644
        glyph->root.metrics.height       = (FT_Long)ysize << 6;
 
645
        glyph->root.metrics.horiBearingX = xpos << 6;
 
646
        glyph->root.metrics.horiBearingY = ypos << 6;
 
647
        glyph->root.metrics.horiAdvance  = FT_PIX_ROUND( ( advance >> 2 ) );
 
648
        glyph->root.metrics.vertBearingX = - glyph->root.metrics.width >> 1;
 
649
        glyph->root.metrics.vertBearingY = 0;
 
650
        glyph->root.metrics.vertAdvance  = size->root.metrics.height;
 
651
 
 
652
        glyph->root.bitmap_left = xpos;
 
653
        glyph->root.bitmap_top  = ypos + ysize;
 
654
 
 
655
        /* Allocate and read bitmap data */
 
656
        {
 
657
          FT_ULong  len = glyph->root.bitmap.pitch * ysize;
 
658
 
 
659
 
 
660
          error = ft_glyphslot_alloc_bitmap( &glyph->root, len );
 
661
          if ( !error )
 
662
          {
 
663
            error = pfr_load_bitmap_bits(
 
664
                      p,
 
665
                      stream->limit,
 
666
                      format,
 
667
                      FT_BOOL(face->header.color_flags & 2),
 
668
                      &glyph->root.bitmap );
 
669
          }
 
670
        }
 
671
      }
 
672
 
 
673
      FT_FRAME_EXIT();
 
674
    }
 
675
 
 
676
  Exit:
 
677
    return error;
 
678
  }
 
679
 
 
680
/* END */