2 * Opentype font interfaces for the Uniscribe Script Processor (usp10.dll)
4 * Copyright 2012 CodeWeavers, Aric Stewart
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
32 #include "usp10_internal.h"
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(uniscribe
);
38 #ifdef WORDS_BIGENDIAN
39 #define GET_BE_WORD(x) (x)
40 #define GET_BE_DWORD(x) (x)
42 #define GET_BE_WORD(x) RtlUshortByteSwap(x)
43 #define GET_BE_DWORD(x) RtlUlongByteSwap(x)
46 /* These are all structures needed for the cmap format 12 table */
47 #define CMAP_TAG MS_MAKE_TAG('c', 'm', 'a', 'p')
53 } CMAP_EncodingRecord
;
58 CMAP_EncodingRecord tables
[1];
65 } CMAP_SegmentedCoverage_group
;
73 CMAP_SegmentedCoverage_group groups
[1];
74 } CMAP_SegmentedCoverage
;
76 /* These are all structures needed for the GDEF table */
77 #define GDEF_TAG MS_MAKE_TAG('G', 'D', 'E', 'F')
79 enum {BaseGlyph
=1, LigatureGlyph
, MarkGlyph
, ComponentGlyph
};
86 WORD MarkAttachClassDef
;
93 WORD ClassValueArray
[1];
94 } GDEF_ClassDefFormat1
;
100 } GDEF_ClassRangeRecord
;
104 WORD ClassRangeCount
;
105 GDEF_ClassRangeRecord ClassRangeRecord
[1];
106 } GDEF_ClassDefFormat2
;
112 static VOID
*load_CMAP_format12_table(HDC hdc
, ScriptCache
*psc
)
114 CMAP_Header
*CMAP_Table
= NULL
;
118 if (!psc
->CMAP_Table
)
120 length
= GetFontData(hdc
, CMAP_TAG
, 0, NULL
, 0);
121 if (length
!= GDI_ERROR
)
123 psc
->CMAP_Table
= HeapAlloc(GetProcessHeap(),0,length
);
124 GetFontData(hdc
, CMAP_TAG
, 0, psc
->CMAP_Table
, length
);
125 TRACE("Loaded cmap table of %i bytes\n",length
);
131 CMAP_Table
= psc
->CMAP_Table
;
133 for (i
= 0; i
< GET_BE_WORD(CMAP_Table
->numTables
); i
++)
135 if ( (GET_BE_WORD(CMAP_Table
->tables
[i
].platformID
) == 3) &&
136 (GET_BE_WORD(CMAP_Table
->tables
[i
].encodingID
) == 10) )
138 CMAP_SegmentedCoverage
*format
= (CMAP_SegmentedCoverage
*)(((BYTE
*)CMAP_Table
) + GET_BE_DWORD(CMAP_Table
->tables
[i
].offset
));
139 if (GET_BE_WORD(format
->format
) == 12)
146 static int compare_group(const void *a
, const void* b
)
148 const DWORD
*chr
= a
;
149 const CMAP_SegmentedCoverage_group
*group
= b
;
151 if (*chr
< GET_BE_DWORD(group
->startCharCode
))
153 if (*chr
> GET_BE_DWORD(group
->endCharCode
))
158 DWORD
OpenType_CMAP_GetGlyphIndex(HDC hdc
, ScriptCache
*psc
, DWORD utf32c
, LPWORD pgi
, DWORD flags
)
160 /* BMP: use gdi32 for ease */
161 if (utf32c
< 0x10000)
164 return GetGlyphIndicesW(hdc
,&ch
, 1, pgi
, flags
);
167 if (!psc
->CMAP_format12_Table
)
168 psc
->CMAP_format12_Table
= load_CMAP_format12_table(hdc
, psc
);
170 if (flags
& GGI_MARK_NONEXISTING_GLYPHS
)
175 if (psc
->CMAP_format12_Table
)
177 CMAP_SegmentedCoverage
*format
= NULL
;
178 CMAP_SegmentedCoverage_group
*group
= NULL
;
180 format
= (CMAP_SegmentedCoverage
*)psc
->CMAP_format12_Table
;
182 group
= bsearch(&utf32c
, format
->groups
, GET_BE_DWORD(format
->nGroups
),
183 sizeof(CMAP_SegmentedCoverage_group
), compare_group
);
187 DWORD offset
= utf32c
- GET_BE_DWORD(group
->startCharCode
);
188 *pgi
= GET_BE_DWORD(group
->startGlyphID
) + offset
;
199 static WORD
GDEF_get_glyph_class(const GDEF_Header
*header
, WORD glyph
)
203 const GDEF_ClassDefFormat1
*cf1
;
208 offset
= GET_BE_WORD(header
->GlyphClassDef
);
212 cf1
= (GDEF_ClassDefFormat1
*)(((BYTE
*)header
)+offset
);
213 if (GET_BE_WORD(cf1
->ClassFormat
) == 1)
215 if (glyph
>= GET_BE_WORD(cf1
->StartGlyph
))
217 int index
= glyph
- GET_BE_WORD(cf1
->StartGlyph
);
218 if (index
< GET_BE_WORD(cf1
->GlyphCount
))
219 class = GET_BE_WORD(cf1
->ClassValueArray
[index
]);
222 else if (GET_BE_WORD(cf1
->ClassFormat
) == 2)
224 const GDEF_ClassDefFormat2
*cf2
= (GDEF_ClassDefFormat2
*)cf1
;
226 top
= GET_BE_WORD(cf2
->ClassRangeCount
);
227 for (i
= 0; i
< top
; i
++)
229 if (glyph
>= GET_BE_WORD(cf2
->ClassRangeRecord
[i
].Start
) &&
230 glyph
<= GET_BE_WORD(cf2
->ClassRangeRecord
[i
].End
))
232 class = GET_BE_WORD(cf2
->ClassRangeRecord
[i
].Class
);
238 ERR("Unknown Class Format %i\n",GET_BE_WORD(cf1
->ClassFormat
));
243 static VOID
*load_gdef_table(HDC hdc
)
245 VOID
* GDEF_Table
= NULL
;
246 int length
= GetFontData(hdc
, GDEF_TAG
, 0, NULL
, 0);
247 if (length
!= GDI_ERROR
)
249 GDEF_Table
= HeapAlloc(GetProcessHeap(),0,length
);
250 GetFontData(hdc
, GDEF_TAG
, 0, GDEF_Table
, length
);
251 TRACE("Loaded GDEF table of %i bytes\n",length
);
256 void OpenType_GDEF_UpdateGlyphProps(HDC hdc
, ScriptCache
*psc
, const WORD
*pwGlyphs
, const WORD cGlyphs
, WORD
* pwLogClust
, const WORD cChars
, SCRIPT_GLYPHPROP
*pGlyphProp
)
260 if (!psc
->GDEF_Table
)
261 psc
->GDEF_Table
= load_gdef_table(hdc
);
263 for (i
= 0; i
< cGlyphs
; i
++)
269 for (k
= 0; k
< cChars
; k
++)
270 if (pwLogClust
[k
] == i
)
273 class = GDEF_get_glyph_class(psc
->GDEF_Table
, pwGlyphs
[i
]);
279 pGlyphProp
[i
].sva
.fClusterStart
= 1;
280 pGlyphProp
[i
].sva
.fDiacritic
= 0;
281 pGlyphProp
[i
].sva
.fZeroWidth
= 0;
284 pGlyphProp
[i
].sva
.fClusterStart
= 1;
285 pGlyphProp
[i
].sva
.fDiacritic
= 0;
286 pGlyphProp
[i
].sva
.fZeroWidth
= 0;
289 pGlyphProp
[i
].sva
.fClusterStart
= 0;
290 pGlyphProp
[i
].sva
.fDiacritic
= 1;
291 pGlyphProp
[i
].sva
.fZeroWidth
= 1;
294 pGlyphProp
[i
].sva
.fClusterStart
= 0;
295 pGlyphProp
[i
].sva
.fDiacritic
= 0;
296 pGlyphProp
[i
].sva
.fZeroWidth
= 0;
299 ERR("Unknown glyph class %i\n",class);
300 pGlyphProp
[i
].sva
.fClusterStart
= 1;
301 pGlyphProp
[i
].sva
.fDiacritic
= 0;
302 pGlyphProp
[i
].sva
.fZeroWidth
= 0;
306 pGlyphProp
[i
].sva
.fClusterStart
= 0;