Beispiel #1
0
HPALETTE
FASTCALL
GdiSelectPalette(
    HDC hDC,
    HPALETTE hpal,
    BOOL ForceBackground)
{
    PDC pdc;
    HPALETTE oldPal = NULL;
    PPALETTE ppal;

    // FIXME: mark the palette as a [fore\back]ground pal
    pdc = DC_LockDc(hDC);
    if (!pdc)
    {
        return NULL;
    }

    /* Check if this is a valid palette handle */
    ppal = PALETTE_ShareLockPalette(hpal);
    if (!ppal)
    {
        DC_UnlockDc(pdc);
        return NULL;
    }

    /* Is this a valid palette for this depth? */
	if ((BitsPerFormat(pdc->dclevel.pSurface->SurfObj.iBitmapFormat) <= 8
					&& (ppal->flFlags & PAL_INDEXED)) ||
			(BitsPerFormat(pdc->dclevel.pSurface->SurfObj.iBitmapFormat) > 8))
    {
        /* Get old palette, set new one */
        oldPal = pdc->dclevel.hpal;
        pdc->dclevel.hpal = hpal;
        DC_vSelectPalette(pdc, ppal);

        /* Mark the brushes invalid */
        pdc->pdcattr->ulDirty_ |= DIRTY_FILL | DIRTY_LINE |
                                  DIRTY_BACKGROUND | DIRTY_TEXT;
    }

    if(pdc->dctype == DCTYPE_MEMORY)
    {
        // This didn't work anyway
        //IntGdiRealizePalette(hDC);
    }

    PALETTE_ShareUnlockPalette(ppal);
    DC_UnlockDc(pdc);

    return oldPal;
}
Beispiel #2
0
void
NTAPI
UnsafeSetBitmapBits(
    PSURFACE psurf,
    IN ULONG cjBits,
    IN PVOID pvBits)
{
    PUCHAR pjDst, pjSrc;
    LONG lDeltaDst, lDeltaSrc;
    ULONG nWidth, nHeight, cBitsPixel;

    nWidth = psurf->SurfObj.sizlBitmap.cx;
    nHeight = psurf->SurfObj.sizlBitmap.cy;
    cBitsPixel = BitsPerFormat(psurf->SurfObj.iBitmapFormat);

    /* Get pointers */
    pjDst = psurf->SurfObj.pvScan0;
    pjSrc = pvBits;
    lDeltaDst = psurf->SurfObj.lDelta;
    lDeltaSrc = WIDTH_BYTES_ALIGN16(nWidth, cBitsPixel);

    while (nHeight--)
    {
        /* Copy one line */
        memcpy(pjDst, pjSrc, lDeltaSrc);
        pjSrc += lDeltaSrc;
        pjDst += lDeltaDst;
    }

}
Beispiel #3
0
/**
 * This function is not exported, because it makes no sense for
 * The driver to punt back to this function */
