mirror of
https://github.com/reactos/reactos.git
synced 2025-08-06 06:43:13 +00:00
[GDIPLUS]
* Sync to Wine 1.5.4. svn path=/trunk/; revision=56613
This commit is contained in:
parent
aca91a4b14
commit
a87a379620
12 changed files with 1745 additions and 797 deletions
|
@ -5,8 +5,6 @@ add_definitions(
|
||||||
|
|
||||||
include_directories(${REACTOS_SOURCE_DIR}/include/reactos/wine)
|
include_directories(${REACTOS_SOURCE_DIR}/include/reactos/wine)
|
||||||
|
|
||||||
set_rc_compiler()
|
|
||||||
|
|
||||||
spec2def(gdiplus.dll gdiplus.spec ADD_IMPORTLIB)
|
spec2def(gdiplus.dll gdiplus.spec ADD_IMPORTLIB)
|
||||||
|
|
||||||
list(APPEND SOURCE
|
list(APPEND SOURCE
|
||||||
|
@ -19,12 +17,12 @@ list(APPEND SOURCE
|
||||||
image.c
|
image.c
|
||||||
imageattributes.c
|
imageattributes.c
|
||||||
matrix.c
|
matrix.c
|
||||||
metafile.c
|
metafile.c
|
||||||
pathiterator.c
|
pathiterator.c
|
||||||
pen.c
|
pen.c
|
||||||
region.c
|
region.c
|
||||||
stringformat.c
|
stringformat.c
|
||||||
gdiplus.rc
|
gdiplus.rc
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/gdiplus_stubs.c
|
${CMAKE_CURRENT_BINARY_DIR}/gdiplus_stubs.c
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/gdiplus.def)
|
${CMAKE_CURRENT_BINARY_DIR}/gdiplus.def)
|
||||||
|
|
||||||
|
@ -32,15 +30,5 @@ add_library(gdiplus SHARED ${SOURCE})
|
||||||
set_module_type(gdiplus win32dll)
|
set_module_type(gdiplus win32dll)
|
||||||
target_link_libraries(gdiplus uuid wine)
|
target_link_libraries(gdiplus uuid wine)
|
||||||
add_delay_importlibs(gdiplus windowscodecs)
|
add_delay_importlibs(gdiplus windowscodecs)
|
||||||
|
add_importlibs(gdiplus msvcrt shlwapi oleaut32 ole32 user32 gdi32 kernel32 ntdll)
|
||||||
add_importlibs(gdiplus
|
|
||||||
msvcrt
|
|
||||||
shlwapi
|
|
||||||
oleaut32
|
|
||||||
ole32
|
|
||||||
user32
|
|
||||||
gdi32
|
|
||||||
kernel32
|
|
||||||
ntdll)
|
|
||||||
|
|
||||||
add_cd_file(TARGET gdiplus DESTINATION reactos/system32 FOR all)
|
add_cd_file(TARGET gdiplus DESTINATION reactos/system32 FOR all)
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2007 Google (Evan Stade)
|
* Copyright (C) 2007 Google (Evan Stade)
|
||||||
|
* Copyright (C) 2012 Dmitry Timoshkov
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
@ -33,42 +34,121 @@ WINE_DEFAULT_DEBUG_CHANNEL (gdiplus);
|
||||||
#include "gdiplus.h"
|
#include "gdiplus.h"
|
||||||
#include "gdiplus_private.h"
|
#include "gdiplus_private.h"
|
||||||
|
|
||||||
|
/* PANOSE is 10 bytes in size, need to pack the structure properly */
|
||||||
|
#include "pshpack2.h"
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
USHORT version;
|
||||||
|
SHORT xAvgCharWidth;
|
||||||
|
USHORT usWeightClass;
|
||||||
|
USHORT usWidthClass;
|
||||||
|
SHORT fsType;
|
||||||
|
SHORT ySubscriptXSize;
|
||||||
|
SHORT ySubscriptYSize;
|
||||||
|
SHORT ySubscriptXOffset;
|
||||||
|
SHORT ySubscriptYOffset;
|
||||||
|
SHORT ySuperscriptXSize;
|
||||||
|
SHORT ySuperscriptYSize;
|
||||||
|
SHORT ySuperscriptXOffset;
|
||||||
|
SHORT ySuperscriptYOffset;
|
||||||
|
SHORT yStrikeoutSize;
|
||||||
|
SHORT yStrikeoutPosition;
|
||||||
|
SHORT sFamilyClass;
|
||||||
|
PANOSE panose;
|
||||||
|
ULONG ulUnicodeRange1;
|
||||||
|
ULONG ulUnicodeRange2;
|
||||||
|
ULONG ulUnicodeRange3;
|
||||||
|
ULONG ulUnicodeRange4;
|
||||||
|
CHAR achVendID[4];
|
||||||
|
USHORT fsSelection;
|
||||||
|
USHORT usFirstCharIndex;
|
||||||
|
USHORT usLastCharIndex;
|
||||||
|
/* According to the Apple spec, original version didn't have the below fields,
|
||||||
|
* version numbers were taken from the OpenType spec.
|
||||||
|
*/
|
||||||
|
/* version 0 (TrueType 1.5) */
|
||||||
|
USHORT sTypoAscender;
|
||||||
|
USHORT sTypoDescender;
|
||||||
|
USHORT sTypoLineGap;
|
||||||
|
USHORT usWinAscent;
|
||||||
|
USHORT usWinDescent;
|
||||||
|
/* version 1 (TrueType 1.66) */
|
||||||
|
ULONG ulCodePageRange1;
|
||||||
|
ULONG ulCodePageRange2;
|
||||||
|
/* version 2 (OpenType 1.2) */
|
||||||
|
SHORT sxHeight;
|
||||||
|
SHORT sCapHeight;
|
||||||
|
USHORT usDefaultChar;
|
||||||
|
USHORT usBreakChar;
|
||||||
|
USHORT usMaxContext;
|
||||||
|
} TT_OS2_V2;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
ULONG Version;
|
||||||
|
SHORT Ascender;
|
||||||
|
SHORT Descender;
|
||||||
|
SHORT LineGap;
|
||||||
|
USHORT advanceWidthMax;
|
||||||
|
SHORT minLeftSideBearing;
|
||||||
|
SHORT minRightSideBearing;
|
||||||
|
SHORT xMaxExtent;
|
||||||
|
SHORT caretSlopeRise;
|
||||||
|
SHORT caretSlopeRun;
|
||||||
|
SHORT caretOffset;
|
||||||
|
SHORT reserved[4];
|
||||||
|
SHORT metricDataFormat;
|
||||||
|
USHORT numberOfHMetrics;
|
||||||
|
} TT_HHEA;
|
||||||
|
#include "poppack.h"
|
||||||
|
|
||||||
|
#ifdef WORDS_BIGENDIAN
|
||||||
|
#define GET_BE_WORD(x) (x)
|
||||||
|
#define GET_BE_DWORD(x) (x)
|
||||||
|
#else
|
||||||
|
#define GET_BE_WORD(x) MAKEWORD(HIBYTE(x), LOBYTE(x))
|
||||||
|
#define GET_BE_DWORD(x) MAKELONG(GET_BE_WORD(HIWORD(x)), GET_BE_WORD(LOWORD(x)));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MS_MAKE_TAG(ch0, ch1, ch2, ch3) \
|
||||||
|
((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \
|
||||||
|
((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24))
|
||||||
|
#define MS_OS2_TAG MS_MAKE_TAG('O','S','/','2')
|
||||||
|
#define MS_HHEA_TAG MS_MAKE_TAG('h','h','e','a')
|
||||||
|
|
||||||
static const REAL mm_per_inch = 25.4;
|
static const REAL mm_per_inch = 25.4;
|
||||||
static const REAL inch_per_point = 1.0/72.0;
|
static const REAL inch_per_point = 1.0/72.0;
|
||||||
|
|
||||||
static GpFontCollection installedFontCollection = {0};
|
static GpFontCollection installedFontCollection = {0};
|
||||||
|
|
||||||
static inline REAL get_dpi (void)
|
static LONG em_size_to_pixel(REAL em_size, Unit unit, LONG dpi)
|
||||||
{
|
{
|
||||||
REAL dpi;
|
switch (unit)
|
||||||
GpGraphics *graphics;
|
{
|
||||||
HDC hdc = GetDC(0);
|
default:
|
||||||
GdipCreateFromHDC (hdc, &graphics);
|
FIXME("Unhandled unit type: %d\n", unit);
|
||||||
GdipGetDpiX(graphics, &dpi);
|
return 0;
|
||||||
GdipDeleteGraphics(graphics);
|
|
||||||
ReleaseDC (0, hdc);
|
|
||||||
|
|
||||||
return dpi;
|
case UnitPixel:
|
||||||
}
|
case UnitWorld:
|
||||||
|
/* FIXME: Figure out when World != Pixel */
|
||||||
static inline REAL point_to_pixel (REAL point)
|
return em_size;
|
||||||
{
|
case UnitDisplay:
|
||||||
return point * get_dpi() * inch_per_point;
|
FIXME("Unknown behavior for UnitDisplay! Please report!\n");
|
||||||
}
|
/* FIXME: Figure out how this works...
|
||||||
|
* MSDN says that if "DISPLAY" is a monitor, then pixel should be
|
||||||
static inline REAL inch_to_pixel (REAL inch)
|
* used. That's not what I got. Tests on Windows revealed no output,
|
||||||
{
|
* and the tests in tests/font crash windows */
|
||||||
return inch * get_dpi();
|
return 0;
|
||||||
}
|
case UnitPoint:
|
||||||
|
return em_size * dpi * inch_per_point;
|
||||||
static inline REAL document_to_pixel (REAL doc)
|
case UnitInch:
|
||||||
{
|
return em_size * dpi;
|
||||||
return doc * (get_dpi() / 300.0); /* Per MSDN */
|
case UnitDocument:
|
||||||
}
|
return em_size * dpi / 300.0; /* Per MSDN */
|
||||||
|
case UnitMillimeter:
|
||||||
static inline REAL mm_to_pixel (REAL mm)
|
return em_size * dpi / mm_per_inch;
|
||||||
{
|
}
|
||||||
return mm * (get_dpi() / mm_per_inch);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
@ -95,68 +175,53 @@ static inline REAL mm_to_pixel (REAL mm)
|
||||||
GpStatus WINGDIPAPI GdipCreateFont(GDIPCONST GpFontFamily *fontFamily,
|
GpStatus WINGDIPAPI GdipCreateFont(GDIPCONST GpFontFamily *fontFamily,
|
||||||
REAL emSize, INT style, Unit unit, GpFont **font)
|
REAL emSize, INT style, Unit unit, GpFont **font)
|
||||||
{
|
{
|
||||||
WCHAR facename[LF_FACESIZE];
|
HFONT hfont;
|
||||||
LOGFONTW* lfw;
|
OUTLINETEXTMETRICW otm;
|
||||||
const NEWTEXTMETRICW* tmw;
|
LOGFONTW lfw;
|
||||||
|
HDC hdc;
|
||||||
GpStatus stat;
|
GpStatus stat;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (!fontFamily || !font)
|
if (!fontFamily || !font || emSize < 0.0)
|
||||||
return InvalidParameter;
|
return InvalidParameter;
|
||||||
|
|
||||||
TRACE("%p (%s), %f, %d, %d, %p\n", fontFamily,
|
TRACE("%p (%s), %f, %d, %d, %p\n", fontFamily,
|
||||||
debugstr_w(fontFamily->FamilyName), emSize, style, unit, font);
|
debugstr_w(fontFamily->FamilyName), emSize, style, unit, font);
|
||||||
|
|
||||||
stat = GdipGetFamilyName (fontFamily, facename, 0);
|
memset(&lfw, 0, sizeof(lfw));
|
||||||
|
|
||||||
|
stat = GdipGetFamilyName(fontFamily, lfw.lfFaceName, LANG_NEUTRAL);
|
||||||
if (stat != Ok) return stat;
|
if (stat != Ok) return stat;
|
||||||
|
|
||||||
|
lfw.lfHeight = -em_size_to_pixel(emSize, unit, fontFamily->dpi);
|
||||||
|
lfw.lfWeight = style & FontStyleBold ? FW_BOLD : FW_REGULAR;
|
||||||
|
lfw.lfItalic = style & FontStyleItalic;
|
||||||
|
lfw.lfUnderline = style & FontStyleUnderline;
|
||||||
|
lfw.lfStrikeOut = style & FontStyleStrikeout;
|
||||||
|
|
||||||
|
hfont = CreateFontIndirectW(&lfw);
|
||||||
|
hdc = CreateCompatibleDC(0);
|
||||||
|
SelectObject(hdc, hfont);
|
||||||
|
otm.otmSize = sizeof(otm);
|
||||||
|
ret = GetOutlineTextMetricsW(hdc, otm.otmSize, &otm);
|
||||||
|
DeleteDC(hdc);
|
||||||
|
DeleteObject(hfont);
|
||||||
|
|
||||||
|
if (!ret) return NotTrueTypeFont;
|
||||||
|
|
||||||
*font = GdipAlloc(sizeof(GpFont));
|
*font = GdipAlloc(sizeof(GpFont));
|
||||||
|
if (!*font) return OutOfMemory;
|
||||||
tmw = &fontFamily->tmw;
|
|
||||||
lfw = &((*font)->lfw);
|
|
||||||
ZeroMemory(&(*lfw), sizeof(*lfw));
|
|
||||||
|
|
||||||
lfw->lfWeight = tmw->tmWeight;
|
|
||||||
lfw->lfItalic = tmw->tmItalic;
|
|
||||||
lfw->lfUnderline = tmw->tmUnderlined;
|
|
||||||
lfw->lfStrikeOut = tmw->tmStruckOut;
|
|
||||||
lfw->lfCharSet = tmw->tmCharSet;
|
|
||||||
lfw->lfPitchAndFamily = tmw->tmPitchAndFamily;
|
|
||||||
lstrcpynW(lfw->lfFaceName, facename, LF_FACESIZE);
|
|
||||||
|
|
||||||
switch (unit)
|
|
||||||
{
|
|
||||||
case UnitWorld:
|
|
||||||
/* FIXME: Figure out when World != Pixel */
|
|
||||||
(*font)->pixel_size = emSize; break;
|
|
||||||
case UnitDisplay:
|
|
||||||
FIXME("Unknown behavior for UnitDisplay! Please report!\n");
|
|
||||||
/* FIXME: Figure out how this works...
|
|
||||||
* MSDN says that if "DISPLAY" is a monitor, then pixel should be
|
|
||||||
* used. That's not what I got. Tests on Windows revealed no output,
|
|
||||||
* and the tests in tests/font crash windows */
|
|
||||||
(*font)->pixel_size = 0; break;
|
|
||||||
case UnitPixel:
|
|
||||||
(*font)->pixel_size = emSize; break;
|
|
||||||
case UnitPoint:
|
|
||||||
(*font)->pixel_size = point_to_pixel(emSize); break;
|
|
||||||
case UnitInch:
|
|
||||||
(*font)->pixel_size = inch_to_pixel(emSize); break;
|
|
||||||
case UnitDocument:
|
|
||||||
(*font)->pixel_size = document_to_pixel(emSize); break;
|
|
||||||
case UnitMillimeter:
|
|
||||||
(*font)->pixel_size = mm_to_pixel(emSize); break;
|
|
||||||
}
|
|
||||||
|
|
||||||
lfw->lfHeight = (*font)->pixel_size * -1;
|
|
||||||
|
|
||||||
lfw->lfWeight = style & FontStyleBold ? 700 : 400;
|
|
||||||
lfw->lfItalic = style & FontStyleItalic;
|
|
||||||
lfw->lfUnderline = style & FontStyleUnderline;
|
|
||||||
lfw->lfStrikeOut = style & FontStyleStrikeout;
|
|
||||||
|
|
||||||
(*font)->unit = unit;
|
(*font)->unit = unit;
|
||||||
(*font)->emSize = emSize;
|
(*font)->emSize = emSize;
|
||||||
(*font)->height = tmw->ntmSizeEM;
|
(*font)->otm = otm;
|
||||||
(*font)->line_spacing = tmw->tmAscent + tmw->tmDescent + tmw->tmExternalLeading;
|
|
||||||
|
stat = GdipCloneFontFamily((GpFontFamily *)fontFamily, &(*font)->family);
|
||||||
|
if (stat != Ok)
|
||||||
|
{
|
||||||
|
GdipFree(*font);
|
||||||
|
return stat;
|
||||||
|
}
|
||||||
|
|
||||||
TRACE("<-- %p\n", *font);
|
TRACE("<-- %p\n", *font);
|
||||||
|
|
||||||
|
@ -170,43 +235,38 @@ GpStatus WINGDIPAPI GdipCreateFontFromLogfontW(HDC hdc,
|
||||||
GDIPCONST LOGFONTW *logfont, GpFont **font)
|
GDIPCONST LOGFONTW *logfont, GpFont **font)
|
||||||
{
|
{
|
||||||
HFONT hfont, oldfont;
|
HFONT hfont, oldfont;
|
||||||
TEXTMETRICW textmet;
|
OUTLINETEXTMETRICW otm;
|
||||||
|
GpStatus stat;
|
||||||
|
int ret;
|
||||||
|
|
||||||
TRACE("(%p, %p, %p)\n", hdc, logfont, font);
|
TRACE("(%p, %p, %p)\n", hdc, logfont, font);
|
||||||
|
|
||||||
if(!logfont || !font)
|
if (!hdc || !logfont || !font)
|
||||||
return InvalidParameter;
|
return InvalidParameter;
|
||||||
|
|
||||||
if (logfont->lfFaceName[0] == 0)
|
hfont = CreateFontIndirectW(logfont);
|
||||||
return NotTrueTypeFont;
|
|
||||||
|
|
||||||
*font = GdipAlloc(sizeof(GpFont));
|
|
||||||
if(!*font) return OutOfMemory;
|
|
||||||
|
|
||||||
memcpy((*font)->lfw.lfFaceName, logfont->lfFaceName, LF_FACESIZE *
|
|
||||||
sizeof(WCHAR));
|
|
||||||
(*font)->lfw.lfHeight = logfont->lfHeight;
|
|
||||||
(*font)->lfw.lfItalic = logfont->lfItalic;
|
|
||||||
(*font)->lfw.lfUnderline = logfont->lfUnderline;
|
|
||||||
(*font)->lfw.lfStrikeOut = logfont->lfStrikeOut;
|
|
||||||
|
|
||||||
(*font)->pixel_size = (*font)->emSize = logfont->lfHeight;
|
|
||||||
(*font)->unit = UnitPixel;
|
|
||||||
|
|
||||||
hfont = CreateFontIndirectW(&(*font)->lfw);
|
|
||||||
oldfont = SelectObject(hdc, hfont);
|
oldfont = SelectObject(hdc, hfont);
|
||||||
GetTextMetricsW(hdc, &textmet);
|
otm.otmSize = sizeof(otm);
|
||||||
|
ret = GetOutlineTextMetricsW(hdc, otm.otmSize, &otm);
|
||||||
(*font)->lfw.lfHeight = -(textmet.tmHeight-textmet.tmInternalLeading);
|
|
||||||
(*font)->lfw.lfWeight = textmet.tmWeight;
|
|
||||||
(*font)->lfw.lfCharSet = textmet.tmCharSet;
|
|
||||||
|
|
||||||
(*font)->height = 1; /* FIXME: need NEWTEXTMETRIC.ntmSizeEM here */
|
|
||||||
(*font)->line_spacing = textmet.tmAscent + textmet.tmDescent + textmet.tmExternalLeading;
|
|
||||||
|
|
||||||
SelectObject(hdc, oldfont);
|
SelectObject(hdc, oldfont);
|
||||||
DeleteObject(hfont);
|
DeleteObject(hfont);
|
||||||
|
|
||||||
|
if (!ret) return NotTrueTypeFont;
|
||||||
|
|
||||||
|
*font = GdipAlloc(sizeof(GpFont));
|
||||||
|
if (!*font) return OutOfMemory;
|
||||||
|
|
||||||
|
(*font)->unit = UnitWorld;
|
||||||
|
(*font)->emSize = otm.otmTextMetrics.tmAscent;
|
||||||
|
(*font)->otm = otm;
|
||||||
|
|
||||||
|
stat = GdipCreateFontFamilyFromName(logfont->lfFaceName, NULL, &(*font)->family);
|
||||||
|
if (stat != Ok)
|
||||||
|
{
|
||||||
|
GdipFree(*font);
|
||||||
|
return NotTrueTypeFont;
|
||||||
|
}
|
||||||
|
|
||||||
TRACE("<-- %p\n", *font);
|
TRACE("<-- %p\n", *font);
|
||||||
|
|
||||||
return Ok;
|
return Ok;
|
||||||
|
@ -243,6 +303,7 @@ GpStatus WINGDIPAPI GdipDeleteFont(GpFont* font)
|
||||||
if(!font)
|
if(!font)
|
||||||
return InvalidParameter;
|
return InvalidParameter;
|
||||||
|
|
||||||
|
GdipDeleteFontFamily(font->family);
|
||||||
GdipFree(font);
|
GdipFree(font);
|
||||||
|
|
||||||
return Ok;
|
return Ok;
|
||||||
|
@ -291,7 +352,7 @@ GpStatus WINGDIPAPI GdipGetFamily(GpFont *font, GpFontFamily **family)
|
||||||
if (!(font && family))
|
if (!(font && family))
|
||||||
return InvalidParameter;
|
return InvalidParameter;
|
||||||
|
|
||||||
return GdipCreateFontFamilyFromName(font->lfw.lfFaceName, NULL, family);
|
return GdipCloneFontFamily(font->family, family);
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
|
@ -317,6 +378,7 @@ GpStatus WINGDIPAPI GdipGetFontSize(GpFont *font, REAL *size)
|
||||||
if (!(font && size)) return InvalidParameter;
|
if (!(font && size)) return InvalidParameter;
|
||||||
|
|
||||||
*size = font->emSize;
|
*size = font->emSize;
|
||||||
|
TRACE("%s,%d => %f\n", debugstr_w(font->family->FamilyName), font->otm.otmTextMetrics.tmHeight, *size);
|
||||||
|
|
||||||
return Ok;
|
return Ok;
|
||||||
}
|
}
|
||||||
|
@ -341,15 +403,15 @@ GpStatus WINGDIPAPI GdipGetFontStyle(GpFont *font, INT *style)
|
||||||
if (!(font && style))
|
if (!(font && style))
|
||||||
return InvalidParameter;
|
return InvalidParameter;
|
||||||
|
|
||||||
if (font->lfw.lfWeight > 400)
|
if (font->otm.otmTextMetrics.tmWeight > FW_REGULAR)
|
||||||
*style = FontStyleBold;
|
*style = FontStyleBold;
|
||||||
else
|
else
|
||||||
*style = 0;
|
*style = FontStyleRegular;
|
||||||
if (font->lfw.lfItalic)
|
if (font->otm.otmTextMetrics.tmItalic)
|
||||||
*style |= FontStyleItalic;
|
*style |= FontStyleItalic;
|
||||||
if (font->lfw.lfUnderline)
|
if (font->otm.otmTextMetrics.tmUnderlined)
|
||||||
*style |= FontStyleUnderline;
|
*style |= FontStyleUnderline;
|
||||||
if (font->lfw.lfStrikeOut)
|
if (font->otm.otmTextMetrics.tmStruckOut)
|
||||||
*style |= FontStyleStrikeout;
|
*style |= FontStyleStrikeout;
|
||||||
|
|
||||||
return Ok;
|
return Ok;
|
||||||
|
@ -373,6 +435,7 @@ GpStatus WINGDIPAPI GdipGetFontUnit(GpFont *font, Unit *unit)
|
||||||
if (!(font && unit)) return InvalidParameter;
|
if (!(font && unit)) return InvalidParameter;
|
||||||
|
|
||||||
*unit = font->unit;
|
*unit = font->unit;
|
||||||
|
TRACE("%s,%d => %d\n", debugstr_w(font->family->FamilyName), font->otm.otmTextMetrics.tmHeight, *unit);
|
||||||
|
|
||||||
return Ok;
|
return Ok;
|
||||||
}
|
}
|
||||||
|
@ -412,7 +475,22 @@ GpStatus WINGDIPAPI GdipGetLogFontW(GpFont *font, GpGraphics *graphics,
|
||||||
if(!font || !graphics || !lfw)
|
if(!font || !graphics || !lfw)
|
||||||
return InvalidParameter;
|
return InvalidParameter;
|
||||||
|
|
||||||
*lfw = font->lfw;
|
lfw->lfHeight = -font->otm.otmTextMetrics.tmAscent;
|
||||||
|
lfw->lfWidth = 0;
|
||||||
|
lfw->lfEscapement = 0;
|
||||||
|
lfw->lfOrientation = 0;
|
||||||
|
lfw->lfWeight = font->otm.otmTextMetrics.tmWeight;
|
||||||
|
lfw->lfItalic = font->otm.otmTextMetrics.tmItalic ? 1 : 0;
|
||||||
|
lfw->lfUnderline = font->otm.otmTextMetrics.tmUnderlined ? 1 : 0;
|
||||||
|
lfw->lfStrikeOut = font->otm.otmTextMetrics.tmStruckOut ? 1 : 0;
|
||||||
|
lfw->lfCharSet = font->otm.otmTextMetrics.tmCharSet;
|
||||||
|
lfw->lfOutPrecision = OUT_DEFAULT_PRECIS;
|
||||||
|
lfw->lfClipPrecision = CLIP_DEFAULT_PRECIS;
|
||||||
|
lfw->lfQuality = DEFAULT_QUALITY;
|
||||||
|
lfw->lfPitchAndFamily = 0;
|
||||||
|
strcpyW(lfw->lfFaceName, font->family->FamilyName);
|
||||||
|
|
||||||
|
TRACE("=> %s,%d\n", debugstr_w(lfw->lfFaceName), lfw->lfHeight);
|
||||||
|
|
||||||
return Ok;
|
return Ok;
|
||||||
}
|
}
|
||||||
|
@ -422,6 +500,8 @@ GpStatus WINGDIPAPI GdipGetLogFontW(GpFont *font, GpGraphics *graphics,
|
||||||
*/
|
*/
|
||||||
GpStatus WINGDIPAPI GdipCloneFont(GpFont *font, GpFont **cloneFont)
|
GpStatus WINGDIPAPI GdipCloneFont(GpFont *font, GpFont **cloneFont)
|
||||||
{
|
{
|
||||||
|
GpStatus stat;
|
||||||
|
|
||||||
TRACE("(%p, %p)\n", font, cloneFont);
|
TRACE("(%p, %p)\n", font, cloneFont);
|
||||||
|
|
||||||
if(!font || !cloneFont)
|
if(!font || !cloneFont)
|
||||||
|
@ -431,8 +511,10 @@ GpStatus WINGDIPAPI GdipCloneFont(GpFont *font, GpFont **cloneFont)
|
||||||
if(!*cloneFont) return OutOfMemory;
|
if(!*cloneFont) return OutOfMemory;
|
||||||
|
|
||||||
**cloneFont = *font;
|
**cloneFont = *font;
|
||||||
|
stat = GdipCloneFontFamily(font->family, &(*cloneFont)->family);
|
||||||
|
if (stat != Ok) GdipFree(*cloneFont);
|
||||||
|
|
||||||
return Ok;
|
return stat;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
@ -456,12 +538,15 @@ GpStatus WINGDIPAPI GdipGetFontHeight(GDIPCONST GpFont *font,
|
||||||
|
|
||||||
TRACE("%p %p %p\n", font, graphics, height);
|
TRACE("%p %p %p\n", font, graphics, height);
|
||||||
|
|
||||||
stat = GdipGetDpiY((GpGraphics*)graphics, &dpi);
|
if (graphics)
|
||||||
|
{
|
||||||
|
stat = GdipGetDpiY((GpGraphics*)graphics, &dpi);
|
||||||
|
if (stat != Ok) return stat;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
dpi = font->family->dpi;
|
||||||
|
|
||||||
if (stat == Ok)
|
return GdipGetFontHeightGivenDPI(font, dpi, height);
|
||||||
stat = GdipGetFontHeightGivenDPI(font, dpi, height);
|
|
||||||
|
|
||||||
return stat;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
@ -481,14 +566,26 @@ GpStatus WINGDIPAPI GdipGetFontHeight(GDIPCONST GpFont *font,
|
||||||
*/
|
*/
|
||||||
GpStatus WINGDIPAPI GdipGetFontHeightGivenDPI(GDIPCONST GpFont *font, REAL dpi, REAL *height)
|
GpStatus WINGDIPAPI GdipGetFontHeightGivenDPI(GDIPCONST GpFont *font, REAL dpi, REAL *height)
|
||||||
{
|
{
|
||||||
REAL font_height;
|
GpStatus stat;
|
||||||
|
INT style;
|
||||||
|
UINT16 line_spacing, em_height;
|
||||||
|
REAL font_height, font_size;
|
||||||
|
|
||||||
|
if (!font || !height) return InvalidParameter;
|
||||||
|
|
||||||
TRACE("%p (%s), %f, %p\n", font,
|
TRACE("%p (%s), %f, %p\n", font,
|
||||||
debugstr_w(font->lfw.lfFaceName), dpi, height);
|
debugstr_w(font->family->FamilyName), dpi, height);
|
||||||
|
|
||||||
if (!(font && height)) return InvalidParameter;
|
stat = GdipGetFontSize((GpFont *)font, &font_size);
|
||||||
|
if (stat != Ok) return stat;
|
||||||
|
stat = GdipGetFontStyle((GpFont *)font, &style);
|
||||||
|
if (stat != Ok) return stat;
|
||||||
|
stat = GdipGetLineSpacing(font->family, style, &line_spacing);
|
||||||
|
if (stat != Ok) return stat;
|
||||||
|
stat = GdipGetEmHeight(font->family, style, &em_height);
|
||||||
|
if (stat != Ok) return stat;
|
||||||
|
|
||||||
font_height = font->line_spacing * (font->emSize / font->height);
|
font_height = (REAL)line_spacing * font_size / (REAL)em_height;
|
||||||
|
|
||||||
switch (font->unit)
|
switch (font->unit)
|
||||||
{
|
{
|
||||||
|
@ -513,6 +610,9 @@ GpStatus WINGDIPAPI GdipGetFontHeightGivenDPI(GDIPCONST GpFont *font, REAL dpi,
|
||||||
return NotImplemented;
|
return NotImplemented;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TRACE("%s,%d(unit %d) => %f\n",
|
||||||
|
debugstr_w(font->family->FamilyName), font->otm.otmTextMetrics.tmHeight, font->unit, *height);
|
||||||
|
|
||||||
return Ok;
|
return Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -525,25 +625,87 @@ GpStatus WINGDIPAPI GdipGetFontHeightGivenDPI(GDIPCONST GpFont *font, REAL dpi,
|
||||||
static INT CALLBACK is_font_installed_proc(const LOGFONTW *elf,
|
static INT CALLBACK is_font_installed_proc(const LOGFONTW *elf,
|
||||||
const TEXTMETRICW *ntm, DWORD type, LPARAM lParam)
|
const TEXTMETRICW *ntm, DWORD type, LPARAM lParam)
|
||||||
{
|
{
|
||||||
if (!ntm || type == RASTER_FONTTYPE)
|
if (type != TRUETYPE_FONTTYPE)
|
||||||
{
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
|
||||||
|
|
||||||
*(NEWTEXTMETRICW*)lParam = *(const NEWTEXTMETRICW*)ntm;
|
*(LOGFONTW *)lParam = *elf;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL find_installed_font(const WCHAR *name, NEWTEXTMETRICW *ntm)
|
struct font_metrics
|
||||||
{
|
{
|
||||||
HDC hdc = GetDC(0);
|
UINT16 em_height, ascent, descent, line_spacing; /* in font units */
|
||||||
BOOL ret = FALSE;
|
int dpi;
|
||||||
|
};
|
||||||
|
|
||||||
if(!EnumFontFamiliesW(hdc, name, is_font_installed_proc, (LPARAM)ntm))
|
static BOOL get_font_metrics(HDC hdc, struct font_metrics *fm)
|
||||||
ret = TRUE;
|
{
|
||||||
|
OUTLINETEXTMETRICW otm;
|
||||||
|
TT_OS2_V2 tt_os2;
|
||||||
|
TT_HHEA tt_hori;
|
||||||
|
LONG size;
|
||||||
|
UINT16 line_gap;
|
||||||
|
|
||||||
ReleaseDC(0, hdc);
|
otm.otmSize = sizeof(otm);
|
||||||
|
if (!GetOutlineTextMetricsW(hdc, otm.otmSize, &otm)) return FALSE;
|
||||||
|
|
||||||
|
fm->em_height = otm.otmEMSquare;
|
||||||
|
fm->dpi = GetDeviceCaps(hdc, LOGPIXELSY);
|
||||||
|
|
||||||
|
memset(&tt_hori, 0, sizeof(tt_hori));
|
||||||
|
if (GetFontData(hdc, MS_HHEA_TAG, 0, &tt_hori, sizeof(tt_hori)) != GDI_ERROR)
|
||||||
|
{
|
||||||
|
fm->ascent = GET_BE_WORD(tt_hori.Ascender);
|
||||||
|
fm->descent = -GET_BE_WORD(tt_hori.Descender);
|
||||||
|
TRACE("hhea: ascent %d, descent %d\n", fm->ascent, fm->descent);
|
||||||
|
line_gap = GET_BE_WORD(tt_hori.LineGap);
|
||||||
|
fm->line_spacing = fm->ascent + fm->descent + line_gap;
|
||||||
|
TRACE("line_gap %u, line_spacing %u\n", line_gap, fm->line_spacing);
|
||||||
|
if (fm->ascent + fm->descent != 0) return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
size = GetFontData(hdc, MS_OS2_TAG, 0, NULL, 0);
|
||||||
|
if (size == GDI_ERROR) return FALSE;
|
||||||
|
|
||||||
|
if (size > sizeof(tt_os2)) size = sizeof(tt_os2);
|
||||||
|
|
||||||
|
memset(&tt_os2, 0, sizeof(tt_os2));
|
||||||
|
if (GetFontData(hdc, MS_OS2_TAG, 0, &tt_os2, size) != size) return FALSE;
|
||||||
|
|
||||||
|
fm->ascent = GET_BE_WORD(tt_os2.usWinAscent);
|
||||||
|
fm->descent = GET_BE_WORD(tt_os2.usWinDescent);
|
||||||
|
TRACE("usWinAscent %u, usWinDescent %u\n", fm->ascent, fm->descent);
|
||||||
|
if (fm->ascent + fm->descent == 0)
|
||||||
|
{
|
||||||
|
fm->ascent = GET_BE_WORD(tt_os2.sTypoAscender);
|
||||||
|
fm->descent = GET_BE_WORD(tt_os2.sTypoDescender);
|
||||||
|
TRACE("sTypoAscender %u, sTypoDescender %u\n", fm->ascent, fm->descent);
|
||||||
|
}
|
||||||
|
line_gap = GET_BE_WORD(tt_os2.sTypoLineGap);
|
||||||
|
fm->line_spacing = fm->ascent + fm->descent + line_gap;
|
||||||
|
TRACE("line_gap %u, line_spacing %u\n", line_gap, fm->line_spacing);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GpStatus find_installed_font(const WCHAR *name, struct font_metrics *fm)
|
||||||
|
{
|
||||||
|
LOGFONTW lf;
|
||||||
|
HDC hdc = CreateCompatibleDC(0);
|
||||||
|
GpStatus ret = FontFamilyNotFound;
|
||||||
|
|
||||||
|
if(!EnumFontFamiliesW(hdc, name, is_font_installed_proc, (LPARAM)&lf))
|
||||||
|
{
|
||||||
|
HFONT hfont, old_font;
|
||||||
|
|
||||||
|
hfont = CreateFontIndirectW(&lf);
|
||||||
|
old_font = SelectObject(hdc, hfont);
|
||||||
|
ret = get_font_metrics(hdc, fm) ? Ok : NotTrueTypeFont;
|
||||||
|
SelectObject(hdc, old_font);
|
||||||
|
DeleteObject(hfont);
|
||||||
|
}
|
||||||
|
|
||||||
|
DeleteDC(hdc);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -571,8 +733,9 @@ GpStatus WINGDIPAPI GdipCreateFontFamilyFromName(GDIPCONST WCHAR *name,
|
||||||
GpFontCollection *fontCollection,
|
GpFontCollection *fontCollection,
|
||||||
GpFontFamily **FontFamily)
|
GpFontFamily **FontFamily)
|
||||||
{
|
{
|
||||||
|
GpStatus stat;
|
||||||
GpFontFamily* ffamily;
|
GpFontFamily* ffamily;
|
||||||
NEWTEXTMETRICW ntm;
|
struct font_metrics fm;
|
||||||
|
|
||||||
TRACE("%s, %p %p\n", debugstr_w(name), fontCollection, FontFamily);
|
TRACE("%s, %p %p\n", debugstr_w(name), fontCollection, FontFamily);
|
||||||
|
|
||||||
|
@ -581,14 +744,18 @@ GpStatus WINGDIPAPI GdipCreateFontFamilyFromName(GDIPCONST WCHAR *name,
|
||||||
if (fontCollection)
|
if (fontCollection)
|
||||||
FIXME("No support for FontCollections yet!\n");
|
FIXME("No support for FontCollections yet!\n");
|
||||||
|
|
||||||
if (!find_installed_font(name, &ntm))
|
stat = find_installed_font(name, &fm);
|
||||||
return FontFamilyNotFound;
|
if (stat != Ok) return stat;
|
||||||
|
|
||||||
ffamily = GdipAlloc(sizeof (GpFontFamily));
|
ffamily = GdipAlloc(sizeof (GpFontFamily));
|
||||||
if (!ffamily) return OutOfMemory;
|
if (!ffamily) return OutOfMemory;
|
||||||
|
|
||||||
ffamily->tmw = ntm;
|
|
||||||
lstrcpynW(ffamily->FamilyName, name, LF_FACESIZE);
|
lstrcpynW(ffamily->FamilyName, name, LF_FACESIZE);
|
||||||
|
ffamily->em_height = fm.em_height;
|
||||||
|
ffamily->ascent = fm.ascent;
|
||||||
|
ffamily->descent = fm.descent;
|
||||||
|
ffamily->line_spacing = fm.line_spacing;
|
||||||
|
ffamily->dpi = fm.dpi;
|
||||||
|
|
||||||
*FontFamily = ffamily;
|
*FontFamily = ffamily;
|
||||||
|
|
||||||
|
@ -613,13 +780,13 @@ GpStatus WINGDIPAPI GdipCloneFontFamily(GpFontFamily* FontFamily, GpFontFamily**
|
||||||
{
|
{
|
||||||
if (!(FontFamily && clonedFontFamily)) return InvalidParameter;
|
if (!(FontFamily && clonedFontFamily)) return InvalidParameter;
|
||||||
|
|
||||||
TRACE("stub: %p (%s), %p\n", FontFamily,
|
TRACE("%p (%s), %p\n", FontFamily,
|
||||||
debugstr_w(FontFamily->FamilyName), clonedFontFamily);
|
debugstr_w(FontFamily->FamilyName), clonedFontFamily);
|
||||||
|
|
||||||
*clonedFontFamily = GdipAlloc(sizeof(GpFontFamily));
|
*clonedFontFamily = GdipAlloc(sizeof(GpFontFamily));
|
||||||
if (!*clonedFontFamily) return OutOfMemory;
|
if (!*clonedFontFamily) return OutOfMemory;
|
||||||
|
|
||||||
(*clonedFontFamily)->tmw = FontFamily->tmw;
|
**clonedFontFamily = *FontFamily;
|
||||||
lstrcpyW((*clonedFontFamily)->FamilyName, FontFamily->FamilyName);
|
lstrcpyW((*clonedFontFamily)->FamilyName, FontFamily->FamilyName);
|
||||||
|
|
||||||
TRACE("<-- %p\n", *clonedFontFamily);
|
TRACE("<-- %p\n", *clonedFontFamily);
|
||||||
|
@ -692,7 +859,8 @@ GpStatus WINGDIPAPI GdipGetCellAscent(GDIPCONST GpFontFamily *family,
|
||||||
{
|
{
|
||||||
if (!(family && CellAscent)) return InvalidParameter;
|
if (!(family && CellAscent)) return InvalidParameter;
|
||||||
|
|
||||||
*CellAscent = family->tmw.tmAscent;
|
*CellAscent = family->ascent;
|
||||||
|
TRACE("%s => %u\n", debugstr_w(family->FamilyName), *CellAscent);
|
||||||
|
|
||||||
return Ok;
|
return Ok;
|
||||||
}
|
}
|
||||||
|
@ -704,7 +872,8 @@ GpStatus WINGDIPAPI GdipGetCellDescent(GDIPCONST GpFontFamily *family,
|
||||||
|
|
||||||
if (!(family && CellDescent)) return InvalidParameter;
|
if (!(family && CellDescent)) return InvalidParameter;
|
||||||
|
|
||||||
*CellDescent = family->tmw.tmDescent;
|
*CellDescent = family->descent;
|
||||||
|
TRACE("%s => %u\n", debugstr_w(family->FamilyName), *CellDescent);
|
||||||
|
|
||||||
return Ok;
|
return Ok;
|
||||||
}
|
}
|
||||||
|
@ -729,7 +898,8 @@ GpStatus WINGDIPAPI GdipGetEmHeight(GDIPCONST GpFontFamily *family, INT style, U
|
||||||
|
|
||||||
TRACE("%p (%s), %d, %p\n", family, debugstr_w(family->FamilyName), style, EmHeight);
|
TRACE("%p (%s), %d, %p\n", family, debugstr_w(family->FamilyName), style, EmHeight);
|
||||||
|
|
||||||
*EmHeight = family->tmw.ntmSizeEM;
|
*EmHeight = family->em_height;
|
||||||
|
TRACE("%s => %u\n", debugstr_w(family->FamilyName), *EmHeight);
|
||||||
|
|
||||||
return Ok;
|
return Ok;
|
||||||
}
|
}
|
||||||
|
@ -759,7 +929,8 @@ GpStatus WINGDIPAPI GdipGetLineSpacing(GDIPCONST GpFontFamily *family,
|
||||||
|
|
||||||
if (style) FIXME("ignoring style\n");
|
if (style) FIXME("ignoring style\n");
|
||||||
|
|
||||||
*LineSpacing = family->tmw.tmAscent + family->tmw.tmDescent + family->tmw.tmExternalLeading;
|
*LineSpacing = family->line_spacing;
|
||||||
|
TRACE("%s => %u\n", debugstr_w(family->FamilyName), *LineSpacing);
|
||||||
|
|
||||||
return Ok;
|
return Ok;
|
||||||
}
|
}
|
||||||
|
@ -767,7 +938,7 @@ GpStatus WINGDIPAPI GdipGetLineSpacing(GDIPCONST GpFontFamily *family,
|
||||||
static INT CALLBACK font_has_style_proc(const LOGFONTW *elf,
|
static INT CALLBACK font_has_style_proc(const LOGFONTW *elf,
|
||||||
const TEXTMETRICW *ntm, DWORD type, LPARAM lParam)
|
const TEXTMETRICW *ntm, DWORD type, LPARAM lParam)
|
||||||
{
|
{
|
||||||
INT fontstyle=0;
|
INT fontstyle = FontStyleRegular;
|
||||||
|
|
||||||
if (!ntm) return 1;
|
if (!ntm) return 1;
|
||||||
|
|
||||||
|
|
|
@ -265,7 +265,6 @@ COLORREF ARGB2COLORREF(ARGB color)
|
||||||
|
|
||||||
HBITMAP ARGB2BMP(ARGB color)
|
HBITMAP ARGB2BMP(ARGB color)
|
||||||
{
|
{
|
||||||
HDC hdc;
|
|
||||||
BITMAPINFO bi;
|
BITMAPINFO bi;
|
||||||
HBITMAP result;
|
HBITMAP result;
|
||||||
RGBQUAD *bits;
|
RGBQUAD *bits;
|
||||||
|
@ -273,8 +272,6 @@ HBITMAP ARGB2BMP(ARGB color)
|
||||||
|
|
||||||
if ((color & 0xff000000) == 0xff000000) return 0;
|
if ((color & 0xff000000) == 0xff000000) return 0;
|
||||||
|
|
||||||
hdc = CreateCompatibleDC(NULL);
|
|
||||||
|
|
||||||
bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
|
bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
|
||||||
bi.bmiHeader.biWidth = 1;
|
bi.bmiHeader.biWidth = 1;
|
||||||
bi.bmiHeader.biHeight = 1;
|
bi.bmiHeader.biHeight = 1;
|
||||||
|
@ -287,15 +284,13 @@ HBITMAP ARGB2BMP(ARGB color)
|
||||||
bi.bmiHeader.biClrUsed = 0;
|
bi.bmiHeader.biClrUsed = 0;
|
||||||
bi.bmiHeader.biClrImportant = 0;
|
bi.bmiHeader.biClrImportant = 0;
|
||||||
|
|
||||||
result = CreateDIBSection(hdc, &bi, DIB_RGB_COLORS, (void*)&bits, NULL, 0);
|
result = CreateDIBSection(0, &bi, DIB_RGB_COLORS, (void*)&bits, NULL, 0);
|
||||||
|
|
||||||
bits[0].rgbReserved = alpha = (color>>24)&0xff;
|
bits[0].rgbReserved = alpha = (color>>24)&0xff;
|
||||||
bits[0].rgbRed = ((color>>16)&0xff)*alpha/255;
|
bits[0].rgbRed = ((color>>16)&0xff)*alpha/255;
|
||||||
bits[0].rgbGreen = ((color>>8)&0xff)*alpha/255;
|
bits[0].rgbGreen = ((color>>8)&0xff)*alpha/255;
|
||||||
bits[0].rgbBlue = (color&0xff)*alpha/255;
|
bits[0].rgbBlue = (color&0xff)*alpha/255;
|
||||||
|
|
||||||
DeleteDC(hdc);
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -316,7 +316,7 @@
|
||||||
316 stdcall GdipGetPathGradientCenterPointI(ptr ptr)
|
316 stdcall GdipGetPathGradientCenterPointI(ptr ptr)
|
||||||
317 stdcall GdipGetPathGradientFocusScales(ptr ptr ptr)
|
317 stdcall GdipGetPathGradientFocusScales(ptr ptr ptr)
|
||||||
318 stdcall GdipGetPathGradientGammaCorrection(ptr ptr)
|
318 stdcall GdipGetPathGradientGammaCorrection(ptr ptr)
|
||||||
319 stub GdipGetPathGradientPath
|
319 stdcall GdipGetPathGradientPath(ptr ptr)
|
||||||
320 stdcall GdipGetPathGradientPointCount(ptr ptr)
|
320 stdcall GdipGetPathGradientPointCount(ptr ptr)
|
||||||
321 stdcall GdipGetPathGradientPresetBlend(ptr ptr ptr long)
|
321 stdcall GdipGetPathGradientPresetBlend(ptr ptr ptr long)
|
||||||
322 stdcall GdipGetPathGradientPresetBlendCount(ptr ptr)
|
322 stdcall GdipGetPathGradientPresetBlendCount(ptr ptr)
|
||||||
|
@ -457,9 +457,9 @@
|
||||||
457 stdcall GdipResetClip(ptr)
|
457 stdcall GdipResetClip(ptr)
|
||||||
458 stub GdipResetImageAttributes
|
458 stub GdipResetImageAttributes
|
||||||
459 stdcall GdipResetLineTransform(ptr)
|
459 stdcall GdipResetLineTransform(ptr)
|
||||||
460 stub GdipResetPageTransform
|
460 stdcall GdipResetPageTransform(ptr)
|
||||||
461 stdcall GdipResetPath(ptr)
|
461 stdcall GdipResetPath(ptr)
|
||||||
462 stub GdipResetPathGradientTransform
|
462 stdcall GdipResetPathGradientTransform(ptr)
|
||||||
463 stdcall GdipResetPenTransform(ptr)
|
463 stdcall GdipResetPenTransform(ptr)
|
||||||
464 stdcall GdipResetTextureTransform(ptr)
|
464 stdcall GdipResetTextureTransform(ptr)
|
||||||
465 stdcall GdipResetWorldTransform(ptr)
|
465 stdcall GdipResetWorldTransform(ptr)
|
||||||
|
|
|
@ -161,6 +161,7 @@ struct GpGraphics{
|
||||||
UINT textcontrast; /* not used yet. get/set only */
|
UINT textcontrast; /* not used yet. get/set only */
|
||||||
struct list containers;
|
struct list containers;
|
||||||
GraphicsContainer contid; /* last-issued container ID */
|
GraphicsContainer contid; /* last-issued container ID */
|
||||||
|
INT origin_x, origin_y;
|
||||||
/* For giving the caller an HDC when we technically can't: */
|
/* For giving the caller an HDC when we technically can't: */
|
||||||
HBITMAP temp_hbitmap;
|
HBITMAP temp_hbitmap;
|
||||||
int temp_hbitmap_width;
|
int temp_hbitmap_width;
|
||||||
|
@ -170,9 +171,7 @@ struct GpGraphics{
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GpBrush{
|
struct GpBrush{
|
||||||
HBRUSH gdibrush;
|
|
||||||
GpBrushType bt;
|
GpBrushType bt;
|
||||||
LOGBRUSH lb;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GpHatch{
|
struct GpHatch{
|
||||||
|
@ -185,12 +184,11 @@ struct GpHatch{
|
||||||
struct GpSolidFill{
|
struct GpSolidFill{
|
||||||
GpBrush brush;
|
GpBrush brush;
|
||||||
ARGB color;
|
ARGB color;
|
||||||
HBITMAP bmp;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GpPathGradient{
|
struct GpPathGradient{
|
||||||
GpBrush brush;
|
GpBrush brush;
|
||||||
PathData pathdata;
|
GpPath* path;
|
||||||
ARGB centercolor;
|
ARGB centercolor;
|
||||||
GpWrapMode wrap;
|
GpWrapMode wrap;
|
||||||
BOOL gamma;
|
BOOL gamma;
|
||||||
|
@ -199,6 +197,12 @@ struct GpPathGradient{
|
||||||
REAL* blendfac; /* blend factors */
|
REAL* blendfac; /* blend factors */
|
||||||
REAL* blendpos; /* blend positions */
|
REAL* blendpos; /* blend positions */
|
||||||
INT blendcount;
|
INT blendcount;
|
||||||
|
ARGB *surroundcolors;
|
||||||
|
INT surroundcolorcount;
|
||||||
|
ARGB* pblendcolor; /* preset blend colors */
|
||||||
|
REAL* pblendpos; /* preset blend positions */
|
||||||
|
INT pblendcount;
|
||||||
|
GpMatrix *transform;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GpLineGradient{
|
struct GpLineGradient{
|
||||||
|
@ -327,7 +331,7 @@ struct color_matrix{
|
||||||
struct color_remap_table{
|
struct color_remap_table{
|
||||||
BOOL enabled;
|
BOOL enabled;
|
||||||
INT mapsize;
|
INT mapsize;
|
||||||
GDIPCONST ColorMap *colormap;
|
ColorMap *colormap;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GpImageAttributes{
|
struct GpImageAttributes{
|
||||||
|
@ -342,11 +346,9 @@ struct GpImageAttributes{
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GpFont{
|
struct GpFont{
|
||||||
LOGFONTW lfw;
|
GpFontFamily *family;
|
||||||
REAL emSize;
|
OUTLINETEXTMETRICW otm;
|
||||||
REAL pixel_size;
|
REAL emSize; /* in font units */
|
||||||
UINT height;
|
|
||||||
LONG line_spacing;
|
|
||||||
Unit unit;
|
Unit unit;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -373,8 +375,9 @@ struct GpFontCollection{
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GpFontFamily{
|
struct GpFontFamily{
|
||||||
NEWTEXTMETRICW tmw;
|
|
||||||
WCHAR FamilyName[LF_FACESIZE];
|
WCHAR FamilyName[LF_FACESIZE];
|
||||||
|
UINT16 em_height, ascent, descent, line_spacing; /* in font units */
|
||||||
|
int dpi;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* internal use */
|
/* internal use */
|
||||||
|
@ -425,7 +428,8 @@ struct GpRegion{
|
||||||
typedef GpStatus (*gdip_format_string_callback)(HDC hdc,
|
typedef GpStatus (*gdip_format_string_callback)(HDC hdc,
|
||||||
GDIPCONST WCHAR *string, INT index, INT length, GDIPCONST GpFont *font,
|
GDIPCONST WCHAR *string, INT index, INT length, GDIPCONST GpFont *font,
|
||||||
GDIPCONST RectF *rect, GDIPCONST GpStringFormat *format,
|
GDIPCONST RectF *rect, GDIPCONST GpStringFormat *format,
|
||||||
INT lineno, const RectF *bounds, void *user_data);
|
INT lineno, const RectF *bounds, INT *underlined_indexes,
|
||||||
|
INT underlined_index_count, void *user_data);
|
||||||
|
|
||||||
GpStatus gdip_format_string(HDC hdc,
|
GpStatus gdip_format_string(HDC hdc,
|
||||||
GDIPCONST WCHAR *string, INT length, GDIPCONST GpFont *font,
|
GDIPCONST WCHAR *string, INT length, GDIPCONST GpFont *font,
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -846,7 +846,8 @@ struct format_string_args
|
||||||
static GpStatus format_string_callback(HDC dc,
|
static GpStatus format_string_callback(HDC dc,
|
||||||
GDIPCONST WCHAR *string, INT index, INT length, GDIPCONST GpFont *font,
|
GDIPCONST WCHAR *string, INT index, INT length, GDIPCONST GpFont *font,
|
||||||
GDIPCONST RectF *rect, GDIPCONST GpStringFormat *format,
|
GDIPCONST RectF *rect, GDIPCONST GpStringFormat *format,
|
||||||
INT lineno, const RectF *bounds, void *priv)
|
INT lineno, const RectF *bounds, INT *underlined_indexes,
|
||||||
|
INT underlined_index_count, void *priv)
|
||||||
{
|
{
|
||||||
static const MAT2 identity = { {0,1}, {0,0}, {0,0}, {0,1} };
|
static const MAT2 identity = { {0,1}, {0,0}, {0,0}, {0,1} };
|
||||||
struct format_string_args *args = priv;
|
struct format_string_args *args = priv;
|
||||||
|
@ -856,6 +857,9 @@ static GpStatus format_string_callback(HDC dc,
|
||||||
float y = bounds->Y;
|
float y = bounds->Y;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
if (underlined_index_count)
|
||||||
|
FIXME("hotkey underlines not drawn yet\n");
|
||||||
|
|
||||||
for (i = index; i < length; ++i)
|
for (i = index; i < length; ++i)
|
||||||
{
|
{
|
||||||
GLYPHMETRICS gm;
|
GLYPHMETRICS gm;
|
||||||
|
@ -938,6 +942,7 @@ GpStatus WINGDIPAPI GdipAddPathString(GpPath* path, GDIPCONST WCHAR* string, INT
|
||||||
{
|
{
|
||||||
GpFont *font;
|
GpFont *font;
|
||||||
GpStatus status;
|
GpStatus status;
|
||||||
|
LOGFONTW lfw;
|
||||||
HANDLE hfont;
|
HANDLE hfont;
|
||||||
HDC dc;
|
HDC dc;
|
||||||
GpPath *backup;
|
GpPath *backup;
|
||||||
|
@ -952,7 +957,9 @@ GpStatus WINGDIPAPI GdipAddPathString(GpPath* path, GDIPCONST WCHAR* string, INT
|
||||||
if (status != Ok)
|
if (status != Ok)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
hfont = CreateFontIndirectW(&font->lfw);
|
status = GdipGetLogFontW((GpFont *)font, NULL, &lfw);
|
||||||
|
if (status != Ok) return status;
|
||||||
|
hfont = CreateFontIndirectW(&lfw);
|
||||||
if (!hfont)
|
if (!hfont)
|
||||||
{
|
{
|
||||||
WARN("Failed to create font\n");
|
WARN("Failed to create font\n");
|
||||||
|
@ -1207,14 +1214,7 @@ GpStatus WINGDIPAPI GdipFlattenPath(GpPath *path, GpMatrix* matrix, REAL flatnes
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Bezier curve always stored as 4 points */
|
/* Bezier curve */
|
||||||
if((path->pathdata.Types[i-1] & PathPointTypePathTypeMask) != PathPointTypeStart){
|
|
||||||
type = (path->pathdata.Types[i] & ~PathPointTypePathTypeMask) | PathPointTypeLine;
|
|
||||||
if(!add_path_list_node(node, pt.X, pt.Y, type))
|
|
||||||
goto memout;
|
|
||||||
|
|
||||||
node = node->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* test for closed figure */
|
/* test for closed figure */
|
||||||
if(path->pathdata.Types[i+1] & PathPointTypeCloseSubpath){
|
if(path->pathdata.Types[i+1] & PathPointTypeCloseSubpath){
|
||||||
|
@ -1659,12 +1659,222 @@ GpStatus WINGDIPAPI GdipWarpPath(GpPath *path, GpMatrix* matrix,
|
||||||
return NotImplemented;
|
return NotImplemented;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void add_bevel_point(const GpPointF *endpoint, const GpPointF *nextpoint,
|
||||||
|
GpPen *pen, int right_side, path_list_node_t **last_point)
|
||||||
|
{
|
||||||
|
REAL segment_dy = nextpoint->Y-endpoint->Y;
|
||||||
|
REAL segment_dx = nextpoint->X-endpoint->X;
|
||||||
|
REAL segment_length = sqrtf(segment_dy*segment_dy + segment_dx*segment_dx);
|
||||||
|
REAL distance = pen->width/2.0;
|
||||||
|
REAL bevel_dx, bevel_dy;
|
||||||
|
|
||||||
|
if (right_side)
|
||||||
|
{
|
||||||
|
bevel_dx = -distance * segment_dy / segment_length;
|
||||||
|
bevel_dy = distance * segment_dx / segment_length;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bevel_dx = distance * segment_dy / segment_length;
|
||||||
|
bevel_dy = -distance * segment_dx / segment_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
*last_point = add_path_list_node(*last_point, endpoint->X + bevel_dx,
|
||||||
|
endpoint->Y + bevel_dy, PathPointTypeLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void widen_joint(const GpPointF *p1, const GpPointF *p2, const GpPointF *p3,
|
||||||
|
GpPen* pen, path_list_node_t **last_point)
|
||||||
|
{
|
||||||
|
switch (pen->join)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
case LineJoinBevel:
|
||||||
|
add_bevel_point(p2, p1, pen, 1, last_point);
|
||||||
|
add_bevel_point(p2, p3, pen, 0, last_point);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void widen_cap(const GpPointF *endpoint, const GpPointF *nextpoint,
|
||||||
|
GpPen *pen, GpLineCap cap, GpCustomLineCap *custom, int add_first_points,
|
||||||
|
int add_last_point, path_list_node_t **last_point)
|
||||||
|
{
|
||||||
|
switch (cap)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
case LineCapFlat:
|
||||||
|
if (add_first_points)
|
||||||
|
add_bevel_point(endpoint, nextpoint, pen, 1, last_point);
|
||||||
|
if (add_last_point)
|
||||||
|
add_bevel_point(endpoint, nextpoint, pen, 0, last_point);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void widen_open_figure(GpPath *path, GpPen *pen, int start, int end,
|
||||||
|
path_list_node_t **last_point)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (end <= start)
|
||||||
|
return;
|
||||||
|
|
||||||
|
widen_cap(&path->pathdata.Points[start], &path->pathdata.Points[start+1],
|
||||||
|
pen, pen->startcap, pen->customstart, FALSE, TRUE, last_point);
|
||||||
|
|
||||||
|
(*last_point)->type = PathPointTypeStart;
|
||||||
|
|
||||||
|
for (i=start+1; i<end; i++)
|
||||||
|
widen_joint(&path->pathdata.Points[i-1], &path->pathdata.Points[i],
|
||||||
|
&path->pathdata.Points[i+1], pen, last_point);
|
||||||
|
|
||||||
|
widen_cap(&path->pathdata.Points[end], &path->pathdata.Points[end-1],
|
||||||
|
pen, pen->endcap, pen->customend, TRUE, TRUE, last_point);
|
||||||
|
|
||||||
|
for (i=end-1; i>start; i--)
|
||||||
|
widen_joint(&path->pathdata.Points[i+1], &path->pathdata.Points[i],
|
||||||
|
&path->pathdata.Points[i-1], pen, last_point);
|
||||||
|
|
||||||
|
widen_cap(&path->pathdata.Points[start], &path->pathdata.Points[start+1],
|
||||||
|
pen, pen->startcap, pen->customstart, TRUE, FALSE, last_point);
|
||||||
|
|
||||||
|
(*last_point)->type |= PathPointTypeCloseSubpath;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void widen_closed_figure(GpPath *path, GpPen *pen, int start, int end,
|
||||||
|
path_list_node_t **last_point)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
path_list_node_t *prev_point;
|
||||||
|
|
||||||
|
if (end <= start+1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* left outline */
|
||||||
|
prev_point = *last_point;
|
||||||
|
|
||||||
|
widen_joint(&path->pathdata.Points[end], &path->pathdata.Points[start],
|
||||||
|
&path->pathdata.Points[start+1], pen, last_point);
|
||||||
|
|
||||||
|
for (i=start+1; i<end; i++)
|
||||||
|
widen_joint(&path->pathdata.Points[i-1], &path->pathdata.Points[i],
|
||||||
|
&path->pathdata.Points[i+1], pen, last_point);
|
||||||
|
|
||||||
|
widen_joint(&path->pathdata.Points[end-1], &path->pathdata.Points[end],
|
||||||
|
&path->pathdata.Points[start], pen, last_point);
|
||||||
|
|
||||||
|
prev_point->next->type = PathPointTypeStart;
|
||||||
|
(*last_point)->type |= PathPointTypeCloseSubpath;
|
||||||
|
|
||||||
|
/* right outline */
|
||||||
|
prev_point = *last_point;
|
||||||
|
|
||||||
|
widen_joint(&path->pathdata.Points[start], &path->pathdata.Points[end],
|
||||||
|
&path->pathdata.Points[end-1], pen, last_point);
|
||||||
|
|
||||||
|
for (i=end-1; i>start; i--)
|
||||||
|
widen_joint(&path->pathdata.Points[i+1], &path->pathdata.Points[i],
|
||||||
|
&path->pathdata.Points[i-1], pen, last_point);
|
||||||
|
|
||||||
|
widen_joint(&path->pathdata.Points[start+1], &path->pathdata.Points[start],
|
||||||
|
&path->pathdata.Points[end], pen, last_point);
|
||||||
|
|
||||||
|
prev_point->next->type = PathPointTypeStart;
|
||||||
|
(*last_point)->type |= PathPointTypeCloseSubpath;
|
||||||
|
}
|
||||||
|
|
||||||
GpStatus WINGDIPAPI GdipWidenPath(GpPath *path, GpPen *pen, GpMatrix *matrix,
|
GpStatus WINGDIPAPI GdipWidenPath(GpPath *path, GpPen *pen, GpMatrix *matrix,
|
||||||
REAL flatness)
|
REAL flatness)
|
||||||
{
|
{
|
||||||
FIXME("(%p,%p,%p,%0.2f)\n", path, pen, matrix, flatness);
|
GpPath *flat_path=NULL;
|
||||||
|
GpStatus status;
|
||||||
|
path_list_node_t *points=NULL, *last_point=NULL;
|
||||||
|
int i, subpath_start=0, new_length;
|
||||||
|
BYTE type;
|
||||||
|
|
||||||
return NotImplemented;
|
TRACE("(%p,%p,%p,%0.2f)\n", path, pen, matrix, flatness);
|
||||||
|
|
||||||
|
if (!path || !pen)
|
||||||
|
return InvalidParameter;
|
||||||
|
|
||||||
|
if (path->pathdata.Count <= 1)
|
||||||
|
return OutOfMemory;
|
||||||
|
|
||||||
|
status = GdipClonePath(path, &flat_path);
|
||||||
|
|
||||||
|
if (status == Ok)
|
||||||
|
status = GdipFlattenPath(flat_path, matrix, flatness);
|
||||||
|
|
||||||
|
if (status == Ok && !init_path_list(&points, 314.0, 22.0))
|
||||||
|
status = OutOfMemory;
|
||||||
|
|
||||||
|
if (status == Ok)
|
||||||
|
{
|
||||||
|
last_point = points;
|
||||||
|
|
||||||
|
if (pen->endcap != LineCapFlat)
|
||||||
|
FIXME("unimplemented end cap %x\n", pen->endcap);
|
||||||
|
|
||||||
|
if (pen->startcap != LineCapFlat)
|
||||||
|
FIXME("unimplemented start cap %x\n", pen->startcap);
|
||||||
|
|
||||||
|
if (pen->dashcap != DashCapFlat)
|
||||||
|
FIXME("unimplemented dash cap %d\n", pen->dashcap);
|
||||||
|
|
||||||
|
if (pen->join != LineJoinBevel)
|
||||||
|
FIXME("unimplemented line join %d\n", pen->join);
|
||||||
|
|
||||||
|
if (pen->dash != DashStyleSolid)
|
||||||
|
FIXME("unimplemented dash style %d\n", pen->dash);
|
||||||
|
|
||||||
|
if (pen->align != PenAlignmentCenter)
|
||||||
|
FIXME("unimplemented pen alignment %d\n", pen->align);
|
||||||
|
|
||||||
|
for (i=0; i < flat_path->pathdata.Count; i++)
|
||||||
|
{
|
||||||
|
type = flat_path->pathdata.Types[i];
|
||||||
|
|
||||||
|
if ((type&PathPointTypePathTypeMask) == PathPointTypeStart)
|
||||||
|
subpath_start = i;
|
||||||
|
|
||||||
|
if ((type&PathPointTypeCloseSubpath) == PathPointTypeCloseSubpath)
|
||||||
|
{
|
||||||
|
widen_closed_figure(flat_path, pen, subpath_start, i, &last_point);
|
||||||
|
}
|
||||||
|
else if (i == flat_path->pathdata.Count-1 ||
|
||||||
|
(flat_path->pathdata.Types[i+1]&PathPointTypePathTypeMask) == PathPointTypeStart)
|
||||||
|
{
|
||||||
|
widen_open_figure(flat_path, pen, subpath_start, i, &last_point);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
new_length = path_list_count(points)-1;
|
||||||
|
|
||||||
|
if (!lengthen_path(path, new_length))
|
||||||
|
status = OutOfMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status == Ok)
|
||||||
|
{
|
||||||
|
path->pathdata.Count = new_length;
|
||||||
|
|
||||||
|
last_point = points->next;
|
||||||
|
for (i = 0; i < new_length; i++)
|
||||||
|
{
|
||||||
|
path->pathdata.Points[i] = last_point->pt;
|
||||||
|
path->pathdata.Types[i] = last_point->type;
|
||||||
|
last_point = last_point->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
path->fill = FillModeWinding;
|
||||||
|
}
|
||||||
|
|
||||||
|
free_path_list(points);
|
||||||
|
|
||||||
|
GdipDeletePath(flat_path);
|
||||||
|
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
GpStatus WINGDIPAPI GdipAddPathRectangle(GpPath *path, REAL x, REAL y,
|
GpStatus WINGDIPAPI GdipAddPathRectangle(GpPath *path, REAL x, REAL y,
|
||||||
|
|
|
@ -1372,7 +1372,6 @@ GpStatus WINGDIPAPI GdipCreateHBITMAPFromBitmap(GpBitmap* bitmap,
|
||||||
GpStatus stat;
|
GpStatus stat;
|
||||||
HBITMAP result;
|
HBITMAP result;
|
||||||
UINT width, height;
|
UINT width, height;
|
||||||
HDC hdc;
|
|
||||||
BITMAPINFOHEADER bih;
|
BITMAPINFOHEADER bih;
|
||||||
LPBYTE bits;
|
LPBYTE bits;
|
||||||
BitmapData lockeddata;
|
BitmapData lockeddata;
|
||||||
|
@ -1395,11 +1394,7 @@ GpStatus WINGDIPAPI GdipCreateHBITMAPFromBitmap(GpBitmap* bitmap,
|
||||||
bih.biClrUsed = 0;
|
bih.biClrUsed = 0;
|
||||||
bih.biClrImportant = 0;
|
bih.biClrImportant = 0;
|
||||||
|
|
||||||
hdc = CreateCompatibleDC(NULL);
|
result = CreateDIBSection(0, (BITMAPINFO*)&bih, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
|
||||||
if (!hdc) return GenericError;
|
|
||||||
|
|
||||||
result = CreateDIBSection(hdc, (BITMAPINFO*)&bih, DIB_RGB_COLORS, (void**)&bits,
|
|
||||||
NULL, 0);
|
|
||||||
|
|
||||||
if (result)
|
if (result)
|
||||||
{
|
{
|
||||||
|
@ -1415,8 +1410,6 @@ GpStatus WINGDIPAPI GdipCreateHBITMAPFromBitmap(GpBitmap* bitmap,
|
||||||
else
|
else
|
||||||
stat = GenericError;
|
stat = GenericError;
|
||||||
|
|
||||||
DeleteDC(hdc);
|
|
||||||
|
|
||||||
if (stat != Ok && result)
|
if (stat != Ok && result)
|
||||||
{
|
{
|
||||||
DeleteObject(result);
|
DeleteObject(result);
|
||||||
|
@ -1694,7 +1687,6 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromScan0(INT width, INT height, INT stride,
|
||||||
BITMAPINFO* pbmi;
|
BITMAPINFO* pbmi;
|
||||||
HBITMAP hbitmap=NULL;
|
HBITMAP hbitmap=NULL;
|
||||||
INT row_size, dib_stride;
|
INT row_size, dib_stride;
|
||||||
HDC hdc;
|
|
||||||
BYTE *bits=NULL, *own_bits=NULL;
|
BYTE *bits=NULL, *own_bits=NULL;
|
||||||
REAL xres, yres;
|
REAL xres, yres;
|
||||||
GpStatus stat;
|
GpStatus stat;
|
||||||
|
@ -1739,15 +1731,8 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromScan0(INT width, INT height, INT stride,
|
||||||
pbmi->bmiHeader.biClrUsed = 0;
|
pbmi->bmiHeader.biClrUsed = 0;
|
||||||
pbmi->bmiHeader.biClrImportant = 0;
|
pbmi->bmiHeader.biClrImportant = 0;
|
||||||
|
|
||||||
hdc = CreateCompatibleDC(NULL);
|
hbitmap = CreateDIBSection(0, pbmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
|
||||||
if (!hdc) {
|
|
||||||
GdipFree(pbmi);
|
|
||||||
return GenericError;
|
|
||||||
}
|
|
||||||
|
|
||||||
hbitmap = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
|
|
||||||
|
|
||||||
DeleteDC(hdc);
|
|
||||||
GdipFree(pbmi);
|
GdipFree(pbmi);
|
||||||
|
|
||||||
if (!hbitmap) return GenericError;
|
if (!hbitmap) return GenericError;
|
||||||
|
@ -3103,6 +3088,12 @@ static GpStatus encode_image_png(GpImage *image, IStream* stream,
|
||||||
return encode_image_WIC(image, stream, &CLSID_WICPngEncoder, params);
|
return encode_image_WIC(image, stream, &CLSID_WICPngEncoder, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GpStatus encode_image_jpeg(GpImage *image, IStream* stream,
|
||||||
|
GDIPCONST CLSID* clsid, GDIPCONST EncoderParameters* params)
|
||||||
|
{
|
||||||
|
return encode_image_WIC(image, stream, &CLSID_WICJpegEncoder, params);
|
||||||
|
}
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* GdipSaveImageToStream [GDIPLUS.@]
|
* GdipSaveImageToStream [GDIPLUS.@]
|
||||||
*/
|
*/
|
||||||
|
@ -3277,14 +3268,14 @@ static const struct image_codec codecs[NUM_CODECS] = {
|
||||||
/* FormatDescription */ jpeg_format,
|
/* FormatDescription */ jpeg_format,
|
||||||
/* FilenameExtension */ jpeg_extension,
|
/* FilenameExtension */ jpeg_extension,
|
||||||
/* MimeType */ jpeg_mimetype,
|
/* MimeType */ jpeg_mimetype,
|
||||||
/* Flags */ ImageCodecFlagsDecoder | ImageCodecFlagsSupportBitmap | ImageCodecFlagsBuiltin,
|
/* Flags */ ImageCodecFlagsEncoder | ImageCodecFlagsDecoder | ImageCodecFlagsSupportBitmap | ImageCodecFlagsBuiltin,
|
||||||
/* Version */ 1,
|
/* Version */ 1,
|
||||||
/* SigCount */ 1,
|
/* SigCount */ 1,
|
||||||
/* SigSize */ 2,
|
/* SigSize */ 2,
|
||||||
/* SigPattern */ jpeg_sig_pattern,
|
/* SigPattern */ jpeg_sig_pattern,
|
||||||
/* SigMask */ jpeg_sig_mask,
|
/* SigMask */ jpeg_sig_mask,
|
||||||
},
|
},
|
||||||
NULL,
|
encode_image_jpeg,
|
||||||
decode_image_jpeg
|
decode_image_jpeg
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -3520,13 +3511,53 @@ GpStatus WINGDIPAPI GdipGetEncoderParameterListSize(GpImage *image,
|
||||||
return NotImplemented;
|
return NotImplemented;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PixelFormat get_16bpp_format(HBITMAP hbm)
|
||||||
|
{
|
||||||
|
BITMAPV4HEADER bmh;
|
||||||
|
HDC hdc;
|
||||||
|
PixelFormat result;
|
||||||
|
|
||||||
|
hdc = CreateCompatibleDC(NULL);
|
||||||
|
|
||||||
|
memset(&bmh, 0, sizeof(bmh));
|
||||||
|
bmh.bV4Size = sizeof(bmh);
|
||||||
|
bmh.bV4Width = 1;
|
||||||
|
bmh.bV4Height = 1;
|
||||||
|
bmh.bV4V4Compression = BI_BITFIELDS;
|
||||||
|
bmh.bV4BitCount = 16;
|
||||||
|
|
||||||
|
GetDIBits(hdc, hbm, 0, 0, NULL, (BITMAPINFO*)&bmh, DIB_RGB_COLORS);
|
||||||
|
|
||||||
|
if (bmh.bV4RedMask == 0x7c00 &&
|
||||||
|
bmh.bV4GreenMask == 0x3e0 &&
|
||||||
|
bmh.bV4BlueMask == 0x1f)
|
||||||
|
{
|
||||||
|
result = PixelFormat16bppRGB555;
|
||||||
|
}
|
||||||
|
else if (bmh.bV4RedMask == 0xf800 &&
|
||||||
|
bmh.bV4GreenMask == 0x7e0 &&
|
||||||
|
bmh.bV4BlueMask == 0x1f)
|
||||||
|
{
|
||||||
|
result = PixelFormat16bppRGB565;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FIXME("unrecognized bitfields %x,%x,%x\n", bmh.bV4RedMask,
|
||||||
|
bmh.bV4GreenMask, bmh.bV4BlueMask);
|
||||||
|
result = PixelFormatUndefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
DeleteDC(hdc);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* GdipCreateBitmapFromHBITMAP [GDIPLUS.@]
|
* GdipCreateBitmapFromHBITMAP [GDIPLUS.@]
|
||||||
*/
|
*/
|
||||||
GpStatus WINGDIPAPI GdipCreateBitmapFromHBITMAP(HBITMAP hbm, HPALETTE hpal, GpBitmap** bitmap)
|
GpStatus WINGDIPAPI GdipCreateBitmapFromHBITMAP(HBITMAP hbm, HPALETTE hpal, GpBitmap** bitmap)
|
||||||
{
|
{
|
||||||
BITMAP bm;
|
BITMAP bm;
|
||||||
DIBSECTION dib;
|
|
||||||
GpStatus retval;
|
GpStatus retval;
|
||||||
PixelFormat format;
|
PixelFormat format;
|
||||||
BitmapData lockeddata;
|
BitmapData lockeddata;
|
||||||
|
@ -3552,35 +3583,10 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromHBITMAP(HBITMAP hbm, HPALETTE hpal, GpBi
|
||||||
format = PixelFormat8bppIndexed;
|
format = PixelFormat8bppIndexed;
|
||||||
break;
|
break;
|
||||||
case 16:
|
case 16:
|
||||||
{
|
format = get_16bpp_format(hbm);
|
||||||
if (GetObjectA(hbm, sizeof(dib), &dib) == sizeof(dib))
|
if (format == PixelFormatUndefined)
|
||||||
{
|
|
||||||
if (dib.dsBitfields[0] == 0x7c00 &&
|
|
||||||
dib.dsBitfields[1] == 0x3e0 &&
|
|
||||||
dib.dsBitfields[2] == 0x1f)
|
|
||||||
{
|
|
||||||
format = PixelFormat16bppRGB555;
|
|
||||||
}
|
|
||||||
else if (dib.dsBitfields[0] == 0xf800 &&
|
|
||||||
dib.dsBitfields[1] == 0x7e0 &&
|
|
||||||
dib.dsBitfields[2] == 0x1f)
|
|
||||||
{
|
|
||||||
format = PixelFormat16bppRGB565;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FIXME("unrecognized bitfields %x,%x,%x\n", dib.dsBitfields[0],
|
|
||||||
dib.dsBitfields[1], dib.dsBitfields[2]);
|
|
||||||
return InvalidParameter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FIXME("unimplemented for 16-bit ddb\n");
|
|
||||||
return InvalidParameter;
|
return InvalidParameter;
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case 24:
|
case 24:
|
||||||
format = PixelFormat24bppRGB;
|
format = PixelFormat24bppRGB;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -62,11 +62,16 @@ GpStatus WINGDIPAPI GdipCreateImageAttributes(GpImageAttributes **imageattr)
|
||||||
|
|
||||||
GpStatus WINGDIPAPI GdipDisposeImageAttributes(GpImageAttributes *imageattr)
|
GpStatus WINGDIPAPI GdipDisposeImageAttributes(GpImageAttributes *imageattr)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
TRACE("(%p)\n", imageattr);
|
TRACE("(%p)\n", imageattr);
|
||||||
|
|
||||||
if(!imageattr)
|
if(!imageattr)
|
||||||
return InvalidParameter;
|
return InvalidParameter;
|
||||||
|
|
||||||
|
for (i=0; i<ColorAdjustTypeCount; i++)
|
||||||
|
GdipFree(imageattr->colorremaptables[i].colormap);
|
||||||
|
|
||||||
GdipFree(imageattr);
|
GdipFree(imageattr);
|
||||||
|
|
||||||
return Ok;
|
return Ok;
|
||||||
|
@ -205,6 +210,8 @@ GpStatus WINGDIPAPI GdipSetImageAttributesRemapTable(GpImageAttributes *imageAtt
|
||||||
ColorAdjustType type, BOOL enableFlag, UINT mapSize,
|
ColorAdjustType type, BOOL enableFlag, UINT mapSize,
|
||||||
GDIPCONST ColorMap *map)
|
GDIPCONST ColorMap *map)
|
||||||
{
|
{
|
||||||
|
ColorMap *new_map;
|
||||||
|
|
||||||
TRACE("(%p,%u,%i,%u,%p)\n", imageAttr, type, enableFlag, mapSize, map);
|
TRACE("(%p,%u,%i,%u,%p)\n", imageAttr, type, enableFlag, mapSize, map);
|
||||||
|
|
||||||
if(!imageAttr || type >= ColorAdjustTypeCount)
|
if(!imageAttr || type >= ColorAdjustTypeCount)
|
||||||
|
@ -215,8 +222,22 @@ GpStatus WINGDIPAPI GdipSetImageAttributesRemapTable(GpImageAttributes *imageAtt
|
||||||
if(!map || !mapSize)
|
if(!map || !mapSize)
|
||||||
return InvalidParameter;
|
return InvalidParameter;
|
||||||
|
|
||||||
|
new_map = GdipAlloc(sizeof(*map) * mapSize);
|
||||||
|
|
||||||
|
if (!new_map)
|
||||||
|
return OutOfMemory;
|
||||||
|
|
||||||
|
memcpy(new_map, map, sizeof(*map) * mapSize);
|
||||||
|
|
||||||
|
GdipFree(imageAttr->colorremaptables[type].colormap);
|
||||||
|
|
||||||
imageAttr->colorremaptables[type].mapsize = mapSize;
|
imageAttr->colorremaptables[type].mapsize = mapSize;
|
||||||
imageAttr->colorremaptables[type].colormap = map;
|
imageAttr->colorremaptables[type].colormap = new_map;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GdipFree(imageAttr->colorremaptables[type].colormap);
|
||||||
|
imageAttr->colorremaptables[type].colormap = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
imageAttr->colorremaptables[type].enabled = enableFlag;
|
imageAttr->colorremaptables[type].enabled = enableFlag;
|
||||||
|
|
|
@ -554,6 +554,9 @@ GpStatus WINGDIPAPI GdipGetPathGradientCenterPoint(GpPathGradient*,GpPointF*);
|
||||||
GpStatus WINGDIPAPI GdipGetPathGradientCenterPointI(GpPathGradient*,GpPoint*);
|
GpStatus WINGDIPAPI GdipGetPathGradientCenterPointI(GpPathGradient*,GpPoint*);
|
||||||
GpStatus WINGDIPAPI GdipGetPathGradientFocusScales(GpPathGradient*,REAL*,REAL*);
|
GpStatus WINGDIPAPI GdipGetPathGradientFocusScales(GpPathGradient*,REAL*,REAL*);
|
||||||
GpStatus WINGDIPAPI GdipGetPathGradientGammaCorrection(GpPathGradient*,BOOL*);
|
GpStatus WINGDIPAPI GdipGetPathGradientGammaCorrection(GpPathGradient*,BOOL*);
|
||||||
|
GpStatus WINGDIPAPI GdipGetPathGradientPath(GpPathGradient*,GpPath*);
|
||||||
|
GpStatus WINGDIPAPI GdipGetPathGradientPresetBlend(GpPathGradient*,ARGB*,REAL*,INT);
|
||||||
|
GpStatus WINGDIPAPI GdipGetPathGradientPresetBlendCount(GpPathGradient*,INT*);
|
||||||
GpStatus WINGDIPAPI GdipGetPathGradientPointCount(GpPathGradient*,INT*);
|
GpStatus WINGDIPAPI GdipGetPathGradientPointCount(GpPathGradient*,INT*);
|
||||||
GpStatus WINGDIPAPI GdipSetPathGradientPresetBlend(GpPathGradient*,
|
GpStatus WINGDIPAPI GdipSetPathGradientPresetBlend(GpPathGradient*,
|
||||||
GDIPCONST ARGB*,GDIPCONST REAL*,INT);
|
GDIPCONST ARGB*,GDIPCONST REAL*,INT);
|
||||||
|
|
|
@ -61,7 +61,7 @@ reactos/dll/win32/dbghelp # Synced to Wine-1.3.37
|
||||||
reactos/dll/win32/dciman32 # Synced to Wine-1.3.37
|
reactos/dll/win32/dciman32 # Synced to Wine-1.3.37
|
||||||
reactos/dll/win32/dwmapi # Synced to Wine-1.3.37
|
reactos/dll/win32/dwmapi # Synced to Wine-1.3.37
|
||||||
reactos/dll/win32/fusion # Synced to Wine-1.5.4
|
reactos/dll/win32/fusion # Synced to Wine-1.5.4
|
||||||
reactos/dll/win32/gdiplus # Synced to Wine-1.3.37
|
reactos/dll/win32/gdiplus # Synced to Wine-1.5.4
|
||||||
reactos/dll/win32/hhctrl.ocx # Autosync
|
reactos/dll/win32/hhctrl.ocx # Autosync
|
||||||
reactos/dll/win32/hlink # Synced to Wine-1.3.37
|
reactos/dll/win32/hlink # Synced to Wine-1.3.37
|
||||||
reactos/dll/win32/hnetcfg # Synced to Wine-1.3.37
|
reactos/dll/win32/hnetcfg # Synced to Wine-1.3.37
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue