ReactOS 0.4.15-dev-7958-gcd0bb1a
pshints.c File Reference
#include "psft.h"
#include "psglue.h"
#include "psfont.h"
#include "pshints.h"
#include "psintrp.h"
Include dependency graph for pshints.c:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  CF2_HintMoveRec_
 

Macros

#define FT_COMPONENT   trace_cf2hints
 
#define cf2_perp(a, b)    ( FT_MulFix( a.x, b.y ) - FT_MulFix( a.y, b.x ) )
 
#define CF2_CS_SCALE(x)    ( ( (x) + 0x10 ) >> 5 )
 

Typedefs

typedef struct CF2_HintMoveRec_ CF2_HintMoveRec
 
typedef struct CF2_HintMoveRec_CF2_HintMove
 

Functions

static CF2_Int cf2_getWindingMomentum (CF2_Fixed x1, CF2_Fixed y1, CF2_Fixed x2, CF2_Fixed y2)
 
static void cf2_hint_init (CF2_Hint hint, const CF2_ArrStack stemHintArray, size_t indexStemHint, const CF2_Font font, CF2_Fixed hintOrigin, CF2_Fixed scale, FT_Bool bottom)
 
static void cf2_hint_initZero (CF2_Hint hint)
 
 cf2_hint_isValid (const CF2_Hint hint)
 
static FT_Bool cf2_hint_isPair (const CF2_Hint hint)
 
static FT_Bool cf2_hint_isPairTop (const CF2_Hint hint)
 
 cf2_hint_isTop (const CF2_Hint hint)
 
 cf2_hint_isBottom (const CF2_Hint hint)
 
static FT_Bool cf2_hint_isLocked (const CF2_Hint hint)
 
static FT_Bool cf2_hint_isSynthetic (const CF2_Hint hint)
 
 cf2_hint_lock (CF2_Hint hint)
 
 cf2_hintmap_init (CF2_HintMap hintmap, CF2_Font font, CF2_HintMap initialMap, CF2_ArrStack hintMoves, CF2_Fixed scale)
 
static FT_Bool cf2_hintmap_isValid (const CF2_HintMap hintmap)
 
static void cf2_hintmap_dump (CF2_HintMap hintmap)
 
static CF2_Fixed cf2_hintmap_map (CF2_HintMap hintmap, CF2_Fixed csCoord)
 
static void cf2_hintmap_adjustHints (CF2_HintMap hintmap)
 
static void cf2_hintmap_insertHint (CF2_HintMap hintmap, CF2_Hint bottomHintEdge, CF2_Hint topHintEdge)
 
 cf2_hintmap_build (CF2_HintMap hintmap, CF2_ArrStack hStemHintArray, CF2_ArrStack vStemHintArray, CF2_HintMask hintMask, CF2_Fixed hintOrigin, FT_Bool initialMap)
 
 cf2_glyphpath_init (CF2_GlyphPath glyphpath, CF2_Font font, CF2_OutlineCallbacks callbacks, CF2_Fixed scaleY, CF2_ArrStack hStemHintArray, CF2_ArrStack vStemHintArray, CF2_HintMask hintMask, CF2_Fixed hintOriginY, const CF2_Blues blues, const FT_Vector *fractionalTranslation)
 
 cf2_glyphpath_finalize (CF2_GlyphPath glyphpath)
 
static void cf2_glyphpath_hintPoint (CF2_GlyphPath glyphpath, CF2_HintMap hintmap, FT_Vector *ppt, CF2_Fixed x, CF2_Fixed y)
 
static FT_Bool cf2_glyphpath_computeIntersection (CF2_GlyphPath glyphpath, const FT_Vector *u1, const FT_Vector *u2, const FT_Vector *v1, const FT_Vector *v2, FT_Vector *intersection)
 
static void cf2_glyphpath_pushPrevElem (CF2_GlyphPath glyphpath, CF2_HintMap hintmap, FT_Vector *nextP0, FT_Vector nextP1, FT_Bool close)
 
static void cf2_glyphpath_pushMove (CF2_GlyphPath glyphpath, FT_Vector start)
 
static void cf2_glyphpath_computeOffset (CF2_GlyphPath glyphpath, CF2_Fixed x1, CF2_Fixed y1, CF2_Fixed x2, CF2_Fixed y2, CF2_Fixed *x, CF2_Fixed *y)
 
 cf2_glyphpath_moveTo (CF2_GlyphPath glyphpath, CF2_Fixed x, CF2_Fixed y)
 
 cf2_glyphpath_lineTo (CF2_GlyphPath glyphpath, CF2_Fixed x, CF2_Fixed y)
 
 cf2_glyphpath_curveTo (CF2_GlyphPath glyphpath, CF2_Fixed x1, CF2_Fixed y1, CF2_Fixed x2, CF2_Fixed y2, CF2_Fixed x3, CF2_Fixed y3)
 
 cf2_glyphpath_closeOpenPath (CF2_GlyphPath glyphpath)
 

Macro Definition Documentation

◆ CF2_CS_SCALE

#define CF2_CS_SCALE (   x)     ( ( (x) + 0x10 ) >> 5 )

◆ cf2_perp

#define cf2_perp (   a,
  b 
)     ( FT_MulFix( a.x, b.y ) - FT_MulFix( a.y, b.x ) )

◆ FT_COMPONENT

#define FT_COMPONENT   trace_cf2hints

Definition at line 55 of file pshints.c.

Typedef Documentation

◆ CF2_HintMove

◆ CF2_HintMoveRec

Function Documentation

◆ cf2_getWindingMomentum()

static CF2_Int cf2_getWindingMomentum ( CF2_Fixed  x1,
CF2_Fixed  y1,
CF2_Fixed  x2,
CF2_Fixed  y2 
)
static

Definition at line 69 of file pshints.c.

73 {
74 /* cross product of pt1 position from origin with pt2 position from */
75 /* pt1; we reduce the precision so that the result fits into 32 bits */
76
77 return ( x1 >> 16 ) * ( SUB_INT32( y2, y1 ) >> 16 ) -
78 ( y1 >> 16 ) * ( SUB_INT32( x2, x1 ) >> 16 );
79 }
#define SUB_INT32(a, b)
Definition: ftcalc.h:431
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG _In_ LONG _In_ LONG x2
Definition: winddi.h:3710
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG _In_ LONG y1
Definition: winddi.h:3709
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG x1
Definition: winddi.h:3708
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG _In_ LONG _In_ LONG _In_ LONG y2
Definition: winddi.h:3711

Referenced by cf2_glyphpath_computeOffset(), and cf2_glyphpath_curveTo().

◆ cf2_glyphpath_closeOpenPath()

cf2_glyphpath_closeOpenPath ( CF2_GlyphPath  glyphpath)

Definition at line 1907 of file pshints.c.

1908 {
1909 if ( glyphpath->pathIsOpen )
1910 {
1911 /*
1912 * A closing line in Character Space line is always generated below
1913 * with `cf2_glyphPath_lineTo'. It may be ignored later if it turns
1914 * out to be zero length in Device Space.
1915 */
1916 glyphpath->pathIsClosing = TRUE;
1917
1918 cf2_glyphpath_lineTo( glyphpath,
1919 glyphpath->start.x,
1920 glyphpath->start.y );
1921
1922 /* empty the final element from the queue and close the path */
1923 if ( glyphpath->elemIsQueued )
1924 cf2_glyphpath_pushPrevElem( glyphpath,
1925 &glyphpath->hintMap,
1926 &glyphpath->offsetStart0,
1927 glyphpath->offsetStart1,
1928 TRUE );
1929
1930 /* reset state machine */
1931 glyphpath->moveIsPending = TRUE;
1932 glyphpath->pathIsOpen = FALSE;
1933 glyphpath->pathIsClosing = FALSE;
1934 glyphpath->elemIsQueued = FALSE;
1935 }
1936 }
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
cf2_glyphpath_lineTo(CF2_GlyphPath glyphpath, CF2_Fixed x, CF2_Fixed y)
Definition: pshints.c:1711
static void cf2_glyphpath_pushPrevElem(CF2_GlyphPath glyphpath, CF2_HintMap hintmap, FT_Vector *nextP0, FT_Vector nextP1, FT_Bool close)
Definition: pshints.c:1321
CF2_HintMapRec hintMap
Definition: pshints.h:189
FT_Vector offsetStart1
Definition: pshints.h:226
FT_Bool pathIsClosing
Definition: pshints.h:206
FT_Vector start
Definition: pshints.h:233
FT_Vector offsetStart0
Definition: pshints.h:225
FT_Bool moveIsPending
Definition: pshints.h:208
FT_Bool elemIsQueued
Definition: pshints.h:236
FT_Bool pathIsOpen
Definition: pshints.h:205
FT_Pos x
Definition: ftimage.h:76
FT_Pos y
Definition: ftimage.h:77

Referenced by cf2_glyphpath_moveTo(), and cf2_interpT2CharString().

◆ cf2_glyphpath_computeIntersection()

static FT_Bool cf2_glyphpath_computeIntersection ( CF2_GlyphPath  glyphpath,
const FT_Vector u1,
const FT_Vector u2,
const FT_Vector v1,
const FT_Vector v2,
FT_Vector intersection 
)
static

Definition at line 1201 of file pshints.c.

