[GDI32_WINETEST] Sync everything except dib.c with Wine Staging 3.3. CORE-14434
[reactos.git] / modules / rostests / winetests / gdi32 / font.c
index 61ee6f3..a554e15 100644 (file)
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
-#include "precomp.h"
+#include <stdarg.h>
+#include <assert.h>
 
-#include <winnls.h>
+#include "windef.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "winuser.h"
+#include "winnls.h"
+
+#include "wine/heap.h"
+#include "wine/test.h"
 
 static inline BOOL match_off_by_n(int a, int b, unsigned int n)
 {
@@ -102,22 +110,6 @@ static void init(void)
     system_lang_id = PRIMARYLANGID(GetSystemDefaultLangID());
 }
 
-static inline void* __WINE_ALLOC_SIZE(1) heap_alloc(size_t size)
-{
-    return HeapAlloc(GetProcessHeap(), 0, size);
-}
-
-static inline void* __WINE_ALLOC_SIZE(2) heap_realloc(void *mem, size_t size)
-{
-    if (!mem) return heap_alloc(size);
-    return HeapReAlloc(GetProcessHeap(), 0, mem, size);
-}
-
-static inline BOOL heap_free(void *mem)
-{
-    return HeapFree(GetProcessHeap(), 0, mem);
-}
-
 static INT CALLBACK is_truetype_font_installed_proc(const LOGFONTA *elf, const TEXTMETRICA *ntm, DWORD type, LPARAM lParam)
 {
     if (type != TRUETYPE_FONTTYPE) return 1;
@@ -1136,7 +1128,7 @@ static int CALLBACK create_font_proc(const LOGFONTA *lpelfe,
     return 1;
 }
 
-static void ABCWidths_helper(const char* description, HDC hdc, WORD *glyphs, ABC *base_abci, ABC *base_abcw, ABCFLOAT *base_abcf, INT todo)
+static void ABCWidths_helper(const char* description, HDC hdc, WORD *glyphs, const ABC *base_abci, const ABC *base_abcw, const ABCFLOAT *base_abcf)
 {
     ABC abc[1];
     ABCFLOAT abcf[1];
@@ -1145,26 +1137,20 @@ static void ABCWidths_helper(const char* description, HDC hdc, WORD *glyphs, ABC
     ret = pGetCharABCWidthsI(hdc, 0, 1, glyphs, abc);
     ok(ret, "%s: GetCharABCWidthsI should have succeeded\n", description);
     ok ((INT)abc->abcB > 0, "%s: abcB should be positive\n", description);
-    todo_wine_if (todo)
-        ok(abc->abcA * base_abci->abcA >= 0, "%s: abcA's sign should be unchanged\n", description);
-    todo_wine_if (todo)
-        ok(abc->abcC * base_abci->abcC >= 0, "%s: abcC's sign should be unchanged\n", description);
+    ok(abc->abcA * base_abci->abcA >= 0, "%s: abcA's sign should be unchanged\n", description);
+    ok(abc->abcC * base_abci->abcC >= 0, "%s: abcC's sign should be unchanged\n", description);
 
     ret = pGetCharABCWidthsW(hdc, 'i', 'i', abc);
     ok(ret, "%s: GetCharABCWidthsW should have succeeded\n", description);
     ok ((INT)abc->abcB > 0, "%s: abcB should be positive\n", description);
-    todo_wine_if (todo)
-        ok(abc->abcA * base_abcw->abcA >= 0, "%s: abcA's sign should be unchanged\n", description);
-    todo_wine_if (todo)
-        ok(abc->abcC * base_abcw->abcC >= 0, "%s: abcC's sign should be unchanged\n", description);
+    ok(abc->abcA * base_abcw->abcA >= 0, "%s: abcA's sign should be unchanged\n", description);
+    ok(abc->abcC * base_abcw->abcC >= 0, "%s: abcC's sign should be unchanged\n", description);
 
     ret = pGetCharABCWidthsFloatW(hdc, 'i', 'i', abcf);
     ok(ret, "%s: GetCharABCWidthsFloatW should have succeeded\n", description);
     ok (abcf->abcfB > 0.0, "%s: abcfB should be positive\n", description);
-    todo_wine_if (todo)
-        ok(abcf->abcfA * base_abcf->abcfA >= 0.0, "%s: abcfA's sign should be unchanged\n", description);
-    todo_wine_if (todo)
-        ok(abcf->abcfC * base_abcf->abcfC >= 0.0, "%s: abcfC's sign should be unchanged\n", description);
+    ok(abcf->abcfA * base_abcf->abcfA >= 0.0, "%s: abcfA's sign should be unchanged\n", description);
+    ok(abcf->abcfC * base_abcf->abcfC >= 0.0, "%s: abcfC's sign should be unchanged\n", description);
 }
 
 static void test_GetCharABCWidths(void)
@@ -1354,6 +1340,56 @@ static void test_GetCharABCWidths(void)
        "got %d, expected %d (C)\n", abc[0].abcC, abcw[0].abcC);
 
     DeleteObject(SelectObject(hdc, hfont));
+
+    /* test abcA == gmptGlyphOrigin.x && abcB == gmBlackBoxX
+       in various widths. */
+    for (i = 1; i <= 2; i++)
+    {
+        UINT j;
+        UINT code;
+
+        memset(&lf, 0, sizeof(lf));
+        lf.lfHeight = 20;
+        switch(i)
+        {
+        case 1:
+            strcpy(lf.lfFaceName, "Tahoma");
+            code = 'a';
+            break;
+        case 2:
+            strcpy(lf.lfFaceName, "Times New Roman");
+            lf.lfItalic = TRUE;
+            code = 'f';
+            break;
+        }
+        if (!is_truetype_font_installed(lf.lfFaceName))
+        {
+            skip("%s is not installed\n", lf.lfFaceName);
+            continue;
+        }
+        for (j = 1; j <= 80; j++)
+        {
+            GLYPHMETRICS gm;
+
+            lf.lfWidth = j;
+            hfont = CreateFontIndirectA(&lf);
+            hfont = SelectObject(hdc, hfont);
+
+            nb = GetGlyphOutlineA(hdc, code, GGO_METRICS, &gm, 0, NULL, &mat);
+            ok(nb, "GetGlyphOutlineA should have succeeded at width %d\n", i);
+
+            ret = GetCharABCWidthsA(hdc, code, code, abc);
+            ok(ret, "GetCharABCWidthsA should have succeeded at width %d\n", i);
+
+            ok(abc[0].abcA == gm.gmptGlyphOrigin.x,
+               "abcA(%d) and gmptGlyphOrigin.x(%d) values are different at width %d\n",
+               abc[0].abcA, gm.gmptGlyphOrigin.x, i);
+            ok(abc[0].abcB == gm.gmBlackBoxX,
+               "abcB(%d) and gmBlackBoxX(%d) values are different at width %d\n",
+               abc[0].abcB, gm.gmBlackBoxX, i);
+            DeleteObject(SelectObject(hdc, hfont));
+        }
+    }
     ReleaseDC(NULL, hdc);
 
     trace("ABC sign test for a variety of transforms:\n");
@@ -1377,17 +1413,17 @@ static void test_GetCharABCWidths(void)
     ret = pGetCharABCWidthsFloatW(hdc, 'i', 'i', abcf);
     ok(ret, "GetCharABCWidthsFloatW should have succeeded\n");
 
-    ABCWidths_helper("LTR", hdc, glyphs, abc, abcw, abcf, 0);
+    ABCWidths_helper("LTR", hdc, glyphs, abc, abcw, abcf);
     SetWindowExtEx(hdc, -1, -1, NULL);
     SetGraphicsMode(hdc, GM_COMPATIBLE);
-    ABCWidths_helper("LTR -1 compatible", hdc, glyphs, abc, abcw, abcf, 0);
+    ABCWidths_helper("LTR -1 compatible", hdc, glyphs, abc, abcw, abcf);
     SetGraphicsMode(hdc, GM_ADVANCED);
-    ABCWidths_helper("LTR -1 advanced", hdc, glyphs, abc, abcw, abcf, 1);
+    ABCWidths_helper("LTR -1 advanced", hdc, glyphs, abc, abcw, abcf);
     SetWindowExtEx(hdc, 1, 1, NULL);
     SetGraphicsMode(hdc, GM_COMPATIBLE);
-    ABCWidths_helper("LTR 1 compatible", hdc, glyphs, abc, abcw, abcf, 0);
+    ABCWidths_helper("LTR 1 compatible", hdc, glyphs, abc, abcw, abcf);
     SetGraphicsMode(hdc, GM_ADVANCED);
-    ABCWidths_helper("LTR 1 advanced", hdc, glyphs, abc, abcw, abcf, 0);
+    ABCWidths_helper("LTR 1 advanced", hdc, glyphs, abc, abcw, abcf);
 
     ReleaseDC(hwnd, hdc);
     DestroyWindow(hwnd);
@@ -1399,17 +1435,17 @@ static void test_GetCharABCWidths(void)
     SetMapMode(hdc, MM_ANISOTROPIC);
     SelectObject(hdc, hfont);
 
-    ABCWidths_helper("RTL", hdc, glyphs, abc, abcw, abcf, 0);
+    ABCWidths_helper("RTL", hdc, glyphs, abc, abcw, abcf);
     SetWindowExtEx(hdc, -1, -1, NULL);
     SetGraphicsMode(hdc, GM_COMPATIBLE);
-    ABCWidths_helper("RTL -1 compatible", hdc, glyphs, abc, abcw, abcf, 0);
+    ABCWidths_helper("RTL -1 compatible", hdc, glyphs, abc, abcw, abcf);
     SetGraphicsMode(hdc, GM_ADVANCED);
-    ABCWidths_helper("RTL -1 advanced", hdc, glyphs, abc, abcw, abcf, 0);
+    ABCWidths_helper("RTL -1 advanced", hdc, glyphs, abc, abcw, abcf);
     SetWindowExtEx(hdc, 1, 1, NULL);
     SetGraphicsMode(hdc, GM_COMPATIBLE);
-    ABCWidths_helper("RTL 1 compatible", hdc, glyphs, abc, abcw, abcf, 0);
+    ABCWidths_helper("RTL 1 compatible", hdc, glyphs, abc, abcw, abcf);
     SetGraphicsMode(hdc, GM_ADVANCED);
-    ABCWidths_helper("RTL 1 advanced", hdc, glyphs, abc, abcw, abcf, 1);
+    ABCWidths_helper("RTL 1 advanced", hdc, glyphs, abc, abcw, abcf);
 
     ReleaseDC(hwnd, hdc);
     DestroyWindow(hwnd);
@@ -1783,17 +1819,17 @@ static void test_GetKerningPairs(void)
            kd[i].otmMacDescent, otm.otmMacDescent);
         ok(near_match(kd[i].otmMacAscent, otm.otmMacAscent), "expected %d, got %d\n",
            kd[i].otmMacAscent, otm.otmMacAscent);
