Anurag Thakur pushed to branch gsoc-anurag-2023-final at FreeType / FreeType
Commits:
-
3e56c9bf
by Anurag Thakur at 2023-10-10T01:46:37+05:30
-
bca7bda1
by Anurag Thakur at 2023-10-10T01:46:43+05:30
-
668bc29f
by Anurag Thakur at 2023-10-10T01:46:43+05:30
-
724e81ef
by Anurag Thakur at 2023-10-10T01:46:43+05:30
-
d4864581
by Anurag Thakur at 2023-10-10T01:46:43+05:30
-
f7015177
by Anurag Thakur at 2023-10-10T01:46:43+05:30
-
a4dcdee6
by Anurag Thakur at 2023-10-10T02:49:59+05:30
-
849f2b21
by Anurag Thakur at 2023-10-10T02:50:03+05:30
-
ed911fa8
by Anurag Thakur at 2023-10-10T02:50:03+05:30
-
b79951a2
by Anurag Thakur at 2023-10-10T02:50:03+05:30
-
e183ffb9
by Anurag Thakur at 2023-10-10T02:50:03+05:30
-
29a32c81
by Anurag Thakur at 2023-10-10T02:50:03+05:30
-
8d89a20a
by Anurag Thakur at 2023-10-10T02:50:03+05:30
-
bff4c234
by Anurag Thakur at 2023-10-10T02:50:03+05:30
-
70313bde
by Anurag Thakur at 2023-10-10T02:50:03+05:30
-
47ae1bfa
by Anurag Thakur at 2023-10-10T03:05:01+05:30
10 changed files:
- CMakeLists.txt
- builds/meson/parse_modules_cfg.py
- include/freetype/freetype.h
- include/freetype/ftimage.h
- meson.build
- src/base/ftobjs.c
- src/dense/ftdense.c
- src/dense/ftdense.h
- src/dense/ftdenserend.c
- src/dense/rules.mk
Changes:
| ... | ... | @@ -247,6 +247,8 @@ if (BUILD_FRAMEWORK) |
| 247 | 247 | endif ()
|
| 248 | 248 | |
| 249 | 249 | |
| 250 | +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -msse4.1")
|
|
| 251 | + |
|
| 250 | 252 | # Find dependencies
|
| 251 | 253 | include(FindPkgConfig)
|
| 252 | 254 |
| ... | ... | @@ -87,6 +87,7 @@ def generate_ftmodule(lists): |
| 87 | 87 | names = {
|
| 88 | 88 | "raster": ("ft_raster1",),
|
| 89 | 89 | "smooth": ("ft_smooth",),
|
| 90 | + "dense": ("ft_dense",),
|
|
| 90 | 91 | "svg": ("ft_svg",),
|
| 91 | 92 | "sdf": ("ft_sdf", "ft_bitmap_sdf"),
|
| 92 | 93 | }.get(module)
|
| ... | ... | @@ -1276,6 +1276,7 @@ FT_BEGIN_HEADER |
| 1276 | 1276 | FT_ListRec sizes_list;
|
| 1277 | 1277 | |
| 1278 | 1278 | FT_Generic autohint; /* face-specific auto-hinter data */
|
| 1279 | + FT_GlyphSlot* glyph_array;
|
|
| 1279 | 1280 | void* extensions; /* unused */
|
| 1280 | 1281 | |
| 1281 | 1282 | FT_Face_Internal internal;
|
| ... | ... | @@ -1283,6 +1284,44 @@ FT_BEGIN_HEADER |
| 1283 | 1284 | } FT_FaceRec;
|
| 1284 | 1285 | |
| 1285 | 1286 | |
| 1287 | + |
|
| 1288 | + /**************************************************************************
|
|
| 1289 | + *
|
|
| 1290 | + * @type:
|
|
| 1291 | + * FT_PreLine
|
|
| 1292 | + *
|
|
| 1293 | + * @description:
|
|
| 1294 | + * A handle to FT_PreLineRec_ containing coordinates of start and end
|
|
| 1295 | + * points for a line.
|
|
| 1296 | + *
|
|
| 1297 | + */
|
|
| 1298 | + typedef struct FT_PreLineRec_* FT_PreLine;
|
|
| 1299 | + |
|
| 1300 | + /**************************************************************************
|
|
| 1301 | + *
|
|
| 1302 | + * @struct:
|
|
| 1303 | + * FT_PreLineRec
|
|
| 1304 | + *
|
|
| 1305 | + * @description:
|
|
| 1306 | + * Linkedlist containing lines to be drawn for a glyph.
|
|
| 1307 | + *
|
|
| 1308 | + * @fields:
|
|
| 1309 | + * x1, y1 ::
|
|
| 1310 | + * Coordinates of line start point.
|
|
| 1311 | + *
|
|
| 1312 | + * y1, y2 ::
|
|
| 1313 | + * Coordinates of line end point.
|
|
| 1314 | + *
|
|
| 1315 | + * next ::
|
|
| 1316 | + * The next PreLine for current glyph
|
|
| 1317 | + *
|
|
| 1318 | + */
|
|
| 1319 | + typedef struct FT_PreLineRec_
|
|
| 1320 | + {
|
|
| 1321 | + int x1, x2, y1, y2;
|
|
| 1322 | + FT_PreLine next;
|
|
| 1323 | + } FT_PreLineRec;
|
|
| 1324 | + |
|
| 1286 | 1325 | /**************************************************************************
|
| 1287 | 1326 | *
|
| 1288 | 1327 | * @enum:
|
| ... | ... | @@ -2171,6 +2210,12 @@ FT_BEGIN_HEADER |
| 2171 | 2210 | * other ::
|
| 2172 | 2211 | * Reserved.
|
| 2173 | 2212 | *
|
| 2213 | + * prelines ::
|
|
| 2214 | + * Linkedlist containing lines to be drawn for the glyph
|
|
| 2215 | + *
|
|
| 2216 | + * prel_shifted ::
|
|
| 2217 | + * If the points in preline have been adjustted according to target bitmap
|
|
| 2218 | + *
|
|
| 2174 | 2219 | * lsb_delta ::
|
| 2175 | 2220 | * The difference between hinted and unhinted left side bearing while
|
| 2176 | 2221 | * auto-hinting is active. Zero otherwise.
|
| ... | ... | @@ -2288,6 +2333,8 @@ FT_BEGIN_HEADER |
| 2288 | 2333 | FT_Pos rsb_delta;
|
| 2289 | 2334 | |
| 2290 | 2335 | void* other;
|
| 2336 | + FT_PreLine prelines;
|
|
| 2337 | + int prel_shifted;
|
|
| 2291 | 2338 | |
| 2292 | 2339 | FT_Slot_Internal internal;
|
| 2293 | 2340 | |
| ... | ... | @@ -2487,6 +2534,10 @@ FT_BEGIN_HEADER |
| 2487 | 2534 | * params ::
|
| 2488 | 2535 | * Extra parameters passed to the font driver when opening a new face.
|
| 2489 | 2536 | *
|
| 2537 | + * size ::
|
|
| 2538 | + * Size at which the glyphs will be rendered. Use same value as
|
|
| 2539 | + * @FT_Set_Pixel_Sizes
|
|
| 2540 | + *
|
|
| 2490 | 2541 | * @note:
|
| 2491 | 2542 | * The stream type is determined by the contents of `flags`:
|
| 2492 | 2543 | *
|
| ... | ... | @@ -2524,6 +2575,7 @@ FT_BEGIN_HEADER |
| 2524 | 2575 | FT_Module driver;
|
| 2525 | 2576 | FT_Int num_params;
|
| 2526 | 2577 | FT_Parameter* params;
|
| 2578 | + FT_UInt size;
|
|
| 2527 | 2579 | |
| 2528 | 2580 | } FT_Open_Args;
|
| 2529 | 2581 | |
| ... | ... | @@ -2573,6 +2625,54 @@ FT_BEGIN_HEADER |
| 2573 | 2625 | FT_Face *aface );
|
| 2574 | 2626 | |
| 2575 | 2627 | |
| 2628 | +/**************************************************************************
|
|
| 2629 | + *
|
|
| 2630 | + * @function:
|
|
| 2631 | + * FT_New_Face2
|
|
| 2632 | + *
|
|
| 2633 | + * @description:
|
|
| 2634 | + * Call @FT_Open_Face to open a font by its pathname with given flags.
|
|
| 2635 | + *
|
|
| 2636 | + * @inout:
|
|
| 2637 | + * library ::
|
|
| 2638 | + * A handle to the library resource.
|
|
| 2639 | + *
|
|
| 2640 | + * @input:
|
|
| 2641 | + * pathname ::
|
|
| 2642 | + * A path to the font file.
|
|
| 2643 | + *
|
|
| 2644 | + * face_index ::
|
|
| 2645 | + * See @FT_Open_Face for a detailed description of this parameter.
|
|
| 2646 | + *
|
|
| 2647 | + * size ::
|
|
| 2648 | + * Size at which glyphs will be rendered, Use the same value as @FT_Set_Pixel_Sizes
|
|
| 2649 | + *
|
|
| 2650 | + * @output:
|
|
| 2651 | + * aface ::
|
|
| 2652 | + * A handle to a new face object. If `face_index` is greater than or
|
|
| 2653 | + * equal to zero, it must be non-`NULL`.
|
|
| 2654 | + *
|
|
| 2655 | + * @return:
|
|
| 2656 | + * FreeType error code. 0~means success.
|
|
| 2657 | + *
|
|
| 2658 | + * @note:
|
|
| 2659 | + * The `pathname` string should be recognizable as such by a standard
|
|
| 2660 | + * `fopen` call on your system; in particular, this means that `pathname`
|
|
| 2661 | + * must not contain null bytes. If that is not sufficient to address all
|
|
| 2662 | + * file name possibilities (for example, to handle wide character file
|
|
| 2663 | + * names on Windows in UTF-16 encoding) you might use @FT_Open_Face to
|
|
| 2664 | + * pass a memory array or a stream object instead.
|
|
| 2665 | + *
|
|
| 2666 | + * Use @FT_Done_Face to destroy the created @FT_Face object (along with
|
|
| 2667 | + * its slot and sizes).
|
|
| 2668 | + */
|
|
| 2669 | + FT_EXPORT( FT_Error )
|
|
| 2670 | + FT_New_Face2( FT_Library library,
|
|
| 2671 | + const char* filepathname,
|
|
| 2672 | + FT_Long face_index,
|
|
| 2673 | + FT_Face *aface,
|
|
| 2674 | + FT_UInt size);
|
|
| 2675 | + |
|
| 2576 | 2676 | /**************************************************************************
|
| 2577 | 2677 | *
|
| 2578 | 2678 | * @function:
|
| ... | ... | @@ -3228,6 +3328,31 @@ FT_BEGIN_HEADER |
| 3228 | 3328 | FT_UInt glyph_index,
|
| 3229 | 3329 | FT_Int32 load_flags );
|
| 3230 | 3330 | |
| 3331 | + /**************************************************************************
|
|
| 3332 | + *
|
|
| 3333 | + * @function:
|
|
| 3334 | + * FT_Refresh_Glyph
|
|
| 3335 | + *
|
|
| 3336 | + * @description:
|
|
| 3337 | + * Prepare the glyph at glyph_index for rendering. Resets the glyph
|
|
| 3338 | + * if it has already been rendered
|
|
| 3339 | + *
|
|
| 3340 | + * @inout:
|
|
| 3341 | + * face ::
|
|
| 3342 | + * A handle to the target face object where the glyph is loaded.
|
|
| 3343 | + *
|
|
| 3344 | + * @input:
|
|
| 3345 | + * glyph_index ::
|
|
| 3346 | + * The index of the glyph in the font file.
|
|
| 3347 | + *
|
|
| 3348 | + * @return:
|
|
| 3349 | + * FreeType error code. 0~means success.
|
|
| 3350 | + *
|
|
| 3351 | + */
|
|
| 3352 | + FT_EXPORT( FT_Error )
|
|
| 3353 | + FT_Refresh_Glyph( FT_Face face,
|
|
| 3354 | + FT_UInt glyph_index);
|
|
| 3355 | + |
|
| 3231 | 3356 | |
| 3232 | 3357 | /**************************************************************************
|
| 3233 | 3358 | *
|
| ... | ... | @@ -1030,6 +1030,9 @@ FT_BEGIN_HEADER |
| 1030 | 1030 | * An optional span clipping box expressed in _integer_ pixels
|
| 1031 | 1031 | * (not in 26.6 fixed-point units).
|
| 1032 | 1032 | *
|
| 1033 | + * prelines ::
|
|
| 1034 | + * Pointer of type FT_PreLine, containing line data for a glyph
|
|
| 1035 | + *
|
|
| 1033 | 1036 | * @note:
|
| 1034 | 1037 | * The @FT_RASTER_FLAG_AA bit flag must be set in the `flags` to
|
| 1035 | 1038 | * generate an anti-aliased glyph bitmap, otherwise a monochrome bitmap
|
| ... | ... | @@ -1059,6 +1062,7 @@ FT_BEGIN_HEADER |
| 1059 | 1062 | FT_Raster_BitSet_Func bit_set; /* unused */
|
| 1060 | 1063 | void* user;
|
| 1061 | 1064 | FT_BBox clip_box;
|
| 1065 | + void* prelines;
|
|
| 1062 | 1066 | |
| 1063 | 1067 | } FT_Raster_Params;
|
| 1064 | 1068 |
| ... | ... | @@ -395,6 +395,13 @@ if use_unix_ftsystem_c |
| 395 | 395 | endif
|
| 396 | 396 | |
| 397 | 397 | |
| 398 | +if cc.get_id() == 'msvc'
|
|
| 399 | + ft2_defines += ['/arch:AVX']
|
|
| 400 | +else
|
|
| 401 | + ft2_defines += ['-msse4.1']
|
|
| 402 | +endif
|
|
| 403 | + |
|
| 404 | + |
|
| 398 | 405 | ft2_lib = library('freetype',
|
| 399 | 406 | sources: ft2_sources + [ftmodule_h],
|
| 400 | 407 | c_args: ft2_defines,
|
| ... | ... | @@ -403,7 +410,7 @@ ft2_lib = library('freetype', |
| 403 | 410 | dependencies: ft2_deps,
|
| 404 | 411 | install: true,
|
| 405 | 412 | version: ft2_so_version,
|
| 406 | - link_args: common_ldflags,
|
|
| 413 | + link_args: common_ldflags + ['-lm'],
|
|
| 407 | 414 | )
|
| 408 | 415 | |
| 409 | 416 |
| ... | ... | @@ -42,12 +42,18 @@ |
| 42 | 42 | #include <freetype/internal/services/svkern.h>
|
| 43 | 43 | #include <freetype/internal/services/svtteng.h>
|
| 44 | 44 | |
| 45 | +#include <math.h>
|
|
| 45 | 46 | #include <freetype/ftdriver.h>
|
| 46 | 47 | |
| 47 | 48 | #ifdef FT_CONFIG_OPTION_MAC_FONTS
|
| 48 | 49 | #include "ftbase.h"
|
| 49 | 50 | #endif
|
| 50 | 51 | |
| 52 | +#define PIXEL_BITS 8
|
|
| 53 | + |
|
| 54 | +#define ONE_PIXEL ( 1 << PIXEL_BITS )
|
|
| 55 | +#define UPSCALE( x ) ( ( x ) * ( ONE_PIXEL >> 6 ) )
|
|
| 56 | +#define DOWNSCALE( x ) ( ( x ) >> ( PIXEL_BITS - 6 ) )
|
|
| 51 | 57 | |
| 52 | 58 | #ifdef FT_DEBUG_LEVEL_TRACE
|
| 53 | 59 | |
| ... | ... | @@ -893,6 +899,14 @@ |
| 893 | 899 | |
| 894 | 900 | |
| 895 | 901 | /* documentation is in freetype.h */
|
| 902 | + FT_EXPORT_DEF( FT_Error )
|
|
| 903 | + FT_Refresh_Glyph( FT_Face face,
|
|
| 904 | + FT_UInt glyph_index)
|
|
| 905 | + |
|
| 906 | + {
|
|
| 907 | + ft_glyphslot_free_bitmap( face->glyph_array[glyph_index] );
|
|
| 908 | + face->glyph_array[glyph_index]->format = FT_GLYPH_FORMAT_OUTLINE;
|
|
| 909 | + }
|
|
| 896 | 910 | |
| 897 | 911 | FT_EXPORT_DEF( FT_Error )
|
| 898 | 912 | FT_Load_Glyph( FT_Face face,
|
| ... | ... | @@ -914,7 +928,7 @@ |
| 914 | 928 | /* The validity test for `glyph_index' is performed by the */
|
| 915 | 929 | /* font drivers. */
|
| 916 | 930 | |
| 917 | - slot = face->glyph;
|
|
| 931 | + slot = face->glyph_array[glyph_index];
|
|
| 918 | 932 | ft_glyphslot_clear( slot );
|
| 919 | 933 | |
| 920 | 934 | driver = face->driver;
|
| ... | ... | @@ -1616,12 +1630,34 @@ |
| 1616 | 1630 | return FT_THROW( Invalid_Argument );
|
| 1617 | 1631 | |
| 1618 | 1632 | args.flags = FT_OPEN_PATHNAME;
|
| 1633 | + args.size = 0;
|
|
| 1619 | 1634 | args.pathname = (char*)pathname;
|
| 1620 | 1635 | args.stream = NULL;
|
| 1621 | 1636 | |
| 1622 | 1637 | return ft_open_face_internal( library, &args, face_index, aface, 1 );
|
| 1623 | 1638 | }
|
| 1624 | 1639 | |
| 1640 | + FT_EXPORT_DEF( FT_Error )
|
|
| 1641 | + FT_New_Face2( FT_Library library,
|
|
| 1642 | + const char* pathname,
|
|
| 1643 | + FT_Long face_index,
|
|
| 1644 | + FT_Face *aface,
|
|
| 1645 | + FT_UInt size)
|
|
| 1646 | + {
|
|
| 1647 | + FT_Open_Args args;
|
|
| 1648 | + |
|
| 1649 | + /* test for valid `library' and `aface' delayed to `FT_Open_Face' */
|
|
| 1650 | + if ( !pathname )
|
|
| 1651 | + return FT_THROW( Invalid_Argument );
|
|
| 1652 | + |
|
| 1653 | + args.flags = FT_OPEN_PATHNAME;
|
|
| 1654 | + args.size = size;
|
|
| 1655 | + args.pathname = (char*)pathname;
|
|
| 1656 | + args.stream = NULL;
|
|
| 1657 | + |
|
| 1658 | + return ft_open_face_internal( library, &args, face_index, aface, 1 );
|
|
| 1659 | + }
|
|
| 1660 | + |
|
| 1625 | 1661 | #endif
|
| 1626 | 1662 | |
| 1627 | 1663 | |
| ... | ... | @@ -2519,6 +2555,306 @@ |
| 2519 | 2555 | }
|
| 2520 | 2556 | |
| 2521 | 2557 | |
| 2558 | +static FT_Vector
|
|
| 2559 | +Lerp( float T, FT_Vector P0, FT_Vector P1 )
|
|
| 2560 | +{
|
|
| 2561 | + FT_Vector p;
|
|
| 2562 | + p.x = P0.x + T * ( P1.x - P0.x );
|
|
| 2563 | + p.y = P0.y + T * ( P1.y - P0.y );
|
|
| 2564 | + return p;
|
|
| 2565 | +}
|
|
| 2566 | + |
|
| 2567 | +int conic_to2(FT_GlyphSlot* slot, FT_Vector *control, FT_Vector *from, FT_Vector *to, FT_PreLine *ptr)
|
|
| 2568 | +{
|
|
| 2569 | + /*
|
|
| 2570 | + Calculate devsq as the square of four times the
|
|
| 2571 | + distance from the control point to the midpoint of the curve.
|
|
| 2572 | + This is the place at which the curve is furthest from the
|
|
| 2573 | + line joining the control points.
|
|
| 2574 | + |
|
| 2575 | + 4 x point on curve = p0 + 2p1 + p2
|
|
| 2576 | + 4 x midpoint = 4p1
|
|
| 2577 | + |
|
| 2578 | + The division by four is omitted to save time.
|
|
| 2579 | + */
|
|
| 2580 | + FT_Vector aP0 = { from->x , from->y};
|
|
| 2581 | + FT_Vector aP1 = { control->x, control->y };
|
|
| 2582 | + FT_Vector aP2 = { to->x, to->y };
|
|
| 2583 | + |
|
| 2584 | + float devx = aP0.x - aP1.x - aP1.x + aP2.x;
|
|
| 2585 | + float devy = aP0.y - aP1.y - aP1.y + aP2.y;
|
|
| 2586 | + float devsq = devx * devx + devy * devy;
|
|
| 2587 | + |
|
| 2588 | + if ( devsq < 0.333f )
|
|
| 2589 | + {
|
|
| 2590 | + FT_PreLine pl3 = malloc(sizeof(FT_PreLineRec));
|
|
| 2591 | + pl3->x1 = (*ptr)->x2;
|
|
| 2592 | + pl3->y1 = (*ptr)->y2;
|
|
| 2593 | + pl3->x2 = aP2.x;
|
|
| 2594 | + pl3->y2 = aP2.y;
|
|
| 2595 | + pl3->next = NULL;
|
|
| 2596 | + (*ptr)->next = pl3;
|
|
| 2597 | + *ptr = (*ptr)->next;
|
|
| 2598 | + return 0;
|
|
| 2599 | + }
|
|
| 2600 | + |
|
| 2601 | + /*
|
|
| 2602 | + According to Raph Levien, the reason for the subdivision by n (instead of
|
|
| 2603 | + recursive division by the Casteljau system) is that "I expect the flatness
|
|
| 2604 | + computation to be semi-expensive (it's done once rather than on each potential
|
|
| 2605 | + subdivision) and also because you'll often get fewer subdivisions. Taking a
|
|
| 2606 | + circular arc as a simplifying assumption, where I get n, a recursive approach
|
|
| 2607 | + would get 2^ceil(lg n), which, if I haven't made any horrible mistakes, is
|
|
| 2608 | + expected to be 33% more in the limit".
|
|
| 2609 | + */
|
|
| 2610 | + |
|
| 2611 | + const float tol = 3.0f;
|
|
| 2612 | + int n = (int)floor( sqrt( sqrt( tol * devsq ) ) )/8;
|
|
| 2613 | + FT_Vector p = aP0;
|
|
| 2614 | + float nrecip = 1.0f / ( n + 1.0f );
|
|
| 2615 | + float t = 0.0f;
|
|
| 2616 | + for ( int i = 0; i < n; i++ )
|
|
| 2617 | + {
|
|
| 2618 | + t += nrecip;
|
|
| 2619 | + FT_Vector next = Lerp( t, Lerp( t, aP0, aP1 ), Lerp( t, aP1, aP2 ) );
|
|
| 2620 | + FT_PreLine pl4 = malloc(sizeof(FT_PreLineRec));
|
|
| 2621 | + pl4->x1 = (*ptr)->x2;
|
|
| 2622 | + pl4->y1 = (*ptr)->y2;
|
|
| 2623 | + pl4->x2 = next.x;
|
|
| 2624 | + pl4->y2 = next.y;
|
|
| 2625 | + pl4->next = NULL;
|
|
| 2626 | + (*ptr)->next = pl4;
|
|
| 2627 | + *ptr = (*ptr)->next;
|
|
| 2628 | + p = next;
|
|
| 2629 | + }
|
|
| 2630 | + |
|
| 2631 | + FT_PreLine pl5 = malloc(sizeof(FT_PreLineRec));
|
|
| 2632 | + pl5->x1 = (*ptr)->x2;
|
|
| 2633 | + pl5->y1 = (*ptr)->y2;
|
|
| 2634 | + pl5->x2 = aP2.x;
|
|
| 2635 | + pl5->y2 = aP2.y;
|
|
| 2636 | + pl5->next = NULL;
|
|
| 2637 | + (*ptr)->next = pl5;
|
|
| 2638 | + *ptr = (*ptr)->next;
|
|
| 2639 | + return 0;
|
|
| 2640 | +}
|
|
| 2641 | + |
|
| 2642 | +/**
|
|
| 2643 | + * Convert the outline data of slot to prelines
|
|
| 2644 | +*/
|
|
| 2645 | +FT_Error ft_decompose_outline(FT_GlyphSlot* slot){
|
|
| 2646 | + FT_Vector v_last;
|
|
| 2647 | + FT_Vector v_control;
|
|
| 2648 | + FT_Vector v_start;
|
|
| 2649 | + |
|
| 2650 | + FT_Vector* point;
|
|
| 2651 | + FT_Vector* limit;
|
|
| 2652 | + char* tags;
|
|
| 2653 | + |
|
| 2654 | + FT_Error error;
|
|
| 2655 | + |
|
| 2656 | + FT_Int n; /* index of contour in outline */
|
|
| 2657 | + FT_Int first; /* index of first point in contour */
|
|
| 2658 | + FT_Int last; /* index of last point in contour */
|
|
| 2659 | + |
|
| 2660 | + FT_Int tag; /* current point's state */
|
|
| 2661 | + |
|
| 2662 | + FT_Int shift;
|
|
| 2663 | + FT_Pos delta;
|
|
| 2664 | + |
|
| 2665 | + FT_Outline* outline = &(*slot)->outline;
|
|
| 2666 | + |
|
| 2667 | + if ( !outline )
|
|
| 2668 | + return FT_THROW( Invalid_Outline );
|
|
| 2669 | +
|
|
| 2670 | + last = -1;
|
|
| 2671 | + FT_PreLine ptr = (*slot)->prelines;
|
|
| 2672 | + |
|
| 2673 | + for ( n = 0; n < outline->n_contours; n++ )
|
|
| 2674 | + {
|
|
| 2675 | + FT_TRACE5(( "ft_decompose_outline: Contour %d\n", n ));
|
|
| 2676 | + |
|
| 2677 | + first = last + 1;
|
|
| 2678 | + last = outline->contours[n];
|
|
| 2679 | + if ( last < first ){
|
|
| 2680 | + FT_TRACE5(( "Invalid Outline"));
|
|
| 2681 | + break;
|
|
| 2682 | + }
|
|
| 2683 | + limit = outline->points + last;
|
|
| 2684 | + |
|
| 2685 | + v_start = outline->points[first];
|
|
| 2686 | + |
|
| 2687 | + |
|
| 2688 | + v_last = outline->points[last];
|
|
| 2689 | + |
|
| 2690 | + v_control = v_start;
|
|
| 2691 | + |
|
| 2692 | + point = outline->points + first;
|
|
| 2693 | + tags = outline->tags + first;
|
|
| 2694 | + tag = FT_CURVE_TAG( tags[0] );
|
|
| 2695 | + |
|
| 2696 | + /* A contour cannot start with a cubic control point! */
|
|
| 2697 | + if ( tag == FT_CURVE_TAG_CUBIC )
|
|
| 2698 | + {
|
|
| 2699 | + FT_TRACE5(( "Invalid Outline"));
|
|
| 2700 | + break;
|
|
| 2701 | + }
|
|
| 2702 | + /* check first point to determine origin */
|
|
| 2703 | + if ( tag == FT_CURVE_TAG_CONIC )
|
|
| 2704 | + {
|
|
| 2705 | + /* first point is conic control. Yes, this happens. */
|
|
| 2706 | + if ( FT_CURVE_TAG( outline->tags[last] ) == FT_CURVE_TAG_ON )
|
|
| 2707 | + {
|
|
| 2708 | + /* start at last point if it is on the curve */
|
|
| 2709 | + v_start = v_last;
|
|
| 2710 | + limit--;
|
|
| 2711 | + }
|
|
| 2712 | + else
|
|
| 2713 | + {
|
|
| 2714 | + /* if both first and last points are conic, */
|
|
| 2715 | + /* start at their middle and record its position */
|
|
| 2716 | + /* for closure */
|
|
| 2717 | + v_start.x = ( v_start.x + v_last.x ) / 2;
|
|
| 2718 | + v_start.y = ( v_start.y + v_last.y ) / 2;
|
|
| 2719 | + |
|
| 2720 | + /* v_last = v_start; */
|
|
| 2721 | + }
|
|
| 2722 | + point--;
|
|
| 2723 | + tags--;
|
|
| 2724 | + }
|
|
| 2725 | +
|
|
| 2726 | + FT_TRACE5(( " move to (%.2f, %.2f)\n",
|
|
| 2727 | + (double)v_start.x / 64, (double)v_start.y / 64 ));
|
|
| 2728 | + |
|
| 2729 | + |
|
| 2730 | + FT_PreLine pl = malloc(sizeof(FT_PreLineRec));
|
|
| 2731 | + pl->x1 = v_start.x;
|
|
| 2732 | + pl->y1 = v_start.y;
|
|
| 2733 | + pl->x2 = v_start.x;
|
|
| 2734 | + pl->y2 = v_start.y;
|
|
| 2735 | + pl->next = NULL;
|
|
| 2736 | + |
|
| 2737 | + if ( ( *slot )->prelines == NULL )
|
|
| 2738 | + {
|
|
| 2739 | + ptr = ( *slot )->prelines = pl;
|
|
| 2740 | + }
|
|
| 2741 | + else
|
|
| 2742 | + {
|
|
| 2743 | + ptr->next = pl;
|
|
| 2744 | + ptr = ptr->next;
|
|
| 2745 | + }
|
|
| 2746 | + |
|
| 2747 | + while ( point < limit )
|
|
| 2748 | + {
|
|
| 2749 | + point++;
|
|
| 2750 | + tags++;
|
|
| 2751 | + |
|
| 2752 | + tag = FT_CURVE_TAG( tags[0] );
|
|
| 2753 | + switch ( tag )
|
|
| 2754 | + {
|
|
| 2755 | + case FT_CURVE_TAG_ON: /* emit a single line_to */
|
|
| 2756 | + {
|
|
| 2757 | + FT_Vector vec;
|
|
| 2758 | + |
|
| 2759 | + |
|
| 2760 | + vec.x = point->x;
|
|
| 2761 | + vec.y = point->y;
|
|
| 2762 | + |
|
| 2763 | + FT_TRACE5(( " line to (%.2f, %.2f)\n",
|
|
| 2764 | + (double)vec.x / 64, (double)vec.y / 64 ));
|
|
| 2765 | + |
|
| 2766 | + FT_PreLine pl3 = malloc(sizeof(FT_PreLineRec));
|
|
| 2767 | + pl3->x1 = ptr->x2;
|
|
| 2768 | + pl3->y1 = ptr->y2;
|
|
| 2769 | + pl3->x2 = vec.x;
|
|
| 2770 | + pl3->y2 = vec.y;
|
|
| 2771 | + pl3->next = NULL;
|
|
| 2772 | + ptr->next = pl3;
|
|
| 2773 | + ptr = ptr->next;
|
|
| 2774 | + continue;
|
|
| 2775 | + }
|
|
| 2776 | +
|
|
| 2777 | + case FT_CURVE_TAG_CONIC: /* consume conic arcs */
|
|
| 2778 | + v_control.x = point->x ;
|
|
| 2779 | + v_control.y = point->y ;
|
|
| 2780 | + |
|
| 2781 | + Do_Conic:
|
|
| 2782 | + if ( point < limit )
|
|
| 2783 | + {
|
|
| 2784 | + FT_Vector vec;
|
|
| 2785 | + FT_Vector v_middle;
|
|
| 2786 | + |
|
| 2787 | + |
|
| 2788 | + point++;
|
|
| 2789 | + tags++;
|
|
| 2790 | + tag = FT_CURVE_TAG( tags[0] );
|
|
| 2791 | + |
|
| 2792 | + vec.x = point->x;
|
|
| 2793 | + vec.y = point->y;
|
|
| 2794 | + |
|
| 2795 | + if ( tag == FT_CURVE_TAG_ON )
|
|
| 2796 | + {
|
|
| 2797 | + FT_TRACE5(( " conic to (%.2f, %.2f)"
|
|
| 2798 | + " with control (%.2f, %.2f)\n",
|
|
| 2799 | + (double)vec.x / 64,
|
|
| 2800 | + (double)vec.y / 64,
|
|
| 2801 | + (double)v_control.x / 64,
|
|
| 2802 | + (double)v_control.y / 64 ));
|
|
| 2803 | + FT_Vector vex0 = {ptr->x2, ptr->y2};
|
|
| 2804 | + error = conic_to2(slot, &v_control, &vex0,&vec , &ptr);
|
|
| 2805 | +
|
|
| 2806 | + continue;
|
|
| 2807 | + }
|
|
| 2808 | + |
|
| 2809 | + if ( tag != FT_CURVE_TAG_CONIC )
|
|
| 2810 | + {
|
|
| 2811 | + FT_TRACE5( ( "Invalid Outline" ) );
|
|
| 2812 | + break;
|
|
| 2813 | + }
|
|
| 2814 | + v_middle.x = ( v_control.x + vec.x ) / 2;
|
|
| 2815 | + v_middle.y = ( v_control.y + vec.y ) / 2;
|
|
| 2816 | + |
|
| 2817 | + FT_TRACE5(( " conic to (%.2f, %.2f)"
|
|
| 2818 | + " with control (%.2f, %.2f)\n",
|
|
| 2819 | + (double)v_middle.x / 64,
|
|
| 2820 | + (double)v_middle.y / 64,
|
|
| 2821 | + (double)v_control.x / 64,
|
|
| 2822 | + (double)v_control.y / 64 ));
|
|
| 2823 | + FT_Vector vex = {ptr->x2, ptr->y2};
|
|
| 2824 | + error = conic_to2(slot, &v_control, &vex,&v_middle, &ptr);
|
|
| 2825 | + |
|
| 2826 | + v_control = vec;
|
|
| 2827 | + goto Do_Conic;
|
|
| 2828 | + }
|
|
| 2829 | + |
|
| 2830 | + FT_TRACE5(( " conic to (%.2f, %.2f)"
|
|
| 2831 | + " with control (%.2f, %.2f)\n",
|
|
| 2832 | + (double)v_start.x / 64,
|
|
| 2833 | + (double)v_start.y / 64,
|
|
| 2834 | + (double)v_control.x / 64,
|
|
| 2835 | + (double)v_control.y / 64 ));
|
|
| 2836 | + FT_Vector vex2 = {ptr->x2, ptr->y2};
|
|
| 2837 | + error = conic_to2( slot, &v_control, &vex2, &v_start, &ptr );
|
|
| 2838 | + }
|
|
| 2839 | + }
|
|
| 2840 | + |
|
| 2841 | + /* close the contour with a line segment */
|
|
| 2842 | + FT_TRACE5(( " line to (%.2f, %.2f)\n",
|
|
| 2843 | + (double)v_start.x / 64, (double)v_start.y / 64 ));
|
|
| 2844 | + FT_PreLine pl2 = malloc(sizeof(FT_PreLineRec));
|
|
| 2845 | + pl2->x1 = ptr->x2;
|
|
| 2846 | + pl2->y1 = ptr->y2;
|
|
| 2847 | + pl2->x2 = v_start.x;
|
|
| 2848 | + pl2->y2 = v_start.y;
|
|
| 2849 | + pl2->next = NULL;
|
|
| 2850 | + ptr->next = pl2;
|
|
| 2851 | + ptr = ptr->next;
|
|
| 2852 | +
|
|
| 2853 | + }
|
|
| 2854 | + |
|
| 2855 | + return 0;
|
|
| 2856 | +}
|
|
| 2857 | + |
|
| 2522 | 2858 | static FT_Error
|
| 2523 | 2859 | ft_open_face_internal( FT_Library library,
|
| 2524 | 2860 | const FT_Open_Args* args,
|
| ... | ... | @@ -2748,6 +3084,33 @@ |
| 2748 | 3084 | |
| 2749 | 3085 | face->size = size;
|
| 2750 | 3086 | }
|
| 3087 | + if ( args->size > 0 )
|
|
| 3088 | + {
|
|
| 3089 | + face->glyph_array = (FT_GlyphSlot*)malloc(
|
|
| 3090 | + face->driver->clazz->slot_object_size * face->num_glyphs );
|
|
| 3091 | + error = FT_Set_Pixel_Sizes( face, 0, args->size );
|
|
| 3092 | + |
|
| 3093 | + for ( int gindex = 0; gindex < face->num_glyphs; gindex++ )
|
|
| 3094 | + {
|
|
| 3095 | + driver = face->driver;
|
|
| 3096 | + FT_Driver_Class clazz = driver->clazz;
|
|
| 3097 | + memory = driver->root.memory;
|
|
| 3098 | + |
|
| 3099 | + FT_ALLOC( face->glyph_array[gindex], clazz->slot_object_size );
|
|
| 3100 | +
|
|
| 3101 | + face->glyph_array[gindex]->face = face;
|
|
| 3102 | + face->glyph_array[gindex]->prel_shifted = 0;
|
|
| 3103 | + face->glyph_array[gindex]->glyph_index = gindex;
|
|
| 3104 | + ft_glyphslot_init( face->glyph_array[gindex] );
|
|
| 3105 | + |
|
| 3106 | + face->glyph_array[gindex]->next = NULL;
|
|
| 3107 | + *face->glyph = *face->glyph_array[gindex];
|
|
| 3108 | + |
|
| 3109 | + FT_Load_Glyph( face, gindex, FT_LOAD_NO_HINTING );
|
|
| 3110 | + |
|
| 3111 | + ft_decompose_outline( &face->glyph_array[gindex] );
|
|
| 3112 | + }
|
|
| 3113 | + }
|
|
| 2751 | 3114 | }
|
| 2752 | 3115 | |
| 2753 | 3116 | /* some checks */
|
| ... | ... | @@ -16,15 +16,25 @@ |
| 16 | 16 | defined( __x86_64__ ) || \
|
| 17 | 17 | defined( _M_AMD64 ) || \
|
| 18 | 18 | ( defined( _M_IX86_FP ) && _M_IX86_FP >= 2 )
|
| 19 | -# define FT_SSE4_1 1
|
|
| 19 | + #define FT_SSE4_1 1
|
|
| 20 | 20 | #else
|
| 21 | -# define FT_SSE4_1 0
|
|
| 21 | + #define FT_SSE4_1 0
|
|
| 22 | +#endif
|
|
| 23 | + |
|
| 24 | +#if defined(__ARM_NEON)
|
|
| 25 | + #define FT_NEON 1
|
|
| 26 | +#else
|
|
| 27 | + #define FT_NEON 0
|
|
| 22 | 28 | #endif
|
| 23 | 29 | |
| 24 | 30 | |
| 25 | 31 | #if FT_SSE4_1
|
| 26 | 32 | |
| 27 | - #include <tmmintrin.h>
|
|
| 33 | + #include <immintrin.h>
|
|
| 34 | + |
|
| 35 | +#elif FT_NEON
|
|
| 36 | + |
|
| 37 | + #include <arm_neon.h>
|
|
| 28 | 38 | |
| 29 | 39 | #endif
|
| 30 | 40 | |
| ... | ... | @@ -41,6 +51,11 @@ |
| 41 | 51 | #define FT_MAX( a, b ) ( (a) > (b) ? (a) : (b) )
|
| 42 | 52 | #define FT_ABS( a ) ( (a) < 0 ? -(a) : (a) )
|
| 43 | 53 | |
| 54 | +// TODO: Fix types
|
|
| 55 | +#define FT_UDIVPREP( c, b ) \
|
|
| 56 | + FT26D6 b ## _r = c ? (FT26D6)0xFFFFFFFF / ( b ) : 0
|
|
| 57 | +#define FT_UDIV( a, b ) \
|
|
| 58 | + (FT26D6)( ( (FT26D6)( a ) * (FT26D6)( b ## _r ) ) >> 32 )
|
|
| 44 | 59 | |
| 45 | 60 | typedef struct dense_TRaster_
|
| 46 | 61 | {
|
| ... | ... | @@ -79,108 +94,319 @@ dense_line_to( const FT_Vector* to, dense_worker* worker ) |
| 79 | 94 | }
|
| 80 | 95 | |
| 81 | 96 | void
|
| 82 | -dense_render_line( dense_worker* worker, FT_Pos tox, FT_Pos toy )
|
|
| 97 | +dense_render_line2( dense_worker* worker, FT_PreLine pl )
|
|
| 83 | 98 | {
|
| 84 | - float from_x = worker->prev_x;
|
|
| 85 | - float from_y = worker->prev_y;
|
|
| 86 | - if ( from_y == toy )
|
|
| 87 | - return;
|
|
| 88 | 99 | |
| 100 | + FT26D6 fx = UPSCALE(pl->x1)>>2;
|
|
| 101 | + FT26D6 fy = UPSCALE(pl->y1)>>2;
|
|
| 89 | 102 | |
| 90 | - from_x /= 256.0;
|
|
| 91 | - from_y /= 256.0;
|
|
| 92 | - float to_x = tox / 256.0;
|
|
| 93 | - float to_y = toy / 256.0;
|
|
| 103 | + FT26D6 from_x = fx;
|
|
| 104 | + FT26D6 from_y = fy;
|
|
| 94 | 105 | |
| 95 | 106 | |
| 96 | - float dir;
|
|
| 97 | - if ( from_y < to_y )
|
|
| 98 | - dir = 1;
|
|
| 99 | - else
|
|
| 107 | + FT26D6 tx = UPSCALE(pl->x2)>>2;
|
|
| 108 | + FT26D6 ty = UPSCALE(pl->y2)>>2;
|
|
| 109 | + |
|
| 110 | + if ( fy == ty )
|
|
| 111 | + return;
|
|
| 112 | + |
|
| 113 | + FT26D6 to_x = tx;
|
|
| 114 | + FT26D6 to_y = ty;
|
|
| 115 | + |
|
| 116 | + int dir = 1;
|
|
| 117 | + if ( from_y >= to_y )
|
|
| 100 | 118 | {
|
| 101 | 119 | dir = -1;
|
| 102 | - FT_SWAP(from_x, to_x );
|
|
| 103 | - FT_SWAP(from_y, to_y );
|
|
| 120 | + FT_SWAP(from_x, to_x);
|
|
| 121 | + FT_SWAP(from_y, to_y);
|
|
| 104 | 122 | }
|
| 105 | 123 | |
| 106 | 124 | // Clip to the height.
|
| 107 | - if ( from_y >= worker->m_h || to_y <= 0 )
|
|
| 125 | + if ( from_y >= worker->m_h<<6 || to_y <= 0 )
|
|
| 108 | 126 | return;
|
| 109 | 127 | |
| 110 | - float dxdy = ( to_x - from_x ) / (float)( to_y - from_y );
|
|
| 128 | + FT26D6 deltax,deltay;
|
|
| 129 | + deltax = to_x - from_x;
|
|
| 130 | + deltay = to_y - from_y;
|
|
| 131 | + |
|
| 132 | + FT_UDIVPREP(from_x != to_x, deltax);
|
|
| 133 | + |
|
| 134 | + FT_UDIVPREP(from_y != to_y, deltay);
|
|
| 135 | + |
|
| 111 | 136 | if ( from_y < 0 )
|
| 112 | 137 | {
|
| 113 | - from_x -= from_y * dxdy;
|
|
| 138 | + from_x -= from_y * deltax/deltay;
|
|
| 114 | 139 | from_y = 0;
|
| 115 | 140 | }
|
| 116 | - if ( to_y > worker->m_h )
|
|
| 141 | + |
|
| 142 | + if ( to_y > worker->m_h<<6 )
|
|
| 117 | 143 | {
|
| 118 | - to_x -= ( to_y - worker->m_h ) * dxdy;
|
|
| 119 | - to_y = (float)worker->m_h;
|
|
| 144 | + to_x -= (( to_y - worker->m_h<<6 ) * deltax/deltay);
|
|
| 145 | + to_y = worker->m_h<<6;
|
|
| 120 | 146 | }
|
| 121 | 147 | |
| 122 | - float x = from_x;
|
|
| 123 | - int y0 = (int)from_y;
|
|
| 124 | - int y_limit = (int)ceil( to_y );
|
|
| 125 | - float* m_a = worker->m_a;
|
|
| 126 | 148 | |
| 127 | - for ( int y = y0; y < y_limit; y++ )
|
|
| 128 | - {
|
|
| 129 | - int linestart = y * worker->m_w;
|
|
| 130 | - float dy = fmin( y + 1.0f, to_y ) - fmax( (float)y, from_y );
|
|
| 131 | - float xnext = x + dxdy * dy;
|
|
| 132 | - float d = dy * dir;
|
|
| 149 | + if(deltax == 0){
|
|
| 150 | + FT26D6 x = from_x;
|
|
| 151 | + int x0i = x>>6;
|
|
| 152 | + FT26D6 x0floor = x0i<<6;
|
|
| 153 | + |
|
| 154 | + // y-coordinate of first pixel of line
|
|
| 155 | + int y0 = from_y>>6;
|
|
| 156 | + |
|
| 157 | + // y-coordinate of last pixel of line
|
|
| 158 | + int y_limit = (to_y + 0x3f)>>6;
|
|
| 159 | + FT20D12* m_a = worker->m_a;
|
|
| 133 | 160 | |
| 134 | - float x0, x1;
|
|
| 135 | - if ( x < xnext )
|
|
| 161 | + |
|
| 162 | + |
|
| 163 | + for ( int y = y0; y < y_limit; y++ )
|
|
| 136 | 164 | {
|
| 137 | - x0 = x;
|
|
| 138 | - x1 = xnext;
|
|
| 165 | + int linestart = y * worker->m_w;
|
|
| 166 | + |
|
| 167 | + FT26D6 dy = FT_MIN( (y + 1)<<6, to_y ) - FT_MAX( y<<6, from_y );
|
|
| 168 | + |
|
| 169 | + m_a[linestart + x0i] += dir*dy*(64 - x + x0floor);
|
|
| 170 | + m_a[linestart + ( x0i + 1 )] += dir*dy*(x-x0floor);
|
|
| 171 | + |
|
| 139 | 172 | }
|
| 140 | - else
|
|
| 173 | + }
|
|
| 174 | + else
|
|
| 175 | + {
|
|
| 176 | + int x = from_x;
|
|
| 177 | + int y0 = from_y>>6;
|
|
| 178 | + int y_limit = (to_y + 0x3f)>>6;
|
|
| 179 | + |
|
| 180 | + FT20D12* m_a = worker->m_a;
|
|
| 181 | + |
|
| 182 | + for ( int y = y0; y < y_limit; y++ )
|
|
| 141 | 183 | {
|
| 142 | - x0 = xnext;
|
|
| 143 | - x1 = x;
|
|
| 184 | + int linestart = y * worker->m_w;
|
|
| 185 | + FT26D6 dy = FT_MIN( (y + 1)<<6, to_y ) - FT_MAX( y<<6, from_y );
|
|
| 186 | + FT26D6 xnext = x + FT_UDIV((dy*deltax), deltay);
|
|
| 187 | + FT26D6 d = dy * dir;
|
|
| 188 | + |
|
| 189 | + FT26D6 x0, x1;
|
|
| 190 | + if ( x < xnext )
|
|
| 191 | + {
|
|
| 192 | + x0 = x;
|
|
| 193 | + x1 = xnext;
|
|
| 194 | + }
|
|
| 195 | + else
|
|
| 196 | + {
|
|
| 197 | + x0 = xnext;
|
|
| 198 | + x1 = x;
|
|
| 199 | + }
|
|
| 200 | + |
|
| 201 | + |
|
| 202 | + int x0i = x0>>6;
|
|
| 203 | + FT26D6 x0floor = x0i<<6;
|
|
| 204 | + |
|
| 205 | + |
|
| 206 | + int x1i = (x1+0x3f)>>6;
|
|
| 207 | + FT26D6 x1ceil = x1i <<6;
|
|
| 208 | + |
|
| 209 | + if ( x1i <= x0i + 1 )
|
|
| 210 | + {
|
|
| 211 | + FT26D6 xmf = ( ( x + xnext )>>1) - x0floor;
|
|
| 212 | + m_a[linestart + x0i] += d * ((1<<6) - xmf);
|
|
| 213 | + m_a[linestart + ( x0i + 1 )] += d * xmf;
|
|
| 214 | + }
|
|
| 215 | + else
|
|
| 216 | + {
|
|
| 217 | + |
|
| 218 | + FT26D6 oneOverS = x1 - x0;
|
|
| 219 | + |
|
| 220 | + FT_UDIVPREP(x1 != x0, oneOverS);
|
|
| 221 | + |
|
| 222 | + FT26D6 x0f = x0 - x0floor;
|
|
| 223 | + |
|
| 224 | + |
|
| 225 | + FT26D6 oneMinusX0f = (1<<6) - x0f;
|
|
| 226 | + FT26D6 a0 = FT_UDIV(((oneMinusX0f * oneMinusX0f) >> 1), oneOverS);
|
|
| 227 | + FT26D6 x1f = x1 - x1ceil + (1<<6);
|
|
| 228 | + FT26D6 am = FT_UDIV(((x1f * x1f) >> 1) , oneOverS);
|
|
| 229 | + |
|
| 230 | + m_a[linestart + x0i] += d * a0;
|
|
| 231 | + |
|
| 232 | + if ( x1i == x0i + 2 )
|
|
| 233 | + m_a[linestart + ( x0i + 1 )] += d * ( (1<<6) - a0 - am );
|
|
| 234 | + else
|
|
| 235 | + {
|
|
| 236 | + FT26D6 a1 = FT_UDIV((((1<<6) + (1<<5) - x0f) << 6) , oneOverS);
|
|
| 237 | + m_a[linestart + ( x0i + 1 )] += d * ( a1 - a0 );
|
|
| 238 | + |
|
| 239 | + FT26D6 dTimesS = FT_UDIV((d << 12) , oneOverS);
|
|
| 240 | + |
|
| 241 | + for ( FT26D6 xi = x0i + 2; xi < x1i - 1; xi++ )
|
|
| 242 | + m_a[linestart + xi] += dTimesS;
|
|
| 243 | + |
|
| 244 | + FT26D6 a2 = a1 + FT_UDIV((( x1i - x0i - 3 )<<12),oneOverS);
|
|
| 245 | + m_a[linestart + ( x1i - 1 )] += d * ( (1<<6) - a2 - am );
|
|
| 246 | + }
|
|
| 247 | + m_a[linestart + x1i] += d * am;
|
|
| 248 | + }
|
|
| 249 | + x = xnext;
|
|
| 144 | 250 | }
|
| 251 | + }
|
|
| 252 | +}
|
|
| 253 | + |
|
| 254 | + |
|
| 255 | +void
|
|
| 256 | +dense_render_line( dense_worker* worker, FT_Pos tox, FT_Pos toy )
|
|
| 257 | +{
|
|
| 258 | + |
|
| 259 | + FT26D6 fx = worker->prev_x>>2;
|
|
| 260 | + FT26D6 fy = worker->prev_y>>2;
|
|
| 261 | + |
|
| 262 | + FT26D6 from_x = fx;
|
|
| 263 | + FT26D6 from_y = fy;
|
|
| 264 | + |
|
| 265 | + |
|
| 266 | + FT26D6 tx = tox>>2;
|
|
| 267 | + FT26D6 ty = toy>>2;
|
|
| 268 | + |
|
| 269 | + if ( fy == ty )
|
|
| 270 | + return;
|
|
| 271 | + |
|
| 272 | + FT26D6 to_x = tx;
|
|
| 273 | + FT26D6 to_y = ty;
|
|
| 274 | + |
|
| 275 | + int dir = 1;
|
|
| 276 | + if ( from_y >= to_y )
|
|
| 277 | + {
|
|
| 278 | + dir = -1;
|
|
| 279 | + FT_SWAP(from_x, to_x);
|
|
| 280 | + FT_SWAP(from_y, to_y);
|
|
| 281 | + }
|
|
| 282 | + |
|
| 283 | + // Clip to the height.
|
|
| 284 | + if ( from_y >= worker->m_h<<6 || to_y <= 0 )
|
|
| 285 | + return;
|
|
| 145 | 286 | |
| 146 | - /*
|
|
| 147 | - It's possible for x0 to be negative on the last scanline because of
|
|
| 148 | - floating-point inaccuracy That would cause an out-of-bounds array access at
|
|
| 149 | - index -1.
|
|
| 150 | - */
|
|
| 151 | - float x0floor = x0 <= 0.0f ? 0.0f : (float)floor( x0 );
|
|
| 152 | - |
|
| 153 | - int x0i = (int)x0floor;
|
|
| 154 | - float x1ceil = (float)ceil( x1 );
|
|
| 155 | - int x1i = (int)x1ceil;
|
|
| 156 | - if ( x1i <= x0i + 1 )
|
|
| 287 | + FT26D6 deltax,deltay;
|
|
| 288 | + deltax = to_x - from_x;
|
|
| 289 | + deltay = to_y - from_y;
|
|
| 290 | + |
|
| 291 | + FT_UDIVPREP(from_x != to_x, deltax);
|
|
| 292 | + |
|
| 293 | + FT_UDIVPREP(from_y != to_y, deltay);
|
|
| 294 | + |
|
| 295 | + if ( from_y < 0 )
|
|
| 296 | + {
|
|
| 297 | + from_x -= from_y * deltax/deltay;
|
|
| 298 | + from_y = 0;
|
|
| 299 | + }
|
|
| 300 | + |
|
| 301 | + if ( to_y > worker->m_h<<6 )
|
|
| 302 | + {
|
|
| 303 | + to_x -= (( to_y - worker->m_h<<6 ) * deltax/deltay);
|
|
| 304 | + to_y = worker->m_h<<6;
|
|
| 305 | + }
|
|
| 306 | + |
|
| 307 | + |
|
| 308 | + if(deltax == 0){
|
|
| 309 | + FT26D6 x = from_x;
|
|
| 310 | + int x0i = x>>6;
|
|
| 311 | + FT26D6 x0floor = x0i<<6;
|
|
| 312 | + |
|
| 313 | + // y-coordinate of first pixel of line
|
|
| 314 | + int y0 = from_y>>6;
|
|
| 315 | + |
|
| 316 | + // y-coordinate of last pixel of line
|
|
| 317 | + int y_limit = (to_y + 0x3f)>>6;
|
|
| 318 | + FT20D12* m_a = worker->m_a;
|
|
| 319 | + |
|
| 320 | + |
|
| 321 | + |
|
| 322 | + for ( int y = y0; y < y_limit; y++ )
|
|
| 157 | 323 | {
|
| 158 | - float xmf = 0.5f * ( x + xnext ) - x0floor;
|
|
| 159 | - m_a[linestart + x0i] += d - d * xmf;
|
|
| 160 | - m_a[linestart + ( x0i + 1 )] += d * xmf;
|
|
| 324 | + int linestart = y * worker->m_w;
|
|
| 325 | + |
|
| 326 | + FT26D6 dy = FT_MIN( (y + 1)<<6, to_y ) - FT_MAX( y<<6, from_y );
|
|
| 327 | + |
|
| 328 | + m_a[linestart + x0i] += dir*dy*(64 - x + x0floor);
|
|
| 329 | + m_a[linestart + ( x0i + 1 )] += dir*dy*(x-x0floor);
|
|
| 330 | + |
|
| 161 | 331 | }
|
| 162 | - else
|
|
| 332 | + }
|
|
| 333 | + else
|
|
| 334 | + {
|
|
| 335 | + int x = from_x;
|
|
| 336 | + int y0 = from_y>>6;
|
|
| 337 | + int y_limit = (to_y + 0x3f)>>6;
|
|
| 338 | + |
|
| 339 | + FT20D12* m_a = worker->m_a;
|
|
| 340 | + |
|
| 341 | + for ( int y = y0; y < y_limit; y++ )
|
|
| 163 | 342 | {
|
| 164 | - float s = 1.0f / ( x1 - x0 );
|
|
| 165 | - float x0f = x0 - x0floor;
|
|
| 166 | - float a0 = 0.5f * s * ( 1.0f - x0f ) * ( 1.0f - x0f );
|
|
| 167 | - float x1f = x1 - x1ceil + 1.0f;
|
|
| 168 | - float am = 0.5f * s * x1f * x1f;
|
|
| 169 | - m_a[linestart + x0i] += d * a0;
|
|
| 170 | - if ( x1i == x0i + 2 )
|
|
| 171 | - m_a[linestart + ( x0i + 1 )] += d * ( 1.0f - a0 - am );
|
|
| 343 | + int linestart = y * worker->m_w;
|
|
| 344 | + FT26D6 dy = FT_MIN( (y + 1)<<6, to_y ) - FT_MAX( y<<6, from_y );
|
|
| 345 | + FT26D6 xnext = x + FT_UDIV((dy*deltax), deltay);
|
|
| 346 | + FT26D6 d = dy * dir;
|
|
| 347 | + |
|
| 348 | + FT26D6 x0, x1;
|
|
| 349 | + if ( x < xnext )
|
|
| 350 | + {
|
|
| 351 | + x0 = x;
|
|
| 352 | + x1 = xnext;
|
|
| 353 | + }
|
|
| 354 | + else
|
|
| 355 | + {
|
|
| 356 | + x0 = xnext;
|
|
| 357 | + x1 = x;
|
|
| 358 | + }
|
|
| 359 | + |
|
| 360 | + |
|
| 361 | + int x0i = x0>>6;
|
|
| 362 | + FT26D6 x0floor = x0i<<6;
|
|
| 363 | + |
|
| 364 | + |
|
| 365 | + int x1i = (x1+0x3f)>>6;
|
|
| 366 | + FT26D6 x1ceil = x1i <<6;
|
|
| 367 | + |
|
| 368 | + if ( x1i <= x0i + 1 )
|
|
| 369 | + {
|
|
| 370 | + FT26D6 xmf = ( ( x + xnext )>>1) - x0floor;
|
|
| 371 | + m_a[linestart + x0i] += d * ((1<<6) - xmf);
|
|
| 372 | + m_a[linestart + ( x0i + 1 )] += d * xmf;
|
|
| 373 | + }
|
|
| 172 | 374 | else
|
| 173 | 375 | {
|
| 174 | - float a1 = s * ( 1.5f - x0f );
|
|
| 175 | - m_a[linestart + ( x0i + 1 )] += d * ( a1 - a0 );
|
|
| 176 | - for ( int xi = x0i + 2; xi < x1i - 1; xi++ )
|
|
| 177 | - m_a[linestart + xi] += d * s;
|
|
| 178 | - float a2 = a1 + ( x1i - x0i - 3 ) * s;
|
|
| 179 | - m_a[linestart + ( x1i - 1 )] += d * ( 1.0f - a2 - am );
|
|
| 376 | + |
|
| 377 | + FT26D6 oneOverS = x1 - x0;
|
|
| 378 | + |
|
| 379 | + FT_UDIVPREP(x1 != x0, oneOverS);
|
|
| 380 | + |
|
| 381 | + FT26D6 x0f = x0 - x0floor;
|
|
| 382 | + |
|
| 383 | + |
|
| 384 | + FT26D6 oneMinusX0f = (1<<6) - x0f;
|
|
| 385 | + FT26D6 a0 = FT_UDIV(((oneMinusX0f * oneMinusX0f) >> 1), oneOverS);
|
|
| 386 | + FT26D6 x1f = x1 - x1ceil + (1<<6);
|
|
| 387 | + FT26D6 am = FT_UDIV(((x1f * x1f) >> 1) , oneOverS);
|
|
| 388 | + |
|
| 389 | + m_a[linestart + x0i] += d * a0;
|
|
| 390 | + |
|
| 391 | + if ( x1i == x0i + 2 )
|
|
| 392 | + m_a[linestart + ( x0i + 1 )] += d * ( (1<<6) - a0 - am );
|
|
| 393 | + else
|
|
| 394 | + {
|
|
| 395 | + FT26D6 a1 = FT_UDIV((((1<<6) + (1<<5) - x0f) << 6) , oneOverS);
|
|
| 396 | + m_a[linestart + ( x0i + 1 )] += d * ( a1 - a0 );
|
|
| 397 | + |
|
| 398 | + FT26D6 dTimesS = FT_UDIV((d << 12) , oneOverS);
|
|
| 399 | + |
|
| 400 | + for ( FT26D6 xi = x0i + 2; xi < x1i - 1; xi++ )
|
|
| 401 | + m_a[linestart + xi] += dTimesS;
|
|
| 402 | + |
|
| 403 | + FT26D6 a2 = a1 + FT_UDIV((( x1i - x0i - 3 )<<12),oneOverS);
|
|
| 404 | + m_a[linestart + ( x1i - 1 )] += d * ( (1<<6) - a2 - am );
|
|
| 405 | + }
|
|
| 406 | + m_a[linestart + x1i] += d * am;
|
|
| 180 | 407 | }
|
| 181 | - m_a[linestart + x1i] += d * am;
|
|
| 408 | + x = xnext;
|
|
| 182 | 409 | }
|
| 183 | - x = xnext;
|
|
| 184 | 410 | }
|
| 185 | 411 | }
|
| 186 | 412 | |
| ... | ... | @@ -359,53 +585,92 @@ FT_DEFINE_OUTLINE_FUNCS( dense_decompose_funcs, |
| 359 | 585 | )
|
| 360 | 586 | |
| 361 | 587 | static int
|
| 362 | -dense_render_glyph( dense_worker* worker, const FT_Bitmap* target )
|
|
| 588 | +dense_render_glyph( dense_worker* worker, const FT_Bitmap* target, FT_PreLine pl )
|
|
| 363 | 589 | {
|
| 364 | - FT_Error error = FT_Outline_Decompose( &( worker->outline ),
|
|
| 365 | - &dense_decompose_funcs, worker );
|
|
| 590 | + FT_Error error = 0;
|
|
| 591 | + |
|
| 592 | + while (pl != NULL)
|
|
| 593 | + {
|
|
| 594 | + dense_render_line2(worker, pl);
|
|
| 595 | + pl = pl->next;
|
|
| 596 | + }
|
|
| 597 | + |
|
| 366 | 598 | // Render into bitmap
|
| 367 | - const float* source = worker->m_a;
|
|
| 599 | + const FT20D12* source = worker->m_a;
|
|
| 368 | 600 | unsigned char* dest = target->buffer;
|
| 369 | 601 | unsigned char* dest_end = target->buffer + worker->m_w * worker->m_h;
|
| 370 | 602 | |
| 371 | 603 | #if FT_SSE4_1
|
| 372 | 604 | |
| 373 | - __m128 offset = _mm_setzero_ps();
|
|
| 374 | - __m128i mask = _mm_set1_epi32(0x0c080400);
|
|
| 375 | - __m128 sign_mask = _mm_set1_ps(-0.f);
|
|
| 376 | - for (int i = 0; i < worker->m_h*worker->m_w; i += 4) {
|
|
| 377 | - __m128 x = _mm_load_ps(&source[i]);
|
|
| 378 | - x = _mm_add_ps(x, _mm_castsi128_ps(_mm_slli_si128(_mm_castps_si128(x), 4)));
|
|
| 379 | - x = _mm_add_ps(x, _mm_shuffle_ps(_mm_setzero_ps(), x, 0x40));
|
|
| 380 | - x = _mm_add_ps(x, offset);
|
|
| 381 | - __m128 y = _mm_andnot_ps(sign_mask, x); // fabs(x)
|
|
| 382 | - y = _mm_min_ps(y, _mm_set1_ps(1.0f));
|
|
| 383 | - y = _mm_mul_ps(y, _mm_set1_ps(255.0f));
|
|
| 384 | - __m128i z = _mm_cvtps_epi32(y);
|
|
| 385 | - z = _mm_shuffle_epi8(z, mask);
|
|
| 386 | - _mm_store_ss((float *)&dest[i], (__m128)z);
|
|
| 387 | - offset = _mm_shuffle_ps(x, x, _MM_SHUFFLE(3, 3, 3, 3));
|
|
| 605 | + __m128i offset = _mm_setzero_si128();
|
|
| 606 | + __m128i nzero = _mm_castps_si128(_mm_set1_ps(-0.0));
|
|
| 607 | + |
|
| 608 | + for (int i = 0; i < worker->m_h*worker->m_w; i += 4)
|
|
| 609 | + {
|
|
| 610 | + // load 4 floats from source
|
|
| 611 | + |
|
| 612 | + __m128i x = _mm_load_si128( (__m128i*)&source[i] );
|
|
| 613 | + |
|
| 614 | + x = _mm_add_epi32( x, _mm_slli_si128( x, 4 ) );
|
|
| 615 | + |
|
| 616 | + x = _mm_add_epi32( x, _mm_slli_si128( x, 8 ) );
|
|
| 617 | + |
|
| 618 | + // add the prefix sum of previous 4 ints to all ints
|
|
| 619 | + x = _mm_add_epi32( x, offset );
|
|
| 620 | + |
|
| 621 | + // take absolute value
|
|
| 622 | + __m128i y = _mm_srli_epi32( _mm_abs_epi32( x) , 4 );
|
|
| 623 | + y = _mm_packus_epi16(_mm_packs_epi32(y, nzero), nzero);
|
|
| 624 | + _mm_storeu_si32(&dest[i], y);
|
|
| 625 | + |
|
| 626 | + // store the current prefix sum in offset
|
|
| 627 | + offset = _mm_shuffle_epi32(x,_MM_SHUFFLE( 3, 3, 3, 3 ) );
|
|
| 388 | 628 | }
|
| 629 | +#elif FT_NEON
|
|
| 630 | + int32x4_t offset = vdupq_n_s32(0);
|
|
| 631 | + int32x4_t nzero = vreinterpretq_s32_f32(vdupq_n_f32(-0.0));
|
|
| 632 | + |
|
| 633 | + for (int i = 0; i < worker->m_h*worker->m_w; i += 4)
|
|
| 634 | + {
|
|
| 635 | + // load 4 floats from source
|
|
| 636 | + |
|
| 637 | + int32x4_t x = vld1q_s32( (int32_t*)&source[i] );
|
|
| 638 | + |
|
| 639 | + x = vaddq_s32( x, vreinterpretq_s32_s8(vextq_s8(vdupq_n_s8(0), vreinterpretq_s8_s32( x), 12) ));
|
|
| 640 | + |
|
| 641 | + x = vaddq_s32(x, vreinterpretq_s32_s8(vextq_s8(vdupq_n_s8(0), vreinterpretq_s8_s32(x), 8)));
|
|
| 642 | + |
|
| 643 | + // add the prefsum of previous 4 floats to all current floats
|
|
| 644 | + x = vaddq_s32( x, offset );
|
|
| 645 | + |
|
| 646 | + int32x4_t y = vshrq_n_s32( vabsq_s32( x) , 4 );
|
|
| 647 | + y = vreinterpretq_s32_s16(vcombine_s16(vqmovn_s32(y), vqmovn_s32(nzero)));
|
|
| 648 | + y = vreinterpretq_s32_u8(vcombine_u8(vqmovun_s16(vreinterpretq_s16_s32(y)), vqmovun_s16(vreinterpretq_s16_s32(nzero))));
|
|
| 389 | 649 | |
| 390 | -#else /* FT_SSE4_1 */
|
|
| 650 | + vst1q_s32(&dest[i], y);
|
|
| 651 | + |
|
| 652 | + offset = vdupq_laneq_s32(x,3 );
|
|
| 653 | + }
|
|
| 654 | +#else
|
|
| 655 | + |
|
| 656 | + FT20D12 value = 0;
|
|
| 391 | 657 | |
| 392 | - float value = 0.0f;
|
|
| 393 | 658 | while ( dest < dest_end )
|
| 394 | 659 | {
|
| 395 | 660 | value += *source++;
|
| 396 | - if ( value > 0.0f )
|
|
| 397 | - {
|
|
| 398 | - int n = (int)( fabs( value ) * 255.0f + 0.5f );
|
|
| 399 | - if ( n > 255 )
|
|
| 400 | - n = 255;
|
|
| 661 | + |
|
| 662 | + if(value > 0){
|
|
| 663 | + int n = value >>4;
|
|
| 664 | + |
|
| 665 | + if(n>255)n=255;
|
|
| 401 | 666 | *dest = (unsigned char)n;
|
| 402 | - }
|
|
| 403 | - else
|
|
| 667 | + }else{
|
|
| 404 | 668 | *dest = 0;
|
| 669 | + }
|
|
| 405 | 670 | dest++;
|
| 406 | 671 | }
|
| 407 | 672 | |
| 408 | -#endif /* FT_SSE4_1 */
|
|
| 673 | +#endif /* FT_SSE4_1 || FT_NEON */
|
|
| 409 | 674 | |
| 410 | 675 | free(worker->m_a);
|
| 411 | 676 | return error;
|
| ... | ... | @@ -416,6 +681,7 @@ dense_raster_render( FT_Raster raster, const FT_Raster_Params* params ) |
| 416 | 681 | {
|
| 417 | 682 | const FT_Outline* outline = (const FT_Outline*)params->source;
|
| 418 | 683 | FT_Bitmap* target_map = params->target;
|
| 684 | + FT_PreLine pl = params->prelines;
|
|
| 419 | 685 | |
| 420 | 686 | dense_worker worker[1];
|
| 421 | 687 | |
| ... | ... | @@ -442,12 +708,12 @@ dense_raster_render( FT_Raster raster, const FT_Raster_Params* params ) |
| 442 | 708 | worker->m_w = target_map->pitch;
|
| 443 | 709 | worker->m_h = target_map->rows;
|
| 444 | 710 | |
| 445 | - int size = worker->m_w * worker->m_h + 4;
|
|
| 711 | + int size = (worker->m_w * worker->m_h + 3) & ~3;
|
|
| 446 | 712 | |
| 447 | - worker->m_a = malloc( sizeof( float ) * size );
|
|
| 713 | + worker->m_a = malloc( sizeof( FT20D12 ) * size );
|
|
| 448 | 714 | worker->m_a_size = size;
|
| 449 | 715 | |
| 450 | - memset( worker->m_a, 0, ( sizeof( float ) * size ) );
|
|
| 716 | + memset( worker->m_a, 0, ( sizeof( FT20D12 ) * size ) );
|
|
| 451 | 717 | /* exit if nothing to do */
|
| 452 | 718 | if ( worker->m_w <= worker->m_origin_x || worker->m_h <= worker->m_origin_y )
|
| 453 | 719 | {
|
| ... | ... | @@ -457,7 +723,7 @@ dense_raster_render( FT_Raster raster, const FT_Raster_Params* params ) |
| 457 | 723 | // Invert the pitch to account for different +ve y-axis direction in dense array
|
| 458 | 724 | // (maybe temporary solution)
|
| 459 | 725 | target_map->pitch *= -1;
|
| 460 | - return dense_render_glyph( worker, target_map );
|
|
| 726 | + return dense_render_glyph( worker, target_map, pl );
|
|
| 461 | 727 | }
|
| 462 | 728 | |
| 463 | 729 | FT_DEFINE_RASTER_FUNCS(
|
| ... | ... | @@ -19,10 +19,14 @@ extern "C" |
| 19 | 19 | {
|
| 20 | 20 | #endif
|
| 21 | 21 | |
| 22 | + |
|
| 23 | + typedef signed long FT26D6; /* 26.6 fixed-point representation */
|
|
| 24 | + typedef signed int FT20D12; /* 20.12 fixed-point representation */
|
|
| 25 | + |
|
| 22 | 26 | typedef struct
|
| 23 | 27 | {
|
| 24 | 28 | /** The array used to store signed area differences. */
|
| 25 | - float* m_a;
|
|
| 29 | + FT20D12* m_a;
|
|
| 26 | 30 | /** The number of elements in m_a. */
|
| 27 | 31 | int m_a_size;
|
| 28 | 32 | /** The width of the current raster in pixels. */
|
| ... | ... | @@ -139,7 +139,8 @@ |
| 139 | 139 | |
| 140 | 140 | |
| 141 | 141 | /* allocate new one */
|
| 142 | - if ( FT_ALLOC_MULT( bitmap->buffer, bitmap->rows, bitmap->pitch ) )
|
|
| 142 | + // ARM NEON crashes if memory is not aligned
|
|
| 143 | + if ( FT_ALLOC_MULT( bitmap->buffer, 1,bitmap->rows*bitmap->pitch + 16 ) )
|
|
| 143 | 144 | goto Exit;
|
| 144 | 145 | |
| 145 | 146 | slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
|
| ... | ... | @@ -161,12 +162,25 @@ |
| 161 | 162 | }
|
| 162 | 163 | |
| 163 | 164 | /* translate outline to render it into the bitmap */
|
| 164 | - if ( x_shift || y_shift )
|
|
| 165 | - FT_Outline_Translate( outline, x_shift, y_shift );
|
|
| 165 | + if ( (x_shift || y_shift) && !slot->prel_shifted){
|
|
| 166 | + //FT_Outline_Translate( outline, x_shift, y_shift );
|
|
| 167 | + FT_PreLine pl = slot->prelines;
|
|
| 168 | + while (pl!=NULL)
|
|
| 169 | + {
|
|
| 170 | + pl->x1 += x_shift;
|
|
| 171 | + pl->y1 += y_shift;
|
|
| 172 | + pl->x2 += x_shift;
|
|
| 173 | + pl->y2 += y_shift;
|
|
| 174 | + |
|
| 175 | + pl = pl->next;
|
|
| 176 | + }
|
|
| 177 | + slot->prel_shifted = 1;
|
|
| 178 | + }
|
|
| 166 | 179 | |
| 167 | 180 | /* set up parameters */
|
| 168 | 181 | params.target = bitmap;
|
| 169 | 182 | params.source = outline;
|
| 183 | + params.prelines = slot->prelines;
|
|
| 170 | 184 | |
| 171 | 185 | /* render the outline */
|
| 172 | 186 | error =
|
| ... | ... | @@ -184,8 +198,8 @@ |
| 184 | 198 | slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
|
| 185 | 199 | }
|
| 186 | 200 | |
| 187 | - if ( x_shift || y_shift )
|
|
| 188 | - FT_Outline_Translate( outline, -x_shift, -y_shift );
|
|
| 201 | + // if ( x_shift || y_shift )
|
|
| 202 | + // FT_Outline_Translate( outline, -x_shift, -y_shift );
|
|
| 189 | 203 | |
| 190 | 204 | return error;
|
| 191 | 205 | }
|
| ... | ... | @@ -24,7 +24,7 @@ DENSE_COMPILE := $(CC) $(ANSIFLAGS) \ |
| 24 | 24 | $I$(subst /,$(COMPILER_SEP),$(DENSE_DIR)) \
|
| 25 | 25 | $(INCLUDE_FLAGS) \
|
| 26 | 26 | $(FT_CFLAGS) \
|
| 27 | - "-msse4.1"
|
|
| 27 | + "-march=native"
|
|
| 28 | 28 | |
| 29 | 29 | # DENSE driver sources (i.e., C files)
|
| 30 | 30 | #
|