diff options
author | Werner Lemberg <wl@gnu.org> | 2009-06-18 15:42:52 +0200 |
---|---|---|
committer | Werner Lemberg <wl@gnu.org> | 2009-06-18 15:42:52 +0200 |
commit | 72271140434028186a49a5dc5925f0727559e46f (patch) | |
tree | 090fc9322d5b80e215191a2da657a32b643964b7 /src | |
parent | 780d7e05e71635812efd3b3a19d70e2411803136 (diff) | |
download | freetype2-72271140434028186a49a5dc5925f0727559e46f.tar.gz |
Fix B/W rasterization of subglyphs with different drop-out modes.
Normally, the SCANMODE instruction (if present) to set the drop-out
mode in a TrueType font is located in the `prep' table only and thus
valid for all glyphs. However, there are fonts like `pala.ttf'
which additionally contain this instruction in the hinting code of
some glyphs (but not all). As a result it can happen that a
composite glyph needs multiple drop-out modes for its subglyphs
since the rendering state gets reset for each subglyph.
FreeType collects the hinted outlines from all subglyphs, then it
sends the data to the rasterizer. It also sends the drop-out mode
-- after hinting has been applied -- and here is the error: It sends
the drop-out mode of the last subglyph only; drop-out modes of all
other subglyphs are lost.
This patch fixes the problem; it adds a second, alternative
mechanism to pass the drop-out mode: For each contour, the
rasterizer now checks the first `tags' array element. If bit 2 is
set, bits 5-7 contain the contour's drop-out mode, overriding the
global drop-out mode.
* include/freetype/ftimage.h (FT_CURVE_TAG_HAS_SCANMODE): New macro.
* src/truetype/ttgload.c (TT_Hint_Glyph): Store drop-out mode in
`tags[0]'.
* src/raster/ftraster.c (Flow_Up, Overshoot_Top, Overshoot_Bottom):
Use bits 3-5 instead of 0-2.
(New_Profile): Set the drop-out mode in the profile's `flags' field.
(Decompose_Curve): Check `tags[0]' and set `dropOutControl' if
necessary.
(Vertical_Sweep_Drop, Horizontal_Sweep_Drop,
Horizontal_Gray_Sweep_Drop, Draw_Sweep): Use the profile's drop-out
mode.
Diffstat (limited to 'src')
-rw-r--r-- | src/raster/ftraster.c | 46 | ||||
-rw-r--r-- | src/truetype/ttgload.c | 7 |
2 files changed, 40 insertions, 13 deletions
diff --git a/src/raster/ftraster.c b/src/raster/ftraster.c index c8c13f22e..4547dc9bf 100644 --- a/src/raster/ftraster.c +++ b/src/raster/ftraster.c @@ -306,9 +306,9 @@ /* values for the `flags' bit field */ -#define Flow_Up 0x1 -#define Overshoot_Top 0x2 -#define Overshoot_Bottom 0x4 +#define Flow_Up 0x8 +#define Overshoot_Top 0x10 +#define Overshoot_Bottom 0x20 /* States of each line, arc, and profile */ @@ -330,8 +330,10 @@ FT_F26Dot6 X; /* current coordinate during sweep */ PProfile link; /* link to next profile (various purposes) */ PLong offset; /* start of profile's data in render pool */ - unsigned flags; /* Bit 0: profile orientation (up/down) */ - /* Bit 1, 2: profile overshoot (top/bottom) */ + unsigned flags; /* Bit 0-2: drop-out mode */ + /* Bit 3: profile orientation (up/down) */ + /* Bit 4: is top profile? */ + /* Bit 5: is bottom profile? */ long height; /* profile's height in scanlines */ long start; /* profile's starting scanline */ @@ -656,6 +658,7 @@ ras.cProfile->offset = ras.top; ras.cProfile->link = (PProfile)0; ras.cProfile->next = (PProfile)0; + ras.cProfile->flags = ras.dropOutControl; switch ( aState ) { @@ -1739,7 +1742,12 @@ point = points + first; tags = ras.outline.tags + first; - tag = FT_CURVE_TAG( tags[0] ); + + /* set scan mode if necessary */ + if ( tags[0] & FT_CURVE_TAG_HAS_SCANMODE ) + ras.dropOutControl = (Byte)tags[0] >> 5; + + tag = FT_CURVE_TAG( tags[0] ); /* A contour cannot start with a cubic control point! */ if ( tag == FT_CURVE_TAG_CUBIC ) @@ -2269,9 +2277,12 @@ if ( e1 > e2 ) { + Int dropOutControl = left->flags & 7; + + if ( e1 == e2 + ras.precision ) { - switch ( ras.dropOutControl ) + switch ( dropOutControl ) { case 0: /* simple drop-outs including stubs */ pxl = e2; @@ -2324,7 +2335,7 @@ x2 - x1 >= ras.precision_half ) ) return; - if ( ras.dropOutControl == 1 ) + if ( dropOutControl == 1 ) pxl = e2; else pxl = FLOOR( ( x1 + x2 - 1 ) / 2 + ras.precision_half ); @@ -2467,9 +2478,12 @@ if ( e1 > e2 ) { + Int dropOutControl = left->flags & 7; + + if ( e1 == e2 + ras.precision ) { - switch ( ras.dropOutControl ) + switch ( dropOutControl ) { case 0: /* simple drop-outs including stubs */ pxl = e2; @@ -2497,7 +2511,7 @@ x2 - x1 >= ras.precision_half ) ) return; - if ( ras.dropOutControl == 1 ) + if ( dropOutControl == 1 ) pxl = e2; else pxl = FLOOR( ( x1 + x2 - 1 ) / 2 + ras.precision_half ); @@ -2723,9 +2737,12 @@ if ( e1 > e2 ) { + Int dropOutControl = left->flags & 7; + + if ( e1 == e2 + ras.precision ) { - switch ( ras.dropOutControl ) + switch ( dropOutControl ) { case 0: /* simple drop-outs including stubs */ e1 = e2; @@ -2747,7 +2764,7 @@ if ( right->next == left && left->start == y ) return; - if ( ras.dropOutControl == 1 ) + if ( dropOutControl == 1 ) e1 = e2; else e1 = FLOOR( ( x1 + x2 - 1 ) / 2 + ras.precision_half ); @@ -2928,7 +2945,10 @@ { if ( e1 > e2 || e2 == e1 + ras.precision ) { - if ( ras.dropOutControl != 2 ) + Int dropOutControl = P_Left->flags & 7; + + + if ( dropOutControl != 2 ) { /* a drop-out was detected */ diff --git a/src/truetype/ttgload.c b/src/truetype/ttgload.c index ad2b62e74..38023b82c 100644 --- a/src/truetype/ttgload.c +++ b/src/truetype/ttgload.c @@ -680,6 +680,9 @@ FT_Bool debug; FT_Error error; + FT_GlyphLoader gloader = loader->gloader; + FT_Outline current_outline = gloader->current.outline; + error = TT_Set_CodeRange( loader->exec, tt_coderange_glyph, loader->exec->glyphIns, n_ins ); @@ -695,6 +698,10 @@ error = TT_Run_Context( loader->exec, debug ); if ( error && loader->exec->pedantic_hinting ) return error; + + /* store drop-out mode in bits 5-7; set bit 2 also as a marker */ + current_outline.tags[0] |= + ( loader->exec->GS.scan_type << 5 ) | FT_CURVE_TAG_HAS_SCANMODE; } #endif |