1207 {
1208 /*
1209 * Let `u' be a zero-based vector from the first segment, `v' from the
1210 * second segment.
1211 * Let `w 'be the zero-based vector from `u1' to `v1'.
1212 * `perp' is the `perpendicular dot product'; see
1213 * https://mathworld.wolfram.com/PerpDotProduct.html.
1214 * `s' is the parameter for the parametric line for the first segment
1215 * (`u').
1216 *
1217 * See notation in
1218 * http://softsurfer.com/Archive/algorithm_0104/algorithm_0104B.htm.
1219 * Calculations are done in 16.16, but must handle the squaring of
1220 * line lengths in character space. We scale all vectors by 1/32 to
1221 * avoid overflow. This allows values up to 4095 to be squared. The
1222 * scale factor cancels in the divide.
1223 *
1224 * TODO: the scale factor could be computed from UnitsPerEm.
1225 *
1226 */
1227
1228#define cf2_perp( a, b ) \
1229 ( FT_MulFix( a.x, b.y ) - FT_MulFix( a.y, b.x ) )
1230
1231 /* round and divide by 32 */
1232#define CF2_CS_SCALE( x ) \
1233 ( ( (x) + 0x10 ) >> 5 )
1234
1235 FT_Vector u, v, w; /* scaled vectors */
1236 CF2_Fixed denominator, s;
1237
1238
1239 u.x = CF2_CS_SCALE( SUB_INT32( u2->x, u1->x ) );
1240 u.y = CF2_CS_SCALE( SUB_INT32( u2->y, u1->y ) );
1241 v.x = CF2_CS_SCALE( SUB_INT32( v2->x, v1->x ) );
1242 v.y = CF2_CS_SCALE( SUB_INT32( v2->y, v1->y ) );
1243 w.x = CF2_CS_SCALE( SUB_INT32( v1->x, u1->x ) );
1244 w.y = CF2_CS_SCALE( SUB_INT32( v1->y, u1->y ) );
1245
1246 denominator = cf2_perp( u, v );
1247
1248 if ( denominator == 0 )
1249 return FALSE; /* parallel or coincident lines */
1250
1251 s = FT_DivFix( cf2_perp( w, v ), denominator );
1252
1253 intersection->x = ADD_INT32( u1->x,
1254 FT_MulFix( s, SUB_INT32( u2->x, u1->x ) ) );
1255 intersection->y = ADD_INT32( u1->y,
1256 FT_MulFix( s, SUB_INT32( u2->y, u1->y ) ) );
1257
1258
1259 /*
1260 * Special case snapping for horizontal and vertical lines.
1261 * This cleans up intersections and reduces problems with winding
1262 * order detection.
1263 * Sample case is sbc cd KozGoPr6N-Medium.otf 20 16685.
1264 * Note: these calculations are in character space.
1265 *
1266 */
1267
1268 if ( u1->x == u2->x &&
1269 cf2_fixedAbs( SUB_INT32( intersection->x,
1270 u1->x ) ) < glyphpath->snapThreshold )
1271 intersection->x = u1->x;
1272 if ( u1->y == u2->y &&
1273 cf2_fixedAbs( SUB_INT32( intersection->y,
1274 u1->y ) ) < glyphpath->snapThreshold )
1275 intersection->y = u1->y;
1276
1277 if ( v1->x == v2->x &&
1278 cf2_fixedAbs( SUB_INT32( intersection->x,
1279 v1->x ) ) < glyphpath->snapThreshold )
1280 intersection->x = v1->x;
1281 if ( v1->y == v2->y &&
1282 cf2_fixedAbs( SUB_INT32( intersection->y,
1283 v1->y ) ) < glyphpath->snapThreshold )
1284 intersection->y = v1->y;
1285
1286 /* limit the intersection distance from midpoint of u2 and v1 */
1287 if ( cf2_fixedAbs( intersection->x - ADD_INT32( u2->x, v1->x ) / 2 ) >
1288 glyphpath->miterLimit ||
1289 cf2_fixedAbs( intersection->y - ADD_INT32( u2->y, v1->y ) / 2 ) >
1290 glyphpath->miterLimit )
1291 return FALSE;
1292
1293 return TRUE;
1294 }
FT_DivFix(FT_Long a, FT_Long b)
Definition: ftcalc.c:608
FT_MulFix(FT_Long a, FT_Long b)
Definition: ftcalc.c:509
#define ADD_INT32(a, b)
Definition: ftcalc.h:429
const GLdouble * v
Definition: gl.h:2040
GLdouble s
Definition: gl.h:2039
GLdouble GLdouble u2
Definition: glext.h:8308
GLfloat GLfloat v1
Definition: glext.h:6062
GLfloat GLfloat GLfloat v2
Definition: glext.h:6063
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:6102
GLdouble u1
Definition: glext.h:8308
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble * u
Definition: glfuncs.h:240
#define CF2_Fixed
Definition: psfixed.h:48
#define cf2_fixedAbs(x)
Definition: psfixed.h:68
#define cf2_perp(a, b)
#define CF2_CS_SCALE(x)
CF2_Fixed miterLimit
Definition: pshints.h:221
CF2_Fixed snapThreshold
Definition: pshints.h:223

Referenced by cf2_glyphpath_pushPrevElem().

◆ cf2_glyphpath_computeOffset()

static void cf2_glyphpath_computeOffset ( CF2_GlyphPath  glyphpath,
CF2_Fixed  x1,
CF2_Fixed  y1,
CF2_Fixed  x2,
CF2_Fixed  y2,
CF2_Fixed x,
CF2_Fixed y 
)
static

Definition at line 1530 of file pshints.c.

