From 35b21c71e5d9513a7c29ad4fc3efbbb0546a6e6a Mon Sep 17 00:00:00 2001 From: Werner Lemberg Date: Tue, 8 Jun 2021 09:06:39 +0200 Subject: [PATCH] [sdf] Make `make multi` work. * src/sdf/ftsdf.c: Include `ftbitmap.h`. * src/sdf/ftsdfcommon.h: Move function bodies to `ftsdfcommon.c`. Include `ftobjs.h` to get definitions of `FT_LOCAL` and friends. * src/sdf/ftsdfcommon.c: New file. * src/sdf/rules.mk, src/sdf/sdf.c: Updated. --- ChangeLog | 13 ++++ src/sdf/ftsdf.c | 1 + src/sdf/ftsdfcommon.c | 147 ++++++++++++++++++++++++++++++++++++++++++ src/sdf/ftsdfcommon.h | 119 +++------------------------------- src/sdf/rules.mk | 7 +- src/sdf/sdf.c | 1 + 6 files changed, 175 insertions(+), 113 deletions(-) create mode 100644 src/sdf/ftsdfcommon.c diff --git a/ChangeLog b/ChangeLog index 84d0088b9..c57f56214 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2021-06-08 Werner Lemberg + + [sdf] Make `make multi` work. + + * src/sdf/ftsdf.c: Include `ftbitmap.h`. + + * src/sdf/ftsdfcommon.h: Move function bodies to `ftsdfcommon.c`. + Include `ftobjs.h` to get definitions of `FT_LOCAL` and friends. + + * src/sdf/ftsdfcommon.c: New file. + + * src/sdf/rules.mk, src/sdf/sdf.c: Updated. + 2021-06-08 Anuj Verma [sdf] Use 8 bits for final SDF output instead of 16bits. diff --git a/src/sdf/ftsdf.c b/src/sdf/ftsdf.c index a2f38be53..b377bde6b 100644 --- a/src/sdf/ftsdf.c +++ b/src/sdf/ftsdf.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "ftsdf.h" #include "ftsdferrs.h" diff --git a/src/sdf/ftsdfcommon.c b/src/sdf/ftsdfcommon.c new file mode 100644 index 000000000..031f2bab8 --- /dev/null +++ b/src/sdf/ftsdfcommon.c @@ -0,0 +1,147 @@ +/**************************************************************************** + * + * ftsdfcommon.c + * + * Auxiliary data for Signed Distance Field support (body). + * + * Copyright (C) 2020-2021 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * Written by Anuj Verma. + * + * This file is part of the FreeType project, and may only be used, + * modified, and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + */ + + +#include +#include + + + /************************************************************************** + * + * common functions + * + */ + + /* + * Original algorithm: + * + * https://github.com/chmike/fpsqrt + * + * Use this to compute the square root of a 16.16 fixed point number. + */ + FT_LOCAL_DEF( FT_16D16 ) + square_root( FT_16D16 val ) + { + FT_ULong t, q, b, r; + + + r = (FT_ULong)val; + b = 0x40000000L; + q = 0; + + while ( b > 0x40L ) + { + t = q + b; + + if ( r >= t ) + { + r -= t; + q = t + b; + } + + r <<= 1; + b >>= 1; + } + + q >>= 8; + + return (FT_16D16)q; + } + + + /************************************************************************** + * + * format and sign manipulating functions + * + */ + + /* + * Convert 16.16 fixed point values to the desired output format. + * In this case we reduce 16.16 fixed point values to normalized + * 8-bit values. + * + * The `max_value` in the parameter is the maximum value in the + * distance field map and is equal to the spread. We normalize + * the distances using this value instead of computing the maximum + * value for the entire bitmap. + * + * You can use this function to map the 16.16 signed values to any + * format required. Do note that the output buffer is 8-bit, so only + * use an 8-bit format for `FT_SDFFormat`, or increase the buffer size in + * `ftsdfrend.c`. + */ + FT_LOCAL_DEF( FT_SDFFormat ) + map_fixed_to_sdf( FT_16D16 dist, + FT_16D16 max_value ) + { + FT_SDFFormat out; + FT_16D16 udist; + + + /* normalize the distance values */ + dist = FT_DivFix( dist, max_value ); + + udist = dist < 0 ? -dist : dist; + + /* Reduce the distance values to 8 bits. */ + /* */ + /* Since +1/-1 in 16.16 takes the 16th bit, we right-shift */ + /* the number by 9 to make it fit into the 7-bit range. */ + /* */ + /* One bit is reserved for the sign. */ + udist >>= 9; + + /* Since `char` can only store a maximum positive value */ + /* of 127 we need to make sure it does not wrap around and */ + /* give a negative value. */ + if ( dist > 0 && udist > 127 ) + udist = 127; + if ( dist < 0 && udist > 128 ) + udist = 128; + + /* Output the data; negative values are from [0, 127] and positive */ + /* from [128, 255]. One important thing is that negative values */ + /* are inverted here, that means [0, 128] maps to [-128, 0] linearly. */ + /* More on that in `freetype.h` near the documentation of */ + /* `FT_RENDER_MODE_SDF`. */ + out = dist < 0 ? 128 - (FT_SDFFormat)udist + : (FT_SDFFormat)udist + 128; + + return out; + } + + + /* + * Invert the signed distance packed into the corresponding format. + * So if the values are negative they will become positive in the + * chosen format. + * + * [Note]: This function should only be used after converting the + * 16.16 signed distance values to `FT_SDFFormat`. If that + * conversion has not been done, then simply invert the sign + * and use the above function to pack the values. + */ + FT_LOCAL_DEF( FT_SDFFormat ) + invert_sign( FT_SDFFormat dist ) + { + return 255 - dist; + } + + +/* END */ diff --git a/src/sdf/ftsdfcommon.h b/src/sdf/ftsdfcommon.h index 7ce49bb98..44f6bba53 100644 --- a/src/sdf/ftsdfcommon.h +++ b/src/sdf/ftsdfcommon.h @@ -2,7 +2,7 @@ * * ftsdfcommon.h * - * Auxiliary data for Signed Distance Field support (specification only). + * Auxiliary data for Signed Distance Field support (specification). * * Copyright (C) 2020-2021 by * David Turner, Robert Wilhelm, and Werner Lemberg. @@ -30,7 +30,7 @@ #include #include FT_CONFIG_CONFIG_H -#include +#include FT_BEGIN_HEADER @@ -120,116 +120,15 @@ FT_BEGIN_HEADER typedef FT_BBox FT_CBox; /* control box of a curve */ - /************************************************************************** - * - * common functions - * - */ + FT_LOCAL( FT_16D16 ) + square_root( FT_16D16 val ); - /* - * Original algorithm: - * - * https://github.com/chmike/fpsqrt - * - * Use this to compute the square root of a 16.16 fixed point number. - */ - static FT_16D16 - square_root( FT_16D16 val ) - { - FT_ULong t, q, b, r; + FT_LOCAL( FT_SDFFormat ) + map_fixed_to_sdf( FT_16D16 dist, + FT_16D16 max_value ); - - r = (FT_ULong)val; - b = 0x40000000L; - q = 0; - - while ( b > 0x40L ) - { - t = q + b; - - if ( r >= t ) - { - r -= t; - q = t + b; - } - - r <<= 1; - b >>= 1; - } - - q >>= 8; - - return (FT_16D16)q; - } - - /************************************************************************** - * - * format and sign manipulating functions - * - */ - - /* - * Convert 16.16 fixed point value to the desired output format. - * In this case we reduce 16.16 fixed point value to normalized - * 8-bit values. - * The `max_value` in the parameter is the maximum value in the - * distance field map and is equal to the spread. We normalize - * the distances using this value instead of computing the maximum - * value for the entire bitmap. - * You can use this function to map the 16.16 signed values to any - * format required. Do note that the output buffer is 8-bit, so only - * use 8-bit format for `FT_SDFFormat`, or increase buffer size in - * `ftsdfrend.c`. - */ - static FT_SDFFormat - map_fixed_to_sdf( FT_16D16 dist, FT_16D16 max_value ) - { - FT_SDFFormat out; - FT_16D16 udist; - - - /* normalize the distance values */ - dist = FT_DivFix( dist, max_value ); - - udist = dist < 0 ? -dist : dist; - - /* Reduce the distance values to 8 bits, +1/-1 in */ - /* 16.16 takes the 16th bit. So we right shift the */ - /* number by 9 to make it fit in the 7 bit range. */ - /* 1 bit is reserved for the sign. */ - udist >>= 9; - - /* Since char can only store max positive value */ - /* of 127 we need to make sure it does not wrap */ - /* around and give a negative value. */ - if ( dist > 0 && udist > 127 ) - udist = 127; - if ( dist < 0 && udist > 128 ) - udist = 128; - - /* Output the data; negative values are from [0, 127] and positive */ - /* from [128, 255]. One important thing is that negative values */ - /* are inverted here, that means [0, 128] maps to [-128, 0] linearly. */ - /* More on that in `freetype.h` near `FT_RENDER_MODE_SDF` */ - out = dist < 0 ? 128 - (FT_SDFFormat)udist : - (FT_SDFFormat)udist + 128; - return out; - } - - /* - * Invert the signed distance packed into the corresponding format. - * So if the values are negative they will become positive in the - * chosen format. - * - * [Note]: This function should only be used after converting the - * 16.16 signed distance values to `FT_SDFFormat`, if that - * conversion has not been done, then simply invert the sign - * and use the above function to pack the values. - */ - static FT_SDFFormat - invert_sign( FT_SDFFormat dist ) { - return 255 - dist; - } + FT_LOCAL( FT_SDFFormat ) + invert_sign( FT_SDFFormat dist ); FT_END_HEADER diff --git a/src/sdf/rules.mk b/src/sdf/rules.mk index 72f45ff3e..7e7e4fbe8 100644 --- a/src/sdf/rules.mk +++ b/src/sdf/rules.mk @@ -28,9 +28,10 @@ SDF_COMPILE := $(CC) $(ANSIFLAGS) \ # sdf driver sources (i.e., C files) # -SDF_DRV_SRC := $(SDF_DIR)/ftsdfrend.c \ - $(SDF_DIR)/ftsdf.c \ - $(SDF_DIR)/ftbsdf.c +SDF_DRV_SRC := $(SDF_DIR)/ftsdfrend.c \ + $(SDF_DIR)/ftsdf.c \ + $(SDF_DIR)/ftbsdf.c \ + $(SDF_DIR)/ftsdfcommon.c # sdf driver headers diff --git a/src/sdf/sdf.c b/src/sdf/sdf.c index e3860ef9b..1bc3fc385 100644 --- a/src/sdf/sdf.c +++ b/src/sdf/sdf.c @@ -21,6 +21,7 @@ #define FT_MAKE_OPTION_SINGLE_OBJECT #include "ftsdfrend.c" +#include "ftsdfcommon.c" #include "ftbsdf.c" #include "ftsdf.c"