Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenpshrec.c
Go to the documentation of this file.
00001 /***************************************************************************/ 00002 /* */ 00003 /* pshrec.c */ 00004 /* */ 00005 /* FreeType PostScript hints recorder (body). */ 00006 /* */ 00007 /* Copyright 2001, 2002, 2003, 2004, 2007, 2009 by */ 00008 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ 00009 /* */ 00010 /* This file is part of the FreeType project, and may only be used, */ 00011 /* modified, and distributed under the terms of the FreeType project */ 00012 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 00013 /* this file you indicate that you have read the license and */ 00014 /* understand and accept it fully. */ 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 /***** PS_HINT MANAGEMENT *****/ 00044 /***** *****/ 00045 /*************************************************************************/ 00046 /*************************************************************************/ 00047 00048 /* destroy hints table */ 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 /* ensure that a table can contain "count" elements */ 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 /* try to grow the table */ 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 /***** PS_MASK MANAGEMENT *****/ 00118 /***** *****/ 00119 /*************************************************************************/ 00120 /*************************************************************************/ 00121 00122 /* destroy mask */ 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 /* ensure that a mask can contain "count" bits */ 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 /* test a bit value in a given mask */ 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 /* clear a given bit */ 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 /* set a given bit, possibly grow the mask */ 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 /* destroy mask table */ 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 /* ensure that a mask table can contain "count" masks */ 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 /* allocate a new mask in a table */ 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 /* return last hint mask in a table, create one if the table is empty */ 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 /* set a new mask to a given bit range */ 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 /* now, copy bits */ 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 /* test whether two masks in a table intersect */ 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 /* merge two masks, used by ps_mask_table_merge_all */ 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 /* swap index1 and index2 so that index1 < index2 */ 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 /* we need to merge the bitsets of index1 and index2 with a */ 00426 /* simple union */ 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 /* if "count2" is greater than "count1", we need to grow the */ 00442 /* first bitset, and clear the highest bits */ 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 /* merge (unite) the bitsets */ 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 /* Now, remove "mask2" from the list. We need to keep the masks */ 00467 /* sorted in order of importance, so move table elements. */ 00468 mask2->num_bits = 0; 00469 mask2->end_point = 0; 00470 00471 delta = table->num_masks - 1 - index2; /* number of masks to move */ 00472 if ( delta > 0 ) 00473 { 00474 /* move to end of table for reuse */ 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 /* Try to merge all masks in a given table. This is used to merge */ 00495 /* all counter masks into independent counter "paths". */ 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 /***** PS_DIMENSION MANAGEMENT *****/ 00529 /***** *****/ 00530 /*************************************************************************/ 00531 /*************************************************************************/ 00532 00533 00534 /* finalize a given dimension */ 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 /* initialize a given dimension */ 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 /* set a bit at a given index in the current hint mask */ 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 /* get last hint mask */ 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 /* set the end point in a mask, called from "End" & "Reset" methods */ 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 /* set the end point in the current mask, then create a new empty one */ 00598 /* (called by "Reset" method) */ 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 /* end current mask */ 00608 ps_dimension_end_mask( dim, end_point ); 00609 00610 /* allocate new one */ 00611 return ps_mask_table_alloc( &dim->masks, memory, &mask ); 00612 } 00613 00614 00615 /* set a new mask, called from the "T2Stem" method */ 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 /* reset current mask, if any */ 00628 error = ps_dimension_reset_mask( dim, end_point, memory ); 00629 if ( error ) 00630 goto Exit; 00631 00632 /* set bits in new mask */ 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 /* add a new single stem (called from "T1Stem" method) */ 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 /* detect ghost stem */ 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 /* now, lookup stem in the current hints table */ 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 /* we need to create a new hint in the table */ 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 /* now, store the hint in the current mask */ 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 /* add a "hstem3/vstem3" counter to our dimension table */ 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 /* try to find an existing counter mask that already uses */ 00726 /* one of these stems here */ 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 /* create a new counter when needed */ 00736 if ( count == 0 ) 00737 { 00738 error = ps_mask_table_alloc( &dim->counters, memory, &counter ); 00739 if ( error ) 00740 goto Exit; 00741 } 00742 00743 /* now, set the bits for our hints in the counter mask */ 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 /* end of recording session for a given dimension */ 00762 static FT_Error 00763 ps_dimension_end( PS_Dimension dim, 00764 FT_UInt end_point, 00765 FT_Memory memory ) 00766 { 00767 /* end hint mask table */ 00768 ps_dimension_end_mask( dim, end_point ); 00769 00770 /* merge all counter masks into independent "paths" */ 00771 return ps_mask_table_merge_all( &dim->counters, memory ); 00772 } 00773 00774 00775 /*************************************************************************/ 00776 /*************************************************************************/ 00777 /***** *****/ 00778 /***** PS_RECORDER MANAGEMENT *****/ 00779 /***** *****/ 00780 /*************************************************************************/ 00781 /*************************************************************************/ 00782 00783 00784 /* destroy hints */ 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 /* initialize a hints for a new session */ 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 /* add one or more stems to the current hints table */ 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 /* limit "dimension" to 0..1 */ 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 /* record the stems in the current hints/masks table */ 00853 switch ( hints->hint_type ) 00854 { 00855 case PS_HINT_TYPE_1: /* Type 1 "hstem" or "vstem" operator */ 00856 case PS_HINT_TYPE_2: /* Type 2 "hstem" or "vstem" operator */ 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 /* add one Type1 counter stem to the current hints table */ 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 /* limit "dimension" to 0..1 */ 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 /* there must be 6 elements in the 'stem' array */ 00919 if ( hints->hint_type == PS_HINT_TYPE_1 ) 00920 { 00921 /* add the three stems to our hints/masks table */ 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 /* now, add the hints to the counters table */ 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 /* reset hints (only with Type 1 hints) */ 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 /* invalid hint type */ 00982 error = PSH_Err_Invalid_Argument; 00983 goto Fail; 00984 } 00985 } 00986 return; 00987 00988 Fail: 00989 hints->error = error; 00990 } 00991 00992 00993 /* Type2 "hintmask" operator, add a new hintmask to each direction */ 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 /* check bit count; must be equal to current total hint count */ 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 /* simply ignore the operator */ 01019 return; 01020 } 01021 01022 /* set-up new horizontal and vertical hint mask now */ 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 /* check bit count, must be equal to current total hint count */ 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 /* simply ignore the operator */ 01064 return; 01065 } 01066 01067 /* set-up new horizontal and vertical hint mask now */ 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 /* end recording session */ 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 /***** TYPE 1 HINTS RECORDING INTERFACE *****/ 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 /***** TYPE 2 HINTS RECORDING INTERFACE *****/ 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 /* determine number of stems to write */ 01187 count = total; 01188 if ( count > 16 ) 01189 count = 16; 01190 01191 /* compute integer stem positions in font units */ 01192 for ( n = 0; n < count * 2; n++ ) 01193 { 01194 y += coords[n]; 01195 stems[n] = FIXED_TO_INT( y ); 01196 } 01197 01198 /* compute lengths */ 01199 for ( n = 0; n < count * 2; n += 2 ) 01200 stems[n + 1] = stems[n + 1] - stems[n]; 01201 01202 /* add them to the current dimension */ 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 /* END */ Generated on Sun May 27 2012 04:34:00 for ReactOS by
1.7.6.1
|