Beispiel #1
0
int FASTCALL
CLIPPING_UpdateGCRegion(DC* Dc)
{
   PROSRGNDATA CombinedRegion;
   HRGN hRgnVis;
   PREGION prgnClip, prgnGCClip;

    // would prefer this, but the rest of the code sucks
//    ASSERT(Dc->rosdc.hGCClipRgn);
//    ASSERT(Dc->rosdc.hClipRgn);
   ASSERT(Dc->prgnVis);
   hRgnVis = Dc->prgnVis->BaseObject.hHmgr;

   if (Dc->rosdc.hGCClipRgn == NULL)
      Dc->rosdc.hGCClipRgn = IntSysCreateRectRgn(0, 0, 0, 0);

   prgnGCClip = REGION_LockRgn(Dc->rosdc.hGCClipRgn);
   ASSERT(prgnGCClip);

   if (Dc->rosdc.hClipRgn == NULL)
      IntGdiCombineRgn(prgnGCClip, Dc->prgnVis, NULL, RGN_COPY);
   else
   {
      prgnClip = REGION_LockRgn(Dc->rosdc.hClipRgn); // FIXME: locking order, ugh
      IntGdiCombineRgn(prgnGCClip, Dc->prgnVis, prgnClip, RGN_AND);
      REGION_UnlockRgn(prgnClip);
   }
   REGION_UnlockRgn(prgnGCClip);

   NtGdiOffsetRgn(Dc->rosdc.hGCClipRgn, Dc->ptlDCOrig.x, Dc->ptlDCOrig.y);

   if((CombinedRegion = RGNOBJAPI_Lock(Dc->rosdc.hGCClipRgn, NULL)))
   {
     CLIPOBJ *CombinedClip;

     CombinedClip = IntEngCreateClipRegion(CombinedRegion->rdh.nCount,
        CombinedRegion->Buffer,
        &CombinedRegion->rdh.rcBound);

     RGNOBJAPI_Unlock(CombinedRegion);

     if ( !CombinedClip )
     {
       DPRINT1("IntEngCreateClipRegion() failed\n");
       return ERROR;
     }

     if(Dc->rosdc.CombinedClip != NULL)
       IntEngDeleteClipRegion(Dc->rosdc.CombinedClip);

      Dc->rosdc.CombinedClip = CombinedClip ;
   }

   return NtGdiOffsetRgn(Dc->rosdc.hGCClipRgn, -Dc->ptlDCOrig.x, -Dc->ptlDCOrig.y);
}
Beispiel #2
0
/*
 * @implemented
 *
 */
