| OLD | NEW |
| 1 /***************************************************************************/ | 1 /***************************************************************************/ |
| 2 /* */ | 2 /* */ |
| 3 /* sfobjs.c */ | 3 /* sfobjs.c */ |
| 4 /* */ | 4 /* */ |
| 5 /* SFNT object management (base). */ | 5 /* SFNT object management (base). */ |
| 6 /* */ | 6 /* */ |
| 7 /* Copyright 1996-2008, 2010-2014 by */ | 7 /* Copyright 1996-2015 by */ |
| 8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ | 8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ |
| 9 /* */ | 9 /* */ |
| 10 /* This file is part of the FreeType project, and may only be used, */ | 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 */ | 11 /* modified, and distributed under the terms of the FreeType project */ |
| 12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ | 12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ |
| 13 /* this file you indicate that you have read the license and */ | 13 /* this file you indicate that you have read the license and */ |
| 14 /* understand and accept it fully. */ | 14 /* understand and accept it fully. */ |
| 15 /* */ | 15 /* */ |
| 16 /***************************************************************************/ | 16 /***************************************************************************/ |
| 17 | 17 |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 113 string[n] = 0; | 113 string[n] = 0; |
| 114 | 114 |
| 115 return string; | 115 return string; |
| 116 } | 116 } |
| 117 | 117 |
| 118 | 118 |
| 119 typedef FT_String* (*TT_NameEntry_ConvertFunc)( TT_NameEntry entry, | 119 typedef FT_String* (*TT_NameEntry_ConvertFunc)( TT_NameEntry entry, |
| 120 FT_Memory memory ); | 120 FT_Memory memory ); |
| 121 | 121 |
| 122 | 122 |
| 123 /*************************************************************************/ | 123 /* documentation is in sfnt.h */ |
| 124 /* */ | 124 |
| 125 /* <Function> */ | 125 FT_LOCAL_DEF( FT_Error ) |
| 126 /* tt_face_get_name */ | |
| 127 /* */ | |
| 128 /* <Description> */ | |
| 129 /* Returns a given ENGLISH name record in ASCII. */ | |
| 130 /* */ | |
| 131 /* <Input> */ | |
| 132 /* face :: A handle to the source face object. */ | |
| 133 /* */ | |
| 134 /* nameid :: The name id of the name record to return. */ | |
| 135 /* */ | |
| 136 /* <InOut> */ | |
| 137 /* name :: The address of a string pointer. NULL if no name is */ | |
| 138 /* present. */ | |
| 139 /* */ | |
| 140 /* <Return> */ | |
| 141 /* FreeType error code. 0 means success. */ | |
| 142 /* */ | |
| 143 static FT_Error | |
| 144 tt_face_get_name( TT_Face face, | 126 tt_face_get_name( TT_Face face, |
| 145 FT_UShort nameid, | 127 FT_UShort nameid, |
| 146 FT_String** name ) | 128 FT_String** name ) |
| 147 { | 129 { |
| 148 FT_Memory memory = face->root.memory; | 130 FT_Memory memory = face->root.memory; |
| 149 FT_Error error = FT_Err_Ok; | 131 FT_Error error = FT_Err_Ok; |
| 150 FT_String* result = NULL; | 132 FT_String* result = NULL; |
| 151 FT_UShort n; | 133 FT_UShort n; |
| 152 TT_NameEntryRec* rec; | 134 TT_NameEntryRec* rec; |
| 153 FT_Int found_apple = -1; | 135 FT_Int found_apple = -1; |
| (...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 369 | 351 |
| 370 static void | 352 static void |
| 371 sfnt_stream_close( FT_Stream stream ) | 353 sfnt_stream_close( FT_Stream stream ) |
| 372 { | 354 { |
| 373 FT_Memory memory = stream->memory; | 355 FT_Memory memory = stream->memory; |
| 374 | 356 |
| 375 | 357 |
| 376 FT_FREE( stream->base ); | 358 FT_FREE( stream->base ); |
| 377 | 359 |
| 378 stream->size = 0; | 360 stream->size = 0; |
| 379 stream->base = 0; | 361 stream->base = NULL; |
| 380 stream->close = 0; | 362 stream->close = NULL; |
| 381 } | 363 } |
| 382 | 364 |
| 383 | 365 |
| 384 FT_CALLBACK_DEF( int ) | 366 FT_CALLBACK_DEF( int ) |
| 385 compare_offsets( const void* a, | 367 compare_offsets( const void* a, |
| 386 const void* b ) | 368 const void* b ) |
| 387 { | 369 { |
| 388 WOFF_Table table1 = *(WOFF_Table*)a; | 370 WOFF_Table table1 = *(WOFF_Table*)a; |
| 389 WOFF_Table table2 = *(WOFF_Table*)b; | 371 WOFF_Table table2 = *(WOFF_Table*)b; |
| 390 | 372 |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 573 sfnt_offset > woff.totalSfntSize - table->OrigLength || | 555 sfnt_offset > woff.totalSfntSize - table->OrigLength || |
| 574 table->CompLength > table->OrigLength ) | 556 table->CompLength > table->OrigLength ) |
| 575 { | 557 { |
| 576 error = FT_THROW( Invalid_Table ); | 558 error = FT_THROW( Invalid_Table ); |
| 577 goto Exit; | 559 goto Exit; |
| 578 } | 560 } |
| 579 | 561 |
| 580 table->OrigOffset = sfnt_offset; | 562 table->OrigOffset = sfnt_offset; |
| 581 | 563 |
| 582 /* The offsets must be multiples of 4. */ | 564 /* The offsets must be multiples of 4. */ |
| 583 woff_offset += ( table->CompLength + 3 ) & ~3; | 565 woff_offset += ( table->CompLength + 3 ) & ~3U; |
| 584 sfnt_offset += ( table->OrigLength + 3 ) & ~3; | 566 sfnt_offset += ( table->OrigLength + 3 ) & ~3U; |
| 585 } | 567 } |
| 586 | 568 |
| 587 /* | 569 /* |
| 588 * Final checks! | 570 * Final checks! |
| 589 * | 571 * |
| 590 * We don't decode and check the metadata block. | 572 * We don't decode and check the metadata block. |
| 591 * We don't check table checksums either. | 573 * We don't check table checksums either. |
| 592 * But other than those, I think we implement all | 574 * But other than those, I think we implement all |
| 593 * `MUST' checks from the spec. | 575 * `MUST' checks from the spec. |
| 594 */ | 576 */ |
| 595 | 577 |
| 596 if ( woff.metaOffset ) | 578 if ( woff.metaOffset ) |
| 597 { | 579 { |
| 598 if ( woff.metaOffset != woff_offset || | 580 if ( woff.metaOffset != woff_offset || |
| 599 woff.metaOffset + woff.metaLength > woff.length ) | 581 woff.metaOffset + woff.metaLength > woff.length ) |
| 600 { | 582 { |
| 601 error = FT_THROW( Invalid_Table ); | 583 error = FT_THROW( Invalid_Table ); |
| 602 goto Exit; | 584 goto Exit; |
| 603 } | 585 } |
| 604 | 586 |
| 605 /* We have padding only ... */ | 587 /* We have padding only ... */ |
| 606 woff_offset += woff.metaLength; | 588 woff_offset += woff.metaLength; |
| 607 } | 589 } |
| 608 | 590 |
| 609 if ( woff.privOffset ) | 591 if ( woff.privOffset ) |
| 610 { | 592 { |
| 611 /* ... if it isn't the last block. */ | 593 /* ... if it isn't the last block. */ |
| 612 woff_offset = ( woff_offset + 3 ) & ~3; | 594 woff_offset = ( woff_offset + 3 ) & ~3U; |
| 613 | 595 |
| 614 if ( woff.privOffset != woff_offset || | 596 if ( woff.privOffset != woff_offset || |
| 615 woff.privOffset + woff.privLength > woff.length ) | 597 woff.privOffset + woff.privLength > woff.length ) |
| 616 { | 598 { |
| 617 error = FT_THROW( Invalid_Table ); | 599 error = FT_THROW( Invalid_Table ); |
| 618 goto Exit; | 600 goto Exit; |
| 619 } | 601 } |
| 620 | 602 |
| 621 /* No padding for the last block. */ | 603 /* No padding for the last block. */ |
| 622 woff_offset += woff.privLength; | 604 woff_offset += woff.privLength; |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 832 face->ttc_header.offsets[0] = offset; | 814 face->ttc_header.offsets[0] = offset; |
| 833 } | 815 } |
| 834 | 816 |
| 835 return error; | 817 return error; |
| 836 } | 818 } |
| 837 | 819 |
| 838 | 820 |
| 839 FT_LOCAL_DEF( FT_Error ) | 821 FT_LOCAL_DEF( FT_Error ) |
| 840 sfnt_init_face( FT_Stream stream, | 822 sfnt_init_face( FT_Stream stream, |
| 841 TT_Face face, | 823 TT_Face face, |
| 842 FT_Int face_index, | 824 FT_Int face_instance_index, |
| 843 FT_Int num_params, | 825 FT_Int num_params, |
| 844 FT_Parameter* params ) | 826 FT_Parameter* params ) |
| 845 { | 827 { |
| 846 FT_Error error; | 828 FT_Error error; |
| 847 FT_Library library = face->root.driver->root.library; | 829 FT_Library library = face->root.driver->root.library; |
| 848 SFNT_Service sfnt; | 830 SFNT_Service sfnt; |
| 831 FT_Int face_index; |
| 849 | 832 |
| 850 | 833 |
| 851 /* for now, parameters are unused */ | 834 /* for now, parameters are unused */ |
| 852 FT_UNUSED( num_params ); | 835 FT_UNUSED( num_params ); |
| 853 FT_UNUSED( params ); | 836 FT_UNUSED( params ); |
| 854 | 837 |
| 855 | 838 |
| 856 sfnt = (SFNT_Service)face->sfnt; | 839 sfnt = (SFNT_Service)face->sfnt; |
| 857 if ( !sfnt ) | 840 if ( !sfnt ) |
| 858 { | 841 { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 871 | 854 |
| 872 FT_TRACE2(( "SFNT driver\n" )); | 855 FT_TRACE2(( "SFNT driver\n" )); |
| 873 | 856 |
| 874 error = sfnt_open_font( stream, face ); | 857 error = sfnt_open_font( stream, face ); |
| 875 if ( error ) | 858 if ( error ) |
| 876 return error; | 859 return error; |
| 877 | 860 |
| 878 /* Stream may have changed in sfnt_open_font. */ | 861 /* Stream may have changed in sfnt_open_font. */ |
| 879 stream = face->root.stream; | 862 stream = face->root.stream; |
| 880 | 863 |
| 881 FT_TRACE2(( "sfnt_init_face: %08p, %ld\n", face, face_index )); | 864 FT_TRACE2(( "sfnt_init_face: %08p, %ld\n", face, face_instance_index )); |
| 882 | 865 |
| 883 if ( face_index < 0 ) | 866 face_index = FT_ABS( face_instance_index ) & 0xFFFF; |
| 884 face_index = 0; | |
| 885 | 867 |
| 886 if ( face_index >= face->ttc_header.count ) | 868 if ( face_index >= face->ttc_header.count ) |
| 887 return FT_THROW( Invalid_Argument ); | 869 { |
| 870 if ( face_instance_index >= 0 ) |
| 871 return FT_THROW( Invalid_Argument ); |
| 872 else |
| 873 face_index = 0; |
| 874 } |
| 888 | 875 |
| 889 if ( FT_STREAM_SEEK( face->ttc_header.offsets[face_index] ) ) | 876 if ( FT_STREAM_SEEK( face->ttc_header.offsets[face_index] ) ) |
| 890 return error; | 877 return error; |
| 891 | 878 |
| 892 /* check that we have a valid TrueType file */ | 879 /* check whether we have a valid TrueType file */ |
| 893 error = sfnt->load_font_dir( face, stream ); | 880 error = sfnt->load_font_dir( face, stream ); |
| 894 if ( error ) | 881 if ( error ) |
| 895 return error; | 882 return error; |
| 896 | 883 |
| 884 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT |
| 885 { |
| 886 FT_ULong fvar_len; |
| 887 FT_UShort num_instances; |
| 888 FT_Int instance_index; |
| 889 |
| 890 |
| 891 instance_index = FT_ABS( face_instance_index ) >> 16; |
| 892 |
| 893 /* test whether current face is a GX font with named instances */ |
| 894 if ( face->goto_table( face, TTAG_fvar, stream, &fvar_len ) || |
| 895 fvar_len < 20 || |
| 896 FT_STREAM_SKIP( 12 ) || |
| 897 FT_READ_USHORT( num_instances ) ) |
| 898 num_instances = 0; |
| 899 |
| 900 /* we support at most 2^15 - 1 instances */ |
| 901 if ( num_instances >= ( 1U << 15 ) - 1 ) |
| 902 { |
| 903 if ( face_instance_index >= 0 ) |
| 904 return FT_THROW( Invalid_Argument ); |
| 905 else |
| 906 num_instances = 0; |
| 907 } |
| 908 |
| 909 /* instance indices in `face_instance_index' start with index 1, */ |
| 910 /* thus `>' and not `>=' */ |
| 911 if ( instance_index > num_instances ) |
| 912 { |
| 913 if ( face_instance_index >= 0 ) |
| 914 return FT_THROW( Invalid_Argument ); |
| 915 else |
| 916 num_instances = 0; |
| 917 } |
| 918 |
| 919 face->root.style_flags = (FT_Long)num_instances << 16; |
| 920 } |
| 921 #endif |
| 922 |
| 897 face->root.num_faces = face->ttc_header.count; | 923 face->root.num_faces = face->ttc_header.count; |
| 898 face->root.face_index = face_index; | 924 face->root.face_index = face_index; |
| 899 | 925 |
| 900 return error; | 926 return error; |
| 901 } | 927 } |
| 902 | 928 |
| 903 | 929 |
| 904 #define LOAD_( x ) \ | 930 #define LOAD_( x ) \ |
| 905 do \ | 931 do \ |
| 906 { \ | 932 { \ |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 939 { \ | 965 { \ |
| 940 error = tt_face_get_name( face, TT_NAME_ID_ ## id, field ); \ | 966 error = tt_face_get_name( face, TT_NAME_ID_ ## id, field ); \ |
| 941 if ( error ) \ | 967 if ( error ) \ |
| 942 goto Exit; \ | 968 goto Exit; \ |
| 943 } while ( 0 ) | 969 } while ( 0 ) |
| 944 | 970 |
| 945 | 971 |
| 946 FT_LOCAL_DEF( FT_Error ) | 972 FT_LOCAL_DEF( FT_Error ) |
| 947 sfnt_load_face( FT_Stream stream, | 973 sfnt_load_face( FT_Stream stream, |
| 948 TT_Face face, | 974 TT_Face face, |
| 949 FT_Int face_index, | 975 FT_Int face_instance_index, |
| 950 FT_Int num_params, | 976 FT_Int num_params, |
| 951 FT_Parameter* params ) | 977 FT_Parameter* params ) |
| 952 { | 978 { |
| 953 FT_Error error; | 979 FT_Error error; |
| 954 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES | 980 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES |
| 955 FT_Error psnames_error; | 981 FT_Error psnames_error; |
| 956 #endif | 982 #endif |
| 957 FT_Bool has_outline; | 983 FT_Bool has_outline; |
| 958 FT_Bool is_apple_sbit; | 984 FT_Bool is_apple_sbit; |
| 959 FT_Bool is_apple_sbix; | 985 FT_Bool is_apple_sbix; |
| 960 FT_Bool ignore_preferred_family = FALSE; | 986 FT_Bool ignore_preferred_family = FALSE; |
| 961 FT_Bool ignore_preferred_subfamily = FALSE; | 987 FT_Bool ignore_preferred_subfamily = FALSE; |
| 962 | 988 |
| 963 SFNT_Service sfnt = (SFNT_Service)face->sfnt; | 989 SFNT_Service sfnt = (SFNT_Service)face->sfnt; |
| 964 | 990 |
| 965 FT_UNUSED( face_index ); | 991 FT_UNUSED( face_instance_index ); |
| 966 | 992 |
| 967 | 993 |
| 968 /* Check parameters */ | 994 /* Check parameters */ |
| 969 | 995 |
| 970 { | 996 { |
| 971 FT_Int i; | 997 FT_Int i; |
| 972 | 998 |
| 973 | 999 |
| 974 for ( i = 0; i < num_params; i++ ) | 1000 for ( i = 0; i < num_params; i++ ) |
| 975 { | 1001 { |
| (...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1277 { | 1303 { |
| 1278 /* this is an old Mac font, use the header field */ | 1304 /* this is an old Mac font, use the header field */ |
| 1279 | 1305 |
| 1280 if ( face->header.Mac_Style & 1 ) | 1306 if ( face->header.Mac_Style & 1 ) |
| 1281 flags |= FT_STYLE_FLAG_BOLD; | 1307 flags |= FT_STYLE_FLAG_BOLD; |
| 1282 | 1308 |
| 1283 if ( face->header.Mac_Style & 2 ) | 1309 if ( face->header.Mac_Style & 2 ) |
| 1284 flags |= FT_STYLE_FLAG_ITALIC; | 1310 flags |= FT_STYLE_FLAG_ITALIC; |
| 1285 } | 1311 } |
| 1286 | 1312 |
| 1287 root->style_flags = flags; | 1313 root->style_flags |= flags; |
| 1288 | 1314 |
| 1289 /*********************************************************************/ | 1315 /*********************************************************************/ |
| 1290 /* */ | 1316 /* */ |
| 1291 /* Polish the charmaps. */ | 1317 /* Polish the charmaps. */ |
| 1292 /* */ | 1318 /* */ |
| 1293 /* Try to set the charmap encoding according to the platform & */ | 1319 /* Try to set the charmap encoding according to the platform & */ |
| 1294 /* encoding ID of each charmap. */ | 1320 /* encoding ID of each charmap. */ |
| 1295 /* */ | 1321 /* */ |
| 1296 | 1322 |
| 1297 tt_face_build_cmaps( face ); /* ignore errors */ | 1323 tt_face_build_cmaps( face ); /* ignore errors */ |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1424 /* usWinAscent/Descent values -- as a conclusion, the OS/2 */ | 1450 /* usWinAscent/Descent values -- as a conclusion, the OS/2 */ |
| 1425 /* table cannot be used to compute the text height reliably! */ | 1451 /* table cannot be used to compute the text height reliably! */ |
| 1426 /* */ | 1452 /* */ |
| 1427 | 1453 |
| 1428 /* The ascender and descender are taken from the `hhea' table. */ | 1454 /* The ascender and descender are taken from the `hhea' table. */ |
| 1429 /* If zero, they are taken from the `OS/2' table. */ | 1455 /* If zero, they are taken from the `OS/2' table. */ |
| 1430 | 1456 |
| 1431 root->ascender = face->horizontal.Ascender; | 1457 root->ascender = face->horizontal.Ascender; |
| 1432 root->descender = face->horizontal.Descender; | 1458 root->descender = face->horizontal.Descender; |
| 1433 | 1459 |
| 1434 root->height = (FT_Short)( root->ascender - root->descender + | 1460 root->height = root->ascender - root->descender + |
| 1435 face->horizontal.Line_Gap ); | 1461 face->horizontal.Line_Gap; |
| 1436 | 1462 |
| 1437 if ( !( root->ascender || root->descender ) ) | 1463 if ( !( root->ascender || root->descender ) ) |
| 1438 { | 1464 { |
| 1439 if ( face->os2.version != 0xFFFFU ) | 1465 if ( face->os2.version != 0xFFFFU ) |
| 1440 { | 1466 { |
| 1441 if ( face->os2.sTypoAscender || face->os2.sTypoDescender ) | 1467 if ( face->os2.sTypoAscender || face->os2.sTypoDescender ) |
| 1442 { | 1468 { |
| 1443 root->ascender = face->os2.sTypoAscender; | 1469 root->ascender = face->os2.sTypoAscender; |
| 1444 root->descender = face->os2.sTypoDescender; | 1470 root->descender = face->os2.sTypoDescender; |
| 1445 | 1471 |
| 1446 root->height = (FT_Short)( root->ascender - root->descender + | 1472 root->height = root->ascender - root->descender + |
| 1447 face->os2.sTypoLineGap ); | 1473 face->os2.sTypoLineGap; |
| 1448 } | 1474 } |
| 1449 else | 1475 else |
| 1450 { | 1476 { |
| 1451 root->ascender = (FT_Short)face->os2.usWinAscent; | 1477 root->ascender = (FT_Short)face->os2.usWinAscent; |
| 1452 root->descender = -(FT_Short)face->os2.usWinDescent; | 1478 root->descender = -(FT_Short)face->os2.usWinDescent; |
| 1453 | 1479 |
| 1454 root->height = (FT_UShort)( root->ascender - root->descender ); | 1480 root->height = root->ascender - root->descender; |
| 1455 } | 1481 } |
| 1456 } | 1482 } |
| 1457 } | 1483 } |
| 1458 | 1484 |
| 1459 root->max_advance_width = face->horizontal.advance_Width_Max; | 1485 root->max_advance_width = |
| 1460 root->max_advance_height = (FT_Short)( face->vertical_info | 1486 (FT_Short)face->horizontal.advance_Width_Max; |
| 1461 ? face->vertical.advance_Height_Max | 1487 root->max_advance_height = |
| 1462 : root->height ); | 1488 (FT_Short)( face->vertical_info ? face->vertical.advance_Height_Max |
| 1489 : root->height ); |
| 1463 | 1490 |
| 1464 /* See http://www.microsoft.com/OpenType/OTSpec/post.htm -- */ | 1491 /* See http://www.microsoft.com/OpenType/OTSpec/post.htm -- */ |
| 1465 /* Adjust underline position from top edge to centre of */ | 1492 /* Adjust underline position from top edge to centre of */ |
| 1466 /* stroke to convert TrueType meaning to FreeType meaning. */ | 1493 /* stroke to convert TrueType meaning to FreeType meaning. */ |
| 1467 root->underline_position = face->postscript.underlinePosition - | 1494 root->underline_position = face->postscript.underlinePosition - |
| 1468 face->postscript.underlineThickness / 2; | 1495 face->postscript.underlineThickness / 2; |
| 1469 root->underline_thickness = face->postscript.underlineThickness; | 1496 root->underline_thickness = face->postscript.underlineThickness; |
| 1470 } | 1497 } |
| 1471 | 1498 |
| 1472 } | 1499 } |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1562 /* freeing family and style name */ | 1589 /* freeing family and style name */ |
| 1563 FT_FREE( face->root.family_name ); | 1590 FT_FREE( face->root.family_name ); |
| 1564 FT_FREE( face->root.style_name ); | 1591 FT_FREE( face->root.style_name ); |
| 1565 | 1592 |
| 1566 /* freeing sbit size table */ | 1593 /* freeing sbit size table */ |
| 1567 FT_FREE( face->root.available_sizes ); | 1594 FT_FREE( face->root.available_sizes ); |
| 1568 face->root.num_fixed_sizes = 0; | 1595 face->root.num_fixed_sizes = 0; |
| 1569 | 1596 |
| 1570 FT_FREE( face->postscript_name ); | 1597 FT_FREE( face->postscript_name ); |
| 1571 | 1598 |
| 1572 face->sfnt = 0; | 1599 face->sfnt = NULL; |
| 1573 } | 1600 } |
| 1574 | 1601 |
| 1575 | 1602 |
| 1576 /* END */ | 1603 /* END */ |
| OLD | NEW |