-todo_wine {
+todo_wine
         ok(kd[i].otmsCapEmHeight == otm.otmsCapEmHeight, "expected %u, got %u\n",
            kd[i].otmsCapEmHeight, otm.otmsCapEmHeight);
+todo_wine
         ok(kd[i].otmsXHeight == otm.otmsXHeight, "expected %u, got %u\n",
            kd[i].otmsXHeight, otm.otmsXHeight);
-        /* FIXME: this one sometimes succeeds due to expected 0, enable it when removing todo */
-        if (0) ok(kd[i].otmMacLineGap == otm.otmMacLineGap, "expected %u, got %u\n",
+        ok(kd[i].otmMacLineGap == otm.otmMacLineGap, "expected %u, got %u\n",
            kd[i].otmMacLineGap, otm.otmMacLineGap);
+todo_wine
         ok(kd[i].otmusMinimumPPEM == otm.otmusMinimumPPEM, "expected %u, got %u\n",
            kd[i].otmusMinimumPPEM, otm.otmusMinimumPPEM);
-}
 
         total_kern_pairs = GetKerningPairsW(hdc, 0, NULL);
         trace("total_kern_pairs %u\n", total_kern_pairs);
@@ -5924,7 +5960,7 @@ static void check_vertical_metrics(const char *face)
     GLYPHMETRICS rgm, vgm;
     const UINT code = 0x5EAD, height = 1000;
     WORD idx;
-    ABC abc;
+    ABC abc, vabc;
     OUTLINETEXTMETRICA otm;
     USHORT numOfLongVerMetrics;
 
@@ -5952,6 +5988,15 @@ static void check_vertical_metrics(const char *face)
     hfont_prev = SelectObject(hdc, hfont);
     ret = GetGlyphOutlineW(hdc, code, GGO_METRICS, &vgm, 0, NULL, &mat);
     ok(ret != GDI_ERROR, "GetGlyphOutlineW failed\n");
+    ret = GetCharABCWidthsW(hdc, code, code, &vabc);
+    ok(ret, "GetCharABCWidthsW failed\n");
+    ok(vabc.abcA == vgm.gmptGlyphOrigin.x, "expected %d, got %d\n",
+       vabc.abcA, vgm.gmptGlyphOrigin.x);
+    ok(vabc.abcB == vgm.gmBlackBoxX, "expected %d, got %d\n",
+       vabc.abcB, vgm.gmBlackBoxX);
+    ok(vabc.abcA + vabc.abcB + vabc.abcC == vgm.gmCellIncX,
+       "expected %d, got %d\n",
+       vabc.abcA + vabc.abcB + vabc.abcC, vgm.gmCellIncX);
 
     memset(&otm, 0, sizeof(otm));
     otm.otmSize = sizeof(otm);
@@ -6411,7 +6456,7 @@ static void test_GetCharWidth32(void)
     SetGraphicsMode(hdc, GM_ADVANCED);
     ret = pGetCharWidth32W(hdc, 'a', 'a', &bufferW);
     ok(ret, "GetCharWidth32W should have succeeded\n");
-    todo_wine ok (bufferW > 0," Width should be greater than zero\n");
+    ok (bufferW > 0," Width should be greater than zero\n");
     SetWindowExtEx(hdc, 1,1,NULL);
     SetGraphicsMode(hdc, GM_COMPATIBLE);
     ret = pGetCharWidth32W(hdc, 'a', 'a', &bufferW);
@@ -6451,7 +6496,7 @@ static void test_GetCharWidth32(void)
     SetGraphicsMode(hdc, GM_ADVANCED);
     ret = pGetCharWidth32W(hdc, 'a', 'a', &bufferW);
     ok(ret, "GetCharWidth32W should have succeeded\n");
-    todo_wine ok (bufferW > 0," Width should be greater than zero\n");
+    ok (bufferW > 0," Width should be greater than zero\n");
 
     ReleaseDC(hwnd, hdc);
     DestroyWindow(hwnd);
@@ -6469,7 +6514,7 @@ static void test_fake_bold_font(void)
         ABC abc;
         INT w;
         GLYPHMETRICS gm;
-    } data[2];
+    } data[4];
     int i;
     DWORD r;
 