BOOL
APIENTRY
EngRealizeBrush(
    BRUSHOBJ *pbo,
    SURFOBJ  *psoDst,
    SURFOBJ  *psoPattern,
    SURFOBJ  *psoMask,
    XLATEOBJ *pxlo,
    ULONG    iHatch)
{
    EBRUSHOBJ *pebo;
    HBITMAP hbmpRealize;
    SURFOBJ *psoRealize;
    PSURFACE psurfRealize;
    POINTL ptlSrc = {0, 0};
    RECTL rclDest;
    ULONG lWidth;

    /* Calculate width in bytes of the realized brush */
    lWidth = WIDTH_BYTES_ALIGN32(psoPattern->sizlBitmap.cx,
                                  BitsPerFormat(psoDst->iBitmapFormat));

    /* Allocate a bitmap */
    hbmpRealize = EngCreateBitmap(psoPattern->sizlBitmap,
                                  lWidth,
                                  psoDst->iBitmapFormat,
                                  BMF_NOZEROINIT,
                                  NULL);
    if (!hbmpRealize)
    {
        return FALSE;
    }

    /* Lock the bitmap */
    psurfRealize = SURFACE_ShareLockSurface(hbmpRealize);

    /* Already delete the pattern bitmap (will be kept until dereferenced) */
    EngDeleteSurface((HSURF)hbmpRealize);

    if (!psurfRealize)
    {
        return FALSE;
    }

    /* Copy the bits to the new format bitmap */
    rclDest.left = rclDest.top = 0;
    rclDest.right = psoPattern->sizlBitmap.cx;
    rclDest.bottom = psoPattern->sizlBitmap.cy;
    psoRealize = &psurfRealize->SurfObj;
    EngCopyBits(psoRealize, psoPattern, NULL, pxlo, &rclDest, &ptlSrc);


    pebo = CONTAINING_RECORD(pbo, EBRUSHOBJ, BrushObject);
    pebo->pengbrush = (PVOID)psurfRealize;

    return TRUE;
}
Beispiel #4
0
BOOL
NTAPI
UnsafeSetBitmapBits(
    _Inout_ PSURFACE psurf,
    _In_ ULONG cjBits,
    _In_ const VOID *pvBits)
{
    PUCHAR pjDst;
    const UCHAR *pjSrc;
    LONG lDeltaDst, lDeltaSrc;
    ULONG nWidth, nHeight, cBitsPixel;
    NT_ASSERT(psurf->flags & API_BITMAP);
    NT_ASSERT(psurf->SurfObj.iBitmapFormat <= BMF_32BPP);

    nWidth = psurf->SurfObj.sizlBitmap.cx;
    nHeight = psurf->SurfObj.sizlBitmap.cy;
    cBitsPixel = BitsPerFormat(psurf->SurfObj.iBitmapFormat);

    /* Get pointers */
    pjDst = psurf->SurfObj.pvScan0;
    pjSrc = pvBits;
    lDeltaDst = psurf->SurfObj.lDelta;
    lDeltaSrc = WIDTH_BYTES_ALIGN16(nWidth, cBitsPixel);
    NT_ASSERT(lDeltaSrc <= abs(lDeltaDst));

    /* Make sure the buffer is large enough*/
    if (cjBits < (lDeltaSrc * nHeight))
        return FALSE;

    while (nHeight--)
    {
        /* Copy one line */
        memcpy(pjDst, pjSrc, lDeltaSrc);
        pjSrc += lDeltaSrc;
        pjDst += lDeltaDst;
    }

    return TRUE;
}
Beispiel #5
0
/*
 * @implemented
 */
