mirror of
https://github.com/reactos/reactos.git
synced 2025-02-20 15:35:04 +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)
|
||||
|
||||
set_rc_compiler()
|
||||
|
||||
spec2def(gdiplus.dll gdiplus.spec ADD_IMPORTLIB)
|
||||
|
||||
list(APPEND SOURCE
|
||||
|
@ -19,12 +17,12 @@ list(APPEND SOURCE
|
|||
image.c
|
||||
imageattributes.c
|
||||
matrix.c
|
||||
metafile.c
|
||||
metafile.c
|
||||
pathiterator.c
|
||||
pen.c
|
||||
region.c
|
||||
stringformat.c
|
||||
gdiplus.rc
|
||||
gdiplus.rc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/gdiplus_stubs.c
|
||||
${CMAKE_CURRENT_BINARY_DIR}/gdiplus.def)
|
||||
|
||||
|
@ -32,15 +30,5 @@ add_library(gdiplus SHARED ${SOURCE})
|
|||
set_module_type(gdiplus win32dll)
|
||||
target_link_libraries(gdiplus uuid wine)
|
||||
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)
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (C) 2007 Google (Evan Stade)
|
||||
* Copyright (C) 2012 Dmitry Timoshkov
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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_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 inch_per_point = 1.0/72.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;
|
||||
GpGraphics *graphics;
|
||||
HDC hdc = GetDC(0);
|
||||
GdipCreateFromHDC (hdc, &graphics);
|
||||
GdipGetDpiX(graphics, &dpi);
|
||||
GdipDeleteGraphics(graphics);
|
||||
ReleaseDC (0, hdc);
|
||||
switch (unit)
|
||||
{
|
||||
default:
|
||||
FIXME("Unhandled unit type: %d\n", unit);
|
||||
return 0;
|
||||
|
||||
return dpi;
|
||||
}
|
||||
|
||||
static inline REAL point_to_pixel (REAL point)
|
||||
{
|
||||
return point * get_dpi() * inch_per_point;
|
||||
}
|
||||
|
||||
static inline REAL inch_to_pixel (REAL inch)
|
||||
{
|
||||
return inch * get_dpi();
|
||||
}
|
||||
|
||||
static inline REAL document_to_pixel (REAL doc)
|
||||
{
|
||||
return doc * (get_dpi() / 300.0); /* Per MSDN */
|
||||
}
|
||||
|
||||
static inline REAL mm_to_pixel (REAL mm)
|
||||
{
|
||||
return mm * (get_dpi() / mm_per_inch);
|
||||
case UnitPixel:
|
||||
case UnitWorld:
|
||||
/* FIXME: Figure out when World != Pixel */
|
||||
return em_size;
|
||||
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 */
|
||||
return 0;
|
||||
case UnitPoint:
|
||||
return em_size * dpi * inch_per_point;
|
||||
case UnitInch:
|
||||
return em_size * dpi;
|
||||
case UnitDocument:
|
||||
return em_size * dpi / 300.0; /* Per MSDN */
|
||||
case UnitMillimeter:
|
||||
return em_size * dpi / mm_per_inch;
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
@ -95,68 +175,53 @@ static inline REAL mm_to_pixel (REAL mm)
|
|||
GpStatus WINGDIPAPI GdipCreateFont(GDIPCONST GpFontFamily *fontFamily,
|
||||
REAL emSize, INT style, Unit unit, GpFont **font)
|
||||
{
|
||||
WCHAR facename[LF_FACESIZE];
|
||||
LOGFONTW* lfw;
|
||||
const NEWTEXTMETRICW* tmw;
|
||||
HFONT hfont;
|
||||
OUTLINETEXTMETRICW otm;
|
||||
LOGFONTW lfw;
|
||||
HDC hdc;
|
||||
GpStatus stat;
|
||||
int ret;
|
||||
|
||||
if (!fontFamily || !font)
|
||||
if (!fontFamily || !font || emSize < 0.0)
|
||||
return InvalidParameter;
|
||||
|
||||
TRACE("%p (%s), %f, %d, %d, %p\n", fontFamily,
|
||||
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;
|
||||
|
||||
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));
|
||||
|
||||
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;
|
||||
if (!*font) return OutOfMemory;
|
||||
|
||||
(*font)->unit = unit;
|
||||
(*font)->emSize = emSize;
|
||||
(*font)->height = tmw->ntmSizeEM;
|
||||
(*font)->line_spacing = tmw->tmAscent + tmw->tmDescent + tmw->tmExternalLeading;
|
||||
(*font)->otm = otm;
|
||||
|
||||
stat = GdipCloneFontFamily((GpFontFamily *)fontFamily, &(*font)->family);
|
||||
if (stat != Ok)
|
||||
{
|
||||
GdipFree(*font);
|
||||
return stat;
|
||||
}
|
||||
|
||||
TRACE("<-- %p\n", *font);
|
||||
|
||||
|
@ -170,43 +235,38 @@ GpStatus WINGDIPAPI GdipCreateFontFromLogfontW(HDC hdc,
|
|||
GDIPCONST LOGFONTW *logfont, GpFont **font)
|
||||
{
|
||||
HFONT hfont, oldfont;
|
||||
TEXTMETRICW textmet;
|
||||
OUTLINETEXTMETRICW otm;
|
||||
GpStatus stat;
|
||||
int ret;
|
||||
|
||||
TRACE("(%p, %p, %p)\n", hdc, logfont, font);
|
||||
|
||||
if(!logfont || !font)
|
||||
if (!hdc || !logfont || !font)
|
||||
return InvalidParameter;
|
||||
|
||||
if (logfont->lfFaceName[0] == 0)
|
||||
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);
|
||||
hfont = CreateFontIndirectW(logfont);
|
||||
oldfont = SelectObject(hdc, hfont);
|
||||
GetTextMetricsW(hdc, &textmet);
|
||||
|
||||
(*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;
|
||||
|
||||
otm.otmSize = sizeof(otm);
|
||||
ret = GetOutlineTextMetricsW(hdc, otm.otmSize, &otm);
|
||||
SelectObject(hdc, oldfont);
|
||||
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);
|
||||
|
||||
return Ok;
|
||||
|
@ -243,6 +303,7 @@ GpStatus WINGDIPAPI GdipDeleteFont(GpFont* font)
|
|||
if(!font)
|
||||
return InvalidParameter;
|
||||
|
||||
GdipDeleteFontFamily(font->family);
|
||||
GdipFree(font);
|
||||
|
||||
return Ok;
|
||||
|
@ -291,7 +352,7 @@ GpStatus WINGDIPAPI GdipGetFamily(GpFont *font, GpFontFamily **family)
|
|||
if (!(font && family))
|
||||
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;
|
||||
|
||||
*size = font->emSize;
|
||||
TRACE("%s,%d => %f\n", debugstr_w(font->family->FamilyName), font->otm.otmTextMetrics.tmHeight, *size);
|
||||
|
||||
return Ok;
|
||||
}
|
||||
|
@ -341,15 +403,15 @@ GpStatus WINGDIPAPI GdipGetFontStyle(GpFont *font, INT *style)
|
|||
if (!(font && style))
|
||||
return InvalidParameter;
|
||||
|
||||
if (font->lfw.lfWeight > 400)
|
||||
if (font->otm.otmTextMetrics.tmWeight > FW_REGULAR)
|
||||
*style = FontStyleBold;
|
||||
else
|
||||
*style = 0;
|
||||
if (font->lfw.lfItalic)
|
||||
*style = FontStyleRegular;
|
||||
if (font->otm.otmTextMetrics.tmItalic)
|
||||
*style |= FontStyleItalic;
|
||||
if (font->lfw.lfUnderline)
|
||||
if (font->otm.otmTextMetrics.tmUnderlined)
|
||||
*style |= FontStyleUnderline;
|
||||
if (font->lfw.lfStrikeOut)
|
||||
if (font->otm.otmTextMetrics.tmStruckOut)
|
||||
*style |= FontStyleStrikeout;
|
||||
|
||||
return Ok;
|
||||
|
@ -373,6 +435,7 @@ GpStatus WINGDIPAPI GdipGetFontUnit(GpFont *font, Unit *unit)
|
|||
if (!(font && unit)) return InvalidParameter;
|
||||
|
||||
*unit = font->unit;
|
||||
TRACE("%s,%d => %d\n", debugstr_w(font->family->FamilyName), font->otm.otmTextMetrics.tmHeight, *unit);
|
||||
|
||||
return Ok;
|
||||
}
|
||||
|
@ -412,7 +475,22 @@ GpStatus WINGDIPAPI GdipGetLogFontW(GpFont *font, GpGraphics *graphics,
|
|||
if(!font || !graphics || !lfw)
|
||||
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;
|
||||
}
|
||||
|
@ -422,6 +500,8 @@ GpStatus WINGDIPAPI GdipGetLogFontW(GpFont *font, GpGraphics *graphics,
|
|||
*/
|
||||
GpStatus WINGDIPAPI GdipCloneFont(GpFont *font, GpFont **cloneFont)
|
||||
{
|
||||
GpStatus stat;
|
||||
|
||||
TRACE("(%p, %p)\n", font, cloneFont);
|
||||
|
||||
if(!font || !cloneFont)
|
||||
|
@ -431,8 +511,10 @@ GpStatus WINGDIPAPI GdipCloneFont(GpFont *font, GpFont **cloneFont)
|
|||
if(!*cloneFont) return OutOfMemory;
|
||||
|
||||
**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);
|
||||
|
||||
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)
|
||||
stat = GdipGetFontHeightGivenDPI(font, dpi, height);
|
||||
|
||||
return stat;
|
||||
return GdipGetFontHeightGivenDPI(font, dpi, height);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
@ -481,14 +566,26 @@ GpStatus WINGDIPAPI GdipGetFontHeight(GDIPCONST GpFont *font,
|
|||
*/
|
||||
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,
|
||||
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)
|
||||
{
|
||||
|
@ -513,6 +610,9 @@ GpStatus WINGDIPAPI GdipGetFontHeightGivenDPI(GDIPCONST GpFont *font, REAL dpi,
|
|||
return NotImplemented;
|
||||
}
|
||||
|
||||
TRACE("%s,%d(unit %d) => %f\n",
|
||||
debugstr_w(font->family->FamilyName), font->otm.otmTextMetrics.tmHeight, font->unit, *height);
|
||||
|
||||
return Ok;
|
||||
}
|
||||
|
||||
|
@ -525,25 +625,87 @@ GpStatus WINGDIPAPI GdipGetFontHeightGivenDPI(GDIPCONST GpFont *font, REAL dpi,
|
|||
static INT CALLBACK is_font_installed_proc(const LOGFONTW *elf,
|
||||
const TEXTMETRICW *ntm, DWORD type, LPARAM lParam)
|
||||
{
|
||||
if (!ntm || type == RASTER_FONTTYPE)
|
||||
{
|
||||
if (type != TRUETYPE_FONTTYPE)
|
||||
return 1;
|
||||
}
|
||||
|
||||
*(NEWTEXTMETRICW*)lParam = *(const NEWTEXTMETRICW*)ntm;
|
||||
*(LOGFONTW *)lParam = *elf;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static BOOL find_installed_font(const WCHAR *name, NEWTEXTMETRICW *ntm)
|
||||
struct font_metrics
|
||||
{
|
||||
HDC hdc = GetDC(0);
|
||||
BOOL ret = FALSE;
|
||||
UINT16 em_height, ascent, descent, line_spacing; /* in font units */
|
||||
int dpi;
|
||||
};
|
||||
|
||||
if(!EnumFontFamiliesW(hdc, name, is_font_installed_proc, (LPARAM)ntm))
|
||||
ret = TRUE;
|
||||
static BOOL get_font_metrics(HDC hdc, struct font_metrics *fm)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -571,8 +733,9 @@ GpStatus WINGDIPAPI GdipCreateFontFamilyFromName(GDIPCONST WCHAR *name,
|
|||
GpFontCollection *fontCollection,
|
||||
GpFontFamily **FontFamily)
|
||||
{
|
||||
GpStatus stat;
|
||||
GpFontFamily* ffamily;
|
||||
NEWTEXTMETRICW ntm;
|
||||
struct font_metrics fm;
|
||||
|
||||
TRACE("%s, %p %p\n", debugstr_w(name), fontCollection, FontFamily);
|
||||
|
||||
|
@ -581,14 +744,18 @@ GpStatus WINGDIPAPI GdipCreateFontFamilyFromName(GDIPCONST WCHAR *name,
|
|||
if (fontCollection)
|
||||
FIXME("No support for FontCollections yet!\n");
|
||||
|
||||
if (!find_installed_font(name, &ntm))
|
||||
return FontFamilyNotFound;
|
||||
stat = find_installed_font(name, &fm);
|
||||
if (stat != Ok) return stat;
|
||||
|
||||
ffamily = GdipAlloc(sizeof (GpFontFamily));
|
||||
if (!ffamily) return OutOfMemory;
|
||||
|
||||
ffamily->tmw = ntm;
|
||||
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;
|
||||
|
||||
|
@ -613,13 +780,13 @@ GpStatus WINGDIPAPI GdipCloneFontFamily(GpFontFamily* FontFamily, GpFontFamily**
|
|||
{
|
||||
if (!(FontFamily && clonedFontFamily)) return InvalidParameter;
|
||||
|
||||
TRACE("stub: %p (%s), %p\n", FontFamily,
|
||||
TRACE("%p (%s), %p\n", FontFamily,
|
||||
debugstr_w(FontFamily->FamilyName), clonedFontFamily);
|
||||
|
||||
*clonedFontFamily = GdipAlloc(sizeof(GpFontFamily));
|
||||
if (!*clonedFontFamily) return OutOfMemory;
|
||||
|
||||
(*clonedFontFamily)->tmw = FontFamily->tmw;
|
||||
**clonedFontFamily = *FontFamily;
|
||||
lstrcpyW((*clonedFontFamily)->FamilyName, FontFamily->FamilyName);
|
||||
|
||||
TRACE("<-- %p\n", *clonedFontFamily);
|
||||
|
@ -692,7 +859,8 @@ GpStatus WINGDIPAPI GdipGetCellAscent(GDIPCONST GpFontFamily *family,
|
|||
{
|
||||
if (!(family && CellAscent)) return InvalidParameter;
|
||||
|
||||
*CellAscent = family->tmw.tmAscent;
|
||||
*CellAscent = family->ascent;
|
||||
TRACE("%s => %u\n", debugstr_w(family->FamilyName), *CellAscent);
|
||||
|
||||
return Ok;
|
||||
}
|
||||
|
@ -704,7 +872,8 @@ GpStatus WINGDIPAPI GdipGetCellDescent(GDIPCONST GpFontFamily *family,
|
|||
|
||||
if (!(family && CellDescent)) return InvalidParameter;
|
||||
|
||||
*CellDescent = family->tmw.tmDescent;
|
||||
*CellDescent = family->descent;
|
||||
TRACE("%s => %u\n", debugstr_w(family->FamilyName), *CellDescent);
|
||||
|
||||
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);
|
||||
|
||||
*EmHeight = family->tmw.ntmSizeEM;
|
||||
*EmHeight = family->em_height;
|
||||
TRACE("%s => %u\n", debugstr_w(family->FamilyName), *EmHeight);
|
||||
|
||||
return Ok;
|
||||
}
|
||||
|
@ -759,7 +929,8 @@ GpStatus WINGDIPAPI GdipGetLineSpacing(GDIPCONST GpFontFamily *family,
|
|||
|
||||
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;
|
||||
}
|
||||
|
@ -767,7 +938,7 @@ GpStatus WINGDIPAPI GdipGetLineSpacing(GDIPCONST GpFontFamily *family,
|
|||
static INT CALLBACK font_has_style_proc(const LOGFONTW *elf,
|
||||
const TEXTMETRICW *ntm, DWORD type, LPARAM lParam)
|
||||
{
|
||||
INT fontstyle=0;
|
||||
INT fontstyle = FontStyleRegular;
|
||||
|
||||
if (!ntm) return 1;
|
||||
|
||||
|
|
|
@ -265,7 +265,6 @@ COLORREF ARGB2COLORREF(ARGB color)
|
|||
|
||||
HBITMAP ARGB2BMP(ARGB color)
|
||||
{
|
||||
HDC hdc;
|
||||
BITMAPINFO bi;
|
||||
HBITMAP result;
|
||||
RGBQUAD *bits;
|
||||
|
@ -273,8 +272,6 @@ HBITMAP ARGB2BMP(ARGB color)
|
|||
|
||||
if ((color & 0xff000000) == 0xff000000) return 0;
|
||||
|
||||
hdc = CreateCompatibleDC(NULL);
|
||||
|
||||
bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
|
||||
bi.bmiHeader.biWidth = 1;
|
||||
bi.bmiHeader.biHeight = 1;
|
||||
|
@ -287,15 +284,13 @@ HBITMAP ARGB2BMP(ARGB color)
|
|||
bi.bmiHeader.biClrUsed = 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].rgbRed = ((color>>16)&0xff)*alpha/255;
|
||||
bits[0].rgbGreen = ((color>>8)&0xff)*alpha/255;
|
||||
bits[0].rgbBlue = (color&0xff)*alpha/255;
|
||||
|
||||
DeleteDC(hdc);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -316,7 +316,7 @@
|
|||
316 stdcall GdipGetPathGradientCenterPointI(ptr ptr)
|
||||
317 stdcall GdipGetPathGradientFocusScales(ptr ptr ptr)
|
||||
318 stdcall GdipGetPathGradientGammaCorrection(ptr ptr)
|
||||
319 stub GdipGetPathGradientPath
|
||||
319 stdcall GdipGetPathGradientPath(ptr ptr)
|
||||
320 stdcall GdipGetPathGradientPointCount(ptr ptr)
|
||||
321 stdcall GdipGetPathGradientPresetBlend(ptr ptr ptr long)
|
||||
322 stdcall GdipGetPathGradientPresetBlendCount(ptr ptr)
|
||||
|
@ -457,9 +457,9 @@
|
|||
457 stdcall GdipResetClip(ptr)
|
||||
458 stub GdipResetImageAttributes
|
||||
459 stdcall GdipResetLineTransform(ptr)
|
||||
460 stub GdipResetPageTransform
|
||||
460 stdcall GdipResetPageTransform(ptr)
|
||||
461 stdcall GdipResetPath(ptr)
|
||||
462 stub GdipResetPathGradientTransform
|
||||
462 stdcall GdipResetPathGradientTransform(ptr)
|
||||
463 stdcall GdipResetPenTransform(ptr)
|
||||
464 stdcall GdipResetTextureTransform(ptr)
|
||||
465 stdcall GdipResetWorldTransform(ptr)
|
||||
|
|
|
@ -161,6 +161,7 @@ struct GpGraphics{
|
|||
UINT textcontrast; /* not used yet. get/set only */
|
||||
struct list containers;
|
||||
GraphicsContainer contid; /* last-issued container ID */
|
||||
INT origin_x, origin_y;
|
||||
/* For giving the caller an HDC when we technically can't: */
|
||||
HBITMAP temp_hbitmap;
|
||||
int temp_hbitmap_width;
|
||||
|
@ -170,9 +171,7 @@ struct GpGraphics{
|
|||
};
|
||||
|
||||
struct GpBrush{
|
||||
HBRUSH gdibrush;
|
||||
GpBrushType bt;
|
||||
LOGBRUSH lb;
|
||||
};
|
||||
|
||||
struct GpHatch{
|
||||
|
@ -185,12 +184,11 @@ struct GpHatch{
|
|||
struct GpSolidFill{
|
||||
GpBrush brush;
|
||||
ARGB color;
|
||||
HBITMAP bmp;
|
||||
};
|
||||
|
||||
struct GpPathGradient{
|
||||
GpBrush brush;
|
||||
PathData pathdata;
|
||||
GpPath* path;
|
||||
ARGB centercolor;
|
||||
GpWrapMode wrap;
|
||||
BOOL gamma;
|
||||
|
@ -199,6 +197,12 @@ struct GpPathGradient{
|
|||
REAL* blendfac; /* blend factors */
|
||||
REAL* blendpos; /* blend positions */
|
||||
INT blendcount;
|
||||
ARGB *surroundcolors;
|
||||
INT surroundcolorcount;
|
||||
ARGB* pblendcolor; /* preset blend colors */
|
||||
REAL* pblendpos; /* preset blend positions */
|
||||
INT pblendcount;
|
||||
GpMatrix *transform;
|
||||
};
|
||||
|
||||
struct GpLineGradient{
|
||||
|
@ -327,7 +331,7 @@ struct color_matrix{
|
|||
struct color_remap_table{
|
||||
BOOL enabled;
|
||||
INT mapsize;
|
||||
GDIPCONST ColorMap *colormap;
|
||||
ColorMap *colormap;
|
||||
};
|
||||
|
||||
struct GpImageAttributes{
|
||||
|
@ -342,11 +346,9 @@ struct GpImageAttributes{
|
|||
};
|
||||
|
||||
struct GpFont{
|
||||
LOGFONTW lfw;
|
||||
REAL emSize;
|
||||
REAL pixel_size;
|
||||
UINT height;
|
||||
LONG line_spacing;
|
||||
GpFontFamily *family;
|
||||
OUTLINETEXTMETRICW otm;
|
||||
REAL emSize; /* in font units */
|
||||
Unit unit;
|
||||
};
|
||||
|
||||
|
@ -373,8 +375,9 @@ struct GpFontCollection{
|
|||
};
|
||||
|
||||
struct GpFontFamily{
|
||||
NEWTEXTMETRICW tmw;
|
||||
WCHAR FamilyName[LF_FACESIZE];
|
||||
UINT16 em_height, ascent, descent, line_spacing; /* in font units */
|
||||
int dpi;
|
||||
};
|
||||
|
||||
/* internal use */
|
||||
|
@ -425,7 +428,8 @@ struct GpRegion{
|
|||
typedef GpStatus (*gdip_format_string_callback)(HDC hdc,
|
||||
GDIPCONST WCHAR *string, INT index, INT length, GDIPCONST GpFont *font,
|
||||
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,
|
||||
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,
|
||||
GDIPCONST WCHAR *string, INT index, INT length, GDIPCONST GpFont *font,
|
||||
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} };
|
||||
struct format_string_args *args = priv;
|
||||
|
@ -856,6 +857,9 @@ static GpStatus format_string_callback(HDC dc,
|
|||
float y = bounds->Y;
|
||||
int i;
|
||||
|
||||
if (underlined_index_count)
|
||||
FIXME("hotkey underlines not drawn yet\n");
|
||||
|
||||
for (i = index; i < length; ++i)
|
||||
{
|
||||
GLYPHMETRICS gm;
|
||||
|
@ -938,6 +942,7 @@ GpStatus WINGDIPAPI GdipAddPathString(GpPath* path, GDIPCONST WCHAR* string, INT
|
|||
{
|
||||
GpFont *font;
|
||||
GpStatus status;
|
||||
LOGFONTW lfw;
|
||||
HANDLE hfont;
|
||||
HDC dc;
|
||||
GpPath *backup;
|
||||
|
@ -952,7 +957,9 @@ GpStatus WINGDIPAPI GdipAddPathString(GpPath* path, GDIPCONST WCHAR* string, INT
|
|||
if (status != Ok)
|
||||
return status;
|
||||
|
||||
hfont = CreateFontIndirectW(&font->lfw);
|
||||
status = GdipGetLogFontW((GpFont *)font, NULL, &lfw);
|
||||
if (status != Ok) return status;
|
||||
hfont = CreateFontIndirectW(&lfw);
|
||||
if (!hfont)
|
||||
{
|
||||
WARN("Failed to create font\n");
|
||||
|
@ -1207,14 +1214,7 @@ GpStatus WINGDIPAPI GdipFlattenPath(GpPath *path, GpMatrix* matrix, REAL flatnes
|
|||
continue;
|
||||
}
|
||||
|
||||
/* Bezier curve always stored as 4 points */
|
||||
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;
|
||||
}
|
||||
/* Bezier curve */
|
||||
|
||||
/* test for closed figure */
|
||||
if(path->pathdata.Types[i+1] & PathPointTypeCloseSubpath){
|
||||
|
@ -1659,12 +1659,222 @@ GpStatus WINGDIPAPI GdipWarpPath(GpPath *path, GpMatrix* matrix,
|
|||
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,
|
||||
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,
|
||||
|
|
|
@ -1372,7 +1372,6 @@ GpStatus WINGDIPAPI GdipCreateHBITMAPFromBitmap(GpBitmap* bitmap,
|
|||
GpStatus stat;
|
||||
HBITMAP result;
|
||||
UINT width, height;
|
||||
HDC hdc;
|
||||
BITMAPINFOHEADER bih;
|
||||
LPBYTE bits;
|
||||
BitmapData lockeddata;
|
||||
|
@ -1395,11 +1394,7 @@ GpStatus WINGDIPAPI GdipCreateHBITMAPFromBitmap(GpBitmap* bitmap,
|
|||
bih.biClrUsed = 0;
|
||||
bih.biClrImportant = 0;
|
||||
|
||||
hdc = CreateCompatibleDC(NULL);
|
||||
if (!hdc) return GenericError;
|
||||
|
||||
result = CreateDIBSection(hdc, (BITMAPINFO*)&bih, DIB_RGB_COLORS, (void**)&bits,
|
||||
NULL, 0);
|
||||
result = CreateDIBSection(0, (BITMAPINFO*)&bih, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
|
||||
|
||||
if (result)
|
||||
{
|
||||
|
@ -1415,8 +1410,6 @@ GpStatus WINGDIPAPI GdipCreateHBITMAPFromBitmap(GpBitmap* bitmap,
|
|||
else
|
||||
stat = GenericError;
|
||||
|
||||
DeleteDC(hdc);
|
||||
|
||||
if (stat != Ok && result)
|
||||
{
|
||||
DeleteObject(result);
|
||||
|
@ -1694,7 +1687,6 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromScan0(INT width, INT height, INT stride,
|
|||
BITMAPINFO* pbmi;
|
||||
HBITMAP hbitmap=NULL;
|
||||
INT row_size, dib_stride;
|
||||
HDC hdc;
|
||||
BYTE *bits=NULL, *own_bits=NULL;
|
||||
REAL xres, yres;
|
||||
GpStatus stat;
|
||||
|
@ -1739,15 +1731,8 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromScan0(INT width, INT height, INT stride,
|
|||
pbmi->bmiHeader.biClrUsed = 0;
|
||||
pbmi->bmiHeader.biClrImportant = 0;
|
||||
|
||||
hdc = CreateCompatibleDC(NULL);
|
||||
if (!hdc) {
|
||||
GdipFree(pbmi);
|
||||
return GenericError;
|
||||
}
|
||||
hbitmap = CreateDIBSection(0, pbmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
|
||||
|
||||
hbitmap = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
|
||||
|
||||
DeleteDC(hdc);
|
||||
GdipFree(pbmi);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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.@]
|
||||
*/
|
||||
|
@ -3277,14 +3268,14 @@ static const struct image_codec codecs[NUM_CODECS] = {
|
|||
/* FormatDescription */ jpeg_format,
|
||||
/* FilenameExtension */ jpeg_extension,
|
||||
/* MimeType */ jpeg_mimetype,
|
||||
/* Flags */ ImageCodecFlagsDecoder | ImageCodecFlagsSupportBitmap | ImageCodecFlagsBuiltin,
|
||||
/* Flags */ ImageCodecFlagsEncoder | ImageCodecFlagsDecoder | ImageCodecFlagsSupportBitmap | ImageCodecFlagsBuiltin,
|
||||
/* Version */ 1,
|
||||
/* SigCount */ 1,
|
||||
/* SigSize */ 2,
|
||||
/* SigPattern */ jpeg_sig_pattern,
|
||||
/* SigMask */ jpeg_sig_mask,
|
||||
},
|
||||
NULL,
|
||||
encode_image_jpeg,
|
||||
decode_image_jpeg
|
||||
},
|
||||
{
|
||||
|
@ -3520,13 +3511,53 @@ GpStatus WINGDIPAPI GdipGetEncoderParameterListSize(GpImage *image,
|
|||
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.@]
|
||||
*/
|
||||
GpStatus WINGDIPAPI GdipCreateBitmapFromHBITMAP(HBITMAP hbm, HPALETTE hpal, GpBitmap** bitmap)
|
||||
{
|
||||
BITMAP bm;
|
||||
DIBSECTION dib;
|
||||
GpStatus retval;
|
||||
PixelFormat format;
|
||||
BitmapData lockeddata;
|
||||
|
@ -3552,35 +3583,10 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromHBITMAP(HBITMAP hbm, HPALETTE hpal, GpBi
|
|||
format = PixelFormat8bppIndexed;
|
||||
break;
|
||||
case 16:
|
||||
{
|
||||
if (GetObjectA(hbm, sizeof(dib), &dib) == sizeof(dib))
|
||||
{
|
||||
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");
|
||||
format = get_16bpp_format(hbm);
|
||||
if (format == PixelFormatUndefined)
|
||||
return InvalidParameter;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 24:
|
||||
format = PixelFormat24bppRGB;
|
||||
break;
|
||||
|
|
|
@ -62,11 +62,16 @@ GpStatus WINGDIPAPI GdipCreateImageAttributes(GpImageAttributes **imageattr)
|
|||
|
||||
GpStatus WINGDIPAPI GdipDisposeImageAttributes(GpImageAttributes *imageattr)
|
||||
{
|
||||
int i;
|
||||
|
||||
TRACE("(%p)\n", imageattr);
|
||||
|
||||
if(!imageattr)
|
||||
return InvalidParameter;
|
||||
|
||||
for (i=0; i<ColorAdjustTypeCount; i++)
|
||||
GdipFree(imageattr->colorremaptables[i].colormap);
|
||||
|
||||
GdipFree(imageattr);
|
||||
|
||||
return Ok;
|
||||
|
@ -205,6 +210,8 @@ GpStatus WINGDIPAPI GdipSetImageAttributesRemapTable(GpImageAttributes *imageAtt
|
|||
ColorAdjustType type, BOOL enableFlag, UINT mapSize,
|
||||
GDIPCONST ColorMap *map)
|
||||
{
|
||||
ColorMap *new_map;
|
||||
|
||||
TRACE("(%p,%u,%i,%u,%p)\n", imageAttr, type, enableFlag, mapSize, map);
|
||||
|
||||
if(!imageAttr || type >= ColorAdjustTypeCount)
|
||||
|
@ -215,8 +222,22 @@ GpStatus WINGDIPAPI GdipSetImageAttributesRemapTable(GpImageAttributes *imageAtt
|
|||
if(!map || !mapSize)
|
||||
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].colormap = map;
|
||||
imageAttr->colorremaptables[type].colormap = new_map;
|
||||
}
|
||||
else
|
||||
{
|
||||
GdipFree(imageAttr->colorremaptables[type].colormap);
|
||||
imageAttr->colorremaptables[type].colormap = NULL;
|
||||
}
|
||||
|
||||
imageAttr->colorremaptables[type].enabled = enableFlag;
|
||||
|
|
|
@ -554,6 +554,9 @@ GpStatus WINGDIPAPI GdipGetPathGradientCenterPoint(GpPathGradient*,GpPointF*);
|
|||
GpStatus WINGDIPAPI GdipGetPathGradientCenterPointI(GpPathGradient*,GpPoint*);
|
||||
GpStatus WINGDIPAPI GdipGetPathGradientFocusScales(GpPathGradient*,REAL*,REAL*);
|
||||
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 GdipSetPathGradientPresetBlend(GpPathGradient*,
|
||||
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/dwmapi # Synced to Wine-1.3.37
|
||||
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/hlink # Synced to Wine-1.3.37
|
||||
reactos/dll/win32/hnetcfg # Synced to Wine-1.3.37
|
||||
|
|
Loading…
Reference in a new issue