... |
... |
@@ -469,10 +469,8 @@ typedef ptrdiff_t FT_PtrDist; |
469
|
469
|
} TPixmap;
|
470
|
470
|
|
471
|
471
|
/* maximum number of gray cells in the buffer */
|
472
|
|
-#if FT_RENDER_POOL_SIZE > 2048
|
|
472
|
+#if defined( FT_GRAY_POOL_SIZE ) && FT_GRAY_POOL_SIZE > 2048
|
473
|
473
|
#define FT_MAX_GRAY_POOL ( FT_RENDER_POOL_SIZE / sizeof ( TCell ) )
|
474
|
|
-#else
|
475
|
|
-#define FT_MAX_GRAY_POOL ( 2048 / sizeof ( TCell ) )
|
476
|
474
|
#endif
|
477
|
475
|
|
478
|
476
|
/* FT_Span buffer size for direct rendering only */
|
... |
... |
@@ -490,6 +488,7 @@ typedef ptrdiff_t FT_PtrDist; |
490
|
488
|
typedef struct gray_TWorker_
|
491
|
489
|
{
|
492
|
490
|
ft_jmp_buf jump_buffer;
|
|
491
|
+ FT_Memory memory;
|
493
|
492
|
|
494
|
493
|
TCoord min_ex, max_ex; /* min and max integer pixel coordinates */
|
495
|
494
|
TCoord min_ey, max_ey;
|
... |
... |
@@ -1486,139 +1485,6 @@ typedef ptrdiff_t FT_PtrDist; |
1486
|
1485
|
}
|
1487
|
1486
|
|
1488
|
1487
|
|
1489
|
|
- static void
|
1490
|
|
- gray_sweep( RAS_ARG )
|
1491
|
|
- {
|
1492
|
|
- int fill = ( ras.outline.flags & FT_OUTLINE_EVEN_ODD_FILL ) ? 0x100
|
1493
|
|
- : INT_MIN;
|
1494
|
|
- int coverage;
|
1495
|
|
- int y;
|
1496
|
|
-
|
1497
|
|
-
|
1498
|
|
- for ( y = ras.min_ey; y < ras.max_ey; y++ )
|
1499
|
|
- {
|
1500
|
|
- PCell cell = ras.ycells[y - ras.min_ey];
|
1501
|
|
- TCoord x = ras.min_ex;
|
1502
|
|
- TArea cover = 0;
|
1503
|
|
-
|
1504
|
|
- unsigned char* line = ras.target.origin - ras.target.pitch * y;
|
1505
|
|
-
|
1506
|
|
-
|
1507
|
|
- for ( ; cell != ras.cell_null; cell = cell->next )
|
1508
|
|
- {
|
1509
|
|
- TArea area;
|
1510
|
|
-
|
1511
|
|
-
|
1512
|
|
- if ( cover != 0 && cell->x > x )
|
1513
|
|
- {
|
1514
|
|
- FT_FILL_RULE( coverage, cover, fill );
|
1515
|
|
- FT_GRAY_SET( line + x, coverage, cell->x - x );
|
1516
|
|
- }
|
1517
|
|
-
|
1518
|
|
- cover += (TArea)cell->cover * ( ONE_PIXEL * 2 );
|
1519
|
|
- area = cover - cell->area;
|
1520
|
|
-
|
1521
|
|
- if ( area != 0 && cell->x >= ras.min_ex )
|
1522
|
|
- {
|
1523
|
|
- FT_FILL_RULE( coverage, area, fill );
|
1524
|
|
- line[cell->x] = (unsigned char)coverage;
|
1525
|
|
- }
|
1526
|
|
-
|
1527
|
|
- x = cell->x + 1;
|
1528
|
|
- }
|
1529
|
|
-
|
1530
|
|
- if ( cover != 0 ) /* only if cropped */
|
1531
|
|
- {
|
1532
|
|
- FT_FILL_RULE( coverage, cover, fill );
|
1533
|
|
- FT_GRAY_SET( line + x, coverage, ras.max_ex - x );
|
1534
|
|
- }
|
1535
|
|
- }
|
1536
|
|
- }
|
1537
|
|
-
|
1538
|
|
-
|
1539
|
|
- static void
|
1540
|
|
- gray_sweep_direct( RAS_ARG )
|
1541
|
|
- {
|
1542
|
|
- int fill = ( ras.outline.flags & FT_OUTLINE_EVEN_ODD_FILL ) ? 0x100
|
1543
|
|
- : INT_MIN;
|
1544
|
|
- int coverage;
|
1545
|
|
- int y;
|
1546
|
|
-
|
1547
|
|
- FT_Span span[FT_MAX_GRAY_SPANS];
|
1548
|
|
- int n = 0;
|
1549
|
|
-
|
1550
|
|
-
|
1551
|
|
- for ( y = ras.min_ey; y < ras.max_ey; y++ )
|
1552
|
|
- {
|
1553
|
|
- PCell cell = ras.ycells[y - ras.min_ey];
|
1554
|
|
- TCoord x = ras.min_ex;
|
1555
|
|
- TArea cover = 0;
|
1556
|
|
-
|
1557
|
|
-
|
1558
|
|
- for ( ; cell != ras.cell_null; cell = cell->next )
|
1559
|
|
- {
|
1560
|
|
- TArea area;
|
1561
|
|
-
|
1562
|
|
-
|
1563
|
|
- if ( cover != 0 && cell->x > x )
|
1564
|
|
- {
|
1565
|
|
- FT_FILL_RULE( coverage, cover, fill );
|
1566
|
|
-
|
1567
|
|
- span[n].coverage = (unsigned char)coverage;
|
1568
|
|
- span[n].x = (short)x;
|
1569
|
|
- span[n].len = (unsigned short)( cell->x - x );
|
1570
|
|
-
|
1571
|
|
- if ( ++n == FT_MAX_GRAY_SPANS )
|
1572
|
|
- {
|
1573
|
|
- /* flush the span buffer and reset the count */
|
1574
|
|
- ras.render_span( y, n, span, ras.render_span_data );
|
1575
|
|
- n = 0;
|
1576
|
|
- }
|
1577
|
|
- }
|
1578
|
|
-
|
1579
|
|
- cover += (TArea)cell->cover * ( ONE_PIXEL * 2 );
|
1580
|
|
- area = cover - cell->area;
|
1581
|
|
-
|
1582
|
|
- if ( area != 0 && cell->x >= ras.min_ex )
|
1583
|
|
- {
|
1584
|
|
- FT_FILL_RULE( coverage, area, fill );
|
1585
|
|
-
|
1586
|
|
- span[n].coverage = (unsigned char)coverage;
|
1587
|
|
- span[n].x = (short)cell->x;
|
1588
|
|
- span[n].len = 1;
|
1589
|
|
-
|
1590
|
|
- if ( ++n == FT_MAX_GRAY_SPANS )
|
1591
|
|
- {
|
1592
|
|
- /* flush the span buffer and reset the count */
|
1593
|
|
- ras.render_span( y, n, span, ras.render_span_data );
|
1594
|
|
- n = 0;
|
1595
|
|
- }
|
1596
|
|
- }
|
1597
|
|
-
|
1598
|
|
- x = cell->x + 1;
|
1599
|
|
- }
|
1600
|
|
-
|
1601
|
|
- if ( cover != 0 ) /* only if cropped */
|
1602
|
|
- {
|
1603
|
|
- FT_FILL_RULE( coverage, cover, fill );
|
1604
|
|
-
|
1605
|
|
- span[n].coverage = (unsigned char)coverage;
|
1606
|
|
- span[n].x = (short)x;
|
1607
|
|
- span[n].len = (unsigned short)( ras.max_ex - x );
|
1608
|
|
-
|
1609
|
|
- ++n;
|
1610
|
|
- }
|
1611
|
|
-
|
1612
|
|
- if ( n )
|
1613
|
|
- {
|
1614
|
|
- /* flush the span buffer and reset the count */
|
1615
|
|
- ras.render_span( y, n, span, ras.render_span_data );
|
1616
|
|
- n = 0;
|
1617
|
|
- }
|
1618
|
|
- }
|
1619
|
|
- }
|
1620
|
|
-
|
1621
|
|
-
|
1622
|
1488
|
#ifdef STANDALONE_
|
1623
|
1489
|
|
1624
|
1490
|
/**************************************************************************
|
... |
... |
@@ -1934,7 +1800,7 @@ typedef ptrdiff_t FT_PtrDist; |
1934
|
1800
|
if ( continued )
|
1935
|
1801
|
FT_Trace_Enable();
|
1936
|
1802
|
|
1937
|
|
- FT_TRACE7(( "band [%d..%d]: %td cell%s remaining/\n",
|
|
1803
|
+ FT_TRACE7(( "band [%d..%d]: %td cell%s remaining\n",
|
1938
|
1804
|
ras.min_ey,
|
1939
|
1805
|
ras.max_ey,
|
1940
|
1806
|
ras.cell_null - ras.cell_free,
|
... |
... |
@@ -1952,15 +1818,190 @@ typedef ptrdiff_t FT_PtrDist; |
1952
|
1818
|
}
|
1953
|
1819
|
|
1954
|
1820
|
|
|
1821
|
+ static void
|
|
1822
|
+ gray_sweep( RAS_ARG )
|
|
1823
|
+ {
|
|
1824
|
+ int fill = ( ras.outline.flags & FT_OUTLINE_EVEN_ODD_FILL ) ? 0x100
|
|
1825
|
+ : INT_MIN;
|
|
1826
|
+ int coverage;
|
|
1827
|
+ int y;
|
|
1828
|
+
|
|
1829
|
+
|
|
1830
|
+ for ( y = ras.min_ey; y < ras.max_ey; y++ )
|
|
1831
|
+ {
|
|
1832
|
+ PCell cell = ras.ycells[y - ras.min_ey];
|
|
1833
|
+ TCoord x = ras.min_ex;
|
|
1834
|
+ TArea cover = 0;
|
|
1835
|
+
|
|
1836
|
+ unsigned char* line = ras.target.origin - ras.target.pitch * y;
|
|
1837
|
+
|
|
1838
|
+
|
|
1839
|
+ for ( ; cell != ras.cell_null; cell = cell->next )
|
|
1840
|
+ {
|
|
1841
|
+ TArea area;
|
|
1842
|
+
|
|
1843
|
+
|
|
1844
|
+ if ( cover != 0 && cell->x > x )
|
|
1845
|
+ {
|
|
1846
|
+ FT_FILL_RULE( coverage, cover, fill );
|
|
1847
|
+ FT_GRAY_SET( line + x, coverage, cell->x - x );
|
|
1848
|
+ }
|
|
1849
|
+
|
|
1850
|
+ cover += (TArea)cell->cover * ( ONE_PIXEL * 2 );
|
|
1851
|
+ area = cover - cell->area;
|
|
1852
|
+
|
|
1853
|
+ if ( area != 0 && cell->x >= ras.min_ex )
|
|
1854
|
+ {
|
|
1855
|
+ FT_FILL_RULE( coverage, area, fill );
|
|
1856
|
+ line[cell->x] = (unsigned char)coverage;
|
|
1857
|
+ }
|
|
1858
|
+
|
|
1859
|
+ x = cell->x + 1;
|
|
1860
|
+ }
|
|
1861
|
+
|
|
1862
|
+ if ( cover != 0 ) /* only if cropped */
|
|
1863
|
+ {
|
|
1864
|
+ FT_FILL_RULE( coverage, cover, fill );
|
|
1865
|
+ FT_GRAY_SET( line + x, coverage, ras.max_ex - x );
|
|
1866
|
+ }
|
|
1867
|
+ }
|
|
1868
|
+ }
|
|
1869
|
+
|
|
1870
|
+
|
|
1871
|
+ static void
|
|
1872
|
+ gray_sweep_direct( RAS_ARG )
|
|
1873
|
+ {
|
|
1874
|
+ int fill = ( ras.outline.flags & FT_OUTLINE_EVEN_ODD_FILL ) ? 0x100
|
|
1875
|
+ : INT_MIN;
|
|
1876
|
+ int coverage;
|
|
1877
|
+ int y;
|
|
1878
|
+
|
|
1879
|
+ FT_Span span[FT_MAX_GRAY_SPANS];
|
|
1880
|
+ int n = 0;
|
|
1881
|
+
|
|
1882
|
+
|
|
1883
|
+ for ( y = ras.min_ey; y < ras.max_ey; y++ )
|
|
1884
|
+ {
|
|
1885
|
+ PCell cell = ras.ycells[y - ras.min_ey];
|
|
1886
|
+ TCoord x = ras.min_ex;
|
|
1887
|
+ TArea cover = 0;
|
|
1888
|
+
|
|
1889
|
+
|
|
1890
|
+ for ( ; cell != ras.cell_null; cell = cell->next )
|
|
1891
|
+ {
|
|
1892
|
+ TArea area;
|
|
1893
|
+
|
|
1894
|
+
|
|
1895
|
+ if ( cover != 0 && cell->x > x )
|
|
1896
|
+ {
|
|
1897
|
+ FT_FILL_RULE( coverage, cover, fill );
|
|
1898
|
+
|
|
1899
|
+ span[n].coverage = (unsigned char)coverage;
|
|
1900
|
+ span[n].x = (short)x;
|
|
1901
|
+ span[n].len = (unsigned short)( cell->x - x );
|
|
1902
|
+
|
|
1903
|
+ if ( ++n == FT_MAX_GRAY_SPANS )
|
|
1904
|
+ {
|
|
1905
|
+ /* flush the span buffer and reset the count */
|
|
1906
|
+ ras.render_span( y, n, span, ras.render_span_data );
|
|
1907
|
+ n = 0;
|
|
1908
|
+ }
|
|
1909
|
+ }
|
|
1910
|
+
|
|
1911
|
+ cover += (TArea)cell->cover * ( ONE_PIXEL * 2 );
|
|
1912
|
+ area = cover - cell->area;
|
|
1913
|
+
|
|
1914
|
+ if ( area != 0 && cell->x >= ras.min_ex )
|
|
1915
|
+ {
|
|
1916
|
+ FT_FILL_RULE( coverage, area, fill );
|
|
1917
|
+
|
|
1918
|
+ span[n].coverage = (unsigned char)coverage;
|
|
1919
|
+ span[n].x = (short)cell->x;
|
|
1920
|
+ span[n].len = 1;
|
|
1921
|
+
|
|
1922
|
+ if ( ++n == FT_MAX_GRAY_SPANS )
|
|
1923
|
+ {
|
|
1924
|
+ /* flush the span buffer and reset the count */
|
|
1925
|
+ ras.render_span( y, n, span, ras.render_span_data );
|
|
1926
|
+ n = 0;
|
|
1927
|
+ }
|
|
1928
|
+ }
|
|
1929
|
+
|
|
1930
|
+ x = cell->x + 1;
|
|
1931
|
+ }
|
|
1932
|
+
|
|
1933
|
+ if ( cover != 0 ) /* only if cropped */
|
|
1934
|
+ {
|
|
1935
|
+ FT_FILL_RULE( coverage, cover, fill );
|
|
1936
|
+
|
|
1937
|
+ span[n].coverage = (unsigned char)coverage;
|
|
1938
|
+ span[n].x = (short)x;
|
|
1939
|
+ span[n].len = (unsigned short)( ras.max_ex - x );
|
|
1940
|
+
|
|
1941
|
+ ++n;
|
|
1942
|
+ }
|
|
1943
|
+
|
|
1944
|
+ if ( n )
|
|
1945
|
+ {
|
|
1946
|
+ /* flush the span buffer and reset the count */
|
|
1947
|
+ ras.render_span( y, n, span, ras.render_span_data );
|
|
1948
|
+ n = 0;
|
|
1949
|
+ }
|
|
1950
|
+ }
|
|
1951
|
+ }
|
|
1952
|
+
|
|
1953
|
+
|
|
1954
|
+ /*
|
|
1955
|
+ * The taxicab perimeter of the entire outline is used to estimate
|
|
1956
|
+ * the necessary memory pool or the job size in general. Clipping
|
|
1957
|
+ * is ignored because it might hurt the performance.
|
|
1958
|
+ */
|
|
1959
|
+ static long
|
|
1960
|
+ gray_taxi( RAS_ARG )
|
|
1961
|
+ {
|
|
1962
|
+ FT_Outline* outline = &ras.outline;
|
|
1963
|
+ short c, p, first, last;
|
|
1964
|
+ FT_Vector d, v;
|
|
1965
|
+ FT_Pos taxi;
|
|
1966
|
+
|
|
1967
|
+
|
|
1968
|
+ taxi = 0;
|
|
1969
|
+ last = -1;
|
|
1970
|
+ for ( c = 0; c < outline->n_contours; c++ )
|
|
1971
|
+ {
|
|
1972
|
+ first = last + 1;
|
|
1973
|
+ last = outline->contours[c];
|
|
1974
|
+
|
|
1975
|
+ d = outline->points[last];
|
|
1976
|
+ for ( p = first; p <= last; p++ )
|
|
1977
|
+ {
|
|
1978
|
+ v = outline->points[p];
|
|
1979
|
+ d.x -= v.x;
|
|
1980
|
+ d.y -= v.y;
|
|
1981
|
+
|
|
1982
|
+ taxi += FT_ABS( d.x ) + FT_ABS( d.y );
|
|
1983
|
+
|
|
1984
|
+ d = v;
|
|
1985
|
+ }
|
|
1986
|
+ }
|
|
1987
|
+
|
|
1988
|
+ return taxi >> 6;
|
|
1989
|
+ }
|
|
1990
|
+
|
|
1991
|
+
|
1955
|
1992
|
static int
|
1956
|
1993
|
gray_convert_glyph( RAS_ARG )
|
1957
|
1994
|
{
|
1958
|
1995
|
const TCoord yMin = ras.min_ey;
|
1959
|
1996
|
const TCoord yMax = ras.max_ey;
|
1960
|
1997
|
|
1961
|
|
- TCell buffer[FT_MAX_GRAY_POOL];
|
|
1998
|
+ FT_Error error = FT_THROW( Ok );
|
|
1999
|
+ FT_Memory memory = ras.memory;
|
|
2000
|
+
|
|
2001
|
+ TCell* buffer;
|
1962
|
2002
|
size_t height = (size_t)( yMax - yMin );
|
1963
|
|
- size_t n = FT_MAX_GRAY_POOL / 8;
|
|
2003
|
+ size_t n;
|
|
2004
|
+ long size;
|
1964
|
2005
|
TCoord y;
|
1965
|
2006
|
TCoord bands[32]; /* enough to accommodate bisections */
|
1966
|
2007
|
TCoord* band;
|
... |
... |
@@ -1968,8 +2009,39 @@ typedef ptrdiff_t FT_PtrDist; |
1968
|
2009
|
int continued = 0;
|
1969
|
2010
|
|
1970
|
2011
|
|
|
2012
|
+ size = gray_taxi( RAS_VAR );
|
|
2013
|
+
|
|
2014
|
+ /* taxicab perimeters in excess of 20 CBox perimeters are */
|
|
2015
|
+ /* not drawn unless in direct mode with possible clipping */
|
|
2016
|
+ if ( !ras.render_span &&
|
|
2017
|
+ size > 20 * 2 * ( ras.max_ex - ras.min_ex + height ) )
|
|
2018
|
+ {
|
|
2019
|
+ FT_TRACE5(( "Blanking on taxi:cbox = %.2lf\n",
|
|
2020
|
+ 0.5 * size / ( ras.max_ex - ras.min_ex + height ) ));
|
|
2021
|
+ return FT_THROW( Ok );
|
|
2022
|
+ }
|
|
2023
|
+
|
|
2024
|
+ size += height * sizeof ( PCell ) / sizeof ( TCell ) +
|
|
2025
|
+ 9; /* empirical extra for local extrema */
|
|
2026
|
+
|
|
2027
|
+#ifdef FT_MAX_GRAY_POOL
|
|
2028
|
+ if ( size > FT_MAX_GRAY_POOL )
|
|
2029
|
+ {
|
|
2030
|
+ /* both divisions rounded up */
|
|
2031
|
+ n = ( size + FT_MAX_GRAY_POOL - 1 ) / FT_MAX_GRAY_POOL;
|
|
2032
|
+ height = ( height + n - 1 ) / n;
|
|
2033
|
+ size = FT_MAX_GRAY_POOL;
|
|
2034
|
+ }
|
|
2035
|
+#endif
|
|
2036
|
+
|
|
2037
|
+ if ( FT_QNEW_ARRAY( buffer, size ) )
|
|
2038
|
+ return error;
|
|
2039
|
+
|
|
2040
|
+ FT_TRACE7(( "Allocated %ld cells (%ld bytes)\n",
|
|
2041
|
+ size, size * sizeof ( TCell ) ));
|
|
2042
|
+
|
1971
|
2043
|
/* Initialize the null cell at the end of the poll. */
|
1972
|
|
- ras.cell_null = buffer + FT_MAX_GRAY_POOL - 1;
|
|
2044
|
+ ras.cell_null = buffer + size - 1;
|
1973
|
2045
|
ras.cell_null->x = CELL_MAX_X_VALUE;
|
1974
|
2046
|
ras.cell_null->area = 0;
|
1975
|
2047
|
ras.cell_null->cover = 0;
|
... |
... |
@@ -1978,13 +2050,6 @@ typedef ptrdiff_t FT_PtrDist; |
1978
|
2050
|
/* set up vertical bands */
|
1979
|
2051
|
ras.ycells = (PCell*)buffer;
|
1980
|
2052
|
|
1981
|
|
- if ( height > n )
|
1982
|
|
- {
|
1983
|
|
- /* two divisions rounded up */
|
1984
|
|
- n = ( height + n - 1 ) / n;
|
1985
|
|
- height = ( height + n - 1 ) / n;
|
1986
|
|
- }
|
1987
|
|
-
|
1988
|
2053
|
for ( y = yMin; y < yMax; )
|
1989
|
2054
|
{
|
1990
|
2055
|
ras.min_ey = y;
|
... |
... |
@@ -1999,7 +2064,6 @@ typedef ptrdiff_t FT_PtrDist; |
1999
|
2064
|
{
|
2000
|
2065
|
TCoord width = band[0] - band[1];
|
2001
|
2066
|
TCoord w;
|
2002
|
|
- int error;
|
2003
|
2067
|
|
2004
|
2068
|
|
2005
|
2069
|
for ( w = 0; w < width; ++w )
|
... |
... |
@@ -2028,7 +2092,7 @@ typedef ptrdiff_t FT_PtrDist; |
2028
|
2092
|
continue;
|
2029
|
2093
|
}
|
2030
|
2094
|
else if ( error != Smooth_Err_Raster_Overflow )
|
2031
|
|
- return error;
|
|
2095
|
+ goto Exit;
|
2032
|
2096
|
|
2033
|
2097
|
/* render pool overflow; we will reduce the render band by half */
|
2034
|
2098
|
width >>= 1;
|
... |
... |
@@ -2037,7 +2101,8 @@ typedef ptrdiff_t FT_PtrDist; |
2037
|
2101
|
if ( width == 0 )
|
2038
|
2102
|
{
|
2039
|
2103
|
FT_TRACE7(( "gray_convert_glyph: rotten glyph\n" ));
|
2040
|
|
- return FT_THROW( Raster_Overflow );
|
|
2104
|
+ error = FT_THROW( Raster_Overflow );
|
|
2105
|
+ goto Exit;
|
2041
|
2106
|
}
|
2042
|
2107
|
|
2043
|
2108
|
band++;
|
... |
... |
@@ -2046,7 +2111,9 @@ typedef ptrdiff_t FT_PtrDist; |
2046
|
2111
|
} while ( band >= bands );
|
2047
|
2112
|
}
|
2048
|
2113
|
|
2049
|
|
- return Smooth_Err_Ok;
|
|
2114
|
+ Exit:
|
|
2115
|
+ FT_FREE( buffer );
|
|
2116
|
+ return error;
|
2050
|
2117
|
}
|
2051
|
2118
|
|
2052
|
2119
|
|
... |
... |
@@ -2132,6 +2199,8 @@ typedef ptrdiff_t FT_PtrDist; |
2132
|
2199
|
if ( ras.max_ex <= ras.min_ex || ras.max_ey <= ras.min_ey )
|
2133
|
2200
|
return Smooth_Err_Ok;
|
2134
|
2201
|
|
|
2202
|
+ ras.memory = (FT_Memory)((gray_PRaster)raster)->memory;
|
|
2203
|
+
|
2135
|
2204
|
return gray_convert_glyph( RAS_VAR );
|
2136
|
2205
|
}
|
2137
|
2206
|
|