⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 metafile.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 4 页
字号:
            x1 = MulDiv(10, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES));
            y1 = MulDiv(10, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES));
        }
        ok(mapping[0].x == x0 && mapping[0].y == y0 && mapping[1].x == x1 && mapping[1].y == y1,
            "(%ld,%ld)->(%ld,%ld), expected (%d,%d)->(%d,%d)\n",
            mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y,
            x0, y0, x1, y1);
    }
    return TRUE;
}

static HENHMETAFILE create_converted_emf(const METAFILEPICT *mfp)
{
    HDC hdcMf;
    HMETAFILE hmf;
    BOOL ret;
    UINT size;
    LPBYTE pBits;

    hdcMf = CreateMetaFile(NULL);
    ok(hdcMf != NULL, "CreateMetaFile failed with error %ld\n", GetLastError());
    ret = LineTo(hdcMf, (INT)LINE_X, (INT)LINE_Y);
    ok(ret, "LineTo failed with error %ld\n", GetLastError());
    hmf = CloseMetaFile(hdcMf);
    ok(hmf != NULL, "CloseMetaFile failed with error %ld\n", GetLastError());

    if (compare_mf_bits (hmf, MF_LINETO_BITS, sizeof(MF_LINETO_BITS), "mf_LineTo") != 0)
    {
        dump_mf_bits(hmf, "mf_LineTo");
        EnumMetaFile(0, hmf, mf_enum_proc, 0);
    }

    size = GetMetaFileBitsEx(hmf, 0, NULL);
    ok(size, "GetMetaFileBitsEx failed with error %ld\n", GetLastError());
    pBits = HeapAlloc(GetProcessHeap(), 0, size);
    GetMetaFileBitsEx(hmf, size, pBits);
    DeleteMetaFile(hmf);
    return SetWinMetaFileBits(size, pBits, NULL, mfp);
}

static void test_mf_conversions(void)
{
    trace("Testing MF->EMF conversion (MM_ANISOTROPIC)\n");
    {
        HDC hdcOffscreen = CreateCompatibleDC(NULL);
        HENHMETAFILE hemf;
        METAFILEPICT mfp;
        RECT rect = { 0, 0, 100, 100 };
        mfp.mm = MM_ANISOTROPIC;
        mfp.xExt = 100;
        mfp.yExt = 100;
        mfp.hMF = NULL;
        hemf = create_converted_emf(&mfp);

        if (compare_emf_bits(hemf, EMF_LINETO_MM_ANISOTROPIC_BITS, sizeof(EMF_LINETO_MM_ANISOTROPIC_BITS),
                             "emf_LineTo MM_ANISOTROPIC", TRUE) != 0)
        {
            dump_emf_bits(hemf, "emf_LineTo MM_ANISOTROPIC");
            dump_emf_records(hemf, "emf_LineTo MM_ANISOTROPIC");
        }

        EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);

        DeleteEnhMetaFile(hemf);
        DeleteDC(hdcOffscreen);
    }

    trace("Testing MF->EMF conversion (MM_TEXT)\n");
    {
        HDC hdcOffscreen = CreateCompatibleDC(NULL);
        HENHMETAFILE hemf;
        METAFILEPICT mfp;
        RECT rect = { 0, 0, 100, 100 };
        mfp.mm = MM_TEXT;
        mfp.xExt = 0;
        mfp.yExt = 0;
        mfp.hMF = NULL;
        hemf = create_converted_emf(&mfp);

        if (compare_emf_bits(hemf, EMF_LINETO_MM_TEXT_BITS, sizeof(EMF_LINETO_MM_TEXT_BITS),
                             "emf_LineTo MM_TEXT", TRUE) != 0)
        {
            dump_emf_bits(hemf, "emf_LineTo MM_TEXT");
            dump_emf_records(hemf, "emf_LineTo MM_TEXT");
        }

        EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, &mfp, &rect);

        DeleteEnhMetaFile(hemf);
        DeleteDC(hdcOffscreen);
    }

    trace("Testing MF->EMF conversion (NULL mfp)\n");
    {
        HDC hdcOffscreen = CreateCompatibleDC(NULL);
        HENHMETAFILE hemf;
        RECT rect = { 0, 0, 100, 100 };
        hemf = create_converted_emf(NULL);

        if (compare_emf_bits(hemf, EMF_LINETO_BITS, sizeof(EMF_LINETO_BITS),
                             "emf_LineTo NULL", TRUE) != 0)
        {
            dump_emf_bits(hemf, "emf_LineTo NULL");
            dump_emf_records(hemf, "emf_LineTo NULL");
        }

        EnumEnhMetaFile(hdcOffscreen, hemf, EmfEnumProc, NULL, &rect);

        DeleteEnhMetaFile(hemf);
        DeleteDC(hdcOffscreen);
    }
}

