Index: rostests/apitests/gdi32/CMakeLists.txt =================================================================== --- rostests/apitests/gdi32/CMakeLists.txt (revision 75147) +++ rostests/apitests/gdi32/CMakeLists.txt (working copy) @@ -72,6 +72,7 @@ SetSysColors.c SetWindowExtEx.c SetWorldTransform.c + Tategaki.c init.c testlist.c) Index: rostests/apitests/gdi32/resource.rc =================================================================== --- rostests/apitests/gdi32/resource.rc (revision 75147) +++ rostests/apitests/gdi32/resource.rc (working copy) @@ -5,3 +5,4 @@ TTCTestV.ttc RCDATA TTCTestV.ttc Shadows_Into_Light.ttf RCDATA Shadows_Into_Light.ttf ExampleFont.ttf RCDATA ExampleFont.ttf +TategakiTest.ttf RCDATA TategakiTest.ttf Index: rostests/apitests/gdi32/Tategaki.c =================================================================== --- rostests/apitests/gdi32/Tategaki.c (nonexistent) +++ rostests/apitests/gdi32/Tategaki.c (working copy) @@ -0,0 +1,266 @@ +/* + * PROJECT: ReactOS api tests + * LICENSE: GPL - See COPYING in the top level directory + * PURPOSE: Tests for tategaki font (vertically writing) + * PROGRAMMERS: Katayama Hirofumi MZ + */ +#include +#include +#include + +/* #define CREATE_BITMAPS */ + +/* create 24bpp bitmap */ +static HBITMAP Create24BppBitmapDx(INT width, INT height) +{ + BITMAPINFO bi; + HDC hDC; + LPVOID pvBits; + HBITMAP hbm; + + ZeroMemory(&bi, sizeof(bi)); + bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bi.bmiHeader.biWidth = width; + bi.bmiHeader.biHeight = height; + bi.bmiHeader.biPlanes = 1; + bi.bmiHeader.biBitCount = 24; + bi.bmiHeader.biCompression = BI_RGB; + hDC = CreateCompatibleDC(NULL); + hbm = CreateDIBSection(hDC, &bi, DIB_RGB_COLORS, &pvBits, NULL, 0); + DeleteDC(hDC); + return hbm; +} + +#ifdef CREATE_BITMAPS + typedef struct tagBITMAPINFOEX + { + BITMAPINFOHEADER bmiHeader; + RGBQUAD bmiColors[256]; + } BITMAPINFOEX, FAR * LPBITMAPINFOEX; + + /* save a bitmap object to a file */ + static BOOL SaveBitmapToFileDx(LPCTSTR pszFileName, HBITMAP hbm) + { + BOOL f; + BITMAPFILEHEADER bf; + BITMAPINFOEX bi; + BITMAPINFOHEADER *pbmih; + DWORD cb; + DWORD cColors, cbColors; + HDC hDC; + HANDLE hFile; + LPVOID pBits; + BITMAP bm; + DWORD dwError = 0; + + if (!GetObject(hbm, sizeof(BITMAP), &bm)) + return FALSE; + + pbmih = &bi.bmiHeader; + ZeroMemory(pbmih, sizeof(BITMAPINFOHEADER)); + pbmih->biSize = sizeof(BITMAPINFOHEADER); + pbmih->biWidth = bm.bmWidth; + pbmih->biHeight = bm.bmHeight; + pbmih->biPlanes = 1; + pbmih->biBitCount = bm.bmBitsPixel; + pbmih->biCompression = BI_RGB; + pbmih->biSizeImage = bm.bmWidthBytes * bm.bmHeight; + + if (bm.bmBitsPixel < 16) + cColors = 1 << bm.bmBitsPixel; + else + cColors = 0; + cbColors = cColors * sizeof(RGBQUAD); + + bf.bfType = 0x4d42; + bf.bfReserved1 = 0; + bf.bfReserved2 = 0; + cb = sizeof(BITMAPFILEHEADER) + pbmih->biSize + cbColors; + bf.bfOffBits = cb; + bf.bfSize = cb + pbmih->biSizeImage; + + pBits = HeapAlloc(GetProcessHeap(), 0, pbmih->biSizeImage); + if (pBits == NULL) + return FALSE; + + f = FALSE; + hDC = CreateCompatibleDC(NULL); + if (hDC != NULL) + { + if (GetDIBits(hDC, hbm, 0, bm.bmHeight, pBits, (BITMAPINFO*)&bi, + DIB_RGB_COLORS)) + { + hFile = CreateFile(pszFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, + CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | + FILE_FLAG_WRITE_THROUGH, NULL); + if (hFile != INVALID_HANDLE_VALUE) + { + f = WriteFile(hFile, &bf, sizeof(BITMAPFILEHEADER), &cb, NULL) && + WriteFile(hFile, &bi, sizeof(BITMAPINFOHEADER), &cb, NULL) && + WriteFile(hFile, bi.bmiColors, cbColors, &cb, NULL) && + WriteFile(hFile, pBits, pbmih->biSizeImage, &cb, NULL); + if (!f) + dwError = GetLastError(); + CloseHandle(hFile); + + if (!f) + DeleteFile(pszFileName); + } + else + dwError = GetLastError(); + } + else + dwError = GetLastError(); + DeleteDC(hDC); + } + else + dwError = GetLastError(); + + HeapFree(GetProcessHeap(), 0, pBits); + SetLastError(dwError); + return f; + } +#endif + +static void Tategaki_Test_Main(void) +{ + LOGFONT lf; + HDC hDC; + HFONT hFont; + HBITMAP hbm; + HGDIOBJ hbmOld, hFontOld; + WCHAR a[2] = { L'A', 0 }; /* U+0041: Don't rotate */ + WCHAR ka[2] = { 0x304B, 0 }; /* U+304B: Rotate */ + COLORREF black = RGB(0, 0, 0); + COLORREF white = RGB(255, 255, 255); + RECT rc = { 0, 0, 30, 30 }; + + ZeroMemory(&lf, sizeof(lf)); + lf.lfHeight = 30; + lf.lfCharSet = DEFAULT_CHARSET; + + hDC = CreateCompatibleDC(NULL); + ok(hDC != NULL, "hDC was NULL\n"); + SetTextColor(hDC, black); + SetBkColor(hDC, white); + SetBkMode(hDC, OPAQUE); + + lstrcpy(lf.lfFaceName, TEXT("TategakiTest")); + hFont = CreateFontIndirect(&lf); + ok(hFont != NULL, "hFont was NULL.\n"); + { + hbm = Create24BppBitmapDx(30, 30); + ok(hbm != NULL, "hbm was NULL.\n"); + hbmOld = SelectObject(hDC, hbm); + hFontOld = SelectObject(hDC, hFont); + { + FillRect(hDC, &rc, (HBRUSH)GetStockObject(WHITE_BRUSH)); + TextOutW(hDC, 0, 0, a, 1); + ok_int(GetPixel(hDC, 7, 7), white); /* up */ + ok_int(GetPixel(hDC, 7, 20), black); /* down */ + ok_int(GetPixel(hDC, 20, 7), white); /* out of glyph extent */ + ok_int(GetPixel(hDC, 20, 20), white); /* out of glyph extent */ + } + SelectObject(hDC, hFontOld); + SelectObject(hDC, hbmOld); +#ifdef CREATE_BITMAPS + SaveBitmapToFileDx(TEXT("a1.bmp"), hbm); +#endif + DeleteObject(hbm); + + hbm = Create24BppBitmapDx(30, 30); + ok(hbm != NULL, "hbm was NULL.\n"); + hbmOld = SelectObject(hDC, hbm); + hFontOld = SelectObject(hDC, hFont); + { + FillRect(hDC, &rc, (HBRUSH)GetStockObject(WHITE_BRUSH)); + TextOutW(hDC, 0, 0, ka, 1); + ok_int(GetPixel(hDC, 8, 14), white); /* left */ + ok_int(GetPixel(hDC, 14, 7), white); /* up */ + ok_int(GetPixel(hDC, 14, 25), black); /* down */ + ok_int(GetPixel(hDC, 24, 14), white); /* right */ + } + SelectObject(hDC, hFontOld); + SelectObject(hDC, hbmOld); +#ifdef CREATE_BITMAPS + SaveBitmapToFileDx(TEXT("ka1.bmp"), hbm); +#endif + DeleteObject(hbm); + } + DeleteObject(hFont); + + lstrcpy(lf.lfFaceName, TEXT("@TategakiTest")); + hFont = CreateFontIndirect(&lf); + ok(hFont != NULL, "hFont was NULL.\n"); + { + hbm = Create24BppBitmapDx(30, 30); + ok(hbm != NULL, "hbm was NULL.\n"); + hbmOld = SelectObject(hDC, hbm); + hFontOld = SelectObject(hDC, hFont); + { + FillRect(hDC, &rc, (HBRUSH)GetStockObject(WHITE_BRUSH)); + TextOutW(hDC, 0, 0, a, 1); + ok_int(GetPixel(hDC, 7, 7), white); /* up */ + ok_int(GetPixel(hDC, 7, 20), black); /* down */ + ok_int(GetPixel(hDC, 20, 7), white); /* out of glyph extent */ + ok_int(GetPixel(hDC, 20, 20), white); /* out of glyph extent */ + } + SelectObject(hDC, hFontOld); + SelectObject(hDC, hbmOld); +#ifdef CREATE_BITMAPS + SaveBitmapToFileDx(TEXT("a2.bmp"), hbm); +#endif + DeleteObject(hbm); + + hbm = Create24BppBitmapDx(30, 30); + ok(hbm != NULL, "hbm was NULL.\n"); + hbmOld = SelectObject(hDC, hbm); + hFontOld = SelectObject(hDC, hFont); + { + FillRect(hDC, &rc, (HBRUSH)GetStockObject(WHITE_BRUSH)); + TextOutW(hDC, 0, 0, ka, 1); + ok_int(GetPixel(hDC, 8, 14), white); /* left */ + ok_int(GetPixel(hDC, 14, 7), white); /* up */ + ok_int(GetPixel(hDC, 14, 25), white); /* down */ + ok_int(GetPixel(hDC, 24, 14), black); /* right */ + } + SelectObject(hDC, hFontOld); + SelectObject(hDC, hbmOld); +#ifdef CREATE_BITMAPS + SaveBitmapToFileDx(TEXT("ka2.bmp"), hbm); +#endif + DeleteObject(hbm); + } + DeleteObject(hFont); + + DeleteDC(hDC); +} + +START_TEST(Tategaki) +{ + HMODULE mod; + HRSRC hRsrc; + HGLOBAL hGlobal; + DWORD dwSize, dwNumFonts; + LPVOID pFont; + HANDLE hFontRes; + + mod = GetModuleHandle(NULL); + hRsrc = FindResourceA(mod, "TategakiTest.ttf", MAKEINTRESOURCEA(RT_RCDATA)); + hGlobal = LoadResource(mod, hRsrc); + dwSize = SizeofResource(mod, hRsrc); + pFont = LockResource(hGlobal); + ok(pFont != NULL, "Unable to load \"TategakiTest.ttf\".\n"); + + dwNumFonts = 0; + hFontRes = AddFontMemResourceEx(pFont, dwSize, NULL, &dwNumFonts); + ok(dwNumFonts == 2, "dwNumFonts was %lu, expected %d\n", dwNumFonts, 2); + ok(hFontRes != NULL, "Expected valid handle\n"); + + Tategaki_Test_Main(); + + RemoveFontMemResourceEx(hFontRes); + + UnlockResource(hGlobal); + FreeResource(hGlobal); +} Index: rostests/apitests/gdi32/TategakiTest.ttf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: rostests/apitests/gdi32/TategakiTest.ttf =================================================================== --- rostests/apitests/gdi32/TategakiTest.ttf (nonexistent) +++ rostests/apitests/gdi32/TategakiTest.ttf (working copy) Property changes on: rostests/apitests/gdi32/TategakiTest.ttf ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: rostests/apitests/gdi32/testlist.c =================================================================== --- rostests/apitests/gdi32/testlist.c (revision 75147) +++ rostests/apitests/gdi32/testlist.c (working copy) @@ -73,6 +73,7 @@ extern void func_SetSysColors(void); extern void func_SetWindowExtEx(void); extern void func_SetWorldTransform(void); +extern void func_Tategaki(void); const struct test winetest_testlist[] = { @@ -146,6 +147,7 @@ { "SetSysColors", func_SetSysColors }, { "SetWindowExtEx", func_SetWindowExtEx }, { "SetWorldTransform", func_SetWorldTransform }, + { "Tategaki", func_Tategaki }, { 0, 0 } };