ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

fillshap.c
Go to the documentation of this file.
00001 /*
00002  * PROJECT:         ReactOS win32 kernel mode subsystem
00003  * LICENSE:         GPL - See COPYING in the top level directory
00004  * FILE:            subsystems/win32/win32k/objects/fillshap.c
00005  * PURPOSE:         fillshap
00006  * PROGRAMMER:
00007  */
00008 
00009 #include <win32k.h>
00010 
00011 #define NDEBUG
00012 #include <debug.h>
00013 
00014 #define Rsin(d) ((d) == 0.0 ? 0.0 : ((d) == 90.0 ? 1.0 : sin(d*M_PI/180.0)))
00015 #define Rcos(d) ((d) == 0.0 ? 1.0 : ((d) == 90.0 ? 0.0 : cos(d*M_PI/180.0)))
00016 
00017 BOOL FASTCALL
00018 IntGdiPolygon(PDC    dc,
00019               PPOINT Points,
00020               int    Count)
00021 {
00022     SURFACE *psurf;
00023     PBRUSH pbrLine, pbrFill;
00024     BOOL ret = FALSE; // Default to failure
00025     RECTL DestRect;
00026     int CurrentPoint;
00027     PDC_ATTR pdcattr;
00028     POINTL BrushOrigin;
00029 //    int Left;
00030 //    int Top;
00031 
00032     ASSERT(dc); // Caller's responsibility to pass a valid dc
00033 
00034     if (!Points || Count < 2 )
00035     {
00036         EngSetLastError(ERROR_INVALID_PARAMETER);
00037         return FALSE;
00038     }
00039 
00040 /*
00041     // Find start x, y
00042     Left = Points[0].x;
00043     Top  = Points[0].y;
00044     for (CurrentPoint = 1; CurrentPoint < Count; ++CurrentPoint) {
00045       Left = min(Left, Points[CurrentPoint].x);
00046       Top  = min(Top, Points[CurrentPoint].y);
00047     }
00048 */
00049 
00050     pdcattr = dc->pdcattr;
00051 
00052     /* Convert to screen coordinates */
00053     IntLPtoDP(dc, Points, Count);
00054     for (CurrentPoint = 0; CurrentPoint < Count; CurrentPoint++)
00055     {
00056         Points[CurrentPoint].x += dc->ptlDCOrig.x;
00057         Points[CurrentPoint].y += dc->ptlDCOrig.y;
00058     }
00059     // No need to have path here.
00060     {
00061         DestRect.left   = Points[0].x;
00062         DestRect.right  = Points[0].x;
00063         DestRect.top    = Points[0].y;
00064         DestRect.bottom = Points[0].y;
00065 
00066         for (CurrentPoint = 1; CurrentPoint < Count; ++CurrentPoint)
00067         {
00068             DestRect.left     = min(DestRect.left, Points[CurrentPoint].x);
00069             DestRect.right    = max(DestRect.right, Points[CurrentPoint].x);
00070             DestRect.top      = min(DestRect.top, Points[CurrentPoint].y);
00071             DestRect.bottom   = max(DestRect.bottom, Points[CurrentPoint].y);
00072         }
00073 
00074         if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
00075             DC_vUpdateFillBrush(dc);
00076 
00077         if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
00078             DC_vUpdateLineBrush(dc);
00079 
00080         /* Special locking order to avoid lock-ups */
00081         pbrFill = dc->dclevel.pbrFill;
00082         pbrLine = dc->dclevel.pbrLine;
00083         psurf = dc->dclevel.pSurface;
00084         /* FIXME: psurf can be NULL!!!! don't assert but handle this case gracefully! */
00085         ASSERT(psurf);
00086 
00087         /* Now fill the polygon with the current fill brush. */
00088         if (!(pbrFill->flAttrs & BR_IS_NULL))
00089         {
00090             BrushOrigin = *((PPOINTL)&pbrFill->ptOrigin);
00091             BrushOrigin.x += dc->ptlDCOrig.x;
00092             BrushOrigin.y += dc->ptlDCOrig.y;
00093             ret = IntFillPolygon (dc,
00094                                   psurf,
00095                                   &dc->eboFill.BrushObject,
00096                                   Points,
00097                                   Count,
00098                                   DestRect,
00099                                   &BrushOrigin);
00100         }
00101 
00102         // Draw the Polygon Edges with the current pen ( if not a NULL pen )
00103         if (!(pbrLine->flAttrs & BR_IS_NULL))
00104         {
00105             int i;
00106 
00107             for (i = 0; i < Count-1; i++)
00108             {
00109 
00110 // DPRINT1("Polygon Making line from (%d,%d) to (%d,%d)\n",
00111 //                                 Points[0].x, Points[0].y,
00112 //                                 Points[1].x, Points[1].y );
00113 
00114                 ret = IntEngLineTo(&psurf->SurfObj,
00115                                    dc->rosdc.CombinedClip,
00116                                    &dc->eboLine.BrushObject,
00117                                    Points[i].x,          /* From */
00118                                    Points[i].y,
00119                                    Points[i+1].x,        /* To */
00120                                    Points[i+1].y,
00121                                    &DestRect,
00122                                    ROP2_TO_MIX(pdcattr->jROP2)); /* MIX */
00123                 if (!ret) break;
00124             }
00125             /* Close the polygon */
00126             if (ret)
00127             {
00128                 ret = IntEngLineTo(&psurf->SurfObj,
00129                                    dc->rosdc.CombinedClip,
00130                                    &dc->eboLine.BrushObject,
00131                                    Points[Count-1].x, /* From */
00132                                    Points[Count-1].y,
00133                                    Points[0].x,       /* To */
00134                                    Points[0].y,
00135                                    &DestRect,
00136                                    ROP2_TO_MIX(pdcattr->jROP2)); /* MIX */
00137             }
00138         }
00139     }
00140 
00141     return ret;
00142 }
00143 
00144 BOOL FASTCALL
00145 IntGdiPolyPolygon(DC      *dc,
00146                   LPPOINT Points,
00147                   PULONG  PolyCounts,
00148                   int     Count)
00149 {
00150     if (PATH_IsPathOpen(dc->dclevel))
00151         return PATH_PolyPolygon ( dc, Points, (PINT)PolyCounts, Count);
00152 
00153     while (--Count >=0)
00154     {
00155         if (!IntGdiPolygon ( dc, Points, *PolyCounts ))
00156             return FALSE;
00157         Points+=*PolyCounts++;
00158     }
00159     return TRUE;
00160 }
00161 
00162 
00163 
00164 /******************************************************************************/
00165 
00166 /*
00167  * NtGdiEllipse
00168  *
00169  * Author
00170  *    Filip Navara
00171  *
00172  * Remarks
00173  *    This function uses optimized Bresenham's ellipse algorithm. It draws
00174  *    four lines of the ellipse in one pass.
00175  *
00176  */
00177 
00178 BOOL APIENTRY
00179 NtGdiEllipse(
00180     HDC hDC,
00181     int Left,
00182     int Top,
00183     int Right,
00184     int Bottom)
00185 {
00186     PDC dc;
00187     PDC_ATTR pdcattr;
00188     RECTL RectBounds;
00189     PBRUSH pbrush;
00190     BOOL ret = TRUE;
00191     LONG PenWidth, PenOrigWidth;
00192     LONG RadiusX, RadiusY, CenterX, CenterY;
00193     PBRUSH pFillBrushObj;
00194     BRUSH tmpFillBrushObj;
00195 
00196     if ((Left == Right) || (Top == Bottom)) return TRUE;
00197 
00198     dc = DC_LockDc(hDC);
00199     if (dc == NULL)
00200     {
00201        EngSetLastError(ERROR_INVALID_HANDLE);
00202        return FALSE;
00203     }
00204     if (dc->dctype == DC_TYPE_INFO)
00205     {
00206        DC_UnlockDc(dc);
00207        /* Yes, Windows really returns TRUE in this case */
00208        return TRUE;
00209     }
00210 
00211     if (PATH_IsPathOpen(dc->dclevel))
00212     {
00213         ret = PATH_Ellipse(dc, Left, Top, Right, Bottom);
00214         DC_UnlockDc(dc);
00215         return ret;
00216     }
00217 
00218     if (Right < Left)
00219     {
00220        INT tmp = Right; Right = Left; Left = tmp;
00221     }
00222     if (Bottom < Top)
00223     {
00224        INT tmp = Bottom; Bottom = Top; Top = tmp;
00225     }
00226 
00227     pdcattr = dc->pdcattr;
00228 
00229     if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
00230         DC_vUpdateFillBrush(dc);
00231 
00232     if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
00233         DC_vUpdateLineBrush(dc);
00234 
00235     pbrush = PEN_ShareLockPen(pdcattr->hpen);
00236     if (!pbrush)
00237     {
00238         DPRINT1("Ellipse Fail 1\n");
00239         DC_UnlockDc(dc);
00240         EngSetLastError(ERROR_INTERNAL_ERROR);
00241         return FALSE;
00242     }
00243 
00244     PenOrigWidth = PenWidth = pbrush->ptPenWidth.x;
00245     if (pbrush->ulPenStyle == PS_NULL) PenWidth = 0;
00246 
00247     if (pbrush->ulPenStyle == PS_INSIDEFRAME)
00248     {
00249        if (2*PenWidth > (Right - Left)) PenWidth = (Right -Left + 1)/2;
00250        if (2*PenWidth > (Bottom - Top)) PenWidth = (Bottom -Top + 1)/2;
00251        Left   += PenWidth / 2;
00252        Right  -= (PenWidth - 1) / 2;
00253        Top    += PenWidth / 2;
00254        Bottom -= (PenWidth - 1) / 2;
00255     }
00256 
00257     if (!PenWidth) PenWidth = 1;
00258     pbrush->ptPenWidth.x = PenWidth;
00259 
00260     RectBounds.left   = Left;
00261     RectBounds.right  = Right;
00262     RectBounds.top    = Top;
00263     RectBounds.bottom = Bottom;
00264 
00265     IntLPtoDP(dc, (LPPOINT)&RectBounds, 2);
00266 
00267     RectBounds.left += dc->ptlDCOrig.x;
00268     RectBounds.right += dc->ptlDCOrig.x;
00269     RectBounds.top += dc->ptlDCOrig.y;
00270     RectBounds.bottom += dc->ptlDCOrig.y;
00271 
00272     // Setup for dynamic width and height.
00273     RadiusX = max((RectBounds.right - RectBounds.left) / 2, 2); // Needs room
00274     RadiusY = max((RectBounds.bottom - RectBounds.top) / 2, 2);
00275     CenterX = (RectBounds.right + RectBounds.left) / 2;
00276     CenterY = (RectBounds.bottom + RectBounds.top) / 2;
00277 
00278     DPRINT("Ellipse 1: Left: %d, Top: %d, Right: %d, Bottom: %d\n",
00279                RectBounds.left,RectBounds.top,RectBounds.right,RectBounds.bottom);
00280 
00281     DPRINT("Ellipse 2: XLeft: %d, YLeft: %d, Width: %d, Height: %d\n",
00282                CenterX - RadiusX, CenterY + RadiusY, RadiusX*2, RadiusY*2);
00283 
00284     pFillBrushObj = BRUSH_ShareLockBrush(pdcattr->hbrush);
00285     if (NULL == pFillBrushObj)
00286     {
00287         DPRINT1("FillEllipse Fail\n");
00288         EngSetLastError(ERROR_INTERNAL_ERROR);
00289         ret = FALSE;
00290     }
00291     else
00292     {
00293         RtlCopyMemory(&tmpFillBrushObj, pFillBrushObj, sizeof(tmpFillBrushObj));
00294         //tmpFillBrushObj.ptOrigin.x += RectBounds.left - Left;
00295         //tmpFillBrushObj.ptOrigin.y += RectBounds.top - Top;
00296         tmpFillBrushObj.ptOrigin.x += dc->ptlDCOrig.x;
00297         tmpFillBrushObj.ptOrigin.y += dc->ptlDCOrig.y;
00298         ret = IntFillEllipse( dc,
00299                               CenterX - RadiusX,
00300                               CenterY - RadiusY,
00301                               RadiusX*2, // Width
00302                               RadiusY*2, // Height
00303                               &tmpFillBrushObj);
00304         BRUSH_ShareUnlockBrush(pFillBrushObj);
00305     }
00306 
00307     if (ret)
00308        ret = IntDrawEllipse( dc,
00309                              CenterX - RadiusX,
00310                              CenterY - RadiusY,
00311                              RadiusX*2, // Width
00312                              RadiusY*2, // Height
00313                              pbrush);
00314 
00315     pbrush->ptPenWidth.x = PenOrigWidth;
00316     PEN_ShareUnlockPen(pbrush);
00317     DC_UnlockDc(dc);
00318     DPRINT("Ellipse Exit.\n");
00319     return ret;
00320 }
00321 
00322 #if 0
00323 
00324 // When the fill mode is ALTERNATE, GDI fills the area between odd-numbered and
00325 // even-numbered polygon sides on each scan line. That is, GDI fills the area between the
00326 // first and second side, between the third and fourth side, and so on.
00327 
00328 // WINDING Selects winding mode (fills any region with a nonzero winding value).
00329 // When the fill mode is WINDING, GDI fills any region that has a nonzero winding value.
00330 // This value is defined as the number of times a pen used to draw the polygon would go around the region.
00331 // The direction of each edge of the polygon is important.
00332 
00333 extern BOOL FillPolygon(PDC dc,
00334                             SURFOBJ *SurfObj,
00335                             PBRUSHOBJ BrushObj,
00336                             MIX RopMode,
00337                             CONST PPOINT Points,
00338                             int Count,
00339                             RECTL BoundRect);
00340 
00341 #endif
00342 
00343 
00344 ULONG_PTR
00345 APIENTRY
00346 NtGdiPolyPolyDraw( IN HDC hDC,
00347                    IN PPOINT UnsafePoints,
00348                    IN PULONG UnsafeCounts,
00349                    IN ULONG Count,
00350                    IN INT iFunc )
00351 {
00352     DC *dc;
00353     PVOID pTemp;
00354     LPPOINT SafePoints;
00355     PULONG SafeCounts;
00356     NTSTATUS Status = STATUS_SUCCESS;
00357     BOOL Ret = TRUE;
00358     ULONG nPoints = 0, nMaxPoints = 0, nInvalid = 0, i;
00359 
00360     if (!UnsafePoints || !UnsafeCounts ||
00361         Count == 0 || iFunc == 0 || iFunc > GdiPolyPolyRgn)
00362     {
00363         /* Windows doesn't set last error */
00364         return FALSE;
00365     }
00366 
00367     _SEH2_TRY
00368     {
00369         ProbeForRead(UnsafePoints, Count * sizeof(POINT), 1);
00370         ProbeForRead(UnsafeCounts, Count * sizeof(ULONG), 1);
00371 
00372         /* Count points and validate poligons */
00373         for (i = 0; i < Count; i++)
00374         {
00375             if (UnsafeCounts[i] < 2)
00376             {
00377                 nInvalid++;
00378             }
00379             nPoints += UnsafeCounts[i];
00380             nMaxPoints = max(nMaxPoints, UnsafeCounts[i]);
00381         }
00382     }
00383     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00384     {
00385         Status = _SEH2_GetExceptionCode();
00386     }
00387     _SEH2_END;
00388 
00389     if (!NT_SUCCESS(Status))
00390     {
00391         /* Windows doesn't set last error */
00392         return FALSE;
00393     }
00394 
00395     if (nPoints == 0 || nPoints < nMaxPoints)
00396     {
00397         /* If all polygon counts are zero, or we have overflow,
00398            return without setting a last error code. */
00399         return FALSE;
00400     }
00401 
00402     if (nInvalid != 0)
00403     {
00404         /* If at least one poly count is 0 or 1, fail */
00405         EngSetLastError(ERROR_INVALID_PARAMETER);
00406         return FALSE;
00407     }
00408 
00409     /* Allocate one buffer for both counts and points */
00410     pTemp = ExAllocatePoolWithTag(PagedPool,
00411                                   Count * sizeof(ULONG) + nPoints * sizeof(POINT),
00412                                   TAG_SHAPE);
00413     if (!pTemp)
00414     {
00415         EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
00416         return FALSE;
00417     }
00418 
00419     SafeCounts = pTemp;
00420     SafePoints = (PVOID)(SafeCounts + Count);
00421 
00422     _SEH2_TRY
00423     {
00424         /* Pointers already probed! */
00425         RtlCopyMemory(SafeCounts, UnsafeCounts, Count * sizeof(ULONG));
00426         RtlCopyMemory(SafePoints, UnsafePoints, nPoints * sizeof(POINT));
00427     }
00428     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00429     {
00430         Status = _SEH2_GetExceptionCode();
00431     }
00432     _SEH2_END;
00433 
00434     if (!NT_SUCCESS(Status))
00435     {
00436         ExFreePoolWithTag(pTemp, TAG_SHAPE);
00437         return FALSE;
00438     }
00439 
00440     /* Special handling for GdiPolyPolyRgn */
00441     if (iFunc == GdiPolyPolyRgn)
00442     {
00443         HRGN hRgn;
00444         hRgn = IntCreatePolyPolygonRgn(SafePoints, SafeCounts, Count, (INT_PTR)hDC);
00445         ExFreePoolWithTag(pTemp, TAG_SHAPE);
00446         return (ULONG_PTR)hRgn;
00447     }
00448 
00449     dc = DC_LockDc(hDC);
00450     if (!dc)
00451     {
00452         EngSetLastError(ERROR_INVALID_HANDLE);
00453         ExFreePool(pTemp);
00454         return FALSE;
00455     }
00456 
00457     if (dc->dctype == DC_TYPE_INFO)
00458     {
00459         DC_UnlockDc(dc);
00460         ExFreePool(pTemp);
00461         /* Yes, Windows really returns TRUE in this case */
00462         return TRUE;
00463     }
00464 
00465     DC_vPrepareDCsForBlit(dc, dc->rosdc.CombinedClip->rclBounds,
00466                             NULL, dc->rosdc.CombinedClip->rclBounds);
00467 
00468     if (dc->pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
00469         DC_vUpdateFillBrush(dc);
00470 
00471     if (dc->pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
00472         DC_vUpdateLineBrush(dc);
00473 
00474     /* Perform the actual work */
00475     switch (iFunc)
00476     {
00477         case GdiPolyPolygon:
00478             Ret = IntGdiPolyPolygon(dc, SafePoints, SafeCounts, Count);
00479             break;
00480         case GdiPolyPolyLine:
00481             Ret = IntGdiPolyPolyline(dc, SafePoints, SafeCounts, Count);
00482             break;
00483         case GdiPolyBezier:
00484             Ret = IntGdiPolyBezier(dc, SafePoints, *SafeCounts);
00485             break;
00486         case GdiPolyLineTo:
00487             Ret = IntGdiPolylineTo(dc, SafePoints, *SafeCounts);
00488             break;
00489         case GdiPolyBezierTo:
00490             Ret = IntGdiPolyBezierTo(dc, SafePoints, *SafeCounts);
00491             break;
00492         default:
00493             EngSetLastError(ERROR_INVALID_PARAMETER);
00494             Ret = FALSE;
00495     }
00496 
00497     /* Cleanup and return */
00498     DC_vFinishBlit(dc, NULL);
00499     DC_UnlockDc(dc);
00500     ExFreePool(pTemp);
00501 
00502     return (ULONG_PTR)Ret;
00503 }
00504 
00505 
00506 BOOL
00507 FASTCALL
00508 IntRectangle(PDC dc,
00509              int LeftRect,
00510              int TopRect,
00511              int RightRect,
00512              int BottomRect)
00513 {
00514     SURFACE *psurf = NULL;
00515     PBRUSH pbrLine, pbrFill;
00516     BOOL       ret = FALSE; // Default to failure
00517     RECTL      DestRect;
00518     MIX        Mix;
00519     PDC_ATTR pdcattr;
00520     POINTL BrushOrigin;
00521 
00522     ASSERT ( dc ); // Caller's responsibility to set this up
00523 
00524     pdcattr = dc->pdcattr;
00525 
00526     // Rectangle Path only.
00527     if ( PATH_IsPathOpen(dc->dclevel) )
00528     {
00529         return PATH_Rectangle ( dc, LeftRect, TopRect, RightRect, BottomRect );
00530     }
00531 
00532     /* Make sure rectangle is not inverted */
00533     DestRect.left   = min(LeftRect, RightRect);
00534     DestRect.right  = max(LeftRect, RightRect);
00535     DestRect.top    = min(TopRect,  BottomRect);
00536     DestRect.bottom = max(TopRect,  BottomRect);
00537 
00538     IntLPtoDP(dc, (LPPOINT)&DestRect, 2);
00539 
00540     DestRect.left   += dc->ptlDCOrig.x;
00541     DestRect.right  += dc->ptlDCOrig.x;
00542     DestRect.top    += dc->ptlDCOrig.y;
00543     DestRect.bottom += dc->ptlDCOrig.y;
00544 
00545     /* In GM_COMPATIBLE, don't include bottom and right edges */
00546     if (pdcattr->iGraphicsMode == GM_COMPATIBLE)
00547     {
00548         DestRect.right--;
00549         DestRect.bottom--;
00550     }
00551 
00552     DC_vPrepareDCsForBlit(dc, DestRect, NULL, DestRect);
00553 
00554     if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
00555         DC_vUpdateFillBrush(dc);
00556 
00557     if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
00558         DC_vUpdateLineBrush(dc);
00559 
00560     pbrFill = dc->dclevel.pbrFill;
00561     pbrLine = dc->dclevel.pbrLine;
00562     if (!pbrLine)
00563     {
00564         ret = FALSE;
00565         goto cleanup;
00566     }
00567 
00568     psurf = dc->dclevel.pSurface;
00569     if (!psurf)
00570     {
00571         ret = FALSE;
00572         goto cleanup;
00573     }
00574 
00575     if (pbrFill)
00576     {
00577         if (!(pbrFill->flAttrs & BR_IS_NULL))
00578         {
00579             BrushOrigin = *((PPOINTL)&pbrFill->ptOrigin);
00580             BrushOrigin.x += dc->ptlDCOrig.x;
00581             BrushOrigin.y += dc->ptlDCOrig.y;
00582             ret = IntEngBitBlt(&psurf->SurfObj,
00583                                NULL,
00584                                NULL,
00585                                dc->rosdc.CombinedClip,
00586                                NULL,
00587                                &DestRect,
00588                                NULL,
00589                                NULL,
00590                                &dc->eboFill.BrushObject,
00591                                &BrushOrigin,
00592                                ROP4_FROM_INDEX(R3_OPINDEX_PATCOPY));
00593         }
00594     }
00595 
00596     // Draw the rectangle with the current pen
00597 
00598     ret = TRUE; // Change default to success
00599 
00600     if (!(pbrLine->flAttrs & BR_IS_NULL))
00601     {
00602         Mix = ROP2_TO_MIX(pdcattr->jROP2);
00603         ret = ret && IntEngLineTo(&psurf->SurfObj,
00604                                   dc->rosdc.CombinedClip,
00605                                   &dc->eboLine.BrushObject,
00606                                   DestRect.left, DestRect.top, DestRect.right, DestRect.top,
00607                                   &DestRect, // Bounding rectangle
00608                                   Mix);
00609 
00610         ret = ret && IntEngLineTo(&psurf->SurfObj,
00611                                   dc->rosdc.CombinedClip,
00612                                   &dc->eboLine.BrushObject,
00613                                   DestRect.right, DestRect.top, DestRect.right, DestRect.bottom,
00614                                   &DestRect, // Bounding rectangle
00615                                   Mix);
00616 
00617         ret = ret && IntEngLineTo(&psurf->SurfObj,
00618                                   dc->rosdc.CombinedClip,
00619                                   &dc->eboLine.BrushObject,
00620                                   DestRect.right, DestRect.bottom, DestRect.left, DestRect.bottom,
00621                                   &DestRect, // Bounding rectangle
00622                                   Mix);
00623 
00624         ret = ret && IntEngLineTo(&psurf->SurfObj,
00625                                   dc->rosdc.CombinedClip,
00626                                   &dc->eboLine.BrushObject,
00627                                   DestRect.left, DestRect.bottom, DestRect.left, DestRect.top,
00628                                   &DestRect, // Bounding rectangle
00629                                   Mix);
00630     }
00631 
00632 cleanup:
00633     DC_vFinishBlit(dc, NULL);
00634 
00635     /* Move current position in DC?
00636        MSDN: The current position is neither used nor updated by Rectangle. */
00637 
00638     return ret;
00639 }
00640 
00641 BOOL
00642 APIENTRY
00643 NtGdiRectangle(HDC  hDC,
00644                int  LeftRect,
00645                int  TopRect,
00646                int  RightRect,
00647                int  BottomRect)
00648 {
00649     DC   *dc;
00650     BOOL ret; // Default to failure
00651 
00652     dc = DC_LockDc(hDC);
00653     if (!dc)
00654     {
00655         EngSetLastError(ERROR_INVALID_HANDLE);
00656         return FALSE;
00657     }
00658     if (dc->dctype == DC_TYPE_INFO)
00659     {
00660         DC_UnlockDc(dc);
00661         /* Yes, Windows really returns TRUE in this case */
00662         return TRUE;
00663     }
00664 
00665     /* Do we rotate or shear? */
00666     if (!(dc->dclevel.mxWorldToDevice.flAccel & XFORM_SCALE))
00667     {
00668         POINTL DestCoords[4];
00669         ULONG PolyCounts = 4;
00670 
00671         DestCoords[0].x = DestCoords[3].x = LeftRect;
00672         DestCoords[0].y = DestCoords[1].y = TopRect;
00673         DestCoords[1].x = DestCoords[2].x = RightRect;
00674         DestCoords[2].y = DestCoords[3].y = BottomRect;
00675         // Use IntGdiPolyPolygon so to support PATH.
00676         ret = IntGdiPolyPolygon(dc, DestCoords, &PolyCounts, 1);
00677     }
00678     else
00679     {
00680         ret = IntRectangle(dc, LeftRect, TopRect, RightRect, BottomRect );
00681     }
00682 
00683     DC_UnlockDc(dc);
00684 
00685     return ret;
00686 }
00687 
00688 
00689 BOOL
00690 FASTCALL
00691 IntRoundRect(
00692     PDC  dc,
00693     int  Left,
00694     int  Top,
00695     int  Right,
00696     int  Bottom,
00697     int  xCurveDiameter,
00698     int  yCurveDiameter)
00699 {
00700     PDC_ATTR pdcattr;
00701     PBRUSH   pbrLine, pbrFill;
00702     RECTL RectBounds;
00703     LONG PenWidth, PenOrigWidth;
00704     BOOL ret = TRUE; // Default to success
00705     BRUSH brushTemp;
00706 
00707     ASSERT ( dc ); // Caller's responsibility to set this up
00708 
00709     if ( PATH_IsPathOpen(dc->dclevel) )
00710         return PATH_RoundRect ( dc, Left, Top, Right, Bottom,
00711                                 xCurveDiameter, yCurveDiameter );
00712 
00713     if ((Left == Right) || (Top == Bottom)) return TRUE;
00714 
00715     xCurveDiameter = max(abs( xCurveDiameter ), 1);
00716     yCurveDiameter = max(abs( yCurveDiameter ), 1);
00717 
00718     if (Right < Left)
00719     {
00720        INT tmp = Right; Right = Left; Left = tmp;
00721     }
00722     if (Bottom < Top)
00723     {
00724        INT tmp = Bottom; Bottom = Top; Top = tmp;
00725     }
00726 
00727     pdcattr = dc->pdcattr;
00728 
00729     if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
00730         DC_vUpdateFillBrush(dc);
00731 
00732     if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
00733         DC_vUpdateLineBrush(dc);
00734 
00735     pbrLine = PEN_ShareLockPen(pdcattr->hpen);
00736     if (!pbrLine)
00737     {
00738         /* Nothing to do, as we don't have a bitmap */
00739         EngSetLastError(ERROR_INTERNAL_ERROR);
00740         return FALSE;
00741     }
00742 
00743     PenOrigWidth = PenWidth = pbrLine->ptPenWidth.x;
00744     if (pbrLine->ulPenStyle == PS_NULL) PenWidth = 0;
00745 
00746     if (pbrLine->ulPenStyle == PS_INSIDEFRAME)
00747     {
00748        if (2*PenWidth > (Right - Left)) PenWidth = (Right -Left + 1)/2;
00749        if (2*PenWidth > (Bottom - Top)) PenWidth = (Bottom -Top + 1)/2;
00750        Left   += PenWidth / 2;
00751        Right  -= (PenWidth - 1) / 2;
00752        Top    += PenWidth / 2;
00753        Bottom -= (PenWidth - 1) / 2;
00754     }
00755 
00756     if (!PenWidth) PenWidth = 1;
00757     pbrLine->ptPenWidth.x = PenWidth;
00758 
00759     RectBounds.left = Left;
00760     RectBounds.top = Top;
00761     RectBounds.right = Right;
00762     RectBounds.bottom = Bottom;
00763 
00764     IntLPtoDP(dc, (LPPOINT)&RectBounds, 2);
00765 
00766     RectBounds.left   += dc->ptlDCOrig.x;
00767     RectBounds.top    += dc->ptlDCOrig.y;
00768     RectBounds.right  += dc->ptlDCOrig.x;
00769     RectBounds.bottom += dc->ptlDCOrig.y;
00770 
00771     pbrFill = BRUSH_ShareLockBrush(pdcattr->hbrush);
00772     if (!pbrFill)
00773     {
00774         DPRINT1("FillRound Fail\n");
00775         EngSetLastError(ERROR_INTERNAL_ERROR);
00776         ret = FALSE;
00777     }
00778     else
00779     {
00780         RtlCopyMemory(&brushTemp, pbrFill, sizeof(brushTemp));
00781         brushTemp.ptOrigin.x += RectBounds.left - Left;
00782         brushTemp.ptOrigin.y += RectBounds.top - Top;
00783         ret = IntFillRoundRect( dc,
00784                                 RectBounds.left,
00785                                 RectBounds.top,
00786                                 RectBounds.right,
00787                                 RectBounds.bottom,
00788                                 xCurveDiameter,
00789                                 yCurveDiameter,
00790                                 &brushTemp);
00791         BRUSH_ShareUnlockBrush(pbrFill);
00792     }
00793 
00794     if (ret)
00795        ret = IntDrawRoundRect( dc,
00796                   RectBounds.left,
00797                    RectBounds.top,
00798                  RectBounds.right,
00799                 RectBounds.bottom,
00800                    xCurveDiameter,
00801                    yCurveDiameter,
00802                    pbrLine);
00803 
00804     pbrLine->ptPenWidth.x = PenOrigWidth;
00805     PEN_ShareUnlockPen(pbrLine);
00806     return ret;
00807 }
00808 
00809 BOOL
00810 APIENTRY
00811 NtGdiRoundRect(
00812     HDC  hDC,
00813     int  LeftRect,
00814     int  TopRect,
00815     int  RightRect,
00816     int  BottomRect,
00817     int  Width,
00818     int  Height)
00819 {
00820     DC   *dc = DC_LockDc(hDC);
00821     BOOL  ret = FALSE; /* Default to failure */
00822 
00823     DPRINT("NtGdiRoundRect(0x%x,%i,%i,%i,%i,%i,%i)\n",hDC,LeftRect,TopRect,RightRect,BottomRect,Width,Height);
00824     if ( !dc )
00825     {
00826         DPRINT1("NtGdiRoundRect() - hDC is invalid\n");
00827         EngSetLastError(ERROR_INVALID_HANDLE);
00828     }
00829     else if (dc->dctype == DC_TYPE_INFO)
00830     {
00831         DC_UnlockDc(dc);
00832         /* Yes, Windows really returns TRUE in this case */
00833         ret = TRUE;
00834     }
00835     else
00836     {
00837         ret = IntRoundRect ( dc, LeftRect, TopRect, RightRect, BottomRect, Width, Height );
00838         DC_UnlockDc ( dc );
00839     }
00840 
00841     return ret;
00842 }
00843 
00844 BOOL
00845 NTAPI
00846 GreGradientFill(
00847     HDC hdc,
00848     PTRIVERTEX pVertex,
00849     ULONG nVertex,
00850     PVOID pMesh,
00851     ULONG nMesh,
00852     ULONG ulMode)
00853 {
00854     PDC pdc;
00855     SURFACE *psurf;
00856     EXLATEOBJ exlo;
00857     RECTL rclExtent;
00858     POINTL ptlDitherOrg;
00859     ULONG i;
00860     BOOL bRet;
00861 
00862     /* Check parameters */
00863     if (ulMode & GRADIENT_FILL_TRIANGLE)
00864     {
00865         PGRADIENT_TRIANGLE pTriangle = (PGRADIENT_TRIANGLE)pMesh;
00866 
00867         for (i = 0; i < nMesh; i++, pTriangle++)
00868         {
00869             if (pTriangle->Vertex1 >= nVertex ||
00870                 pTriangle->Vertex2 >= nVertex ||
00871                 pTriangle->Vertex3 >= nVertex)
00872             {
00873                 EngSetLastError(ERROR_INVALID_PARAMETER);
00874                 return FALSE;
00875             }
00876         }
00877     }
00878     else
00879     {
00880         PGRADIENT_RECT pRect = (PGRADIENT_RECT)pMesh;
00881         for (i = 0; i < nMesh; i++, pRect++)
00882         {
00883             if (pRect->UpperLeft >= nVertex || pRect->LowerRight >= nVertex)
00884             {
00885                 EngSetLastError(ERROR_INVALID_PARAMETER);
00886                 return FALSE;
00887             }
00888         }
00889     }
00890 
00891     /* Lock the output DC */
00892     pdc = DC_LockDc(hdc);
00893     if(!pdc)
00894     {
00895         EngSetLastError(ERROR_INVALID_HANDLE);
00896         return FALSE;
00897     }
00898 
00899     if(pdc->dctype == DC_TYPE_INFO)
00900     {
00901         DC_UnlockDc(pdc);
00902         /* Yes, Windows really returns TRUE in this case */
00903         return TRUE;
00904     }
00905 
00906     psurf = pdc->dclevel.pSurface;
00907     if(!psurf)
00908     {
00909         /* Memory DC with no surface selected */
00910         DC_UnlockDc(pdc);
00911         return TRUE; // CHECKME
00912     }
00913 
00914     /* Calculate extent */
00915     rclExtent.left = rclExtent.right = pVertex->x;
00916     rclExtent.top = rclExtent.bottom = pVertex->y;
00917     for (i = 0; i < nVertex; i++)
00918     {
00919         rclExtent.left = min(rclExtent.left, (pVertex + i)->x);
00920         rclExtent.right = max(rclExtent.right, (pVertex + i)->x);
00921         rclExtent.top = min(rclExtent.top, (pVertex + i)->y);
00922         rclExtent.bottom = max(rclExtent.bottom, (pVertex + i)->y);
00923     }
00924     IntLPtoDP(pdc, (LPPOINT)&rclExtent, 2);
00925 
00926     rclExtent.left   += pdc->ptlDCOrig.x;
00927     rclExtent.right  += pdc->ptlDCOrig.x;
00928     rclExtent.top    += pdc->ptlDCOrig.y;
00929     rclExtent.bottom += pdc->ptlDCOrig.y;
00930 
00931     ptlDitherOrg.x = ptlDitherOrg.y = 0;
00932     IntLPtoDP(pdc, (LPPOINT)&ptlDitherOrg, 1);
00933 
00934     ptlDitherOrg.x += pdc->ptlDCOrig.x;
00935     ptlDitherOrg.y += pdc->ptlDCOrig.y;
00936 
00937     EXLATEOBJ_vInitialize(&exlo, &gpalRGB, psurf->ppal, 0, 0, 0);
00938 
00939     ASSERT(pdc->rosdc.CombinedClip);
00940 
00941     DC_vPrepareDCsForBlit(pdc, rclExtent, NULL, rclExtent);
00942 
00943     bRet = IntEngGradientFill(&psurf->SurfObj,
00944                              pdc->rosdc.CombinedClip,
00945                              &exlo.xlo,
00946                              pVertex,
00947                              nVertex,
00948                              pMesh,
00949                              nMesh,
00950                              &rclExtent,
00951                              &ptlDitherOrg,
00952                              ulMode);
00953 
00954     EXLATEOBJ_vCleanup(&exlo);
00955     DC_vFinishBlit(pdc, NULL);
00956     DC_UnlockDc(pdc);
00957 
00958     return bRet;
00959 }
00960 
00961 BOOL
00962 APIENTRY
00963 NtGdiGradientFill(
00964     HDC hdc,
00965     PTRIVERTEX pVertex,
00966     ULONG nVertex,
00967     PVOID pMesh,
00968     ULONG nMesh,
00969     ULONG ulMode)
00970 {
00971     BOOL bRet;
00972     PTRIVERTEX SafeVertex;
00973     PVOID SafeMesh;
00974     ULONG cbVertex, cbMesh;
00975 
00976     /* Validate parameters */
00977     if (!pVertex || !nVertex || !pMesh || !nMesh)
00978     {
00979         EngSetLastError(ERROR_INVALID_PARAMETER);
00980         return FALSE;
00981     }
00982 
00983     switch (ulMode)
00984     {
00985         case GRADIENT_FILL_RECT_H:
00986         case GRADIENT_FILL_RECT_V:
00987             cbMesh = nMesh * sizeof(GRADIENT_RECT);
00988             break;
00989         case GRADIENT_FILL_TRIANGLE:
00990             cbMesh = nMesh * sizeof(GRADIENT_TRIANGLE);
00991             break;
00992         default:
00993             EngSetLastError(ERROR_INVALID_PARAMETER);
00994             return FALSE;
00995     }
00996 
00997     cbVertex = nVertex * sizeof(TRIVERTEX) ;
00998     if(cbVertex + cbMesh <= cbVertex)
00999     {
01000         /* Overflow */
01001         return FALSE ;
01002     }
01003 
01004     /* Allocate a kernel mode buffer */
01005     SafeVertex = ExAllocatePoolWithTag(PagedPool, cbVertex + cbMesh, TAG_SHAPE);
01006     if(!SafeVertex)
01007     {
01008         EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
01009         return FALSE;
01010     }
01011 
01012     SafeMesh = (PVOID)((ULONG_PTR)SafeVertex + cbVertex);
01013 
01014     /* Copy the parameters to kernel mode */
01015     _SEH2_TRY
01016     {
01017         ProbeForRead(pVertex, cbVertex, 1);
01018         ProbeForRead(pMesh, cbMesh, 1);
01019         RtlCopyMemory(SafeVertex, pVertex, cbVertex);
01020         RtlCopyMemory(SafeMesh, pMesh, cbMesh);
01021     }
01022     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
01023     {
01024         ExFreePoolWithTag(SafeVertex, TAG_SHAPE);
01025         SetLastNtError(_SEH2_GetExceptionCode());
01026         _SEH2_YIELD(return FALSE;)
01027     }
01028     _SEH2_END;
01029 
01030     /* Call the internal function */
01031     bRet = GreGradientFill(hdc, SafeVertex, nVertex, SafeMesh, nMesh, ulMode);
01032 
01033     /* Cleanup and return result */
01034     ExFreePoolWithTag(SafeVertex, TAG_SHAPE);
01035     return bRet;
01036 }
01037 
01038 BOOL APIENTRY
01039 NtGdiExtFloodFill(
01040     HDC  hDC,
01041     INT  XStart,
01042     INT  YStart,
01043     COLORREF  Color,
01044     UINT  FillType)
01045 {
01046     PDC dc;
01047     PDC_ATTR   pdcattr;
01048     SURFACE    *psurf = NULL;
01049     EXLATEOBJ  exlo;
01050     BOOL       Ret = FALSE;
01051     RECTL      DestRect;
01052     POINTL     Pt;
01053     ULONG      ConvColor;
01054 
01055     dc = DC_LockDc(hDC);
01056     if (!dc)
01057     {
01058         EngSetLastError(ERROR_INVALID_HANDLE);
01059         return FALSE;
01060     }
01061     if (dc->dctype == DC_TYPE_INFO)
01062     {
01063         DC_UnlockDc(dc);
01064         /* Yes, Windows really returns TRUE in this case */
01065         return TRUE;
01066     }
01067 
01068     pdcattr = dc->pdcattr;
01069 
01070     if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
01071         DC_vUpdateFillBrush(dc);
01072 
01073     if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
01074         DC_vUpdateLineBrush(dc);
01075 
01076     Pt.x = XStart;
01077     Pt.y = YStart;
01078     IntLPtoDP(dc, (LPPOINT)&Pt, 1);
01079 
01080     Ret = NtGdiPtInRegion(dc->rosdc.hGCClipRgn, Pt.x, Pt.y);
01081     if (Ret)
01082         IntGdiGetRgnBox(dc->rosdc.hGCClipRgn,(LPRECT)&DestRect);
01083     else
01084         goto cleanup;
01085 
01086     psurf = dc->dclevel.pSurface;
01087     if (!psurf)
01088     {
01089         Ret = FALSE;
01090         goto cleanup;
01091     }
01092 
01093     EXLATEOBJ_vInitialize(&exlo, &gpalRGB, psurf->ppal, 0, 0xffffff, 0);
01094 
01095     /* Only solid fills supported for now
01096      * How to support pattern brushes and non standard surfaces (not offering dib functions):
01097      * Version a (most likely slow): call DrvPatBlt for every pixel
01098      * Version b: create a flood mask and let MaskBlt blit a masked brush */
01099     ConvColor = XLATEOBJ_iXlate(&exlo.xlo, Color);
01100     Ret = DIB_XXBPP_FloodFillSolid(&psurf->SurfObj, &dc->eboFill.BrushObject, &DestRect, &Pt, ConvColor, FillType);
01101 
01102     EXLATEOBJ_vCleanup(&exlo);
01103 
01104 cleanup:
01105     DC_UnlockDc(dc);
01106     return Ret;
01107 }
01108 
01109 /* EOF */

Generated on Sun May 27 2012 04:38:25 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.