void BitmapContainer::clipRect(_R<BitmapContainer> source, const RECT& sourceRect, int32_t destX, int32_t destY, RECT& outputSourceRect, int32_t& outputX, int32_t& outputY) const { int sLeft = imax(sourceRect.Xmin, 0); int sTop = imax(sourceRect.Ymin, 0); int sRight = imax(imin(sourceRect.Xmax, source->getWidth()), 0); int sBottom = imax(imin(sourceRect.Ymax, source->getHeight()), 0); int dLeft = destX; int dTop = destY; if (dLeft < 0) { sLeft += -dLeft; dLeft = 0; } if (dTop < 0) { sTop += -dTop; dTop = 0; } int clippedWidth = imax(imin(sRight - sLeft, getWidth() - dLeft), 0); int clippedHeight = imax(imin(sBottom - sTop, getHeight() - dTop), 0); outputSourceRect.Xmin = sLeft; outputSourceRect.Xmax = sLeft + clippedWidth; outputSourceRect.Ymin = sTop; outputSourceRect.Ymax = sTop + clippedHeight; outputX = dLeft; outputY = dTop; }
void BitmapContainer::copyRectangle(_R<BitmapContainer> source, const RECT& sourceRect, int32_t destX, int32_t destY, bool mergeAlpha) { RECT clippedSourceRect; int32_t clippedX; int32_t clippedY; clipRect(source, sourceRect, destX, destY, clippedSourceRect, clippedX, clippedY); int copyWidth = clippedSourceRect.Xmax - clippedSourceRect.Xmin; int copyHeight = clippedSourceRect.Ymax - clippedSourceRect.Ymin; if (copyWidth <= 0 || copyHeight <= 0) return; int sx = clippedSourceRect.Xmin; int sy = clippedSourceRect.Ymin; if (mergeAlpha==false) { //Fast path using memmove for (int i=0; i<copyHeight; i++) { memmove(&data[(clippedY+i)*stride + 4*clippedX], &source->data[(sy+i)*source->stride + 4*sx], 4*copyWidth); } } else { //Slow path using Cairo CairoRenderContext ctxt(&data[0], width, height); ctxt.simpleBlit(clippedX, clippedY, &source->data[0], source->getWidth(), source->getHeight(), sx, sy, copyWidth, copyHeight); } }