1537 {
1538 CF2_Fixed dx = SUB_INT32( x2, x1 );
1539 CF2_Fixed dy = SUB_INT32( y2, y1 );
1540
1541
1542 /* note: negative offsets don't work here; negate deltas to change */
1543 /* quadrants, below */
1544 if ( glyphpath->font->reverseWinding )
1545 {
1546 dx = NEG_INT32( dx );
1547 dy = NEG_INT32( dy );
1548 }
1549
1550 *x = *y = 0;
1551
1552 if ( !glyphpath->darken )
1553 return;
1554
1555 /* add momentum for this path element */
1556 glyphpath->callbacks->windingMomentum =
1557 ADD_INT32( glyphpath->callbacks->windingMomentum,
1559
1560 /* note: allow mixed integer and fixed multiplication here */
1561 if ( dx >= 0 )
1562 {
1563 if ( dy >= 0 )
1564 {
1565 /* first quadrant, +x +y */
1566
1567 if ( dx > MUL_INT32( 2, dy ) )
1568 {
1569 /* +x */
1570 *x = 0;
1571 *y = 0;
1572 }
1573 else if ( dy > MUL_INT32( 2, dx ) )
1574 {
1575 /* +y */
1576 *x = glyphpath->xOffset;
1577 *y = glyphpath->yOffset;
1578 }
1579 else
1580 {
1581 /* +x +y */
1582 *x = FT_MulFix( cf2_doubleToFixed( 0.7 ),
1583 glyphpath->xOffset );
1584 *y = FT_MulFix( cf2_doubleToFixed( 1.0 - 0.7 ),
1585 glyphpath->yOffset );
1586 }
1587 }
1588 else
1589 {
1590 /* fourth quadrant, +x -y */
1591
1592 if ( dx > MUL_INT32( -2, dy ) )
1593 {
1594 /* +x */
1595 *x = 0;
1596 *y = 0;
1597 }
1598 else if ( NEG_INT32( dy ) > MUL_INT32( 2, dx ) )
1599 {
1600 /* -y */
1601 *x = NEG_INT32( glyphpath->xOffset );
1602 *y = glyphpath->yOffset;
1603 }
1604 else
1605 {
1606 /* +x -y */
1607 *x = FT_MulFix( cf2_doubleToFixed( -0.7 ),
1608 glyphpath->xOffset );
1609 *y = FT_MulFix( cf2_doubleToFixed( 1.0 - 0.7 ),
1610 glyphpath->yOffset );
1611 }
1612 }
1613 }
1614 else
1615 {
1616 if ( dy >= 0 )
1617 {
1618 /* second quadrant, -x +y */
1619
1620 if ( NEG_INT32( dx ) > MUL_INT32( 2, dy ) )
1621 {
1622 /* -x */
1623 *x = 0;
1624 *y = MUL_INT32( 2, glyphpath->yOffset );
1625 }
1626 else if ( dy > MUL_INT32( -2, dx ) )
1627 {
1628 /* +y */
1629 *x = glyphpath->xOffset;
1630 *y = glyphpath->yOffset;
1631 }
1632 else
1633 {
1634 /* -x +y */
1635 *x = FT_MulFix( cf2_doubleToFixed( 0.7 ),
1636 glyphpath->xOffset );
1637 *y = FT_MulFix( cf2_doubleToFixed( 1.0 + 0.7 ),
1638 glyphpath->yOffset );
1639 }
1640 }
1641 else
1642 {
1643 /* third quadrant, -x -y */
1644
1645 if ( NEG_INT32( dx ) > MUL_INT32( -2, dy ) )
1646 {
1647 /* -x */
1648 *x = 0;
1649 *y = MUL_INT32( 2, glyphpath->yOffset );
1650 }
1651 else if ( NEG_INT32( dy ) > MUL_INT32( -2, dx ) )
1652 {
1653 /* -y */
1654 *x = NEG_INT32( glyphpath->xOffset );
1655 *y = glyphpath->yOffset;
1656 }
1657 else
1658 {
1659 /* -x -y */
1660 *x = FT_MulFix( cf2_doubleToFixed( -0.7 ),
1661 glyphpath->xOffset );
1662 *y = FT_MulFix( cf2_doubleToFixed( 1.0 + 0.7 ),
1663 glyphpath->yOffset );
1664 }
1665 }
1666 }
1667 }
#define MUL_INT32(a, b)
Definition: ftcalc.h:433
#define NEG_INT32(a)
Definition: ftcalc.h:435
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLint dy
Definition: linetemp.h:97
GLint dx
Definition: linetemp.h:97
#define cf2_doubleToFixed(f)
Definition: psfixed.h:66
static CF2_Int cf2_getWindingMomentum(CF2_Fixed x1, CF2_Fixed y1, CF2_Fixed x2, CF2_Fixed y2)
Definition: pshints.c:69
FT_Bool reverseWinding
Definition: psfont.h:112
CF2_Fixed yOffset
Definition: pshints.h:218
CF2_Font font
Definition: pshints.h:185
CF2_Fixed xOffset
Definition: pshints.h:217
CF2_OutlineCallbacks callbacks
Definition: pshints.h:186
FT_Bool darken
Definition: pshints.h:207

Referenced by cf2_glyphpath_curveTo(), and cf2_glyphpath_lineTo().

◆ cf2_glyphpath_curveTo()

cf2_glyphpath_curveTo ( CF2_GlyphPath  glyphpath,
CF2_Fixed  x1,
CF2_Fixed  y1,
CF2_Fixed  x2,
CF2_Fixed  y2,
CF2_Fixed  x3,
CF2_Fixed  y3 
)

Definition at line 1817 of file pshints.c.

1824 {
1825 CF2_Fixed xOffset1, yOffset1, xOffset3, yOffset3;
1826 FT_Vector P0, P1, P2, P3;
1827
1828
1829 /* TODO: ignore zero length portions of curve?? */
1830 cf2_glyphpath_computeOffset( glyphpath,
1831 glyphpath->currentCS.x,
1832 glyphpath->currentCS.y,
1833 x1,
1834 y1,
1835 &xOffset1,
1836 &yOffset1 );
1837 cf2_glyphpath_computeOffset( glyphpath,
1838 x2,
1839 y2,
1840 x3,
1841 y3,
1842 &xOffset3,
1843 &yOffset3 );
1844
1845 /* add momentum from the middle segment */
1846 glyphpath->callbacks->windingMomentum =
1847 ADD_INT32( glyphpath->callbacks->windingMomentum,
1849
1850 /* construct offset points */
1851 P0.x = ADD_INT32( glyphpath->currentCS.x, xOffset1 );
1852 P0.y = ADD_INT32( glyphpath->currentCS.y, yOffset1 );
1853 P1.x = ADD_INT32( x1, xOffset1 );
1854 P1.y = ADD_INT32( y1, yOffset1 );
1855 /* note: preserve angle of final segment by using offset3 at both ends */
1856 P2.x = ADD_INT32( x2, xOffset3 );
1857 P2.y = ADD_INT32( y2, yOffset3 );
1858 P3.x = ADD_INT32( x3, xOffset3 );
1859 P3.y = ADD_INT32( y3, yOffset3 );
1860
1861 if ( glyphpath->moveIsPending )
1862 {
1863 /* emit offset 1st point as MoveTo */
1864 cf2_glyphpath_pushMove( glyphpath, P0 );
1865
1866 glyphpath->moveIsPending = FALSE;
1867 glyphpath->pathIsOpen = TRUE;
1868
1869 glyphpath->offsetStart1 = P1; /* record second point */
1870 }
1871
1872 if ( glyphpath->elemIsQueued )
1873 {
1874 FT_ASSERT( cf2_hintmap_isValid( &glyphpath->hintMap ) ||
1875 glyphpath->hintMap.count == 0 );
1876
1877 cf2_glyphpath_pushPrevElem( glyphpath,
1878 &glyphpath->hintMap,
1879 &P0,
1880 P1,
1881 FALSE );
1882 }
1883
1884 /* queue the current element with offset points */
1885 glyphpath->elemIsQueued = TRUE;
1886 glyphpath->prevElemOp = CF2_PathOpCubeTo;
1887 glyphpath->prevElemP0 = P0;
1888 glyphpath->prevElemP1 = P1;
1889 glyphpath->prevElemP2 = P2;
1890 glyphpath->prevElemP3 = P3;
1891
1892 /* update current map */
1893 if ( cf2_hintmask_isNew( glyphpath->hintMask ) )
1894 cf2_hintmap_build( &glyphpath->hintMap,
1895 glyphpath->hStemHintArray,
1896 glyphpath->vStemHintArray,
1897 glyphpath->hintMask,
1898 glyphpath->hintOriginY,
1899 FALSE );
1900
1901 glyphpath->currentCS.x = x3; /* pre-offset current point */
1902 glyphpath->currentCS.y = y3;
1903 }
#define FT_ASSERT(condition)
Definition: ftdebug.h:211
@ CF2_PathOpCubeTo
Definition: psglue.h:70
static void cf2_glyphpath_pushMove(CF2_GlyphPath glyphpath, FT_Vector start)
Definition: pshints.c:1485
cf2_hintmap_build(CF2_HintMap hintmap, CF2_ArrStack hStemHintArray, CF2_ArrStack vStemHintArray, CF2_HintMask hintMask, CF2_Fixed hintOrigin, FT_Bool initialMap)
Definition: pshints.c:808
static FT_Bool cf2_hintmap_isValid(const CF2_HintMap hintmap)
Definition: pshints.c:296
static void cf2_glyphpath_computeOffset(CF2_GlyphPath glyphpath, CF2_Fixed x1, CF2_Fixed y1, CF2_Fixed x2, CF2_Fixed y2, CF2_Fixed *x, CF2_Fixed *y)
Definition: pshints.c:1530
cf2_hintmask_isNew(const CF2_HintMask hintmask)
Definition: psintrp.c:83
FT_Vector prevElemP1
Definition: pshints.h:240
FT_Vector currentCS
Definition: pshints.h:229
CF2_HintMask hintMask
Definition: pshints.h:213
CF2_ArrStack vStemHintArray
Definition: pshints.h:212
CF2_Fixed hintOriginY
Definition: pshints.h:214
CF2_Int prevElemOp
Definition: pshints.h:237
FT_Vector prevElemP2
Definition: pshints.h:241
FT_Vector prevElemP0
Definition: pshints.h:239
CF2_ArrStack hStemHintArray
Definition: pshints.h:211
FT_Vector prevElemP3
Definition: pshints.h:242
CF2_UInt count
Definition: pshints.h:140

Referenced by cf2_doFlex(), and cf2_interpT2CharString().

◆ cf2_glyphpath_finalize()

cf2_glyphpath_finalize ( CF2_GlyphPath  glyphpath)

Definition at line 1154 of file pshints.c.

1155 {
1156 cf2_arrstack_finalize( &glyphpath->hintMoves );
1157 }
cf2_arrstack_finalize(CF2_ArrStack arrstack)
Definition: psarrst.c:76
CF2_ArrStackRec hintMoves
Definition: pshints.h:193

Referenced by cf2_interpT2CharString().

◆ cf2_glyphpath_hintPoint()

static void cf2_glyphpath_hintPoint ( CF2_GlyphPath  glyphpath,
CF2_HintMap  hintmap,
FT_Vector ppt,
CF2_Fixed  x,
CF2_Fixed  y 
)
static

Definition at line 1167 of file pshints.c.

1172 {
1173 FT_Vector pt; /* hinted point in upright DS */
1174
1175
1176 pt.x = ADD_INT32( FT_MulFix( glyphpath->scaleX, x ),
1177 FT_MulFix( glyphpath->scaleC, y ) );
1178 pt.y = cf2_hintmap_map( hintmap, y );
1179
1180 ppt->x = ADD_INT32(
1181 FT_MulFix( glyphpath->font->outerTransform.a, pt.x ),
1182 ADD_INT32(
1183 FT_MulFix( glyphpath->font->outerTransform.c, pt.y ),
1184 glyphpath->fractionalTranslation.x ) );
1185 ppt->y = ADD_INT32(
1186 FT_MulFix( glyphpath->font->outerTransform.b, pt.x ),
1187 ADD_INT32(
1188 FT_MulFix( glyphpath->font->outerTransform.d, pt.y ),
1189 glyphpath->fractionalTranslation.y ) );
1190 }
#define pt(x, y)
Definition: drawing.c:79
static CF2_Fixed cf2_hintmap_map(CF2_HintMap hintmap, CF2_Fixed csCoord)
Definition: pshints.c:334
CF2_Matrix outerTransform
Definition: psfont.h:78
FT_Vector fractionalTranslation
Definition: pshints.h:199
CF2_Fixed scaleC
Definition: pshints.h:196
CF2_Fixed scaleX
Definition: pshints.h:195
CF2_F16Dot16 c
Definition: psglue.h:80
CF2_F16Dot16 b
Definition: psglue.h:79
CF2_F16Dot16 a
Definition: psglue.h:78
CF2_F16Dot16 d
Definition: psglue.h:81

Referenced by cf2_glyphpath_pushMove(), and cf2_glyphpath_pushPrevElem().

◆ cf2_glyphpath_init()

cf2_glyphpath_init ( CF2_GlyphPath  glyphpath,
CF2_Font  font,
CF2_OutlineCallbacks  callbacks,
CF2_Fixed  scaleY,
CF2_ArrStack  hStemHintArray,
CF2_ArrStack  vStemHintArray,
CF2_HintMask  hintMask,
CF2_Fixed  hintOriginY,
const CF2_Blues  blues,
const FT_Vector fractionalTranslation 
)

Definition at line 1083 of file pshints.c.

1094 {
1095 FT_ZERO( glyphpath );
1096
1097 glyphpath->font = font;
1098 glyphpath->callbacks = callbacks;
1099
1100 cf2_arrstack_init( &glyphpath->hintMoves,
1101 font->memory,
1102 &font->error,
1103 sizeof ( CF2_HintMoveRec ) );
1104
1105 cf2_hintmap_init( &glyphpath->initialHintMap,
1106 font,
1107 &glyphpath->initialHintMap,
1108 &glyphpath->hintMoves,
1109 scaleY );
1110 cf2_hintmap_init( &glyphpath->firstHintMap,
1111 font,
1112 &glyphpath->initialHintMap,
1113 &glyphpath->hintMoves,
1114 scaleY );
1115 cf2_hintmap_init( &glyphpath->hintMap,
1116 font,
1117 &glyphpath->initialHintMap,
1118 &glyphpath->hintMoves,
1119 scaleY );
1120
1121 glyphpath->scaleX = font->innerTransform.a;
1122 glyphpath->scaleC = font->innerTransform.c;
1123 glyphpath->scaleY = font->innerTransform.d;
1124
1125 glyphpath->fractionalTranslation = *fractionalTranslation;
1126
1127#if 0
1128 glyphpath->hShift = hShift; /* for fauxing */
1129#endif
1130
1131 glyphpath->hStemHintArray = hStemHintArray;
1132 glyphpath->vStemHintArray = vStemHintArray;
1133 glyphpath->hintMask = hintMask; /* ptr to current mask */
1134 glyphpath->hintOriginY = hintOriginY;
1135 glyphpath->blues = blues;
1136 glyphpath->darken = font->darkened; /* TODO: should we make copies? */
1137 glyphpath->xOffset = font->darkenX;
1138 glyphpath->yOffset = font->darkenY;
1139 glyphpath->miterLimit = 2 * FT_MAX(
1140 cf2_fixedAbs( glyphpath->xOffset ),
1141 cf2_fixedAbs( glyphpath->yOffset ) );
1142
1143 /* .1 character space unit */
1144 glyphpath->snapThreshold = cf2_doubleToFixed( 0.1 );
1145
1146 glyphpath->moveIsPending = TRUE;
1147 glyphpath->pathIsOpen = FALSE;
1148 glyphpath->pathIsClosing = FALSE;
1149 glyphpath->elemIsQueued = FALSE;
1150 }
#define FT_ZERO(p)
Definition: ftmemory.h:237
#define FT_MAX(a, b)
Definition: ftobjs.h:72
Definition: mk_font.cpp:20
cf2_arrstack_init(CF2_ArrStack arrstack, FT_Memory memory, FT_Error *error, size_t sizeItem)
Definition: psarrst.c:56
cf2_hintmap_init(CF2_HintMap hintmap, CF2_Font font, CF2_HintMap initialMap, CF2_ArrStack hintMoves, CF2_Fixed scale)
Definition: pshints.c:277
CF2_Fixed scaleY
Definition: pshints.h:197
CF2_HintMapRec firstHintMap
Definition: pshints.h:190
CF2_HintMapRec initialHintMap
Definition: pshints.h:191
const CF2_BluesRec * blues
Definition: pshints.h:215
ActualNumberDriverObjects * sizeof(PDRIVER_OBJECT)) PDRIVER_OBJECT *DriverObjectList
static int callbacks
Definition: xmllint.c:838

Referenced by cf2_interpT2CharString().

◆ cf2_glyphpath_lineTo()

cf2_glyphpath_lineTo ( CF2_GlyphPath  glyphpath,
CF2_Fixed  x,
CF2_Fixed  y 
)

Definition at line 1711 of file pshints.c.

1714 {
1716 FT_Vector P0, P1;
1717 FT_Bool newHintMap;
1718
1719 /*
1720 * New hints will be applied after cf2_glyphpath_pushPrevElem has run.
1721 * In case this is a synthesized closing line, any new hints should be
1722 * delayed until this path is closed (`cf2_hintmask_isNew' will be
1723 * called again before the next line or curve).
1724 */
1725
1726 /* true if new hint map not on close */
1727 newHintMap = cf2_hintmask_isNew( glyphpath->hintMask ) &&
1728 !glyphpath->pathIsClosing;
1729
1730 /*
1731 * Zero-length lines may occur in the charstring. Because we cannot
1732 * compute darkening offsets or intersections from zero-length lines,
1733 * it is best to remove them and avoid artifacts. However, zero-length
1734 * lines in CS at the start of a new hint map can generate non-zero
1735 * lines in DS due to hint substitution. We detect a change in hint
1736 * map here and pass those zero-length lines along.
1737 */
1738
1739 /*
1740 * Note: Find explicitly closed paths here with a conditional
1741 * breakpoint using
1742 *
1743 * !gp->pathIsClosing && gp->start.x == x && gp->start.y == y
1744 *
1745 */
1746
1747 if ( glyphpath->currentCS.x == x &&
1748 glyphpath->currentCS.y == y &&
1749 !newHintMap )
1750 /*
1751 * Ignore zero-length lines in CS where the hint map is the same
1752 * because the line in DS will also be zero length.
1753 *
1754 * Ignore zero-length lines when we synthesize a closing line because
1755 * the close will be handled in cf2_glyphPath_pushPrevElem.
1756 */
1757 return;
1758
1759 cf2_glyphpath_computeOffset( glyphpath,
1760 glyphpath->currentCS.x,
1761 glyphpath->currentCS.y,
1762 x,
1763 y,
1764 &xOffset,
1765 &yOffset );
1766
1767 /* construct offset points */
1768 P0.x = ADD_INT32( glyphpath->currentCS.x, xOffset );
1769 P0.y = ADD_INT32( glyphpath->currentCS.y, yOffset );
1770 P1.x = ADD_INT32( x, xOffset );
1771 P1.y = ADD_INT32( y, yOffset );
1772
1773 if ( glyphpath->moveIsPending )
1774 {
1775 /* emit offset 1st point as MoveTo */
1776 cf2_glyphpath_pushMove( glyphpath, P0 );
1777
1778 glyphpath->moveIsPending = FALSE; /* adjust state machine */
1779 glyphpath->pathIsOpen = TRUE;
1780
1781 glyphpath->offsetStart1 = P1; /* record second point */
1782 }
1783
1784 if ( glyphpath->elemIsQueued )
1785 {
1786 FT_ASSERT( cf2_hintmap_isValid( &glyphpath->hintMap ) ||
1787 glyphpath->hintMap.count == 0 );
1788
1789 cf2_glyphpath_pushPrevElem( glyphpath,
1790 &glyphpath->hintMap,
1791 &P0,
1792 P1,
1793 FALSE );
1794 }
1795
1796 /* queue the current element with offset points */
1797 glyphpath->elemIsQueued = TRUE;
1798 glyphpath->prevElemOp = CF2_PathOpLineTo;
1799 glyphpath->prevElemP0 = P0;
1800 glyphpath->prevElemP1 = P1;
1801
1802 /* update current map */
1803 if ( newHintMap )
1804 cf2_hintmap_build( &glyphpath->hintMap,
1805 glyphpath->hStemHintArray,
1806 glyphpath->vStemHintArray,
1807 glyphpath->hintMask,
1808 glyphpath->hintOriginY,
1809 FALSE );
1810
1811 glyphpath->currentCS.x = x; /* pre-offset current point */
1812 glyphpath->currentCS.y = y;
1813 }
int yOffset
Definition: appswitch.c:59
int xOffset
Definition: appswitch.c:59
FT_BEGIN_HEADER typedef unsigned char FT_Bool
Definition: fttypes.h:108
@ CF2_PathOpLineTo
Definition: psglue.h:68

Referenced by cf2_glyphpath_closeOpenPath(), and cf2_interpT2CharString().

◆ cf2_glyphpath_moveTo()

cf2_glyphpath_moveTo ( CF2_GlyphPath  glyphpath,
CF2_Fixed  x,
CF2_Fixed  y 
)

Definition at line 1681 of file pshints.c.

1684 {
1685 cf2_glyphpath_closeOpenPath( glyphpath );
1686
1687 /* save the parameters of the move for later, when we'll know how to */
1688 /* offset it; */
1689 /* also save last move point */
1690 glyphpath->currentCS.x = glyphpath->start.x = x;
1691 glyphpath->currentCS.y = glyphpath->start.y = y;
1692
1693 glyphpath->moveIsPending = TRUE;
1694
1695 /* ensure we have a valid map with current mask */
1696 if ( !cf2_hintmap_isValid( &glyphpath->hintMap ) ||
1697 cf2_hintmask_isNew( glyphpath->hintMask ) )
1698 cf2_hintmap_build( &glyphpath->hintMap,
1699 glyphpath->hStemHintArray,
1700 glyphpath->vStemHintArray,
1701 glyphpath->hintMask,
1702 glyphpath->hintOriginY,
1703 FALSE );
1704
1705 /* save a copy of current HintMap to use when drawing initial point */
1706 glyphpath->firstHintMap = glyphpath->hintMap; /* structure copy */
1707 }
cf2_glyphpath_closeOpenPath(CF2_GlyphPath glyphpath)
Definition: pshints.c:1907

Referenced by cf2_glyphpath_pushMove(), and cf2_interpT2CharString().

◆ cf2_glyphpath_pushMove()

static void cf2_glyphpath_pushMove ( CF2_GlyphPath  glyphpath,
FT_Vector  start 
)
static

Definition at line 1485 of file pshints.c.

1487 {
1489
1490
1492 params.pt0 = glyphpath->currentDS;
1493
1494 /* Test if move has really happened yet; it would have called */
1495 /* `cf2_hintmap_build' to set `isValid'. */
1496 if ( !cf2_hintmap_isValid( &glyphpath->hintMap ) )
1497 {
1498 /* we are here iff first subpath is missing a moveto operator: */
1499 /* synthesize first moveTo to finish initialization of hintMap */
1500 cf2_glyphpath_moveTo( glyphpath,
1501 glyphpath->start.x,
1502 glyphpath->start.y );
1503 }
1504
1505 cf2_glyphpath_hintPoint( glyphpath,
1506 &glyphpath->hintMap,
1507 &params.pt1,
1508 start.x,
1509 start.y );
1510
1511 /* note: pt2 and pt3 are unused */
1512 glyphpath->callbacks->moveTo( glyphpath->callbacks, &params );
1513
1514 glyphpath->currentDS = params.pt1;
1515 glyphpath->offsetStart0 = start;
1516 }
GLuint start
Definition: gl.h:1545
GLenum const GLfloat * params
Definition: glext.h:5645
@ CF2_PathOpMoveTo
Definition: psglue.h:67
cf2_glyphpath_moveTo(CF2_GlyphPath glyphpath, CF2_Fixed x, CF2_Fixed y)
Definition: pshints.c:1681
static void cf2_glyphpath_hintPoint(CF2_GlyphPath glyphpath, CF2_HintMap hintmap, FT_Vector *ppt, CF2_Fixed x, CF2_Fixed y)
Definition: pshints.c:1167
FT_Vector currentDS
Definition: pshints.h:231
CF2_Callback_Type moveTo
Definition: psglue.h:126

Referenced by cf2_glyphpath_curveTo(), and cf2_glyphpath_lineTo().

◆ cf2_glyphpath_pushPrevElem()

static void cf2_glyphpath_pushPrevElem ( CF2_GlyphPath  glyphpath,
CF2_HintMap  hintmap,
FT_Vector nextP0,
FT_Vector  nextP1,
FT_Bool  close 
)
static

Definition at line 1321 of file pshints.c.

1326 {
1328
1329 FT_Vector* prevP0;
1330 FT_Vector* prevP1;
1331
1332 FT_Vector intersection = { 0, 0 };
1333 FT_Bool useIntersection = FALSE;
1334
1335
1336 FT_ASSERT( glyphpath->prevElemOp == CF2_PathOpLineTo ||
1337 glyphpath->prevElemOp == CF2_PathOpCubeTo );
1338
1339 if ( glyphpath->prevElemOp == CF2_PathOpLineTo )
1340 {
1341 prevP0 = &glyphpath->prevElemP0;
1342 prevP1 = &glyphpath->prevElemP1;
1343 }
1344 else
1345 {
1346 prevP0 = &glyphpath->prevElemP2;
1347 prevP1 = &glyphpath->prevElemP3;
1348 }
1349
1350 /* optimization: if previous and next elements are offset by the same */
1351 /* amount, then there will be no gap, and no need to compute an */
1352 /* intersection. */
1353 if ( prevP1->x != nextP0->x || prevP1->y != nextP0->y )
1354 {
1355 /* previous element does not join next element: */
1356 /* adjust end point of previous element to the intersection */
1357 useIntersection = cf2_glyphpath_computeIntersection( glyphpath,
1358 prevP0,
1359 prevP1,
1360 nextP0,
1361 &nextP1,
1362 &intersection );
1363 if ( useIntersection )
1364 {
1365 /* modify the last point of the cached element (either line or */
1366 /* curve) */
1367 *prevP1 = intersection;
1368 }
1369 }
1370
1371 params.pt0 = glyphpath->currentDS;
1372
1373 switch( glyphpath->prevElemOp )
1374 {
1375 case CF2_PathOpLineTo:
1377
1378 /* note: pt2 and pt3 are unused */
1379
1380 if ( close )
1381 {
1382 /* use first hint map if closing */
1383 cf2_glyphpath_hintPoint( glyphpath,
1384 &glyphpath->firstHintMap,
1385 &params.pt1,
1386 glyphpath->prevElemP1.x,
1387 glyphpath->prevElemP1.y );
1388 }
1389 else
1390 {
1391 cf2_glyphpath_hintPoint( glyphpath,
1392 hintmap,
1393 &params.pt1,
1394 glyphpath->prevElemP1.x,
1395 glyphpath->prevElemP1.y );
1396 }
1397
1398 /* output only non-zero length lines */
1399 if ( params.pt0.x != params.pt1.x || params.pt0.y != params.pt1.y )
1400 {
1401 glyphpath->callbacks->lineTo( glyphpath->callbacks, &params );
1402
1403 glyphpath->currentDS = params.pt1;
1404 }
1405 break;
1406
1407 case CF2_PathOpCubeTo:
1409
1410 /* TODO: should we intersect the interior joins (p1-p2 and p2-p3)? */
1411 cf2_glyphpath_hintPoint( glyphpath,
1412 hintmap,
1413 &params.pt1,
1414 glyphpath->prevElemP1.x,
1415 glyphpath->prevElemP1.y );
1416 cf2_glyphpath_hintPoint( glyphpath,
1417 hintmap,
1418 &params.pt2,
1419 glyphpath->prevElemP2.x,
1420 glyphpath->prevElemP2.y );
1421 cf2_glyphpath_hintPoint( glyphpath,
1422 hintmap,
1423 &params.pt3,
1424 glyphpath->prevElemP3.x,
1425 glyphpath->prevElemP3.y );
1426
1427 glyphpath->callbacks->cubeTo( glyphpath->callbacks, &params );
1428
1429 glyphpath->currentDS = params.pt3;
1430
1431 break;
1432 }
1433
1434 if ( !useIntersection || close )
1435 {
1436 /* insert connecting line between end of previous element and start */
1437 /* of current one */
1438 /* note: at the end of a subpath, we might do both, so use `nextP0' */
1439 /* before we change it, below */
1440
1441 if ( close )
1442 {
1443 /* if we are closing the subpath, then nextP0 is in the first */
1444 /* hint zone */
1445 cf2_glyphpath_hintPoint( glyphpath,
1446 &glyphpath->firstHintMap,
1447 &params.pt1,
1448 nextP0->x,
1449 nextP0->y );
1450 }
1451 else
1452 {
1453 cf2_glyphpath_hintPoint( glyphpath,
1454 hintmap,
1455 &params.pt1,
1456 nextP0->x,
1457 nextP0->y );
1458 }
1459
1460 if ( params.pt1.x != glyphpath->currentDS.x ||
1461 params.pt1.y != glyphpath->currentDS.y )
1462 {
1463 /* length is nonzero */
1465 params.pt0 = glyphpath->currentDS;
1466
1467 /* note: pt2 and pt3 are unused */
1468 glyphpath->callbacks->lineTo( glyphpath->callbacks, &params );
1469
1470 glyphpath->currentDS = params.pt1;
1471 }
1472 }
1473
1474 if ( useIntersection )
1475 {
1476 /* return intersection point to caller */
1477 *nextP0 = intersection;
1478 }
1479 }
#define close
Definition: acwin.h:98
static FT_Bool cf2_glyphpath_computeIntersection(CF2_GlyphPath glyphpath, const FT_Vector *u1, const FT_Vector *u2, const FT_Vector *v1, const FT_Vector *v2, FT_Vector *intersection)
Definition: pshints.c:1201
CF2_Callback_Type cubeTo
Definition: psglue.h:129
CF2_Callback_Type lineTo
Definition: psglue.h:127

Referenced by cf2_glyphpath_closeOpenPath(), cf2_glyphpath_curveTo(), and cf2_glyphpath_lineTo().

◆ cf2_hint_init()

static void cf2_hint_init ( CF2_Hint  hint,
const CF2_ArrStack  stemHintArray,
size_t  indexStemHint,
const CF2_Font  font,
CF2_Fixed  hintOrigin,
CF2_Fixed  scale,
FT_Bool  bottom 
)
static

Definition at line 90 of file pshints.c.

97 {
99 const CF2_StemHintRec* stemHint;
100
101
102 FT_ZERO( hint );
103
104 stemHint = (const CF2_StemHintRec*)cf2_arrstack_getPointer(
105 stemHintArray,
106 indexStemHint );
107
108 width = SUB_INT32( stemHint->max, stemHint->min );
109
110 if ( width == cf2_intToFixed( -21 ) )
111 {
112 /* ghost bottom */
113
114 if ( bottom )
115 {
116 hint->csCoord = stemHint->max;
117 hint->flags = CF2_GhostBottom;
118 }
119 else
120 hint->flags = 0;
121 }
122
123 else if ( width == cf2_intToFixed( -20 ) )
124 {
125 /* ghost top */
126
127 if ( bottom )
128 hint->flags = 0;
129 else
130 {
131 hint->csCoord = stemHint->min;
132 hint->flags = CF2_GhostTop;
133 }
134 }
135
136 else if ( width < 0 )
137 {
138 /* inverted pair */
139
140 /*
141 * Hints with negative widths were produced by an early version of a
142 * non-Adobe font tool. The Type 2 spec allows edge (ghost) hints
143 * with negative widths, but says
144 *
145 * All other negative widths have undefined meaning.
146 *
147 * CoolType has a silent workaround that negates the hint width; for
148 * permissive mode, we do the same here.
149 *
150 * Note: Such fonts cannot use ghost hints, but should otherwise work.
151 * Note: Some poor hints in our faux fonts can produce negative
152 * widths at some blends. For example, see a light weight of
153 * `u' in ASerifMM.
154 *
155 */
156 if ( bottom )
157 {
158 hint->csCoord = stemHint->max;
159 hint->flags = CF2_PairBottom;
160 }
161 else
162 {
163 hint->csCoord = stemHint->min;
164 hint->flags = CF2_PairTop;
165 }
166 }
167
168 else
169 {
170 /* normal pair */
171
172 if ( bottom )
173 {
174 hint->csCoord = stemHint->min;
175 hint->flags = CF2_PairBottom;
176 }
177 else
178 {
179 hint->csCoord = stemHint->max;
180 hint->flags = CF2_PairTop;
181 }
182 }
183
184 /* Now that ghost hints have been detected, adjust this edge for */
185 /* darkening. Bottoms are not changed; tops are incremented by twice */
186 /* `darkenY'. */
187 if ( cf2_hint_isTop( hint ) )
188 hint->csCoord = ADD_INT32( hint->csCoord, 2 * font->darkenY );
189
190 hint->csCoord = ADD_INT32( hint->csCoord, hintOrigin );
191 hint->scale = scale;
192 hint->index = indexStemHint; /* index in original stem hint array */
193
194 /* if original stem hint has been used, use the same position */
195 if ( hint->flags != 0 && stemHint->used )
196 {
197 if ( cf2_hint_isTop( hint ) )
198 hint->dsCoord = stemHint->maxDS;
199 else
200 hint->dsCoord = stemHint->minDS;
201
203 }
204 else
205 hint->dsCoord = FT_MulFix( hint->csCoord, scale );
206 }
GLint GLint GLsizei width
Definition: gl.h:1546
GLenum GLenum GLenum GLenum GLenum scale
Definition: glext.h:9032
GLint GLint bottom
Definition: glext.h:7726
cf2_arrstack_getPointer(const CF2_ArrStack arrstack, size_t idx)
Definition: psarrst.c:187
@ CF2_PairTop
Definition: psblues.h:90
@ CF2_PairBottom
Definition: psblues.h:89
@ CF2_GhostTop
Definition: psblues.h:88
@ CF2_GhostBottom
Definition: psblues.h:87
#define cf2_intToFixed(i)
Definition: psfixed.h:60
cf2_hint_isTop(const CF2_Hint hint)
Definition: pshints.c:240
cf2_hint_lock(CF2_Hint hint)
Definition: pshints.c:270
CF2_Fixed maxDS
Definition: pshints.h:93
CF2_Fixed min
Definition: pshints.h:89
CF2_Fixed max
Definition: pshints.h:90
FT_Bool used
Definition: pshints.h:87
CF2_Fixed minDS
Definition: pshints.h:92
DWORD hint
Definition: vfdcmd.c:88

Referenced by cf2_hintmap_build().

◆ cf2_hint_initZero()

static void cf2_hint_initZero ( CF2_Hint  hint)
static

Definition at line 211 of file pshints.c.

212 {
213 FT_ZERO( hint );
214 }

Referenced by cf2_hintmap_build().

◆ cf2_hint_isBottom()

cf2_hint_isBottom ( const CF2_Hint  hint)

Definition at line 248 of file pshints.c.

249 {
250 return (FT_Bool)( ( hint->flags &
251 ( CF2_PairBottom | CF2_GhostBottom ) ) != 0 );
252 }

Referenced by cf2_blues_capture().

◆ cf2_hint_isLocked()

static FT_Bool cf2_hint_isLocked ( const CF2_Hint  hint)
static

Definition at line 256 of file pshints.c.

257 {
258 return (FT_Bool)( ( hint->flags & CF2_Locked ) != 0 );
259 }
@ CF2_Locked
Definition: psblues.h:91

Referenced by cf2_hintmap_adjustHints(), cf2_hintmap_build(), cf2_hintmap_dump(), and cf2_hintmap_insertHint().

◆ cf2_hint_isPair()

static FT_Bool cf2_hint_isPair ( const CF2_Hint  hint)
static

Definition at line 225 of file pshints.c.

226 {
227 return (FT_Bool)( ( hint->flags &
228 ( CF2_PairBottom | CF2_PairTop ) ) != 0 );
229 }

Referenced by cf2_hintmap_adjustHints(), and cf2_hintmap_dump().

◆ cf2_hint_isPairTop()

static FT_Bool cf2_hint_isPairTop ( const CF2_Hint  hint)
static

Definition at line 233 of file pshints.c.

234 {
235 return (FT_Bool)( ( hint->flags & CF2_PairTop ) != 0 );
236 }

Referenced by cf2_hintmap_insertHint().

◆ cf2_hint_isSynthetic()

static FT_Bool cf2_hint_isSynthetic ( const CF2_Hint  hint)
static

Definition at line 263 of file pshints.c.

264 {
265 return (FT_Bool)( ( hint->flags & CF2_Synthetic ) != 0 );
266 }
@ CF2_Synthetic
Definition: psblues.h:93

Referenced by cf2_hintmap_adjustHints(), cf2_hintmap_build(), and cf2_hintmap_dump().

◆ cf2_hint_isTop()

cf2_hint_isTop ( const CF2_Hint  hint)

Definition at line 240 of file pshints.c.

241 {
242 return (FT_Bool)( ( hint->flags &
243 ( CF2_PairTop | CF2_GhostTop ) ) != 0 );
244 }

Referenced by cf2_blues_capture(), cf2_hint_init(), cf2_hintmap_build(), and cf2_hintmap_dump().

◆ cf2_hint_isValid()

cf2_hint_isValid ( const CF2_Hint  hint)

Definition at line 218 of file pshints.c.

219 {
220 return (FT_Bool)( hint->flags != 0 );
221 }

Referenced by cf2_blues_capture(), cf2_hintmap_adjustHints(), and cf2_hintmap_insertHint().

◆ cf2_hint_lock()

cf2_hint_lock ( CF2_Hint  hint)

Definition at line 270 of file pshints.c.

271 {
272 hint->flags |= CF2_Locked;
273 }

Referenced by cf2_blues_capture(), and cf2_hint_init().

◆ cf2_hintmap_adjustHints()

static void cf2_hintmap_adjustHints ( CF2_HintMap  hintmap)
static

Definition at line 399 of file pshints.c.

400 {
401 size_t i, j;
402
403
404 cf2_arrstack_clear( hintmap->hintMoves ); /* working storage */
405
406 /*
407 * First pass is bottom-up (font hint order) without look-ahead.
408 * Locked edges are already adjusted.
409 * Unlocked edges begin with dsCoord from `initialHintMap'.
410 * Save edges that are not optimally adjusted in `hintMoves' array,
411 * and process them in second pass.
412 */
413
414 for ( i = 0; i < hintmap->count; i++ )
415 {
416 FT_Bool isPair = cf2_hint_isPair( &hintmap->edge[i] );
417
418
419 /* index of upper edge (same value for ghost hint) */
420 j = isPair ? i + 1 : i;
421
422 FT_ASSERT( j < hintmap->count );
423 FT_ASSERT( cf2_hint_isValid( &hintmap->edge[i] ) );
424 FT_ASSERT( cf2_hint_isValid( &hintmap->edge[j] ) );
425 FT_ASSERT( cf2_hint_isLocked( &hintmap->edge[i] ) ==
426 cf2_hint_isLocked( &hintmap->edge[j] ) );
427
428 if ( !cf2_hint_isLocked( &hintmap->edge[i] ) )
429 {
430 /* hint edge is not locked, we can adjust it */
431 CF2_Fixed fracDown = cf2_fixedFraction( hintmap->edge[i].dsCoord );
432 CF2_Fixed fracUp = cf2_fixedFraction( hintmap->edge[j].dsCoord );
433
434 /* calculate all four possibilities; moves down are negative */
435 CF2_Fixed downMoveDown = 0 - fracDown;
436 CF2_Fixed upMoveDown = 0 - fracUp;
437 CF2_Fixed downMoveUp = ( fracDown == 0 )
438 ? 0
439 : cf2_intToFixed( 1 ) - fracDown;
440 CF2_Fixed upMoveUp = ( fracUp == 0 )
441 ? 0
442 : cf2_intToFixed( 1 ) - fracUp;
443
444 /* smallest move up */
445 CF2_Fixed moveUp = FT_MIN( downMoveUp, upMoveUp );
446 /* smallest move down */
447 CF2_Fixed moveDown = FT_MAX( downMoveDown, upMoveDown );
448
449 /* final amount to move edge or edge pair */
450 CF2_Fixed move;
451
452 CF2_Fixed downMinCounter = CF2_MIN_COUNTER;
453 CF2_Fixed upMinCounter = CF2_MIN_COUNTER;
454 FT_Bool saveEdge = FALSE;
455
456
457 /* minimum counter constraint doesn't apply when adjacent edges */
458 /* are synthetic */
459 /* TODO: doesn't seem a big effect; for now, reduce the code */
460#if 0
461 if ( i == 0 ||
462 cf2_hint_isSynthetic( &hintmap->edge[i - 1] ) )
463 downMinCounter = 0;
464
465 if ( j >= hintmap->count - 1 ||
466 cf2_hint_isSynthetic( &hintmap->edge[j + 1] ) )
467 upMinCounter = 0;
468#endif
469
470 /* is there room to move up? */
471 /* there is if we are at top of array or the next edge is at or */
472 /* beyond proposed move up? */
473 if ( j >= hintmap->count - 1 ||
474 hintmap->edge[j + 1].dsCoord >=
475 ADD_INT32( hintmap->edge[j].dsCoord,
476 moveUp + upMinCounter ) )
477 {
478 /* there is room to move up; is there also room to move down? */
479 if ( i == 0 ||
480 hintmap->edge[i - 1].dsCoord <=
481 ADD_INT32( hintmap->edge[i].dsCoord,
482 moveDown - downMinCounter ) )
483 {
484 /* move smaller absolute amount */
485 move = ( -moveDown < moveUp ) ? moveDown : moveUp; /* optimum */
486 }
487 else
488 move = moveUp;
489 }
490 else
491 {
492 /* is there room to move down? */
493 if ( i == 0 ||
494 hintmap->edge[i - 1].dsCoord <=
495 ADD_INT32( hintmap->edge[i].dsCoord,
496 moveDown - downMinCounter ) )
497 {
498 move = moveDown;
499 /* true if non-optimum move */
500 saveEdge = (FT_Bool)( moveUp < -moveDown );
501 }
502 else
503 {
504 /* no room to move either way without overlapping or reducing */
505 /* the counter too much */
506 move = 0;
507 saveEdge = TRUE;
508 }
509 }
510
511 /* Identify non-moves and moves down that aren't optimal, and save */
512 /* them for second pass. */
513 /* Do this only if there is an unlocked edge above (which could */
514 /* possibly move). */
515 if ( saveEdge &&
516 j < hintmap->count - 1 &&
517 !cf2_hint_isLocked( &hintmap->edge[j + 1] ) )
518 {
519 CF2_HintMoveRec savedMove;
520
521
522 savedMove.j = j;
523 /* desired adjustment in second pass */
524 savedMove.moveUp = moveUp - move;
525
526 cf2_arrstack_push( hintmap->hintMoves, &savedMove );
527 }
528
529 /* move the edge(s) */
530 hintmap->edge[i].dsCoord = ADD_INT32( hintmap->edge[i].dsCoord,
531 move );
532 if ( isPair )
533 hintmap->edge[j].dsCoord = ADD_INT32( hintmap->edge[j].dsCoord,
534 move );
535 }
536
537 /* assert there are no overlaps in device space */
538 FT_ASSERT( i == 0 ||
539 hintmap->edge[i - 1].dsCoord <= hintmap->edge[i].dsCoord );
540 FT_ASSERT( i < j ||
541 hintmap->edge[i].dsCoord <= hintmap->edge[j].dsCoord );
542
543 /* adjust the scales, avoiding divide by zero */
544 if ( i > 0 )
545 {
546 if ( hintmap->edge[i].csCoord != hintmap->edge[i - 1].csCoord )
547 hintmap->edge[i - 1].scale =
548 FT_DivFix( SUB_INT32( hintmap->edge[i].dsCoord,
549 hintmap->edge[i - 1].dsCoord ),
550 SUB_INT32( hintmap->edge[i].csCoord,
551 hintmap->edge[i - 1].csCoord ) );
552 }
553
554 if ( isPair )
555 {
556 if ( hintmap->edge[j].csCoord != hintmap->edge[j - 1].csCoord )
557 hintmap->edge[j - 1].scale =
558 FT_DivFix( SUB_INT32( hintmap->edge[j].dsCoord,
559 hintmap->edge[j - 1].dsCoord ),
560 SUB_INT32( hintmap->edge[j].csCoord,
561 hintmap->edge[j - 1].csCoord ) );
562
563 i += 1; /* skip upper edge on next loop */
564 }
565 }
566
567 /* second pass tries to move non-optimal hints up, in case there is */
568 /* room now */
569 for ( i = cf2_arrstack_size( hintmap->hintMoves ); i > 0; i-- )
570 {
571 CF2_HintMove hintMove = (CF2_HintMove)
572 cf2_arrstack_getPointer( hintmap->hintMoves, i - 1 );
573
574
575 j = hintMove->j;
576
577 /* this was tested before the push, above */
578 FT_ASSERT( j < hintmap->count - 1 );
579
580 /* is there room to move up? */
581 if ( hintmap->edge[j + 1].dsCoord >=
582 ADD_INT32( hintmap->edge[j].dsCoord,
583 hintMove->moveUp + CF2_MIN_COUNTER ) )
584 {
585 /* there is more room now, move edge up */
586 hintmap->edge[j].dsCoord = ADD_INT32( hintmap->edge[j].dsCoord,
587 hintMove->moveUp );
588
589 if ( cf2_hint_isPair( &hintmap->edge[j] ) )
590 {
591 FT_ASSERT( j > 0 );
592 hintmap->edge[j - 1].dsCoord =
593 ADD_INT32( hintmap->edge[j - 1].dsCoord, hintMove->moveUp );
594 }
595 }
596 }
597 }
#define FT_MIN(a, b)
Definition: ftobjs.h:71
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
cf2_arrstack_push(CF2_ArrStack arrstack, const void *ptr)
Definition: psarrst.c:212
cf2_arrstack_clear(CF2_ArrStack arrstack)
Definition: psarrst.c:158
cf2_arrstack_size(const CF2_ArrStack arrstack)
Definition: psarrst.c:168
#define CF2_MIN_COUNTER
Definition: psblues.h:114
#define cf2_fixedFraction(x)
Definition: psfixed.h:72
static FT_Bool cf2_hint_isLocked(const CF2_Hint hint)
Definition: pshints.c:256
static FT_Bool cf2_hint_isSynthetic(const CF2_Hint hint)
Definition: pshints.c:263
struct CF2_HintMoveRec_ * CF2_HintMove
cf2_hint_isValid(const CF2_Hint hint)
Definition: pshints.c:218
static FT_Bool cf2_hint_isPair(const CF2_Hint hint)
Definition: pshints.c:225
CF2_ArrStack hintMoves
Definition: pshints.h:134
CF2_HintRec edge[CF2_MAX_HINT_EDGES]
Definition: pshints.h:145
CF2_Fixed moveUp
Definition: pshints.c:61
CF2_Fixed scale
Definition: psblues.h:125
CF2_Fixed csCoord
Definition: psblues.h:123
CF2_Fixed dsCoord
Definition: psblues.h:124

Referenced by cf2_hintmap_build().

◆ cf2_hintmap_build()

cf2_hintmap_build ( CF2_HintMap  hintmap,
CF2_ArrStack  hStemHintArray,
CF2_ArrStack  vStemHintArray,
CF2_HintMask  hintMask,
CF2_Fixed  hintOrigin,
FT_Bool  initialMap 
)

Definition at line 808 of file pshints.c.

814 {
815 FT_Byte* maskPtr;
816
817 CF2_Font font = hintmap->font;
818 CF2_HintMaskRec tempHintMask;
819
820 size_t bitCount, i;
821 FT_Byte maskByte;
822
823
824 /* check whether initial map is constructed */
825 if ( !initialMap && !cf2_hintmap_isValid( hintmap->initialHintMap ) )
826 {
827 /* make recursive call with initialHintMap and temporary mask; */
828 /* temporary mask will get all bits set, below */
829 cf2_hintmask_init( &tempHintMask, hintMask->error );
831 hStemHintArray,
832 vStemHintArray,
833 &tempHintMask,
834 hintOrigin,
835 TRUE );
836 }
837
838 if ( !cf2_hintmask_isValid( hintMask ) )
839 {
840 /* without a hint mask, assume all hints are active */
841 cf2_hintmask_setAll( hintMask,
842 cf2_arrstack_size( hStemHintArray ) +
843 cf2_arrstack_size( vStemHintArray ) );
844 if ( !cf2_hintmask_isValid( hintMask ) )
845 {
846 if ( font->isT1 )
847 {
848 /* no error, just continue unhinted */
849 *hintMask->error = FT_Err_Ok;
850 hintmap->hinted = FALSE;
851 }
852 return; /* too many stem hints */
853 }
854 }
855
856 /* begin by clearing the map */
857 hintmap->count = 0;
858 hintmap->lastIndex = 0;
859
860 /* make a copy of the hint mask so we can modify it */
861 tempHintMask = *hintMask;
862 maskPtr = cf2_hintmask_getMaskPtr( &tempHintMask );
863
864 /* use the hStem hints only, which are first in the mask */
865 bitCount = cf2_arrstack_size( hStemHintArray );
866
867 /* Defense-in-depth. Should never return here. */
868 if ( bitCount > hintMask->bitCount )
869 return;
870
871 /* synthetic embox hints get highest priority */
872 if ( font->blues.doEmBoxHints )
873 {
875
876
877 cf2_hint_initZero( &dummy ); /* invalid hint map element */
878
879 /* ghost bottom */
880 cf2_hintmap_insertHint( hintmap,
881 &font->blues.emBoxBottomEdge,
882 &dummy );
883 /* ghost top */
884 cf2_hintmap_insertHint( hintmap,
885 &dummy,
886 &font->blues.emBoxTopEdge );
887 }
888
889 /* insert hints captured by a blue zone or already locked (higher */
890 /* priority) */
891 for ( i = 0, maskByte = 0x80; i < bitCount; i++ )
892 {
893 if ( maskByte & *maskPtr )
894 {
895 /* expand StemHint into two `CF2_Hint' elements */
896 CF2_HintRec bottomHintEdge, topHintEdge;
897
898
899 cf2_hint_init( &bottomHintEdge,
900 hStemHintArray,
901 i,
902 font,
903 hintOrigin,
904 hintmap->scale,
905 TRUE /* bottom */ );
906 cf2_hint_init( &topHintEdge,
907 hStemHintArray,
908 i,
909 font,
910 hintOrigin,
911 hintmap->scale,
912 FALSE /* top */ );
913
914 if ( cf2_hint_isLocked( &bottomHintEdge ) ||
915 cf2_hint_isLocked( &topHintEdge ) ||
916 cf2_blues_capture( &font->blues,
917 &bottomHintEdge,
918 &topHintEdge ) )
919 {
920 /* insert captured hint into map */
921 cf2_hintmap_insertHint( hintmap, &bottomHintEdge, &topHintEdge );
922
923 *maskPtr &= ~maskByte; /* turn off the bit for this hint */
924 }
925 }
926
927 if ( ( i & 7 ) == 7 )
928 {
929 /* move to next mask byte */
930 maskPtr++;
931 maskByte = 0x80;
932 }
933 else
934 maskByte >>= 1;
935 }
936
937 /* initial hint map includes only captured hints plus maybe one at 0 */
938
939 /*
940 * TODO: There is a problem here because we are trying to build a
941 * single hint map containing all captured hints. It is
942 * possible for there to be conflicts between captured hints,
943 * either because of darkening or because the hints are in
944 * separate hint zones (we are ignoring hint zones for the
945 * initial map). An example of the latter is MinionPro-Regular
946 * v2.030 glyph 883 (Greek Capital Alpha with Psili) at 15ppem.
947 * A stem hint for the psili conflicts with the top edge hint
948 * for the base character. The stem hint gets priority because
949 * of its sort order. In glyph 884 (Greek Capital Alpha with
950 * Psili and Oxia), the top of the base character gets a stem
951 * hint, and the psili does not. This creates different initial
952 * maps for the two glyphs resulting in different renderings of
953 * the base character. Will probably defer this either as not
954 * worth the cost or as a font bug. I don't think there is any
955 * good reason for an accent to be captured by an alignment
956 * zone. -darnold 2/12/10
957 */
958
959 if ( initialMap )
960 {
961 /* Apply a heuristic that inserts a point for (0,0), unless it's */
962 /* already covered by a mapping. This locks the baseline for glyphs */
963 /* that have no baseline hints. */
964
965 if ( hintmap->count == 0 ||
966 hintmap->edge[0].csCoord > 0 ||
967 hintmap->edge[hintmap->count - 1].csCoord < 0 )
968 {
969 /* all edges are above 0 or all edges are below 0; */
970 /* construct a locked edge hint at 0 */
971
972 CF2_HintRec edge, invalid;
973
974
975 cf2_hint_initZero( &edge );
976
977 edge.flags = CF2_GhostBottom |
978 CF2_Locked |
980 edge.scale = hintmap->scale;
981
983 cf2_hintmap_insertHint( hintmap, &edge, &invalid );
984 }
985 }
986 else
987 {
988 /* insert remaining hints */
989
990 maskPtr = cf2_hintmask_getMaskPtr( &tempHintMask );
991
992 for ( i = 0, maskByte = 0x80; i < bitCount; i++ )
993 {
994 if ( maskByte & *maskPtr )
995 {
996 CF2_HintRec bottomHintEdge, topHintEdge;
997
998
999 cf2_hint_init( &bottomHintEdge,
1000 hStemHintArray,
1001 i,
1002 font,
1003 hintOrigin,
1004 hintmap->scale,
1005 TRUE /* bottom */ );
1006 cf2_hint_init( &topHintEdge,
1007 hStemHintArray,
1008 i,
1009 font,
1010 hintOrigin,
1011 hintmap->scale,
1012 FALSE /* top */ );
1013
1014 cf2_hintmap_insertHint( hintmap, &bottomHintEdge, &topHintEdge );
1015 }
1016
1017 if ( ( i & 7 ) == 7 )
1018 {
1019 /* move to next mask byte */
1020 maskPtr++;
1021 maskByte = 0x80;
1022 }
1023 else
1024 maskByte >>= 1;
1025 }
1026 }
1027
1028 FT_TRACE6(( initialMap ? "flags: [p]air [g]host [t]op "
1029 "[b]ottom [L]ocked [S]ynthetic\n"
1030 "Initial hintmap\n"
1031 : "Hints:\n" ));
1032 cf2_hintmap_dump( hintmap );
1033
1034 /*
1035 * Note: The following line is a convenient place to break when
1036 * debugging hinting. Examine `hintmap->edge' for the list of
1037 * enabled hints, then step over the call to see the effect of
1038 * adjustment. We stop here first on the recursive call that
1039 * creates the initial map, and then on each counter group and
1040 * hint zone.
1041 */
1042
1043 /* adjust positions of hint edges that are not locked to blue zones */
1044 cf2_hintmap_adjustHints( hintmap );
1045
1046 FT_TRACE6(( "(adjusted)\n" ));
1047 cf2_hintmap_dump( hintmap );
1048
1049 /* save the position of all hints that were used in this hint map; */
1050 /* if we use them again, we'll locate them in the same position */
1051 if ( !initialMap )
1052 {
1053 for ( i = 0; i < hintmap->count; i++ )
1054 {
1055 if ( !cf2_hint_isSynthetic( &hintmap->edge[i] ) )
1056 {
1057 /* Note: include both valid and invalid edges */
1058 /* Note: top and bottom edges are copied back separately */
1059 CF2_StemHint stemhint = (CF2_StemHint)
1060 cf2_arrstack_getPointer( hStemHintArray,
1061 hintmap->edge[i].index );
1062
1063
1064 if ( cf2_hint_isTop( &hintmap->edge[i] ) )
1065 stemhint->maxDS = hintmap->edge[i].dsCoord;
1066 else
1067 stemhint->minDS = hintmap->edge[i].dsCoord;
1068
1069 stemhint->used = TRUE;
1070 }
1071 }
1072 }
1073
1074 /* hint map is ready to use */
1075 hintmap->isValid = TRUE;
1076
1077 /* remember this mask has been used */
1078 cf2_hintmask_setNew( hintMask, FALSE );
1079 }
return FT_Err_Ok
Definition: ftbbox.c:511
#define FT_TRACE6(varformat)
Definition: ftdebug.h:163
unsigned char FT_Byte
Definition: fttypes.h:154
static const WCHAR invalid[]
Definition: assoc.c:39
cf2_blues_capture(const CF2_Blues blues, CF2_Hint bottomHintEdge, CF2_Hint topHintEdge)
Definition: psblues.c:465
static void cf2_hintmap_adjustHints(CF2_HintMap hintmap)
Definition: pshints.c:399
static void cf2_hint_init(CF2_Hint hint, const CF2_ArrStack stemHintArray, size_t indexStemHint, const CF2_Font font, CF2_Fixed hintOrigin, CF2_Fixed scale, FT_Bool bottom)
Definition: pshints.c:90
static void cf2_hintmap_dump(CF2_HintMap hintmap)
Definition: pshints.c:303
static void cf2_hint_initZero(CF2_Hint hint)
Definition: pshints.c:211
static void cf2_hintmap_insertHint(CF2_HintMap hintmap, CF2_Hint bottomHintEdge, CF2_Hint topHintEdge)
Definition: pshints.c:602
cf2_hintmask_getMaskPtr(CF2_HintMask hintmask)
Definition: psintrp.c:101
cf2_hintmask_setAll(CF2_HintMask hintmask, size_t bitCount)
Definition: psintrp.c:173
cf2_hintmask_isValid(const CF2_HintMask hintmask)
Definition: psintrp.c:76
cf2_hintmask_init(CF2_HintMask hintmask, FT_Error *error)
Definition: psintrp.c:66
cf2_hintmask_setNew(CF2_HintMask hintmask, FT_Bool val)
Definition: psintrp.c:90
struct CF2_StemHintRec_ * CF2_StemHint
FT_Bool isValid
Definition: pshints.h:136
CF2_UInt lastIndex
Definition: pshints.h:143
struct CF2_HintMapRec_ * initialHintMap
Definition: pshints.h:131
FT_Bool hinted
Definition: pshints.h:137
CF2_Fixed scale
Definition: pshints.h:139
CF2_Font font
Definition: pshints.h:128
FT_Error * error
Definition: pshints.h:72
size_t bitCount
Definition: pshints.h:77
size_t index
Definition: psblues.h:121
CF2_UInt flags
Definition: psblues.h:120