@@ -6526,6 +6571,60 @@ static void test_fake_bold_font(void)
        "expected %d, got %d\n", data[0].gm.gmCellIncX + 1, data[1].gm.gmCellIncX);
     ok(data[0].gm.gmCellIncY == data[1].gm.gmCellIncY,
        "expected %d, got %d\n", data[0].gm.gmCellIncY, data[1].gm.gmCellIncY);
+
+    /* Test bitmap font */
+    memset(&data, 0xaa, sizeof(data));
+    memset(&lf, 0, sizeof(lf));
+    strcpy(lf.lfFaceName, "Courier");
+    lf.lfCharSet = ANSI_CHARSET;
+
+    hdc = GetDC(NULL);
+
+    for (i = 0; i < 4; i++)
+    {
+        HFONT hfont, hfont_old;
+
+        lf.lfWeight = (i % 2) ? FW_BOLD : FW_NORMAL;
+        lf.lfHeight = (i > 1) ? data[0].tm.tmHeight * x2_mat.eM11.value : 0;
+        hfont = CreateFontIndirectA(&lf);
+        hfont_old = SelectObject(hdc, hfont);
+
+        ret = GetTextMetricsA(hdc, &data[i].tm);
+        ok(ret, "got %d\n", ret);
+        ret = pGetCharWidth32A(hdc, 0x76, 0x76, &data[i].w);
+        ok(ret, "got %d\n", ret);
+
+        SelectObject(hdc, hfont_old);
+        DeleteObject(hfont);
+    }
+    ReleaseDC(NULL, hdc);
+
+    /* compare results (bitmap) */
+    for (i = 0; i < 4; i+=2)
+    {
+        int diff = (i > 1) ? x2_mat.eM11.value : 1;
+        if (data[i].tm.tmPitchAndFamily & TMPF_TRUETYPE)
+        {
+            skip("TrueType font is selected (expected a bitmap one)\n");
+            continue;
+        }
+        ok(data[i].tm.tmHeight == data[i+1].tm.tmHeight,
+           "expected %d, got %d\n", data[i].tm.tmHeight, data[i+1].tm.tmHeight);
+        ok(data[i].tm.tmAscent == data[i+1].tm.tmAscent,
+           "expected %d, got %d\n", data[i].tm.tmAscent, data[i+1].tm.tmAscent);
+        ok(data[i].tm.tmDescent == data[i+1].tm.tmDescent,
+           "expected %d, got %d\n", data[i].tm.tmDescent, data[i+1].tm.tmDescent);
+        ok(data[i+1].tm.tmAveCharWidth - data[i].tm.tmAveCharWidth == diff,
+           "expected %d, got %d\n", diff, data[i+1].tm.tmAveCharWidth - data[i].tm.tmAveCharWidth);
+        ok(data[i+1].tm.tmMaxCharWidth - data[i].tm.tmMaxCharWidth == diff,
+           "expected %d, got %d\n", diff, data[i+1].tm.tmMaxCharWidth - data[i].tm.tmMaxCharWidth);
+        ok(data[i].tm.tmOverhang == 0,
+           "expected 0, got %d\n", data[i].tm.tmOverhang);
+        ok(data[i+1].tm.tmOverhang == 1,
+           "expected 1, got %d\n", data[i+1].tm.tmOverhang);
+        ok(data[i].w + 1 == data[i+1].w,
+           "expected %d, got %d\n", data[i].w + 1, data[i+1].w);
+    }
 }
 
 static void test_bitmap_font_glyph_index(void)