INT
WINAPI
OffsetRgn( HRGN hrgn,
           int nXOffset,
           int nYOffset)
{
    PRGN_ATTR pRgn_Attr;
    int nLeftRect, nTopRect, nRightRect, nBottomRect;

// HACKFIX
//  if (!GdiGetHandleUserData((HGDIOBJ) hrgn, GDI_OBJECT_TYPE_REGION, (PVOID) &pRgn_Attr))
    return NtGdiOffsetRgn(hrgn,nXOffset,nYOffset);

    if ( pRgn_Attr->iComplexity == NULLREGION)
        return pRgn_Attr->iComplexity;

    if ( pRgn_Attr->iComplexity != SIMPLEREGION)
        return NtGdiOffsetRgn(hrgn,nXOffset,nYOffset);

    nLeftRect   = pRgn_Attr->Rect.left;
    nTopRect    = pRgn_Attr->Rect.top;
    nRightRect  = pRgn_Attr->Rect.right;
    nBottomRect = pRgn_Attr->Rect.bottom;

    if (nLeftRect < nRightRect)
    {
        if (nTopRect < nBottomRect)
        {
            nLeftRect   = nXOffset + nLeftRect;
            nTopRect    = nYOffset + nTopRect;
            nRightRect  = nXOffset + nRightRect;
            nBottomRect = nYOffset + nBottomRect;

            /* Check 28 bit limit. Chp 9 Areas, pg 560. */
            if ( nLeftRect   < -(1<<27)  ||
                    nTopRect    < -(1<<27)  ||
                    nRightRect  > (1<<27)-1 ||
                    nBottomRect > (1<<27)-1  )
            {
                return ERROR;
            }

            pRgn_Attr->Rect.top    = nTopRect;
            pRgn_Attr->Rect.left   = nLeftRect;
            pRgn_Attr->Rect.right  = nRightRect;
            pRgn_Attr->Rect.bottom = nBottomRect;
            pRgn_Attr->AttrFlags |= ATTR_RGN_DIRTY;
        }
    }
    return pRgn_Attr->iComplexity;
}
Beispiel #3
0
VOID FASTCALL
co_VIS_WindowLayoutChanged(
   PWND Wnd,
   HRGN NewlyExposed)
{
   HRGN Temp;
   PWND Parent;
   USER_REFERENCE_ENTRY Ref;

   ASSERT_REFS_CO(Wnd);

   Parent = Wnd->spwndParent;
   if(Parent)
   {
      Temp = IntSysCreateRectRgn(0, 0, 0, 0);

      NtGdiCombineRgn(Temp, NewlyExposed, NULL, RGN_COPY);
      NtGdiOffsetRgn(Temp,
                     Wnd->rcWindow.left - Parent->rcClient.left,
                     Wnd->rcWindow.top - Parent->rcClient.top);

      UserRefObjectCo(Parent, &Ref);
      co_UserRedrawWindow(Parent, NULL, Temp,
                          RDW_FRAME | RDW_ERASE | RDW_INVALIDATE |
                          RDW_ALLCHILDREN);
      UserDerefObjectCo(Parent);

      GreDeleteObject(Temp);
   }
}
Beispiel #4
0
int APIENTRY NtGdiOffsetClipRgn(HDC  hDC,
                       int  XOffset,
                       int  YOffset)
{
  INT Result;
  DC *dc;

  if(!(dc = DC_LockDc(hDC)))
  {
    EngSetLastError(ERROR_INVALID_HANDLE);
    return ERROR;
  }

  if(dc->rosdc.hClipRgn != NULL)
  {
    Result = NtGdiOffsetRgn(dc->rosdc.hClipRgn,
                            XOffset,
                            YOffset);
    CLIPPING_UpdateGCRegion(dc);
  }
  else
  {
    Result = NULLREGION;
  }

  DC_UnlockDc(dc);
  return Result;
}
Beispiel #5
0
HRGN FASTCALL
VIS_ComputeVisibleRegion(
   PWND Wnd,
   BOOLEAN ClientArea,
   BOOLEAN ClipChildren,
   BOOLEAN ClipSiblings)
{
   HRGN VisRgn, ClipRgn;
   PWND PreviousWindow, CurrentWindow, CurrentSibling;

   if (!Wnd || !(Wnd->style & WS_VISIBLE))
   {
      return NULL;
   }

   VisRgn = NULL;

   if (ClientArea)
   {
      VisRgn = IntSysCreateRectRgnIndirect(&Wnd->rcClient);
   }
   else
   {
      VisRgn = IntSysCreateRectRgnIndirect(&Wnd->rcWindow);
   }

   /*
    * Walk through all parent windows and for each clip the visble region
    * to the parent's client area and exclude all siblings that are over
    * our window.
    */

   PreviousWindow = Wnd;
   CurrentWindow = Wnd->spwndParent;
   while (CurrentWindow)
   {
      if ( CurrentWindow->state2 & WNDS2_INDESTROY ||
           CurrentWindow->state & WNDS_DESTROYED )
      {
         ERR("ATM the Current Window or Parent is dead!\n");
         if (VisRgn) GreDeleteObject(VisRgn);
         return NULL;
      }

      if (!(CurrentWindow->style & WS_VISIBLE))
      {
         if (VisRgn) GreDeleteObject(VisRgn);
         return NULL;
      }

      ClipRgn = IntSysCreateRectRgnIndirect(&CurrentWindow->rcClient);
      NtGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_AND);
      GreDeleteObject(ClipRgn);

      if ((PreviousWindow->style & WS_CLIPSIBLINGS) ||
          (PreviousWindow == Wnd && ClipSiblings))
      {
         CurrentSibling = CurrentWindow->spwndChild;
         while ( CurrentSibling != NULL &&
                 CurrentSibling != PreviousWindow )
         {
            if ((CurrentSibling->style & WS_VISIBLE) &&
                !(CurrentSibling->ExStyle & WS_EX_TRANSPARENT))
            {
               ClipRgn = IntSysCreateRectRgnIndirect(&CurrentSibling->rcWindow);
               /* Combine it with the window region if available */
               if (CurrentSibling->hrgnClip && !(CurrentSibling->style & WS_MINIMIZE))
               {
                  NtGdiOffsetRgn(ClipRgn, -CurrentSibling->rcWindow.left, -CurrentSibling->rcWindow.top);
                  NtGdiCombineRgn(ClipRgn, ClipRgn, CurrentSibling->hrgnClip, RGN_AND);
                  NtGdiOffsetRgn(ClipRgn, CurrentSibling->rcWindow.left, CurrentSibling->rcWindow.top);
               }
               NtGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_DIFF);
               GreDeleteObject(ClipRgn);
            }
            CurrentSibling = CurrentSibling->spwndNext;
         }
      }

      PreviousWindow = CurrentWindow;
      CurrentWindow = CurrentWindow->spwndParent;
   }

   if (ClipChildren)
   {
      CurrentWindow = Wnd->spwndChild;
      while (CurrentWindow)
      {
         if ((CurrentWindow->style & WS_VISIBLE) &&
             !(CurrentWindow->ExStyle & WS_EX_TRANSPARENT))
         {
            ClipRgn = IntSysCreateRectRgnIndirect(&CurrentWindow->rcWindow);
            /* Combine it with the window region if available */
            if (CurrentWindow->hrgnClip && !(CurrentWindow->style & WS_MINIMIZE))
            {
               NtGdiOffsetRgn(ClipRgn, -CurrentWindow->rcWindow.left, -CurrentWindow->rcWindow.top);
               NtGdiCombineRgn(ClipRgn, ClipRgn, CurrentWindow->hrgnClip, RGN_AND);
               NtGdiOffsetRgn(ClipRgn, CurrentWindow->rcWindow.left, CurrentWindow->rcWindow.top);
            }
            NtGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_DIFF);
            GreDeleteObject(ClipRgn);
         }
         CurrentWindow = CurrentWindow->spwndNext;
      }
   }

   if (Wnd->hrgnClip && !(Wnd->style & WS_MINIMIZE))
   {
      NtGdiOffsetRgn(VisRgn, -Wnd->rcWindow.left, -Wnd->rcWindow.top);
      NtGdiCombineRgn(VisRgn, VisRgn, Wnd->hrgnClip, RGN_AND);
      NtGdiOffsetRgn(VisRgn, Wnd->rcWindow.left, Wnd->rcWindow.top);
   }

   return VisRgn;
}
Beispiel #6
0
/* See wine, msdn, osr and  Feng Yuan - Windows Graphics Programming Win32 Gdi And Directdraw

   1st: http://www.codeproject.com/gdi/cliprgnguide.asp is wrong!

   The intersection of the clip with the meta region is not Rao it's API!
   Go back and read 7.2 Clipping pages 418-19:
   Rao = API & Vis:
   1) The Rao region is the intersection of the API region and the system region,
      named after the Microsoft engineer who initially proposed it.
   2) The Rao region can be calculated from the API region and the system region.

   API:
      API region is the intersection of the meta region and the clipping region,
      clearly named after the fact that it is controlled by GDI API calls.
*/
INT
APIENTRY
NtGdiGetRandomRgn(
    HDC hdc,
    HRGN hrgnDest,
    INT iCode)
{
    INT ret = 0;
    PDC pdc;
    HRGN hrgnSrc = NULL;
    POINTL ptlOrg;

    pdc = DC_LockDc(hdc);
    if (!pdc)
    {
        EngSetLastError(ERROR_INVALID_PARAMETER);
        return -1;
    }

    switch (iCode)
    {
        case CLIPRGN:
            hrgnSrc = pdc->rosdc.hClipRgn;
//            if (pdc->dclevel.prgnClip) hrgnSrc = pdc->dclevel.prgnClip->BaseObject.hHmgr;
            break;
        case METARGN:
            if (pdc->dclevel.prgnMeta)
                hrgnSrc = pdc->dclevel.prgnMeta->BaseObject.hHmgr;
            break;
        case APIRGN:
            if (pdc->prgnAPI) hrgnSrc = pdc->prgnAPI->BaseObject.hHmgr;
//            else if (pdc->dclevel.prgnClip) hrgnSrc = pdc->dclevel.prgnClip->BaseObject.hHmgr;
            else if (pdc->rosdc.hClipRgn) hrgnSrc = pdc->rosdc.hClipRgn;
            else if (pdc->dclevel.prgnMeta) hrgnSrc = pdc->dclevel.prgnMeta->BaseObject.hHmgr;
            break;
        case SYSRGN:
            if (pdc->prgnVis)
            {
                PREGION prgnDest = REGION_LockRgn(hrgnDest);
                ret = IntGdiCombineRgn(prgnDest, pdc->prgnVis, 0, RGN_COPY) == ERROR ? -1 : 1;
                REGION_UnlockRgn(prgnDest);
            }
            break;
        default:
            hrgnSrc = NULL;
    }

    if (hrgnSrc)
    {
        ret = NtGdiCombineRgn(hrgnDest, hrgnSrc, 0, RGN_COPY) == ERROR ? -1 : 1;
    }

    if (iCode == SYSRGN)
    {
        ptlOrg = pdc->ptlDCOrig;
        NtGdiOffsetRgn(hrgnDest, ptlOrg.x, ptlOrg.y );
    }

    DC_UnlockDc(pdc);

    return ret;
}
Beispiel #7
0
VOID FASTCALL
DceResetActiveDCEs(PWND Window)
{
   DCE *pDCE;
   PDC dc;
   PWND CurrentWindow;
   INT DeltaX;
   INT DeltaY;
   PLIST_ENTRY ListEntry;

   if (NULL == Window)
   {
      return;
   }

   ListEntry = LEDce.Flink;
   while (ListEntry != &LEDce)
   {
      pDCE = CONTAINING_RECORD(ListEntry, DCE, List);
      ListEntry = ListEntry->Flink;
      if (0 == (pDCE->DCXFlags & (DCX_DCEEMPTY|DCX_INDESTROY)))
      {
         if (Window->head.h == pDCE->hwndCurrent)
         {
            CurrentWindow = Window;
         }
         else
         {
            if (!pDCE->hwndCurrent)
               CurrentWindow = NULL;
            else
               CurrentWindow = UserGetWindowObject(pDCE->hwndCurrent);
            if (NULL == CurrentWindow)
            {
               continue;
            }
         }

         if (!GreIsHandleValid(pDCE->hDC) ||
             (dc = DC_LockDc(pDCE->hDC)) == NULL)
         {
            continue;
         }
         if (Window == CurrentWindow || IntIsChildWindow(Window, CurrentWindow))
         {
            if (pDCE->DCXFlags & DCX_WINDOW)
            {
               DeltaX = CurrentWindow->rcWindow.left - dc->ptlDCOrig.x;
               DeltaY = CurrentWindow->rcWindow.top - dc->ptlDCOrig.y;
               dc->ptlDCOrig.x = CurrentWindow->rcWindow.left;
               dc->ptlDCOrig.y = CurrentWindow->rcWindow.top;
            }
            else
            {
               DeltaX = CurrentWindow->rcClient.left - dc->ptlDCOrig.x;
               DeltaY = CurrentWindow->rcClient.top - dc->ptlDCOrig.y;
               dc->ptlDCOrig.x = CurrentWindow->rcClient.left;
               dc->ptlDCOrig.y = CurrentWindow->rcClient.top;
            }

            if (NULL != dc->dclevel.prgnClip)
            {
               REGION_bOffsetRgn(dc->dclevel.prgnClip, DeltaX, DeltaY);
               dc->fs |= DC_FLAG_DIRTY_RAO;
            }
            if (NULL != pDCE->hrgnClip)
            {
               NtGdiOffsetRgn(pDCE->hrgnClip, DeltaX, DeltaY);
            }
         }
         DC_UnlockDc(dc);

         DceUpdateVisRgn(pDCE, CurrentWindow, pDCE->DCXFlags);
         IntGdiSetHookFlags(pDCE->hDC, DCHF_VALIDATEVISRGN);
      }
   }
}
Beispiel #8
0
/*
 * Fills the CLIPOBJ and client rect of the WNDOBJ with the data from the given WND
 */