Referenced by cf2_glyphpath_curveTo(), cf2_glyphpath_lineTo(), cf2_glyphpath_moveTo(), cf2_hintmap_build(), and cf2_interpT2CharString().

◆ cf2_hintmap_dump()

static void cf2_hintmap_dump ( CF2_HintMap  hintmap)
static

Definition at line 303 of file pshints.c.

304 {
305#ifdef FT_DEBUG_LEVEL_TRACE
306 CF2_UInt i;
307
308
309 FT_TRACE6(( " index csCoord dsCoord scale flags\n" ));
310
311 for ( i = 0; i < hintmap->count; i++ )
312 {
313 CF2_Hint hint = &hintmap->edge[i];
314
315
316 FT_TRACE6(( " %3d %7.2f %7.2f %5d %s%s%s%s\n",
317 hint->index,
318 hint->csCoord / 65536.0,
319 hint->dsCoord / ( hint->scale * 1.0 ),
320 hint->scale,
321 ( cf2_hint_isPair( hint ) ? "p" : "g" ),
322 ( cf2_hint_isTop( hint ) ? "t" : "b" ),
323 ( cf2_hint_isLocked( hint ) ? "L" : ""),
324 ( cf2_hint_isSynthetic( hint ) ? "S" : "" ) ));
325 }
326#else
327 FT_UNUSED( hintmap );
328#endif
329 }
#define FT_UNUSED(arg)
Definition: ftconfig.h:101
#define CF2_UInt
Definition: pstypes.h:64

Referenced by cf2_hintmap_build().

◆ cf2_hintmap_init()

cf2_hintmap_init ( CF2_HintMap  hintmap,
CF2_Font  font,
CF2_HintMap  initialMap,
CF2_ArrStack  hintMoves,
CF2_Fixed  scale 
)

Definition at line 277 of file pshints.c.

282 {
283 FT_ZERO( hintmap );
284
285 /* copy parameters from font instance */
286 hintmap->hinted = font->hinted;
287 hintmap->scale = scale;
288 hintmap->font = font;
289 hintmap->initialHintMap = initialMap;
290 /* will clear in `cf2_hintmap_adjustHints' */
291 hintmap->hintMoves = hintMoves;
292 }

Referenced by cf2_glyphpath_init(), and cf2_interpT2CharString().

◆ cf2_hintmap_insertHint()

static void cf2_hintmap_insertHint ( CF2_HintMap  hintmap,
CF2_Hint  bottomHintEdge,
CF2_Hint  topHintEdge 
)
static

Definition at line 602 of file pshints.c.

605 {
606 CF2_UInt indexInsert;
607
608 /* set default values, then check for edge hints */
609 FT_Bool isPair = TRUE;
610 CF2_Hint firstHintEdge = bottomHintEdge;
611 CF2_Hint secondHintEdge = topHintEdge;
612
613
614 /* one or none of the input params may be invalid when dealing with */
615 /* edge hints; at least one edge must be valid */
616 FT_ASSERT( cf2_hint_isValid( bottomHintEdge ) ||
617 cf2_hint_isValid( topHintEdge ) );
618
619 /* determine how many and which edges to insert */
620 if ( !cf2_hint_isValid( bottomHintEdge ) )
621 {
622 /* insert only the top edge */
623 firstHintEdge = topHintEdge;
624 isPair = FALSE;
625 }
626 else if ( !cf2_hint_isValid( topHintEdge ) )
627 {
628 /* insert only the bottom edge */
629 isPair = FALSE;
630 }
631
632 /* paired edges must be in proper order */
633 if ( isPair &&
634 topHintEdge->csCoord < bottomHintEdge->csCoord )
635 return;
636
637 /* linear search to find index value of insertion point */
638 indexInsert = 0;
639 for ( ; indexInsert < hintmap->count; indexInsert++ )
640 {
641 if ( hintmap->edge[indexInsert].csCoord >= firstHintEdge->csCoord )
642 break;
643 }
644
645 FT_TRACE7(( " Got hint at %.2f (%.2f)\n",
646 firstHintEdge->csCoord / 65536.0,
647 firstHintEdge->dsCoord / 65536.0 ));
648 if ( isPair )
649 FT_TRACE7(( " Got hint at %.2f (%.2f)\n",
650 secondHintEdge->csCoord / 65536.0,
651 secondHintEdge->dsCoord / 65536.0 ));
652
653 /*
654 * Discard any hints that overlap in character space. Most often, this
655 * is while building the initial map, where captured hints from all
656 * zones are combined. Define overlap to include hints that `touch'
657 * (overlap zero). Hiragino Sans/Gothic fonts have numerous hints that
658 * touch. Some fonts have non-ideographic glyphs that overlap our
659 * synthetic hints.
660 *
661 * Overlap also occurs when darkening stem hints that are close.
662 *
663 */
664 if ( indexInsert < hintmap->count )
665 {
666 /* we are inserting before an existing edge: */
667 /* verify that an existing edge is not the same */
668 if ( hintmap->edge[indexInsert].csCoord == firstHintEdge->csCoord )
669 return; /* ignore overlapping stem hint */
670
671 /* verify that a new pair does not straddle the next edge */
672 if ( isPair &&
673 hintmap->edge[indexInsert].csCoord <= secondHintEdge->csCoord )
674 return; /* ignore overlapping stem hint */
675
676 /* verify that we are not inserting between paired edges */
677 if ( cf2_hint_isPairTop( &hintmap->edge[indexInsert] ) )
678 return; /* ignore overlapping stem hint */
679 }
680
681 /* recompute device space locations using initial hint map */
682 if ( cf2_hintmap_isValid( hintmap->initialHintMap ) &&
683 !cf2_hint_isLocked( firstHintEdge ) )
684 {
685 if ( isPair )
686 {
687 /* Use hint map to position the center of stem, and nominal scale */
688 /* to position the two edges. This preserves the stem width. */
689 CF2_Fixed midpoint =
691 hintmap->initialHintMap,
692 ADD_INT32( secondHintEdge->csCoord,
693 firstHintEdge->csCoord ) / 2 );
694 CF2_Fixed halfWidth =
695 FT_MulFix( SUB_INT32( secondHintEdge->csCoord,
696 firstHintEdge->csCoord ) / 2,
697 hintmap->scale );
698
699
700 firstHintEdge->dsCoord = SUB_INT32( midpoint, halfWidth );
701 secondHintEdge->dsCoord = ADD_INT32( midpoint, halfWidth );
702 }
703 else
704 firstHintEdge->dsCoord = cf2_hintmap_map( hintmap->initialHintMap,
705 firstHintEdge->csCoord );
706 }
707
708 /*
709 * Discard any hints that overlap in device space; this can occur
710 * because locked hints have been moved to align with blue zones.
711 *
712 * TODO: Although we might correct this later during adjustment, we
713 * don't currently have a way to delete a conflicting hint once it has
714 * been inserted. See v2.030 MinionPro-Regular, 12 ppem darkened,
715 * initial hint map for second path, glyph 945 (the perispomeni (tilde)
716 * in U+1F6E, Greek omega with psili and perispomeni). Darkening is
717 * 25. Pair 667,747 initially conflicts in design space with top edge
718 * 660. This is because 667 maps to 7.87, and the top edge was
719 * captured by a zone at 8.0. The pair is later successfully inserted
720 * in a zone without the top edge. In this zone it is adjusted to 8.0,
721 * and no longer conflicts with the top edge in design space. This
722 * means it can be included in yet a later zone which does have the top
723 * edge hint. This produces a small mismatch between the first and
724 * last points of this path, even though the hint masks are the same.
725 * The density map difference is tiny (1/256).
726 *
727 */
728
729 if ( indexInsert > 0 )
730 {
731 /* we are inserting after an existing edge */
732 if ( firstHintEdge->dsCoord < hintmap->edge[indexInsert - 1].dsCoord )
733 return;
734 }
735
736 if ( indexInsert < hintmap->count )
737 {
738 /* we are inserting before an existing edge */
739 if ( isPair )
740 {
741 if ( secondHintEdge->dsCoord > hintmap->edge[indexInsert].dsCoord )
742 return;
743 }
744 else
745 {
746 if ( firstHintEdge->dsCoord > hintmap->edge[indexInsert].dsCoord )
747 return;
748 }
749 }
750
751 /* make room to insert */
752 {
753 CF2_UInt iSrc = hintmap->count - 1;
754 CF2_UInt iDst = isPair ? hintmap->count + 1 : hintmap->count;
755
756 CF2_UInt count = hintmap->count - indexInsert;
757
758
759 if ( iDst >= CF2_MAX_HINT_EDGES )
760 {
761 FT_TRACE4(( "cf2_hintmap_insertHint: too many hintmaps\n" ));
762 return;
763 }
764
765 while ( count-- )
766 hintmap->edge[iDst--] = hintmap->edge[iSrc--];
767
768 /* insert first edge */
769 hintmap->edge[indexInsert] = *firstHintEdge; /* copy struct */
770 hintmap->count += 1;
771
772 FT_TRACE7(( " Inserting hint %.2f (%.2f)\n",
773 firstHintEdge->csCoord / 65536.0,
774 firstHintEdge->dsCoord / 65536.0 ));
775
776 if ( isPair )
777 {
778 /* insert second edge */
779 hintmap->edge[indexInsert + 1] = *secondHintEdge; /* copy struct */
780 hintmap->count += 1;
781
782 FT_TRACE7(( " Inserting hint %.2f (%.2f)\n",
783 secondHintEdge->csCoord / 65536.0,
784 secondHintEdge->dsCoord / 65536.0 ));
785
786 }
787 }
788
789 return;
790 }
#define FT_TRACE7(varformat)
Definition: ftdebug.h:164
#define FT_TRACE4(varformat)
Definition: ftdebug.h:161
static FT_Bool cf2_hint_isPairTop(const CF2_Hint hint)
Definition: pshints.c:233
@ CF2_MAX_HINT_EDGES
Definition: pshints.h:122

