00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <ft2build.h>
00020 #include FT_FREETYPE_H
00021 #include FT_INTERNAL_OBJECTS_H
00022 #include FT_INTERNAL_DEBUG_H
00023 #include FT_INTERNAL_CALC_H
00024
00025 #include "pshrec.h"
00026 #include "pshalgo.h"
00027
00028 #include "pshnterr.h"
00029
00030 #undef FT_COMPONENT
00031 #define FT_COMPONENT trace_pshrec
00032
00033 #ifdef DEBUG_HINTER
00034 PS_Hints ps_debug_hints = 0;
00035 int ps_debug_no_horz_hints = 0;
00036 int ps_debug_no_vert_hints = 0;
00037 #endif
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049 static void
00050 ps_hint_table_done( PS_Hint_Table table,
00051 FT_Memory memory )
00052 {
00053 FT_FREE( table->hints );
00054 table->num_hints = 0;
00055 table->max_hints = 0;
00056 }
00057
00058
00059
00060 static FT_Error
00061 ps_hint_table_ensure( PS_Hint_Table table,
00062 FT_UInt count,
00063 FT_Memory memory )
00064 {
00065 FT_UInt old_max = table->max_hints;
00066 FT_UInt new_max = count;
00067 FT_Error error = PSH_Err_Ok;
00068
00069
00070 if ( new_max > old_max )
00071 {
00072
00073 new_max = FT_PAD_CEIL( new_max, 8 );
00074 if ( !FT_RENEW_ARRAY( table->hints, old_max, new_max ) )
00075 table->max_hints = new_max;
00076 }
00077 return error;
00078 }
00079
00080
00081 static FT_Error
00082 ps_hint_table_alloc( PS_Hint_Table table,
00083 FT_Memory memory,
00084 PS_Hint *ahint )
00085 {
00086 FT_Error error = PSH_Err_Ok;
00087 FT_UInt count;
00088 PS_Hint hint = 0;
00089
00090
00091 count = table->num_hints;
00092 count++;
00093
00094 if ( count >= table->max_hints )
00095 {
00096 error = ps_hint_table_ensure( table, count, memory );
00097 if ( error )
00098 goto Exit;
00099 }
00100
00101 hint = table->hints + count - 1;
00102 hint->pos = 0;
00103 hint->len = 0;
00104 hint->flags = 0;
00105
00106 table->num_hints = count;
00107
00108 Exit:
00109 *ahint = hint;
00110 return error;
00111 }
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123 static void
00124 ps_mask_done( PS_Mask mask,
00125 FT_Memory memory )
00126 {
00127 FT_FREE( mask->bytes );
00128 mask->num_bits = 0;
00129 mask->max_bits = 0;
00130 mask->end_point = 0;
00131 }
00132
00133
00134
00135 static FT_Error
00136 ps_mask_ensure( PS_Mask mask,
00137 FT_UInt count,
00138 FT_Memory memory )
00139 {
00140 FT_UInt old_max = ( mask->max_bits + 7 ) >> 3;
00141 FT_UInt new_max = ( count + 7 ) >> 3;
00142 FT_Error error = PSH_Err_Ok;
00143
00144
00145 if ( new_max > old_max )
00146 {
00147 new_max = FT_PAD_CEIL( new_max, 8 );
00148 if ( !FT_RENEW_ARRAY( mask->bytes, old_max, new_max ) )
00149 mask->max_bits = new_max * 8;
00150 }
00151 return error;
00152 }
00153
00154
00155
00156 static FT_Int
00157 ps_mask_test_bit( PS_Mask mask,
00158 FT_Int idx )
00159 {
00160 if ( (FT_UInt)idx >= mask->num_bits )
00161 return 0;
00162
00163 return mask->bytes[idx >> 3] & ( 0x80 >> ( idx & 7 ) );
00164 }
00165
00166
00167
00168 static void
00169 ps_mask_clear_bit( PS_Mask mask,
00170 FT_Int idx )
00171 {
00172 FT_Byte* p;
00173
00174
00175 if ( (FT_UInt)idx >= mask->num_bits )
00176 return;
00177
00178 p = mask->bytes + ( idx >> 3 );
00179 p[0] = (FT_Byte)( p[0] & ~( 0x80 >> ( idx & 7 ) ) );
00180 }
00181
00182
00183
00184 static FT_Error
00185 ps_mask_set_bit( PS_Mask mask,
00186 FT_Int idx,
00187 FT_Memory memory )
00188 {
00189 FT_Error error = PSH_Err_Ok;
00190 FT_Byte* p;
00191
00192
00193 if ( idx < 0 )
00194 goto Exit;
00195
00196 if ( (FT_UInt)idx >= mask->num_bits )
00197 {
00198 error = ps_mask_ensure( mask, idx + 1, memory );
00199 if ( error )
00200 goto Exit;
00201
00202 mask->num_bits = idx + 1;
00203 }
00204
00205 p = mask->bytes + ( idx >> 3 );
00206 p[0] = (FT_Byte)( p[0] | ( 0x80 >> ( idx & 7 ) ) );
00207
00208 Exit:
00209 return error;
00210 }
00211
00212
00213
00214 static void
00215 ps_mask_table_done( PS_Mask_Table table,
00216 FT_Memory memory )
00217 {
00218 FT_UInt count = table->max_masks;
00219 PS_Mask mask = table->masks;
00220
00221
00222 for ( ; count > 0; count--, mask++ )
00223 ps_mask_done( mask, memory );
00224
00225 FT_FREE( table->masks );
00226 table->num_masks = 0;
00227 table->max_masks = 0;
00228 }
00229
00230
00231
00232 static FT_Error
00233 ps_mask_table_ensure( PS_Mask_Table table,
00234 FT_UInt count,
00235 FT_Memory memory )
00236 {
00237 FT_UInt old_max = table->max_masks;
00238 FT_UInt new_max = count;
00239 FT_Error error = PSH_Err_Ok;
00240
00241
00242 if ( new_max > old_max )
00243 {
00244 new_max = FT_PAD_CEIL( new_max, 8 );
00245 if ( !FT_RENEW_ARRAY( table->masks, old_max, new_max ) )
00246 table->max_masks = new_max;
00247 }
00248 return error;
00249 }
00250
00251
00252
00253 static FT_Error
00254 ps_mask_table_alloc( PS_Mask_Table table,
00255 FT_Memory memory,
00256 PS_Mask *amask )
00257 {
00258 FT_UInt count;
00259 FT_Error error = PSH_Err_Ok;
00260 PS_Mask mask = 0;
00261
00262
00263 count = table->num_masks;
00264 count++;
00265
00266 if ( count > table->max_masks )
00267 {
00268 error = ps_mask_table_ensure( table, count, memory );
00269 if ( error )
00270 goto Exit;
00271 }
00272
00273 mask = table->masks + count - 1;
00274 mask->num_bits = 0;
00275 mask->end_point = 0;
00276 table->num_masks = count;
00277
00278 Exit:
00279 *amask = mask;
00280 return error;
00281 }
00282
00283
00284
00285 static FT_Error
00286 ps_mask_table_last( PS_Mask_Table table,
00287 FT_Memory memory,
00288 PS_Mask *amask )
00289 {
00290 FT_Error error = PSH_Err_Ok;
00291 FT_UInt count;
00292 PS_Mask mask;
00293
00294
00295 count = table->num_masks;
00296 if ( count == 0 )
00297 {
00298 error = ps_mask_table_alloc( table, memory, &mask );
00299 if ( error )
00300 goto Exit;
00301 }
00302 else
00303 mask = table->masks + count - 1;
00304
00305 Exit:
00306 *amask = mask;
00307 return error;
00308 }
00309
00310
00311
00312 static FT_Error
00313 ps_mask_table_set_bits( PS_Mask_Table table,
00314 const FT_Byte* source,
00315 FT_UInt bit_pos,
00316 FT_UInt bit_count,
00317 FT_Memory memory )
00318 {
00319 FT_Error error = PSH_Err_Ok;
00320 PS_Mask mask;
00321
00322
00323 error = ps_mask_table_last( table, memory, &mask );
00324 if ( error )
00325 goto Exit;
00326
00327 error = ps_mask_ensure( mask, bit_count, memory );
00328 if ( error )
00329 goto Exit;
00330
00331 mask->num_bits = bit_count;
00332
00333
00334 {
00335 FT_Byte* read = (FT_Byte*)source + ( bit_pos >> 3 );
00336 FT_Int rmask = 0x80 >> ( bit_pos & 7 );
00337 FT_Byte* write = mask->bytes;
00338 FT_Int wmask = 0x80;
00339 FT_Int val;
00340
00341
00342 for ( ; bit_count > 0; bit_count-- )
00343 {
00344 val = write[0] & ~wmask;
00345
00346 if ( read[0] & rmask )
00347 val |= wmask;
00348
00349 write[0] = (FT_Byte)val;
00350
00351 rmask >>= 1;
00352 if ( rmask == 0 )
00353 {
00354 read++;
00355 rmask = 0x80;
00356 }
00357
00358 wmask >>= 1;
00359 if ( wmask == 0 )
00360 {
00361 write++;
00362 wmask = 0x80;
00363 }
00364 }
00365 }
00366
00367 Exit:
00368 return error;
00369 }
00370
00371
00372
00373 static FT_Int
00374 ps_mask_table_test_intersect( PS_Mask_Table table,
00375 FT_Int index1,
00376 FT_Int index2 )
00377 {
00378 PS_Mask mask1 = table->masks + index1;
00379 PS_Mask mask2 = table->masks + index2;
00380 FT_Byte* p1 = mask1->bytes;
00381 FT_Byte* p2 = mask2->bytes;
00382 FT_UInt count1 = mask1->num_bits;
00383 FT_UInt count2 = mask2->num_bits;
00384 FT_UInt count;
00385
00386
00387 count = ( count1 <= count2 ) ? count1 : count2;
00388 for ( ; count >= 8; count -= 8 )
00389 {
00390 if ( p1[0] & p2[0] )
00391 return 1;
00392
00393 p1++;
00394 p2++;
00395 }
00396
00397 if ( count == 0 )
00398 return 0;
00399
00400 return ( p1[0] & p2[0] ) & ~( 0xFF >> count );
00401 }
00402
00403
00404
00405 static FT_Error
00406 ps_mask_table_merge( PS_Mask_Table table,
00407 FT_Int index1,
00408 FT_Int index2,
00409 FT_Memory memory )
00410 {
00411 FT_UInt temp;
00412 FT_Error error = PSH_Err_Ok;
00413
00414
00415
00416 if ( index1 > index2 )
00417 {
00418 temp = index1;
00419 index1 = index2;
00420 index2 = temp;
00421 }
00422
00423 if ( index1 < index2 && index1 >= 0 && index2 < (FT_Int)table->num_masks )
00424 {
00425
00426
00427 PS_Mask mask1 = table->masks + index1;
00428 PS_Mask mask2 = table->masks + index2;
00429 FT_UInt count1 = mask1->num_bits;
00430 FT_UInt count2 = mask2->num_bits;
00431 FT_Int delta;
00432
00433
00434 if ( count2 > 0 )
00435 {
00436 FT_UInt pos;
00437 FT_Byte* read;
00438 FT_Byte* write;
00439
00440
00441
00442
00443 if ( count2 > count1 )
00444 {
00445 error = ps_mask_ensure( mask1, count2, memory );
00446 if ( error )
00447 goto Exit;
00448
00449 for ( pos = count1; pos < count2; pos++ )
00450 ps_mask_clear_bit( mask1, pos );
00451 }
00452
00453
00454 read = mask2->bytes;
00455 write = mask1->bytes;
00456 pos = (FT_UInt)( ( count2 + 7 ) >> 3 );
00457
00458 for ( ; pos > 0; pos-- )
00459 {
00460 write[0] = (FT_Byte)( write[0] | read[0] );
00461 write++;
00462 read++;
00463 }
00464 }
00465
00466
00467
00468 mask2->num_bits = 0;
00469 mask2->end_point = 0;
00470
00471 delta = table->num_masks - 1 - index2;
00472 if ( delta > 0 )
00473 {
00474
00475 PS_MaskRec dummy = *mask2;
00476
00477
00478 ft_memmove( mask2, mask2 + 1, delta * sizeof ( PS_MaskRec ) );
00479
00480 mask2[delta] = dummy;
00481 }
00482
00483 table->num_masks--;
00484 }
00485 else
00486 FT_TRACE0(( "ps_mask_table_merge: ignoring invalid indices (%d,%d)\n",
00487 index1, index2 ));
00488
00489 Exit:
00490 return error;
00491 }
00492
00493
00494
00495
00496
00497 static FT_Error
00498 ps_mask_table_merge_all( PS_Mask_Table table,
00499 FT_Memory memory )
00500 {
00501 FT_Int index1, index2;
00502 FT_Error error = PSH_Err_Ok;
00503
00504
00505 for ( index1 = table->num_masks - 1; index1 > 0; index1-- )
00506 {
00507 for ( index2 = index1 - 1; index2 >= 0; index2-- )
00508 {
00509 if ( ps_mask_table_test_intersect( table, index1, index2 ) )
00510 {
00511 error = ps_mask_table_merge( table, index2, index1, memory );
00512 if ( error )
00513 goto Exit;
00514
00515 break;
00516 }
00517 }
00518 }
00519
00520 Exit:
00521 return error;
00522 }
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535 static void
00536 ps_dimension_done( PS_Dimension dimension,
00537 FT_Memory memory )
00538 {
00539 ps_mask_table_done( &dimension->counters, memory );
00540 ps_mask_table_done( &dimension->masks, memory );
00541 ps_hint_table_done( &dimension->hints, memory );
00542 }
00543
00544
00545
00546 static void
00547 ps_dimension_init( PS_Dimension dimension )
00548 {
00549 dimension->hints.num_hints = 0;
00550 dimension->masks.num_masks = 0;
00551 dimension->counters.num_masks = 0;
00552 }
00553
00554
00555 #if 0
00556
00557
00558 static FT_Error
00559 ps_dimension_set_mask_bit( PS_Dimension dim,
00560 FT_UInt idx,
00561 FT_Memory memory )
00562 {
00563 PS_Mask mask;
00564 FT_Error error = PSH_Err_Ok;
00565
00566
00567
00568 error = ps_mask_table_last( &dim->masks, memory, &mask );
00569 if ( error )
00570 goto Exit;
00571
00572 error = ps_mask_set_bit( mask, idx, memory );
00573
00574 Exit:
00575 return error;
00576 }
00577
00578 #endif
00579
00580
00581 static void
00582 ps_dimension_end_mask( PS_Dimension dim,
00583 FT_UInt end_point )
00584 {
00585 FT_UInt count = dim->masks.num_masks;
00586 PS_Mask mask;
00587
00588
00589 if ( count > 0 )
00590 {
00591 mask = dim->masks.masks + count - 1;
00592 mask->end_point = end_point;
00593 }
00594 }
00595
00596
00597
00598
00599 static FT_Error
00600 ps_dimension_reset_mask( PS_Dimension dim,
00601 FT_UInt end_point,
00602 FT_Memory memory )
00603 {
00604 PS_Mask mask;
00605
00606
00607
00608 ps_dimension_end_mask( dim, end_point );
00609
00610
00611 return ps_mask_table_alloc( &dim->masks, memory, &mask );
00612 }
00613
00614
00615
00616 static FT_Error
00617 ps_dimension_set_mask_bits( PS_Dimension dim,
00618 const FT_Byte* source,
00619 FT_UInt source_pos,
00620 FT_UInt source_bits,
00621 FT_UInt end_point,
00622 FT_Memory memory )
00623 {
00624 FT_Error error = PSH_Err_Ok;
00625
00626
00627
00628 error = ps_dimension_reset_mask( dim, end_point, memory );
00629 if ( error )
00630 goto Exit;
00631
00632
00633 error = ps_mask_table_set_bits( &dim->masks, source,
00634 source_pos, source_bits, memory );
00635
00636 Exit:
00637 return error;
00638 }
00639
00640
00641
00642 static FT_Error
00643 ps_dimension_add_t1stem( PS_Dimension dim,
00644 FT_Int pos,
00645 FT_Int len,
00646 FT_Memory memory,
00647 FT_Int *aindex )
00648 {
00649 FT_Error error = PSH_Err_Ok;
00650 FT_UInt flags = 0;
00651
00652
00653
00654 if ( len < 0 )
00655 {
00656 flags |= PS_HINT_FLAG_GHOST;
00657 if ( len == -21 )
00658 {
00659 flags |= PS_HINT_FLAG_BOTTOM;
00660 pos += len;
00661 }
00662 len = 0;
00663 }
00664
00665 if ( aindex )
00666 *aindex = -1;
00667
00668
00669 {
00670 PS_Mask mask;
00671 FT_UInt idx;
00672 FT_UInt max = dim->hints.num_hints;
00673 PS_Hint hint = dim->hints.hints;
00674
00675
00676 for ( idx = 0; idx < max; idx++, hint++ )
00677 {
00678 if ( hint->pos == pos && hint->len == len )
00679 break;
00680 }
00681
00682
00683 if ( idx >= max )
00684 {
00685 error = ps_hint_table_alloc( &dim->hints, memory, &hint );
00686 if ( error )
00687 goto Exit;
00688
00689 hint->pos = pos;
00690 hint->len = len;
00691 hint->flags = flags;
00692 }
00693
00694
00695 error = ps_mask_table_last( &dim->masks, memory, &mask );
00696 if ( error )
00697 goto Exit;
00698
00699 error = ps_mask_set_bit( mask, idx, memory );
00700 if ( error )
00701 goto Exit;
00702
00703 if ( aindex )
00704 *aindex = (FT_Int)idx;
00705 }
00706
00707 Exit:
00708 return error;
00709 }
00710
00711
00712
00713 static FT_Error
00714 ps_dimension_add_counter( PS_Dimension dim,
00715 FT_Int hint1,
00716 FT_Int hint2,
00717 FT_Int hint3,
00718 FT_Memory memory )
00719 {
00720 FT_Error error = PSH_Err_Ok;
00721 FT_UInt count = dim->counters.num_masks;
00722 PS_Mask counter = dim->counters.masks;
00723
00724
00725
00726
00727 for ( ; count > 0; count--, counter++ )
00728 {
00729 if ( ps_mask_test_bit( counter, hint1 ) ||
00730 ps_mask_test_bit( counter, hint2 ) ||
00731 ps_mask_test_bit( counter, hint3 ) )
00732 break;
00733 }
00734
00735
00736 if ( count == 0 )
00737 {
00738 error = ps_mask_table_alloc( &dim->counters, memory, &counter );
00739 if ( error )
00740 goto Exit;
00741 }
00742
00743
00744 error = ps_mask_set_bit( counter, hint1, memory );
00745 if ( error )
00746 goto Exit;
00747
00748 error = ps_mask_set_bit( counter, hint2, memory );
00749 if ( error )
00750 goto Exit;
00751
00752 error = ps_mask_set_bit( counter, hint3, memory );
00753 if ( error )
00754 goto Exit;
00755
00756 Exit:
00757 return error;
00758 }
00759
00760
00761
00762 static FT_Error
00763 ps_dimension_end( PS_Dimension dim,
00764 FT_UInt end_point,
00765 FT_Memory memory )
00766 {
00767
00768 ps_dimension_end_mask( dim, end_point );
00769
00770
00771 return ps_mask_table_merge_all( &dim->counters, memory );
00772 }
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785 FT_LOCAL( void )
00786 ps_hints_done( PS_Hints hints )
00787 {
00788 FT_Memory memory = hints->memory;
00789
00790
00791 ps_dimension_done( &hints->dimension[0], memory );
00792 ps_dimension_done( &hints->dimension[1], memory );
00793
00794 hints->error = PSH_Err_Ok;
00795 hints->memory = 0;
00796 }
00797
00798
00799 FT_LOCAL( FT_Error )
00800 ps_hints_init( PS_Hints hints,
00801 FT_Memory memory )
00802 {
00803 FT_MEM_ZERO( hints, sizeof ( *hints ) );
00804 hints->memory = memory;
00805 return PSH_Err_Ok;
00806 }
00807
00808
00809
00810 static void
00811 ps_hints_open( PS_Hints hints,
00812 PS_Hint_Type hint_type )
00813 {
00814 switch ( hint_type )
00815 {
00816 case PS_HINT_TYPE_1:
00817 case PS_HINT_TYPE_2:
00818 hints->error = PSH_Err_Ok;
00819 hints->hint_type = hint_type;
00820
00821 ps_dimension_init( &hints->dimension[0] );
00822 ps_dimension_init( &hints->dimension[1] );
00823 break;
00824
00825 default:
00826 hints->error = PSH_Err_Invalid_Argument;
00827 hints->hint_type = hint_type;
00828
00829 FT_TRACE0(( "ps_hints_open: invalid charstring type\n" ));
00830 break;
00831 }
00832 }
00833
00834
00835
00836 static void
00837 ps_hints_stem( PS_Hints hints,
00838 FT_Int dimension,
00839 FT_UInt count,
00840 FT_Long* stems )
00841 {
00842 if ( !hints->error )
00843 {
00844
00845 if ( dimension < 0 || dimension > 1 )
00846 {
00847 FT_TRACE0(( "ps_hints_stem: invalid dimension (%d) used\n",
00848 dimension ));
00849 dimension = ( dimension != 0 );
00850 }
00851
00852
00853 switch ( hints->hint_type )
00854 {
00855 case PS_HINT_TYPE_1:
00856 case PS_HINT_TYPE_2:
00857 {
00858 PS_Dimension dim = &hints->dimension[dimension];
00859
00860
00861 for ( ; count > 0; count--, stems += 2 )
00862 {
00863 FT_Error error;
00864 FT_Memory memory = hints->memory;
00865
00866
00867 error = ps_dimension_add_t1stem(
00868 dim, (FT_Int)stems[0], (FT_Int)stems[1],
00869 memory, NULL );
00870 if ( error )
00871 {
00872 FT_ERROR(( "ps_hints_stem: could not add stem"
00873 " (%d,%d) to hints table\n", stems[0], stems[1] ));
00874
00875 hints->error = error;
00876 return;
00877 }
00878 }
00879 break;
00880 }
00881
00882 default:
00883 FT_TRACE0(( "ps_hints_stem: called with invalid hint type (%d)\n",
00884 hints->hint_type ));
00885 break;
00886 }
00887 }
00888 }
00889
00890
00891
00892 static void
00893 ps_hints_t1stem3( PS_Hints hints,
00894 FT_Int dimension,
00895 FT_Fixed* stems )
00896 {
00897 FT_Error error = PSH_Err_Ok;
00898
00899
00900 if ( !hints->error )
00901 {
00902 PS_Dimension dim;
00903 FT_Memory memory = hints->memory;
00904 FT_Int count;
00905 FT_Int idx[3];
00906
00907
00908
00909 if ( dimension < 0 || dimension > 1 )
00910 {
00911 FT_TRACE0(( "ps_hints_t1stem3: invalid dimension (%d) used\n",
00912 dimension ));
00913 dimension = ( dimension != 0 );
00914 }
00915
00916 dim = &hints->dimension[dimension];
00917
00918
00919 if ( hints->hint_type == PS_HINT_TYPE_1 )
00920 {
00921
00922 for ( count = 0; count < 3; count++, stems += 2 )
00923 {
00924 error = ps_dimension_add_t1stem( dim,
00925 (FT_Int)FIXED_TO_INT( stems[0] ),
00926 (FT_Int)FIXED_TO_INT( stems[1] ),
00927 memory, &idx[count] );
00928 if ( error )
00929 goto Fail;
00930 }
00931
00932
00933 error = ps_dimension_add_counter( dim, idx[0], idx[1], idx[2],
00934 memory );
00935 if ( error )
00936 goto Fail;
00937 }
00938 else
00939 {
00940 FT_ERROR(( "ps_hints_t1stem3: called with invalid hint type\n" ));
00941 error = PSH_Err_Invalid_Argument;
00942 goto Fail;
00943 }
00944 }
00945
00946 return;
00947
00948 Fail:
00949 FT_ERROR(( "ps_hints_t1stem3: could not add counter stems to table\n" ));
00950 hints->error = error;
00951 }
00952
00953
00954
00955 static void
00956 ps_hints_t1reset( PS_Hints hints,
00957 FT_UInt end_point )
00958 {
00959 FT_Error error = PSH_Err_Ok;
00960
00961
00962 if ( !hints->error )
00963 {
00964 FT_Memory memory = hints->memory;
00965
00966
00967 if ( hints->hint_type == PS_HINT_TYPE_1 )
00968 {
00969 error = ps_dimension_reset_mask( &hints->dimension[0],
00970 end_point, memory );
00971 if ( error )
00972 goto Fail;
00973
00974 error = ps_dimension_reset_mask( &hints->dimension[1],
00975 end_point, memory );
00976 if ( error )
00977 goto Fail;
00978 }
00979 else
00980 {
00981
00982 error = PSH_Err_Invalid_Argument;
00983 goto Fail;
00984 }
00985 }
00986 return;
00987
00988 Fail:
00989 hints->error = error;
00990 }
00991
00992
00993
00994 static void
00995 ps_hints_t2mask( PS_Hints hints,
00996 FT_UInt end_point,
00997 FT_UInt bit_count,
00998 const FT_Byte* bytes )
00999 {
01000 FT_Error error;
01001
01002
01003 if ( !hints->error )
01004 {
01005 PS_Dimension dim = hints->dimension;
01006 FT_Memory memory = hints->memory;
01007 FT_UInt count1 = dim[0].hints.num_hints;
01008 FT_UInt count2 = dim[1].hints.num_hints;
01009
01010
01011
01012 if ( bit_count != count1 + count2 )
01013 {
01014 FT_TRACE0(( "ps_hints_t2mask:"
01015 " called with invalid bitcount %d (instead of %d)\n",
01016 bit_count, count1 + count2 ));
01017
01018
01019 return;
01020 }
01021
01022
01023 error = ps_dimension_set_mask_bits( &dim[0], bytes, count2, count1,
01024 end_point, memory );
01025 if ( error )
01026 goto Fail;
01027
01028 error = ps_dimension_set_mask_bits( &dim[1], bytes, 0, count2,
01029 end_point, memory );
01030 if ( error )
01031 goto Fail;
01032 }
01033 return;
01034
01035 Fail:
01036 hints->error = error;
01037 }
01038
01039
01040 static void
01041 ps_hints_t2counter( PS_Hints hints,
01042 FT_UInt bit_count,
01043 const FT_Byte* bytes )
01044 {
01045 FT_Error error;
01046
01047
01048 if ( !hints->error )
01049 {
01050 PS_Dimension dim = hints->dimension;
01051 FT_Memory memory = hints->memory;
01052 FT_UInt count1 = dim[0].hints.num_hints;
01053 FT_UInt count2 = dim[1].hints.num_hints;
01054
01055
01056
01057 if ( bit_count != count1 + count2 )
01058 {
01059 FT_TRACE0(( "ps_hints_t2counter:"
01060 " called with invalid bitcount %d (instead of %d)\n",
01061 bit_count, count1 + count2 ));
01062
01063
01064 return;
01065 }
01066
01067
01068 error = ps_dimension_set_mask_bits( &dim[0], bytes, 0, count1,
01069 0, memory );
01070 if ( error )
01071 goto Fail;
01072
01073 error = ps_dimension_set_mask_bits( &dim[1], bytes, count1, count2,
01074 0, memory );
01075 if ( error )
01076 goto Fail;
01077 }
01078 return;
01079
01080 Fail:
01081 hints->error = error;
01082 }
01083
01084
01085
01086 static FT_Error
01087 ps_hints_close( PS_Hints hints,
01088 FT_UInt end_point )
01089 {
01090 FT_Error error;
01091
01092
01093 error = hints->error;
01094 if ( !error )
01095 {
01096 FT_Memory memory = hints->memory;
01097 PS_Dimension dim = hints->dimension;
01098
01099
01100 error = ps_dimension_end( &dim[0], end_point, memory );
01101 if ( !error )
01102 {
01103 error = ps_dimension_end( &dim[1], end_point, memory );
01104 }
01105 }
01106
01107 #ifdef DEBUG_HINTER
01108 if ( !error )
01109 ps_debug_hints = hints;
01110 #endif
01111 return error;
01112 }
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123 static void
01124 t1_hints_open( T1_Hints hints )
01125 {
01126 ps_hints_open( (PS_Hints)hints, PS_HINT_TYPE_1 );
01127 }
01128
01129 static void
01130 t1_hints_stem( T1_Hints hints,
01131 FT_Int dimension,
01132 FT_Fixed* coords )
01133 {
01134 FT_Pos stems[2];
01135
01136
01137 stems[0] = FIXED_TO_INT( coords[0] );
01138 stems[1] = FIXED_TO_INT( coords[1] );
01139
01140 ps_hints_stem( (PS_Hints)hints, dimension, 1, stems );
01141 }
01142
01143
01144 FT_LOCAL_DEF( void )
01145 t1_hints_funcs_init( T1_Hints_FuncsRec* funcs )
01146 {
01147 FT_MEM_ZERO( (char*)funcs, sizeof ( *funcs ) );
01148
01149 funcs->open = (T1_Hints_OpenFunc) t1_hints_open;
01150 funcs->close = (T1_Hints_CloseFunc) ps_hints_close;
01151 funcs->stem = (T1_Hints_SetStemFunc) t1_hints_stem;
01152 funcs->stem3 = (T1_Hints_SetStem3Func)ps_hints_t1stem3;
01153 funcs->reset = (T1_Hints_ResetFunc) ps_hints_t1reset;
01154 funcs->apply = (T1_Hints_ApplyFunc) ps_hints_apply;
01155 }
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166 static void
01167 t2_hints_open( T2_Hints hints )
01168 {
01169 ps_hints_open( (PS_Hints)hints, PS_HINT_TYPE_2 );
01170 }
01171
01172
01173 static void
01174 t2_hints_stems( T2_Hints hints,
01175 FT_Int dimension,
01176 FT_Int count,
01177 FT_Fixed* coords )
01178 {
01179 FT_Pos stems[32], y, n;
01180 FT_Int total = count;
01181
01182
01183 y = 0;
01184 while ( total > 0 )
01185 {
01186
01187 count = total;
01188 if ( count > 16 )
01189 count = 16;
01190
01191
01192 for ( n = 0; n < count * 2; n++ )
01193 {
01194 y += coords[n];
01195 stems[n] = FIXED_TO_INT( y );
01196 }
01197
01198
01199 for ( n = 0; n < count * 2; n += 2 )
01200 stems[n + 1] = stems[n + 1] - stems[n];
01201
01202
01203 ps_hints_stem( (PS_Hints)hints, dimension, count, stems );
01204
01205 total -= count;
01206 }
01207 }
01208
01209
01210 FT_LOCAL_DEF( void )
01211 t2_hints_funcs_init( T2_Hints_FuncsRec* funcs )
01212 {
01213 FT_MEM_ZERO( funcs, sizeof ( *funcs ) );
01214
01215 funcs->open = (T2_Hints_OpenFunc) t2_hints_open;
01216 funcs->close = (T2_Hints_CloseFunc) ps_hints_close;
01217 funcs->stems = (T2_Hints_StemsFunc) t2_hints_stems;
01218 funcs->hintmask= (T2_Hints_MaskFunc) ps_hints_t2mask;
01219 funcs->counter = (T2_Hints_CounterFunc)ps_hints_t2counter;
01220 funcs->apply = (T2_Hints_ApplyFunc) ps_hints_apply;
01221 }
01222
01223
01224