[GDIPLUS]

* Sync to Wine 1.5.4.

svn path=/trunk/; revision=56613
This commit is contained in:
Amine Khaldi 2012-05-19 10:03:40 +00:00
parent aca91a4b14
commit a87a379620
12 changed files with 1745 additions and 797 deletions

View file

@ -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

View file

@ -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;

View file

@ -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;
} }

View file

@ -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)

View file

@ -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

View file

@ -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,

View file

@ -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;

View file

@ -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;

View file

@ -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);

View file

@ -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