1 /***************************************************************************/ |
|
2 /* */ |
|
3 /* pshglob.c */ |
|
4 /* */ |
|
5 /* PostScript hinter global hinting management (body). */ |
|
6 /* Inspired by the new auto-hinter module. */ |
|
7 /* */ |
|
8 /* Copyright 2001, 2002, 2003, 2004, 2006, 2010 by */ |
|
9 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ |
|
10 /* */ |
|
11 /* This file is part of the FreeType project, and may only be used */ |
|
12 /* modified and distributed under the terms of the FreeType project */ |
|
13 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ |
|
14 /* this file you indicate that you have read the license and */ |
|
15 /* understand and accept it fully. */ |
|
16 /* */ |
|
17 /***************************************************************************/ |
|
18 |
|
19 |
|
20 #include <ft2build.h> |
|
21 #include FT_FREETYPE_H |
|
22 #include FT_INTERNAL_OBJECTS_H |
|
23 #include "pshglob.h" |
|
24 |
|
25 #ifdef DEBUG_HINTER |
|
26 PSH_Globals ps_debug_globals = 0; |
|
27 #endif |
|
28 |
|
29 |
|
30 /*************************************************************************/ |
|
31 /*************************************************************************/ |
|
32 /***** *****/ |
|
33 /***** STANDARD WIDTHS *****/ |
|
34 /***** *****/ |
|
35 /*************************************************************************/ |
|
36 /*************************************************************************/ |
|
37 |
|
38 |
|
39 /* scale the widths/heights table */ |
|
40 static void |
|
41 psh_globals_scale_widths( PSH_Globals globals, |
|
42 FT_UInt direction ) |
|
43 { |
|
44 PSH_Dimension dim = &globals->dimension[direction]; |
|
45 PSH_Widths stdw = &dim->stdw; |
|
46 FT_UInt count = stdw->count; |
|
47 PSH_Width width = stdw->widths; |
|
48 PSH_Width stand = width; /* standard width/height */ |
|
49 FT_Fixed scale = dim->scale_mult; |
|
50 |
|
51 |
|
52 if ( count > 0 ) |
|
53 { |
|
54 width->cur = FT_MulFix( width->org, scale ); |
|
55 width->fit = FT_PIX_ROUND( width->cur ); |
|
56 |
|
57 width++; |
|
58 count--; |
|
59 |
|
60 for ( ; count > 0; count--, width++ ) |
|
61 { |
|
62 FT_Pos w, dist; |
|
63 |
|
64 |
|
65 w = FT_MulFix( width->org, scale ); |
|
66 dist = w - stand->cur; |
|
67 |
|
68 if ( dist < 0 ) |
|
69 dist = -dist; |
|
70 |
|
71 if ( dist < 128 ) |
|
72 w = stand->cur; |
|
73 |
|
74 width->cur = w; |
|
75 width->fit = FT_PIX_ROUND( w ); |
|
76 } |
|
77 } |
|
78 } |
|
79 |
|
80 |
|
81 #if 0 |
|
82 |
|
83 /* org_width is is font units, result in device pixels, 26.6 format */ |
|
84 FT_LOCAL_DEF( FT_Pos ) |
|
85 psh_dimension_snap_width( PSH_Dimension dimension, |
|
86 FT_Int org_width ) |
|
87 { |
|
88 FT_UInt n; |
|
89 FT_Pos width = FT_MulFix( org_width, dimension->scale_mult ); |
|
90 FT_Pos best = 64 + 32 + 2; |
|
91 FT_Pos reference = width; |
|
92 |
|
93 |
|
94 for ( n = 0; n < dimension->stdw.count; n++ ) |
|
95 { |
|
96 FT_Pos w; |
|
97 FT_Pos dist; |
|
98 |
|
99 |
|
100 w = dimension->stdw.widths[n].cur; |
|
101 dist = width - w; |
|
102 if ( dist < 0 ) |
|
103 dist = -dist; |
|
104 if ( dist < best ) |
|
105 { |
|
106 best = dist; |
|
107 reference = w; |
|
108 } |
|
109 } |
|
110 |
|
111 if ( width >= reference ) |
|
112 { |
|
113 width -= 0x21; |
|
114 if ( width < reference ) |
|
115 width = reference; |
|
116 } |
|
117 else |
|
118 { |
|
119 width += 0x21; |
|
120 if ( width > reference ) |
|
121 width = reference; |
|
122 } |
|
123 |
|
124 return width; |
|
125 } |
|
126 |
|
127 #endif /* 0 */ |
|
128 |
|
129 |
|
130 /*************************************************************************/ |
|
131 /*************************************************************************/ |
|
132 /***** *****/ |
|
133 /***** BLUE ZONES *****/ |
|
134 /***** *****/ |
|
135 /*************************************************************************/ |
|
136 /*************************************************************************/ |
|
137 |
|
138 static void |
|
139 psh_blues_set_zones_0( PSH_Blues target, |
|
140 FT_Bool is_others, |
|
141 FT_UInt read_count, |
|
142 FT_Short* read, |
|
143 PSH_Blue_Table top_table, |
|
144 PSH_Blue_Table bot_table ) |
|
145 { |
|
146 FT_UInt count_top = top_table->count; |
|
147 FT_UInt count_bot = bot_table->count; |
|
148 FT_Bool first = 1; |
|
149 |
|
150 FT_UNUSED( target ); |
|
151 |
|
152 |
|
153 for ( ; read_count > 1; read_count -= 2 ) |
|
154 { |
|
155 FT_Int reference, delta; |
|
156 FT_UInt count; |
|
157 PSH_Blue_Zone zones, zone; |
|
158 FT_Bool top; |
|
159 |
|
160 |
|
161 /* read blue zone entry, and select target top/bottom zone */ |
|
162 top = 0; |
|
163 if ( first || is_others ) |
|
164 { |
|
165 reference = read[1]; |
|
166 delta = read[0] - reference; |
|
167 |
|
168 zones = bot_table->zones; |
|
169 count = count_bot; |
|
170 first = 0; |
|
171 } |
|
172 else |
|
173 { |
|
174 reference = read[0]; |
|
175 delta = read[1] - reference; |
|
176 |
|
177 zones = top_table->zones; |
|
178 count = count_top; |
|
179 top = 1; |
|
180 } |
|
181 |
|
182 /* insert into sorted table */ |
|
183 zone = zones; |
|
184 for ( ; count > 0; count--, zone++ ) |
|
185 { |
|
186 if ( reference < zone->org_ref ) |
|
187 break; |
|
188 |
|
189 if ( reference == zone->org_ref ) |
|
190 { |
|
191 FT_Int delta0 = zone->org_delta; |
|
192 |
|
193 |
|
194 /* we have two zones on the same reference position -- */ |
|
195 /* only keep the largest one */ |
|
196 if ( delta < 0 ) |
|
197 { |
|
198 if ( delta < delta0 ) |
|
199 zone->org_delta = delta; |
|
200 } |
|
201 else |
|
202 { |
|
203 if ( delta > delta0 ) |
|
204 zone->org_delta = delta; |
|
205 } |
|
206 goto Skip; |
|
207 } |
|
208 } |
|
209 |
|
210 for ( ; count > 0; count-- ) |
|
211 zone[count] = zone[count-1]; |
|
212 |
|
213 zone->org_ref = reference; |
|
214 zone->org_delta = delta; |
|
215 |
|
216 if ( top ) |
|
217 count_top++; |
|
218 else |
|
219 count_bot++; |
|
220 |
|
221 Skip: |
|
222 read += 2; |
|
223 } |
|
224 |
|
225 top_table->count = count_top; |
|
226 bot_table->count = count_bot; |
|
227 } |
|
228 |
|
229 |
|
230 /* Re-read blue zones from the original fonts and store them into out */ |
|
231 /* private structure. This function re-orders, sanitizes and */ |
|
232 /* fuzz-expands the zones as well. */ |
|
233 static void |
|
234 psh_blues_set_zones( PSH_Blues target, |
|
235 FT_UInt count, |
|
236 FT_Short* blues, |
|
237 FT_UInt count_others, |
|
238 FT_Short* other_blues, |
|
239 FT_Int fuzz, |
|
240 FT_Int family ) |
|
241 { |
|
242 PSH_Blue_Table top_table, bot_table; |
|
243 FT_Int count_top, count_bot; |
|
244 |
|
245 |
|
246 if ( family ) |
|
247 { |
|
248 top_table = &target->family_top; |
|
249 bot_table = &target->family_bottom; |
|
250 } |
|
251 else |
|
252 { |
|
253 top_table = &target->normal_top; |
|
254 bot_table = &target->normal_bottom; |
|
255 } |
|
256 |
|
257 /* read the input blue zones, and build two sorted tables */ |
|
258 /* (one for the top zones, the other for the bottom zones) */ |
|
259 top_table->count = 0; |
|
260 bot_table->count = 0; |
|
261 |
|
262 /* first, the blues */ |
|
263 psh_blues_set_zones_0( target, 0, |
|
264 count, blues, top_table, bot_table ); |
|
265 psh_blues_set_zones_0( target, 1, |
|
266 count_others, other_blues, top_table, bot_table ); |
|
267 |
|
268 count_top = top_table->count; |
|
269 count_bot = bot_table->count; |
|
270 |
|
271 /* sanitize top table */ |
|
272 if ( count_top > 0 ) |
|
273 { |
|
274 PSH_Blue_Zone zone = top_table->zones; |
|
275 |
|
276 |
|
277 for ( count = count_top; count > 0; count--, zone++ ) |
|
278 { |
|
279 FT_Int delta; |
|
280 |
|
281 |
|
282 if ( count > 1 ) |
|
283 { |
|
284 delta = zone[1].org_ref - zone[0].org_ref; |
|
285 if ( zone->org_delta > delta ) |
|
286 zone->org_delta = delta; |
|
287 } |
|
288 |
|
289 zone->org_bottom = zone->org_ref; |
|
290 zone->org_top = zone->org_delta + zone->org_ref; |
|
291 } |
|
292 } |
|
293 |
|
294 /* sanitize bottom table */ |
|
295 if ( count_bot > 0 ) |
|
296 { |
|
297 PSH_Blue_Zone zone = bot_table->zones; |
|
298 |
|
299 |
|
300 for ( count = count_bot; count > 0; count--, zone++ ) |
|
301 { |
|
302 FT_Int delta; |
|
303 |
|
304 |
|
305 if ( count > 1 ) |
|
306 { |
|
307 delta = zone[0].org_ref - zone[1].org_ref; |
|
308 if ( zone->org_delta < delta ) |
|
309 zone->org_delta = delta; |
|
310 } |
|
311 |
|
312 zone->org_top = zone->org_ref; |
|
313 zone->org_bottom = zone->org_delta + zone->org_ref; |
|
314 } |
|
315 } |
|
316 |
|
317 /* expand top and bottom tables with blue fuzz */ |
|
318 { |
|
319 FT_Int dim, top, bot, delta; |
|
320 PSH_Blue_Zone zone; |
|
321 |
|
322 |
|
323 zone = top_table->zones; |
|
324 count = count_top; |
|
325 |
|
326 for ( dim = 1; dim >= 0; dim-- ) |
|
327 { |
|
328 if ( count > 0 ) |
|
329 { |
|
330 /* expand the bottom of the lowest zone normally */ |
|
331 zone->org_bottom -= fuzz; |
|
332 |
|
333 /* expand the top and bottom of intermediate zones; */ |
|
334 /* checking that the interval is smaller than the fuzz */ |
|
335 top = zone->org_top; |
|
336 |
|
337 for ( count--; count > 0; count-- ) |
|
338 { |
|
339 bot = zone[1].org_bottom; |
|
340 delta = bot - top; |
|
341 |
|
342 if ( delta < 2 * fuzz ) |
|
343 zone[0].org_top = zone[1].org_bottom = top + delta / 2; |
|
344 else |
|
345 { |
|
346 zone[0].org_top = top + fuzz; |
|
347 zone[1].org_bottom = bot - fuzz; |
|
348 } |
|
349 |
|
350 zone++; |
|
351 top = zone->org_top; |
|
352 } |
|
353 |
|
354 /* expand the top of the highest zone normally */ |
|
355 zone->org_top = top + fuzz; |
|
356 } |
|
357 zone = bot_table->zones; |
|
358 count = count_bot; |
|
359 } |
|
360 } |
|
361 } |
|
362 |
|
363 |
|
364 /* reset the blues table when the device transform changes */ |
|
365 static void |
|
366 psh_blues_scale_zones( PSH_Blues blues, |
|
367 FT_Fixed scale, |
|
368 FT_Pos delta ) |
|
369 { |
|
370 FT_UInt count; |
|
371 FT_UInt num; |
|
372 PSH_Blue_Table table = 0; |
|
373 |
|
374 /* */ |
|
375 /* Determine whether we need to suppress overshoots or */ |
|
376 /* not. We simply need to compare the vertical scale */ |
|
377 /* parameter to the raw bluescale value. Here is why: */ |
|
378 /* */ |
|
379 /* We need to suppress overshoots for all pointsizes. */ |
|
380 /* At 300dpi that satisfies: */ |
|
381 /* */ |
|
382 /* pointsize < 240*bluescale + 0.49 */ |
|
383 /* */ |
|
384 /* This corresponds to: */ |
|
385 /* */ |
|
386 /* pixelsize < 1000*bluescale + 49/24 */ |
|
387 /* */ |
|
388 /* scale*EM_Size < 1000*bluescale + 49/24 */ |
|
389 /* */ |
|
390 /* However, for normal Type 1 fonts, EM_Size is 1000! */ |
|
391 /* We thus only check: */ |
|
392 /* */ |
|
393 /* scale < bluescale + 49/24000 */ |
|
394 /* */ |
|
395 /* which we shorten to */ |
|
396 /* */ |
|
397 /* "scale < bluescale" */ |
|
398 /* */ |
|
399 /* Note that `blue_scale' is stored 1000 times its real */ |
|
400 /* value, and that `scale' converts from font units to */ |
|
401 /* fractional pixels. */ |
|
402 /* */ |
|
403 |
|
404 /* 1000 / 64 = 125 / 8 */ |
|
405 if ( scale >= 0x20C49BAL ) |
|
406 blues->no_overshoots = FT_BOOL( scale < blues->blue_scale * 8 / 125 ); |
|
407 else |
|
408 blues->no_overshoots = FT_BOOL( scale * 125 < blues->blue_scale * 8 ); |
|
409 |
|
410 /* */ |
|
411 /* The blue threshold is the font units distance under */ |
|
412 /* which overshoots are suppressed due to the BlueShift */ |
|
413 /* even if the scale is greater than BlueScale. */ |
|
414 /* */ |
|
415 /* It is the smallest distance such that */ |
|
416 /* */ |
|
417 /* dist <= BlueShift && dist*scale <= 0.5 pixels */ |
|
418 /* */ |
|
419 { |
|
420 FT_Int threshold = blues->blue_shift; |
|
421 |
|
422 |
|
423 while ( threshold > 0 && FT_MulFix( threshold, scale ) > 32 ) |
|
424 threshold--; |
|
425 |
|
426 blues->blue_threshold = threshold; |
|
427 } |
|
428 |
|
429 for ( num = 0; num < 4; num++ ) |
|
430 { |
|
431 PSH_Blue_Zone zone; |
|
432 |
|
433 |
|
434 switch ( num ) |
|
435 { |
|
436 case 0: |
|
437 table = &blues->normal_top; |
|
438 break; |
|
439 case 1: |
|
440 table = &blues->normal_bottom; |
|
441 break; |
|
442 case 2: |
|
443 table = &blues->family_top; |
|
444 break; |
|
445 default: |
|
446 table = &blues->family_bottom; |
|
447 break; |
|
448 } |
|
449 |
|
450 zone = table->zones; |
|
451 count = table->count; |
|
452 for ( ; count > 0; count--, zone++ ) |
|
453 { |
|
454 zone->cur_top = FT_MulFix( zone->org_top, scale ) + delta; |
|
455 zone->cur_bottom = FT_MulFix( zone->org_bottom, scale ) + delta; |
|
456 zone->cur_ref = FT_MulFix( zone->org_ref, scale ) + delta; |
|
457 zone->cur_delta = FT_MulFix( zone->org_delta, scale ); |
|
458 |
|
459 /* round scaled reference position */ |
|
460 zone->cur_ref = FT_PIX_ROUND( zone->cur_ref ); |
|
461 |
|
462 #if 0 |
|
463 if ( zone->cur_ref > zone->cur_top ) |
|
464 zone->cur_ref -= 64; |
|
465 else if ( zone->cur_ref < zone->cur_bottom ) |
|
466 zone->cur_ref += 64; |
|
467 #endif |
|
468 } |
|
469 } |
|
470 |
|
471 /* process the families now */ |
|
472 |
|
473 for ( num = 0; num < 2; num++ ) |
|
474 { |
|
475 PSH_Blue_Zone zone1, zone2; |
|
476 FT_UInt count1, count2; |
|
477 PSH_Blue_Table normal, family; |
|
478 |
|
479 |
|
480 switch ( num ) |
|
481 { |
|
482 case 0: |
|
483 normal = &blues->normal_top; |
|
484 family = &blues->family_top; |
|
485 break; |
|
486 |
|
487 default: |
|
488 normal = &blues->normal_bottom; |
|
489 family = &blues->family_bottom; |
|
490 } |
|
491 |
|
492 zone1 = normal->zones; |
|
493 count1 = normal->count; |
|
494 |
|
495 for ( ; count1 > 0; count1--, zone1++ ) |
|
496 { |
|
497 /* try to find a family zone whose reference position is less */ |
|
498 /* than 1 pixel far from the current zone */ |
|
499 zone2 = family->zones; |
|
500 count2 = family->count; |
|
501 |
|
502 for ( ; count2 > 0; count2--, zone2++ ) |
|
503 { |
|
504 FT_Pos Delta; |
|
505 |
|
506 |
|
507 Delta = zone1->org_ref - zone2->org_ref; |
|
508 if ( Delta < 0 ) |
|
509 Delta = -Delta; |
|
510 |
|
511 if ( FT_MulFix( Delta, scale ) < 64 ) |
|
512 { |
|
513 zone1->cur_top = zone2->cur_top; |
|
514 zone1->cur_bottom = zone2->cur_bottom; |
|
515 zone1->cur_ref = zone2->cur_ref; |
|
516 zone1->cur_delta = zone2->cur_delta; |
|
517 break; |
|
518 } |
|
519 } |
|
520 } |
|
521 } |
|
522 } |
|
523 |
|
524 |
|
525 FT_LOCAL_DEF( void ) |
|
526 psh_blues_snap_stem( PSH_Blues blues, |
|
527 FT_Int stem_top, |
|
528 FT_Int stem_bot, |
|
529 PSH_Alignment alignment ) |
|
530 { |
|
531 PSH_Blue_Table table; |
|
532 FT_UInt count; |
|
533 FT_Pos delta; |
|
534 PSH_Blue_Zone zone; |
|
535 FT_Int no_shoots; |
|
536 |
|
537 |
|
538 alignment->align = PSH_BLUE_ALIGN_NONE; |
|
539 |
|
540 no_shoots = blues->no_overshoots; |
|
541 |
|
542 /* look up stem top in top zones table */ |
|
543 table = &blues->normal_top; |
|
544 count = table->count; |
|
545 zone = table->zones; |
|
546 |
|
547 for ( ; count > 0; count--, zone++ ) |
|
548 { |
|
549 delta = stem_top - zone->org_bottom; |
|
550 if ( delta < -blues->blue_fuzz ) |
|
551 break; |
|
552 |
|
553 if ( stem_top <= zone->org_top + blues->blue_fuzz ) |
|
554 { |
|
555 if ( no_shoots || delta <= blues->blue_threshold ) |
|
556 { |
|
557 alignment->align |= PSH_BLUE_ALIGN_TOP; |
|
558 alignment->align_top = zone->cur_ref; |
|
559 } |
|
560 break; |
|
561 } |
|
562 } |
|
563 |
|
564 /* look up stem bottom in bottom zones table */ |
|
565 table = &blues->normal_bottom; |
|
566 count = table->count; |
|
567 zone = table->zones + count-1; |
|
568 |
|
569 for ( ; count > 0; count--, zone-- ) |
|
570 { |
|
571 delta = zone->org_top - stem_bot; |
|
572 if ( delta < -blues->blue_fuzz ) |
|
573 break; |
|
574 |
|
575 if ( stem_bot >= zone->org_bottom - blues->blue_fuzz ) |
|
576 { |
|
577 if ( no_shoots || delta < blues->blue_threshold ) |
|
578 { |
|
579 alignment->align |= PSH_BLUE_ALIGN_BOT; |
|
580 alignment->align_bot = zone->cur_ref; |
|
581 } |
|
582 break; |
|
583 } |
|
584 } |
|
585 } |
|
586 |
|
587 |
|
588 /*************************************************************************/ |
|
589 /*************************************************************************/ |
|
590 /***** *****/ |
|
591 /***** GLOBAL HINTS *****/ |
|
592 /***** *****/ |
|
593 /*************************************************************************/ |
|
594 /*************************************************************************/ |
|
595 |
|
596 static void |
|
597 psh_globals_destroy( PSH_Globals globals ) |
|
598 { |
|
599 if ( globals ) |
|
600 { |
|
601 FT_Memory memory; |
|
602 |
|
603 |
|
604 memory = globals->memory; |
|
605 globals->dimension[0].stdw.count = 0; |
|
606 globals->dimension[1].stdw.count = 0; |
|
607 |
|
608 globals->blues.normal_top.count = 0; |
|
609 globals->blues.normal_bottom.count = 0; |
|
610 globals->blues.family_top.count = 0; |
|
611 globals->blues.family_bottom.count = 0; |
|
612 |
|
613 FT_FREE( globals ); |
|
614 |
|
615 #ifdef DEBUG_HINTER |
|
616 ps_debug_globals = 0; |
|
617 #endif |
|
618 } |
|
619 } |
|
620 |
|
621 |
|
622 static FT_Error |
|
623 psh_globals_new( FT_Memory memory, |
|
624 T1_Private* priv, |
|
625 PSH_Globals *aglobals ) |
|
626 { |
|
627 PSH_Globals globals = NULL; |
|
628 FT_Error error; |
|
629 |
|
630 |
|
631 if ( !FT_NEW( globals ) ) |
|
632 { |
|
633 FT_UInt count; |
|
634 FT_Short* read; |
|
635 |
|
636 |
|
637 globals->memory = memory; |
|
638 |
|
639 /* copy standard widths */ |
|
640 { |
|
641 PSH_Dimension dim = &globals->dimension[1]; |
|
642 PSH_Width write = dim->stdw.widths; |
|
643 |
|
644 |
|
645 write->org = priv->standard_width[0]; |
|
646 write++; |
|
647 |
|
648 read = priv->snap_widths; |
|
649 for ( count = priv->num_snap_widths; count > 0; count-- ) |
|
650 { |
|
651 write->org = *read; |
|
652 write++; |
|
653 read++; |
|
654 } |
|
655 |
|
656 dim->stdw.count = priv->num_snap_widths + 1; |
|
657 } |
|
658 |
|
659 /* copy standard heights */ |
|
660 { |
|
661 PSH_Dimension dim = &globals->dimension[0]; |
|
662 PSH_Width write = dim->stdw.widths; |
|
663 |
|
664 |
|
665 write->org = priv->standard_height[0]; |
|
666 write++; |
|
667 read = priv->snap_heights; |
|
668 for ( count = priv->num_snap_heights; count > 0; count-- ) |
|
669 { |
|
670 write->org = *read; |
|
671 write++; |
|
672 read++; |
|
673 } |
|
674 |
|
675 dim->stdw.count = priv->num_snap_heights + 1; |
|
676 } |
|
677 |
|
678 /* copy blue zones */ |
|
679 psh_blues_set_zones( &globals->blues, priv->num_blue_values, |
|
680 priv->blue_values, priv->num_other_blues, |
|
681 priv->other_blues, priv->blue_fuzz, 0 ); |
|
682 |
|
683 psh_blues_set_zones( &globals->blues, priv->num_family_blues, |
|
684 priv->family_blues, priv->num_family_other_blues, |
|
685 priv->family_other_blues, priv->blue_fuzz, 1 ); |
|
686 |
|
687 globals->blues.blue_scale = priv->blue_scale; |
|
688 globals->blues.blue_shift = priv->blue_shift; |
|
689 globals->blues.blue_fuzz = priv->blue_fuzz; |
|
690 |
|
691 globals->dimension[0].scale_mult = 0; |
|
692 globals->dimension[0].scale_delta = 0; |
|
693 globals->dimension[1].scale_mult = 0; |
|
694 globals->dimension[1].scale_delta = 0; |
|
695 |
|
696 #ifdef DEBUG_HINTER |
|
697 ps_debug_globals = globals; |
|
698 #endif |
|
699 } |
|
700 |
|
701 *aglobals = globals; |
|
702 return error; |
|
703 } |
|
704 |
|
705 |
|
706 FT_LOCAL_DEF( FT_Error ) |
|
707 psh_globals_set_scale( PSH_Globals globals, |
|
708 FT_Fixed x_scale, |
|
709 FT_Fixed y_scale, |
|
710 FT_Fixed x_delta, |
|
711 FT_Fixed y_delta ) |
|
712 { |
|
713 PSH_Dimension dim = &globals->dimension[0]; |
|
714 |
|
715 |
|
716 dim = &globals->dimension[0]; |
|
717 if ( x_scale != dim->scale_mult || |
|
718 x_delta != dim->scale_delta ) |
|
719 { |
|
720 dim->scale_mult = x_scale; |
|
721 dim->scale_delta = x_delta; |
|
722 |
|
723 psh_globals_scale_widths( globals, 0 ); |
|
724 } |
|
725 |
|
726 dim = &globals->dimension[1]; |
|
727 if ( y_scale != dim->scale_mult || |
|
728 y_delta != dim->scale_delta ) |
|
729 { |
|
730 dim->scale_mult = y_scale; |
|
731 dim->scale_delta = y_delta; |
|
732 |
|
733 psh_globals_scale_widths( globals, 1 ); |
|
734 psh_blues_scale_zones( &globals->blues, y_scale, y_delta ); |
|
735 } |
|
736 |
|
737 return 0; |
|
738 } |
|
739 |
|
740 |
|
741 FT_LOCAL_DEF( void ) |
|
742 psh_globals_funcs_init( PSH_Globals_FuncsRec* funcs ) |
|
743 { |
|
744 funcs->create = psh_globals_new; |
|
745 funcs->set_scale = psh_globals_set_scale; |
|
746 funcs->destroy = psh_globals_destroy; |
|
747 } |
|
748 |
|
749 |
|
750 /* END */ |
|