Referenced by cf2_hintmap_build().

◆ cf2_hintmap_isValid()

static FT_Bool cf2_hintmap_isValid ( const CF2_HintMap  hintmap)
static

◆ cf2_hintmap_map()

static CF2_Fixed cf2_hintmap_map ( CF2_HintMap  hintmap,
CF2_Fixed  csCoord 
)
static

Definition at line 334 of file pshints.c.

336 {
337 if ( hintmap->count == 0 || ! hintmap->hinted )
338 {
339 /* there are no hints; use uniform scale and zero offset */
340 return FT_MulFix( csCoord, hintmap->scale );
341 }
342 else
343 {
344 /* start linear search from last hit */
345 CF2_UInt i = hintmap->lastIndex;
346
347
349
350 /* search up */
351 while ( i < hintmap->count - 1 &&
352 csCoord >= hintmap->edge[i + 1].csCoord )
353 i += 1;
354
355 /* search down */
356 while ( i > 0 && csCoord < hintmap->edge[i].csCoord )
357 i -= 1;
358
359 hintmap->lastIndex = i;
360
361 if ( i == 0 && csCoord < hintmap->edge[0].csCoord )
362 {
363 /* special case for points below first edge: use uniform scale */
364 return ADD_INT32( FT_MulFix( SUB_INT32( csCoord,
365 hintmap->edge[0].csCoord ),
366 hintmap->scale ),
367 hintmap->edge[0].dsCoord );
368 }
369 else
370 {
371 /*
372 * Note: entries with duplicate csCoord are allowed.
373 * Use edge[i], the highest entry where csCoord >= entry[i].csCoord
374 */
375 return ADD_INT32( FT_MulFix( SUB_INT32( csCoord,
376 hintmap->edge[i].csCoord ),
377 hintmap->edge[i].scale ),
378 hintmap->edge[i].dsCoord );
379 }
380 }
381 }

Referenced by cf2_glyphpath_hintPoint(), and cf2_hintmap_insertHint().