static BOOL getConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
                                       LONG mm, LONG xExt, LONG yExt,
                                       RECTL * rclBounds, RECTL * rclFrame)
{
  METAFILEPICT mfp;
  METAFILEPICT * mfpPtr = NULL;
  HENHMETAFILE emf;
  ENHMETAHEADER header;
  UINT res;

  if (!mfpIsNull)
  {
    mfp.mm = mm;
    mfp.xExt = xExt;
    mfp.yExt = yExt;
    mfpPtr = &mfp;
  }

  emf = SetWinMetaFileBits(buffer_size, buffer, NULL, mfpPtr);
  ok(emf != NULL, "SetWinMetaFileBits failed\n");
  if (!emf) return FALSE;
  res = GetEnhMetaFileHeader(emf, sizeof(header), &header);
  ok(res != 0, "GetEnhMetaHeader failed\n");
  DeleteEnhMetaFile(emf);
  if (!res) return FALSE;

  *rclBounds = header.rclBounds;
  *rclFrame = header.rclFrame;
  return TRUE;
}

static void checkConvertedFrameAndBounds(UINT buffer_size, BYTE * buffer, BOOL mfpIsNull,
                                         LONG mm, LONG xExt, LONG yExt,
                                         RECTL * rclBoundsExpected, RECTL * rclFrameExpected)
{
  RECTL rclBounds, rclFrame;

  if (getConvertedFrameAndBounds(buffer_size, buffer, mfpIsNull, mm, xExt, yExt, &rclBounds, &rclFrame))
  {
    const char * msg;
    char buf[64];

    if (mfpIsNull)
    {
       msg = "mfp == NULL";
    }
    else
    {
      const char * mm_str;
      switch (mm)
      {
         case MM_ANISOTROPIC: mm_str = "MM_ANISOTROPIC"; break;
         case MM_ISOTROPIC:   mm_str = "MM_ISOTROPIC"; break;
         default:             mm_str = "Unexpected";
      }
      sprintf(buf, "mm=%s, xExt=%ld, yExt=%ld", mm_str, xExt, yExt);
      msg = buf;
    }

    ok(rclBounds.left == rclBoundsExpected->left, "rclBounds.left: Expected %ld, got %ld (%s)\n", rclBoundsExpected->left, rclBounds.left, msg);
    ok(rclBounds.top == rclBoundsExpected->top, "rclBounds.top: Expected %ld, got %ld (%s)\n", rclBoundsExpected->top, rclBounds.top, msg);
    ok(rclBounds.right == rclBoundsExpected->right, "rclBounds.right: Expected %ld, got %ld (%s)\n", rclBoundsExpected->right, rclBounds.right, msg);
    ok(rclBounds.bottom == rclBoundsExpected->bottom, "rclBounds.bottom: Expected %ld, got %ld (%s)\n", rclBoundsExpected->bottom, rclBounds.bottom, msg);
    ok(rclFrame.left == rclFrameExpected->left, "rclFrame.left: Expected %ld, got %ld (%s)\n", rclFrameExpected->left, rclFrame.left, msg);
    ok(rclFrame.top == rclFrameExpected->top, "rclFrame.top: Expected %ld, got %ld (%s)\n", rclFrameExpected->top, rclFrame.top, msg);
    ok(rclFrame.right == rclFrameExpected->right, "rclFrame.right: Expected %ld, got %ld (%s)\n", rclFrameExpected->right, rclFrame.right, msg);
    ok(rclFrame.bottom == rclFrameExpected->bottom, "rclFrame.bottom: Expected %ld, got %ld (%s)\n", rclFrameExpected->bottom, rclFrame.bottom, msg);
  }
}

