Skip to content

Commit a6433a2

Browse files
committed
[GDI32] Fix pptviewer '97 and calls to PolylineTo and PolyBezierTo
CORE-20553
1 parent 7174935 commit a6433a2

3 files changed

Lines changed: 108 additions & 16 deletions

File tree

win32ss/gdi/gdi32/objects/painting.c

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -283,11 +283,53 @@ PolyBezierTo(
283283
_In_reads_(cpt) const POINT *apt,
284284
_In_ DWORD cpt)
285285
{
286+
POINT pt1 = { 0, 0 };
287+
BOOL ret = FALSE;
288+
286289
HANDLE_EMETAFDC(BOOL, PolyBezierTo, FALSE, hdc, apt, cpt);
287290

288291
if ( GdiConvertAndCheckDC(hdc) == NULL ) return FALSE;
289292

290-
return NtGdiPolyPolyDraw(hdc , (PPOINT)apt, &cpt, 1, GdiPolyBezierTo);
293+
if (cpt == 3)
294+
{
295+
/* If there are exactly 3 points, see if all three points of
296+
* the PolyBezierTo are equal. */
297+
if (apt[0].x == apt[1].x && apt[1].x == apt[2].x &&
298+
apt[0].y == apt[1].y && apt[1].y == apt[2].y)
299+
{
300+
POINT pt1 = { 0, 0 }; // Current Position
301+
/* If all points are equal and they equal the start point,
302+
* then we can just return TRUE as an optimization. */
303+
if (GetCurrentPositionEx(hdc, &pt1) &&
304+
pt1.x == apt[0].x && pt1.y == apt[0].y)
305+
return TRUE;
306+
/* If they are all equal, but not equal to the start point,
307+
* then we can just do a LineTo and return as an optimization. */
308+
else
309+
return LineTo(hdc, apt[0].x, apt[0].y);
310+
}
311+
}
312+
313+
/* Following based on Wine 10.0 nulldrv_PolyBezierTo function */
314+
POINT *pts = HeapAlloc(GetProcessHeap(), 0, (cpt + 1) * sizeof(*apt));
315+
316+
if (pts)
317+
{
318+
if (GetCurrentPositionEx(hdc, &pt1))
319+
{
320+
pts[0] = pt1;
321+
memcpy(&pts[1], apt, sizeof(*apt) * cpt);
322+
cpt++;
323+
ret = NtGdiPolyPolyDraw(hdc , (PPOINT)pts, &cpt, 1, GdiPolyBezierTo);
324+
}
325+
else
326+
ret = FALSE;
327+
HeapFree(GetProcessHeap(), 0, pts);
328+
}
329+
else
330+
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
331+
332+
return ret;
291333
}
292334

293335

@@ -356,11 +398,33 @@ PolylineTo(
356398
_In_reads_(cpt) const POINT *apt,
357399
_In_ DWORD cpt)
358400
{
401+
POINT pt1 = { 0, 0 };
402+
BOOL ret = FALSE;
403+
359404
HANDLE_EMETAFDC(BOOL, PolylineTo, FALSE, hdc, apt, cpt);
360405

361406
if ( GdiConvertAndCheckDC(hdc) == NULL ) return FALSE;
362407

363-
return NtGdiPolyPolyDraw(hdc , (PPOINT)apt, &cpt, 1, GdiPolyLineTo);
408+
/* Following based on Wine 10.0 nulldrv_PolylineTo function */
409+
POINT *pts = HeapAlloc(GetProcessHeap(), 0, (cpt + 1) * sizeof(*apt));
410+
411+
if (pts)
412+
{
413+
if (GetCurrentPositionEx(hdc, &pt1))
414+
{
415+
pts[0] = pt1;
416+
memcpy(&pts[1], apt, sizeof(*apt) * cpt);
417+
cpt++;
418+
ret = NtGdiPolyPolyDraw(hdc , (PPOINT)pts, &cpt, 1, GdiPolyLineTo);
419+
}
420+
else
421+
ret = FALSE;
422+
HeapFree(GetProcessHeap(), 0, pts);
423+
}
424+
else
425+
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
426+
427+
return ret;
364428
}
365429

366430

win32ss/gdi/ntgdi/fillshap.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,7 @@ NtGdiPolyPolyDraw( IN HDC hDC,
432432
ProbeForRead(UnsafePoints, Count * sizeof(POINT), 1);
433433
ProbeForRead(UnsafeCounts, Count * sizeof(ULONG), 1);
434434

435-
/* Count points and validate poligons */
435+
/* Count points and validate polygons */
436436
for (i = 0; i < Count; i++)
437437
{
438438
if (UnsafeCounts[i] < 2)
@@ -544,7 +544,18 @@ NtGdiPolyPolyDraw( IN HDC hDC,
544544
Ret = IntGdiPolylineTo(dc, SafePoints, *SafeCounts);
545545
break;
546546
case GdiPolyBezierTo:
547-
Ret = IntGdiPolyBezierTo(dc, SafePoints, *SafeCounts);
547+
/* From Wine 10.0 dlls/win32u/painting.c NtGdiPolyPolyDraw
548+
* UnsafeCounts[0] must be 3 * n + 1 (where n >= 1) */
549+
if (Count == 1 && UnsafeCounts[0] != 1 && UnsafeCounts[0] % 3 == 1)
550+
{
551+
SafeCounts[0]--;
552+
Ret = IntGdiPolyBezierTo(dc, SafePoints, *SafeCounts);
553+
}
554+
else
555+
{
556+
EngSetLastError(ERROR_INVALID_PARAMETER);
557+
Ret = FALSE;
558+
}
548559
break;
549560
default:
550561
EngSetLastError(ERROR_INVALID_PARAMETER);

win32ss/gdi/ntgdi/path.c

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -323,13 +323,17 @@ PATH_ReserveEntries(
323323
pPointsNew = (POINT *)ExAllocatePoolWithTag(PagedPool, numEntriesToAllocate * sizeof(POINT), TAG_PATH);
324324
if (!pPointsNew)
325325
return FALSE;
326+
else
327+
memset(pPointsNew, 0, numEntriesToAllocate * sizeof(POINT));
326328

327329
pFlagsNew = (BYTE *)ExAllocatePoolWithTag(PagedPool, numEntriesToAllocate * sizeof(BYTE), TAG_PATH);
328330
if (!pFlagsNew)
329331
{
330332
ExFreePoolWithTag(pPointsNew, TAG_PATH);
331333
return FALSE;
332334
}
335+
else
336+
memset(pFlagsNew, 0, numEntriesToAllocate * sizeof(BYTE));
333337

334338
/* Copy old arrays to new arrays and discard old arrays */
335339
if (pPath->pPoints)
@@ -461,15 +465,25 @@ PATH_CheckRect(
461465
/* add a number of points, converting them to device coords */
462466
/* return a pointer to the first type byte so it can be fixed up if necessary */
463467
static BYTE *add_log_points( DC *dc, PPATH path, const POINT *points,
464-
DWORD count, BYTE type )
468+
DWORD count, BYTE type, BOOL bExtraPt )
465469
{
466470
BYTE *ret;
467471

468472
if (!PATH_ReserveEntries( path, path->numEntriesUsed + count )) return NULL;
469473

470474
ret = &path->pFlags[path->numEntriesUsed];
471-
memcpy( &path->pPoints[path->numEntriesUsed], points, count * sizeof(*points) );
472-
IntLPtoDP( dc, &path->pPoints[path->numEntriesUsed], count );
475+
476+
if (bExtraPt && path->numEntriesUsed == 1)
477+
{
478+
memcpy( &path->pPoints[0], points, (count + 1) * sizeof(*points) );
479+
IntLPtoDP( dc, &path->pPoints[0], count + 1);
480+
}
481+
else
482+
{
483+
memcpy( &path->pPoints[path->numEntriesUsed], points, count * sizeof(*points) );
484+
IntLPtoDP( dc, &path->pPoints[path->numEntriesUsed], count );
485+
}
486+
473487
memset( ret, type, count );
474488
path->numEntriesUsed += count;
475489
return ret;
@@ -531,10 +545,10 @@ static void close_figure( PPATH path )
531545

532546
/* add a number of points, starting a new stroke if necessary */
533547
static BOOL add_log_points_new_stroke( DC *dc, PPATH path, const POINT *points,
534-
DWORD count, BYTE type )
548+
DWORD count, BYTE type, BOOL bExtraPt)
535549
{
536550
if (!start_new_stroke( path )) return FALSE;
537-
if (!add_log_points( dc, path, points, count, type )) return FALSE;
551+
if (!add_log_points( dc, path, points, count, type, bExtraPt )) return FALSE;
538552
update_current_pos( path );
539553

540554
TRACE("ALPNS : Pos X %d Y %d\n",path->pos.x, path->pos.y);
@@ -612,7 +626,7 @@ PATH_LineTo(
612626
}
613627
}
614628
}
615-
Ret = add_log_points_new_stroke( dc, pPath, &point, 1, PT_LINETO );
629+
Ret = add_log_points_new_stroke( dc, pPath, &point, 1, PT_LINETO , FALSE);
616630
PATH_UnlockPath(pPath);
617631
return Ret;
618632
}
@@ -1143,7 +1157,7 @@ PATH_PolyBezierTo(
11431157
pPath = PATH_LockPath(dc->dclevel.hPath);
11441158
if (!pPath) return FALSE;
11451159

1146-
ret = add_log_points_new_stroke( dc, pPath, pts, cbPoints, PT_BEZIERTO );
1160+
ret = add_log_points_new_stroke( dc, pPath, pts, cbPoints, PT_BEZIERTO , TRUE);
11471161

11481162
PATH_UnlockPath(pPath);
11491163
return ret;
@@ -1166,7 +1180,7 @@ PATH_PolyBezier(
11661180
pPath = PATH_LockPath(dc->dclevel.hPath);
11671181
if (!pPath) return FALSE;
11681182

1169-
type = add_log_points( dc, pPath, pts, cbPoints, PT_BEZIERTO );
1183+
type = add_log_points( dc, pPath, pts, cbPoints, PT_BEZIERTO, FALSE );
11701184
if (!type) return FALSE;
11711185

11721186
type[0] = PT_MOVETO;
@@ -1217,7 +1231,7 @@ PATH_PolyDraw(
12171231
break;
12181232
case PT_LINETO:
12191233
case PT_LINETO | PT_CLOSEFIGURE:
1220-
if (!add_log_points_new_stroke( dc, pPath, &pts[i], 1, PT_LINETO ))
1234+
if (!add_log_points_new_stroke( dc, pPath, &pts[i], 1, PT_LINETO , FALSE))
12211235
{
12221236
PATH_UnlockPath(pPath);
12231237
return FALSE;
@@ -1227,7 +1241,7 @@ PATH_PolyDraw(
12271241
if ((i + 2 < cbPoints) && (types[i + 1] == PT_BEZIERTO) &&
12281242
(types[i + 2] & ~PT_CLOSEFIGURE) == PT_BEZIERTO)
12291243
{
1230-
if (!add_log_points_new_stroke( dc, pPath, &pts[i], 3, PT_BEZIERTO ))
1244+
if (!add_log_points_new_stroke( dc, pPath, &pts[i], 3, PT_BEZIERTO , FALSE))
12311245
{
12321246
PATH_UnlockPath(pPath);
12331247
return FALSE;
@@ -1278,7 +1292,10 @@ PATH_PolylineTo(
12781292
pPath = PATH_LockPath(dc->dclevel.hPath);
12791293
if (!pPath) return FALSE;
12801294

1281-
ret = add_log_points_new_stroke( dc, pPath, pts, cbPoints, PT_LINETO );
1295+
if (pPath->newStroke)
1296+
cbPoints--;
1297+
1298+
ret = add_log_points_new_stroke( dc, pPath, pts, cbPoints, PT_LINETO , TRUE);
12821299
PATH_UnlockPath(pPath);
12831300
return ret;
12841301
}
@@ -1316,7 +1333,7 @@ PATH_PolyPolygon(
13161333
count += counts[poly];
13171334
}
13181335

1319-
type = add_log_points( dc, pPath, pts, count, PT_LINETO );
1336+
type = add_log_points( dc, pPath, pts, count, PT_LINETO, FALSE );
13201337
if (!type)
13211338
{
13221339
PATH_UnlockPath(pPath);

0 commit comments

Comments
 (0)