Alexei Podtelezhnikov pushed to branch hdmx-advances at FreeType / FreeType
Commits:
-
34fc55de
by Alexei Podtelezhnikov at 2021-12-10T21:55:08-05:00
-
2e3455b1
by Alexei Podtelezhnikov at 2021-12-10T22:05:51-05:00
-
fa353701
by Alexei Podtelezhnikov at 2021-12-10T22:23:56-05:00
-
eaa10b99
by Alexei Podtelezhnikov at 2021-12-10T22:29:21-05:00
-
0dc811b5
by Alexei Podtelezhnikov at 2021-12-10T22:32:05-05:00
4 changed files:
- include/freetype/internal/tttypes.h
- src/truetype/ttgload.c
- src/truetype/ttinterp.c
- src/truetype/ttpload.c
Changes:
... | ... | @@ -1390,8 +1390,8 @@ FT_BEGIN_HEADER |
1390 | 1390 |
* hdmx_record_size ::
|
1391 | 1391 |
* The size of a single hdmx record.
|
1392 | 1392 |
*
|
1393 |
- * hdmx_record_sizes ::
|
|
1394 |
- * An array holding the ppem sizes available in the 'hdmx' table.
|
|
1393 |
+ * hdmx_records ::
|
|
1394 |
+ * A array of pointers to the 'hdmx' table records sorted by ppem.
|
|
1395 | 1395 |
*
|
1396 | 1396 |
* sbit_table ::
|
1397 | 1397 |
* A pointer to the font's embedded bitmap location table.
|
... | ... | @@ -1605,7 +1605,7 @@ FT_BEGIN_HEADER |
1605 | 1605 |
FT_ULong hdmx_table_size;
|
1606 | 1606 |
FT_UInt hdmx_record_count;
|
1607 | 1607 |
FT_ULong hdmx_record_size;
|
1608 |
- FT_Byte* hdmx_record_sizes;
|
|
1608 |
+ FT_Byte** hdmx_records;
|
|
1609 | 1609 |
|
1610 | 1610 |
FT_Byte* sbit_table;
|
1611 | 1611 |
FT_ULong sbit_table_size;
|
... | ... | @@ -1769,6 +1769,9 @@ FT_BEGIN_HEADER |
1769 | 1769 |
/* since version 2.6.2 */
|
1770 | 1770 |
FT_ListRec composites;
|
1771 | 1771 |
|
1772 |
+ /* since version 2.11.2 */
|
|
1773 |
+ FT_Byte* widthp;
|
|
1774 |
+ |
|
1772 | 1775 |
} TT_LoaderRec;
|
1773 | 1776 |
|
1774 | 1777 |
|
... | ... | @@ -2230,10 +2230,6 @@ |
2230 | 2230 |
FT_UInt glyph_index )
|
2231 | 2231 |
{
|
2232 | 2232 |
TT_Face face = loader->face;
|
2233 |
-#if defined TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY || \
|
|
2234 |
- defined TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
|
|
2235 |
- TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face );
|
|
2236 |
-#endif
|
|
2237 | 2233 |
|
2238 | 2234 |
FT_BBox bbox;
|
2239 | 2235 |
FT_Fixed y_scale;
|
... | ... | @@ -2256,37 +2252,10 @@ |
2256 | 2252 |
|
2257 | 2253 |
glyph->metrics.horiBearingX = bbox.xMin;
|
2258 | 2254 |
glyph->metrics.horiBearingY = bbox.yMax;
|
2259 |
- glyph->metrics.horiAdvance = SUB_LONG(loader->pp2.x, loader->pp1.x);
|
|
2260 |
- |
|
2261 |
- /* Adjust advance width to the value contained in the hdmx table */
|
|
2262 |
- /* unless FT_LOAD_COMPUTE_METRICS is set or backward compatibility */
|
|
2263 |
- /* mode of the v40 interpreter is active. See `ttinterp.h' for */
|
|
2264 |
- /* details on backward compatibility mode. */
|
|
2265 |
- if ( IS_HINTED( loader->load_flags ) &&
|
|
2266 |
- !( loader->load_flags & FT_LOAD_COMPUTE_METRICS ) &&
|
|
2267 |
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
|
|
2268 |
- !( driver->interpreter_version == TT_INTERPRETER_VERSION_40 &&
|
|
2269 |
- ( loader->exec && loader->exec->backward_compatibility ) ) &&
|
|
2270 |
-#endif
|
|
2271 |
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
|
|
2272 |
- !( driver->interpreter_version == TT_INTERPRETER_VERSION_38 &&
|
|
2273 |
- !SPH_OPTION_BITMAP_WIDTHS &&
|
|
2274 |
- FT_LOAD_TARGET_MODE( loader->load_flags ) !=
|
|
2275 |
- FT_RENDER_MODE_MONO &&
|
|
2276 |
- ( loader->exec && !loader->exec->compatible_widths ) ) &&
|
|
2277 |
-#endif
|
|
2278 |
- !face->postscript.isFixedPitch )
|
|
2279 |
- {
|
|
2280 |
- FT_Byte* widthp;
|
|
2281 |
- |
|
2282 |
- |
|
2283 |
- widthp = tt_face_get_device_metrics( face,
|
|
2284 |
- size->metrics->x_ppem,
|
|
2285 |
- glyph_index );
|
|
2286 |
- |
|
2287 |
- if ( widthp )
|
|
2288 |
- glyph->metrics.horiAdvance = *widthp * 64;
|
|
2289 |
- }
|
|
2255 |
+ if ( loader->widthp )
|
|
2256 |
+ glyph->metrics.horiAdvance = loader->widthp[glyph_index] * 64;
|
|
2257 |
+ else
|
|
2258 |
+ glyph->metrics.horiAdvance = SUB_LONG(loader->pp2.x, loader->pp1.x);
|
|
2290 | 2259 |
|
2291 | 2260 |
/* set glyph dimensions */
|
2292 | 2261 |
glyph->metrics.width = SUB_LONG( bbox.xMax, bbox.xMin );
|
... | ... | @@ -2720,11 +2689,64 @@ |
2720 | 2689 |
if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 &&
|
2721 | 2690 |
exec->GS.instruct_control & 4 )
|
2722 | 2691 |
exec->ignore_x_mode = 0;
|
2723 |
-#endif
|
|
2692 |
+ |
|
2693 |
+ exec->iup_called = FALSE;
|
|
2694 |
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
|
|
2695 |
+ |
|
2696 |
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
|
|
2697 |
+ /*
|
|
2698 |
+ * Toggle backward compatibility according to what font wants, except
|
|
2699 |
+ * when
|
|
2700 |
+ *
|
|
2701 |
+ * 1) we have a `tricky' font that heavily relies on the interpreter to
|
|
2702 |
+ * render glyphs correctly, for example DFKai-SB, or
|
|
2703 |
+ * 2) FT_RENDER_MODE_MONO (i.e, monochome rendering) is requested.
|
|
2704 |
+ *
|
|
2705 |
+ * In those cases, backward compatibility needs to be turned off to get
|
|
2706 |
+ * correct rendering. The rendering is then completely up to the
|
|
2707 |
+ * font's programming.
|
|
2708 |
+ *
|
|
2709 |
+ */
|
|
2710 |
+ if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 &&
|
|
2711 |
+ subpixel_hinting_lean &&
|
|
2712 |
+ !FT_IS_TRICKY( glyph->face ) )
|
|
2713 |
+ exec->backward_compatibility = !( exec->GS.instruct_control & 4 );
|
|
2714 |
+ else
|
|
2715 |
+ exec->backward_compatibility = FALSE;
|
|
2716 |
+ |
|
2717 |
+ exec->iupx_called = FALSE;
|
|
2718 |
+ exec->iupy_called = FALSE;
|
|
2719 |
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL */
|
|
2724 | 2720 |
|
2725 | 2721 |
exec->pedantic_hinting = FT_BOOL( load_flags & FT_LOAD_PEDANTIC );
|
2726 | 2722 |
loader->exec = exec;
|
2727 | 2723 |
loader->instructions = exec->glyphIns;
|
2724 |
+ |
|
2725 |
+ /* Use the hdmx table if any unless FT_LOAD_COMPUTE_METRICS */
|
|
2726 |
+ /* is set or backward compatibility mode of the v38 or v40 */
|
|
2727 |
+ /* interpreters is active. See `ttinterp.h' for details on */
|
|
2728 |
+ /* backward compatibility mode. */
|
|
2729 |
+ if ( IS_HINTED( loader->load_flags ) &&
|
|
2730 |
+ !( loader->load_flags & FT_LOAD_COMPUTE_METRICS ) &&
|
|
2731 |
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
|
|
2732 |
+ !( driver->interpreter_version == TT_INTERPRETER_VERSION_40 &&
|
|
2733 |
+ exec->backward_compatibility ) &&
|
|
2734 |
+#endif
|
|
2735 |
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
|
|
2736 |
+ !( driver->interpreter_version == TT_INTERPRETER_VERSION_38 &&
|
|
2737 |
+ !SPH_OPTION_BITMAP_WIDTHS &&
|
|
2738 |
+ FT_LOAD_TARGET_MODE( loader->load_flags ) !=
|
|
2739 |
+ FT_RENDER_MODE_MONO &&
|
|
2740 |
+ exec->compatible_widths ) &&
|
|
2741 |
+#endif
|
|
2742 |
+ !face->postscript.isFixedPitch )
|
|
2743 |
+ {
|
|
2744 |
+ loader->widthp = tt_face_get_device_metrics( face,
|
|
2745 |
+ size->metrics->x_ppem,
|
|
2746 |
+ 0 );
|
|
2747 |
+ }
|
|
2748 |
+ else
|
|
2749 |
+ loader->widthp = NULL;
|
|
2728 | 2750 |
}
|
2729 | 2751 |
|
2730 | 2752 |
#endif /* TT_USE_BYTECODE_INTERPRETER */
|
... | ... | @@ -2923,6 +2945,15 @@ |
2923 | 2945 |
if ( error )
|
2924 | 2946 |
goto Exit;
|
2925 | 2947 |
|
2948 |
+ /* done if we are only interested in the `hdmx` advance */
|
|
2949 |
+ if ( load_flags & FT_LOAD_ADVANCE_ONLY &&
|
|
2950 |
+ !( load_flags & FT_LOAD_VERTICAL_LAYOUT ) &&
|
|
2951 |
+ loader.widthp )
|
|
2952 |
+ {
|
|
2953 |
+ glyph->metrics.horiAdvance = loader.widthp[glyph_index] * 64;
|
|
2954 |
+ goto Done;
|
|
2955 |
+ }
|
|
2956 |
+ |
|
2926 | 2957 |
glyph->format = FT_GLYPH_FORMAT_OUTLINE;
|
2927 | 2958 |
glyph->num_subglyphs = 0;
|
2928 | 2959 |
glyph->outline.flags = 0;
|
... | ... | @@ -3001,6 +3032,7 @@ |
3001 | 3032 |
glyph->outline.n_points,
|
3002 | 3033 |
glyph->outline.flags ));
|
3003 | 3034 |
|
3035 |
+ Done:
|
|
3004 | 3036 |
tt_loader_done( &loader );
|
3005 | 3037 |
|
3006 | 3038 |
Exit:
|
... | ... | @@ -5260,10 +5260,15 @@ |
5260 | 5260 |
}
|
5261 | 5261 |
}
|
5262 | 5262 |
|
5263 |
- exc->GS.instruct_control &= ~(FT_Byte)Kf;
|
|
5264 |
- exc->GS.instruct_control |= (FT_Byte)L;
|
|
5263 |
+ /* INSTCTRL should only be used in the CVT program */
|
|
5264 |
+ if ( exc->iniRange == tt_coderange_cvt )
|
|
5265 |
+ {
|
|
5266 |
+ exc->GS.instruct_control &= ~(FT_Byte)Kf;
|
|
5267 |
+ exc->GS.instruct_control |= (FT_Byte)L;
|
|
5268 |
+ }
|
|
5265 | 5269 |
|
5266 |
- if ( K == 3 )
|
|
5270 |
+ /* except to change the subpixel flags temporarily */
|
|
5271 |
+ else if ( exc->iniRange == tt_coderange_glyph && K == 3 )
|
|
5267 | 5272 |
{
|
5268 | 5273 |
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
|
5269 | 5274 |
/* INSTCTRL modifying flag 3 also has an effect */
|
... | ... | @@ -7755,35 +7760,6 @@ |
7755 | 7760 |
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
|
7756 | 7761 |
|
7757 | 7762 |
|
7758 |
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
|
|
7759 |
- exc->iup_called = FALSE;
|
|
7760 |
-#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
|
|
7761 |
- |
|
7762 |
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
|
|
7763 |
- /*
|
|
7764 |
- * Toggle backward compatibility according to what font wants, except
|
|
7765 |
- * when
|
|
7766 |
- *
|
|
7767 |
- * 1) we have a `tricky' font that heavily relies on the interpreter to
|
|
7768 |
- * render glyphs correctly, for example DFKai-SB, or
|
|
7769 |
- * 2) FT_RENDER_MODE_MONO (i.e, monochome rendering) is requested.
|
|
7770 |
- *
|
|
7771 |
- * In those cases, backward compatibility needs to be turned off to get
|
|
7772 |
- * correct rendering. The rendering is then completely up to the
|
|
7773 |
- * font's programming.
|
|
7774 |
- *
|
|
7775 |
- */
|
|
7776 |
- if ( SUBPIXEL_HINTING_MINIMAL &&
|
|
7777 |
- exc->subpixel_hinting_lean &&
|
|
7778 |
- !FT_IS_TRICKY( &exc->face->root ) )
|
|
7779 |
- exc->backward_compatibility = !( exc->GS.instruct_control & 4 );
|
|
7780 |
- else
|
|
7781 |
- exc->backward_compatibility = FALSE;
|
|
7782 |
- |
|
7783 |
- exc->iupx_called = FALSE;
|
|
7784 |
- exc->iupy_called = FALSE;
|
|
7785 |
-#endif
|
|
7786 |
- |
|
7787 | 7763 |
/* We restrict the number of twilight points to a reasonable, */
|
7788 | 7764 |
/* heuristic value to avoid slow execution of malformed bytecode. */
|
7789 | 7765 |
num_twilight_points = FT_MAX( 30,
|
... | ... | @@ -498,6 +498,14 @@ |
498 | 498 |
}
|
499 | 499 |
|
500 | 500 |
|
501 |
+ FT_COMPARE_DEF( int )
|
|
502 |
+ compare_ppem( const void* a,
|
|
503 |
+ const void* b )
|
|
504 |
+ {
|
|
505 |
+ return **(FT_Byte**)a - **(FT_Byte**)b;
|
|
506 |
+ }
|
|
507 |
+ |
|
508 |
+ |
|
501 | 509 |
/**************************************************************************
|
502 | 510 |
*
|
503 | 511 |
* @Function:
|
... | ... | @@ -574,20 +582,21 @@ |
574 | 582 |
goto Fail;
|
575 | 583 |
}
|
576 | 584 |
|
577 |
- if ( FT_QNEW_ARRAY( face->hdmx_record_sizes, num_records ) )
|
|
585 |
+ if ( FT_QNEW_ARRAY( face->hdmx_records, num_records ) )
|
|
578 | 586 |
goto Fail;
|
579 | 587 |
|
580 |
- /* XXX: We do not check if the records are sorted by ppem */
|
|
581 |
- /* and cannot use binary search later. */
|
|
582 | 588 |
for ( nn = 0; nn < num_records; nn++ )
|
583 | 589 |
{
|
584 | 590 |
if ( p + record_size > limit )
|
585 | 591 |
break;
|
586 |
- |
|
587 |
- face->hdmx_record_sizes[nn] = p[0];
|
|
588 |
- p += record_size;
|
|
592 |
+ face->hdmx_records[nn] = p;
|
|
593 |
+ p += record_size;
|
|
589 | 594 |
}
|
590 | 595 |
|
596 |
+ /* The records must be already sorted by ppem but it does not */
|
|
597 |
+ /* hurt to make sure so that the binary search works later. */
|
|
598 |
+ ft_qsort( face->hdmx_records, nn, sizeof ( FT_Byte* ), compare_ppem );
|
|
599 |
+ |
|
591 | 600 |
face->hdmx_record_count = nn;
|
592 | 601 |
face->hdmx_table_size = table_size;
|
593 | 602 |
face->hdmx_record_size = record_size;
|
... | ... | @@ -611,7 +620,7 @@ |
611 | 620 |
FT_Memory memory = stream->memory;
|
612 | 621 |
|
613 | 622 |
|
614 |
- FT_FREE( face->hdmx_record_sizes );
|
|
623 |
+ FT_FREE( face->hdmx_records );
|
|
615 | 624 |
FT_FRAME_RELEASE( face->hdmx_table );
|
616 | 625 |
}
|
617 | 626 |
|
... | ... | @@ -619,27 +628,34 @@ |
619 | 628 |
/**************************************************************************
|
620 | 629 |
*
|
621 | 630 |
* Return the advance width table for a given pixel size if it is found
|
622 |
- * in the font's `hdmx' table (if any).
|
|
631 |
+ * in the font's `hdmx' table (if any). The records must be sorted for
|
|
632 |
+ * the binary search to work properly.
|
|
623 | 633 |
*/
|
624 | 634 |
FT_LOCAL_DEF( FT_Byte* )
|
625 | 635 |
tt_face_get_device_metrics( TT_Face face,
|
626 | 636 |
FT_UInt ppem,
|
627 | 637 |
FT_UInt gindex )
|
628 | 638 |
{
|
629 |
- FT_UInt nn;
|
|
630 |
- FT_Byte* result = NULL;
|
|
631 |
- FT_ULong record_size = face->hdmx_record_size;
|
|
632 |
- FT_Byte* record = FT_OFFSET( face->hdmx_table, 8 );
|
|
639 |
+ FT_UInt min = 0;
|
|
640 |
+ FT_UInt max = face->hdmx_record_count;
|
|
641 |
+ FT_UInt mid;
|
|
642 |
+ FT_Byte* result = NULL;
|
|
643 |
+ |
|
633 | 644 |
|
645 |
+ while ( min < max )
|
|
646 |
+ {
|
|
647 |
+ mid = ( min + max ) >> 1;
|
|
634 | 648 |
|
635 |
- for ( nn = 0; nn < face->hdmx_record_count; nn++ )
|
|
636 |
- if ( face->hdmx_record_sizes[nn] == ppem )
|
|
649 |
+ if ( face->hdmx_records[mid][0] > ppem )
|
|
650 |
+ max = mid;
|
|
651 |
+ else if ( face->hdmx_records[mid][0] < ppem )
|
|
652 |
+ min = mid + 1;
|
|
653 |
+ else
|
|
637 | 654 |
{
|
638 |
- gindex += 2;
|
|
639 |
- if ( gindex < record_size )
|
|
640 |
- result = record + nn * record_size + gindex;
|
|
655 |
+ result = face->hdmx_records[mid] + 2 + gindex;
|
|
641 | 656 |
break;
|
642 | 657 |
}
|
658 |
+ }
|
|
643 | 659 |
|
644 | 660 |
return result;
|
645 | 661 |
}
|