BOOLEAN
FASTCALL
IntEngWndUpdateClipObj(
  WNDGDI *WndObjInt,
  PWND Window)
{
  HRGN hVisRgn;
  PROSRGNDATA visRgn;
  CLIPOBJ *ClipObj = NULL;
  CLIPOBJ *OldClipObj;

  DPRINT("IntEngWndUpdateClipObj\n");

  hVisRgn = VIS_ComputeVisibleRegion(Window, TRUE, TRUE, TRUE);
  if (hVisRgn != NULL)
  {
    NtGdiOffsetRgn(hVisRgn, Window->rcClient.left, Window->rcClient.top);
    visRgn = RGNOBJAPI_Lock(hVisRgn, NULL);
    if (visRgn != NULL)
    {
      if (visRgn->rdh.nCount > 0)
      {
        ClipObj = IntEngCreateClipRegion(visRgn->rdh.nCount, visRgn->Buffer,
                                         &visRgn->rdh.rcBound);
        DPRINT("Created visible region with %lu rects\n", visRgn->rdh.nCount);
        DPRINT("  BoundingRect: %d, %d  %d, %d\n",
               visRgn->rdh.rcBound.left, visRgn->rdh.rcBound.top,
               visRgn->rdh.rcBound.right, visRgn->rdh.rcBound.bottom);
        {
          ULONG i;
          for (i = 0; i < visRgn->rdh.nCount; i++)
          {
            DPRINT("  Rect #%lu: %ld,%ld  %ld,%ld\n", i+1,
                   visRgn->Buffer[i].left, visRgn->Buffer[i].top,
                   visRgn->Buffer[i].right, visRgn->Buffer[i].bottom);
          }
        }
      }
      RGNOBJAPI_Unlock(visRgn);
    }
    else
    {
      DPRINT1("Warning: Couldn't lock visible region of window DC\n");
    }
    GreDeleteObject(hVisRgn);
  }
  else
  {
    DPRINT1("Warning: VIS_ComputeVisibleRegion failed!\n");
  }

  if (ClipObj == NULL)
  {
    /* Fall back to client rect */
    ClipObj = IntEngCreateClipRegion(1, &Window->rcClient,
                                     &Window->rcClient);
  }

  if (ClipObj == NULL)
  {
    DPRINT1("Warning: IntEngCreateClipRegion() failed!\n");
    return FALSE;
  }

  RtlCopyMemory(&WndObjInt->WndObj.coClient, ClipObj, sizeof (CLIPOBJ));
  RtlCopyMemory(&WndObjInt->WndObj.rclClient, &Window->rcClient, sizeof (RECT));
  OldClipObj = InterlockedExchangePointer((PVOID*)&WndObjInt->ClientClipObj, ClipObj);
  if (OldClipObj != NULL)
    IntEngDeleteClipRegion(OldClipObj);

  return TRUE;
}