/* * @implemented */ BOOL APIENTRY EngAlphaBlend(IN SURFOBJ *psoDest, IN SURFOBJ *psoSource, IN CLIPOBJ *ClipRegion, IN XLATEOBJ *ColorTranslation, IN PRECTL DestRect, IN PRECTL SourceRect, IN BLENDOBJ *BlendObj) { RECTL InputRect; RECTL OutputRect; RECTL ClipRect; RECTL CombinedRect; RECTL Rect; POINTL Translate; INTENG_ENTER_LEAVE EnterLeaveSource; INTENG_ENTER_LEAVE EnterLeaveDest; SURFOBJ* InputObj; SURFOBJ* OutputObj; LONG ClippingType; RECT_ENUM RectEnum; BOOL EnumMore; INT i; BOOLEAN Ret; DPRINT("EngAlphaBlend(psoDest:0x%p, psoSource:0x%p, ClipRegion:0x%p, ColorTranslation:0x%p,\n", psoDest, psoSource, ClipRegion, ColorTranslation); DPRINT(" DestRect:{0x%x, 0x%x, 0x%x, 0x%x}, SourceRect:{0x%x, 0x%x, 0x%x, 0x%x},\n", DestRect->left, DestRect->top, DestRect->right, DestRect->bottom, SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom); DPRINT(" BlendObj:{0x%x, 0x%x, 0x%x, 0x%x}\n", BlendObj->BlendFunction.BlendOp, BlendObj->BlendFunction.BlendFlags, BlendObj->BlendFunction.SourceConstantAlpha, BlendObj->BlendFunction.AlphaFormat); /* Validate output */ OutputRect = *DestRect; if (OutputRect.right < OutputRect.left) { OutputRect.left = DestRect->right; OutputRect.right = DestRect->left; } if (OutputRect.bottom < OutputRect.top) { OutputRect.left = DestRect->right; OutputRect.right = DestRect->left; } /* Validate input */ InputRect = *SourceRect; if ( (InputRect.top < 0) || (InputRect.bottom < 0) || (InputRect.left < 0) || (InputRect.right < 0) || InputRect.right > psoSource->sizlBitmap.cx || InputRect.bottom > psoSource->sizlBitmap.cy ) { EngSetLastError(ERROR_INVALID_PARAMETER); return FALSE; } if (psoDest == psoSource && !(OutputRect.left >= SourceRect->right || InputRect.left >= OutputRect.right || OutputRect.top >= SourceRect->bottom || InputRect.top >= OutputRect.bottom)) { DPRINT1("Source and destination rectangles overlap!\n"); return FALSE; } if (BlendObj->BlendFunction.BlendOp != AC_SRC_OVER) { DPRINT1("BlendOp != AC_SRC_OVER (0x%x)\n", BlendObj->BlendFunction.BlendOp); return FALSE; } if (BlendObj->BlendFunction.BlendFlags != 0) { DPRINT1("BlendFlags != 0 (0x%x)\n", BlendObj->BlendFunction.BlendFlags); return FALSE; } if ((BlendObj->BlendFunction.AlphaFormat & ~AC_SRC_ALPHA) != 0) { DPRINT1("Unsupported AlphaFormat (0x%x)\n", BlendObj->BlendFunction.AlphaFormat); return FALSE; } /* Check if there is anything to draw */ if (ClipRegion != NULL && (ClipRegion->rclBounds.left >= ClipRegion->rclBounds.right || ClipRegion->rclBounds.top >= ClipRegion->rclBounds.bottom)) { /* Nothing to do */ return TRUE; } /* Now call the DIB function */ if (!IntEngEnter(&EnterLeaveSource, psoSource, &InputRect, TRUE, &Translate, &InputObj)) { return FALSE; } InputRect.left += Translate.x; InputRect.right += Translate.x; InputRect.top += Translate.y; InputRect.bottom += Translate.y; if (!IntEngEnter(&EnterLeaveDest, psoDest, &OutputRect, FALSE, &Translate, &OutputObj)) { return FALSE; } OutputRect.left += Translate.x; OutputRect.right += Translate.x; OutputRect.top += Translate.y; OutputRect.bottom += Translate.y; Ret = FALSE; ClippingType = (ClipRegion == NULL) ? DC_TRIVIAL : ClipRegion->iDComplexity; switch (ClippingType) { case DC_TRIVIAL: Ret = DibFunctionsForBitmapFormat[OutputObj->iBitmapFormat].DIB_AlphaBlend( OutputObj, InputObj, &OutputRect, &InputRect, ClipRegion, ColorTranslation, BlendObj); break; case DC_RECT: ClipRect.left = ClipRegion->rclBounds.left + Translate.x; ClipRect.right = ClipRegion->rclBounds.right + Translate.x; ClipRect.top = ClipRegion->rclBounds.top + Translate.y; ClipRect.bottom = ClipRegion->rclBounds.bottom + Translate.y; if (RECTL_bIntersectRect(&CombinedRect, &OutputRect, &ClipRect)) { Rect.left = InputRect.left + CombinedRect.left - OutputRect.left; Rect.right = InputRect.right + CombinedRect.right - OutputRect.right; Rect.top = InputRect.top + CombinedRect.top - OutputRect.top; Rect.bottom = InputRect.bottom + CombinedRect.bottom - OutputRect.bottom; Ret = DibFunctionsForBitmapFormat[OutputObj->iBitmapFormat].DIB_AlphaBlend( OutputObj, InputObj, &CombinedRect, &Rect, ClipRegion, ColorTranslation, BlendObj); } break; case DC_COMPLEX: Ret = TRUE; CLIPOBJ_cEnumStart(ClipRegion, FALSE, CT_RECTANGLES, CD_ANY, 0); do { EnumMore = CLIPOBJ_bEnum(ClipRegion,(ULONG) sizeof(RectEnum), (PVOID) &RectEnum); for (i = 0; i < RectEnum.c; i++) { ClipRect.left = RectEnum.arcl[i].left + Translate.x; ClipRect.right = RectEnum.arcl[i].right + Translate.x; ClipRect.top = RectEnum.arcl[i].top + Translate.y; ClipRect.bottom = RectEnum.arcl[i].bottom + Translate.y; if (RECTL_bIntersectRect(&CombinedRect, &OutputRect, &ClipRect)) { Rect.left = InputRect.left + CombinedRect.left - OutputRect.left; Rect.right = InputRect.right + CombinedRect.right - OutputRect.right; Rect.top = InputRect.top + CombinedRect.top - OutputRect.top; Rect.bottom = InputRect.bottom + CombinedRect.bottom - OutputRect.bottom; Ret = DibFunctionsForBitmapFormat[OutputObj->iBitmapFormat].DIB_AlphaBlend( OutputObj, InputObj, &CombinedRect, &Rect, ClipRegion, ColorTranslation, BlendObj) && Ret; } } } while (EnumMore); break; default: UNIMPLEMENTED; ASSERT(FALSE); break; } IntEngLeave(&EnterLeaveDest); IntEngLeave(&EnterLeaveSource); return Ret; }
BOOL APIENTRY EngTransparentBlt( SURFOBJ *psoDest, SURFOBJ *psoSource, CLIPOBJ *Clip, XLATEOBJ *ColorTranslation, PRECTL DestRect, PRECTL SourceRect, ULONG iTransColor, ULONG Reserved) { BOOL Ret = TRUE; BYTE ClippingType; INTENG_ENTER_LEAVE EnterLeaveSource, EnterLeaveDest; SURFOBJ *InputObj, *OutputObj; RECTL OutputRect, InputRect; POINTL Translate; LONG DstHeight; LONG DstWidth; LONG SrcHeight; LONG SrcWidth; InputRect = *SourceRect; if (!IntEngEnter(&EnterLeaveSource, psoSource, &InputRect, TRUE, &Translate, &InputObj)) { return FALSE; } InputRect.left += Translate.x; InputRect.right += Translate.x; InputRect.top += Translate.y; InputRect.bottom += Translate.y; OutputRect = *DestRect; if (OutputRect.right < OutputRect.left) { OutputRect.left = DestRect->right; OutputRect.right = DestRect->left; } if (OutputRect.bottom < OutputRect.top) { OutputRect.top = DestRect->bottom; OutputRect.bottom = DestRect->top; } if (Clip) { if (OutputRect.left < Clip->rclBounds.left) { InputRect.left += Clip->rclBounds.left - OutputRect.left; OutputRect.left = Clip->rclBounds.left; } if (Clip->rclBounds.right < OutputRect.right) { InputRect.right -= OutputRect.right - Clip->rclBounds.right; OutputRect.right = Clip->rclBounds.right; } if (OutputRect.top < Clip->rclBounds.top) { InputRect.top += Clip->rclBounds.top - OutputRect.top; OutputRect.top = Clip->rclBounds.top; } if (Clip->rclBounds.bottom < OutputRect.bottom) { InputRect.bottom -= OutputRect.bottom - Clip->rclBounds.bottom; OutputRect.bottom = Clip->rclBounds.bottom; } } /* Check for degenerate case: if height or width of OutputRect is 0 pixels there's nothing to do */ if (OutputRect.right <= OutputRect.left || OutputRect.bottom <= OutputRect.top) { IntEngLeave(&EnterLeaveSource); return TRUE; } if (!IntEngEnter(&EnterLeaveDest, psoDest, &OutputRect, FALSE, &Translate, &OutputObj)) { IntEngLeave(&EnterLeaveSource); return FALSE; } OutputRect.left = DestRect->left + Translate.x; OutputRect.right = DestRect->right + Translate.x; OutputRect.top = DestRect->top + Translate.y; OutputRect.bottom = DestRect->bottom + Translate.y; ClippingType = (Clip ? Clip->iDComplexity : DC_TRIVIAL); DstHeight = OutputRect.bottom - OutputRect.top; DstWidth = OutputRect.right - OutputRect.left; SrcHeight = InputRect.bottom - InputRect.top; SrcWidth = InputRect.right - InputRect.left; switch (ClippingType) { case DC_TRIVIAL: { Ret = DibFunctionsForBitmapFormat[psoDest->iBitmapFormat].DIB_TransparentBlt( OutputObj, InputObj, &OutputRect, &InputRect, ColorTranslation, iTransColor); break; } case DC_RECT: { RECTL ClipRect, CombinedRect; RECTL InputToCombinedRect; ClipRect.left = Clip->rclBounds.left + Translate.x; ClipRect.right = Clip->rclBounds.right + Translate.x; ClipRect.top = Clip->rclBounds.top + Translate.y; ClipRect.bottom = Clip->rclBounds.bottom + Translate.y; if (RECTL_bIntersectRect(&CombinedRect, &OutputRect, &ClipRect)) { InputToCombinedRect.top = InputRect.top + (CombinedRect.top - OutputRect.top) * SrcHeight / DstHeight; InputToCombinedRect.bottom = InputRect.top + (CombinedRect.bottom - OutputRect.top) * SrcHeight / DstHeight; InputToCombinedRect.left = InputRect.left + (CombinedRect.left - OutputRect.left) * SrcWidth / DstWidth; InputToCombinedRect.right = InputRect.left + (CombinedRect.right - OutputRect.left) * SrcWidth / DstWidth; Ret = DibFunctionsForBitmapFormat[psoDest->iBitmapFormat].DIB_TransparentBlt( OutputObj, InputObj, &CombinedRect, &InputToCombinedRect, ColorTranslation, iTransColor); } break; } case DC_COMPLEX: { ULONG Direction, i; RECT_ENUM RectEnum; BOOL EnumMore; if (OutputObj == InputObj) { if (OutputRect.top < InputRect.top) { Direction = OutputRect.left < (InputRect.left ? CD_RIGHTDOWN : CD_LEFTDOWN); } else { Direction = OutputRect.left < (InputRect.left ? CD_RIGHTUP : CD_LEFTUP); } } else { Direction = CD_ANY; } CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, Direction, 0); do { EnumMore = CLIPOBJ_bEnum(Clip, sizeof(RectEnum), (PVOID)&RectEnum); for (i = 0; i < RectEnum.c; i++) { RECTL ClipRect, CombinedRect; RECTL InputToCombinedRect; ClipRect.left = RectEnum.arcl[i].left + Translate.x; ClipRect.right = RectEnum.arcl[i].right + Translate.x; ClipRect.top = RectEnum.arcl[i].top + Translate.y; ClipRect.bottom = RectEnum.arcl[i].bottom + Translate.y; if (RECTL_bIntersectRect(&CombinedRect, &OutputRect, &ClipRect)) { InputToCombinedRect.top = InputRect.top + (CombinedRect.top - OutputRect.top) * SrcHeight / DstHeight; InputToCombinedRect.bottom = InputRect.top + (CombinedRect.bottom - OutputRect.top) * SrcHeight / DstHeight; InputToCombinedRect.left = InputRect.left + (CombinedRect.left - OutputRect.left) * SrcWidth / DstWidth; InputToCombinedRect.right = InputRect.left + (CombinedRect.right - OutputRect.left) * SrcWidth / DstWidth; Ret = DibFunctionsForBitmapFormat[psoDest->iBitmapFormat].DIB_TransparentBlt( OutputObj, InputObj, &CombinedRect, &InputToCombinedRect, ColorTranslation, iTransColor); if (!Ret) { break; } } } } while (EnumMore && Ret); break; } default: { Ret = FALSE; break; } } IntEngLeave(&EnterLeaveDest); IntEngLeave(&EnterLeaveSource); return Ret; }
BOOL FASTCALL IntEngTransparentBlt( SURFOBJ *psoDest, SURFOBJ *psoSource, CLIPOBJ *Clip, XLATEOBJ *ColorTranslation, PRECTL DestRect, PRECTL SourceRect, ULONG iTransColor, ULONG Reserved) { BOOL Ret; RECTL OutputRect, InputClippedRect; SURFACE *psurfDest; SURFACE *psurfSource; RECTL InputRect; LONG InputClWidth, InputClHeight, InputWidth, InputHeight; ASSERT(psoDest); ASSERT(psoSource); ASSERT(DestRect); psurfDest = CONTAINING_RECORD(psoDest, SURFACE, SurfObj); psurfSource = CONTAINING_RECORD(psoSource, SURFACE, SurfObj); ASSERT(psurfDest); ASSERT(psurfSource); /* If no clip object is given, use trivial one */ if (!Clip) Clip = &gxcoTrivial.ClipObj; InputClippedRect = *DestRect; if (InputClippedRect.right < InputClippedRect.left) { InputClippedRect.left = DestRect->right; InputClippedRect.right = DestRect->left; } if (InputClippedRect.bottom < InputClippedRect.top) { InputClippedRect.top = DestRect->bottom; InputClippedRect.bottom = DestRect->top; } InputRect = *SourceRect; /* Clip against the bounds of the clipping region so we won't try to write * outside the surface */ if (Clip->iDComplexity != DC_TRIVIAL) { if (!RECTL_bIntersectRect(&OutputRect, &InputClippedRect, &Clip->rclBounds)) { return TRUE; } /* Update source rect */ InputClWidth = InputClippedRect.right - InputClippedRect.left; InputClHeight = InputClippedRect.bottom - InputClippedRect.top; InputWidth = InputRect.right - InputRect.left; InputHeight = InputRect.bottom - InputRect.top; InputRect.left += (InputWidth * (OutputRect.left - InputClippedRect.left)) / InputClWidth; InputRect.right -= (InputWidth * (InputClippedRect.right - OutputRect.right)) / InputClWidth; InputRect.top += (InputHeight * (OutputRect.top - InputClippedRect.top)) / InputClHeight; InputRect.bottom -= (InputHeight * (InputClippedRect.bottom - OutputRect.bottom)) / InputClHeight; } else { OutputRect = InputClippedRect; } if (psurfDest->flags & HOOK_TRANSPARENTBLT) { Ret = GDIDEVFUNCS(psoDest).TransparentBlt(psoDest, psoSource, Clip, ColorTranslation, &OutputRect, &InputRect, iTransColor, Reserved); } else Ret = FALSE; if (!Ret) { Ret = EngTransparentBlt(psoDest, psoSource, Clip, ColorTranslation, &OutputRect, &InputRect, iTransColor, Reserved); } return Ret; }
/* IntGetMonitorsFromRect * * Returns a list of monitor handles/rectangles. The rectangles in the list are * the areas of intersection with the monitors. * * Arguments * * pRect * Rectangle in desktop coordinates. If this is NULL all monitors are * returned and the rect list is filled with the sizes of the monitors. * * phMonitorList * Pointer to an array of HMONITOR which is filled with monitor handles. * Can be NULL * * prcMonitorList * Pointer to an array of RECT which is filled with intersection rects in * desktop coordinates. * Can be NULL, will be ignored if no intersecting monitor is found and * flags is MONITOR_DEFAULTTONEAREST * * dwListSize * Size of the phMonitorList and prcMonitorList arguments. If this is zero * phMonitorList and prcMonitorList are ignored. * * dwFlags * Either 0 or MONITOR_DEFAULTTONEAREST (ignored if rect is NULL) * * Returns * The number of monitors which intersect the specified region. */ static UINT IntGetMonitorsFromRect(OPTIONAL IN LPCRECTL pRect, OPTIONAL OUT HMONITOR *phMonitorList, OPTIONAL OUT PRECTL prcMonitorList, OPTIONAL IN DWORD dwListSize, OPTIONAL IN DWORD dwFlags) { PMONITOR pMonitor, pNearestMonitor = NULL, pPrimaryMonitor = NULL; UINT cMonitors = 0; ULONG iNearestDistance = 0xffffffff; /* Find monitors which intersects the rectangle */ for (pMonitor = gMonitorList; pMonitor != NULL; pMonitor = pMonitor->pMonitorNext) { RECTL MonitorRect, IntersectionRect; MonitorRect = pMonitor->rcMonitor; TRACE("MonitorRect: left = %d, top = %d, right = %d, bottom = %d\n", MonitorRect.left, MonitorRect.top, MonitorRect.right, MonitorRect.bottom); /* Save primary monitor for later usage */ if (dwFlags == MONITOR_DEFAULTTOPRIMARY && pMonitor->IsPrimary) pPrimaryMonitor = pMonitor; /* Check if a rect is given */ if (pRect == NULL) { /* No rect given, so use the full monitor rect */ IntersectionRect = MonitorRect; } /* We have a rect, calculate intersection */ else if (!RECTL_bIntersectRect(&IntersectionRect, &MonitorRect, pRect)) { /* Rects did not intersect */ if (dwFlags == MONITOR_DEFAULTTONEAREST) { ULONG cx, cy, iDistance; /* Get x and y distance */ cx = min(abs(MonitorRect.left - pRect->right), abs(pRect->left - MonitorRect.right)); cy = min(abs(MonitorRect.top - pRect->bottom), abs(pRect->top - MonitorRect.bottom)); /* Calculate distance square */ iDistance = cx * cx + cy * cy; /* Check if this is the new nearest monitor */ if (iDistance < iNearestDistance) { iNearestDistance = iDistance; pNearestMonitor = pMonitor; } } continue; } /* Check if there's space in the buffer */ if (cMonitors < dwListSize) { /* Save monitor data */ if (phMonitorList != NULL) phMonitorList[cMonitors] = UserHMGetHandle(pMonitor); if (prcMonitorList != NULL) prcMonitorList[cMonitors] = IntersectionRect; } /* Increase count of found monitors */ cMonitors++; } /* Nothing has been found? */ if (cMonitors == 0) { /* Check if we shall default to the nearest monitor */ if (dwFlags == MONITOR_DEFAULTTONEAREST && pNearestMonitor) { if (phMonitorList && dwListSize > 0) phMonitorList[cMonitors] = UserHMGetHandle(pNearestMonitor); cMonitors++; } /* Check if we shall default to the primary monitor */ else if (dwFlags == MONITOR_DEFAULTTOPRIMARY && pPrimaryMonitor) { if (phMonitorList != NULL && dwListSize > 0) phMonitorList[cMonitors] = UserHMGetHandle(pPrimaryMonitor); cMonitors++; } } return cMonitors; }
/* IntGetMonitorsFromRect * * Returns a list of monitor handles/rectangles. The rectangles in the list are * the areas of intersection with the monitors. * * Arguments * * pRect * Rectangle in desktop coordinates. If this is NULL all monitors are * returned and the rect list is filled with the sizes of the monitors. * * hMonitorList * Pointer to an array of HMONITOR which is filled with monitor handles. * Can be NULL * * monitorRectList * Pointer to an array of RECT which is filled with intersection rects in * desktop coordinates. * Can be NULL, will be ignored if no intersecting monitor is found and * flags is MONITOR_DEFAULTTONEAREST * * listSize * Size of the hMonitorList and monitorRectList arguments. If this is zero * hMonitorList and monitorRectList are ignored. * * flags * Either 0 or MONITOR_DEFAULTTONEAREST (ignored if rect is NULL) * * Returns * The number of monitors which intersect the specified region. */ static UINT IntGetMonitorsFromRect(OPTIONAL IN LPCRECTL pRect, OPTIONAL OUT HMONITOR *hMonitorList, OPTIONAL OUT PRECTL monitorRectList, OPTIONAL IN DWORD listSize, OPTIONAL IN DWORD flags) { PMONITOR Monitor, NearestMonitor = NULL, PrimaryMonitor = NULL; UINT iCount = 0; ULONG iNearestDistance = 0xffffffff; /* Find monitors which intersect the rectangle */ for (Monitor = gMonitorList; Monitor != NULL; Monitor = Monitor->Next) { RECTL MonitorRect, IntersectionRect; ExEnterCriticalRegionAndAcquireFastMutexUnsafe(&Monitor->Lock); MonitorRect = Monitor->rcMonitor; ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(&Monitor->Lock); TRACE("MonitorRect: left = %d, top = %d, right = %d, bottom = %d\n", MonitorRect.left, MonitorRect.top, MonitorRect.right, MonitorRect.bottom); if (flags == MONITOR_DEFAULTTOPRIMARY && Monitor->IsPrimary) { PrimaryMonitor = Monitor; } /* Check if a rect is given */ if (pRect == NULL) { /* No rect given, so use the full monitor rect */ IntersectionRect = MonitorRect; } /* We have a rect, calculate intersection */ else if (!RECTL_bIntersectRect(&IntersectionRect, &MonitorRect, pRect)) { /* Rects did not intersect */ if (flags == MONITOR_DEFAULTTONEAREST) { ULONG cx, cy, iDistance; /* Get x and y distance */ cx = min(abs(MonitorRect.left - pRect->right), abs(pRect->left - MonitorRect.right)); cy = min(abs(MonitorRect.top - pRect->bottom), abs(pRect->top - MonitorRect.bottom)); /* Calculate distance square */ iDistance = cx * cx + cy * cy; /* Check if this is the new nearest monitor */ if (iDistance < iNearestDistance) { iNearestDistance = iDistance; NearestMonitor = Monitor; } } continue; } /* Check if there's space in the buffer */ if (iCount < listSize) { if (hMonitorList != NULL) hMonitorList[iCount] = UserHMGetHandle(Monitor); if (monitorRectList != NULL) monitorRectList[iCount] = IntersectionRect; } /* Increase count of found monitors */ iCount++; } /* Found nothing intersecting? */ if (iCount == 0) { /* Check if we shall default to the nearest monitor */ if (flags == MONITOR_DEFAULTTONEAREST && NearestMonitor) { if (hMonitorList && listSize > 0) hMonitorList[iCount] = UserHMGetHandle(NearestMonitor); iCount++; } /* Check if we shall default to the primary monitor */ else if (flags == MONITOR_DEFAULTTOPRIMARY && PrimaryMonitor) { if (hMonitorList != NULL && listSize > 0) hMonitorList[iCount] = UserHMGetHandle(PrimaryMonitor); iCount++; } } return iCount; }
BOOL FASTCALL IntEngGradientFillRect( IN SURFOBJ *psoDest, IN CLIPOBJ *pco, IN XLATEOBJ *pxlo, IN TRIVERTEX *pVertex, IN ULONG nVertex, IN PGRADIENT_RECT gRect, IN RECTL *prclExtents, IN POINTL *pptlDitherOrg, IN BOOL Horizontal) { SURFOBJ *psoOutput; TRIVERTEX *v1, *v2; RECTL rcGradient, rcSG; RECT_ENUM RectEnum; BOOL EnumMore; ULONG i; POINTL Translate; INTENG_ENTER_LEAVE EnterLeave; LONG y, dy, c[3], dc[3], ec[3], ic[3]; v1 = (pVertex + gRect->UpperLeft); v2 = (pVertex + gRect->LowerRight); rcGradient.left = min(v1->x, v2->x); rcGradient.right = max(v1->x, v2->x); rcGradient.top = min(v1->y, v2->y); rcGradient.bottom = max(v1->y, v2->y); rcSG = rcGradient; RECTL_vOffsetRect(&rcSG, pptlDitherOrg->x, pptlDitherOrg->y); if(Horizontal) { dy = abs(rcGradient.right - rcGradient.left); } else { dy = abs(rcGradient.bottom - rcGradient.top); } if(!IntEngEnter(&EnterLeave, psoDest, &rcSG, FALSE, &Translate, &psoOutput)) { return FALSE; } if((v1->Red != v2->Red || v1->Green != v2->Green || v1->Blue != v2->Blue) && dy > 1) { CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_RIGHTDOWN, 0); do { RECTL FillRect; ULONG Color; if (Horizontal) { EnumMore = CLIPOBJ_bEnum(pco, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); for (i = 0; i < RectEnum.c && RectEnum.arcl[i].top <= rcSG.bottom; i++) { if (RECTL_bIntersectRect(&FillRect, &RectEnum.arcl[i], &rcSG)) { HVINITCOL(Red, 0); HVINITCOL(Green, 1); HVINITCOL(Blue, 2); for (y = rcSG.left; y < FillRect.right; y++) { if (y >= FillRect.left) { Color = XLATEOBJ_iXlate(pxlo, RGB(c[0], c[1], c[2])); DibFunctionsForBitmapFormat[psoOutput->iBitmapFormat].DIB_VLine( psoOutput, y + Translate.x, FillRect.top + Translate.y, FillRect.bottom + Translate.y, Color); } HVSTEPCOL(0); HVSTEPCOL(1); HVSTEPCOL(2); } } } continue; } /* vertical */ EnumMore = CLIPOBJ_bEnum(pco, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); for (i = 0; i < RectEnum.c && RectEnum.arcl[i].top <= rcSG.bottom; i++) { if (RECTL_bIntersectRect(&FillRect, &RectEnum.arcl[i], &rcSG)) { HVINITCOL(Red, 0); HVINITCOL(Green, 1); HVINITCOL(Blue, 2); for (y = rcSG.top; y < FillRect.bottom; y++) { if (y >= FillRect.top) { Color = XLATEOBJ_iXlate(pxlo, RGB(c[0], c[1], c[2])); DibFunctionsForBitmapFormat[psoOutput->iBitmapFormat].DIB_HLine(psoOutput, FillRect.left + Translate.x, FillRect.right + Translate.x, y + Translate.y, Color); } HVSTEPCOL(0); HVSTEPCOL(1); HVSTEPCOL(2); } } } } while (EnumMore); return IntEngLeave(&EnterLeave); } /* rectangle has only one color, no calculation required */ CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_RIGHTDOWN, 0); do { RECTL FillRect; ULONG Color = XLATEOBJ_iXlate(pxlo, RGB(v1->Red, v1->Green, v1->Blue)); EnumMore = CLIPOBJ_bEnum(pco, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); for (i = 0; i < RectEnum.c && RectEnum.arcl[i].top <= rcSG.bottom; i++) { if (RECTL_bIntersectRect(&FillRect, &RectEnum.arcl[i], &rcSG)) { for (; FillRect.top < FillRect.bottom; FillRect.top++) { DibFunctionsForBitmapFormat[psoOutput->iBitmapFormat].DIB_HLine(psoOutput, FillRect.left + Translate.x, FillRect.right + Translate.x, FillRect.top + Translate.y, Color); } } } } while (EnumMore); return IntEngLeave(&EnterLeave); }
/* * @implemented */ BOOL APIENTRY EngCopyBits( _In_ SURFOBJ *psoDest, _In_ SURFOBJ *psoSource, _In_opt_ CLIPOBJ *Clip, _In_opt_ XLATEOBJ *ColorTranslation, _In_ RECTL *DestRect, _In_ POINTL *SourcePoint) { BOOL ret; BYTE clippingType; RECT_ENUM RectEnum; BOOL EnumMore; BLTINFO BltInfo; SURFACE *psurfDest; SURFACE *psurfSource; RECTL rclDest = *DestRect; POINTL ptlSrc = *SourcePoint; ASSERT(psoDest != NULL && psoSource != NULL && DestRect != NULL && SourcePoint != NULL); psurfSource = CONTAINING_RECORD(psoSource, SURFACE, SurfObj); psurfDest = CONTAINING_RECORD(psoDest, SURFACE, SurfObj); /* Clip dest rect against source surface size / source point */ if (psoSource->sizlBitmap.cx - ptlSrc.x < rclDest.right - rclDest.left) rclDest.right = rclDest.left + psoSource->sizlBitmap.cx - ptlSrc.x; if (psoSource->sizlBitmap.cy - ptlSrc.y < rclDest.bottom - rclDest.top) rclDest.bottom = rclDest.top + psoSource->sizlBitmap.cy - ptlSrc.y; /* Clip dest rect against target surface size */ if (rclDest.right > psoDest->sizlBitmap.cx) rclDest.right = psoDest->sizlBitmap.cx; if (rclDest.bottom > psoDest->sizlBitmap.cy) rclDest.bottom = psoDest->sizlBitmap.cy; if (RECTL_bIsEmptyRect(&rclDest)) return TRUE; DestRect = &rclDest; // FIXME: Don't punt to the driver's DrvCopyBits immediately. Instead, // mark the copy block function to be DrvCopyBits instead of the // GDI's copy bit function so as to remove clipping from the // driver's responsibility // If one of the surfaces isn't managed by the GDI if ((psoDest->iType!=STYPE_BITMAP) || (psoSource->iType!=STYPE_BITMAP)) { // Destination surface is device managed if (psoDest->iType!=STYPE_BITMAP) { /* FIXME: Eng* functions shouldn't call Drv* functions. ? */ if (psurfDest->flags & HOOK_COPYBITS) { ret = GDIDEVFUNCS(psoDest).CopyBits( psoDest, psoSource, Clip, ColorTranslation, DestRect, SourcePoint); goto cleanup; } } // Source surface is device managed if (psoSource->iType!=STYPE_BITMAP) { /* FIXME: Eng* functions shouldn't call Drv* functions. ? */ if (psurfSource->flags & HOOK_COPYBITS) { ret = GDIDEVFUNCS(psoSource).CopyBits( psoDest, psoSource, Clip, ColorTranslation, DestRect, SourcePoint); goto cleanup; } } // If CopyBits wasn't hooked, BitBlt must be ret = IntEngBitBlt(psoDest, psoSource, NULL, Clip, ColorTranslation, DestRect, SourcePoint, NULL, NULL, NULL, ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY)); goto cleanup; } // Determine clipping type if (!Clip) { clippingType = DC_TRIVIAL; } else { clippingType = Clip->iDComplexity; } BltInfo.DestSurface = psoDest; BltInfo.SourceSurface = psoSource; BltInfo.PatternSurface = NULL; BltInfo.XlateSourceToDest = ColorTranslation; BltInfo.Rop4 = ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY); switch (clippingType) { case DC_TRIVIAL: BltInfo.DestRect = *DestRect; BltInfo.SourcePoint = *SourcePoint; ret = DibFunctionsForBitmapFormat[psoDest->iBitmapFormat].DIB_BitBltSrcCopy(&BltInfo); break; case DC_RECT: // Clip the blt to the clip rectangle RECTL_bIntersectRect(&BltInfo.DestRect, DestRect, &Clip->rclBounds); BltInfo.SourcePoint.x = SourcePoint->x + BltInfo.DestRect.left - DestRect->left; BltInfo.SourcePoint.y = SourcePoint->y + BltInfo.DestRect.top - DestRect->top; ret = DibFunctionsForBitmapFormat[psoDest->iBitmapFormat].DIB_BitBltSrcCopy(&BltInfo); break; case DC_COMPLEX: CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_ANY, 0); do { EnumMore = CLIPOBJ_bEnum(Clip,(ULONG) sizeof(RectEnum), (PVOID) &RectEnum); if (RectEnum.c > 0) { RECTL* prclEnd = &RectEnum.arcl[RectEnum.c]; RECTL* prcl = &RectEnum.arcl[0]; do { RECTL_bIntersectRect(&BltInfo.DestRect, prcl, DestRect); BltInfo.SourcePoint.x = SourcePoint->x + BltInfo.DestRect.left - DestRect->left; BltInfo.SourcePoint.y = SourcePoint->y + BltInfo.DestRect.top - DestRect->top; if (!DibFunctionsForBitmapFormat[psoDest->iBitmapFormat].DIB_BitBltSrcCopy(&BltInfo)) { ret = FALSE; goto cleanup; } prcl++; } while (prcl < prclEnd); } } while (EnumMore); ret = TRUE; break; default: ASSERT(FALSE); ret = FALSE; break; } cleanup: return ret; }
/* * @implemented */ BOOL APIENTRY EngStretchBltROP( IN SURFOBJ *psoDest, IN SURFOBJ *psoSource, IN SURFOBJ *Mask, IN CLIPOBJ *ClipRegion, IN XLATEOBJ *ColorTranslation, IN COLORADJUSTMENT *pca, IN POINTL *BrushOrigin, IN RECTL *prclDest, IN RECTL *prclSrc, IN POINTL *MaskOrigin, IN ULONG Mode, IN BRUSHOBJ *pbo, IN ROP4 Rop4) { RECTL InputRect; RECTL OutputRect; POINTL Translate; INTENG_ENTER_LEAVE EnterLeaveSource; INTENG_ENTER_LEAVE EnterLeaveDest; SURFOBJ* psoInput; SURFOBJ* psoOutput; PSTRETCHRECTFUNC BltRectFunc; BOOLEAN Ret = TRUE; POINTL AdjustedBrushOrigin; BOOL UsesSource = ROP4_USES_SOURCE(Rop4); BYTE clippingType; RECTL ClipRect; RECT_ENUM RectEnum; BOOL EnumMore; ULONG Direction; RECTL CombinedRect; RECTL InputToCombinedRect; unsigned i; LONG DstHeight; LONG DstWidth; LONG SrcHeight; LONG SrcWidth; if (Rop4 == ROP4_NOOP) { /* Copy destination onto itself: nop */ return TRUE; } /* Determine clipping type */ if (ClipRegion == (CLIPOBJ *) NULL) { clippingType = DC_TRIVIAL; } else { clippingType = ClipRegion->iDComplexity; } OutputRect = *prclDest; if (OutputRect.right < OutputRect.left) { OutputRect.left = prclDest->right; OutputRect.right = prclDest->left; } if (OutputRect.bottom < OutputRect.top) { OutputRect.top = prclDest->bottom; OutputRect.bottom = prclDest->top; } if (UsesSource) { if (NULL == prclSrc) { return FALSE; } InputRect = *prclSrc; if (! IntEngEnter(&EnterLeaveSource, psoSource, &InputRect, TRUE, &Translate, &psoInput)) { return FALSE; } InputRect.left += Translate.x; InputRect.right += Translate.x; InputRect.top += Translate.y; InputRect.bottom += Translate.y; } else { InputRect.left = 0; InputRect.right = OutputRect.right - OutputRect.left; InputRect.top = 0; InputRect.bottom = OutputRect.bottom - OutputRect.top; psoInput = NULL; } if (NULL != ClipRegion) { if (OutputRect.left < ClipRegion->rclBounds.left) { InputRect.left += ClipRegion->rclBounds.left - OutputRect.left; OutputRect.left = ClipRegion->rclBounds.left; } if (ClipRegion->rclBounds.right < OutputRect.right) { InputRect.right -= OutputRect.right - ClipRegion->rclBounds.right; OutputRect.right = ClipRegion->rclBounds.right; } if (OutputRect.top < ClipRegion->rclBounds.top) { InputRect.top += ClipRegion->rclBounds.top - OutputRect.top; OutputRect.top = ClipRegion->rclBounds.top; } if (ClipRegion->rclBounds.bottom < OutputRect.bottom) { InputRect.bottom -= OutputRect.bottom - ClipRegion->rclBounds.bottom; OutputRect.bottom = ClipRegion->rclBounds.bottom; } } /* Check for degenerate case: if height or width of OutputRect is 0 pixels there's nothing to do */ if (OutputRect.right <= OutputRect.left || OutputRect.bottom <= OutputRect.top) { if (UsesSource) { IntEngLeave(&EnterLeaveSource); } return TRUE; } if (! IntEngEnter(&EnterLeaveDest, psoDest, &OutputRect, FALSE, &Translate, &psoOutput)) { if (UsesSource) { IntEngLeave(&EnterLeaveSource); } return FALSE; } OutputRect.left += Translate.x; OutputRect.right += Translate.x; OutputRect.top += Translate.y; OutputRect.bottom += Translate.y; if (BrushOrigin) { AdjustedBrushOrigin.x = BrushOrigin->x + Translate.x; AdjustedBrushOrigin.y = BrushOrigin->y + Translate.y; } else { AdjustedBrushOrigin = Translate; } BltRectFunc = CallDibStretchBlt; DstHeight = OutputRect.bottom - OutputRect.top; DstWidth = OutputRect.right - OutputRect.left; SrcHeight = InputRect.bottom - InputRect.top; SrcWidth = InputRect.right - InputRect.left; switch (clippingType) { case DC_TRIVIAL: Ret = (*BltRectFunc)(psoOutput, psoInput, Mask, ColorTranslation, &OutputRect, &InputRect, MaskOrigin, pbo, &AdjustedBrushOrigin, Rop4); break; case DC_RECT: // Clip the blt to the clip rectangle ClipRect.left = ClipRegion->rclBounds.left + Translate.x; ClipRect.right = ClipRegion->rclBounds.right + Translate.x; ClipRect.top = ClipRegion->rclBounds.top + Translate.y; ClipRect.bottom = ClipRegion->rclBounds.bottom + Translate.y; if (RECTL_bIntersectRect(&CombinedRect, &OutputRect, &ClipRect)) { InputToCombinedRect.top = InputRect.top + (CombinedRect.top - OutputRect.top) * SrcHeight / DstHeight; InputToCombinedRect.bottom = InputRect.top + (CombinedRect.bottom - OutputRect.top) * SrcHeight / DstHeight; InputToCombinedRect.left = InputRect.left + (CombinedRect.left - OutputRect.left) * SrcWidth / DstWidth; InputToCombinedRect.right = InputRect.left + (CombinedRect.right - OutputRect.left) * SrcWidth / DstWidth; Ret = (*BltRectFunc)(psoOutput, psoInput, Mask, ColorTranslation, &CombinedRect, &InputToCombinedRect, MaskOrigin, pbo, &AdjustedBrushOrigin, Rop4); } break; case DC_COMPLEX: if (psoOutput == psoInput) { if (OutputRect.top < InputRect.top) { Direction = OutputRect.left < InputRect.left ? CD_RIGHTDOWN : CD_LEFTDOWN; } else { Direction = OutputRect.left < InputRect.left ? CD_RIGHTUP : CD_LEFTUP; } } else { Direction = CD_ANY; } CLIPOBJ_cEnumStart(ClipRegion, FALSE, CT_RECTANGLES, Direction, 0); do { EnumMore = CLIPOBJ_bEnum(ClipRegion,(ULONG) sizeof(RectEnum), (PVOID) &RectEnum); for (i = 0; i < RectEnum.c; i++) { ClipRect.left = RectEnum.arcl[i].left + Translate.x; ClipRect.right = RectEnum.arcl[i].right + Translate.x; ClipRect.top = RectEnum.arcl[i].top + Translate.y; ClipRect.bottom = RectEnum.arcl[i].bottom + Translate.y; if (RECTL_bIntersectRect(&CombinedRect, &OutputRect, &ClipRect)) { InputToCombinedRect.top = InputRect.top + (CombinedRect.top - OutputRect.top) * SrcHeight / DstHeight; InputToCombinedRect.bottom = InputRect.top + (CombinedRect.bottom - OutputRect.top) * SrcHeight / DstHeight; InputToCombinedRect.left = InputRect.left + (CombinedRect.left - OutputRect.left) * SrcWidth / DstWidth; InputToCombinedRect.right = InputRect.left + (CombinedRect.right - OutputRect.left) * SrcWidth / DstWidth; Ret = (*BltRectFunc)(psoOutput, psoInput, Mask, ColorTranslation, &CombinedRect, &InputToCombinedRect, MaskOrigin, pbo, &AdjustedBrushOrigin, Rop4); } } } while (EnumMore); break; } IntEngLeave(&EnterLeaveDest); if (UsesSource) { IntEngLeave(&EnterLeaveSource); } return Ret; }
BOOL APIENTRY IntEngStretchBlt(SURFOBJ *psoDest, SURFOBJ *psoSource, SURFOBJ *MaskSurf, CLIPOBJ *ClipRegion, XLATEOBJ *ColorTranslation, COLORADJUSTMENT *pca, RECTL *DestRect, RECTL *SourceRect, POINTL *pMaskOrigin, BRUSHOBJ *pbo, POINTL *BrushOrigin, DWORD Rop4) { BOOLEAN ret; POINTL MaskOrigin = {0, 0}; SURFACE *psurfDest; //SURFACE *psurfSource = NULL; RECTL InputClippedRect; RECTL InputRect; RECTL OutputRect; BOOL UsesSource = ROP4_USES_SOURCE(Rop4); LONG InputClWidth, InputClHeight, InputWidth, InputHeight; ASSERT(psoDest); //ASSERT(psoSource); // FIXME! ASSERT(DestRect); //ASSERT(SourceRect); // FIXME! //ASSERT(!RECTL_bIsEmptyRect(SourceRect)); // FIXME! /* If no clip object is given, use trivial one */ if (!ClipRegion) ClipRegion = &gxcoTrivial.ClipObj; psurfDest = CONTAINING_RECORD(psoDest, SURFACE, SurfObj); /* Sanity check */ ASSERT(IS_VALID_ROP4(Rop4)); /* Check if source and dest size are equal */ if (((DestRect->right - DestRect->left) == (SourceRect->right - SourceRect->left)) && ((DestRect->bottom - DestRect->top) == (SourceRect->bottom - SourceRect->top))) { /* Pass the request to IntEngBitBlt */ return IntEngBitBlt(psoDest, psoSource, MaskSurf, ClipRegion, ColorTranslation, DestRect, (PPOINTL)SourceRect, pMaskOrigin, pbo, BrushOrigin, Rop4); } InputClippedRect = *DestRect; if (InputClippedRect.right < InputClippedRect.left) { InputClippedRect.left = DestRect->right; InputClippedRect.right = DestRect->left; } if (InputClippedRect.bottom < InputClippedRect.top) { InputClippedRect.top = DestRect->bottom; InputClippedRect.bottom = DestRect->top; } if (NULL == SourceRect || NULL == psoSource) { return FALSE; } InputRect = *SourceRect; if (InputRect.right < InputRect.left || InputRect.bottom < InputRect.top) { /* Everything clipped away, nothing to do */ return TRUE; } if (ClipRegion->iDComplexity != DC_TRIVIAL) { if (!RECTL_bIntersectRect(&OutputRect, &InputClippedRect, &ClipRegion->rclBounds)) { return TRUE; } /* Update source rect */ InputClWidth = InputClippedRect.right - InputClippedRect.left; InputClHeight = InputClippedRect.bottom - InputClippedRect.top; InputWidth = InputRect.right - InputRect.left; InputHeight = InputRect.bottom - InputRect.top; InputRect.left += (InputWidth * (OutputRect.left - InputClippedRect.left)) / InputClWidth; InputRect.right -= (InputWidth * (InputClippedRect.right - OutputRect.right)) / InputClWidth; InputRect.top += (InputHeight * (OutputRect.top - InputClippedRect.top)) / InputClHeight; InputRect.bottom -= (InputHeight * (InputClippedRect.bottom - OutputRect.bottom)) / InputClHeight; } else { OutputRect = InputClippedRect; } if (pMaskOrigin != NULL) { MaskOrigin.x = pMaskOrigin->x; MaskOrigin.y = pMaskOrigin->y; } /* No success yet */ ret = FALSE; if (UsesSource) { //psurfSource = CONTAINING_RECORD(psoSource, SURFACE, SurfObj); } /* Call the driver's DrvStretchBlt if available */ if (psurfDest->flags & HOOK_STRETCHBLTROP) { /* Drv->StretchBltROP (look at http://www.osronline.com/ddkx/graphics/ddifncs_0z3b.htm ) */ ret = GDIDEVFUNCS(psoDest).StretchBltROP(psoDest, psoSource, MaskSurf, ClipRegion, ColorTranslation, pca, BrushOrigin, &OutputRect, &InputRect, &MaskOrigin, COLORONCOLOR, pbo, Rop4); } if (! ret) { ret = EngStretchBltROP(psoDest, psoSource, MaskSurf, ClipRegion, ColorTranslation, pca, BrushOrigin, &OutputRect, &InputRect, &MaskOrigin, COLORONCOLOR, pbo, Rop4); } return ret; }
BOOL FASTCALL IntEngGradientFillTriangle( IN SURFOBJ *psoDest, IN CLIPOBJ *pco, IN XLATEOBJ *pxlo, IN TRIVERTEX *pVertex, IN ULONG nVertex, IN PGRADIENT_TRIANGLE gTriangle, IN RECTL *prclExtents, IN POINTL *pptlDitherOrg) { SURFOBJ *psoOutput; PTRIVERTEX v1, v2, v3; RECT_ENUM RectEnum; BOOL EnumMore; ULONG i; POINTL Translate; INTENG_ENTER_LEAVE EnterLeave; RECTL FillRect = { 0, 0, 0, 0 }; ULONG Color; BOOL sx[NLINES]; LONG x[NLINES], dx[NLINES], dy[NLINES], incx[NLINES], ex[NLINES], destx[NLINES]; LONG c[NLINES][3], dc[NLINES][3], ec[NLINES][3], ic[NLINES][3]; /* colors on lines */ LONG g, gx, gxi, gc[3], gd[3], ge[3], gi[3]; /* colors in triangle */ LONG sy, y, bt; v1 = (pVertex + gTriangle->Vertex1); v2 = (pVertex + gTriangle->Vertex2); v3 = (pVertex + gTriangle->Vertex3); /* bubble sort */ if (SMALLER(v2, v1)) { TRIVERTEX *t; SWAP(v1, v2, t); } if (SMALLER(v3, v2)) { TRIVERTEX *t; SWAP(v2, v3, t); if (SMALLER(v2, v1)) { SWAP(v1, v2, t); } } DPRINT("Triangle: (%i,%i) (%i,%i) (%i,%i)\n", v1->x, v1->y, v2->x, v2->y, v3->x, v3->y); /* FIXME: commented out because of an endless loop - fix triangles first */ DPRINT("FIXME: IntEngGradientFillTriangle is broken\n"); if (!IntEngEnter(&EnterLeave, psoDest, &FillRect, FALSE, &Translate, &psoOutput)) { return FALSE; } if (VCMPCLRS(v1, v2, v3)) { CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_RIGHTDOWN, 0); do { EnumMore = CLIPOBJ_bEnum(pco, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); for (i = 0; i < RectEnum.c && RectEnum.arcl[i].top <= prclExtents->bottom; i++) { if (RECTL_bIntersectRect(&FillRect, &RectEnum.arcl[i], prclExtents)) { BOOL InY; DOINIT(v1, v3, 0); DOINIT(v1, v2, 1); DOINIT(v2, v3, 2); y = v1->y; sy = v1->y + pptlDitherOrg->y; bt = min(v3->y + pptlDitherOrg->y, FillRect.bottom); while (sy < bt) { InY = !(sy < FillRect.top || sy >= FillRect.bottom); GOLINE(v1, v3, 0); DOLINE(v1, v3, 0); ENDLINE(v1, v3, 0); GOLINE(v1, v2, 1); DOLINE(v1, v2, 1); FILLLINE(0, 1); ENDLINE(v1, v2, 1); GOLINE(v2, v3, 2); DOLINE(v2, v3, 2); FILLLINE(0, 2); ENDLINE(23, v3, 2); y++; sy++; } } } } while (EnumMore); return IntEngLeave(&EnterLeave); } /* fill triangle with one solid color */ Color = XLATEOBJ_iXlate(pxlo, RGB(v1->Red >> 8, v1->Green >> 8, v1->Blue >> 8)); CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_RIGHTDOWN, 0); do { EnumMore = CLIPOBJ_bEnum(pco, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); for (i = 0; i < RectEnum.c && RectEnum.arcl[i].top <= prclExtents->bottom; i++) { if (RECTL_bIntersectRect(&FillRect, &RectEnum.arcl[i], prclExtents)) { S_INITLINE(v1, v3, 0); S_INITLINE(v1, v2, 1); S_INITLINE(v2, v3, 2); y = v1->y; sy = v1->y + pptlDitherOrg->y; bt = min(v3->y + pptlDitherOrg->y, FillRect.bottom); while (sy < bt) { S_GOLINE(v1, v3, 0); S_DOLINE(v1, v3, 0); S_ENDLINE(v1, v3, 0); S_GOLINE(v1, v2, 1); S_DOLINE(v1, v2, 1); S_FILLLINE(0, 1); S_ENDLINE(v1, v2, 1); S_GOLINE(v2, v3, 2); S_DOLINE(v2, v3, 2); S_FILLLINE(0, 2); S_ENDLINE(23, v3, 2); y++; sy++; } } } } while (EnumMore); return IntEngLeave(&EnterLeave); }