Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenpshglob.c
Go to the documentation of this file.
00001 /***************************************************************************/ 00002 /* */ 00003 /* pshglob.c */ 00004 /* */ 00005 /* PostScript hinter global hinting management (body). */ 00006 /* Inspired by the new auto-hinter module. */ 00007 /* */ 00008 /* Copyright 2001, 2002, 2003, 2004, 2006, 2010 by */ 00009 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ 00010 /* */ 00011 /* This file is part of the FreeType project, and may only be used */ 00012 /* modified and distributed under the terms of the FreeType project */ 00013 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 00014 /* this file you indicate that you have read the license and */ 00015 /* understand and accept it fully. */ 00016 /* */ 00017 /***************************************************************************/ 00018 00019 00020 #include <ft2build.h> 00021 #include FT_FREETYPE_H 00022 #include FT_INTERNAL_OBJECTS_H 00023 #include "pshglob.h" 00024 00025 #ifdef DEBUG_HINTER 00026 PSH_Globals ps_debug_globals = 0; 00027 #endif 00028 00029 00030 /*************************************************************************/ 00031 /*************************************************************************/ 00032 /***** *****/ 00033 /***** STANDARD WIDTHS *****/ 00034 /***** *****/ 00035 /*************************************************************************/ 00036 /*************************************************************************/ 00037 00038 00039 /* scale the widths/heights table */ 00040 static void 00041 psh_globals_scale_widths( PSH_Globals globals, 00042 FT_UInt direction ) 00043 { 00044 PSH_Dimension dim = &globals->dimension[direction]; 00045 PSH_Widths stdw = &dim->stdw; 00046 FT_UInt count = stdw->count; 00047 PSH_Width width = stdw->widths; 00048 PSH_Width stand = width; /* standard width/height */ 00049 FT_Fixed scale = dim->scale_mult; 00050 00051 00052 if ( count > 0 ) 00053 { 00054 width->cur = FT_MulFix( width->org, scale ); 00055 width->fit = FT_PIX_ROUND( width->cur ); 00056 00057 width++; 00058 count--; 00059 00060 for ( ; count > 0; count--, width++ ) 00061 { 00062 FT_Pos w, dist; 00063 00064 00065 w = FT_MulFix( width->org, scale ); 00066 dist = w - stand->cur; 00067 00068 if ( dist < 0 ) 00069 dist = -dist; 00070 00071 if ( dist < 128 ) 00072 w = stand->cur; 00073 00074 width->cur = w; 00075 width->fit = FT_PIX_ROUND( w ); 00076 } 00077 } 00078 } 00079 00080 00081 #if 0 00082 00083 /* org_width is is font units, result in device pixels, 26.6 format */ 00084 FT_LOCAL_DEF( FT_Pos ) 00085 psh_dimension_snap_width( PSH_Dimension dimension, 00086 FT_Int org_width ) 00087 { 00088 FT_UInt n; 00089 FT_Pos width = FT_MulFix( org_width, dimension->scale_mult ); 00090 FT_Pos best = 64 + 32 + 2; 00091 FT_Pos reference = width; 00092 00093 00094 for ( n = 0; n < dimension->stdw.count; n++ ) 00095 { 00096 FT_Pos w; 00097 FT_Pos dist; 00098 00099 00100 w = dimension->stdw.widths[n].cur; 00101 dist = width - w; 00102 if ( dist < 0 ) 00103 dist = -dist; 00104 if ( dist < best ) 00105 { 00106 best = dist; 00107 reference = w; 00108 } 00109 } 00110 00111 if ( width >= reference ) 00112 { 00113 width -= 0x21; 00114 if ( width < reference ) 00115 width = reference; 00116 } 00117 else 00118 { 00119 width += 0x21; 00120 if ( width > reference ) 00121 width = reference; 00122 } 00123 00124 return width; 00125 } 00126 00127 #endif /* 0 */ 00128 00129 00130 /*************************************************************************/ 00131 /*************************************************************************/ 00132 /***** *****/ 00133 /***** BLUE ZONES *****/ 00134 /***** *****/ 00135 /*************************************************************************/ 00136 /*************************************************************************/ 00137 00138 static void 00139 psh_blues_set_zones_0( PSH_Blues target, 00140 FT_Bool is_others, 00141 FT_UInt read_count, 00142 FT_Short* read, 00143 PSH_Blue_Table top_table, 00144 PSH_Blue_Table bot_table ) 00145 { 00146 FT_UInt count_top = top_table->count; 00147 FT_UInt count_bot = bot_table->count; 00148 FT_Bool first = 1; 00149 00150 FT_UNUSED( target ); 00151 00152 00153 for ( ; read_count > 1; read_count -= 2 ) 00154 { 00155 FT_Int reference, delta; 00156 FT_UInt count; 00157 PSH_Blue_Zone zones, zone; 00158 FT_Bool top; 00159 00160 00161 /* read blue zone entry, and select target top/bottom zone */ 00162 top = 0; 00163 if ( first || is_others ) 00164 { 00165 reference = read[1]; 00166 delta = read[0] - reference; 00167 00168 zones = bot_table->zones; 00169 count = count_bot; 00170 first = 0; 00171 } 00172 else 00173 { 00174 reference = read[0]; 00175 delta = read[1] - reference; 00176 00177 zones = top_table->zones; 00178 count = count_top; 00179 top = 1; 00180 } 00181 00182 /* insert into sorted table */ 00183 zone = zones; 00184 for ( ; count > 0; count--, zone++ ) 00185 { 00186 if ( reference < zone->org_ref ) 00187 break; 00188 00189 if ( reference == zone->org_ref ) 00190 { 00191 FT_Int delta0 = zone->org_delta; 00192 00193 00194 /* we have two zones on the same reference position -- */ 00195 /* only keep the largest one */ 00196 if ( delta < 0 ) 00197 { 00198 if ( delta < delta0 ) 00199 zone->org_delta = delta; 00200 } 00201 else 00202 { 00203 if ( delta > delta0 ) 00204 zone->org_delta = delta; 00205 } 00206 goto Skip; 00207 } 00208 } 00209 00210 for ( ; count > 0; count-- ) 00211 zone[count] = zone[count-1]; 00212 00213 zone->org_ref = reference; 00214 zone->org_delta = delta; 00215 00216 if ( top ) 00217 count_top++; 00218 else 00219 count_bot++; 00220 00221 Skip: 00222 read += 2; 00223 } 00224 00225 top_table->count = count_top; 00226 bot_table->count = count_bot; 00227 } 00228 00229 00230 /* Re-read blue zones from the original fonts and store them into out */ 00231 /* private structure. This function re-orders, sanitizes and */ 00232 /* fuzz-expands the zones as well. */ 00233 static void 00234 psh_blues_set_zones( PSH_Blues target, 00235 FT_UInt count, 00236 FT_Short* blues, 00237 FT_UInt count_others, 00238 FT_Short* other_blues, 00239 FT_Int fuzz, 00240 FT_Int family ) 00241 { 00242 PSH_Blue_Table top_table, bot_table; 00243 FT_Int count_top, count_bot; 00244 00245 00246 if ( family ) 00247 { 00248 top_table = &target->family_top; 00249 bot_table = &target->family_bottom; 00250 } 00251 else 00252 { 00253 top_table = &target->normal_top; 00254 bot_table = &target->normal_bottom; 00255 } 00256 00257 /* read the input blue zones, and build two sorted tables */ 00258 /* (one for the top zones, the other for the bottom zones) */ 00259 top_table->count = 0; 00260 bot_table->count = 0; 00261 00262 /* first, the blues */ 00263 psh_blues_set_zones_0( target, 0, 00264 count, blues, top_table, bot_table ); 00265 psh_blues_set_zones_0( target, 1, 00266 count_others, other_blues, top_table, bot_table ); 00267 00268 count_top = top_table->count; 00269 count_bot = bot_table->count; 00270 00271 /* sanitize top table */ 00272 if ( count_top > 0 ) 00273 { 00274 PSH_Blue_Zone zone = top_table->zones; 00275 00276 00277 for ( count = count_top; count > 0; count--, zone++ ) 00278 { 00279 FT_Int delta; 00280 00281 00282 if ( count > 1 ) 00283 { 00284 delta = zone[1].org_ref - zone[0].org_ref; 00285 if ( zone->org_delta > delta ) 00286 zone->org_delta = delta; 00287 } 00288 00289 zone->org_bottom = zone->org_ref; 00290 zone->org_top = zone->org_delta + zone->org_ref; 00291 } 00292 } 00293 00294 /* sanitize bottom table */ 00295 if ( count_bot > 0 ) 00296 { 00297 PSH_Blue_Zone zone = bot_table->zones; 00298 00299 00300 for ( count = count_bot; count > 0; count--, zone++ ) 00301 { 00302 FT_Int delta; 00303 00304 00305 if ( count > 1 ) 00306 { 00307 delta = zone[0].org_ref - zone[1].org_ref; 00308 if ( zone->org_delta < delta ) 00309 zone->org_delta = delta; 00310 } 00311 00312 zone->org_top = zone->org_ref; 00313 zone->org_bottom = zone->org_delta + zone->org_ref; 00314 } 00315 } 00316 00317 /* expand top and bottom tables with blue fuzz */ 00318 { 00319 FT_Int dim, top, bot, delta; 00320 PSH_Blue_Zone zone; 00321 00322 00323 zone = top_table->zones; 00324 count = count_top; 00325 00326 for ( dim = 1; dim >= 0; dim-- ) 00327 { 00328 if ( count > 0 ) 00329 { 00330 /* expand the bottom of the lowest zone normally */ 00331 zone->org_bottom -= fuzz; 00332 00333 /* expand the top and bottom of intermediate zones; */ 00334 /* checking that the interval is smaller than the fuzz */ 00335 top = zone->org_top; 00336 00337 for ( count--; count > 0; count-- ) 00338 { 00339 bot = zone[1].org_bottom; 00340 delta = bot - top; 00341 00342 if ( delta < 2 * fuzz ) 00343 zone[0].org_top = zone[1].org_bottom = top + delta / 2; 00344 else 00345 { 00346 zone[0].org_top = top + fuzz; 00347 zone[1].org_bottom = bot - fuzz; 00348 } 00349 00350 zone++; 00351 top = zone->org_top; 00352 } 00353 00354 /* expand the top of the highest zone normally */ 00355 zone->org_top = top + fuzz; 00356 } 00357 zone = bot_table->zones; 00358 count = count_bot; 00359 } 00360 } 00361 } 00362 00363 00364 /* reset the blues table when the device transform changes */ 00365 static void 00366 psh_blues_scale_zones( PSH_Blues blues, 00367 FT_Fixed scale, 00368 FT_Pos delta ) 00369 { 00370 FT_UInt count; 00371 FT_UInt num; 00372 PSH_Blue_Table table = 0; 00373 00374 /* */ 00375 /* Determine whether we need to suppress overshoots or */ 00376 /* not. We simply need to compare the vertical scale */ 00377 /* parameter to the raw bluescale value. Here is why: */ 00378 /* */ 00379 /* We need to suppress overshoots for all pointsizes. */ 00380 /* At 300dpi that satisfies: */ 00381 /* */ 00382 /* pointsize < 240*bluescale + 0.49 */ 00383 /* */ 00384 /* This corresponds to: */ 00385 /* */ 00386 /* pixelsize < 1000*bluescale + 49/24 */ 00387 /* */ 00388 /* scale*EM_Size < 1000*bluescale + 49/24 */ 00389 /* */ 00390 /* However, for normal Type 1 fonts, EM_Size is 1000! */ 00391 /* We thus only check: */ 00392 /* */ 00393 /* scale < bluescale + 49/24000 */ 00394 /* */ 00395 /* which we shorten to */ 00396 /* */ 00397 /* "scale < bluescale" */ 00398 /* */ 00399 /* Note that `blue_scale' is stored 1000 times its real */ 00400 /* value, and that `scale' converts from font units to */ 00401 /* fractional pixels. */ 00402 /* */ 00403 00404 /* 1000 / 64 = 125 / 8 */ 00405 if ( scale >= 0x20C49BAL ) 00406 blues->no_overshoots = FT_BOOL( scale < blues->blue_scale * 8 / 125 ); 00407 else 00408 blues->no_overshoots = FT_BOOL( scale * 125 < blues->blue_scale * 8 ); 00409 00410 /* */ 00411 /* The blue threshold is the font units distance under */ 00412 /* which overshoots are suppressed due to the BlueShift */ 00413 /* even if the scale is greater than BlueScale. */ 00414 /* */ 00415 /* It is the smallest distance such that */ 00416 /* */ 00417 /* dist <= BlueShift && dist*scale <= 0.5 pixels */ 00418 /* */ 00419 { 00420 FT_Int threshold = blues->blue_shift; 00421 00422 00423 while ( threshold > 0 && FT_MulFix( threshold, scale ) > 32 ) 00424 threshold--; 00425 00426 blues->blue_threshold = threshold; 00427 } 00428 00429 for ( num = 0; num < 4; num++ ) 00430 { 00431 PSH_Blue_Zone zone; 00432 00433 00434 switch ( num ) 00435 { 00436 case 0: 00437 table = &blues->normal_top; 00438 break; 00439 case 1: 00440 table = &blues->normal_bottom; 00441 break; 00442 case 2: 00443 table = &blues->family_top; 00444 break; 00445 default: 00446 table = &blues->family_bottom; 00447 break; 00448 } 00449 00450 zone = table->zones; 00451 count = table->count; 00452 for ( ; count > 0; count--, zone++ ) 00453 { 00454 zone->cur_top = FT_MulFix( zone->org_top, scale ) + delta; 00455 zone->cur_bottom = FT_MulFix( zone->org_bottom, scale ) + delta; 00456 zone->cur_ref = FT_MulFix( zone->org_ref, scale ) + delta; 00457 zone->cur_delta = FT_MulFix( zone->org_delta, scale ); 00458 00459 /* round scaled reference position */ 00460 zone->cur_ref = FT_PIX_ROUND( zone->cur_ref ); 00461 00462 #if 0 00463 if ( zone->cur_ref > zone->cur_top ) 00464 zone->cur_ref -= 64; 00465 else if ( zone->cur_ref < zone->cur_bottom ) 00466 zone->cur_ref += 64; 00467 #endif 00468 } 00469 } 00470 00471 /* process the families now */ 00472 00473 for ( num = 0; num < 2; num++ ) 00474 { 00475 PSH_Blue_Zone zone1, zone2; 00476 FT_UInt count1, count2; 00477 PSH_Blue_Table normal, family; 00478 00479 00480 switch ( num ) 00481 { 00482 case 0: 00483 normal = &blues->normal_top; 00484 family = &blues->family_top; 00485 break; 00486 00487 default: 00488 normal = &blues->normal_bottom; 00489 family = &blues->family_bottom; 00490 } 00491 00492 zone1 = normal->zones; 00493 count1 = normal->count; 00494 00495 for ( ; count1 > 0; count1--, zone1++ ) 00496 { 00497 /* try to find a family zone whose reference position is less */ 00498 /* than 1 pixel far from the current zone */ 00499 zone2 = family->zones; 00500 count2 = family->count; 00501 00502 for ( ; count2 > 0; count2--, zone2++ ) 00503 { 00504 FT_Pos Delta; 00505 00506 00507 Delta = zone1->org_ref - zone2->org_ref; 00508 if ( Delta < 0 ) 00509 Delta = -Delta; 00510 00511 if ( FT_MulFix( Delta, scale ) < 64 ) 00512 { 00513 zone1->cur_top = zone2->cur_top; 00514 zone1->cur_bottom = zone2->cur_bottom; 00515 zone1->cur_ref = zone2->cur_ref; 00516 zone1->cur_delta = zone2->cur_delta; 00517 break; 00518 } 00519 } 00520 } 00521 } 00522 } 00523 00524 00525 FT_LOCAL_DEF( void ) 00526 psh_blues_snap_stem( PSH_Blues blues, 00527 FT_Int stem_top, 00528 FT_Int stem_bot, 00529 PSH_Alignment alignment ) 00530 { 00531 PSH_Blue_Table table; 00532 FT_UInt count; 00533 FT_Pos delta; 00534 PSH_Blue_Zone zone; 00535 FT_Int no_shoots; 00536 00537 00538 alignment->align = PSH_BLUE_ALIGN_NONE; 00539 00540 no_shoots = blues->no_overshoots; 00541 00542 /* look up stem top in top zones table */ 00543 table = &blues->normal_top; 00544 count = table->count; 00545 zone = table->zones; 00546 00547 for ( ; count > 0; count--, zone++ ) 00548 { 00549 delta = stem_top - zone->org_bottom; 00550 if ( delta < -blues->blue_fuzz ) 00551 break; 00552 00553 if ( stem_top <= zone->org_top + blues->blue_fuzz ) 00554 { 00555 if ( no_shoots || delta <= blues->blue_threshold ) 00556 { 00557 alignment->align |= PSH_BLUE_ALIGN_TOP; 00558 alignment->align_top = zone->cur_ref; 00559 } 00560 break; 00561 } 00562 } 00563 00564 /* look up stem bottom in bottom zones table */ 00565 table = &blues->normal_bottom; 00566 count = table->count; 00567 zone = table->zones + count-1; 00568 00569 for ( ; count > 0; count--, zone-- ) 00570 { 00571 delta = zone->org_top - stem_bot; 00572 if ( delta < -blues->blue_fuzz ) 00573 break; 00574 00575 if ( stem_bot >= zone->org_bottom - blues->blue_fuzz ) 00576 { 00577 if ( no_shoots || delta < blues->blue_threshold ) 00578 { 00579 alignment->align |= PSH_BLUE_ALIGN_BOT; 00580 alignment->align_bot = zone->cur_ref; 00581 } 00582 break; 00583 } 00584 } 00585 } 00586 00587 00588 /*************************************************************************/ 00589 /*************************************************************************/ 00590 /***** *****/ 00591 /***** GLOBAL HINTS *****/ 00592 /***** *****/ 00593 /*************************************************************************/ 00594 /*************************************************************************/ 00595 00596 static void 00597 psh_globals_destroy( PSH_Globals globals ) 00598 { 00599 if ( globals ) 00600 { 00601 FT_Memory memory; 00602 00603 00604 memory = globals->memory; 00605 globals->dimension[0].stdw.count = 0; 00606 globals->dimension[1].stdw.count = 0; 00607 00608 globals->blues.normal_top.count = 0; 00609 globals->blues.normal_bottom.count = 0; 00610 globals->blues.family_top.count = 0; 00611 globals->blues.family_bottom.count = 0; 00612 00613 FT_FREE( globals ); 00614 00615 #ifdef DEBUG_HINTER 00616 ps_debug_globals = 0; 00617 #endif 00618 } 00619 } 00620 00621 00622 static FT_Error 00623 psh_globals_new( FT_Memory memory, 00624 T1_Private* priv, 00625 PSH_Globals *aglobals ) 00626 { 00627 PSH_Globals globals = NULL; 00628 FT_Error error; 00629 00630 00631 if ( !FT_NEW( globals ) ) 00632 { 00633 FT_UInt count; 00634 FT_Short* read; 00635 00636 00637 globals->memory = memory; 00638 00639 /* copy standard widths */ 00640 { 00641 PSH_Dimension dim = &globals->dimension[1]; 00642 PSH_Width write = dim->stdw.widths; 00643 00644 00645 write->org = priv->standard_width[0]; 00646 write++; 00647 00648 read = priv->snap_widths; 00649 for ( count = priv->num_snap_widths; count > 0; count-- ) 00650 { 00651 write->org = *read; 00652 write++; 00653 read++; 00654 } 00655 00656 dim->stdw.count = priv->num_snap_widths + 1; 00657 } 00658 00659 /* copy standard heights */ 00660 { 00661 PSH_Dimension dim = &globals->dimension[0]; 00662 PSH_Width write = dim->stdw.widths; 00663 00664 00665 write->org = priv->standard_height[0]; 00666 write++; 00667 read = priv->snap_heights; 00668 for ( count = priv->num_snap_heights; count > 0; count-- ) 00669 { 00670 write->org = *read; 00671 write++; 00672 read++; 00673 } 00674 00675 dim->stdw.count = priv->num_snap_heights + 1; 00676 } 00677 00678 /* copy blue zones */ 00679 psh_blues_set_zones( &globals->blues, priv->num_blue_values, 00680 priv->blue_values, priv->num_other_blues, 00681 priv->other_blues, priv->blue_fuzz, 0 ); 00682 00683 psh_blues_set_zones( &globals->blues, priv->num_family_blues, 00684 priv->family_blues, priv->num_family_other_blues, 00685 priv->family_other_blues, priv->blue_fuzz, 1 ); 00686 00687 globals->blues.blue_scale = priv->blue_scale; 00688 globals->blues.blue_shift = priv->blue_shift; 00689 globals->blues.blue_fuzz = priv->blue_fuzz; 00690 00691 globals->dimension[0].scale_mult = 0; 00692 globals->dimension[0].scale_delta = 0; 00693 globals->dimension[1].scale_mult = 0; 00694 globals->dimension[1].scale_delta = 0; 00695 00696 #ifdef DEBUG_HINTER 00697 ps_debug_globals = globals; 00698 #endif 00699 } 00700 00701 *aglobals = globals; 00702 return error; 00703 } 00704 00705 00706 FT_LOCAL_DEF( FT_Error ) 00707 psh_globals_set_scale( PSH_Globals globals, 00708 FT_Fixed x_scale, 00709 FT_Fixed y_scale, 00710 FT_Fixed x_delta, 00711 FT_Fixed y_delta ) 00712 { 00713 PSH_Dimension dim = &globals->dimension[0]; 00714 00715 00716 dim = &globals->dimension[0]; 00717 if ( x_scale != dim->scale_mult || 00718 x_delta != dim->scale_delta ) 00719 { 00720 dim->scale_mult = x_scale; 00721 dim->scale_delta = x_delta; 00722 00723 psh_globals_scale_widths( globals, 0 ); 00724 } 00725 00726 dim = &globals->dimension[1]; 00727 if ( y_scale != dim->scale_mult || 00728 y_delta != dim->scale_delta ) 00729 { 00730 dim->scale_mult = y_scale; 00731 dim->scale_delta = y_delta; 00732 00733 psh_globals_scale_widths( globals, 1 ); 00734 psh_blues_scale_zones( &globals->blues, y_scale, y_delta ); 00735 } 00736 00737 return 0; 00738 } 00739 00740 00741 FT_LOCAL_DEF( void ) 00742 psh_globals_funcs_init( PSH_Globals_FuncsRec* funcs ) 00743 { 00744 funcs->create = psh_globals_new; 00745 funcs->set_scale = psh_globals_set_scale; 00746 funcs->destroy = psh_globals_destroy; 00747 } 00748 00749 00750 /* END */ Generated on Sat May 26 2012 04:32:54 for ReactOS by
1.7.6.1
|