@@ -6703,6 +6802,59 @@ static void test_GetCharWidthI(void)
     ReleaseDC(0, hdc);
 }
 
+static INT CALLBACK long_enum_proc(const LOGFONTA *lf, const TEXTMETRICA *tm, DWORD type, LPARAM lparam)
+{
+    BOOL *found_font = (BOOL *)lparam;
+    *found_font = TRUE;
+    return 1;
+}
+
+static void test_long_names(void)
+{
+    char ttf_name[MAX_PATH];
+    LOGFONTA font = {0};
+    HFONT handle_font;
+    BOOL found_font;
+    int ret;
+    HDC dc;
+
+    if (!write_ttf_file("wine_longname.ttf", ttf_name))
+    {
+        skip("Failed to create ttf file for testing\n");
+        return;
+    }
+
+    dc = GetDC(NULL);
+
+    ret = AddFontResourceExA(ttf_name, FR_PRIVATE, 0);
+    ok(ret, "AddFontResourceEx() failed\n");
+
+    strcpy(font.lfFaceName, "wine_3_this_is_a_very_long_name");
+    found_font = FALSE;
+    EnumFontFamiliesExA(dc, &font, long_enum_proc, (LPARAM)&found_font, 0);
+    ok(found_font == TRUE, "EnumFontFamiliesExA didn't find font.\n");
+
+    strcpy(font.lfFaceName, "wine_2_this_is_a_very_long_name");
+    found_font = FALSE;
+    EnumFontFamiliesExA(dc, &font, long_enum_proc, (LPARAM)&found_font, 0);
+    ok(found_font == TRUE, "EnumFontFamiliesExA didn't find font.\n");
+
+    strcpy(font.lfFaceName, "wine_1_this_is_a_very_long_name");
+    found_font = FALSE;
+    EnumFontFamiliesExA(dc, &font, long_enum_proc, (LPARAM)&found_font, 0);
+    ok(found_font == FALSE, "EnumFontFamiliesExA must not find font.\n");
+
+    handle_font = CreateFontIndirectA(&font);
+    ok(handle_font != NULL, "CreateFontIndirectA failed\n");
+    DeleteObject(handle_font);
+
+    ret = RemoveFontResourceExA(ttf_name, FR_PRIVATE, 0);
+    ok(ret, "RemoveFontResourceEx() failed\n");
+
+    DeleteFileA(ttf_name);
+    ReleaseDC(NULL, dc);
+}
+
 START_TEST(font)
 {
     init();
@@ -6767,6 +6919,7 @@ START_TEST(font)
     test_fake_bold_font();
     test_bitmap_font_glyph_index();
     test_GetCharWidthI();
+    test_long_names();
 
     /* These tests should be last test until RemoveFontResource
      * is properly implemented.