ULONG
APIENTRY
EngSetPointerShape(
    _In_ SURFOBJ *pso,
    _In_opt_ SURFOBJ *psoMask,
    _In_opt_ SURFOBJ *psoColor,
    _In_opt_ XLATEOBJ *pxlo,
    _In_ LONG xHot,
    _In_ LONG yHot,
    _In_ LONG x,
    _In_ LONG y,
    _In_ RECTL *prcl,
    _In_ FLONG fl)
{
    PDEVOBJ *ppdev;
    GDIPOINTER *pgp;
    LONG lDelta = 0;
    HBITMAP hbmSave = NULL, hbmColor = NULL, hbmMask = NULL;
    PSURFACE psurfSave = NULL, psurfColor = NULL, psurfMask = NULL;
    RECTL rectl;
    SIZEL sizel = {0, 0};

    ASSERT(pso);

    ppdev = GDIDEV(pso);
    pgp = &ppdev->Pointer;

    /* Handle the case where we have no XLATEOBJ */
    if (pxlo == NULL)
        pxlo = &gexloTrivial.xlo;

    /* Do we have any bitmap at all? */
    if (psoColor || psoMask)
    {
        /* Get the size of the new pointer */
        if (psoColor)
        {
            sizel.cx = psoColor->sizlBitmap.cx;
            sizel.cy = psoColor->sizlBitmap.cy;
        }
        else// if (psoMask)
        {
            sizel.cx = psoMask->sizlBitmap.cx;
            sizel.cy = psoMask->sizlBitmap.cy / 2;
        }

        rectl.left = 0;
        rectl.top = 0;
        rectl.right = sizel.cx;
        rectl.bottom = sizel.cy;

        /* Calculate lDelta for our surfaces. */
        lDelta = WIDTH_BYTES_ALIGN32(sizel.cx,
                                     BitsPerFormat(pso->iBitmapFormat));

        /* Create a bitmap for saving the pixels under the cursor. */
        hbmSave = EngCreateBitmap(sizel,
                                  lDelta,
                                  pso->iBitmapFormat,
                                  BMF_TOPDOWN | BMF_NOZEROINIT,
                                  NULL);
        psurfSave = SURFACE_ShareLockSurface(hbmSave);
        if (!psurfSave) goto failure;
    }

    if (psoColor)
    {
        if (fl & SPS_ALPHA)
        {
            /* Always store the alpha cursor in RGB. */
            EXLATEOBJ exloSrcRGB;
            PEXLATEOBJ pexlo;

            pexlo = CONTAINING_RECORD(pxlo, EXLATEOBJ, xlo);
            EXLATEOBJ_vInitialize(&exloSrcRGB, pexlo->ppalSrc, &gpalRGB, 0, 0, 0);

            hbmColor = EngCreateBitmap(psoColor->sizlBitmap,
                WIDTH_BYTES_ALIGN32(sizel.cx, 32),
                BMF_32BPP,
                BMF_TOPDOWN | BMF_NOZEROINIT,
                NULL);
            psurfColor = SURFACE_ShareLockSurface(hbmColor);
            if (!psurfColor) goto failure;

            /* Now copy the given bitmap. */
            rectl.bottom = psoColor->sizlBitmap.cy;
            IntEngCopyBits(&psurfColor->SurfObj,
                           psoColor,
                           NULL,
                           &exloSrcRGB.xlo,
                           &rectl,
                           (POINTL*)&rectl);

            EXLATEOBJ_vCleanup(&exloSrcRGB);
        }
        else
        {
            /* Color bitmap must have the same format as the dest surface */
            if (psoColor->iBitmapFormat != pso->iBitmapFormat)
            {
                DPRINT1("Screen surface and cursor color bitmap format don't match!.\n");
                goto failure;
            }

            /* Create a bitmap to copy the color bitmap to */
            hbmColor = EngCreateBitmap(psoColor->sizlBitmap,
                               lDelta,
                               pso->iBitmapFormat,
                               BMF_TOPDOWN | BMF_NOZEROINIT,
                               NULL);
            psurfColor = SURFACE_ShareLockSurface(hbmColor);
            if (!psurfColor) goto failure;

            /* Now copy the given bitmap. */
            rectl.bottom = psoColor->sizlBitmap.cy;
            IntEngCopyBits(&psurfColor->SurfObj,
                           psoColor,
                           NULL,
                           pxlo,
                           &rectl,
                           (POINTL*)&rectl);
        }

    }

    /* Create a mask surface */
    if (psoMask)
    {
        EXLATEOBJ exlo;
        PPALETTE ppal;

        lDelta = WIDTH_BYTES_ALIGN32(sizel.cx, BitsPerFormat(pso->iBitmapFormat));

        /* Create a bitmap for the mask */
        hbmMask = EngCreateBitmap(psoMask->sizlBitmap,
                                  lDelta,
                                  pso->iBitmapFormat,
                                  BMF_TOPDOWN | BMF_NOZEROINIT,
                                  NULL);
        psurfMask = SURFACE_ShareLockSurface(hbmMask);
        if (!psurfMask) goto failure;

        /* Initialize an EXLATEOBJ */
        ppal = PALETTE_ShareLockPalette(ppdev->devinfo.hpalDefault);
        EXLATEOBJ_vInitialize(&exlo,
                              gppalMono,
                              ppal,
                              0,
                              RGB(0xff,0xff,0xff),
                              RGB(0,0,0));

        /* Copy the mask bitmap */
        rectl.bottom = psoMask->sizlBitmap.cy;
        IntEngCopyBits(&psurfMask->SurfObj,
                       psoMask,
                       NULL,
                       &exlo.xlo,
                       &rectl,
                       (POINTL*)&rectl);

        /* Cleanup */
        EXLATEOBJ_vCleanup(&exlo);
        if (ppal) PALETTE_ShareUnlockPalette(ppal);
    }

    /* Hide mouse pointer */
    IntHideMousePointer(ppdev, pso);

    /* Free old color bitmap */
    if (pgp->psurfColor)
    {
        EngDeleteSurface(pgp->psurfColor->BaseObject.hHmgr);
        SURFACE_ShareUnlockSurface(pgp->psurfColor);
        pgp->psurfColor = NULL;
    }

    /* Free old mask bitmap */
    if (pgp->psurfMask)
    {
        EngDeleteSurface(pgp->psurfMask->BaseObject.hHmgr);
        SURFACE_ShareUnlockSurface(pgp->psurfMask);
        pgp->psurfMask = NULL;
    }

    /* Free old save bitmap */
    if (pgp->psurfSave)
    {
        EngDeleteSurface(pgp->psurfSave->BaseObject.hHmgr);
        SURFACE_ShareUnlockSurface(pgp->psurfSave);
        pgp->psurfSave = NULL;
    }

    /* See if we are being asked to hide the pointer. */
    if (psoMask == NULL && psoColor == NULL)
    {
        /* We're done */
        return SPS_ACCEPT_NOEXCLUDE;
    }

    /* Now set the new cursor */
    pgp->psurfColor = psurfColor;
    pgp->psurfMask = psurfMask;
    pgp->psurfSave = psurfSave;
    pgp->HotSpot.x = xHot;
    pgp->HotSpot.y = yHot;
    pgp->Size = sizel;
    pgp->flags = fl;

    if (x != -1)
    {
        ppdev->ptlPointer.x = x;
        ppdev->ptlPointer.y = y;

        IntShowMousePointer(ppdev, pso);

        if (prcl != NULL)
        {
            prcl->left = x - pgp->HotSpot.x;
            prcl->top = y - pgp->HotSpot.x;
            prcl->right = prcl->left + pgp->Size.cx;
            prcl->bottom = prcl->top + pgp->Size.cy;
        }
    }
    else if (prcl != NULL)
    {
        prcl->left = prcl->top = prcl->right = prcl->bottom = -1;
    }

    return SPS_ACCEPT_NOEXCLUDE;

failure:
    /* Cleanup surfaces */
    if (hbmMask) EngDeleteSurface((HSURF)hbmMask);
    if (psurfMask) SURFACE_ShareUnlockSurface(psurfMask);
    if (hbmColor) EngDeleteSurface((HSURF)hbmColor);
    if (psurfColor) SURFACE_ShareUnlockSurface(psurfColor);
    if (hbmSave) EngDeleteSurface((HSURF)hbmSave);
    if (psurfSave) SURFACE_ShareUnlockSurface(psurfSave);

    return SPS_ERROR;
}
Beispiel #6
0
BOOL APIENTRY
IntEngEnter(PINTENG_ENTER_LEAVE EnterLeave,
            SURFOBJ *psoDest,
            RECTL *DestRect,
            BOOL ReadOnly,
            POINTL *Translate,
            SURFOBJ **ppsoOutput)
{
  LONG Exchange;
  SIZEL BitmapSize;
  POINTL SrcPoint;
  LONG Width;
  RECTL ClippedDestRect;

  /* Normalize */
  if (DestRect->right < DestRect->left)
    {
    Exchange = DestRect->left;
    DestRect->left = DestRect->right;
    DestRect->right = Exchange;
    }
  if (DestRect->bottom < DestRect->top)
    {
    Exchange = DestRect->top;
    DestRect->top = DestRect->bottom;
    DestRect->bottom = Exchange;
    }

  if (NULL != psoDest && STYPE_BITMAP != psoDest->iType &&
      (NULL == psoDest->pvScan0 || 0 == psoDest->lDelta))
    {
    /* Driver needs to support DrvCopyBits, else we can't do anything */
    SURFACE *psurfDest = CONTAINING_RECORD(psoDest, SURFACE, SurfObj);
    if (!(psurfDest->flags & HOOK_COPYBITS))
    {
      return FALSE;
    }

    /* Allocate a temporary bitmap */
    BitmapSize.cx = DestRect->right - DestRect->left;
    BitmapSize.cy = DestRect->bottom - DestRect->top;
    Width = WIDTH_BYTES_ALIGN32(BitmapSize.cx, BitsPerFormat(psoDest->iBitmapFormat));
    EnterLeave->OutputBitmap = EngCreateBitmap(BitmapSize, Width,
                                               psoDest->iBitmapFormat,
                                               BMF_TOPDOWN | BMF_NOZEROINIT, NULL);

    if (!EnterLeave->OutputBitmap)
      {
      DPRINT1("EngCreateBitmap() failed\n");
      return FALSE;
      }

    *ppsoOutput = EngLockSurface((HSURF)EnterLeave->OutputBitmap);
    if (*ppsoOutput == NULL)
    {
      EngDeleteSurface((HSURF)EnterLeave->OutputBitmap);
      return FALSE;
    }

    EnterLeave->DestRect.left = 0;
    EnterLeave->DestRect.top = 0;
    EnterLeave->DestRect.right = BitmapSize.cx;
    EnterLeave->DestRect.bottom = BitmapSize.cy;
    SrcPoint.x = DestRect->left;
    SrcPoint.y = DestRect->top;
    ClippedDestRect = EnterLeave->DestRect;
    if (SrcPoint.x < 0)
      {
        ClippedDestRect.left -= SrcPoint.x;
        SrcPoint.x = 0;
      }
    if (psoDest->sizlBitmap.cx < SrcPoint.x + ClippedDestRect.right - ClippedDestRect.left)
      {
        ClippedDestRect.right = ClippedDestRect.left + psoDest->sizlBitmap.cx - SrcPoint.x;
      }
    if (SrcPoint.y < 0)
      {
        ClippedDestRect.top -= SrcPoint.y;
        SrcPoint.y = 0;
      }
    if (psoDest->sizlBitmap.cy < SrcPoint.y + ClippedDestRect.bottom - ClippedDestRect.top)
      {
        ClippedDestRect.bottom = ClippedDestRect.top + psoDest->sizlBitmap.cy - SrcPoint.y;
      }
    EnterLeave->TrivialClipObj = EngCreateClip();
    if (EnterLeave->TrivialClipObj == NULL)
    {
      EngUnlockSurface(*ppsoOutput);
      EngDeleteSurface((HSURF)EnterLeave->OutputBitmap);
      return FALSE;
    }
    EnterLeave->TrivialClipObj->iDComplexity = DC_TRIVIAL;
    if (ClippedDestRect.left < (*ppsoOutput)->sizlBitmap.cx &&
        0 <= ClippedDestRect.right &&
        SrcPoint.x < psoDest->sizlBitmap.cx &&
        ClippedDestRect.top <= (*ppsoOutput)->sizlBitmap.cy &&
        0 <= ClippedDestRect.bottom &&
        SrcPoint.y < psoDest->sizlBitmap.cy &&
        ! GDIDEVFUNCS(psoDest).CopyBits(
                                        *ppsoOutput, psoDest,
                                        EnterLeave->TrivialClipObj, NULL,
                                        &ClippedDestRect, &SrcPoint))
      {
          EngDeleteClip(EnterLeave->TrivialClipObj);
          EngUnlockSurface(*ppsoOutput);
          EngDeleteSurface((HSURF)EnterLeave->OutputBitmap);
          return FALSE;
      }
    EnterLeave->DestRect.left = DestRect->left;
    EnterLeave->DestRect.top = DestRect->top;
    EnterLeave->DestRect.right = DestRect->right;
    EnterLeave->DestRect.bottom = DestRect->bottom;
    Translate->x = - DestRect->left;
    Translate->y = - DestRect->top;
    }
  else
    {
    Translate->x = 0;
    Translate->y = 0;
    *ppsoOutput = psoDest;
    }

  if (NULL != *ppsoOutput)
  {
    SURFACE* psurfOutput = CONTAINING_RECORD(*ppsoOutput, SURFACE, SurfObj);
    if (0 != (psurfOutput->flags & HOOK_SYNCHRONIZE))
    {
      if (NULL != GDIDEVFUNCS(*ppsoOutput).SynchronizeSurface)
        {
          GDIDEVFUNCS(*ppsoOutput).SynchronizeSurface(*ppsoOutput, DestRect, 0);
        }
      else if (STYPE_BITMAP == (*ppsoOutput)->iType
               && NULL != GDIDEVFUNCS(*ppsoOutput).Synchronize)
        {
          GDIDEVFUNCS(*ppsoOutput).Synchronize((*ppsoOutput)->dhpdev, DestRect);
        }
    }
  }
  else return FALSE;

  EnterLeave->DestObj = psoDest;
  EnterLeave->OutputObj = *ppsoOutput;
  EnterLeave->ReadOnly = ReadOnly;

  return TRUE;
}
Beispiel #7
0
BOOLEAN DIB_XXBPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, SURFOBJ *MaskSurf,
                            SURFOBJ *PatternSurface,
                            RECTL *DestRect, RECTL *SourceRect,
                            POINTL *MaskOrigin, BRUSHOBJ *Brush,
                            POINTL *BrushOrigin, XLATEOBJ *ColorTranslation,
                            ROP4 ROP)
{
  LONG sx = 0;
  LONG sy = 0;
  LONG DesX;
  LONG DesY;

  LONG DstHeight;
  LONG DstWidth;
  LONG SrcHeight;
  LONG SrcWidth;
  LONG MaskCy;
  LONG SourceCy;

  ULONG Color;
  ULONG Dest, Source = 0, Pattern = 0;
  ULONG xxBPPMask;
  BOOLEAN CanDraw;

  PFN_DIB_GetPixel fnSource_GetPixel = NULL;
  PFN_DIB_GetPixel fnDest_GetPixel = NULL;
  PFN_DIB_PutPixel fnDest_PutPixel = NULL;
  PFN_DIB_GetPixel fnPattern_GetPixel = NULL;
  PFN_DIB_GetPixel fnMask_GetPixel = NULL;

  LONG PatternX = 0, PatternY = 0;

  BOOL UsesSource = ROP4_USES_SOURCE(ROP);
  BOOL UsesPattern = ROP4_USES_PATTERN(ROP);

  ASSERT(IS_VALID_ROP4(ROP));

  fnDest_GetPixel = DibFunctionsForBitmapFormat[DestSurf->iBitmapFormat].DIB_GetPixel;
  fnDest_PutPixel = DibFunctionsForBitmapFormat[DestSurf->iBitmapFormat].DIB_PutPixel;

  DPRINT("Dest BPP: %u, dstRect: (%d,%d)-(%d,%d)\n",
    BitsPerFormat(DestSurf->iBitmapFormat), DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);

  if (UsesSource)
  {
    SourceCy = abs(SourceSurf->sizlBitmap.cy);
    fnSource_GetPixel = DibFunctionsForBitmapFormat[SourceSurf->iBitmapFormat].DIB_GetPixel;
    DPRINT("Source BPP: %u, srcRect: (%d,%d)-(%d,%d)\n",
      BitsPerFormat(SourceSurf->iBitmapFormat), SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom);
  }

  if (MaskSurf)
  {
    fnMask_GetPixel = DibFunctionsForBitmapFormat[MaskSurf->iBitmapFormat].DIB_GetPixel;
    MaskCy = abs(MaskSurf->sizlBitmap.cy);
  }

  DstHeight = DestRect->bottom - DestRect->top;
  DstWidth = DestRect->right - DestRect->left;
  SrcHeight = SourceRect->bottom - SourceRect->top;
  SrcWidth = SourceRect->right - SourceRect->left;

  /* FIXME: MaskOrigin? */

  switch(DestSurf->iBitmapFormat)
  {
  case BMF_1BPP: xxBPPMask = 0x1; break;
  case BMF_4BPP: xxBPPMask = 0xF; break;
  case BMF_8BPP: xxBPPMask = 0xFF; break;
  case BMF_16BPP: xxBPPMask = 0xFFFF; break;
  case BMF_24BPP: xxBPPMask = 0xFFFFFF; break;
  default:
    xxBPPMask = 0xFFFFFFFF;
  }

  if (UsesPattern)
  {
    if (PatternSurface)
    {
      PatternY = (DestRect->top - BrushOrigin->y) % PatternSurface->sizlBitmap.cy;
      if (PatternY < 0)
      {
        PatternY += PatternSurface->sizlBitmap.cy;
      }
      fnPattern_GetPixel = DibFunctionsForBitmapFormat[PatternSurface->iBitmapFormat].DIB_GetPixel;
    }
    else
    {
      if (Brush)
        Pattern = Brush->iSolidColor;
    }
  }


  for (DesY = DestRect->top; DesY < DestRect->bottom; DesY++)
  {
    if (PatternSurface)
    {
      PatternX = (DestRect->left - BrushOrigin->x) % PatternSurface->sizlBitmap.cx;
      if (PatternX < 0)
      {
        PatternX += PatternSurface->sizlBitmap.cx;
      }
    }
    if (UsesSource)
      sy = SourceRect->top+(DesY - DestRect->top) * SrcHeight / DstHeight;

    for (DesX = DestRect->left; DesX < DestRect->right; DesX++)
    {
      CanDraw = TRUE;

      if (fnMask_GetPixel)
      {
        sx = SourceRect->left+(DesX - DestRect->left) * SrcWidth / DstWidth;
        if (sx < 0 || sy < 0 ||
          MaskSurf->sizlBitmap.cx < sx || MaskCy < sy ||
          fnMask_GetPixel(MaskSurf, sx, sy) != 0)
        {
          CanDraw = FALSE;
        }
      }

      if (UsesSource && CanDraw)
      {
        sx = SourceRect->left+(DesX - DestRect->left) * SrcWidth / DstWidth;
        if (sx >= 0 && sy >= 0 &&
          SourceSurf->sizlBitmap.cx > sx && SourceCy > sy)
        {
          Source = XLATEOBJ_iXlate(ColorTranslation, fnSource_GetPixel(SourceSurf, sx, sy));
        }
        else
        {
          Source = 0;
          CanDraw = ((ROP & 0xFF) != R3_OPINDEX_SRCCOPY);
        }
      }

      if (CanDraw)
      {
        if (UsesPattern && PatternSurface)
        {
          Pattern = fnPattern_GetPixel(PatternSurface, PatternX, PatternY);
          PatternX++;
          PatternX %= PatternSurface->sizlBitmap.cx;
        }

        Dest = fnDest_GetPixel(DestSurf, DesX, DesY);
        Color = DIB_DoRop(ROP, Dest, Source, Pattern) & xxBPPMask;

        fnDest_PutPixel(DestSurf, DesX, DesY, Color);
      }
    }

    if (PatternSurface)
    {
      PatternY++;
      PatternY %= PatternSurface->sizlBitmap.cy;
    }
  }

  return TRUE;
}