Skip to content

UnionRect not ignoring empty input rectangle

Summary

The function UnionRect(R, R1,R2) calculates the union of the input rectangles R1 and R2 and returns the result in rectangle R.

However, when one of the input rectangles, R1 or R2, is (0,0,0,0) then the top/left corner of the unioned rectangle is (0, 0). Such a rectangle is "empty" as tested by the function IsRectEmpty. It would be expected that empty rectangles as input parameters are ignored in the calculation.

System Information

  • Operating system: Windows
  • Processor architecture: x86-64
  • Compiler version: FPC main, ccb19859
  • Device: Computer

Steps to reproduce

The following example program calculates the union of the rectangles (0,0,0,0) and (10, 10, 20, 30). The function UnionRect in unit types reports the union the be (0, 0, 20, 30), but I would expect it to be equal to the non-empty rectangle.

Using the function UnionRect from the Windows api yields the correct result. Delphi, however, has the same bug as FPC and reports the result as (0, 0, 20, 30).

Example Project

program Project1;
uses
  Types;
var
  R1, R2, R3: TRect;
begin
  R1 := Rect(0, 0, 0, 0);
  R2 := Rect(10, 10, 20, 30);
  Types.UnionRect(R3, R1, R2);
  WriteLn('Left=', R3.Left, ' Top=', R3.Top, ' Right=', R3.Right, ' Bottom=', R3.Bottom);
end. 

Possible fixes

The following modified function fixes the issue:

function UnionRect(var Rect : TRect;const R1,R2 : TRect) : Boolean;
var
  lRect: TRect;
begin
  if IsRectEmpty(R1) then
    lRect := R2
  else
  if IsRectEmpty(R2) then
    lRect := R1
  else
  begin
    lRect:=R1;
    if R2.Left<R1.Left then
      lRect.Left:=R2.Left;
    if R2.Top<R1.Top then
      lRect.Top:=R2.Top;
    if R2.Right>R1.Right then
      lRect.Right:=R2.Right;
    if R2.Bottom>R1.Bottom then
      lRect.Bottom:=R2.Bottom;
  end;

  if IsRectEmpty(lRect) then
  begin
    FillChar(Rect,SizeOf(Rect),0);
    UnionRect:=false;
  end
  else
  begin
    Rect:=lRect;
    UnionRect:=true;
  end;
end;
Edited by Werner Pamler
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information