static void test_SetWinMetaFileBits(void)
{
  HMETAFILE wmf;
  HDC wmfDC;
  BYTE * buffer;
  UINT buffer_size;
  RECT rect;
  UINT res;
  RECTL rclBoundsAnisotropic, rclFrameAnisotropic;
  RECTL rclBoundsIsotropic, rclFrameIsotropic;
  RECTL rclBounds, rclFrame;
  HDC dc;
  LONG diffx, diffy;

  wmfDC = CreateMetaFile(NULL);
  ok(wmfDC != NULL, "CreateMetaFile failed\n");
  if (!wmfDC) return;

  SetWindowExtEx(wmfDC, 100, 100, NULL);
  rect.left = rect.top = 0;
  rect.right = rect.bottom = 50;
  FillRect(wmfDC, &rect, GetStockObject(BLACK_BRUSH));
  wmf = CloseMetaFile(wmfDC);
  ok(wmf != NULL, "Metafile creation failed\n");
  if (!wmf) return;

  buffer_size = GetMetaFileBitsEx(wmf, 0, NULL);
  ok(buffer_size != 0, "GetMetaFileBitsEx failed\n");
  if (buffer_size == 0)
  {
    DeleteMetaFile(wmf);
    return;
  }

  buffer = (BYTE *)HeapAlloc(GetProcessHeap(), 0, buffer_size);
  ok(buffer != NULL, "HeapAlloc failed\n");
  if (!buffer)
  {
    DeleteMetaFile(wmf);
    return;
  }

  res = GetMetaFileBitsEx(wmf, buffer_size, buffer);
  ok(res == buffer_size, "GetMetaFileBitsEx failed\n");
  DeleteMetaFile(wmf);
  if (res != buffer_size)
  {
     HeapFree(GetProcessHeap(), 0, buffer);
     return;
  }

  /* Get the reference bounds and frame */
  getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
  getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 0,  &rclBoundsIsotropic, &rclFrameIsotropic);

  ok(rclBoundsAnisotropic.left == 0 && rclBoundsAnisotropic.top == 0 &&
     rclBoundsIsotropic.left == 0 && rclBoundsIsotropic.top == 0,
     "SetWinMetaFileBits: Reference bounds: Left and top bound must be zero\n");

  ok(rclBoundsAnisotropic.right >= rclBoundsIsotropic.right, "SetWinMetaFileBits: Reference bounds: Invalid right bound\n");
  ok(rclBoundsAnisotropic.bottom >= rclBoundsIsotropic.bottom, "SetWinMetaFileBits: Reference bounds: Invalid bottom bound\n");
  diffx = rclBoundsIsotropic.right - rclBoundsIsotropic.bottom;
  if (diffx < 0) diffx = -diffx;
  ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): Reference bounds are not isotropic\n");

  dc = CreateCompatibleDC(NULL);
  todo_wine
  {
  ok(rclBoundsAnisotropic.right == GetDeviceCaps(dc, HORZRES) / 2 - 1 &&
     rclBoundsAnisotropic.bottom == GetDeviceCaps(dc, VERTRES) / 2 - 1,
     "SetWinMetaFileBits (MM_ANISOTROPIC): Reference bounds: The whole device surface must be used (%dx%d), but got (%ldx%ld)\n",
     GetDeviceCaps(dc, HORZRES) / 2 - 1, GetDeviceCaps(dc, VERTRES) / 2 - 1, rclBoundsAnisotropic.right, rclBoundsAnisotropic.bottom);
  }

  /* Allow 1 mm difference (rounding errors) */
  diffx = rclFrameAnisotropic.right / 100 - GetDeviceCaps(dc, HORZSIZE) / 2;
  diffy = rclFrameAnisotropic.bottom / 100 - GetDeviceCaps(dc, VERTSIZE) / 2;
  if (diffx < 0) diffx = -diffx;
  if (diffy < 0) diffy = -diffy;
  todo_wine
  {
  ok(diffx <= 1 && diffy <= 1,
     "SetWinMetaFileBits (MM_ANISOTROPIC): Reference frame: The whole device surface must be used (%dx%d), but got (%ldx%ld)\n",
     GetDeviceCaps(dc, HORZSIZE) / 2, GetDeviceCaps(dc, VERTSIZE) / 2, rclFrameAnisotropic.right / 100, rclFrameAnisotropic.bottom / 100);
  }
  DeleteDC(dc);

  /* If the METAFILEPICT pointer is NULL, the MM_ANISOTROPIC mapping mode and the whole device surface are used */
  checkConvertedFrameAndBounds(buffer_size, buffer, TRUE, 0, 0, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);

  /* If xExt or yExt is zero or negative, the whole device surface is used */
  checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
  checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
  checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
  checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
  checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 0, &rclBoundsAnisotropic, &rclFrameAnisotropic);
  checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 0, &rclBoundsIsotropic, &rclFrameIsotropic);
  checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 0, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
  checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 0, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);
  checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -10000, 10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
  checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -10000, 10000, &rclBoundsIsotropic, &rclFrameIsotropic);
  checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 10000, -10000, &rclBoundsAnisotropic, &rclFrameAnisotropic);
  checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 10000, -10000, &rclBoundsIsotropic, &rclFrameIsotropic);

  /* MSDN says that negative xExt and yExt values specify a ratio.
     Check that this is wrong and the whole device surface is used */
  checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, -1000, -100, &rclBoundsAnisotropic, &rclFrameAnisotropic);
  checkConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, -1000, -100, &rclBoundsIsotropic, &rclFrameIsotropic);

  /* Ordinary conversions */

  if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ANISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
  {
    ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
       "SetWinMetaFileBits (MM_ANISOTROPIC): rclFrame contains invalid values\n");
    ok(rclBounds.left == 0 && rclBounds.top == 0 && rclBounds.right > rclBounds.bottom,
       "SetWinMetaFileBits (MM_ANISOTROPIC): rclBounds contains invalid values\n");
  }

  if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_ISOTROPIC, 30000, 20000, &rclBounds, &rclFrame))
  {
    ok(rclFrame.left == 0 && rclFrame.top == 0 && rclFrame.right == 30000 && rclFrame.bottom == 20000,
       "SetWinMetaFileBits (MM_ISOTROPIC): rclFrame contains invalid values\n");
    ok(rclBounds.left == 0 && rclBounds.top == 0,
       "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds contains invalid values\n");

    /* Wine has a rounding error */
    diffx = rclBounds.right - rclBounds.bottom;
    if (diffx < 0) diffx = -diffx;
    ok(diffx <= 1, "SetWinMetaFileBits (MM_ISOTROPIC): rclBounds is not isotropic\n");
  }

  if (getConvertedFrameAndBounds(buffer_size, buffer, FALSE, MM_HIMETRIC, 30000, 20000, &rclBounds, &rclFrame))
  {
    ok(rclFrame.right - rclFrame.left != 30000 && rclFrame.bottom - rclFrame.top != 20000,
       "SetWinMetaFileBits: xExt and yExt must be ignored for mapping modes other than MM_ANISOTROPIC and MM_ISOTROPIC\n");
  }

  HeapFree(GetProcessHeap(), 0, buffer);
}

