Skip to content
Snippets Groups Projects

gdiplus: Implement path to region conversion without gdi32.

Merged Esme Povirk requested to merge madewokherd/wine:pathrgn into master
11 unresolved threads

This will later allow for optimization by limiting the area we consider to the region's bounding rectangle.

Merge request reports

Checking pipeline status.

Approved by

Merged by Alexandre JulliardAlexandre Julliard 4 days ago (Apr 8, 2025 9:39pm UTC)

Merge details

  • Changes merged into master with a41aa872.
  • Deleted the source branch.

Activity

Filter activity
  • Approvals
  • Assignees & reviewers
  • Comments (from bots)
  • Comments (from users)
  • Commits & branches
  • Edits
  • Labels
  • Lock status
  • Mentions
  • Merge request status
  • Tracking
1132
1133 scans = (RECT*)&(*rgndata)->Buffer;
1134
1135 /* translate edges into scans based on winding mode */
1136 for (i=0; i < edges->length; i++)
1025 1137 {
1026 graphics->hdc = hdc = new_hdc = CreateCompatibleDC(0);
1027 if (!new_hdc)
1028 return OutOfMemory;
1138 BOOL new_in_shape;
1139
1140 winding_count += edges->edges[i].rising ? 1 : -1;
1141
1142 /* check all edges at this point before starting/ending a scan */
1143 if (i + 1 < edges->length &&
1144 edges->edges[i+1].x == edges->edges[i].x && edges->edges[i+1].y == edges->edges[i].y)
  • It would be great to use the same formatting in whole PR

    Suggested change
    1144 edges->edges[i+1].x == edges->edges[i].x && edges->edges[i+1].y == edges->edges[i].y)
    1144 edges->edges[i + 1].x == edges->edges[i].x && edges->edges[i + 1].y == edges->edges[i].y)

    There are more places with inconsistent formatting.

  • Please register or sign in to reply
  • 104 104 short Y;
    105 105 } packed_point;
    106 106
    107 struct edge
    108 {
    109 /* Represents an intersection of a path segment with a scanline */
    110 int x;
    111 int y;
  • 1070 int rounded_x = rgn_round(x);
    1071
    1072 edges->edges[edges->length].x = rounded_x;
    1073 edges->edges[edges->length].y = y;
    1074 edges->edges[edges->length].rising = rising;
    1075 edges->length++;
    1002 1076 }
    1003 1077
    1004 if (!graphics)
    1078 return stat;
    1079 }
    1080
    1081 static GpStatus flat_path_to_edge_list(GpPath *path, struct edge_list *edges)
    1082 {
    1083 GpStatus stat=Ok;
    1084 int i, subpath_start=0;
  • 1084 int i, subpath_start=0;
    1085
    1086 for (i=1; i < path->pathdata.Count && stat == Ok; i++)
    1005 1087 {
    1006 hdc = new_hdc = CreateCompatibleDC(0);
    1007 if (!new_hdc)
    1008 return OutOfMemory;
    1088 BYTE type = path->pathdata.Types[i];
    1089
    1090 if ((type&PathPointTypePathTypeMask) == PathPointTypeStart)
    1091 subpath_start = i;
    1009 1092
    1010 stat = GdipCreateFromHDC(new_hdc, &new_graphics);
    1011 graphics = new_graphics;
    1012 if (stat != Ok)
    1093 if ((type&PathPointTypePathTypeMask) == PathPointTypeLine)
    • Suggested change
      1093 if ((type&PathPointTypePathTypeMask) == PathPointTypeLine)
      1093 if ((type & PathPointTypePathTypeMask) == PathPointTypeLine)

      as it is in line: 1097

    • Please register or sign in to reply
  • 1109
    1110 if (edge1->y != edge2->y)
    1019 1111 {
    1020 stat = gdi_dc_acquire(graphics, &hdc);
    1021 if (stat != Ok)
    1022 return stat;
    1112 return (edge1->y > edge2->y) - (edge1->y < edge2->y);
    1023 1113 }
    1024 else
    1114
    1115 return (edge1->x > edge2->x) - (edge1->x < edge2->x);
    1116 }
    1117
    1118 static GpStatus edge_list_to_rgndata(struct edge_list *edges, FillMode fill_mode, RGNDATA **rgndata)
    1119 {
    1120 int i, start_x = 0, winding_count = 0;
  • Bartosz Kosiorek
    Bartosz Kosiorek @gang65 started a thread on commit 083d40d9
  • 2570 2570 }
    2571 2571 }
    2572 2572
    2573 static void test_rounding(void)
    2574 {
    2575 GpRegion *region;
    2576 GpMatrix *matrix;
    2577 GpBitmap *bitmap;
    2578 GpGraphics *graphics;
    2579 GpBrush *brush;
    2580 GpStatus status;
    2581 UINT count=80085;
    2582 INT icount;
    2583 GpRectF scans[2];
    2584 HRGN hrgn;
    2585 int i, x, y, min_x, min_y, max_x, max_y;
  • Bartosz Kosiorek
    Bartosz Kosiorek @gang65 started a thread on commit 083d40d9
  • 2664 expect(Ok, status);
    2665
    2666 min_x = min_y = 10;
    2667 max_x = max_y = -1;
    2668
    2669 for (x = 0; x < 10; x++)
    2670 for (y = 0; y < 10; y++)
    2671 {
    2672 status = GdipBitmapGetPixel(bitmap, x, y, &color);
    2673 expect(Ok, status);
    2674
    2675 if (color) {
    2676 min_x = min(min_x, x);
    2677 min_y = min(min_y, y);
    2678 max_x = max(min_x, x);
    2679 max_y = max(min_y, y);
    • Why we are not checking colours? I guess that min_x colour will be 0, and max_x will be 9.

    • Author Developer

      We are checking if color is zero (fully transparent, the value we cleared the image to) or non-zero, to figure out where the shape was drawn. I'm assuming (not checking) that it's a rectangle and the min/max x and y drawn correspond to the corners.

    • Please register or sign in to reply
  • Bartosz Kosiorek
    Bartosz Kosiorek @gang65 started a thread on commit 083d40d9
  • 2570 2570 }
    2571 2571 }
    2572 2572
    2573 static void test_rounding(void)
    2574 {
    2575 GpRegion *region;
    2576 GpMatrix *matrix;
    2577 GpBitmap *bitmap;
    2578 GpGraphics *graphics;
    2579 GpBrush *brush;
    2580 GpStatus status;
    2581 UINT count=80085;
  • Bartosz Kosiorek
    Bartosz Kosiorek @gang65 started a thread on commit f6bd1c9a
  • 1113 1280 {
    1114 1281 case CombineModeIntersect:
    1115 1282 return get_region_hrgn(element->elementdata.combine.right, graphics, hrgn);
    1116 1283 case CombineModeXor: case CombineModeExclude:
    • I know that you have not touched this code, but the case formatting is really weird compared to the rest of the code.

      Suggested change
      1283 case CombineModeXor: case CombineModeExclude:
      1283 case CombineModeXor:
      1284 case CombineModeExclude:
    • Please register or sign in to reply
    • Was this taken from win32u mostly? I wouldn't bother with mentioned cosmetic changes, for example I see no reason to prefer INT over int.

    • Author Developer

      It was written mostly from scratch. From what I remember from when the polygon fill code was in gdi32, that version sorts all the line segments by where they intersect the current scanline as it goes. I guess it uses less memory, but I didn't really see the point of that.

    • Author Developer

      That's the reason I want careful review - it's basically a rewrite from scratch of a core part of gdiplus's rendering.

    • Ok, in this case I need to look closely to understand it. Do you think we have sufficient amount of tests for this?

    • Author Developer

      Between the Wine test suite and a manual rendering test program I used (which did identify an issue), yes.

      I guess I should also run the System.Drawing tests with this, though I'm not sure if it has much that'd be applicable.

    • Author Developer

      OK, no new failures in System.Drawing.

    • Please register or sign in to reply
  • Nikolay Sivov approved this merge request

    approved this merge request

  • Nikolay Sivov unapproved this merge request

    unapproved this merge request

  • Esme Povirk added 310 commits

    added 310 commits

    • 083d40d9...856efc7a - 308 commits from branch wine:master
    • 70a06301 - gdiplus: Implement path to region conversion without gdi32.
    • 924e0313 - gdiplus/tests: Test rounding of region rectangles.

    Compare with previous version

  • Nikolay Sivov approved this merge request

    approved this merge request

  • Alexandre Julliard approved this merge request

    approved this merge request

  • Please register or sign in to reply
    Loading