public void BuildDirtyRect(ref int x, int y, out int XStart, out int YStart, out int XEnd, out int YEnd) { int LastX = this.numCellsX - x; DirtyCell curCell = GetCell(x, y); XStart = (x << GetXCellFactor()) + curCell.coverage.Left; YStart = (y << GetYCellFactor()) + curCell.coverage.Bottom; XEnd = (x << GetXCellFactor()) + curCell.coverage.Right; YEnd = (y << GetYCellFactor()) + curCell.coverage.Top; int XCellSize = GetXCellSize(); DirtyCell nextCell = GetCell(x + 1, y); if (curCell.coverage.Right == (int)XCellSize && // it touches the right side of the cell nextCell != null && nextCell.isDirty && // there is a next cell nextCell.coverage.Left == 0 && // that touches the left curCell.coverage.Top == nextCell.coverage.Top && // and they have the same top curCell.coverage.Bottom == nextCell.coverage.Bottom) // and bottom { // get all the ones we can (build a nice big strip rather than every rect) while (x + 1 < LastX && curCell.coverage.Right == (int)XCellSize && // it touches the right side of the cell nextCell != null && nextCell.isDirty && // there is a next cell nextCell.coverage.Left == 0 && // that touches the left curCell.coverage.Top == nextCell.coverage.Top && // and they have the same top curCell.coverage.Bottom == nextCell.coverage.Bottom) // and bottom { x++; XEnd += nextCell.coverage.Width; curCell = nextCell; nextCell = GetCell(x + 1, y); } } }
public void SetDirty(RectangleInt areaToSetDirty) { if (areaToSetDirty.Left >= areaToSetDirty.Right || areaToSetDirty.Bottom >= areaToSetDirty.Top) { return; } RectangleInt BoundRect = new RectangleInt(0, 0, numCellsX << xCellFactor, numCellsY << yCellFactor); RectangleInt Area = areaToSetDirty; if (Area.IntersectWithRectangle(BoundRect)) { Area.Right--; Area.Top--; Area.Left = Area.Left >> xCellFactor; Area.Right = Area.Right >> xCellFactor; Area.Bottom = Area.Bottom >> yCellFactor; Area.Top = Area.Top >> yCellFactor; int offsetForY = yTable[Area.Bottom]; for (int y = Area.Bottom; y <= Area.Top; y++) { for (int x = Area.Left; x <= Area.Right; x++) { DirtyCell currCell = dirtyCells[offsetForY + x]; // if it's not set or it's not totally covered RectangleInt CurCellBounds = new RectangleInt((x << xCellFactor), (y << yCellFactor), ((x << xCellFactor) + xCellSize), ((y << yCellFactor) + yCellSize)); // if we are setting it for the first time if (!currCell.isDirty) { currCell.coverage.Left = Math.Max(Math.Min((areaToSetDirty.Left - CurCellBounds.Left), xCellSize), 0); currCell.coverage.Bottom = Math.Max(Math.Min((areaToSetDirty.Bottom - CurCellBounds.Bottom), yCellSize), 0); currCell.coverage.Right = Math.Max(Math.Min((areaToSetDirty.Right - CurCellBounds.Left), xCellSize), 0); currCell.coverage.Top = Math.Max(Math.Min((areaToSetDirty.Top - CurCellBounds.Bottom), yCellSize), 0); } else // we are adding to it's coverage { currCell.coverage.Left = Math.Max(Math.Min(Math.Min(currCell.coverage.Left, (areaToSetDirty.Left - CurCellBounds.Left)), xCellSize), 0); currCell.coverage.Bottom = Math.Max(Math.Min(Math.Min(currCell.coverage.Bottom, (areaToSetDirty.Bottom - CurCellBounds.Bottom)), yCellSize), 0); currCell.coverage.Right = Math.Max(Math.Min(Math.Max(currCell.coverage.Right, (areaToSetDirty.Right - CurCellBounds.Left)), xCellSize), 0); currCell.coverage.Top = Math.Max(Math.Min(Math.Max(currCell.coverage.Top, (areaToSetDirty.Top - CurCellBounds.Bottom)), yCellSize), 0); } currCell.isDirty = true; } offsetForY += numCellsX; } } }