static BOOL (WINAPI *pGdiIsMetaPrintDC)(HDC);
static BOOL (WINAPI *pGdiIsMetaFileDC)(HDC);
static BOOL (WINAPI *pGdiIsPlayMetafileDC)(HDC);

static void test_gdiis(void)
{
    RECT rect = {0,0,100,100};
    HDC hdc, hemfDC, hmfDC;
    HENHMETAFILE hemf;
    HMODULE hgdi32;

    /* resolve all the functions */
    hgdi32 = GetModuleHandle("gdi32");
    pGdiIsMetaPrintDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaPrintDC");
    pGdiIsMetaFileDC = (void*) GetProcAddress(hgdi32, "GdiIsMetaFileDC");
    pGdiIsPlayMetafileDC = (void*) GetProcAddress(hgdi32, "GdiIsPlayMetafileDC");

    /* they should all exist or none should exist */
    if(!pGdiIsMetaPrintDC)
        return;

    /* try with nothing */
    ok(!pGdiIsMetaPrintDC(NULL), "ismetaprint with NULL parameter\n");
    ok(!pGdiIsMetaFileDC(NULL), "ismetafile with NULL parameter\n");
    ok(!pGdiIsPlayMetafileDC(NULL), "isplaymetafile with NULL parameter\n");

    /* try with a metafile */
    hmfDC = CreateMetaFile(NULL);
    ok(!pGdiIsMetaPrintDC(hmfDC), "ismetaprint on metafile\n");
    ok(pGdiIsMetaFileDC(hmfDC), "ismetafile on metafile\n");
    ok(!pGdiIsPlayMetafileDC(hmfDC), "isplaymetafile on metafile\n");
    DeleteObject(CloseMetaFile(hmfDC));

    /* try with an enhanced metafile */
    hdc = GetDC(NULL);
    hemfDC = CreateEnhMetaFileW(hdc, NULL, &rect, NULL);
    ok(hemfDC != NULL, "failed to create emf\n");

    ok(!pGdiIsMetaPrintDC(hemfDC), "ismetaprint on emf\n");
    ok(pGdiIsMetaFileDC(hemfDC), "ismetafile on emf\n");
    ok(!pGdiIsPlayMetafileDC(hemfDC), "isplaymetafile on emf\n");

    hemf = CloseEnhMetaFile(hemfDC);
    ok(hemf != NULL, "failed to close EMF\n");
    DeleteObject(hemf);
    ReleaseDC(NULL,hdc);
}

START_TEST(metafile)
{
    init_function_pointers();

    /* For enhanced metafiles (enhmfdrv) */
    test_ExtTextOut();
    test_SaveDC();

    /* For win-format metafiles (mfdrv) */
    test_mf_Blank();
    test_mf_Graphics();
    test_mf_PatternBrush();
    test_CopyMetaFile();
    test_SetMetaFileBits();
    test_mf_ExtTextOut_on_path();
    test_emf_ExtTextOut_on_path();

    /* For metafile conversions */
    test_mf_conversions();
    test_SetWinMetaFileBits();

    test_gdiis();
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -