00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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
00034
00035
00036
00037
00038
00039
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;
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
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
00128
00129
00130
00131
00132
00133
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
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
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
00195
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
00231
00232
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
00258
00259 top_table->count = 0;
00260 bot_table->count = 0;
00261
00262
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
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
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
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
00331 zone->org_bottom -= fuzz;
00332
00333
00334
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
00355 zone->org_top = top + fuzz;
00356 }
00357 zone = bot_table->zones;
00358 count = count_bot;
00359 }
00360 }
00361 }
00362
00363
00364
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
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
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
00412
00413
00414
00415
00416
00417
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
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
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
00498
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
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
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
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;
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
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
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
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