2018-06-03 09:01:17 +02:00
|
|
|
/****************************************************************************
|
|
|
|
*
|
|
|
|
* ftcalc.c
|
|
|
|
*
|
|
|
|
* Arithmetic computations (body).
|
|
|
|
*
|
|
|
|
* Copyright 1996-2018 by
|
|
|
|
* David Turner, Robert Wilhelm, and Werner Lemberg.
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
|
|
*
|
|
|
|
* Support for 1-complement arithmetic has been totally dropped in this
|
|
|
|
* release. You can still write your own code if you need it.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
|
|
*
|
|
|
|
* Implementing basic computation routines.
|
|
|
|
*
|
|
|
|
* FT_MulDiv(), FT_MulFix(), FT_DivFix(), FT_RoundFix(), FT_CeilFix(),
|
|
|
|
* and FT_FloorFix() are declared in freetype.h.
|
|
|
|
*
|
|
|
|
*/
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-12-08 17:17:16 +01:00
|
|
|
|
|
|
|
#include <ft2build.h>
|
2008-06-28 00:26:11 +02:00
|
|
|
#include FT_GLYPH_H
|
2013-01-24 09:12:56 +01:00
|
|
|
#include FT_TRIGONOMETRY_H
|
2000-12-08 17:17:16 +01:00
|
|
|
#include FT_INTERNAL_CALC_H
|
|
|
|
#include FT_INTERNAL_DEBUG_H
|
|
|
|
#include FT_INTERNAL_OBJECTS_H
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2014-07-16 05:30:45 +02:00
|
|
|
|
|
|
|
#ifdef FT_MULFIX_ASSEMBLER
|
2014-03-22 06:20:54 +01:00
|
|
|
#undef FT_MulFix
|
|
|
|
#endif
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2013-05-05 10:44:21 +02:00
|
|
|
/* we need to emulate a 64-bit data type if a real one isn't available */
|
2001-06-14 14:34:00 +02:00
|
|
|
|
2013-05-05 10:44:21 +02:00
|
|
|
#ifndef FT_LONG64
|
2001-06-14 14:34:00 +02:00
|
|
|
|
|
|
|
typedef struct FT_Int64_
|
|
|
|
{
|
|
|
|
FT_UInt32 lo;
|
|
|
|
FT_UInt32 hi;
|
|
|
|
|
|
|
|
} FT_Int64;
|
|
|
|
|
2013-05-05 10:44:21 +02:00
|
|
|
#endif /* !FT_LONG64 */
|
2001-06-14 14:34:00 +02:00
|
|
|
|
|
|
|
|
2018-06-03 09:01:17 +02:00
|
|
|
/**************************************************************************
|
|
|
|
*
|
|
|
|
* The macro FT_COMPONENT is used in trace mode. It is an implicit
|
|
|
|
* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
|
|
|
|
* messages during execution.
|
|
|
|
*/
|
2000-06-03 08:03:11 +02:00
|
|
|
#undef FT_COMPONENT
|
|
|
|
#define FT_COMPONENT trace_calc
|
|
|
|
|
2001-03-11 12:28:39 +01:00
|
|
|
|
2017-05-28 07:20:09 +02:00
|
|
|
/* transfer sign, leaving a positive number; */
|
|
|
|
/* we need an unsigned value to safely negate INT_MIN (or LONG_MIN) */
|
|
|
|
#define FT_MOVE_SIGN( x, x_unsigned, s ) \
|
|
|
|
FT_BEGIN_STMNT \
|
|
|
|
if ( x < 0 ) \
|
|
|
|
{ \
|
* Version 2.8.1 released.
=========================
Tag sources with `VER-2-8-1'.
* docs/VERSION.TXT: Add entry for version 2.8.1.
* docs/CHANGES: Updated.
* README, Jamfile (RefDoc), builds/windows/vc2005/freetype.vcproj,
builds/windows/vc2005/index.html,
builds/windows/vc2008/freetype.vcproj,
builds/windows/vc2008/index.html,
builds/windows/vc2010/freetype.vcxproj,
builds/windows/vc2010/index.html,
builds/windows/visualc/freetype.dsp,
builds/windows/visualc/freetype.vcproj,
builds/windows/visualc/index.html,
builds/windows/visualce/freetype.dsp,
builds/windows/visualce/freetype.vcproj,
builds/windows/visualce/index.html,
builds/wince/vc2005-ce/freetype.vcproj,
builds/wince/vc2005-ce/index.html,
builds/wince/vc2008-ce/freetype.vcproj,
builds/wince/vc2008-ce/index.html: s/2.8/2.8.1/, s/28/281/.
* include/freetype/freetype.h (FREETYPE_PATCH): Set to 1.
* builds/unix/configure.raw (version_info): Set to 21:0:15.
* CMakeLists.txt (VERSION_PATCH): Set to 1.
2017-09-16 19:08:17 +02:00
|
|
|
x_unsigned = 0U - (x_unsigned); \
|
2017-05-28 07:20:09 +02:00
|
|
|
s = -s; \
|
|
|
|
} \
|
2014-10-01 05:09:39 +02:00
|
|
|
FT_END_STMNT
|
|
|
|
|
2001-03-10 20:02:51 +01:00
|
|
|
/* The following three functions are available regardless of whether */
|
2002-04-02 16:50:31 +02:00
|
|
|
/* FT_LONG64 is defined. */
|
2001-03-10 20:02:51 +01:00
|
|
|
|
|
|
|
/* documentation is in freetype.h */
|
|
|
|
|
2001-06-27 18:18:10 +02:00
|
|
|
FT_EXPORT_DEF( FT_Fixed )
|
|
|
|
FT_RoundFix( FT_Fixed a )
|
2001-03-10 20:02:51 +01:00
|
|
|
{
|
2017-06-09 11:21:58 +02:00
|
|
|
return ( ADD_LONG( a, 0x8000L - ( a < 0 ) ) ) & ~0xFFFFL;
|
2001-03-10 20:02:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* documentation is in freetype.h */
|
|
|
|
|
2001-06-27 18:18:10 +02:00
|
|
|
FT_EXPORT_DEF( FT_Fixed )
|
|
|
|
FT_CeilFix( FT_Fixed a )
|
2001-03-10 20:02:51 +01:00
|
|
|
{
|
2017-06-09 11:21:58 +02:00
|
|
|
return ( ADD_LONG( a, 0xFFFFL ) ) & ~0xFFFFL;
|
2001-03-10 20:02:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* documentation is in freetype.h */
|
|
|
|
|
2001-06-27 18:18:10 +02:00
|
|
|
FT_EXPORT_DEF( FT_Fixed )
|
|
|
|
FT_FloorFix( FT_Fixed a )
|
2001-03-10 20:02:51 +01:00
|
|
|
{
|
2015-09-09 07:59:10 +02:00
|
|
|
return a & ~0xFFFFL;
|
2001-03-10 20:02:51 +01:00
|
|
|
}
|
|
|
|
|
2014-08-15 05:01:01 +02:00
|
|
|
#ifndef FT_MSB
|
2000-06-03 08:03:11 +02:00
|
|
|
|
2013-01-24 01:43:28 +01:00
|
|
|
FT_BASE_DEF ( FT_Int )
|
|
|
|
FT_MSB( FT_UInt32 z )
|
|
|
|
{
|
2014-12-07 09:40:47 +01:00
|
|
|
FT_Int shift = 0;
|
|
|
|
|
2013-01-24 01:43:28 +01:00
|
|
|
|
|
|
|
/* determine msb bit index in `shift' */
|
2014-12-07 09:40:47 +01:00
|
|
|
if ( z & 0xFFFF0000UL )
|
2013-01-24 01:43:28 +01:00
|
|
|
{
|
|
|
|
z >>= 16;
|
|
|
|
shift += 16;
|
|
|
|
}
|
2014-12-07 09:40:47 +01:00
|
|
|
if ( z & 0x0000FF00UL )
|
2013-01-24 01:43:28 +01:00
|
|
|
{
|
|
|
|
z >>= 8;
|
|
|
|
shift += 8;
|
|
|
|
}
|
2014-12-07 09:40:47 +01:00
|
|
|
if ( z & 0x000000F0UL )
|
2013-01-24 01:43:28 +01:00
|
|
|
{
|
|
|
|
z >>= 4;
|
|
|
|
shift += 4;
|
|
|
|
}
|
2014-12-07 09:40:47 +01:00
|
|
|
if ( z & 0x0000000CUL )
|
2013-01-24 01:43:28 +01:00
|
|
|
{
|
|
|
|
z >>= 2;
|
|
|
|
shift += 2;
|
|
|
|
}
|
2014-12-07 09:40:47 +01:00
|
|
|
if ( z & 0x00000002UL )
|
2013-01-24 01:43:28 +01:00
|
|
|
{
|
Fix clang static analyzer and compiler warnings.
* src/autofit/afhints.c (af_glyph_hints_align_weak_points),
src/autofit/afloader (af_loader_load_g) <FT_GLYPH_FORMAT_COMPOSITE>,
src/base/ftcalc.c (FT_MSB), src/base/ftoutln.c
(FT_Outline_Decompose), src/bdf/bdfdrivr.c (bdf_interpret_style),
src/cff/cffparse.c (cff_parse_integer), src/cid/cidparse.c
(cid_parser_new), src/pfr/pfrload.c (pfr_phy_font_load),
src/raster/ftraster.c (Decompose_Curve), src/sfnt/sfdriver.c
(sfnt_get_ps_name), src/sfnt/ttcmap.c (tt_cmap12_next,
tt_cmap13_next), src/smooth/ftgrays.c (gray_hline): Remove dead
code.
* src/autofit/afmodule.c (af_property_get_face_globals,
af_property_set, af_property_get), src/base/ftbitmap.c
(ft_gray_for_premultiplied_srgb_bgra): Make functions static.
* src/base/ftobjs.c (ft_remove_renderer): Protect against
library == NULL.
(ft_property_do): Make function static.
* src/base/ftrfork.c: Include `ftbase.h'.
* src/sfnt/ttsbit.c (tt_face_load_sbix_image)
[!FT_CONFIG_OPTION_USE_PNG], src/type1/t1gload.c
(T1_Compute_Max_Advance): Avoid compiler warning.
* src/truetype/ttinterp.c (TT_New_Context): Reduce scope of
variable.
2014-02-08 13:55:38 +01:00
|
|
|
/* z >>= 1; */
|
2013-01-24 01:43:28 +01:00
|
|
|
shift += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return shift;
|
|
|
|
}
|
|
|
|
|
2014-08-15 05:01:01 +02:00
|
|
|
#endif /* !FT_MSB */
|
|
|
|
|
2013-01-24 01:43:28 +01:00
|
|
|
|
2013-01-24 09:12:56 +01:00
|
|
|
/* documentation is in ftcalc.h */
|
|
|
|
|
|
|
|
FT_BASE_DEF( FT_Fixed )
|
|
|
|
FT_Hypot( FT_Fixed x,
|
|
|
|
FT_Fixed y )
|
|
|
|
{
|
|
|
|
FT_Vector v;
|
|
|
|
|
|
|
|
|
|
|
|
v.x = x;
|
|
|
|
v.y = y;
|
|
|
|
|
|
|
|
return FT_Vector_Length( &v );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-07-04 20:12:13 +02:00
|
|
|
#ifdef FT_LONG64
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2002-04-02 16:50:31 +02:00
|
|
|
|
2000-11-07 18:21:11 +01:00
|
|
|
/* documentation is in freetype.h */
|
|
|
|
|
2001-06-27 18:18:10 +02:00
|
|
|
FT_EXPORT_DEF( FT_Long )
|
2015-02-15 12:30:42 +01:00
|
|
|
FT_MulDiv( FT_Long a_,
|
|
|
|
FT_Long b_,
|
|
|
|
FT_Long c_ )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2015-02-15 12:30:42 +01:00
|
|
|
FT_Int s = 1;
|
|
|
|
FT_UInt64 a, b, c, d;
|
|
|
|
FT_Long d_;
|
2000-05-30 00:40:57 +02:00
|
|
|
|
2001-05-08 15:52:13 +02:00
|
|
|
|
2015-02-15 12:30:42 +01:00
|
|
|
a = (FT_UInt64)a_;
|
|
|
|
b = (FT_UInt64)b_;
|
|
|
|
c = (FT_UInt64)c_;
|
2001-05-08 14:58:07 +02:00
|
|
|
|
2017-05-28 07:20:09 +02:00
|
|
|
FT_MOVE_SIGN( a_, a, s );
|
|
|
|
FT_MOVE_SIGN( b_, b, s );
|
|
|
|
FT_MOVE_SIGN( c_, c, s );
|
|
|
|
|
2015-02-15 12:30:42 +01:00
|
|
|
d = c > 0 ? ( a * b + ( c >> 1 ) ) / c
|
|
|
|
: 0x7FFFFFFFUL;
|
|
|
|
|
|
|
|
d_ = (FT_Long)d;
|
|
|
|
|
2017-06-27 06:16:04 +02:00
|
|
|
return s < 0 ? NEG_LONG( d_ ) : d_;
|
1999-12-17 00:11:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-11-25 19:15:56 +01:00
|
|
|
/* documentation is in ftcalc.h */
|
|
|
|
|
|
|
|
FT_BASE_DEF( FT_Long )
|
2015-02-15 12:30:42 +01:00
|
|
|
FT_MulDiv_No_Round( FT_Long a_,
|
|
|
|
FT_Long b_,
|
|
|
|
FT_Long c_ )
|
2003-11-25 19:15:56 +01:00
|
|
|
{
|
2015-02-15 12:30:42 +01:00
|
|
|
FT_Int s = 1;
|
|
|
|
FT_UInt64 a, b, c, d;
|
|
|
|
FT_Long d_;
|
|
|
|
|
2003-11-25 19:15:56 +01:00
|
|
|
|
2015-02-15 12:30:42 +01:00
|
|
|
a = (FT_UInt64)a_;
|
|
|
|
b = (FT_UInt64)b_;
|
|
|
|
c = (FT_UInt64)c_;
|
2003-11-25 19:15:56 +01:00
|
|
|
|
2017-05-28 07:20:09 +02:00
|
|
|
FT_MOVE_SIGN( a_, a, s );
|
|
|
|
FT_MOVE_SIGN( b_, b, s );
|
|
|
|
FT_MOVE_SIGN( c_, c, s );
|
|
|
|
|
2015-02-15 12:30:42 +01:00
|
|
|
d = c > 0 ? a * b / c
|
|
|
|
: 0x7FFFFFFFUL;
|
2003-11-25 19:15:56 +01:00
|
|
|
|
2015-02-15 12:30:42 +01:00
|
|
|
d_ = (FT_Long)d;
|
|
|
|
|
2017-06-27 06:16:04 +02:00
|
|
|
return s < 0 ? NEG_LONG( d_ ) : d_;
|
2003-11-25 19:15:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-11-07 18:21:11 +01:00
|
|
|
/* documentation is in freetype.h */
|
|
|
|
|
2001-06-27 18:18:10 +02:00
|
|
|
FT_EXPORT_DEF( FT_Long )
|
2015-02-15 12:30:42 +01:00
|
|
|
FT_MulFix( FT_Long a_,
|
|
|
|
FT_Long b_ )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2008-09-02 04:21:58 +02:00
|
|
|
#ifdef FT_MULFIX_ASSEMBLER
|
2008-09-12 18:27:48 +02:00
|
|
|
|
2016-01-19 19:15:54 +01:00
|
|
|
return FT_MULFIX_ASSEMBLER( (FT_Int32)a_, (FT_Int32)b_ );
|
2008-09-12 18:27:48 +02:00
|
|
|
|
2008-09-02 04:21:58 +02:00
|
|
|
#else
|
2008-09-12 18:27:48 +02:00
|
|
|
|
2015-09-14 05:19:34 +02:00
|
|
|
FT_Int64 ab = (FT_Int64)a_ * (FT_Int64)b_;
|
2008-09-12 18:27:48 +02:00
|
|
|
|
2015-09-14 05:19:34 +02:00
|
|
|
/* this requires arithmetic right shift of signed numbers */
|
|
|
|
return (FT_Long)( ( ab + 0x8000L - ( ab < 0 ) ) >> 16 );
|
2008-09-12 18:27:48 +02:00
|
|
|
|
|
|
|
#endif /* FT_MULFIX_ASSEMBLER */
|
1999-12-17 00:11:37 +01:00
|
|
|
}
|
|
|
|
|
2000-01-02 10:41:30 +01:00
|
|
|
|
2000-11-07 18:21:11 +01:00
|
|
|
/* documentation is in freetype.h */
|
|
|
|
|
2001-06-27 18:18:10 +02:00
|
|
|
FT_EXPORT_DEF( FT_Long )
|
2015-02-15 12:30:42 +01:00
|
|
|
FT_DivFix( FT_Long a_,
|
|
|
|
FT_Long b_ )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2015-02-15 12:30:42 +01:00
|
|
|
FT_Int s = 1;
|
|
|
|
FT_UInt64 a, b, q;
|
|
|
|
FT_Long q_;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2013-05-04 16:40:12 +02:00
|
|
|
|
2015-02-15 12:30:42 +01:00
|
|
|
a = (FT_UInt64)a_;
|
|
|
|
b = (FT_UInt64)b_;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2017-05-28 07:20:09 +02:00
|
|
|
FT_MOVE_SIGN( a_, a, s );
|
2017-06-10 11:03:41 +02:00
|
|
|
FT_MOVE_SIGN( b_, b, s );
|
2017-05-28 07:20:09 +02:00
|
|
|
|
2015-02-15 12:30:42 +01:00
|
|
|
q = b > 0 ? ( ( a << 16 ) + ( b >> 1 ) ) / b
|
|
|
|
: 0x7FFFFFFFUL;
|
|
|
|
|
|
|
|
q_ = (FT_Long)q;
|
|
|
|
|
2017-06-27 06:16:04 +02:00
|
|
|
return s < 0 ? NEG_LONG( q_ ) : q_;
|
1999-12-17 00:11:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-11-03 10:40:12 +01:00
|
|
|
#else /* !FT_LONG64 */
|
2000-09-02 02:20:42 +02:00
|
|
|
|
2001-04-26 02:21:48 +02:00
|
|
|
|
|
|
|
static void
|
|
|
|
ft_multo64( FT_UInt32 x,
|
|
|
|
FT_UInt32 y,
|
|
|
|
FT_Int64 *z )
|
2000-09-02 02:20:42 +02:00
|
|
|
{
|
2001-04-26 15:34:36 +02:00
|
|
|
FT_UInt32 lo1, hi1, lo2, hi2, lo, hi, i1, i2;
|
2001-04-26 02:21:48 +02:00
|
|
|
|
2000-10-31 21:42:18 +01:00
|
|
|
|
2001-04-26 15:34:36 +02:00
|
|
|
lo1 = x & 0x0000FFFFU; hi1 = x >> 16;
|
|
|
|
lo2 = y & 0x0000FFFFU; hi2 = y >> 16;
|
2000-11-07 18:21:11 +01:00
|
|
|
|
2001-04-26 15:34:36 +02:00
|
|
|
lo = lo1 * lo2;
|
|
|
|
i1 = lo1 * hi2;
|
|
|
|
i2 = lo2 * hi1;
|
|
|
|
hi = hi1 * hi2;
|
2001-04-26 02:21:48 +02:00
|
|
|
|
2001-04-26 15:34:36 +02:00
|
|
|
/* Check carry overflow of i1 + i2 */
|
|
|
|
i1 += i2;
|
|
|
|
hi += (FT_UInt32)( i1 < i2 ) << 16;
|
2001-04-26 02:21:48 +02:00
|
|
|
|
2001-04-26 15:34:36 +02:00
|
|
|
hi += i1 >> 16;
|
|
|
|
i1 = i1 << 16;
|
2001-04-26 02:21:48 +02:00
|
|
|
|
2001-04-26 15:34:36 +02:00
|
|
|
/* Check carry overflow of i1 + lo */
|
|
|
|
lo += i1;
|
|
|
|
hi += ( lo < i1 );
|
2001-04-26 02:21:48 +02:00
|
|
|
|
2001-04-26 15:34:36 +02:00
|
|
|
z->lo = lo;
|
|
|
|
z->hi = hi;
|
2000-09-02 02:20:42 +02:00
|
|
|
}
|
|
|
|
|
2001-04-26 02:21:48 +02:00
|
|
|
|
|
|
|
static FT_UInt32
|
|
|
|
ft_div64by32( FT_UInt32 hi,
|
|
|
|
FT_UInt32 lo,
|
2001-04-26 15:34:36 +02:00
|
|
|
FT_UInt32 y )
|
2001-04-26 02:21:48 +02:00
|
|
|
{
|
2001-06-24 19:23:45 +02:00
|
|
|
FT_UInt32 r, q;
|
|
|
|
FT_Int i;
|
2001-04-26 15:34:36 +02:00
|
|
|
|
|
|
|
|
2014-10-03 05:13:33 +02:00
|
|
|
if ( hi >= y )
|
2001-04-26 15:34:36 +02:00
|
|
|
return (FT_UInt32)0x7FFFFFFFL;
|
|
|
|
|
2014-11-20 04:10:29 +01:00
|
|
|
/* We shift as many bits as we can into the high register, perform */
|
2014-10-03 05:13:33 +02:00
|
|
|
/* 32-bit division with modulo there, then work through the remaining */
|
|
|
|
/* bits with long division. This optimization is especially noticeable */
|
|
|
|
/* for smaller dividends that barely use the high register. */
|
|
|
|
|
|
|
|
i = 31 - FT_MSB( hi );
|
|
|
|
r = ( hi << i ) | ( lo >> ( 32 - i ) ); lo <<= i; /* left 64-bit shift */
|
|
|
|
q = r / y;
|
|
|
|
r -= q * y; /* remainder */
|
|
|
|
|
|
|
|
i = 32 - i; /* bits remaining in low register */
|
2001-04-26 02:21:48 +02:00
|
|
|
do
|
|
|
|
{
|
|
|
|
q <<= 1;
|
2014-10-03 05:13:33 +02:00
|
|
|
r = ( r << 1 ) | ( lo >> 31 ); lo <<= 1;
|
2001-04-26 02:21:48 +02:00
|
|
|
|
2012-03-03 12:27:18 +01:00
|
|
|
if ( r >= y )
|
2001-04-26 02:21:48 +02:00
|
|
|
{
|
|
|
|
r -= y;
|
|
|
|
q |= 1;
|
|
|
|
}
|
2001-04-26 15:34:36 +02:00
|
|
|
} while ( --i );
|
|
|
|
|
|
|
|
return q;
|
2001-04-26 02:21:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-11-12 18:07:11 +01:00
|
|
|
static void
|
2001-06-27 18:18:10 +02:00
|
|
|
FT_Add64( FT_Int64* x,
|
|
|
|
FT_Int64* y,
|
|
|
|
FT_Int64 *z )
|
2001-04-26 02:21:48 +02:00
|
|
|
{
|
2014-08-31 08:47:11 +02:00
|
|
|
FT_UInt32 lo, hi;
|
2001-04-26 02:21:48 +02:00
|
|
|
|
2001-04-26 15:34:36 +02:00
|
|
|
|
2006-11-03 10:40:12 +01:00
|
|
|
lo = x->lo + y->lo;
|
|
|
|
hi = x->hi + y->hi + ( lo < x->lo );
|
2001-04-26 02:21:48 +02:00
|
|
|
|
|
|
|
z->lo = lo;
|
|
|
|
z->hi = hi;
|
|
|
|
}
|
2000-05-02 12:52:28 +02:00
|
|
|
|
|
|
|
|
2014-08-20 06:08:38 +02:00
|
|
|
/* The FT_MulDiv function has been optimized thanks to ideas from */
|
|
|
|
/* Graham Asher and Alexei Podtelezhnikov. The trick is to optimize */
|
|
|
|
/* a rather common case when everything fits within 32-bits. */
|
2006-11-19 10:19:17 +01:00
|
|
|
/* */
|
2014-08-20 16:19:32 +02:00
|
|
|
/* We compute 'a*b+c/2', then divide it by 'c' (all positive values). */
|
2006-11-19 10:19:17 +01:00
|
|
|
/* */
|
2014-07-06 04:29:26 +02:00
|
|
|
/* The product of two positive numbers never exceeds the square of */
|
2014-08-20 16:19:32 +02:00
|
|
|
/* its mean values. Therefore, we always avoid the overflow by */
|
|
|
|
/* imposing */
|
2006-11-19 10:19:17 +01:00
|
|
|
/* */
|
2014-08-20 16:19:32 +02:00
|
|
|
/* (a + b) / 2 <= sqrt(X - c/2) , */
|
2006-11-19 10:19:17 +01:00
|
|
|
/* */
|
2014-08-20 16:19:32 +02:00
|
|
|
/* where X = 2^32 - 1, the maximum unsigned 32-bit value, and using */
|
|
|
|
/* unsigned arithmetic. Now we replace `sqrt' with a linear function */
|
|
|
|
/* that is smaller or equal for all values of c in the interval */
|
|
|
|
/* [0;X/2]; it should be equal to sqrt(X) and sqrt(3X/4) at the */
|
|
|
|
/* endpoints. Substituting the linear solution and explicit numbers */
|
|
|
|
/* we get */
|
2006-11-19 10:19:17 +01:00
|
|
|
/* */
|
2014-08-20 16:19:32 +02:00
|
|
|
/* a + b <= 131071.99 - c / 122291.84 . */
|
2014-08-20 06:08:38 +02:00
|
|
|
/* */
|
2014-08-20 16:19:32 +02:00
|
|
|
/* In practice, we should use a faster and even stronger inequality */
|
2006-11-19 10:19:17 +01:00
|
|
|
/* */
|
2014-08-20 16:19:32 +02:00
|
|
|
/* a + b <= 131071 - (c >> 16) */
|
2014-07-05 05:01:32 +02:00
|
|
|
/* */
|
2014-08-20 06:08:38 +02:00
|
|
|
/* or, alternatively, */
|
2006-11-19 10:19:17 +01:00
|
|
|
/* */
|
2014-09-16 04:06:19 +02:00
|
|
|
/* a + b <= 129894 - (c >> 17) . */
|
2014-08-20 06:08:38 +02:00
|
|
|
/* */
|
2014-08-20 06:57:22 +02:00
|
|
|
/* FT_MulFix, on the other hand, is optimized for a small value of */
|
|
|
|
/* the first argument, when the second argument can be much larger. */
|
|
|
|
/* This can be achieved by scaling the second argument and the limit */
|
2014-08-20 16:19:32 +02:00
|
|
|
/* in the above inequalities. For example, */
|
2014-08-20 06:57:22 +02:00
|
|
|
/* */
|
2014-08-20 16:19:32 +02:00
|
|
|
/* a + (b >> 8) <= (131071 >> 4) */
|
2014-08-20 06:57:22 +02:00
|
|
|
/* */
|
2014-09-04 03:57:42 +02:00
|
|
|
/* covers the practical range of use. The actual test below is a bit */
|
|
|
|
/* tighter to avoid the border case overflows. */
|
2014-08-20 06:57:22 +02:00
|
|
|
/* */
|
2014-10-02 05:27:15 +02:00
|
|
|
/* In the case of FT_DivFix, the exact overflow check */
|
2014-09-04 04:55:26 +02:00
|
|
|
/* */
|
|
|
|
/* a << 16 <= X - c/2 */
|
|
|
|
/* */
|
|
|
|
/* is scaled down by 2^16 and we use */
|
|
|
|
/* */
|
|
|
|
/* a <= 65535 - (c >> 17) . */
|
2014-08-20 06:08:38 +02:00
|
|
|
|
|
|
|
/* documentation is in freetype.h */
|
2006-11-19 10:19:17 +01:00
|
|
|
|
2001-06-27 18:18:10 +02:00
|
|
|
FT_EXPORT_DEF( FT_Long )
|
2015-02-15 12:30:42 +01:00
|
|
|
FT_MulDiv( FT_Long a_,
|
|
|
|
FT_Long b_,
|
|
|
|
FT_Long c_ )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2015-02-15 12:30:42 +01:00
|
|
|
FT_Int s = 1;
|
|
|
|
FT_UInt32 a, b, c;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
|
|
|
|
2009-07-31 17:30:24 +02:00
|
|
|
/* XXX: this function does not allow 64-bit arguments */
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2015-02-15 12:30:42 +01:00
|
|
|
a = (FT_UInt32)a_;
|
|
|
|
b = (FT_UInt32)b_;
|
|
|
|
c = (FT_UInt32)c_;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2017-05-28 07:20:09 +02:00
|
|
|
FT_MOVE_SIGN( a_, a, s );
|
|
|
|
FT_MOVE_SIGN( b_, b, s );
|
|
|
|
FT_MOVE_SIGN( c_, c, s );
|
|
|
|
|
2014-08-15 05:21:46 +02:00
|
|
|
if ( c == 0 )
|
2015-02-15 12:30:42 +01:00
|
|
|
a = 0x7FFFFFFFUL;
|
2014-08-15 05:21:46 +02:00
|
|
|
|
2015-02-15 12:30:42 +01:00
|
|
|
else if ( a + b <= 129894UL - ( c >> 17 ) )
|
|
|
|
a = ( a * b + ( c >> 1 ) ) / c;
|
2003-11-25 19:15:56 +01:00
|
|
|
|
2014-08-15 05:21:46 +02:00
|
|
|
else
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
FT_Int64 temp, temp2;
|
|
|
|
|
2000-05-30 00:40:57 +02:00
|
|
|
|
2014-10-02 05:27:15 +02:00
|
|
|
ft_multo64( a, b, &temp );
|
2001-04-26 15:34:36 +02:00
|
|
|
|
|
|
|
temp2.hi = 0;
|
2014-10-02 05:27:15 +02:00
|
|
|
temp2.lo = c >> 1;
|
|
|
|
|
2001-04-26 15:34:36 +02:00
|
|
|
FT_Add64( &temp, &temp2, &temp );
|
2014-09-26 04:54:38 +02:00
|
|
|
|
|
|
|
/* last attempt to ditch long division */
|
2016-12-25 22:55:25 +01:00
|
|
|
a = ( temp.hi == 0 ) ? temp.lo / c
|
|
|
|
: ft_div64by32( temp.hi, temp.lo, c );
|
1999-12-17 00:11:37 +01:00
|
|
|
}
|
|
|
|
|
2015-02-15 12:30:42 +01:00
|
|
|
a_ = (FT_Long)a;
|
|
|
|
|
2017-06-27 06:16:04 +02:00
|
|
|
return s < 0 ? NEG_LONG( a_ ) : a_;
|
1999-12-17 00:11:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-11-25 19:15:56 +01:00
|
|
|
FT_BASE_DEF( FT_Long )
|
2015-02-15 12:30:42 +01:00
|
|
|
FT_MulDiv_No_Round( FT_Long a_,
|
|
|
|
FT_Long b_,
|
|
|
|
FT_Long c_ )
|
2003-11-25 19:15:56 +01:00
|
|
|
{
|
2015-02-15 12:30:42 +01:00
|
|
|
FT_Int s = 1;
|
|
|
|
FT_UInt32 a, b, c;
|
2003-11-25 19:15:56 +01:00
|
|
|
|
|
|
|
|
2015-02-15 12:30:42 +01:00
|
|
|
/* XXX: this function does not allow 64-bit arguments */
|
|
|
|
|
|
|
|
a = (FT_UInt32)a_;
|
|
|
|
b = (FT_UInt32)b_;
|
|
|
|
c = (FT_UInt32)c_;
|
2003-11-25 19:15:56 +01:00
|
|
|
|
2017-05-28 07:20:09 +02:00
|
|
|
FT_MOVE_SIGN( a_, a, s );
|
|
|
|
FT_MOVE_SIGN( b_, b, s );
|
|
|
|
FT_MOVE_SIGN( c_, c, s );
|
|
|
|
|
2014-08-15 05:21:46 +02:00
|
|
|
if ( c == 0 )
|
2015-02-15 12:30:42 +01:00
|
|
|
a = 0x7FFFFFFFUL;
|
2014-08-15 05:21:46 +02:00
|
|
|
|
2015-02-15 12:30:42 +01:00
|
|
|
else if ( a + b <= 131071UL )
|
|
|
|
a = a * b / c;
|
2003-11-25 19:15:56 +01:00
|
|
|
|
2014-08-15 05:21:46 +02:00
|
|
|
else
|
2003-11-25 19:15:56 +01:00
|
|
|
{
|
|
|
|
FT_Int64 temp;
|
|
|
|
|
|
|
|
|
2014-10-02 05:27:15 +02:00
|
|
|
ft_multo64( a, b, &temp );
|
2014-09-26 04:54:38 +02:00
|
|
|
|
|
|
|
/* last attempt to ditch long division */
|
2016-12-25 22:55:25 +01:00
|
|
|
a = ( temp.hi == 0 ) ? temp.lo / c
|
|
|
|
: ft_div64by32( temp.hi, temp.lo, c );
|
2003-11-25 19:15:56 +01:00
|
|
|
}
|
|
|
|
|
2015-02-15 12:30:42 +01:00
|
|
|
a_ = (FT_Long)a;
|
|
|
|
|
2017-06-27 06:16:04 +02:00
|
|
|
return s < 0 ? NEG_LONG( a_ ) : a_;
|
2003-11-25 19:15:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-11-07 18:21:11 +01:00
|
|
|
/* documentation is in freetype.h */
|
|
|
|
|
2001-06-27 18:18:10 +02:00
|
|
|
FT_EXPORT_DEF( FT_Long )
|
2015-02-15 12:30:42 +01:00
|
|
|
FT_MulFix( FT_Long a_,
|
|
|
|
FT_Long b_ )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2008-09-02 04:21:58 +02:00
|
|
|
#ifdef FT_MULFIX_ASSEMBLER
|
2008-09-12 18:27:48 +02:00
|
|
|
|
2015-02-15 12:30:42 +01:00
|
|
|
return FT_MULFIX_ASSEMBLER( a_, b_ );
|
2008-09-12 18:27:48 +02:00
|
|
|
|
2008-07-16 23:03:40 +02:00
|
|
|
#elif 0
|
|
|
|
|
|
|
|
/*
|
2018-06-03 09:01:17 +02:00
|
|
|
* This code is nonportable. See comment below.
|
2008-07-16 23:03:40 +02:00
|
|
|
*
|
2018-06-03 09:01:17 +02:00
|
|
|
* However, on a platform where right-shift of a signed quantity fills
|
|
|
|
* the leftmost bits by copying the sign bit, it might be faster.
|
2008-07-16 23:03:40 +02:00
|
|
|
*/
|
2006-05-18 00:55:04 +02:00
|
|
|
|
2015-02-15 12:30:42 +01:00
|
|
|
FT_Long sa, sb;
|
|
|
|
FT_UInt32 a, b;
|
2005-10-28 18:14:14 +02:00
|
|
|
|
|
|
|
|
2008-07-16 23:03:40 +02:00
|
|
|
/*
|
2018-06-03 09:01:17 +02:00
|
|
|
* This is a clever way of converting a signed number `a' into its
|
|
|
|
* absolute value (stored back into `a') and its sign. The sign is
|
|
|
|
* stored in `sa'; 0 means `a' was positive or zero, and -1 means `a'
|
|
|
|
* was negative. (Similarly for `b' and `sb').
|
2008-07-16 23:03:40 +02:00
|
|
|
*
|
2018-06-03 09:01:17 +02:00
|
|
|
* Unfortunately, it doesn't work (at least not portably).
|
2008-07-16 23:03:40 +02:00
|
|
|
*
|
2018-06-03 09:01:17 +02:00
|
|
|
* It makes the assumption that right-shift on a negative signed value
|
|
|
|
* fills the leftmost bits by copying the sign bit. This is wrong.
|
|
|
|
* According to K&R 2nd ed, section `A7.8 Shift Operators' on page 206,
|
|
|
|
* the result of right-shift of a negative signed value is
|
|
|
|
* implementation-defined. At least one implementation fills the
|
|
|
|
* leftmost bits with 0s (i.e., it is exactly the same as an unsigned
|
|
|
|
* right shift). This means that when `a' is negative, `sa' ends up
|
|
|
|
* with the value 1 rather than -1. After that, everything else goes
|
|
|
|
* wrong.
|
2008-07-16 23:03:40 +02:00
|
|
|
*/
|
2015-02-15 12:30:42 +01:00
|
|
|
sa = ( a_ >> ( sizeof ( a_ ) * 8 - 1 ) );
|
|
|
|
a = ( a_ ^ sa ) - sa;
|
|
|
|
sb = ( b_ >> ( sizeof ( b_ ) * 8 - 1 ) );
|
|
|
|
b = ( b_ ^ sb ) - sb;
|
2005-10-28 18:14:14 +02:00
|
|
|
|
2015-02-15 12:30:42 +01:00
|
|
|
a = (FT_UInt32)a_;
|
|
|
|
b = (FT_UInt32)b_;
|
2005-10-28 18:14:14 +02:00
|
|
|
|
2015-02-15 12:30:42 +01:00
|
|
|
if ( a + ( b >> 8 ) <= 8190UL )
|
|
|
|
a = ( a * b + 0x8000U ) >> 16;
|
2005-10-28 18:14:14 +02:00
|
|
|
else
|
|
|
|
{
|
2015-02-15 12:30:42 +01:00
|
|
|
FT_UInt32 al = a & 0xFFFFUL;
|
2005-10-28 18:14:14 +02:00
|
|
|
|
|
|
|
|
2015-02-15 12:30:42 +01:00
|
|
|
a = ( a >> 16 ) * b + al * ( b >> 16 ) +
|
|
|
|
( ( al * ( b & 0xFFFFUL ) + 0x8000UL ) >> 16 );
|
2005-10-28 18:14:14 +02:00
|
|
|
}
|
|
|
|
|
2015-02-15 12:30:42 +01:00
|
|
|
sa ^= sb;
|
|
|
|
a = ( a ^ sa ) - sa;
|
2005-10-28 18:14:14 +02:00
|
|
|
|
2015-02-15 12:30:42 +01:00
|
|
|
return (FT_Long)a;
|
2005-11-12 08:34:40 +01:00
|
|
|
|
|
|
|
#else /* 0 */
|
|
|
|
|
2015-02-15 12:30:42 +01:00
|
|
|
FT_Int s = 1;
|
|
|
|
FT_UInt32 a, b;
|
2000-01-02 10:41:30 +01:00
|
|
|
|
2000-05-29 22:46:12 +02:00
|
|
|
|
2015-02-15 12:30:42 +01:00
|
|
|
/* XXX: this function does not allow 64-bit arguments */
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2015-02-15 12:30:42 +01:00
|
|
|
a = (FT_UInt32)a_;
|
|
|
|
b = (FT_UInt32)b_;
|
|
|
|
|
2017-05-28 07:20:09 +02:00
|
|
|
FT_MOVE_SIGN( a_, a, s );
|
|
|
|
FT_MOVE_SIGN( b_, b, s );
|
|
|
|
|
2015-02-15 12:30:42 +01:00
|
|
|
if ( a + ( b >> 8 ) <= 8190UL )
|
|
|
|
a = ( a * b + 0x8000UL ) >> 16;
|
1999-12-17 00:11:37 +01:00
|
|
|
else
|
|
|
|
{
|
2015-02-15 12:30:42 +01:00
|
|
|
FT_UInt32 al = a & 0xFFFFUL;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-01-02 10:41:30 +01:00
|
|
|
|
2015-02-15 12:30:42 +01:00
|
|
|
a = ( a >> 16 ) * b + al * ( b >> 16 ) +
|
|
|
|
( ( al * ( b & 0xFFFFUL ) + 0x8000UL ) >> 16 );
|
1999-12-17 00:11:37 +01:00
|
|
|
}
|
|
|
|
|
2015-02-15 12:30:42 +01:00
|
|
|
a_ = (FT_Long)a;
|
|
|
|
|
2017-06-27 06:16:04 +02:00
|
|
|
return s < 0 ? NEG_LONG( a_ ) : a_;
|
2005-11-12 08:34:40 +01:00
|
|
|
|
|
|
|
#endif /* 0 */
|
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-11-07 18:21:11 +01:00
|
|
|
/* documentation is in freetype.h */
|
|
|
|
|
2001-06-27 18:18:10 +02:00
|
|
|
FT_EXPORT_DEF( FT_Long )
|
2015-02-15 12:30:42 +01:00
|
|
|
FT_DivFix( FT_Long a_,
|
|
|
|
FT_Long b_ )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
2015-02-15 12:30:42 +01:00
|
|
|
FT_Int s = 1;
|
|
|
|
FT_UInt32 a, b, q;
|
|
|
|
FT_Long q_;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2000-01-02 10:41:30 +01:00
|
|
|
|
2009-07-31 17:30:24 +02:00
|
|
|
/* XXX: this function does not allow 64-bit arguments */
|
2014-10-01 05:09:39 +02:00
|
|
|
|
2015-02-15 12:30:42 +01:00
|
|
|
a = (FT_UInt32)a_;
|
|
|
|
b = (FT_UInt32)b_;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2017-05-28 07:20:09 +02:00
|
|
|
FT_MOVE_SIGN( a_, a, s );
|
|
|
|
FT_MOVE_SIGN( b_, b, s );
|
|
|
|
|
2014-08-19 05:16:15 +02:00
|
|
|
if ( b == 0 )
|
2000-05-30 00:40:57 +02:00
|
|
|
{
|
|
|
|
/* check for division by 0 */
|
2015-02-15 12:30:42 +01:00
|
|
|
q = 0x7FFFFFFFUL;
|
2000-05-30 00:40:57 +02:00
|
|
|
}
|
2015-02-15 12:30:42 +01:00
|
|
|
else if ( a <= 65535UL - ( b >> 17 ) )
|
1999-12-17 00:11:37 +01:00
|
|
|
{
|
|
|
|
/* compute result directly */
|
2015-02-15 12:30:42 +01:00
|
|
|
q = ( ( a << 16 ) + ( b >> 1 ) ) / b;
|
1999-12-17 00:11:37 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2000-06-29 05:14:25 +02:00
|
|
|
/* we need more bits; we have to do it by hand */
|
2000-09-02 02:20:42 +02:00
|
|
|
FT_Int64 temp, temp2;
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2012-03-03 12:27:18 +01:00
|
|
|
|
2014-11-20 04:10:29 +01:00
|
|
|
temp.hi = a >> 16;
|
2014-10-02 05:27:15 +02:00
|
|
|
temp.lo = a << 16;
|
2001-04-26 02:21:48 +02:00
|
|
|
temp2.hi = 0;
|
2014-11-20 04:10:29 +01:00
|
|
|
temp2.lo = b >> 1;
|
2014-10-02 05:27:15 +02:00
|
|
|
|
2000-09-02 02:20:42 +02:00
|
|
|
FT_Add64( &temp, &temp2, &temp );
|
2015-02-15 12:30:42 +01:00
|
|
|
q = ft_div64by32( temp.hi, temp.lo, b );
|
1999-12-17 00:11:37 +01:00
|
|
|
}
|
|
|
|
|
2015-02-15 12:30:42 +01:00
|
|
|
q_ = (FT_Long)q;
|
|
|
|
|
2017-06-27 06:16:04 +02:00
|
|
|
return s < 0 ? NEG_LONG( q_ ) : q_;
|
1999-12-17 00:11:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-02-15 12:30:42 +01:00
|
|
|
#endif /* !FT_LONG64 */
|
2001-04-26 00:56:30 +02:00
|
|
|
|
|
|
|
|
2008-06-28 00:26:11 +02:00
|
|
|
/* documentation is in ftglyph.h */
|
|
|
|
|
|
|
|
FT_EXPORT_DEF( void )
|
|
|
|
FT_Matrix_Multiply( const FT_Matrix* a,
|
|
|
|
FT_Matrix *b )
|
|
|
|
{
|
|
|
|
FT_Fixed xx, xy, yx, yy;
|
|
|
|
|
|
|
|
|
|
|
|
if ( !a || !b )
|
|
|
|
return;
|
|
|
|
|
2017-06-09 11:21:58 +02:00
|
|
|
xx = ADD_LONG( FT_MulFix( a->xx, b->xx ),
|
|
|
|
FT_MulFix( a->xy, b->yx ) );
|
|
|
|
xy = ADD_LONG( FT_MulFix( a->xx, b->xy ),
|
|
|
|
FT_MulFix( a->xy, b->yy ) );
|
|
|
|
yx = ADD_LONG( FT_MulFix( a->yx, b->xx ),
|
|
|
|
FT_MulFix( a->yy, b->yx ) );
|
|
|
|
yy = ADD_LONG( FT_MulFix( a->yx, b->xy ),
|
|
|
|
FT_MulFix( a->yy, b->yy ) );
|
Handle some integer overflow run-time errors (#46149, #48979).
This commit (mainly for 32bit CPUs) is the first of a series of
similar commits to handle known integer overflows. Basically, all
of them are harmless, since they affect rendering of glyphs only,
not posing security threats. It is expected that fuzzying will show
up more overflows, to be fixed in due course.
The idea is to mark places where overflows can occur, using macros
that simply cast to unsigned integers, because overflow arithmetic
is well defined in this case. Doing so suppresses run-time errors
of sanitizers without adding computational overhead.
* include/freetype/internal/ftcalc.h (OVERFLOW_ADD_INT,
OVERFLOW_SUB_INT, OVERFLOW_MUL_INT, OVERFLOW_ADD_LONG,
OVERFLOW_SUB_LONG, OVERFLOW_MUL_LONG): New macros.
* src/base/ftcalc.c (FT_RoundFix, FT_CeilFix, FT_Matrix_Multiply,
FT_Matrix_Multiply_Scaled, FT_Vector_Transform_Scaled,
ft_corner_orientation): Use new macros.
* src/base/ftoutln.c (FT_Outline_Get_Orientation): Use new macros.
2017-05-29 13:29:28 +02:00
|
|
|
|
|
|
|
b->xx = xx;
|
|
|
|
b->xy = xy;
|
|
|
|
b->yx = yx;
|
|
|
|
b->yy = yy;
|
2008-06-28 00:26:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* documentation is in ftglyph.h */
|
|
|
|
|
|
|
|
FT_EXPORT_DEF( FT_Error )
|
|
|
|
FT_Matrix_Invert( FT_Matrix* matrix )
|
|
|
|
{
|
|
|
|
FT_Pos delta, xx, yy;
|
|
|
|
|
|
|
|
|
|
|
|
if ( !matrix )
|
2013-03-14 10:27:35 +01:00
|
|
|
return FT_THROW( Invalid_Argument );
|
2008-06-28 00:26:11 +02:00
|
|
|
|
|
|
|
/* compute discriminant */
|
|
|
|
delta = FT_MulFix( matrix->xx, matrix->yy ) -
|
|
|
|
FT_MulFix( matrix->xy, matrix->yx );
|
|
|
|
|
|
|
|
if ( !delta )
|
2013-03-14 10:27:35 +01:00
|
|
|
return FT_THROW( Invalid_Argument ); /* matrix can't be inverted */
|
2008-06-28 00:26:11 +02:00
|
|
|
|
|
|
|
matrix->xy = - FT_DivFix( matrix->xy, delta );
|
|
|
|
matrix->yx = - FT_DivFix( matrix->yx, delta );
|
|
|
|
|
|
|
|
xx = matrix->xx;
|
|
|
|
yy = matrix->yy;
|
|
|
|
|
|
|
|
matrix->xx = FT_DivFix( yy, delta );
|
|
|
|
matrix->yy = FT_DivFix( xx, delta );
|
|
|
|
|
|
|
|
return FT_Err_Ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-05-15 01:05:38 +02:00
|
|
|
/* documentation is in ftcalc.h */
|
|
|
|
|
|
|
|
FT_BASE_DEF( void )
|
|
|
|
FT_Matrix_Multiply_Scaled( const FT_Matrix* a,
|
|
|
|
FT_Matrix *b,
|
|
|
|
FT_Long scaling )
|
|
|
|
{
|
|
|
|
FT_Fixed xx, xy, yx, yy;
|
|
|
|
|
|
|
|
FT_Long val = 0x10000L * scaling;
|
|
|
|
|
|
|
|
|
|
|
|
if ( !a || !b )
|
|
|
|
return;
|
|
|
|
|
2017-06-09 11:21:58 +02:00
|
|
|
xx = ADD_LONG( FT_MulDiv( a->xx, b->xx, val ),
|
|
|
|
FT_MulDiv( a->xy, b->yx, val ) );
|
|
|
|
xy = ADD_LONG( FT_MulDiv( a->xx, b->xy, val ),
|
|
|
|
FT_MulDiv( a->xy, b->yy, val ) );
|
|
|
|
yx = ADD_LONG( FT_MulDiv( a->yx, b->xx, val ),
|
|
|
|
FT_MulDiv( a->yy, b->yx, val ) );
|
|
|
|
yy = ADD_LONG( FT_MulDiv( a->yx, b->xy, val ),
|
|
|
|
FT_MulDiv( a->yy, b->yy, val ) );
|
Handle some integer overflow run-time errors (#46149, #48979).
This commit (mainly for 32bit CPUs) is the first of a series of
similar commits to handle known integer overflows. Basically, all
of them are harmless, since they affect rendering of glyphs only,
not posing security threats. It is expected that fuzzying will show
up more overflows, to be fixed in due course.
The idea is to mark places where overflows can occur, using macros
that simply cast to unsigned integers, because overflow arithmetic
is well defined in this case. Doing so suppresses run-time errors
of sanitizers without adding computational overhead.
* include/freetype/internal/ftcalc.h (OVERFLOW_ADD_INT,
OVERFLOW_SUB_INT, OVERFLOW_MUL_INT, OVERFLOW_ADD_LONG,
OVERFLOW_SUB_LONG, OVERFLOW_MUL_LONG): New macros.
* src/base/ftcalc.c (FT_RoundFix, FT_CeilFix, FT_Matrix_Multiply,
FT_Matrix_Multiply_Scaled, FT_Vector_Transform_Scaled,
ft_corner_orientation): Use new macros.
* src/base/ftoutln.c (FT_Outline_Get_Orientation): Use new macros.
2017-05-29 13:29:28 +02:00
|
|
|
|
|
|
|
b->xx = xx;
|
|
|
|
b->xy = xy;
|
|
|
|
b->yx = yx;
|
|
|
|
b->yy = yy;
|
2008-05-15 01:05:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-06-24 06:22:48 +02:00
|
|
|
/* documentation is in ftcalc.h */
|
|
|
|
|
|
|
|
FT_BASE_DEF( FT_Bool )
|
|
|
|
FT_Matrix_Check( const FT_Matrix* matrix )
|
|
|
|
{
|
|
|
|
FT_Matrix m;
|
|
|
|
FT_Fixed val[4];
|
|
|
|
FT_Fixed nonzero_minval, maxval;
|
|
|
|
FT_Fixed temp1, temp2;
|
|
|
|
FT_UInt i;
|
|
|
|
|
|
|
|
|
|
|
|
if ( !matrix )
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
val[0] = FT_ABS( matrix->xx );
|
|
|
|
val[1] = FT_ABS( matrix->xy );
|
|
|
|
val[2] = FT_ABS( matrix->yx );
|
|
|
|
val[3] = FT_ABS( matrix->yy );
|
|
|
|
|
|
|
|
/*
|
|
|
|
* To avoid overflow, we ensure that each value is not larger than
|
|
|
|
*
|
|
|
|
* int(sqrt(2^31 / 4)) = 23170 ;
|
|
|
|
*
|
|
|
|
* we also check that no value becomes zero if we have to scale.
|
|
|
|
*/
|
|
|
|
|
|
|
|
maxval = 0;
|
|
|
|
nonzero_minval = FT_LONG_MAX;
|
|
|
|
|
|
|
|
for ( i = 0; i < 4; i++ )
|
|
|
|
{
|
|
|
|
if ( val[i] > maxval )
|
|
|
|
maxval = val[i];
|
|
|
|
if ( val[i] && val[i] < nonzero_minval )
|
|
|
|
nonzero_minval = val[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( maxval > 23170 )
|
|
|
|
{
|
|
|
|
FT_Fixed scale = FT_DivFix( maxval, 23170 );
|
|
|
|
|
|
|
|
|
|
|
|
if ( !FT_DivFix( nonzero_minval, scale ) )
|
|
|
|
return 0; /* value range too large */
|
|
|
|
|
|
|
|
m.xx = FT_DivFix( matrix->xx, scale );
|
|
|
|
m.xy = FT_DivFix( matrix->xy, scale );
|
|
|
|
m.yx = FT_DivFix( matrix->yx, scale );
|
|
|
|
m.yy = FT_DivFix( matrix->yy, scale );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
m = *matrix;
|
|
|
|
|
|
|
|
temp1 = FT_ABS( m.xx * m.yy - m.xy * m.yx );
|
|
|
|
temp2 = m.xx * m.xx + m.xy * m.xy + m.yx * m.yx + m.yy * m.yy;
|
|
|
|
|
|
|
|
if ( temp1 == 0 ||
|
|
|
|
temp2 / temp1 > 50 )
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-05-15 01:05:38 +02:00
|
|
|
/* documentation is in ftcalc.h */
|
|
|
|
|
|
|
|
FT_BASE_DEF( void )
|
|
|
|
FT_Vector_Transform_Scaled( FT_Vector* vector,
|
|
|
|
const FT_Matrix* matrix,
|
|
|
|
FT_Long scaling )
|
|
|
|
{
|
|
|
|
FT_Pos xz, yz;
|
|
|
|
|
|
|
|
FT_Long val = 0x10000L * scaling;
|
|
|
|
|
|
|
|
|
|
|
|
if ( !vector || !matrix )
|
|
|
|
return;
|
|
|
|
|
2017-06-09 11:21:58 +02:00
|
|
|
xz = ADD_LONG( FT_MulDiv( vector->x, matrix->xx, val ),
|
|
|
|
FT_MulDiv( vector->y, matrix->xy, val ) );
|
|
|
|
yz = ADD_LONG( FT_MulDiv( vector->x, matrix->yx, val ),
|
|
|
|
FT_MulDiv( vector->y, matrix->yy, val ) );
|
2008-05-15 01:05:38 +02:00
|
|
|
|
|
|
|
vector->x = xz;
|
|
|
|
vector->y = yz;
|
|
|
|
}
|
|
|
|
|
2015-06-30 04:32:05 +02:00
|
|
|
|
|
|
|
/* documentation is in ftcalc.h */
|
|
|
|
|
|
|
|
FT_BASE_DEF( FT_UInt32 )
|
|
|
|
FT_Vector_NormLen( FT_Vector* vector )
|
|
|
|
{
|
2015-07-28 05:22:34 +02:00
|
|
|
FT_Int32 x_ = vector->x;
|
|
|
|
FT_Int32 y_ = vector->y;
|
2015-06-30 04:32:05 +02:00
|
|
|
FT_Int32 b, z;
|
2015-07-28 05:22:34 +02:00
|
|
|
FT_UInt32 x, y, u, v, l;
|
2015-06-30 04:32:05 +02:00
|
|
|
FT_Int sx = 1, sy = 1, shift;
|
|
|
|
|
|
|
|
|
2015-07-28 05:22:34 +02:00
|
|
|
x = (FT_UInt32)x_;
|
|
|
|
y = (FT_UInt32)y_;
|
2015-06-30 04:32:05 +02:00
|
|
|
|
2017-05-28 07:20:09 +02:00
|
|
|
FT_MOVE_SIGN( x_, x, sx );
|
|
|
|
FT_MOVE_SIGN( y_, y, sy );
|
|
|
|
|
2015-06-30 04:32:05 +02:00
|
|
|
/* trivial cases */
|
|
|
|
if ( x == 0 )
|
|
|
|
{
|
|
|
|
if ( y > 0 )
|
|
|
|
vector->y = sy * 0x10000;
|
|
|
|
return y;
|
|
|
|
}
|
|
|
|
else if ( y == 0 )
|
|
|
|
{
|
|
|
|
if ( x > 0 )
|
|
|
|
vector->x = sx * 0x10000;
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
|
2015-07-28 07:37:19 +02:00
|
|
|
/* Estimate length and prenormalize by shifting so that */
|
2015-07-28 05:22:34 +02:00
|
|
|
/* the new approximate length is between 2/3 and 4/3. */
|
2015-07-28 07:37:19 +02:00
|
|
|
/* The magic constant 0xAAAAAAAAUL (2/3 of 2^32) helps */
|
|
|
|
/* achieve this in 16.16 fixed-point representation. */
|
2015-07-28 05:22:34 +02:00
|
|
|
l = x > y ? x + ( y >> 1 )
|
|
|
|
: y + ( x >> 1 );
|
2015-06-30 04:32:05 +02:00
|
|
|
|
|
|
|
shift = 31 - FT_MSB( l );
|
2015-07-28 05:22:34 +02:00
|
|
|
shift -= 15 + ( l >= ( 0xAAAAAAAAUL >> shift ) );
|
2015-06-30 04:32:05 +02:00
|
|
|
|
|
|
|
if ( shift > 0 )
|
|
|
|
{
|
|
|
|
x <<= shift;
|
|
|
|
y <<= shift;
|
|
|
|
|
2015-07-28 07:37:19 +02:00
|
|
|
/* re-estimate length for tiny vectors */
|
2015-07-28 05:22:34 +02:00
|
|
|
l = x > y ? x + ( y >> 1 )
|
|
|
|
: y + ( x >> 1 );
|
2015-06-30 04:32:05 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
x >>= -shift;
|
|
|
|
y >>= -shift;
|
|
|
|
l >>= -shift;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* lower linear approximation for reciprocal length minus one */
|
|
|
|
b = 0x10000 - (FT_Int32)l;
|
|
|
|
|
2015-07-28 05:22:34 +02:00
|
|
|
x_ = (FT_Int32)x;
|
|
|
|
y_ = (FT_Int32)y;
|
|
|
|
|
2015-07-29 05:14:30 +02:00
|
|
|
/* Newton's iterations */
|
2015-06-30 04:32:05 +02:00
|
|
|
do
|
|
|
|
{
|
2015-07-28 05:22:34 +02:00
|
|
|
u = (FT_UInt32)( x_ + ( x_ * b >> 16 ) );
|
|
|
|
v = (FT_UInt32)( y_ + ( y_ * b >> 16 ) );
|
2015-06-30 04:32:05 +02:00
|
|
|
|
2015-07-29 05:14:30 +02:00
|
|
|
/* Normalized squared length in the parentheses approaches 2^32. */
|
|
|
|
/* On two's complement systems, converting to signed gives the */
|
|
|
|
/* difference with 2^32 even if the expression wraps around. */
|
2015-06-30 04:32:05 +02:00
|
|
|
z = -(FT_Int32)( u * u + v * v ) / 0x200;
|
|
|
|
z = z * ( ( 0x10000 + b ) >> 8 ) / 0x10000;
|
|
|
|
|
|
|
|
b += z;
|
2015-07-28 07:37:19 +02:00
|
|
|
|
2015-06-30 04:32:05 +02:00
|
|
|
} while ( z > 0 );
|
|
|
|
|
|
|
|
vector->x = sx < 0 ? -(FT_Pos)u : (FT_Pos)u;
|
|
|
|
vector->y = sy < 0 ? -(FT_Pos)v : (FT_Pos)v;
|
|
|
|
|
2015-07-29 05:14:30 +02:00
|
|
|
/* Conversion to signed helps to recover from likely wrap around */
|
|
|
|
/* in calculating the prenormalized length, because it gives the */
|
|
|
|
/* correct difference with 2^32 on two's complement systems. */
|
|
|
|
l = (FT_UInt32)( 0x10000 + (FT_Int32)( u * x + v * y ) / 0x10000 );
|
2015-06-30 04:32:05 +02:00
|
|
|
if ( shift > 0 )
|
|
|
|
l = ( l + ( 1 << ( shift - 1 ) ) ) >> shift;
|
|
|
|
else
|
|
|
|
l <<= -shift;
|
|
|
|
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
2008-05-15 01:05:38 +02:00
|
|
|
|
2013-08-27 21:36:03 +02:00
|
|
|
#if 0
|
|
|
|
|
2004-12-14 00:16:59 +01:00
|
|
|
/* documentation is in ftcalc.h */
|
2001-04-26 15:34:36 +02:00
|
|
|
|
* src/base/ftcalc.c (FT_MulTo64): Commented out.
* include/freetype/internal/ftcalc.h (FT_SqrtFixed), src/base/ftcalc.c
(FT_SqrtFixed), include/freetype/internal/ftdebug.h
(FT_Trace_Get_Count, FT_Trace_Get_Name, FT_Message, FT_Panic),
src/base/ftdebug.c (FT_Trace_Get_Count, FT_Trace_Get_Name, FT_Message,
FT_Panic), include/freetype/internal/ftobjs.h (FT_New_Memory,
FT_Done_Memory), include/freetype/internal/ftstream.h
(FT_Stream_Open), src/base/ftsystem.c (FT_New_Memory, FT_Done_Memory,
FT_Stream_Open): s/FT_EXPORT/FT_BASE/.
* builds/exports.mk: Manually add TT_New_Context to EXPORTS_LIST too.
2005-11-17 02:53:07 +01:00
|
|
|
FT_BASE_DEF( FT_Int32 )
|
2001-06-27 18:18:10 +02:00
|
|
|
FT_SqrtFixed( FT_Int32 x )
|
2000-09-02 02:20:42 +02:00
|
|
|
{
|
2001-04-25 20:11:16 +02:00
|
|
|
FT_UInt32 root, rem_hi, rem_lo, test_div;
|
|
|
|
FT_Int count;
|
2000-10-31 21:42:18 +01:00
|
|
|
|
2001-04-26 15:34:36 +02:00
|
|
|
|
2001-04-25 20:11:16 +02:00
|
|
|
root = 0;
|
2000-09-02 02:20:42 +02:00
|
|
|
|
2001-04-25 20:11:16 +02:00
|
|
|
if ( x > 0 )
|
|
|
|
{
|
|
|
|
rem_hi = 0;
|
2015-02-15 12:30:42 +01:00
|
|
|
rem_lo = (FT_UInt32)x;
|
2001-04-26 00:56:30 +02:00
|
|
|
count = 24;
|
2001-04-26 15:34:36 +02:00
|
|
|
do
|
2001-04-25 20:11:16 +02:00
|
|
|
{
|
2001-04-26 15:34:36 +02:00
|
|
|
rem_hi = ( rem_hi << 2 ) | ( rem_lo >> 30 );
|
2001-04-25 20:11:16 +02:00
|
|
|
rem_lo <<= 2;
|
|
|
|
root <<= 1;
|
2001-04-26 15:34:36 +02:00
|
|
|
test_div = ( root << 1 ) + 1;
|
|
|
|
|
2001-04-25 20:11:16 +02:00
|
|
|
if ( rem_hi >= test_div )
|
|
|
|
{
|
|
|
|
rem_hi -= test_div;
|
|
|
|
root += 1;
|
|
|
|
}
|
2001-04-26 15:34:36 +02:00
|
|
|
} while ( --count );
|
2001-04-25 20:11:16 +02:00
|
|
|
}
|
2000-09-12 00:50:13 +02:00
|
|
|
|
2001-04-25 20:11:16 +02:00
|
|
|
return (FT_Int32)root;
|
|
|
|
}
|
2000-05-02 12:52:28 +02:00
|
|
|
|
2013-08-27 21:36:03 +02:00
|
|
|
#endif /* 0 */
|
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
|
2006-11-03 10:40:12 +01:00
|
|
|
/* documentation is in ftcalc.h */
|
2006-11-02 18:21:02 +01:00
|
|
|
|
|
|
|
FT_BASE_DEF( FT_Int )
|
2006-11-03 10:40:12 +01:00
|
|
|
ft_corner_orientation( FT_Pos in_x,
|
|
|
|
FT_Pos in_y,
|
|
|
|
FT_Pos out_x,
|
|
|
|
FT_Pos out_y )
|
2006-11-02 18:21:02 +01:00
|
|
|
{
|
|
|
|
#ifdef FT_LONG64
|
2006-11-03 10:40:12 +01:00
|
|
|
|
2015-08-04 05:26:13 +02:00
|
|
|
FT_Int64 delta = (FT_Int64)in_x * out_y - (FT_Int64)in_y * out_x;
|
2006-11-03 10:40:12 +01:00
|
|
|
|
2006-11-02 18:21:02 +01:00
|
|
|
|
2015-08-04 05:26:13 +02:00
|
|
|
return ( delta > 0 ) - ( delta < 0 );
|
2006-11-03 10:40:12 +01:00
|
|
|
|
2006-11-02 18:21:02 +01:00
|
|
|
#else
|
2006-11-03 10:40:12 +01:00
|
|
|
|
2015-08-04 05:26:13 +02:00
|
|
|
FT_Int result;
|
|
|
|
|
|
|
|
|
Handle some integer overflow run-time errors (#46149, #48979).
This commit (mainly for 32bit CPUs) is the first of a series of
similar commits to handle known integer overflows. Basically, all
of them are harmless, since they affect rendering of glyphs only,
not posing security threats. It is expected that fuzzying will show
up more overflows, to be fixed in due course.
The idea is to mark places where overflows can occur, using macros
that simply cast to unsigned integers, because overflow arithmetic
is well defined in this case. Doing so suppresses run-time errors
of sanitizers without adding computational overhead.
* include/freetype/internal/ftcalc.h (OVERFLOW_ADD_INT,
OVERFLOW_SUB_INT, OVERFLOW_MUL_INT, OVERFLOW_ADD_LONG,
OVERFLOW_SUB_LONG, OVERFLOW_MUL_LONG): New macros.
* src/base/ftcalc.c (FT_RoundFix, FT_CeilFix, FT_Matrix_Multiply,
FT_Matrix_Multiply_Scaled, FT_Vector_Transform_Scaled,
ft_corner_orientation): Use new macros.
* src/base/ftoutln.c (FT_Outline_Get_Orientation): Use new macros.
2017-05-29 13:29:28 +02:00
|
|
|
/* we silently ignore overflow errors, since such large values */
|
|
|
|
/* lead to even more (harmless) rendering errors later on */
|
2017-06-09 11:21:58 +02:00
|
|
|
if ( ADD_LONG( FT_ABS( in_x ), FT_ABS( out_y ) ) <= 131071L &&
|
|
|
|
ADD_LONG( FT_ABS( in_y ), FT_ABS( out_x ) ) <= 131071L )
|
2015-08-04 05:26:13 +02:00
|
|
|
{
|
2017-06-09 11:21:58 +02:00
|
|
|
FT_Long z1 = MUL_LONG( in_x, out_y );
|
|
|
|
FT_Long z2 = MUL_LONG( in_y, out_x );
|
2015-08-04 05:26:13 +02:00
|
|
|
|
|
|
|
|
|
|
|
if ( z1 > z2 )
|
|
|
|
result = +1;
|
|
|
|
else if ( z1 < z2 )
|
|
|
|
result = -1;
|
|
|
|
else
|
|
|
|
result = 0;
|
|
|
|
}
|
|
|
|
else /* products might overflow 32 bits */
|
|
|
|
{
|
2006-11-03 10:40:12 +01:00
|
|
|
FT_Int64 z1, z2;
|
|
|
|
|
2006-11-02 18:21:02 +01:00
|
|
|
|
2009-07-31 17:30:24 +02:00
|
|
|
/* XXX: this function does not allow 64-bit arguments */
|
2015-02-15 12:30:42 +01:00
|
|
|
ft_multo64( (FT_UInt32)in_x, (FT_UInt32)out_y, &z1 );
|
|
|
|
ft_multo64( (FT_UInt32)in_y, (FT_UInt32)out_x, &z2 );
|
2006-11-02 18:21:02 +01:00
|
|
|
|
|
|
|
if ( z1.hi > z2.hi )
|
|
|
|
result = +1;
|
|
|
|
else if ( z1.hi < z2.hi )
|
|
|
|
result = -1;
|
|
|
|
else if ( z1.lo > z2.lo )
|
|
|
|
result = +1;
|
|
|
|
else if ( z1.lo < z2.lo )
|
|
|
|
result = -1;
|
|
|
|
else
|
|
|
|
result = 0;
|
|
|
|
}
|
|
|
|
|
2009-07-31 17:32:06 +02:00
|
|
|
/* XXX: only the sign of return value, +1/0/-1 must be used */
|
2015-08-04 05:26:13 +02:00
|
|
|
return result;
|
|
|
|
|
|
|
|
#endif
|
2006-11-02 18:21:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-11-03 10:40:12 +01:00
|
|
|
/* documentation is in ftcalc.h */
|
|
|
|
|
2006-11-02 18:21:02 +01:00
|
|
|
FT_BASE_DEF( FT_Int )
|
|
|
|
ft_corner_is_flat( FT_Pos in_x,
|
|
|
|
FT_Pos in_y,
|
|
|
|
FT_Pos out_x,
|
|
|
|
FT_Pos out_y )
|
|
|
|
{
|
2014-10-25 05:50:57 +02:00
|
|
|
FT_Pos ax = in_x + out_x;
|
|
|
|
FT_Pos ay = in_y + out_y;
|
|
|
|
|
2014-10-25 06:28:18 +02:00
|
|
|
FT_Pos d_in, d_out, d_hypot;
|
|
|
|
|
|
|
|
|
|
|
|
/* The idea of this function is to compare the length of the */
|
|
|
|
/* hypotenuse with the `in' and `out' length. The `corner' */
|
|
|
|
/* represented by `in' and `out' is flat if the hypotenuse's */
|
|
|
|
/* length isn't too large. */
|
|
|
|
/* */
|
|
|
|
/* This approach has the advantage that the angle between */
|
|
|
|
/* `in' and `out' is not checked. In case one of the two */
|
|
|
|
/* vectors is `dominant', this is, much larger than the */
|
|
|
|
/* other vector, we thus always have a flat corner. */
|
|
|
|
/* */
|
|
|
|
/* hypotenuse */
|
|
|
|
/* x---------------------------x */
|
|
|
|
/* \ / */
|
|
|
|
/* \ / */
|
|
|
|
/* in \ / out */
|
|
|
|
/* \ / */
|
|
|
|
/* o */
|
|
|
|
/* Point */
|
|
|
|
|
|
|
|
d_in = FT_HYPOT( in_x, in_y );
|
|
|
|
d_out = FT_HYPOT( out_x, out_y );
|
|
|
|
d_hypot = FT_HYPOT( ax, ay );
|
2014-10-25 05:50:57 +02:00
|
|
|
|
2013-08-04 18:24:02 +02:00
|
|
|
/* now do a simple length comparison: */
|
|
|
|
/* */
|
2014-10-25 06:28:18 +02:00
|
|
|
/* d_in + d_out < 17/16 d_hypot */
|
2006-11-02 18:21:02 +01:00
|
|
|
|
2014-10-25 06:28:18 +02:00
|
|
|
return ( d_in + d_out - d_hypot ) < ( d_hypot >> 4 );
|
2006-11-02 18:21:02 +01:00
|
|
|
}
|
2006-11-03 10:40:12 +01:00
|
|
|
|
|
|
|
|
1999-12-17 00:11:37 +01:00
|
|
|
/* END */
|