From 4391f3846df8675e7d8d0128c104160ba609ee91 Mon Sep 17 00:00:00 2001 From: Jakub Sobon Date: Sun, 28 Apr 2019 20:14:26 -0400 Subject: [PATCH] Adding HSplitCells into the area package. --- internal/area/area.go | 23 +++++++++++ internal/area/area_test.go | 85 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+) diff --git a/internal/area/area.go b/internal/area/area.go index 236b9b7..5a36b91 100644 --- a/internal/area/area.go +++ b/internal/area/area.go @@ -101,6 +101,29 @@ func VSplitCells(area image.Rectangle, cells int) (left image.Rectangle, right i return left, right, nil } +// HSplitCells returns two new areas created by splitting the provided area +// after the specified amount of cells of its height. The number of cells must +// be a zero or a positive integer. Providing a zero returns top=image.ZR, +// bottom=area. Providing a number equal or larger to area's height returns +// top=area, bottom=image.ZR. +func HSplitCells(area image.Rectangle, cells int) (top image.Rectangle, bottom image.Rectangle, err error) { + if min := 0; cells < min { + return image.ZR, image.ZR, fmt.Errorf("invalid cells %d, must be a positive integer", cells) + } + if cells == 0 { + return image.ZR, area, nil + } + + height := area.Dy() + if cells >= height { + return area, image.ZR, nil + } + + top = image.Rect(area.Min.X, area.Min.Y, area.Max.X, area.Min.Y+cells) + bottom = image.Rect(area.Min.X, area.Min.Y+cells, area.Max.X, area.Max.Y) + return top, bottom, nil +} + // ExcludeBorder returns a new area created by subtracting a border around the // provided area. Return the zero area if there isn't enough space to exclude // the border. diff --git a/internal/area/area_test.go b/internal/area/area_test.go index 16630cd..4acd496 100644 --- a/internal/area/area_test.go +++ b/internal/area/area_test.go @@ -367,6 +367,91 @@ func TestVSplitCells(t *testing.T) { } } +func TestHSplitCells(t *testing.T) { + tests := []struct { + desc string + area image.Rectangle + cells int + wantTop image.Rectangle + wantBottom image.Rectangle + wantErr bool + }{ + { + desc: "fails on negative cells", + area: image.Rect(1, 1, 2, 2), + cells: -1, + wantErr: true, + }, + { + desc: "returns area as top on cells too large", + area: image.Rect(1, 1, 2, 2), + cells: 2, + wantTop: image.Rect(1, 1, 2, 2), + wantBottom: image.ZR, + }, + { + desc: "returns area as top on cells equal area width", + area: image.Rect(1, 1, 2, 2), + cells: 1, + wantTop: image.Rect(1, 1, 2, 2), + wantBottom: image.ZR, + }, + { + desc: "returns area as bottom on zero cells", + area: image.Rect(1, 1, 2, 2), + cells: 0, + wantBottom: image.Rect(1, 1, 2, 2), + wantTop: image.ZR, + }, + { + desc: "zero area to begin with", + area: image.ZR, + cells: 0, + wantTop: image.ZR, + wantBottom: image.ZR, + }, + { + desc: "splits area with even height", + area: image.Rect(1, 1, 3, 3), + cells: 1, + wantTop: image.Rect(1, 1, 3, 2), + wantBottom: image.Rect(1, 2, 3, 3), + }, + { + desc: "splits area with odd width", + area: image.Rect(1, 1, 4, 4), + cells: 1, + wantTop: image.Rect(1, 1, 4, 2), + wantBottom: image.Rect(1, 2, 4, 4), + }, + { + desc: "splits to unequal areas", + area: image.Rect(0, 0, 4, 4), + cells: 3, + wantTop: image.Rect(0, 0, 4, 3), + wantBottom: image.Rect(0, 3, 4, 4), + }, + } + + for _, tc := range tests { + t.Run(tc.desc, func(t *testing.T) { + gotTop, gotBottom, err := HSplitCells(tc.area, tc.cells) + if (err != nil) != tc.wantErr { + t.Errorf("HSplitCells => unexpected error:%v, wantErr:%v", err, tc.wantErr) + } + if err != nil { + return + } + if diff := pretty.Compare(tc.wantTop, gotTop); diff != "" { + t.Errorf("HSplitCells => left value unexpected diff (-want, +got):\n%s", diff) + } + if diff := pretty.Compare(tc.wantBottom, gotBottom); diff != "" { + t.Errorf("HSplitCells => right value unexpected diff (-want, +got):\n%s", diff) + } + }) + } +} + func TestExcludeBorder(t *testing.T) { tests := []struct { desc string