Author: jgardou Date: Wed Feb 27 14:11:44 2013 New Revision: 58375
URL: http://svn.reactos.org/svn/reactos?rev=58375&view=rev Log: [USP10] - sync to WINE-1.5.24 This gets wordpad performance to a bearable state when gdebug output is on
Modified: trunk/reactos/dll/win32/usp10/bidi.c trunk/reactos/dll/win32/usp10/breaking.c trunk/reactos/dll/win32/usp10/indic.c trunk/reactos/dll/win32/usp10/indicsyllable.c trunk/reactos/dll/win32/usp10/linebreak.c trunk/reactos/dll/win32/usp10/mirror.c trunk/reactos/dll/win32/usp10/opentype.c trunk/reactos/dll/win32/usp10/shape.c trunk/reactos/dll/win32/usp10/shaping.c trunk/reactos/dll/win32/usp10/usp10.c trunk/reactos/dll/win32/usp10/usp10_internal.h trunk/reactos/dll/win32/usp10/usp10_ros.diff trunk/reactos/media/doc/README.WINE
Modified: trunk/reactos/dll/win32/usp10/bidi.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/usp10/bidi.c?rev=... ============================================================================== --- trunk/reactos/dll/win32/usp10/bidi.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/usp10/bidi.c [iso-8859-1] Wed Feb 27 14:11:44 2013 @@ -41,16 +41,16 @@ * has been modified. */
-#include <config.h> - -//#include <stdarg.h> -#include <windef.h> -//#include "winbase.h" -#include <wingdi.h> -//#include "winnls.h" -#include <usp10.h> -#include <wine/unicode.h> -#include <wine/debug.h> +#include "config.h" + +#include <stdarg.h> +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "winnls.h" +#include "usp10.h" +#include "wine/unicode.h" +#include "wine/debug.h"
#include "usp10_internal.h"
@@ -872,11 +872,13 @@ reverse(pIndexs, ich); }
- if (newlevel > 1) + if (newlevel >= 0) { ich = 0; for (; ich < cch; ich++) - if (plevel[ich] > level) + if (plevel[ich] < level) + break; + else if (plevel[ich] > level) ich += BIDI_ReorderL2vLevel(level + 1, pIndexs + ich, plevel + ich, cch - ich, fReverse) - 1; }
Modified: trunk/reactos/dll/win32/usp10/breaking.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/usp10/breaking.c?... ============================================================================== --- trunk/reactos/dll/win32/usp10/breaking.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/usp10/breaking.c [iso-8859-1] Wed Feb 27 14:11:44 2013 @@ -18,20 +18,20 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA * */ -#include <config.h> +#include "config.h" #include <stdarg.h> -//#include <stdio.h> -//#include <stdlib.h> - -#include <windef.h> -#include <winbase.h> -//#include "winuser.h" -#include <wingdi.h> -//#include "winnls.h" -#include <usp10.h> -//#include "winternl.h" - -#include <wine/debug.h> +#include <stdio.h> +#include <stdlib.h> + +#include "windef.h" +#include "winbase.h" +#include "winuser.h" +#include "wingdi.h" +#include "winnls.h" +#include "usp10.h" +#include "winternl.h" + +#include "wine/debug.h" #include "usp10_internal.h"
WINE_DEFAULT_DEBUG_CHANNEL(uniscribe); @@ -132,7 +132,7 @@ case b_NL: case b_BK: if (i < count-1) else_break(&break_before[i+1],b_r); - else_break(&break_before[i],b_x); + else_break(&break_before[i],b_x); break; /* LB7 */ case b_SP:
Modified: trunk/reactos/dll/win32/usp10/indic.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/usp10/indic.c?rev... ============================================================================== --- trunk/reactos/dll/win32/usp10/indic.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/usp10/indic.c [iso-8859-1] Wed Feb 27 14:11:44 2013 @@ -18,20 +18,20 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA * */ -#include <config.h> +#include "config.h" #include <stdarg.h> -//#include <stdio.h> -//#include <stdlib.h> - -#include <windef.h> -#include <winbase.h> -//#include "winuser.h" -#include <wingdi.h> -//#include "winnls.h" -#include <usp10.h> -//#include "winternl.h" - -#include <wine/debug.h> +#include <stdio.h> +#include <stdlib.h> + +#include "windef.h" +#include "winbase.h" +#include "winuser.h" +#include "wingdi.h" +#include "winnls.h" +#include "usp10.h" +#include "winternl.h" + +#include "wine/debug.h" #include "usp10_internal.h"
WINE_DEFAULT_DEBUG_CHANNEL(uniscribe);
Modified: trunk/reactos/dll/win32/usp10/indicsyllable.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/usp10/indicsyllab... ============================================================================== --- trunk/reactos/dll/win32/usp10/indicsyllable.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/usp10/indicsyllable.c [iso-8859-1] Wed Feb 27 14:11:44 2013 @@ -3,7 +3,7 @@ /* and from http://www.unicode.org/Public/6.0.0/ucd/IndicMatraCategory.txt */ /* DO NOT EDIT!! */
-//#include "wine/unicode.h" +#include "wine/unicode.h"
const unsigned short indic_syllabic_table[2624] = {
Modified: trunk/reactos/dll/win32/usp10/linebreak.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/usp10/linebreak.c... ============================================================================== --- trunk/reactos/dll/win32/usp10/linebreak.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/usp10/linebreak.c [iso-8859-1] Wed Feb 27 14:11:44 2013 @@ -2,7 +2,7 @@ /* generated from http://www.unicode.org/Public/6.0.0/ucd/LineBreak.txt */ /* DO NOT EDIT!! */
-//#include "wine/unicode.h" +#include "wine/unicode.h"
const unsigned short wine_linebreak_table[6800] = {
Modified: trunk/reactos/dll/win32/usp10/mirror.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/usp10/mirror.c?re... ============================================================================== --- trunk/reactos/dll/win32/usp10/mirror.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/usp10/mirror.c [iso-8859-1] Wed Feb 27 14:11:44 2013 @@ -2,7 +2,7 @@ /* generated from http://www.unicode.org/Public/6.0.0/ucd/BidiMirroring.txt */ /* DO NOT EDIT!! */
-#include <wine/unicode.h> +#include "wine/unicode.h"
const WCHAR wine_mirror_map[3292] = {
Modified: trunk/reactos/dll/win32/usp10/opentype.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/usp10/opentype.c?... ============================================================================== --- trunk/reactos/dll/win32/usp10/opentype.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/usp10/opentype.c [iso-8859-1] Wed Feb 27 14:11:44 2013 @@ -21,17 +21,17 @@ #include <stdarg.h> #include <stdlib.h>
-#include <windef.h> -#include <winbase.h> -#include <wingdi.h> -//#include "winuser.h" -//#include "winnls.h" -#include <usp10.h> -#include <winternl.h> +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "winuser.h" +#include "winnls.h" +#include "usp10.h" +#include "winternl.h"
#include "usp10_internal.h"
-#include <wine/debug.h> +#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(uniscribe);
@@ -76,8 +76,6 @@ } CMAP_SegmentedCoverage;
/* These are all structures needed for the GDEF table */ -#define GDEF_TAG MS_MAKE_TAG('G', 'D', 'E', 'F') - enum {BaseGlyph=1, LigatureGlyph, MarkGlyph, ComponentGlyph};
typedef struct { @@ -93,19 +91,19 @@ WORD StartGlyph; WORD GlyphCount; WORD ClassValueArray[1]; -} GDEF_ClassDefFormat1; +} OT_ClassDefFormat1;
typedef struct { WORD Start; WORD End; WORD Class; -} GDEF_ClassRangeRecord; +} OT_ClassRangeRecord;
typedef struct { WORD ClassFormat; WORD ClassRangeCount; - GDEF_ClassRangeRecord ClassRangeRecord[1]; -} GDEF_ClassDefFormat2; + OT_ClassRangeRecord ClassRangeRecord[1]; +} OT_ClassDefFormat2;
/* These are all structures needed for the GSUB table */
@@ -352,6 +350,18 @@ } GPOS_PairPosFormat1;
typedef struct { + WORD PosFormat; + WORD Coverage; + WORD ValueFormat1; + WORD ValueFormat2; + WORD ClassDef1; + WORD ClassDef2; + WORD Class1Count; + WORD Class2Count; + WORD Class1Record[1]; +} GPOS_PairPosFormat2; + +typedef struct { WORD SecondGlyph; WORD Value1[1]; WORD Value2[1]; @@ -361,6 +371,18 @@ WORD PairValueCount; GPOS_PairValueRecord PairValueRecord[1]; } GPOS_PairSet; + +typedef struct { + WORD EntryAnchor; + WORD ExitAnchor; +} GPOS_EntryExitRecord; + +typedef struct { + WORD PosFormat; + WORD Coverage; + WORD EntryExitCount; + GPOS_EntryExitRecord EntryExitRecord[1]; +} GPOS_CursivePosFormat1;
typedef struct { WORD PosFormat; @@ -392,6 +414,29 @@
typedef struct { WORD PosFormat; + WORD MarkCoverage; + WORD LigatureCoverage; + WORD ClassCount; + WORD MarkArray; + WORD LigatureArray; +} GPOS_MarkLigPosFormat1; + +typedef struct { + WORD LigatureCount; + WORD LigatureAttach[1]; +} GPOS_LigatureArray; + +typedef struct { + WORD LigatureAnchor[1]; +} GPOS_ComponentRecord; + +typedef struct { + WORD ComponentCount; + GPOS_ComponentRecord ComponentRecord[1]; +} GPOS_LigatureAttach; + +typedef struct { + WORD PosFormat; WORD Mark1Coverage; WORD Mark2Coverage; WORD ClassCount; @@ -525,20 +570,13 @@ * GDEF **********/
-static WORD GDEF_get_glyph_class(const GDEF_Header *header, WORD glyph) -{ - int offset; +static WORD OT_get_glyph_class(const void *table, WORD glyph) +{ WORD class = 0; - const GDEF_ClassDefFormat1 *cf1; - - if (!header) - return 0; - - offset = GET_BE_WORD(header->GlyphClassDef); - if (!offset) - return 0; - - cf1 = (GDEF_ClassDefFormat1*)(((BYTE*)header)+offset); + const OT_ClassDefFormat1 *cf1 = table; + + if (!table) return 0; + if (GET_BE_WORD(cf1->ClassFormat) == 1) { if (glyph >= GET_BE_WORD(cf1->StartGlyph)) @@ -550,7 +588,7 @@ } else if (GET_BE_WORD(cf1->ClassFormat) == 2) { - const GDEF_ClassDefFormat2 *cf2 = (GDEF_ClassDefFormat2*)cf1; + const OT_ClassDefFormat2 *cf2 = table; int i, top; top = GET_BE_WORD(cf2->ClassRangeCount); for (i = 0; i < top; i++) @@ -569,25 +607,18 @@ return class; }
-static VOID *load_gdef_table(HDC hdc) -{ - VOID* GDEF_Table = NULL; - int length = GetFontData(hdc, GDEF_TAG , 0, NULL, 0); - if (length != GDI_ERROR) - { - GDEF_Table = HeapAlloc(GetProcessHeap(),0,length); - GetFontData(hdc, GDEF_TAG , 0, GDEF_Table, length); - TRACE("Loaded GDEF table of %i bytes\n",length); - } - return GDEF_Table; -} - -void OpenType_GDEF_UpdateGlyphProps(HDC hdc, ScriptCache *psc, const WORD *pwGlyphs, const WORD cGlyphs, WORD* pwLogClust, const WORD cChars, SCRIPT_GLYPHPROP *pGlyphProp) +void OpenType_GDEF_UpdateGlyphProps(ScriptCache *psc, const WORD *pwGlyphs, const WORD cGlyphs, WORD* pwLogClust, const WORD cChars, SCRIPT_GLYPHPROP *pGlyphProp) { int i; - - if (!psc->GDEF_Table) - psc->GDEF_Table = load_gdef_table(hdc); + void *glyph_class_table = NULL; + + if (psc->GDEF_Table) + { + const GDEF_Header *header = psc->GDEF_Table; + WORD offset = GET_BE_WORD( header->GlyphClassDef ); + if (offset) + glyph_class_table = (BYTE *)psc->GDEF_Table + offset; + }
for (i = 0; i < cGlyphs; i++) { @@ -602,7 +633,7 @@ char_count++; }
- class = GDEF_get_glyph_class(psc->GDEF_Table, pwGlyphs[i]); + class = OT_get_glyph_class( glyph_class_table, pwGlyphs[i] );
switch (class) { @@ -1023,7 +1054,8 @@ /********** * GPOS **********/ -static INT GPOS_apply_lookup(LPOUTLINETEXTMETRICW lpotm, LPLOGFONTW lplogfont, INT* piAdvance, const OT_LookupList* lookup, INT lookup_index, const WORD *glyphs, INT glyph_index, INT write_dir, INT glyph_count, GOFFSET *pGoffset); +static INT GPOS_apply_lookup(ScriptCache *psc, LPOUTLINETEXTMETRICW lpotm, LPLOGFONTW lplogfont, const SCRIPT_ANALYSIS *analysis, INT* piAdvance, + const OT_LookupList* lookup, INT lookup_index, const WORD *glyphs, INT glyph_index, INT glyph_count, GOFFSET *pGoffset);
static INT GPOS_get_device_table_value(const OT_DeviceTable *DeviceTable, WORD ppem) { @@ -1110,14 +1142,14 @@ static INT GPOS_get_value_record(WORD ValueFormat, const WORD data[], GPOS_ValueRecord *record) { INT offset = 0; - if (ValueFormat & 0x0001) record->XPlacement = GET_BE_WORD(data[offset++]); - if (ValueFormat & 0x0002) record->YPlacement = GET_BE_WORD(data[offset++]); - if (ValueFormat & 0x0004) record->XAdvance = GET_BE_WORD(data[offset++]); - if (ValueFormat & 0x0008) record->YAdvance = GET_BE_WORD(data[offset++]); - if (ValueFormat & 0x0010) record->XPlaDevice = GET_BE_WORD(data[offset++]); - if (ValueFormat & 0x0020) record->YPlaDevice = GET_BE_WORD(data[offset++]); - if (ValueFormat & 0x0040) record->XAdvDevice = GET_BE_WORD(data[offset++]); - if (ValueFormat & 0x0080) record->YAdvDevice = GET_BE_WORD(data[offset++]); + if (ValueFormat & 0x0001) { if (data) record->XPlacement = GET_BE_WORD(data[offset]); offset++; } + if (ValueFormat & 0x0002) { if (data) record->YPlacement = GET_BE_WORD(data[offset]); offset++; } + if (ValueFormat & 0x0004) { if (data) record->XAdvance = GET_BE_WORD(data[offset]); offset++; } + if (ValueFormat & 0x0008) { if (data) record->YAdvance = GET_BE_WORD(data[offset]); offset++; } + if (ValueFormat & 0x0010) { if (data) record->XPlaDevice = GET_BE_WORD(data[offset]); offset++; } + if (ValueFormat & 0x0020) { if (data) record->YPlaDevice = GET_BE_WORD(data[offset]); offset++; } + if (ValueFormat & 0x0040) { if (data) record->XAdvDevice = GET_BE_WORD(data[offset]); offset++; } + if (ValueFormat & 0x0080) { if (data) record->YAdvDevice = GET_BE_WORD(data[offset]); offset++; } return offset; }
@@ -1134,7 +1166,8 @@ if (ValueFormat & 0xFF00) FIXME("Unhandled Value Format %x\n",ValueFormat&0xFF00); }
-static VOID GPOS_apply_SingleAdjustment(const OT_LookupTable *look, const WORD *glyphs, INT glyph_index, INT write_dir, INT glyph_count, INT ppem, LPPOINT ptAdjust, LPPOINT ptAdvance) +static VOID GPOS_apply_SingleAdjustment(const OT_LookupTable *look, const SCRIPT_ANALYSIS *analysis, const WORD *glyphs, INT glyph_index, + INT glyph_count, INT ppem, LPPOINT ptAdjust, LPPOINT ptAdvance) { int j;
@@ -1184,9 +1217,37 @@ } }
-static INT GPOS_apply_PairAdjustment(const OT_LookupTable *look, const WORD *glyphs, INT glyph_index, INT write_dir, INT glyph_count, INT ppem, LPPOINT ptAdjust, LPPOINT ptAdvance) +static void apply_pair_value( const void *pos_table, WORD val_fmt1, WORD val_fmt2, const WORD *pair, + INT ppem, POINT *adjust, POINT *advance ) +{ + GPOS_ValueRecord val_rec1 = {0,0,0,0,0,0,0,0}; + GPOS_ValueRecord val_rec2 = {0,0,0,0,0,0,0,0}; + INT size; + + size = GPOS_get_value_record( val_fmt1, pair, &val_rec1 ); + GPOS_get_value_record( val_fmt2, pair + size, &val_rec2 ); + + if (val_fmt1) + { + GPOS_get_value_record_offsets( pos_table, &val_rec1, val_fmt1, ppem, adjust, advance ); + TRACE( "Glyph 1 resulting cumulative offset is %i,%i design units\n", adjust[0].x, adjust[0].y ); + TRACE( "Glyph 1 resulting cumulative advance is %i,%i design units\n", advance[0].x, advance[0].y ); + } + if (val_fmt2) + { + GPOS_get_value_record_offsets( pos_table, &val_rec2, val_fmt2, ppem, adjust + 1, advance + 1 ); + TRACE( "Glyph 2 resulting cumulative offset is %i,%i design units\n", adjust[1].x, adjust[1].y ); + TRACE( "Glyph 2 resulting cumulative advance is %i,%i design units\n", advance[1].x, advance[1].y ); + } +} + +static INT GPOS_apply_PairAdjustment(const OT_LookupTable *look, const SCRIPT_ANALYSIS *analysis, const WORD *glyphs, INT glyph_index, + INT glyph_count, INT ppem, LPPOINT ptAdjust, LPPOINT ptAdvance) { int j; + int write_dir = (analysis->fRTL && !analysis->fLogicalOrder) ? -1 : 1; + + if (glyph_index + write_dir < 0 || glyph_index + write_dir >= glyph_count) return glyph_index + 1;
TRACE("Pair Adjustment Positioning Subtable\n");
@@ -1198,6 +1259,10 @@ if (GET_BE_WORD(ppf1->PosFormat) == 1) { int index; + WORD ValueFormat1 = GET_BE_WORD(ppf1->ValueFormat1); + WORD ValueFormat2 = GET_BE_WORD(ppf1->ValueFormat2); + INT val_fmt1_size = GPOS_get_value_record( ValueFormat1, NULL, NULL ); + INT val_fmt2_size = GPOS_get_value_record( ValueFormat2, NULL, NULL ); offset = GET_BE_WORD(ppf1->Coverage); index = GSUB_is_glyph_covered((const BYTE*)ppf1+offset, glyphs[glyph_index]); if (index != -1 && index < GET_BE_WORD(ppf1->PairSetCount)) @@ -1205,40 +1270,54 @@ int k; int pair_count; const GPOS_PairSet *ps; + const GPOS_PairValueRecord *pair_val_rec; offset = GET_BE_WORD(ppf1->PairSetOffset[index]); ps = (const GPOS_PairSet*)((const BYTE*)ppf1+offset); pair_count = GET_BE_WORD(ps->PairValueCount); + pair_val_rec = ps->PairValueRecord; for (k = 0; k < pair_count; k++) { - WORD second_glyph = GET_BE_WORD(ps->PairValueRecord[k].SecondGlyph); + WORD second_glyph = GET_BE_WORD(pair_val_rec->SecondGlyph); if (glyphs[glyph_index+write_dir] == second_glyph) { int next = 1; - GPOS_ValueRecord ValueRecord1 = {0,0,0,0,0,0,0,0}; - GPOS_ValueRecord ValueRecord2 = {0,0,0,0,0,0,0,0}; - WORD ValueFormat1 = GET_BE_WORD(ppf1->ValueFormat1); - WORD ValueFormat2 = GET_BE_WORD(ppf1->ValueFormat2); - TRACE("Format 1: Found Pair %x,%x\n",glyphs[glyph_index],glyphs[glyph_index+write_dir]); - - offset = GPOS_get_value_record(ValueFormat1, ps->PairValueRecord[k].Value1, &ValueRecord1); - GPOS_get_value_record(ValueFormat2, (WORD*)((const BYTE*)(ps->PairValueRecord[k].Value2)+offset), &ValueRecord2); - if (ValueFormat1) - { - GPOS_get_value_record_offsets((const BYTE*)ppf1, &ValueRecord1, ValueFormat1, ppem, &ptAdjust[0], &ptAdvance[0]); - TRACE("Glyph 1 resulting cumulative offset is %i,%i design units\n",ptAdjust[0].x,ptAdjust[0].y); - TRACE("Glyph 1 resulting cumulative advance is %i,%i design units\n",ptAdvance[0].x,ptAdvance[0].y); - } - if (ValueFormat2) - { - GPOS_get_value_record_offsets((const BYTE*)ppf1, &ValueRecord2, ValueFormat2, ppem, &ptAdjust[1], &ptAdvance[1]); - TRACE("Glyph 2 resulting cumulative offset is %i,%i design units\n",ptAdjust[1].x,ptAdjust[1].y); - TRACE("Glyph 2 resulting cumulative advance is %i,%i design units\n",ptAdvance[1].x,ptAdvance[1].y); - next++; - } - if (next) - return glyph_index + next; + apply_pair_value( ppf1, ValueFormat1, ValueFormat2, pair_val_rec->Value1, ppem, ptAdjust, ptAdvance ); + if (ValueFormat2) next++; + return glyph_index + next; } + pair_val_rec = (const GPOS_PairValueRecord *)(pair_val_rec->Value1 + val_fmt1_size + val_fmt2_size); + } + } + } + else if (GET_BE_WORD(ppf1->PosFormat) == 2) + { + const GPOS_PairPosFormat2 *ppf2 = (const GPOS_PairPosFormat2*)((const BYTE*)look + offset); + int index; + WORD ValueFormat1 = GET_BE_WORD( ppf2->ValueFormat1 ); + WORD ValueFormat2 = GET_BE_WORD( ppf2->ValueFormat2 ); + INT val_fmt1_size = GPOS_get_value_record( ValueFormat1, NULL, NULL ); + INT val_fmt2_size = GPOS_get_value_record( ValueFormat2, NULL, NULL ); + WORD class1_count = GET_BE_WORD( ppf2->Class1Count ); + WORD class2_count = GET_BE_WORD( ppf2->Class2Count ); + + offset = GET_BE_WORD( ppf2->Coverage ); + index = GSUB_is_glyph_covered( (const BYTE*)ppf2 + offset, glyphs[glyph_index] ); + if (index != -1) + { + WORD class1, class2; + class1 = OT_get_glyph_class( (const BYTE *)ppf2 + GET_BE_WORD(ppf2->ClassDef1), glyphs[glyph_index] ); + class2 = OT_get_glyph_class( (const BYTE *)ppf2 + GET_BE_WORD(ppf2->ClassDef2), glyphs[glyph_index + write_dir] ); + if (class1 < class1_count && class2 < class2_count) + { + const WORD *pair_val = ppf2->Class1Record + (class1 * class2_count + class2) * (val_fmt1_size + val_fmt2_size); + int next = 1; + + TRACE( "Format 2: Found Pair %x,%x\n", glyphs[glyph_index], glyphs[glyph_index + write_dir] ); + + apply_pair_value( ppf2, ValueFormat1, ValueFormat2, pair_val, ppem, ptAdjust, ptAdvance ); + if (ValueFormat2) next++; + return glyph_index + next; } } } @@ -1248,9 +1327,63 @@ return glyph_index+1; }
-static VOID GPOS_apply_MarkToBase(const OT_LookupTable *look, const WORD *glyphs, INT glyph_index, INT write_dir, INT glyph_count, INT ppem, LPPOINT pt) +static VOID GPOS_apply_CursiveAttachment(const OT_LookupTable *look, const SCRIPT_ANALYSIS *analysis, const WORD *glyphs, INT glyph_index, + INT glyph_count, INT ppem, LPPOINT pt) { int j; + int write_dir = (analysis->fRTL && !analysis->fLogicalOrder) ? -1 : 1; + + if (glyph_index + write_dir < 0 || glyph_index + write_dir >= glyph_count) return; + + TRACE("Cursive Attachment Positioning Subtable\n"); + + for (j = 0; j < GET_BE_WORD(look->SubTableCount); j++) + { + const GPOS_CursivePosFormat1 *cpf1; + WORD offset = GET_BE_WORD(look->SubTable[j]); + cpf1 = (const GPOS_CursivePosFormat1*)((const BYTE*)look+offset); + if (GET_BE_WORD(cpf1->PosFormat) == 1) + { + int index_exit, index_entry; + offset = GET_BE_WORD( cpf1->Coverage ); + index_exit = GSUB_is_glyph_covered((const BYTE*)cpf1+offset, glyphs[glyph_index]); + if (index_exit != -1 && cpf1->EntryExitRecord[index_exit].ExitAnchor!= 0) + { + index_entry = GSUB_is_glyph_covered((const BYTE*)cpf1+offset, glyphs[glyph_index+write_dir]); + if (index_entry != -1 && cpf1->EntryExitRecord[index_entry].EntryAnchor != 0) + { + POINT exit_pt, entry_pt; + offset = GET_BE_WORD(cpf1->EntryExitRecord[index_exit].ExitAnchor); + GPOS_get_anchor_values((const BYTE*)cpf1 + offset, &exit_pt, ppem); + offset = GET_BE_WORD(cpf1->EntryExitRecord[index_entry].EntryAnchor); + GPOS_get_anchor_values((const BYTE*)cpf1 + offset, &entry_pt, ppem); + TRACE("Found linkage %x[%i,%i] %x[%i,%i]\n",glyphs[glyph_index], exit_pt.x,exit_pt.y, glyphs[glyph_index+write_dir], entry_pt.x, entry_pt.y); + pt->x = entry_pt.x - exit_pt.x; + pt->y = entry_pt.y - exit_pt.y; + return; + } + } + } + else + FIXME("Cursive Attachment Positioning: Format %i Unhandled\n",GET_BE_WORD(cpf1->PosFormat)); + } + return; +} + +static int GPOS_apply_MarkToBase(ScriptCache *psc, const OT_LookupTable *look, const SCRIPT_ANALYSIS *analysis, const WORD *glyphs, INT glyph_index, INT glyph_count, INT ppem, LPPOINT pt) +{ + int j; + int write_dir = (analysis->fRTL && !analysis->fLogicalOrder) ? -1 : 1; + void *glyph_class_table = NULL; + int rc = -1; + + if (psc->GDEF_Table) + { + const GDEF_Header *header = psc->GDEF_Table; + WORD offset = GET_BE_WORD( header->GlyphClassDef ); + if (offset) + glyph_class_table = (BYTE *)psc->GDEF_Table + offset; + }
TRACE("MarkToBase Attachment Positioning Subtable\n");
@@ -1268,8 +1401,16 @@ if (mark_index != -1) { int base_index; + int base_glyph = glyph_index - write_dir; + + if (glyph_class_table) + { + while (OT_get_glyph_class(glyph_class_table, glyphs[base_glyph]) == MarkGlyph && base_glyph > 0 && base_glyph < glyph_count) + base_glyph -= write_dir; + } + offset = GET_BE_WORD(mbpf1->BaseCoverage); - base_index = GSUB_is_glyph_covered((const BYTE*)mbpf1+offset, glyphs[glyph_index - write_dir]); + base_index = GSUB_is_glyph_covered((const BYTE*)mbpf1+offset, glyphs[base_glyph]); if (base_index != -1) { const GPOS_MarkArray *ma; @@ -1281,13 +1422,13 @@ int baserecord_size; POINT base_pt; POINT mark_pt; - TRACE("Mark %x(%i) and base %x(%i)\n",glyphs[glyph_index], mark_index, glyphs[glyph_index - write_dir], base_index); + TRACE("Mark %x(%i) and base %x(%i)\n",glyphs[glyph_index], mark_index, glyphs[base_glyph], base_index); offset = GET_BE_WORD(mbpf1->MarkArray); ma = (const GPOS_MarkArray*)((const BYTE*)mbpf1 + offset); if (mark_index > GET_BE_WORD(ma->MarkCount)) { ERR("Mark index exeeded mark count\n"); - return; + return -1; } mr = &ma->MarkRecord[mark_index]; mark_class = GET_BE_WORD(mr->Class); @@ -1305,17 +1446,115 @@ pt->x += base_pt.x - mark_pt.x; pt->y += base_pt.y - mark_pt.y; TRACE("Resulting cumulative offset is %i,%i design units\n",pt->x,pt->y); + rc = base_glyph; } } } else FIXME("Unhandled Mark To Base Format %i\n",GET_BE_WORD(mbpf1->PosFormat)); } -} - -static VOID GPOS_apply_MarkToMark(const OT_LookupTable *look, const WORD *glyphs, INT glyph_index, INT write_dir, INT glyph_count, INT ppem, LPPOINT pt) + return rc; +} + +static VOID GPOS_apply_MarkToLigature(const OT_LookupTable *look, const SCRIPT_ANALYSIS *analysis, const WORD *glyphs, INT glyph_index, + INT glyph_count, INT ppem, LPPOINT pt) { int j; + int write_dir = (analysis->fRTL && !analysis->fLogicalOrder) ? -1 : 1; + + TRACE("MarkToLigature Attachment Positioning Subtable\n"); + + for (j = 0; j < GET_BE_WORD(look->SubTableCount); j++) + { + int offset; + const GPOS_MarkLigPosFormat1 *mlpf1; + offset = GET_BE_WORD(look->SubTable[j]); + mlpf1 = (const GPOS_MarkLigPosFormat1*)((const BYTE*)look+offset); + if (GET_BE_WORD(mlpf1->PosFormat) == 1) + { + int offset = GET_BE_WORD(mlpf1->MarkCoverage); + int mark_index; + mark_index = GSUB_is_glyph_covered((const BYTE*)mlpf1+offset, glyphs[glyph_index]); + if (mark_index != -1) + { + int ligature_index; + offset = GET_BE_WORD(mlpf1->LigatureCoverage); + ligature_index = GSUB_is_glyph_covered((const BYTE*)mlpf1+offset, glyphs[glyph_index - write_dir]); + if (ligature_index != -1) + { + const GPOS_MarkArray *ma; + const GPOS_MarkRecord *mr; + + const GPOS_LigatureArray *la; + const GPOS_LigatureAttach *lt; + int mark_class; + int class_count = GET_BE_WORD(mlpf1->ClassCount); + int component_count; + int component_size; + int i; + POINT ligature_pt; + POINT mark_pt; + + TRACE("Mark %x(%i) and ligature %x(%i)\n",glyphs[glyph_index], mark_index, glyphs[glyph_index - write_dir], ligature_index); + offset = GET_BE_WORD(mlpf1->MarkArray); + ma = (const GPOS_MarkArray*)((const BYTE*)mlpf1 + offset); + if (mark_index > GET_BE_WORD(ma->MarkCount)) + { + ERR("Mark index exeeded mark count\n"); + return; + } + mr = &ma->MarkRecord[mark_index]; + mark_class = GET_BE_WORD(mr->Class); + TRACE("Mark Class %i total classes %i\n",mark_class,class_count); + offset = GET_BE_WORD(mlpf1->LigatureArray); + la = (const GPOS_LigatureArray*)((const BYTE*)mlpf1 + offset); + if (ligature_index > GET_BE_WORD(la->LigatureCount)) + { + ERR("Ligature index exeeded ligature count\n"); + return; + } + offset = GET_BE_WORD(la->LigatureAttach[ligature_index]); + lt = (const GPOS_LigatureAttach*)((const BYTE*)la + offset); + + component_count = GET_BE_WORD(lt->ComponentCount); + component_size = class_count * sizeof(WORD); + offset = 0; + for (i = 0; i < component_count && !offset; i++) + { + int k; + const GPOS_ComponentRecord *cr = (const GPOS_ComponentRecord*)((const BYTE*)lt->ComponentRecord + (component_size * i)); + for (k = 0; k < class_count && !offset; k++) + offset = GET_BE_WORD(cr->LigatureAnchor[k]); + cr = (const GPOS_ComponentRecord*)((const BYTE*)cr + component_size); + } + if (!offset) + { + ERR("Failed to find avalible ligature connection point\n"); + return; + } + + GPOS_get_anchor_values((const BYTE*)lt + offset, &ligature_pt, ppem); + offset = GET_BE_WORD(mr->MarkAnchor); + GPOS_get_anchor_values((const BYTE*)ma + offset, &mark_pt, ppem); + TRACE("Offset on ligature is %i,%i design units\n",ligature_pt.x,ligature_pt.y); + TRACE("Offset on mark is %i,%i design units\n",mark_pt.x, mark_pt.y); + pt->x += ligature_pt.x - mark_pt.x; + pt->y += ligature_pt.y - mark_pt.y; + TRACE("Resulting cumulative offset is %i,%i design units\n",pt->x,pt->y); + } + } + } + else + FIXME("Unhandled Mark To Ligature Format %i\n",GET_BE_WORD(mlpf1->PosFormat)); + } +} + +static BOOL GPOS_apply_MarkToMark(const OT_LookupTable *look, const SCRIPT_ANALYSIS *analysis, const WORD *glyphs, INT glyph_index, + INT glyph_count, INT ppem, LPPOINT pt) +{ + int j; + BOOL rc = FALSE; + int write_dir = (analysis->fRTL && !analysis->fLogicalOrder) ? -1 : 1;
TRACE("MarkToMark Attachment Positioning Subtable\n");
@@ -1352,7 +1591,7 @@ if (mark_index > GET_BE_WORD(ma->MarkCount)) { ERR("Mark index exeeded mark count\n"); - return; + return FALSE; } mr = &ma->MarkRecord[mark_index]; mark_class = GET_BE_WORD(mr->Class); @@ -1370,17 +1609,22 @@ pt->x += mark2_pt.x - mark_pt.x; pt->y += mark2_pt.y - mark_pt.y; TRACE("Resulting cumulative offset is %i,%i design units\n",pt->x,pt->y); + rc = TRUE; } } } else FIXME("Unhandled Mark To Mark Format %i\n",GET_BE_WORD(mmpf1->PosFormat)); } -} - -static INT GPOS_apply_ChainContextPos(LPOUTLINETEXTMETRICW lpotm, LPLOGFONTW lplogfont, INT* piAdvance, const OT_LookupList *lookup, const OT_LookupTable *look, const WORD *glyphs, INT glyph_index, INT write_dir, INT glyph_count, INT ppem, GOFFSET *pGoffset) + return rc; +} + +static INT GPOS_apply_ChainContextPos(ScriptCache *psc, LPOUTLINETEXTMETRICW lpotm, LPLOGFONTW lplogfont, const SCRIPT_ANALYSIS *analysis, INT* piAdvance, + const OT_LookupList *lookup, const OT_LookupTable *look, const WORD *glyphs, INT glyph_index, + INT glyph_count, INT ppem, GOFFSET *pGoffset) { int j; + int write_dir = (analysis->fRTL && !analysis->fLogicalOrder) ? -1 : 1;
TRACE("Chaining Contextual Positioning Subtable\n");
@@ -1462,7 +1706,7 @@ int SequenceIndex = GET_BE_WORD(ccpf3_4->PosLookupRecord[k].SequenceIndex) * write_dir;
TRACE("Position: %i -> %i %i\n",k, SequenceIndex, lookupIndex); - GPOS_apply_lookup(lpotm, lplogfont, piAdvance, lookup, lookupIndex, glyphs, glyph_index + SequenceIndex, write_dir, glyph_count, pGoffset); + GPOS_apply_lookup(psc, lpotm, lplogfont, analysis, piAdvance, lookup, lookupIndex, glyphs, glyph_index + SequenceIndex, glyph_count, pGoffset); } return glyph_index + indexGlyphs + GET_BE_WORD(ccpf3_3->LookaheadGlyphCount); } @@ -1474,7 +1718,7 @@ return glyph_index + 1; }
-static INT GPOS_apply_lookup(LPOUTLINETEXTMETRICW lpotm, LPLOGFONTW lplogfont, INT* piAdvance, const OT_LookupList* lookup, INT lookup_index, const WORD *glyphs, INT glyph_index, INT write_dir, INT glyph_count, GOFFSET *pGoffset) +static INT GPOS_apply_lookup(ScriptCache *psc, LPOUTLINETEXTMETRICW lpotm, LPLOGFONTW lplogfont, const SCRIPT_ANALYSIS *analysis, INT* piAdvance, const OT_LookupList* lookup, INT lookup_index, const WORD *glyphs, INT glyph_index, INT glyph_count, GOFFSET *pGoffset) { int offset; const OT_LookupTable *look; @@ -1490,7 +1734,7 @@ double devX, devY; POINT adjust = {0,0}; POINT advance = {0,0}; - GPOS_apply_SingleAdjustment(look, glyphs, glyph_index, write_dir, glyph_count, ppem, &adjust, &advance); + GPOS_apply_SingleAdjustment(look, analysis, glyphs, glyph_index, glyph_count, ppem, &adjust, &advance); if (adjust.x || adjust.y) { GPOS_convert_design_units_to_device(lpotm, lplogfont, adjust.x, adjust.y, &devX, &devY); @@ -1512,11 +1756,14 @@ POINT adjust[2]= {{0,0},{0,0}}; double devX, devY; int index; - index = GPOS_apply_PairAdjustment(look, glyphs, glyph_index, write_dir, glyph_count, ppem, adjust, advance); + int write_dir = (analysis->fRTL && !analysis->fLogicalOrder) ? -1 : 1; + int offset_sign = (analysis->fRTL && analysis->fLogicalOrder) ? -1 : 1; + + index = GPOS_apply_PairAdjustment(look, analysis, glyphs, glyph_index, glyph_count, ppem, adjust, advance); if (adjust[0].x || adjust[0].y) { GPOS_convert_design_units_to_device(lpotm, lplogfont, adjust[0].x, adjust[0].y, &devX, &devY); - pGoffset[glyph_index].du += round(devX); + pGoffset[glyph_index].du += round(devX) * offset_sign; pGoffset[glyph_index].dv += round(devY); } if (advance[0].x || advance[0].y) @@ -1527,7 +1774,7 @@ if (adjust[1].x || adjust[1].y) { GPOS_convert_design_units_to_device(lpotm, lplogfont, adjust[1].x, adjust[1].y, &devX, &devY); - pGoffset[glyph_index + write_dir].du += round(devX); + pGoffset[glyph_index + write_dir].du += round(devX) * offset_sign; pGoffset[glyph_index + write_dir].dv += round(devY); } if (advance[1].x || advance[1].y) @@ -1537,35 +1784,69 @@ } return index; } + case 3: + { + POINT desU = {0,0}; + double devX, devY; + int write_dir = (analysis->fRTL && !analysis->fLogicalOrder) ? -1 : 1; + + GPOS_apply_CursiveAttachment(look, analysis, glyphs, glyph_index, glyph_count, ppem, &desU); + if (desU.x || desU.y) + { + GPOS_convert_design_units_to_device(lpotm, lplogfont, desU.x, desU.y, &devX, &devY); + /* Windows does not appear to apply X offsets here */ + pGoffset[glyph_index].dv = round(devY) + pGoffset[glyph_index+write_dir].dv; + } + break; + } case 4: { double devX, devY; POINT desU = {0,0}; - GPOS_apply_MarkToBase(look, glyphs, glyph_index, write_dir, glyph_count, ppem, &desU); - if (desU.x || desU.y) + int base_index = GPOS_apply_MarkToBase(psc, look, analysis, glyphs, glyph_index, glyph_count, ppem, &desU); + if (base_index != -1) { GPOS_convert_design_units_to_device(lpotm, lplogfont, desU.x, desU.y, &devX, &devY); - pGoffset[glyph_index].du += (round(devX) - piAdvance[glyph_index-1]); - pGoffset[glyph_index].dv += round(devY); + if (!analysis->fRTL) pGoffset[glyph_index].du = round(devX) - piAdvance[base_index]; + else + { + if (analysis->fLogicalOrder) devX *= -1; + pGoffset[glyph_index].du = round(devX); + } + pGoffset[glyph_index].dv = round(devY); } break; } - case 6: + case 5: { double devX, devY; POINT desU = {0,0}; - GPOS_apply_MarkToMark(look, glyphs, glyph_index, write_dir, glyph_count, ppem, &desU); + GPOS_apply_MarkToLigature(look, analysis, glyphs, glyph_index, glyph_count, ppem, &desU); if (desU.x || desU.y) { GPOS_convert_design_units_to_device(lpotm, lplogfont, desU.x, desU.y, &devX, &devY); - pGoffset[glyph_index].du += round(devX) + pGoffset[glyph_index-1].du; - pGoffset[glyph_index].dv += round(devY) + pGoffset[glyph_index-1].dv; + pGoffset[glyph_index].du = (round(devX) - piAdvance[glyph_index-1]); + pGoffset[glyph_index].dv = round(devY); } break; } + case 6: + { + double devX, devY; + POINT desU = {0,0}; + int write_dir = (analysis->fRTL && !analysis->fLogicalOrder) ? -1 : 1; + if (GPOS_apply_MarkToMark(look, analysis, glyphs, glyph_index, glyph_count, ppem, &desU)) + { + GPOS_convert_design_units_to_device(lpotm, lplogfont, desU.x, desU.y, &devX, &devY); + if (analysis->fRTL && analysis->fLogicalOrder) devX *= -1; + pGoffset[glyph_index].du = round(devX) + pGoffset[glyph_index - write_dir].du; + pGoffset[glyph_index].dv = round(devY) + pGoffset[glyph_index - write_dir].dv; + } + break; + } case 8: { - return GPOS_apply_ChainContextPos(lpotm, lplogfont, piAdvance, lookup, look, glyphs, glyph_index, write_dir, glyph_count, ppem, pGoffset); + return GPOS_apply_ChainContextPos(psc, lpotm, lplogfont, analysis, piAdvance, lookup, look, glyphs, glyph_index, glyph_count, ppem, pGoffset); } default: FIXME("We do not handle SubType %i\n",GET_BE_WORD(look->LookupType)); @@ -1573,12 +1854,12 @@ return glyph_index+1; }
-INT OpenType_apply_GPOS_lookup(LPOUTLINETEXTMETRICW lpotm, LPLOGFONTW lplogfont, INT* piAdvance, LPCVOID table, INT lookup_index, const WORD *glyphs, INT glyph_index, INT write_dir, INT glyph_count, GOFFSET *pGoffset) -{ - const GPOS_Header *header = (const GPOS_Header *)table; +INT OpenType_apply_GPOS_lookup(ScriptCache *psc, LPOUTLINETEXTMETRICW lpotm, LPLOGFONTW lplogfont, const SCRIPT_ANALYSIS *analysis, INT* piAdvance, INT lookup_index, const WORD *glyphs, INT glyph_index, INT glyph_count, GOFFSET *pGoffset) +{ + const GPOS_Header *header = (const GPOS_Header *)psc->GPOS_Table; const OT_LookupList *lookup = (const OT_LookupList*)((const BYTE*)header + GET_BE_WORD(header->LookupList));
- return GPOS_apply_lookup(lpotm, lplogfont, piAdvance, lookup, lookup_index, glyphs, glyph_index, write_dir, glyph_count, pGoffset); + return GPOS_apply_lookup(psc, lpotm, lplogfont, analysis, piAdvance, lookup, lookup_index, glyphs, glyph_index, glyph_count, pGoffset); }
static void GSUB_initialize_script_cache(ScriptCache *psc) @@ -1617,6 +1898,9 @@ script = (const OT_ScriptList*)((const BYTE*)header + GET_BE_WORD(header->ScriptList)); count = GET_BE_WORD(script->ScriptCount);
+ if (!count) + return; + if (!psc->script_count) { psc->script_count = count; @@ -1660,10 +1944,11 @@
static void _initialize_script_cache(ScriptCache *psc) { - if (!psc->script_count) + if (!psc->scripts_initialized) { GSUB_initialize_script_cache(psc); GPOS_expand_script_cache(psc); + psc->scripts_initialized = TRUE; } }
@@ -1748,6 +2033,10 @@ count = GET_BE_WORD(table->LangSysCount);
TRACE("Deflang %p, LangCount %i\n",script->default_language.gpos_table, count); + + if (!count) + return; + if (!script->language_count) { int i; @@ -1791,10 +2080,11 @@
static void _initialize_language_cache(LoadedScript *script) { - if (!script->language_count) + if (!script->languages_initialized) { GSUB_initialize_language_cache(script); GPOS_expand_language_cache(script); + script->languages_initialized = TRUE; } }
@@ -1893,6 +2183,7 @@ language->features[i].lookups = HeapAlloc(GetProcessHeap(),0,sizeof(WORD) * language->features[i].lookup_count); for (j = 0; j < language->features[i].lookup_count; j++) language->features[i].lookups[j] = GET_BE_WORD(feature->LookupListIndex[j]); + language->features[i].tableType = FEATURE_GSUB_TABLE; } } } @@ -1912,6 +2203,10 @@ feature_list = (const OT_FeatureList*)((const BYTE*)header + GET_BE_WORD(header->FeatureList));
TRACE("%i features\n",count); + + if (!count) + return; + if (!language->feature_count) { language->feature_count = count; @@ -1933,10 +2228,11 @@ language->features[i].lookups = HeapAlloc(GetProcessHeap(),0,sizeof(WORD) * language->features[i].lookup_count); for (j = 0; j < language->features[i].lookup_count; j++) language->features[i].lookups[j] = GET_BE_WORD(feature->LookupListIndex[j]); - } - } - } - else if (count) + language->features[i].tableType = FEATURE_GPOS_TABLE; + } + } + } + else { language->features = HeapReAlloc(GetProcessHeap(),0,language->features, sizeof(LoadedFeature)*(language->feature_count + count));
@@ -1954,6 +2250,7 @@ language->features[idx].lookups = HeapAlloc(GetProcessHeap(),0,sizeof(WORD) * language->features[idx].lookup_count); for (j = 0; j < language->features[idx].lookup_count; j++) language->features[idx].lookups[j] = GET_BE_WORD(feature->LookupListIndex[j]); + language->features[idx].tableType = FEATURE_GPOS_TABLE; } language->feature_count += count; } @@ -1961,14 +2258,15 @@
static void _initialize_feature_cache(ScriptCache *psc, LoadedLanguage *language) { - if (!language->feature_count) + if (!language->features_initialized) { GSUB_initialize_feature_cache(psc->GSUB_Table, language); GPOS_expand_feature_cache(psc->GPOS_Table, language); - } -} - -HRESULT OpenType_GetFontFeatureTags(ScriptCache *psc, OPENTYPE_TAG script_tag, OPENTYPE_TAG language_tag, BOOL filtered, OPENTYPE_TAG searchingFor, int cMaxTags, OPENTYPE_TAG *pFeatureTags, int *pcTags, LoadedFeature** feature) + language->features_initialized = TRUE; + } +} + +HRESULT OpenType_GetFontFeatureTags(ScriptCache *psc, OPENTYPE_TAG script_tag, OPENTYPE_TAG language_tag, BOOL filtered, OPENTYPE_TAG searchingFor, char tableType, int cMaxTags, OPENTYPE_TAG *pFeatureTags, int *pcTags, LoadedFeature** feature) { int i; HRESULT rc = S_OK; @@ -2019,7 +2317,15 @@
_initialize_feature_cache(psc, language);
- *pcTags = language->feature_count; + if (tableType) + { + *pcTags = 0; + for (i = 0; i < language->feature_count; i++) + if (language->features[i].tableType == tableType) + *pcTags = (*pcTags)+1; + } + else + *pcTags = language->feature_count;
if (!searchingFor && cMaxTags < *pcTags) rc = E_OUTOFMEMORY; @@ -2029,11 +2335,15 @@ for (i = 0; i < language->feature_count; i++) { if (i < cMaxTags) - pFeatureTags[i] = language->features[i].tag; + { + if (!tableType || language->features[i].tableType == tableType) + pFeatureTags[i] = language->features[i].tag; + }
if (searchingFor) { - if (searchingFor == language->features[i].tag) + if ((searchingFor == language->features[i].tag) && + (!tableType || language->features[i].tableType == tableType)) { pFeatureTags[0] = language->features[i].tag; *pcTags = 1;
Modified: trunk/reactos/dll/win32/usp10/shape.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/usp10/shape.c?rev... ============================================================================== --- trunk/reactos/dll/win32/usp10/shape.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/usp10/shape.c [iso-8859-1] Wed Feb 27 14:11:44 2013 @@ -19,19 +19,19 @@ * */ #include <stdarg.h> -//#include <stdlib.h> - -#include <windef.h> -#include <winbase.h> -#include <wingdi.h> -//#include "winuser.h" -//#include "winnls.h" -#include <usp10.h> -//#include "winternl.h" +#include <stdlib.h> + +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "winuser.h" +#include "winnls.h" +#include "usp10.h" +#include "winternl.h"
#include "usp10_internal.h"
-#include <wine/debug.h> +#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(uniscribe);
@@ -41,6 +41,7 @@ typedef VOID (*ContextualShapingProc)(HDC, ScriptCache*, SCRIPT_ANALYSIS*, WCHAR*, INT, WORD*, INT*, INT, WORD*);
+static void ContextualShape_Control(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); static void ContextualShape_Arabic(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); static void ContextualShape_Hebrew(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); static void ContextualShape_Syriac(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); @@ -63,7 +64,9 @@
typedef VOID (*ShapeCharGlyphPropProc)( HDC , ScriptCache*, SCRIPT_ANALYSIS*, const WCHAR*, const INT, const WORD*, const INT, WORD*, SCRIPT_CHARPROP*, SCRIPT_GLYPHPROP*);
-static void ShapeCharGlyphProp_Default( HDC hdc, ScriptCache* psc, SCRIPT_ANALYSIS* psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD* pwLogClust, SCRIPT_CHARPROP* pCharProp, SCRIPT_GLYPHPROP* pGlyphProp); +static void ShapeCharGlyphProp_Default( ScriptCache* psc, SCRIPT_ANALYSIS* psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD* pwLogClust, SCRIPT_CHARPROP* pCharProp, SCRIPT_GLYPHPROP* pGlyphProp); +static void ShapeCharGlyphProp_Control( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD *pwLogClust, SCRIPT_CHARPROP* pCharProp, SCRIPT_GLYPHPROP *pGlyphProp ); +static void ShapeCharGlyphProp_Latin( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD *pwLogClust, SCRIPT_CHARPROP* pCharProp, SCRIPT_GLYPHPROP *pGlyphProp ); static void ShapeCharGlyphProp_Arabic( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD *pwLogClust, SCRIPT_CHARPROP* pCharProp, SCRIPT_GLYPHPROP *pGlyphProp ); static void ShapeCharGlyphProp_Hebrew( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD *pwLogClust, SCRIPT_CHARPROP* pCharProp, SCRIPT_GLYPHPROP *pGlyphProp ); static void ShapeCharGlyphProp_Thai( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD *pwLogClust, SCRIPT_CHARPROP *pCharProp, SCRIPT_GLYPHPROP *pGlyphProp ); @@ -142,6 +145,8 @@
static OPENTYPE_FEATURE_RECORD latin_features[] = { + { MS_MAKE_TAG('l','o','c','l'), 1}, + { MS_MAKE_TAG('c','c','m','p'), 1}, { MS_MAKE_TAG('l','i','g','a'), 1}, { MS_MAKE_TAG('c','l','i','g'), 1}, }; @@ -182,6 +187,7 @@
static OPENTYPE_FEATURE_RECORD hebrew_features[] = { + { MS_MAKE_TAG('c','c','m','p'), 1}, { MS_MAKE_TAG('d','l','i','g'), 0}, };
@@ -450,14 +456,14 @@ static const ScriptShapeData ShapingData[] = { {{ standard_features, 2}, {NULL, 0}, NULL, 0, NULL, NULL}, - {{ latin_features, 2}, {latin_gpos_features, 3}, NULL, 0, NULL, NULL}, - {{ latin_features, 2}, {latin_gpos_features, 3}, NULL, 0, NULL, NULL}, - {{ latin_features, 2}, {latin_gpos_features, 3}, NULL, 0, NULL, NULL}, - {{ standard_features, 2}, {NULL, 0}, NULL, 0, NULL, NULL}, - {{ latin_features, 2}, {latin_gpos_features, 3}, NULL, 0, NULL, NULL}, + {{ latin_features, 4}, {latin_gpos_features, 3}, NULL, 0, NULL, ShapeCharGlyphProp_Latin}, + {{ latin_features, 4}, {latin_gpos_features, 3}, NULL, 0, NULL, ShapeCharGlyphProp_Latin}, + {{ latin_features, 4}, {latin_gpos_features, 3}, NULL, 0, NULL, ShapeCharGlyphProp_Latin}, + {{ standard_features, 2}, {NULL, 0}, NULL, 0, ContextualShape_Control, ShapeCharGlyphProp_Control}, + {{ latin_features, 4}, {latin_gpos_features, 3}, NULL, 0, NULL, ShapeCharGlyphProp_Latin}, {{ arabic_features, 6}, {arabic_gpos_features, 4}, required_arabic_features, 0, ContextualShape_Arabic, ShapeCharGlyphProp_Arabic}, {{ arabic_features, 6}, {arabic_gpos_features, 4}, required_arabic_features, 0, ContextualShape_Arabic, ShapeCharGlyphProp_Arabic}, - {{ hebrew_features, 1}, {hebrew_gpos_features, 2}, NULL, 0, ContextualShape_Hebrew, ShapeCharGlyphProp_Hebrew}, + {{ hebrew_features, 2}, {hebrew_gpos_features, 2}, NULL, 0, ContextualShape_Hebrew, ShapeCharGlyphProp_Hebrew}, {{ syriac_features, 4}, {syriac_gpos_features, 3}, required_syriac_features, 0, ContextualShape_Syriac, ShapeCharGlyphProp_None}, {{ arabic_features, 6}, {arabic_gpos_features, 4}, required_arabic_features, 0, ContextualShape_Arabic, ShapeCharGlyphProp_Arabic}, {{ NULL, 0}, {NULL, 0}, NULL, 0, ContextualShape_Thaana, ShapeCharGlyphProp_None}, @@ -494,7 +500,7 @@ {{ devanagari_features, 6}, {devanagari_gpos_features, 4}, required_telugu_features, MS_MAKE_TAG('m','l','m','2'), ContextualShape_Malayalam, ShapeCharGlyphProp_Malayalam}, {{ devanagari_features, 6}, {devanagari_gpos_features, 4}, required_telugu_features, MS_MAKE_TAG('m','l','m','2'), ContextualShape_Malayalam, NULL}, {{ standard_features, 2}, {NULL, 0}, NULL, 0, NULL, NULL}, - {{ latin_features, 2}, {latin_gpos_features, 3}, NULL, 0, NULL, NULL}, + {{ latin_features, 4}, {latin_gpos_features, 3}, NULL, 0, NULL, ShapeCharGlyphProp_Latin}, {{ standard_features, 2}, {NULL, 0}, NULL, 0, NULL, NULL}, {{ myanmar_features, 2}, {NULL, 0}, NULL, 0, NULL, NULL}, {{ myanmar_features, 2}, {NULL, 0}, NULL, 0, NULL, NULL}, @@ -528,8 +534,8 @@ {{ NULL, 0}, {NULL, 0}, NULL, 0, NULL, NULL}, {{ NULL, 0}, {NULL, 0}, NULL, 0, NULL, NULL}, {{ NULL, 0}, {NULL, 0}, NULL, 0, NULL, NULL}, - {{ hebrew_features, 1}, {hebrew_gpos_features, 2}, NULL, 0, ContextualShape_Hebrew, NULL}, - {{ latin_features, 2}, {latin_gpos_features, 3}, NULL, 0, NULL, NULL}, + {{ hebrew_features, 2}, {hebrew_gpos_features, 2}, NULL, 0, ContextualShape_Hebrew, NULL}, + {{ latin_features, 4}, {latin_gpos_features, 3}, NULL, 0, NULL, ShapeCharGlyphProp_Latin}, {{ thai_features, 1}, {thai_gpos_features, 3}, NULL, 0, ContextualShape_Thai, ShapeCharGlyphProp_Thai}, };
@@ -602,7 +608,7 @@ } }
-static LoadedFeature* load_OT_feature(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache *psc, const char* feat) +static LoadedFeature* load_OT_feature(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache *psc, char tableType, const char* feat) { LoadedFeature *feature = NULL;
@@ -611,7 +617,7 @@ int attempt = 2; OPENTYPE_TAG tags; OPENTYPE_TAG language; - OPENTYPE_TAG script; + OPENTYPE_TAG script = 0x00000000; int cTags;
do @@ -623,13 +629,13 @@ language = MS_MAKE_TAG('d','f','l','t'); attempt--;
- OpenType_GetFontFeatureTags(psc, script, language, FALSE, MS_MAKE_TAG(feat[0],feat[1],feat[2],feat[3]), 1, &tags, &cTags, &feature); + OpenType_GetFontFeatureTags(psc, script, language, FALSE, MS_MAKE_TAG(feat[0],feat[1],feat[2],feat[3]), tableType, 1, &tags, &cTags, &feature);
} while(attempt && !feature);
/* try in the default (latin) table */ - if (!feature) - OpenType_GetFontFeatureTags(psc, MS_MAKE_TAG('l','a','t','n'), MS_MAKE_TAG('d','f','l','t'), FALSE, MS_MAKE_TAG(feat[0],feat[1],feat[2],feat[3]), 1, &tags, &cTags, &feature); + if (!feature && !script) + OpenType_GetFontFeatureTags(psc, MS_MAKE_TAG('l','a','t','n'), MS_MAKE_TAG('d','f','l','t'), FALSE, MS_MAKE_TAG(feat[0],feat[1],feat[2],feat[3]), tableType, 1, &tags, &cTags, &feature); }
TRACE("Feature %s located at %p\n",debugstr_an(feat,4),feature); @@ -640,7 +646,7 @@ { LoadedFeature *feature;
- feature = load_OT_feature(hdc, psa, psc, feat); + feature = load_OT_feature(hdc, psa, psc, FEATURE_GSUB_TABLE, feat); if (!feature) return GSUB_E_NOFEATURE;
@@ -672,6 +678,19 @@ TRACE("Loaded GPOS table of %i bytes\n",length); } return GPOS_Table; +} + +static VOID *load_gdef_table(HDC hdc) +{ + VOID* GDEF_Table = NULL; + int length = GetFontData(hdc, MS_MAKE_TAG('G', 'D', 'E', 'F'), 0, NULL, 0); + if (length != GDI_ERROR) + { + GDEF_Table = HeapAlloc(GetProcessHeap(),0,length); + GetFontData(hdc, MS_MAKE_TAG('G', 'D', 'E', 'F'), 0, GDEF_Table, length); + TRACE("Loaded GDEF table of %i bytes\n",length); + } + return GDEF_Table; }
static VOID load_ot_tables(HDC hdc, ScriptCache *psc) @@ -680,6 +699,8 @@ psc->GSUB_Table = load_gsub_table(hdc); if (!psc->GPOS_Table) psc->GPOS_Table = load_gpos_table(hdc); + if (!psc->GDEF_Table) + psc->GDEF_Table = load_gdef_table(hdc); }
INT SHAPE_does_GSUB_feature_apply_to_chars(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, const WCHAR *chars, INT write_dir, INT count, const char* feature) @@ -825,7 +846,7 @@ LoadedFeature *feature; int lookup_index;
- feature = load_OT_feature(hdc, psa, psc, feat); + feature = load_OT_feature(hdc, psa, psc, FEATURE_GSUB_TABLE, feat); if (!feature) return GSUB_E_NOFEATURE;
@@ -859,7 +880,7 @@ return GSUB_E_NOFEATURE; }
-static VOID GPOS_apply_feature(LPOUTLINETEXTMETRICW lpotm, LPLOGFONTW lplogfont, INT* piAdvance, LPCVOID header, LoadedFeature *feature, const WORD *glyphs, INT write_dir, INT glyph_count, GOFFSET *pGoffset) +static VOID GPOS_apply_feature(ScriptCache *psc, LPOUTLINETEXTMETRICW lpotm, LPLOGFONTW lplogfont, const SCRIPT_ANALYSIS *analysis, INT* piAdvance, LoadedFeature *feature, const WORD *glyphs, INT glyph_count, GOFFSET *pGoffset) { int i;
@@ -868,7 +889,7 @@ { int j; for (j = 0; j < glyph_count; ) - j = OpenType_apply_GPOS_lookup(lpotm, lplogfont, piAdvance, header, feature->lookups[i], glyphs, j, write_dir, glyph_count, pGoffset); + j = OpenType_apply_GPOS_lookup(psc, lpotm, lplogfont, analysis, piAdvance, feature->lookups[i], glyphs, j, glyph_count, pGoffset); } }
@@ -920,6 +941,23 @@ }
HeapFree(GetProcessHeap(),0,context_type); +} + +static void ContextualShape_Control(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) +{ + int i; + for (i=0; i < cChars; i++) + { + switch (pwcChars[i]) + { + case 0x000D: pwOutGlyphs[i] = psc->sfp.wgBlank; break; + default: + if (pwcChars[i] < 0x1C) + pwOutGlyphs[i] = psc->sfp.wgDefault; + else + pwOutGlyphs[i] = psc->sfp.wgBlank; + } + } }
static WCHAR neighbour_char(int i, int delta, const WCHAR* chars, INT cchLen) @@ -2020,17 +2058,17 @@ { int c; int overall_shift = 0; - LoadedFeature *locl = (modern)?load_OT_feature(hdc, psa, psc, "locl"):NULL; - LoadedFeature *nukt = load_OT_feature(hdc, psa, psc, "nukt"); - LoadedFeature *akhn = load_OT_feature(hdc, psa, psc, "akhn"); - LoadedFeature *rkrf = (modern)?load_OT_feature(hdc, psa, psc, "rkrf"):NULL; - LoadedFeature *pstf = load_OT_feature(hdc, psa, psc, "pstf"); - LoadedFeature *vatu = (!rkrf)?load_OT_feature(hdc, psa, psc, "vatu"):NULL; - LoadedFeature *cjct = (modern)?load_OT_feature(hdc, psa, psc, "cjct"):NULL; - BOOL rphf = (load_OT_feature(hdc, psa, psc, "rphf") != NULL); - BOOL pref = (load_OT_feature(hdc, psa, psc, "pref") != NULL); - BOOL blwf = (load_OT_feature(hdc, psa, psc, "blwf") != NULL); - BOOL half = (load_OT_feature(hdc, psa, psc, "half") != NULL); + LoadedFeature *locl = (modern)?load_OT_feature(hdc, psa, psc, FEATURE_GSUB_TABLE, "locl"):NULL; + LoadedFeature *nukt = load_OT_feature(hdc, psa, psc, FEATURE_GSUB_TABLE, "nukt"); + LoadedFeature *akhn = load_OT_feature(hdc, psa, psc, FEATURE_GSUB_TABLE, "akhn"); + LoadedFeature *rkrf = (modern)?load_OT_feature(hdc, psa, psc, FEATURE_GSUB_TABLE, "rkrf"):NULL; + LoadedFeature *pstf = load_OT_feature(hdc, psa, psc, FEATURE_GSUB_TABLE, "pstf"); + LoadedFeature *vatu = (!rkrf)?load_OT_feature(hdc, psa, psc, FEATURE_GSUB_TABLE, "vatu"):NULL; + LoadedFeature *cjct = (modern)?load_OT_feature(hdc, psa, psc, FEATURE_GSUB_TABLE, "cjct"):NULL; + BOOL rphf = (load_OT_feature(hdc, psa, psc, FEATURE_GSUB_TABLE, "rphf") != NULL); + BOOL pref = (load_OT_feature(hdc, psa, psc, FEATURE_GSUB_TABLE, "pref") != NULL); + BOOL blwf = (load_OT_feature(hdc, psa, psc, FEATURE_GSUB_TABLE, "blwf") != NULL); + BOOL half = (load_OT_feature(hdc, psa, psc, FEATURE_GSUB_TABLE, "half") != NULL); IndicSyllable glyph_indexs;
for (c = 0; c < syllable_count; c++) @@ -2739,8 +2777,6 @@ else dirL = 1;
- load_ot_tables(hdc, psc); - if (!psc->GSUB_Table) return;
@@ -2783,7 +2819,7 @@ HeapFree(GetProcessHeap(),0,context_shape); }
-static void ShapeCharGlyphProp_Default( HDC hdc, ScriptCache* psc, SCRIPT_ANALYSIS* psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD* pwLogClust, SCRIPT_CHARPROP* pCharProp, SCRIPT_GLYPHPROP* pGlyphProp) +static void ShapeCharGlyphProp_Default( ScriptCache* psc, SCRIPT_ANALYSIS* psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD* pwLogClust, SCRIPT_CHARPROP* pCharProp, SCRIPT_GLYPHPROP* pGlyphProp) { int i,k;
@@ -2811,8 +2847,35 @@ pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_CHARACTER; }
- OpenType_GDEF_UpdateGlyphProps(hdc, psc, pwGlyphs, cGlyphs, pwLogClust, cChars, pGlyphProp); + OpenType_GDEF_UpdateGlyphProps(psc, pwGlyphs, cGlyphs, pwLogClust, cChars, pGlyphProp); UpdateClustersFromGlyphProp(cGlyphs, cChars, pwLogClust, pGlyphProp); +} + +static void ShapeCharGlyphProp_Latin( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD *pwLogClust, SCRIPT_CHARPROP *pCharProp, SCRIPT_GLYPHPROP *pGlyphProp ) +{ + int i; + + ShapeCharGlyphProp_Default( psc, psa, pwcChars, cChars, pwGlyphs, cGlyphs, pwLogClust, pCharProp, pGlyphProp); + + for (i = 0; i < cGlyphs; i++) + if (pGlyphProp[i].sva.fZeroWidth) + pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_NONE; +} + +static void ShapeCharGlyphProp_Control( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD *pwLogClust, SCRIPT_CHARPROP *pCharProp, SCRIPT_GLYPHPROP *pGlyphProp ) +{ + int i; + for (i = 0; i < cGlyphs; i++) + { + pGlyphProp[i].sva.fClusterStart = 1; + pGlyphProp[i].sva.fDiacritic = 0; + pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_BLANK; + + if (pwGlyphs[i] == psc->sfp.wgDefault) + pGlyphProp[i].sva.fZeroWidth = 0; + else + pGlyphProp[i].sva.fZeroWidth = 1; + } }
static void ShapeCharGlyphProp_Arabic( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD *pwLogClust, SCRIPT_CHARPROP *pCharProp, SCRIPT_GLYPHPROP *pGlyphProp ) @@ -2920,7 +2983,7 @@ pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_NONE; }
- OpenType_GDEF_UpdateGlyphProps(hdc, psc, pwGlyphs, cGlyphs, pwLogClust, cChars, pGlyphProp); + OpenType_GDEF_UpdateGlyphProps(psc, pwGlyphs, cGlyphs, pwLogClust, cChars, pGlyphProp); UpdateClustersFromGlyphProp(cGlyphs, cChars, pwLogClust, pGlyphProp); HeapFree(GetProcessHeap(),0,spaces); } @@ -2951,7 +3014,7 @@ } }
- OpenType_GDEF_UpdateGlyphProps(hdc, psc, pwGlyphs, cGlyphs, pwLogClust, cChars, pGlyphProp); + OpenType_GDEF_UpdateGlyphProps(psc, pwGlyphs, cGlyphs, pwLogClust, cChars, pGlyphProp); UpdateClustersFromGlyphProp(cGlyphs, cChars, pwLogClust, pGlyphProp); }
@@ -2972,7 +3035,7 @@ dirL = 1; }
- OpenType_GDEF_UpdateGlyphProps(hdc, psc, pwGlyphs, cGlyphs, pwLogClust, cChars, pGlyphProp); + OpenType_GDEF_UpdateGlyphProps(psc, pwGlyphs, cGlyphs, pwLogClust, cChars, pGlyphProp);
for (i = 0; i < cGlyphs; i++) { @@ -3040,7 +3103,7 @@ else pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_NONE; } - OpenType_GDEF_UpdateGlyphProps(hdc, psc, pwGlyphs, cGlyphs, pwLogClust, cChars, pGlyphProp); + OpenType_GDEF_UpdateGlyphProps(psc, pwGlyphs, cGlyphs, pwLogClust, cChars, pGlyphProp); UpdateClustersFromGlyphProp(cGlyphs, cChars, pwLogClust, pGlyphProp); }
@@ -3071,7 +3134,7 @@ else pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_NONE; } - OpenType_GDEF_UpdateGlyphProps(hdc, psc, pwGlyphs, cGlyphs, pwLogClust, cChars, pGlyphProp); + OpenType_GDEF_UpdateGlyphProps(psc, pwGlyphs, cGlyphs, pwLogClust, cChars, pGlyphProp); UpdateClustersFromGlyphProp(cGlyphs, cChars, pwLogClust, pGlyphProp);
/* Tibeten script does not set sva.fDiacritic or sva.fZeroWidth */ @@ -3089,7 +3152,7 @@ { int i,k;
- OpenType_GDEF_UpdateGlyphProps(hdc, psc, pwGlyphs, cGlyphs, pwLogClust, cChars, pGlyphProp); + OpenType_GDEF_UpdateGlyphProps(psc, pwGlyphs, cGlyphs, pwLogClust, cChars, pGlyphProp); for (i = 0; i < cGlyphs; i++) { int char_index[20]; @@ -3233,10 +3296,12 @@
void SHAPE_CharGlyphProp(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD *pwLogClust, SCRIPT_CHARPROP *pCharProp, SCRIPT_GLYPHPROP *pGlyphProp) { + load_ot_tables(hdc, psc); + if (ShapingData[psa->eScript].charGlyphPropProc) ShapingData[psa->eScript].charGlyphPropProc(hdc, psc, psa, pwcChars, cChars, pwGlyphs, cGlyphs, pwLogClust, pCharProp, pGlyphProp); else - ShapeCharGlyphProp_Default(hdc, psc, psa, pwcChars, cChars, pwGlyphs, cGlyphs, pwLogClust, pCharProp, pGlyphProp); + ShapeCharGlyphProp_Default(psc, psa, pwcChars, cChars, pwGlyphs, cGlyphs, pwLogClust, pCharProp, pGlyphProp); }
void SHAPE_ContextualShaping(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) @@ -3284,7 +3349,6 @@ { const TEXTRANGE_PROPERTIES *rpRangeProperties; int i; - INT dirL;
rpRangeProperties = &ShapingData[psa->eScript].defaultGPOSTextRange;
@@ -3296,22 +3360,17 @@ if (!psc->GPOS_Table || !psc->otm) return;
- if (!psa->fLogicalOrder && psa->fRTL) - dirL = -1; - else - dirL = 1; - for (i = 0; i < rpRangeProperties->cotfRecords; i++) { if (rpRangeProperties->potfRecords[i].lParameter > 0) { LoadedFeature *feature;
- feature = load_OT_feature(hdc, psa, psc, (const char*)&rpRangeProperties->potfRecords[i].tagFeature); + feature = load_OT_feature(hdc, psa, psc, FEATURE_GPOS_TABLE, (const char*)&rpRangeProperties->potfRecords[i].tagFeature); if (!feature) continue;
- GPOS_apply_feature(psc->otm, &psc->lf, piAdvance, psc->GPOS_Table, feature, pwGlyphs, dirL, cGlyphs, pGoffset); + GPOS_apply_feature(psc, psc->otm, &psc->lf, psa, piAdvance, feature, pwGlyphs, cGlyphs, pGoffset); } } } @@ -3330,7 +3389,7 @@ i = 0; while (ShapingData[psa->eScript].requiredFeatures[i]) { - feature = load_OT_feature(hdc, psa, psc, ShapingData[psa->eScript].requiredFeatures[i]); + feature = load_OT_feature(hdc, psa, psc, FEATURE_ALL_TABLES, ShapingData[psa->eScript].requiredFeatures[i]); if (feature) return S_OK; i++; @@ -3401,7 +3460,7 @@ filter = TRUE; }
- hr = OpenType_GetFontFeatureTags(psc, tagScript, tagLangSys, filter, 0x00000000, cMaxTags, pFeatureTags, pcTags, NULL); + hr = OpenType_GetFontFeatureTags(psc, tagScript, tagLangSys, filter, 0x00000000, FEATURE_ALL_TABLES, cMaxTags, pFeatureTags, pcTags, NULL);
if (FAILED(hr)) *pcTags = 0;
Modified: trunk/reactos/dll/win32/usp10/shaping.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/usp10/shaping.c?r... ============================================================================== --- trunk/reactos/dll/win32/usp10/shaping.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/usp10/shaping.c [iso-8859-1] Wed Feb 27 14:11:44 2013 @@ -2,7 +2,7 @@ /* generated from http://www.unicode.org/Public/6.0.0/ucd/ArabicShaping.txt */ /* DO NOT EDIT!! */
-//#include "wine/unicode.h" +#include "wine/unicode.h"
const unsigned short wine_shaping_table[2656] = {
Modified: trunk/reactos/dll/win32/usp10/usp10.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/usp10/usp10.c?rev... ============================================================================== --- trunk/reactos/dll/win32/usp10/usp10.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/usp10/usp10.c [iso-8859-1] Wed Feb 27 14:11:44 2013 @@ -25,20 +25,20 @@ */
#include <stdarg.h> -//#include <stdlib.h> - -#include <windef.h> -//#include "winbase.h" -#include <wingdi.h> -#include <winuser.h> -//#include "winnls.h" -#include <winreg.h> -#include <usp10.h> +#include <stdlib.h> + +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "winuser.h" +#include "winnls.h" +#include "winreg.h" +#include "usp10.h"
#include "usp10_internal.h"
-#include <wine/debug.h> -#include <wine/unicode.h> +#include "wine/debug.h" +#include "wine/unicode.h"
WINE_DEFAULT_DEBUG_CHANNEL(uniscribe);
@@ -513,7 +513,7 @@ {0x53, 0, 1, 1, 1, DEFAULT_CHARSET, 0, 0, 0, 0, 1, 0, 0, 0, 0}, MS_MAKE_TAG('k','h','m','r'), {'D','a','u','n','P','e','n','h'}}, - {{Script_Khmer, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, + {{Script_Khmer_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, {0x53, 1, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, MS_MAKE_TAG('k','h','m','r'), {'D','a','u','n','P','e','n','h'}}, @@ -999,23 +999,6 @@ }
/*********************************************************************** - * DllMain - * - */ -BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv) -{ - switch(fdwReason) - { - case DLL_PROCESS_ATTACH: - DisableThreadLibraryCalls(hInstDLL); - break; - case DLL_PROCESS_DETACH: - break; - } - return TRUE; -} - -/*********************************************************************** * ScriptFreeCache (USP10.@) * * Free a script cache. @@ -1060,6 +1043,9 @@ heap_free(((ScriptCache *)*psc)->scripts[i].languages[j].features[k].lookups); heap_free(((ScriptCache *)*psc)->scripts[i].languages[j].features); } + for (j = 0; j < ((ScriptCache *)*psc)->scripts[i].default_language.feature_count; j++) + heap_free(((ScriptCache *)*psc)->scripts[i].default_language.features[j].lookups); + heap_free(((ScriptCache *)*psc)->scripts[i].default_language.features); heap_free(((ScriptCache *)*psc)->scripts[i].languages); } heap_free(((ScriptCache *)*psc)->scripts); @@ -1270,28 +1256,11 @@ }; }
-/*********************************************************************** - * ScriptItemizeOpenType (USP10.@) - * - * Split a Unicode string into shapeable parts. - * - * PARAMS - * pwcInChars [I] String to split. - * cInChars [I] Number of characters in pwcInChars. - * cMaxItems [I] Maximum number of items to return. - * psControl [I] Pointer to a SCRIPT_CONTROL structure. - * psState [I] Pointer to a SCRIPT_STATE structure. - * pItems [O] Buffer to receive SCRIPT_ITEM structures. - * pScriptTags [O] Buffer to receive OPENTYPE_TAGs. - * pcItems [O] Number of script items returned. - * - * RETURNS - * Success: S_OK - * Failure: Non-zero HRESULT value. - */ -HRESULT WINAPI ScriptItemizeOpenType(const WCHAR *pwcInChars, int cInChars, int cMaxItems, - const SCRIPT_CONTROL *psControl, const SCRIPT_STATE *psState, - SCRIPT_ITEM *pItems, OPENTYPE_TAG *pScriptTags, int *pcItems) + +static HRESULT _ItemizeInternal(const WCHAR *pwcInChars, int cInChars, + int cMaxItems, const SCRIPT_CONTROL *psControl, + const SCRIPT_STATE *psState, SCRIPT_ITEM *pItems, + OPENTYPE_TAG *pScriptTags, int *pcItems) {
#define Numeric_space 0x0020 @@ -1346,8 +1315,36 @@ forceLevels = TRUE;
/* Diacritical marks merge with other scripts */ - if (scripts[i] == Script_Diacritical && i > 0) - scripts[i] = scripts[i-1]; + if (scripts[i] == Script_Diacritical) + { + if (i > 0) + { + if (pScriptTags) + scripts[i] = scripts[i-1]; + else + { + int j; + BOOL asian = FALSE; + WORD first_script = scripts[i-1]; + for (j = i-1; j >= 0 && scripts[j] == first_script && pwcInChars[j] != Numeric_space; j--) + { + WORD original = scripts[j]; + if (original == Script_Ideograph || original == Script_Kana || original == Script_Yi || original == Script_CJK_Han || original == Script_Bopomofo) + { + asian = TRUE; + break; + } + if (original != Script_MathAlpha && scriptInformation[scripts[j]].props.fComplex) + break; + scripts[j] = scripts[i]; + if (original == Script_Punctuation2) + break; + } + if (scriptInformation[scripts[j]].props.fComplex || asian) + scripts[i] = scripts[j]; + } + } + } }
for (i = 0; i < cInChars; i++) @@ -1496,7 +1493,8 @@
pItems[index].iCharPos = 0; pItems[index].a = scriptInformation[scripts[cnt]].a; - pScriptTags[index] = scriptInformation[scripts[cnt]].scriptTag; + if (pScriptTags) + pScriptTags[index] = scriptInformation[scripts[cnt]].scriptTag;
if (strength && strength[cnt] == BIDI_STRONG) str = strength[cnt]; @@ -1590,7 +1588,8 @@ memset(&pItems[index].a, 0, sizeof(SCRIPT_ANALYSIS));
pItems[index].a = scriptInformation[New_Script].a; - pScriptTags[index] = scriptInformation[New_Script].scriptTag; + if (pScriptTags) + pScriptTags[index] = scriptInformation[New_Script].scriptTag; if (levels) { if (levels[cnt] == 0) @@ -1633,6 +1632,32 @@ }
/*********************************************************************** + * ScriptItemizeOpenType (USP10.@) + * + * Split a Unicode string into shapeable parts. + * + * PARAMS + * pwcInChars [I] String to split. + * cInChars [I] Number of characters in pwcInChars. + * cMaxItems [I] Maximum number of items to return. + * psControl [I] Pointer to a SCRIPT_CONTROL structure. + * psState [I] Pointer to a SCRIPT_STATE structure. + * pItems [O] Buffer to receive SCRIPT_ITEM structures. + * pScriptTags [O] Buffer to receive OPENTYPE_TAGs. + * pcItems [O] Number of script items returned. + * + * RETURNS + * Success: S_OK + * Failure: Non-zero HRESULT value. + */ +HRESULT WINAPI ScriptItemizeOpenType(const WCHAR *pwcInChars, int cInChars, int cMaxItems, + const SCRIPT_CONTROL *psControl, const SCRIPT_STATE *psState, + SCRIPT_ITEM *pItems, OPENTYPE_TAG *pScriptTags, int *pcItems) +{ + return _ItemizeInternal(pwcInChars, cInChars, cMaxItems, psControl, psState, pItems, pScriptTags, pcItems); +} + +/*********************************************************************** * ScriptItemize (USP10.@) * * Split a Unicode string into shapeable parts. @@ -1654,15 +1679,7 @@ const SCRIPT_CONTROL *psControl, const SCRIPT_STATE *psState, SCRIPT_ITEM *pItems, int *pcItems) { - OPENTYPE_TAG *discarded_tags; - HRESULT res; - - discarded_tags = heap_alloc(cMaxItems * sizeof(OPENTYPE_TAG)); - if (!discarded_tags) - return E_OUTOFMEMORY; - res = ScriptItemizeOpenType(pwcInChars, cInChars, cMaxItems, psControl, psState, pItems, discarded_tags, pcItems); - heap_free(discarded_tags); - return res; + return _ItemizeInternal(pwcInChars, cInChars, cMaxItems, psControl, psState, pItems, NULL, pcItems); }
static inline int getGivenTabWidth(ScriptCache *psc, SCRIPT_TABDEF *pTabdef, int charPos, int current_x) @@ -1847,7 +1864,7 @@ hr = ScriptItemize(pString, cString, num_items, &sControl, &sState, analysis->pItem, &analysis->numItems);
- if FAILED(hr) + if (FAILED(hr)) { if (hr == E_OUTOFMEMORY) hr = E_INVALIDARG; @@ -1935,7 +1952,7 @@ if ((dwFlags & SSA_LINK) && !analysis->glyphs[i].fallbackFont && analysis->pItem[i].a.eScript == Script_Hangul) analysis->pItem[i].a.fNoGlyphIndex = TRUE;
- if ((dwFlags & SSA_LINK) && !analysis->glyphs[i].fallbackFont && !scriptInformation[analysis->pItem[i].a.eScript].props.fComplex) + if ((dwFlags & SSA_LINK) && !analysis->glyphs[i].fallbackFont && !scriptInformation[analysis->pItem[i].a.eScript].props.fComplex && !analysis->pItem[i].a.fRTL) analysis->pItem[i].a.fNoGlyphIndex = TRUE;
hr = ScriptShape(hdc, sc, &pStr[analysis->pItem[i].iCharPos], @@ -3237,8 +3254,9 @@ const int *piJustify, const GOFFSET *pGoffset) { HRESULT hr = S_OK; - INT i; + INT i, dir = 1; INT *lpDx; + WORD *reordered_glyphs = (WORD *)pwGlyphs;
TRACE("(%p, %p, %d, %d, %04x, %p, %p, %p, %d, %p, %d, %p, %p, %p)\n", hdc, psc, x, y, fuOptions, lprc, psa, pwcReserved, iReserved, pwGlyphs, cGlyphs, @@ -3253,67 +3271,50 @@ fuOptions |= ETO_GLYPH_INDEX; /* Say don't do translation to glyph */
lpDx = heap_alloc(cGlyphs * sizeof(INT) * 2); - - if (pGoffset) - { + if (!lpDx) return E_OUTOFMEMORY; + fuOptions |= ETO_PDY; + + if (psa->fRTL && psa->fLogicalOrder) + { + reordered_glyphs = heap_alloc( cGlyphs * sizeof(WORD) ); + if (!reordered_glyphs) + { + heap_free( lpDx ); + return E_OUTOFMEMORY; + } + for (i = 0; i < cGlyphs; i++) - if (!(fuOptions&ETO_PDY) && pGoffset[i].dv) - fuOptions |= ETO_PDY; - } + reordered_glyphs[i] = pwGlyphs[cGlyphs - 1 - i]; + dir = -1; + } + for (i = 0; i < cGlyphs; i++) { - int idx = i; - if (fuOptions&ETO_PDY) - { - idx *=2; - lpDx[idx+1] = 0; - } - lpDx[idx] = piAdvance[i]; - } - if (pGoffset) - { - for (i = 1; i < cGlyphs; i++) - { - int idx = i; - int prev_idx = i-1; - if (fuOptions&ETO_PDY) + int orig_index = (dir > 0) ? i : cGlyphs - 1 - i; + lpDx[i * 2] = piAdvance[orig_index]; + lpDx[i * 2 + 1] = 0; + + if (pGoffset) + { + if (i == 0) { - idx*=2; - prev_idx = idx-2; + x += pGoffset[orig_index].du * dir; + y += pGoffset[orig_index].dv; } - lpDx[prev_idx] += pGoffset[i].du; - lpDx[idx] -= pGoffset[i].du; - if (fuOptions&ETO_PDY) + else { - lpDx[prev_idx+1] += pGoffset[i].dv; - lpDx[idx+1] -= pGoffset[i].dv; + lpDx[(i - 1) * 2] += pGoffset[orig_index].du * dir; + lpDx[(i - 1) * 2 + 1] += pGoffset[orig_index].dv; } - } - } - - if (psa->fRTL && psa->fLogicalOrder) - { - int i; - WORD *rtlGlyphs; - - rtlGlyphs = heap_alloc(cGlyphs * sizeof(WORD)); - if (!rtlGlyphs) - { - heap_free(lpDx); - return E_OUTOFMEMORY; - } - - for (i = 0; i < cGlyphs; i++) - rtlGlyphs[i] = pwGlyphs[cGlyphs-1-i]; - - if (!ExtTextOutW(hdc, x, y, fuOptions, lprc, rtlGlyphs, cGlyphs, lpDx)) - hr = S_FALSE; - heap_free(rtlGlyphs); - } - else - if (!ExtTextOutW(hdc, x, y, fuOptions, lprc, pwGlyphs, cGlyphs, lpDx)) - hr = S_FALSE; - + lpDx[i * 2] -= pGoffset[orig_index].du * dir; + lpDx[i * 2 + 1] -= pGoffset[orig_index].dv; + } + } + + if (!ExtTextOutW(hdc, x, y, fuOptions, lprc, reordered_glyphs, cGlyphs, lpDx)) + hr = S_FALSE; + + if (reordered_glyphs != pwGlyphs) heap_free( reordered_glyphs ); heap_free(lpDx);
return hr;
Modified: trunk/reactos/dll/win32/usp10/usp10_internal.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/usp10/usp10_inter... ============================================================================== --- trunk/reactos/dll/win32/usp10/usp10_internal.h [iso-8859-1] (original) +++ trunk/reactos/dll/win32/usp10/usp10_internal.h [iso-8859-1] Wed Feb 27 14:11:44 2013 @@ -128,8 +128,13 @@ #define GSUB_E_NOFEATURE -2 #define GSUB_E_NOGLYPH -1
+#define FEATURE_ALL_TABLES 0 +#define FEATURE_GSUB_TABLE 1 +#define FEATURE_GPOS_TABLE 2 + typedef struct { OPENTYPE_TAG tag; + CHAR tableType; LPCVOID feature; INT lookup_count; WORD *lookups; @@ -139,6 +144,7 @@ OPENTYPE_TAG tag; LPCVOID gsub_table; LPCVOID gpos_table; + BOOL features_initialized; INT feature_count; LoadedFeature *features; } LoadedLanguage; @@ -148,6 +154,7 @@ LPCVOID gsub_table; LPCVOID gpos_table; LoadedLanguage default_language; + BOOL languages_initialized; INT language_count; LoadedLanguage *languages; } LoadedScript; @@ -169,6 +176,7 @@ LPVOID CMAP_Table; LPVOID CMAP_format12_Table; LPVOID GPOS_Table; + BOOL scripts_initialized; INT script_count; LoadedScript *scripts;
@@ -223,7 +231,7 @@ INT BIDI_ReorderL2vLevel(int level, int *pIndexs, const BYTE* plevel, int cch, BOOL fReverse) DECLSPEC_HIDDEN; void SHAPE_ContextualShaping(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) DECLSPEC_HIDDEN; void SHAPE_ApplyDefaultOpentypeFeatures(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, INT cChars, WORD *pwLogClust) DECLSPEC_HIDDEN; -void SHAPE_ApplyOpenTypePositions(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WORD* pwGlyphs, INT cGlyphs, int *piAdvance, GOFFSET *pGoffset ); +void SHAPE_ApplyOpenTypePositions(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WORD* pwGlyphs, INT cGlyphs, int *piAdvance, GOFFSET *pGoffset ) DECLSPEC_HIDDEN; HRESULT SHAPE_CheckFontForRequiredFeatures(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa) DECLSPEC_HIDDEN; void SHAPE_CharGlyphProp(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD *pwLogClust, SCRIPT_CHARPROP *pCharProp, SCRIPT_GLYPHPROP *pGlyphProp) DECLSPEC_HIDDEN; INT SHAPE_does_GSUB_feature_apply_to_chars(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, const WCHAR *chars, INT write_dir, INT count, const char* feature) DECLSPEC_HIDDEN; @@ -237,9 +245,9 @@ void BREAK_line(const WCHAR *chars, int count, const SCRIPT_ANALYSIS *sa, SCRIPT_LOGATTR *la) DECLSPEC_HIDDEN;
DWORD OpenType_CMAP_GetGlyphIndex(HDC hdc, ScriptCache *psc, DWORD utf32c, LPWORD pgi, DWORD flags) DECLSPEC_HIDDEN; -void OpenType_GDEF_UpdateGlyphProps(HDC hdc, ScriptCache *psc, const WORD *pwGlyphs, const WORD cGlyphs, WORD* pwLogClust, const WORD cChars, SCRIPT_GLYPHPROP *pGlyphProp) DECLSPEC_HIDDEN; +void OpenType_GDEF_UpdateGlyphProps(ScriptCache *psc, const WORD *pwGlyphs, const WORD cGlyphs, WORD* pwLogClust, const WORD cChars, SCRIPT_GLYPHPROP *pGlyphProp) DECLSPEC_HIDDEN; INT OpenType_apply_GSUB_lookup(LPCVOID table, INT lookup_index, WORD *glyphs, INT glyph_index, INT write_dir, INT *glyph_count) DECLSPEC_HIDDEN; -INT OpenType_apply_GPOS_lookup(LPOUTLINETEXTMETRICW lpotm, LPLOGFONTW lplogfont, INT* piAdvance, LPCVOID table, INT lookup_index, const WORD *glyphs, INT glyph_index, INT write_dir, INT glyph_count, GOFFSET *pGoffset) DECLSPEC_HIDDEN; +INT OpenType_apply_GPOS_lookup(ScriptCache *psc, LPOUTLINETEXTMETRICW lpotm, LPLOGFONTW lplogfont, const SCRIPT_ANALYSIS *analysis, INT* piAdvance, INT lookup_index, const WORD *glyphs, INT glyph_index, INT glyph_count, GOFFSET *pGoffset) DECLSPEC_HIDDEN; HRESULT OpenType_GetFontScriptTags(ScriptCache *psc, OPENTYPE_TAG searchingFor, int cMaxTags, OPENTYPE_TAG *pScriptTags, int *pcTags) DECLSPEC_HIDDEN; HRESULT OpenType_GetFontLanguageTags(ScriptCache *psc, OPENTYPE_TAG script_tag, OPENTYPE_TAG searchingFor, int cMaxTags, OPENTYPE_TAG *pLanguageTags, int *pcTags) DECLSPEC_HIDDEN; -HRESULT OpenType_GetFontFeatureTags(ScriptCache *psc, OPENTYPE_TAG script_tag, OPENTYPE_TAG language_tag, BOOL filtered, OPENTYPE_TAG searchingFor, int cMaxTags, OPENTYPE_TAG *pFeatureTags, int *pcTags, LoadedFeature** feature) DECLSPEC_HIDDEN; +HRESULT OpenType_GetFontFeatureTags(ScriptCache *psc, OPENTYPE_TAG script_tag, OPENTYPE_TAG language_tag, BOOL filtered, OPENTYPE_TAG searchingFor, char tableType, int cMaxTags, OPENTYPE_TAG *pFeatureTags, int *pcTags, LoadedFeature** feature) DECLSPEC_HIDDEN;
Modified: trunk/reactos/dll/win32/usp10/usp10_ros.diff URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/usp10/usp10_ros.d... ============================================================================== --- trunk/reactos/dll/win32/usp10/usp10_ros.diff [iso-8859-1] (original) +++ trunk/reactos/dll/win32/usp10/usp10_ros.diff [iso-8859-1] Wed Feb 27 14:11:44 2013 @@ -2,7 +2,7 @@ =================================================================== --- usp10.c (revision 54504) +++ usp10.c (working copy) -@@ -3621,3 +3621,9 @@ +@@ -3746,3 +3746,9 @@
return SHAPE_GetFontFeatureTags(hdc, (ScriptCache *)*psc, psa, tagScript, tagLangSys, cMaxTags, pFeatureTags, pcTags); }
Modified: trunk/reactos/media/doc/README.WINE URL: http://svn.reactos.org/svn/reactos/trunk/reactos/media/doc/README.WINE?rev=5... ============================================================================== --- trunk/reactos/media/doc/README.WINE [iso-8859-1] (original) +++ trunk/reactos/media/doc/README.WINE [iso-8859-1] Wed Feb 27 14:11:44 2013 @@ -179,7 +179,7 @@ reactos/dll/win32/updspapi # Synced to Wine-1.5.4 reactos/dll/win32/url # Synced to Wine-1.5.19 reactos/dll/win32/urlmon # Autosync -reactos/dll/win32/usp10 # Synced to Wine-1.5.19 +reactos/dll/win32/usp10 # Synced to Wine-1.5.24 reactos/dll/win32/uxtheme # Forked reactos/dll/win32/version # Autosync reactos/dll/win32/wer # Autosync