Index: reactos/win32ss/gdi/eng/engobjects.h =================================================================== --- reactos/win32ss/gdi/eng/engobjects.h (revision 75147) +++ reactos/win32ss/gdi/eng/engobjects.h (working copy) @@ -126,6 +126,8 @@ PSHARED_MEM Memory; SHARED_FACE_CACHE EnglishUS; SHARED_FACE_CACHE UserLanguage; + SHARED_FACE_CACHE EnglishUSVert; + SHARED_FACE_CACHE UserLanguageVert; } SHARED_FACE, *PSHARED_FACE; typedef struct _FONTGDI { @@ -148,6 +150,7 @@ BYTE OriginalItalic; LONG OriginalWeight; BYTE CharSet; + BOOL Vertical; } FONTGDI, *PFONTGDI; typedef struct _PATHGDI { Index: reactos/win32ss/gdi/ntgdi/freetype.c =================================================================== --- reactos/win32ss/gdi/ntgdi/freetype.c (revision 75147) +++ reactos/win32ss/gdi/ntgdi/freetype.c (working copy) @@ -194,6 +194,8 @@ Ptr->Memory = Memory; SharedFaceCache_Init(&Ptr->EnglishUS); SharedFaceCache_Init(&Ptr->UserLanguage); + SharedFaceCache_Init(&Ptr->EnglishUSVert); + SharedFaceCache_Init(&Ptr->UserLanguageVert); SharedMem_AddRef(Memory); DPRINT("Creating SharedFace for %s\n", Face->family_name); @@ -303,6 +305,8 @@ SharedMem_Release(Ptr->Memory); SharedFaceCache_Release(&Ptr->EnglishUS); SharedFaceCache_Release(&Ptr->UserLanguage); + SharedFaceCache_Release(&Ptr->EnglishUSVert); + SharedFaceCache_Release(&Ptr->UserLanguageVert); ExFreePoolWithTag(Ptr, TAG_FONT); } IntUnLockFreeType; @@ -777,8 +781,8 @@ } static INT FASTCALL -IntGdiLoadFontsFromMemory(PGDI_LOAD_FONT pLoadFont, - PSHARED_FACE SharedFace, FT_Long FontIndex, INT CharSetIndex) +IntGdiLoadFontsFromMemory(PGDI_LOAD_FONT pLoadFont, PSHARED_FACE SharedFace, + INT FontIndex, INT VertIndex, INT CharSetIndex) { FT_Error Error; PFONT_ENTRY Entry; @@ -793,12 +797,13 @@ DWORD Characteristics = pLoadFont->Characteristics; PUNICODE_STRING pValueName = &pLoadFont->RegValueName; TT_OS2 * pOS2; - INT BitIndex; + INT i, BitIndex; FT_UShort os2_version; FT_ULong os2_ulCodePageRange1; FT_UShort os2_usWeightClass; + BOOL FaceIsLoaded = FALSE; - if (SharedFace == NULL && CharSetIndex == -1) + if (SharedFace == NULL) { /* load a face from memory */ IntLockFreeType; @@ -828,6 +833,8 @@ DPRINT1("Error reading font (error code: %d)\n", Error); return 0; /* failure */ } + + FaceIsLoaded = TRUE; } else { @@ -907,9 +914,21 @@ FontGDI->RequestItalic = FALSE; FontGDI->OriginalWeight = WeightFromStyle(Face->style_name); FontGDI->RequestWeight = FW_NORMAL; + FontGDI->Vertical = (VertIndex == 1); - RtlInitAnsiString(&AnsiFaceName, Face->family_name); - Status = RtlAnsiStringToUnicodeString(&Entry->FaceName, &AnsiFaceName, TRUE); + if (VertIndex == 1) + { + char NewName[LF_FACESIZE] = "@"; + strcat(NewName, Face->family_name); + RtlInitAnsiString(&AnsiFaceName, NewName); + Status = RtlAnsiStringToUnicodeString(&Entry->FaceName, &AnsiFaceName, TRUE); + } + else + { + RtlInitAnsiString(&AnsiFaceName, Face->family_name); + Status = RtlAnsiStringToUnicodeString(&Entry->FaceName, &AnsiFaceName, TRUE); + } + if (!NT_SUCCESS(Status)) { if (PrivateEntry) @@ -989,9 +1008,9 @@ } ++FaceCount; - DPRINT("Font loaded: %s (%s)\n", Face->family_name, Face->style_name); - DPRINT("Num glyphs: %d\n", Face->num_glyphs); - DPRINT("CharSet: %d\n", FontGDI->CharSet); + DPRINT("Font loaded: %s%s (%s)\n", FontGDI->Vertical ? "@" : "", + Face->family_name, Face->style_name); + DPRINT("Num glyphs: %d, CharSet: %d\n", Face->num_glyphs, FontGDI->CharSet); /* Add this font resource to the font table */ Entry->Font = FontGDI; @@ -1015,25 +1034,31 @@ if (FontIndex == -1) { + FontIndex = 0; if (FT_IS_SFNT(Face)) { TT_Face TrueType = (TT_Face)Face; if (TrueType->ttc_header.count > 1) { - FT_Long i; - for (i = 1; i < TrueType->ttc_header.count; ++i) + for (i = FaceIsLoaded; i < TrueType->ttc_header.count; ++i) { - FaceCount += IntGdiLoadFontsFromMemory(pLoadFont, NULL, i, -1); + FaceCount += IntGdiLoadFontsFromMemory(pLoadFont, NULL, i, -1, -1); } } } - FontIndex = 0; } + if (VertIndex == -1) + { + VertIndex = 0; + if (FT_HAS_VERTICAL(Face)) + { + FaceCount += IntGdiLoadFontsFromMemory(pLoadFont, SharedFace, FontIndex, 1, -1); + } + } + if (CharSetIndex == -1) { - INT i; - if (pLoadFont->RegValueName.Length == 0) { RtlCreateUnicodeString(pValueName, Entry->FaceName.Buffer); @@ -1057,10 +1082,10 @@ *pValueName = NewString; } - for (i = 1; i < CharSetCount; ++i) + for (i = FaceIsLoaded; i < CharSetCount; ++i) { /* Do not count charsets towards 'faces' loaded */ - IntGdiLoadFontsFromMemory(pLoadFont, SharedFace, FontIndex, i); + IntGdiLoadFontsFromMemory(pLoadFont, SharedFace, FontIndex, VertIndex, i); } } @@ -1130,7 +1155,7 @@ RtlInitUnicodeString(&LoadFont.RegValueName, NULL); LoadFont.IsTrueType = FALSE; LoadFont.PrivateEntry = NULL; - FontCount = IntGdiLoadFontsFromMemory(&LoadFont, NULL, -1, -1); + FontCount = IntGdiLoadFontsFromMemory(&LoadFont, NULL, -1, -1, -1); ObDereferenceObject(SectionObject); @@ -1208,7 +1233,7 @@ RtlInitUnicodeString(&LoadFont.RegValueName, NULL); LoadFont.IsTrueType = FALSE; LoadFont.PrivateEntry = NULL; - FaceCount = IntGdiLoadFontsFromMemory(&LoadFont, NULL, -1, -1); + FaceCount = IntGdiLoadFontsFromMemory(&LoadFont, NULL, -1, -1, -1); RtlFreeUnicodeString(&LoadFont.RegValueName); @@ -1754,8 +1779,32 @@ FillTMEx(TM, FontGDI, pOS2, pHori, pFNT, FALSE); } +static inline PSHARED_FACE_CACHE +IntSelectCache(PFONTGDI FontGDI) +{ + PSHARED_FACE_CACHE Cache; + PSHARED_FACE SharedFace = FontGDI->SharedFace; + + if (PRIMARYLANGID(gusLanguageID) == LANG_ENGLISH) + { + if (FontGDI->Vertical) + Cache = &SharedFace->EnglishUSVert; + else + Cache = &SharedFace->EnglishUS; + } + else + { + if (FontGDI->Vertical) + Cache = &SharedFace->UserLanguageVert; + else + Cache = &SharedFace->UserLanguage; + } + + return Cache; +} + static NTSTATUS -IntGetFontLocalizedName(PUNICODE_STRING pNameW, PSHARED_FACE SharedFace, +IntGetFontLocalizedName(PUNICODE_STRING pNameW, PFONTGDI FontGDI, FT_UShort NameID, FT_UShort LangID); /************************************************************* @@ -1776,8 +1825,8 @@ char *Cp; UNICODE_STRING FamilyNameW, FaceNameW, StyleNameW, FullNameW; PSHARED_FACE SharedFace = FontGDI->SharedFace; - PSHARED_FACE_CACHE Cache = (PRIMARYLANGID(gusLanguageID) == LANG_ENGLISH) ? &SharedFace->EnglishUS : &SharedFace->UserLanguage; FT_Face Face = SharedFace->Face; + PSHARED_FACE_CACHE Cache = IntSelectCache(FontGDI); if (Cache->OutlineRequiredSize && Size < Cache->OutlineRequiredSize) { @@ -1786,29 +1835,37 @@ /* family name */ RtlInitUnicodeString(&FamilyNameW, NULL); - IntGetFontLocalizedName(&FamilyNameW, SharedFace, TT_NAME_ID_FONT_FAMILY, gusLanguageID); + IntGetFontLocalizedName(&FamilyNameW, FontGDI, TT_NAME_ID_FONT_FAMILY, gusLanguageID); /* face name */ RtlInitUnicodeString(&FaceNameW, NULL); - IntGetFontLocalizedName(&FaceNameW, SharedFace, TT_NAME_ID_FULL_NAME, gusLanguageID); + IntGetFontLocalizedName(&FaceNameW, FontGDI, TT_NAME_ID_FULL_NAME, gusLanguageID); /* style name */ RtlInitUnicodeString(&StyleNameW, NULL); - IntGetFontLocalizedName(&StyleNameW, SharedFace, TT_NAME_ID_FONT_SUBFAMILY, gusLanguageID); + IntGetFontLocalizedName(&StyleNameW, FontGDI, TT_NAME_ID_FONT_SUBFAMILY, gusLanguageID); /* unique name (full name) */ RtlInitUnicodeString(&FullNameW, NULL); - IntGetFontLocalizedName(&FullNameW, SharedFace, TT_NAME_ID_UNIQUE_ID, gusLanguageID); + IntGetFontLocalizedName(&FullNameW, FontGDI, TT_NAME_ID_UNIQUE_ID, gusLanguageID); if (!Cache->OutlineRequiredSize) { - UINT Needed; - Needed = sizeof(OUTLINETEXTMETRICW); - Needed += FamilyNameW.Length + sizeof(WCHAR); - Needed += FaceNameW.Length + sizeof(WCHAR); - Needed += StyleNameW.Length + sizeof(WCHAR); - Needed += FullNameW.Length + sizeof(WCHAR); - + UINT Needed = sizeof(OUTLINETEXTMETRICW); + if (FontGDI->Vertical) + { + Needed += FamilyNameW.Length + 2 * sizeof(WCHAR); + Needed += FaceNameW.Length + 2 * sizeof(WCHAR); + Needed += StyleNameW.Length + sizeof(WCHAR); + Needed += FullNameW.Length + 2 * sizeof(WCHAR); + } + else + { + Needed += FamilyNameW.Length + sizeof(WCHAR); + Needed += FaceNameW.Length + sizeof(WCHAR); + Needed += StyleNameW.Length + sizeof(WCHAR); + Needed += FullNameW.Length + sizeof(WCHAR); + } Cache->OutlineRequiredSize = Needed; } @@ -1903,26 +1960,53 @@ Cp = (char*) Otm + sizeof(OUTLINETEXTMETRICW); - /* family name */ - Otm->otmpFamilyName = (LPSTR)(Cp - (char*) Otm); - wcscpy((WCHAR*) Cp, FamilyNameW.Buffer); - Cp += FamilyNameW.Length + sizeof(WCHAR); + if (FontGDI->Vertical) + { + /* family name */ + Otm->otmpFamilyName = (LPSTR)(Cp - (char*) Otm); + ((WCHAR*) Cp)[0] = L'@'; + wcscpy((WCHAR*)Cp + 1, FamilyNameW.Buffer); + Cp += FamilyNameW.Length + 2 * sizeof(WCHAR); - /* face name */ - Otm->otmpFaceName = (LPSTR)(Cp - (char*) Otm); - wcscpy((WCHAR*) Cp, FaceNameW.Buffer); - Cp += FaceNameW.Length + sizeof(WCHAR); + /* face name */ + Otm->otmpFaceName = (LPSTR)(Cp - (char*) Otm); + ((WCHAR*) Cp)[0] = L'@'; + wcscpy((WCHAR*)Cp + 1, FaceNameW.Buffer); + Cp += FaceNameW.Length + 2 * sizeof(WCHAR); - /* style name */ - Otm->otmpStyleName = (LPSTR)(Cp - (char*) Otm); - wcscpy((WCHAR*) Cp, StyleNameW.Buffer); - Cp += StyleNameW.Length + sizeof(WCHAR); + /* style name */ + Otm->otmpStyleName = (LPSTR)(Cp - (char*) Otm); + wcscpy((WCHAR*) Cp, StyleNameW.Buffer); + Cp += StyleNameW.Length + sizeof(WCHAR); - /* unique name (full name) */ - Otm->otmpFullName = (LPSTR)(Cp - (char*) Otm); - wcscpy((WCHAR*) Cp, FullNameW.Buffer); - Cp += FullNameW.Length + sizeof(WCHAR); + /* unique name (full name) */ + Otm->otmpFullName = (LPSTR)(Cp - (char*) Otm); + ((WCHAR*) Cp)[0] = L'@'; + wcscpy((WCHAR*)Cp + 1, FullNameW.Buffer); + Cp += FullNameW.Length + 2 * sizeof(WCHAR); + } + else + { + /* family name */ + Otm->otmpFamilyName = (LPSTR)(Cp - (char*) Otm); + wcscpy((WCHAR*) Cp, FamilyNameW.Buffer); + Cp += FamilyNameW.Length + sizeof(WCHAR); + /* face name */ + Otm->otmpFaceName = (LPSTR)(Cp - (char*) Otm); + wcscpy((WCHAR*) Cp, FaceNameW.Buffer); + Cp += FaceNameW.Length + sizeof(WCHAR); + + /* style name */ + Otm->otmpStyleName = (LPSTR)(Cp - (char*) Otm); + wcscpy((WCHAR*) Cp, StyleNameW.Buffer); + Cp += StyleNameW.Length + sizeof(WCHAR); + + /* unique name (full name) */ + Otm->otmpFullName = (LPSTR)(Cp - (char*) Otm); + wcscpy((WCHAR*) Cp, FullNameW.Buffer); + Cp += FullNameW.Length + sizeof(WCHAR); + } ASSERT(Cp - (char*)Otm == Cache->OutlineRequiredSize); RtlFreeUnicodeString(&FamilyNameW); @@ -2085,7 +2169,7 @@ } static NTSTATUS -IntGetFontLocalizedName(PUNICODE_STRING pNameW, PSHARED_FACE SharedFace, +IntGetFontLocalizedName(PUNICODE_STRING pNameW, PFONTGDI FontGDI, FT_UShort NameID, FT_UShort LangID) { FT_SfntName Name; @@ -2094,21 +2178,12 @@ FT_Error Error; NTSTATUS Status = STATUS_NOT_FOUND; ANSI_STRING AnsiName; - PSHARED_FACE_CACHE Cache; + PSHARED_FACE_CACHE Cache = IntSelectCache(FontGDI); + PSHARED_FACE SharedFace = FontGDI->SharedFace; FT_Face Face = SharedFace->Face; RtlFreeUnicodeString(pNameW); - /* select cache */ - if (PRIMARYLANGID(LangID) == LANG_ENGLISH) - { - Cache = &SharedFace->EnglishUS; - } - else - { - Cache = &SharedFace->UserLanguage; - } - /* use cache if available */ if (NameID == TT_NAME_ID_FONT_FAMILY && Cache->FontFamily.Buffer) { @@ -5329,7 +5404,13 @@ plf->lfHeight, pmxWorldToDevice); if (!realglyph) { - error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT); + FT_Int32 load_flags = FT_LOAD_DEFAULT; + if (FontGDI->Vertical) + { + load_flags |= FT_LOAD_VERTICAL_LAYOUT; + } + + error = FT_Load_Glyph(face, glyph_index, load_flags); if (error) { DPRINT1("WARNING: Failed to load and render glyph! [index: %d]\n", glyph_index); @@ -5428,12 +5509,18 @@ BackgroundLeft = (RealXStart + 32) >> 6; for (i = 0; i < Count; ++i) { + FT_Int32 load_flags = FT_LOAD_DEFAULT; + if (FontGDI->Vertical) + { + load_flags |= FT_LOAD_VERTICAL_LAYOUT; + } + if (fuOptions & ETO_GLYPH_INDEX) glyph_index = String[i]; else glyph_index = FT_Get_Char_Index(face, String[i]); - error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT); + error = FT_Load_Glyph(face, glyph_index, load_flags); if (error) { DPRINT1("Failed to load and render glyph! [index: %d]\n", glyph_index); @@ -5554,7 +5641,13 @@ plf->lfHeight, pmxWorldToDevice); if (!realglyph) { - error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT); + FT_Int32 load_flags = FT_LOAD_DEFAULT; + if (FontGDI->Vertical) + { + load_flags |= FT_LOAD_VERTICAL_LAYOUT; + } + + error = FT_Load_Glyph(face, glyph_index, load_flags); if (error) { DPRINT1("Failed to load and render glyph! [index: %d]\n", glyph_index); @@ -6086,6 +6179,11 @@ for (i = FirstChar; i < FirstChar+Count; i++) { int adv, lsb, bbx, left, right; + FT_Int32 load_flags = FT_LOAD_DEFAULT; + if (FontGDI->Vertical) + { + load_flags |= FT_LOAD_VERTICAL_LAYOUT; + } if (Safepwch) { @@ -6101,7 +6199,7 @@ else glyph_index = FT_Get_Char_Index(face, i); } - FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT); + FT_Load_Glyph(face, glyph_index, load_flags); left = (INT)face->glyph->metrics.horiBearingX & -64; right = (INT)((face->glyph->metrics.horiBearingX + face->glyph->metrics.width) + 63) & -64; @@ -6281,6 +6379,12 @@ for (i = FirstChar; i < FirstChar+Count; i++) { + FT_Int32 load_flags = FT_LOAD_DEFAULT; + if (FontGDI->Vertical) + { + load_flags |= FT_LOAD_VERTICAL_LAYOUT; + } + if (Safepwc) { if (fl & GCW_INDICES) @@ -6295,7 +6399,7 @@ else glyph_index = FT_Get_Char_Index(face, i); } - FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT); + FT_Load_Glyph(face, glyph_index, load_flags); if (!fl) SafeBuffF[i - FirstChar] = (FLOAT) ((face->glyph->advance.x + 32) >> 6); else