hlfw.ca

binpack

Download patch

ref: d1f3f76a2fcdfc57a58f2b834fad61ea2c71ec3d
parent: b0b116b71e8a5ab10b2f2e32c4ac48894e579558
author: Halfwit <michaelmisch1985@gmail.com>
date: Sun Oct 15 11:32:49 PDT 2017

Add in skeleton for multimon

--- a/binpack.c
+++ b/binpack.c
@@ -1,337 +1,73 @@
-/* Simple bin packing algorithm implementation */
-
-#include <stdlib.h>
 #include <stdio.h>
-#include <getopt.h>
+#include <stdlib.h>
 #include <stdbool.h>
+#include <getopt.h>
 
-enum {
-	MAX_RECTS	= 50,
-	LINE_LNG	= 50
-};
+#include "binpack.h"
 
-struct mbin {
-	unsigned x, y, gaps;
-};
-
-struct input {
-	unsigned min_w, min_h, max_w, max_h;
-	unsigned long wid;
-};
-
-struct output {
-	unsigned x, y, w, h;
-	unsigned long wid;
-};
-
-struct bins {
-  /* temporary storage of available sub-bins */
-  unsigned x, y, w, h;
-};
-
-size_t
-binpack_init(struct input r[])
-{
-
-	/* Read from stdin, create each rect */
-	size_t length = 0;
-	char line[LINE_LNG];
-	for (unsigned i = 0; fgets(line, sizeof(line), stdin); ++i) {
-		sscanf(line, "%d %d %d %d %lx", &r[i].min_w, &r[i].min_h, &r[i].max_w, &r[i].max_h, &r[i].wid);
-		length++;
-	}
-
-	return length;
-
+void center(int width, int height, struct Output out[], int gaps) {
+	// r = rightmost edge of bins
+	// d = bottommost edge of bins
+	// Move all windows (width - r) / 2
+	// Move all windows (height - d) / 2
+	// g = gaps / 2
+	// x - g, y + g, w - g, h - g for all windows 
 }
 
-void
-center(const size_t length, struct output r[], struct mbin mb)
-{
+int 
+main(int argc, char* argv[]) {
 
-	/* (max bin size - blob size) / 2 */
-	unsigned w = 0, h = 0;
-	for (size_t i = 0; i < length; i++) {
-		if (w < (r[i].w + r[i].x))
-			w = r[i].w + r[i].x;
-
-		if (h < (r[i].h + r[i].y))
-			h = r[i].h + r[i].y;
-	}
-
-	for (size_t i = 0; i < length; i++) {
-		r[i].x += (mb.x - w) / 2;
-		r[i].y += (mb.y - h) / 2;
-	}
-
-}
-
-void
-sort_bins(struct bins b[], size_t *bin_count)
-{
-
-	/* given set of bins, arrange them smallest to largest w*h */
-	struct bins temp;
-	for (unsigned i = 1; i < *bin_count; i++) {
-		for (unsigned j = 0; j < *bin_count - i; j++) {
-			if ((b[j + 1].w * b[j + 1].h) > (b[j].w * b[j].h)) {
-				temp = b[j];
-				b[j] = b[j + 1];
-				b[j + 1] = temp;
-			}
-		}
-	}
-
-}
-
-void
-sort_input(struct input r[], const size_t length)
-{
-
-	/* arrange rectangles largest to smallest, normalized some over min/max */
-	struct input temp;
-	for (size_t i = 1; i < length; i++) {
-		for (size_t j = 0; j < length - i; j++) {
-			if ((r[j + 1].max_w * r[j + 1].min_h) > (r[j].max_w * r[j].min_h)) {
-				temp = r[j];
-				r[j] = r[j + 1];
-				r[j + 1] = temp;
-			}
-		}
-	}
-
-}
-
-void
-create_bins(struct bins bin[], struct output out[], size_t i, size_t j, size_t *bin_count, struct mbin mb)
-{
-
-	/* New bins based on subsection of old  */
-	unsigned x, y, w, h;
-	x = bin[j].x;
-	y = bin[j].y;
-	w = bin[j].w;
-	h = bin[j].h;
-
-	/* rect smaller, make two sub bins */
-	if (out[i].h + mb.gaps < h && out[i].w + mb.gaps < w) {
-		bin[*bin_count] = (struct bins){.x = x + out[i].w + mb.gaps, .y = y, .w = w - out[i].w - mb.gaps, .h = h};
-		bin[j].y += (out[i].h + mb.gaps);
-		bin[j].h -= (out[i].h - mb.gaps);
-		*bin_count += 1;
-	}
-
-	/* rect same height */
-	else if (out[i].h + mb.gaps < h) {
-		bin[j].y += (out[i].h + mb.gaps);
-		bin[j].h -= (out[i].h - mb.gaps);
-	}
-
-	/* rect same width */
-	else if (out[i].w + mb.gaps < w) {
-		bin[j].x += (out[i].w + mb.gaps);
-    	bin[j].w -= (out[i].w - mb.gaps);
-	}
-
-	/* rect fills space, lose a bin */
-	else {
-		bin[j].w = 0;
-		bin[j].h = 0;
-		*bin_count -= 1;
-	}
-
-}
-
-void
-save_rect(struct bins bin[], struct output out[], struct input r[], size_t i, size_t j, struct mbin mb)
-{
-
-	/* Store rect x y w h wid */
-	out[i] = (struct output){.x = bin[j].x + (mb.gaps / 2), .y = bin[j].y + (mb.gaps / 2), .w = r[i].min_w, .h = r[i].min_h, .wid = r[i].wid};
-
-}
-
-bool
-pack_bin(struct output out[], struct input r[], const size_t length, unsigned *bin_width, unsigned *bin_height, struct mbin mb)
-{
-
-	/* Main algorithm */
-	struct bins bin[MAX_RECTS];
-
-	for (int i = 0; i < MAX_RECTS; i++) {
-		bin[i] = (struct bins){.x = 0, .y = 0, .w = 0, .h = 0};
-	}
-
-	/* default bin */
-	bin[0] = (struct bins){ .x = 0, .y = 0, .w = *bin_width + mb.gaps, .h = *bin_height + mb.gaps};
-
-	size_t bin_count = 1;
-	bool rect_fits;
-
-	/* loop through each rect */
-	for (size_t i = 0; i < length; i++) {
-		rect_fits = false;
-
-		/* loop through each bin */
-		for (size_t j = 0; j < bin_count; j++) {
-			/* rect fits in current bin */
-			if (r[i].min_w + mb.gaps <= bin[j].w && r[i].min_h + mb.gaps <= bin[j].h) {
-				rect_fits = true;
-				save_rect(bin, out, r, i, j, mb);
-				create_bins(bin, out, i, j, &bin_count, mb);
-				sort_bins(bin, &bin_count);
-				break;
-			}
-		}
-
-		/* if rect does not fit all bin */
-		if (rect_fits == false) {
-
-			/* Grow main bin if possible */
-			if (mb.x > *bin_width)
-				*bin_width += 2;
-
-			if (mb.y > *bin_height)
-				*bin_height += 2;
-
-			return true;
-		}
-	}
-
-	return false;
-
-}
-
-bool
-resize(struct output out[], struct input r[], const size_t length, unsigned *bin_width, unsigned *bin_height, struct mbin mb, size_t index)
-{
-
-	/* When a bin fills all the space available, pack_bin */
-	for (size_t i = index; i < length; i++) {
-		unsigned limitcheck = 0;
-		while (pack_bin(out, r, length, bin_width, bin_height, mb)) {
-			if (limitcheck == mb.x)
-				return false;
-
-			limitcheck++;
-		}
-
-		/* If rect can grow */
-		if (out[i].h < r[i].max_h)
-			r[i].min_h += 1;
-
-		if (out[i].w < r[i].max_w)
-			r[i].min_w += 1;
-
-		sort_input(r, length);
-	}
-
-	/* max_h to handle cases of smaller windows */
-	unsigned w = 0, h = 0;
-
-	for (size_t i = index; i < length; i++) {
-		if (w < (out[i].w + out[i].x))
-			w = out[i].w + out[i].x + mb.gaps;
-
-		if (h < (out[i].h + out[i].y))
-			h = out[i].h + out[i].y + mb.gaps;
-	}
-
-	if (h >= mb.y + (mb.gaps / 2))
-		return false;
-
-	if (w >= mb.x + (mb.gaps / 2))
-		return false;
-
-	return true;
-
-}
-
-int
-main(int argc, char *argv[])
-{
-
-	struct mbin mb;
-	mb.gaps = 0, mb.x = 0, mb.y = 0;
-	int c;
-
-	while ((c = getopt(argc, argv, "hg:x:y:")) != -1) {
+	int gaps = 0;
+	int width = 0;
+	int height = 0;
+	int screens = 1;
+	char c;
+	
+	while ((c = getopt(argc, argv, "hg:w:h:s:")) != -1) {
 		switch (c) {
-		/* read in, all vars unsigned int */
 		case 'g':
-			sscanf(optarg, "%u", &mb.gaps);
-			break;
-		case 'x':
-			sscanf(optarg, "%u", &mb.x);
-			break;
-		case 'y':
-			sscanf(optarg, "%u", &mb.y);
-			break;
-		case 'h':
-			fputs("Usage: bin_pack -x screen_width -y screen_height -g gaps\n", stderr);
+			sscanf(optarg, "%u", gaps);
+	        break;
+    	case 'x':
+        	sscanf(optarg, "%u", width);
+           	break;
+        case 'y':
+        	sscanf(optarg, "%u", height);
+        	break;
+    	case 's':
+        	sscanf(optarg, "%u", screens);
+        	break;
+    	case 'h':
+			fputs("Usage: bin_pack -x screen_width -y screen_height -g gaps -s number_of_screens\n", stderr);
 			return EXIT_SUCCESS;
-		}
+        }
 	}
 
-	struct input r[MAX_RECTS];
-	struct output out[MAX_RECTS];
+	switch (screens) {
+		case 1:	   		
+//	   		bin_pack(width, height, *output, *input);
+//	   		center(width, height, *output, gaps);
+	   		break;
 
-	const size_t length = (binpack_init(r));
-
-	/* If we have no windows, exit */
-	if (length == 0 || mb.x == 0 || mb.y == 0)
-		return EXIT_SUCCESS;
-
-	sort_input(r, length);
-
-	unsigned bin_width = mb.x;
-	unsigned bin_height = mb.y;
-
-	/* If we have no large windows */
-	bool no_large_windows = true;
-	for (size_t i = 0; i < length; i++) {
-		struct input temp = r[i];
-		r[i].min_w = r[i].max_w;
-		r[i].min_h = r[i].max_h;
-
-		if (pack_bin(out, r, length, &bin_width, &bin_height, mb)) {
-			r[i] = temp;
-			no_large_windows = false;
-		}
+		case 2:
+//	   		split total width into two 'bins'
+//	   		split into two Input, a and b
+//	   		bin_pack a and b
+//	  		center a and b
+//	  		add $width to all bins in b (shift to the right fro second monitor)
+	  		break;
+		case 3:
+//	   		split total width into three 'bins'
+//	   		bin_pack a
+//	    	- if bin_pack fails, split out second window into bin b
+//			- sanity check that there is infact a second window
+//	    	- all subsequent fails will split out second window into bin b
+//	   		once success, split b into two Input, b and c
+//	   		bin_pack b and c
+//	   		center a b and c
+//	   		add $width to everything in b, and 2 * $width to everything in c
+			break;
 	}
-
-	unsigned limitcheck = 0;
-
-	if (no_large_windows == false) {
-		bin_width = r[0].min_w;
-		bin_height = r[0].min_h;
-
-		while (pack_bin(out, r, length, &bin_width, &bin_height, mb)) {
-			/* if we've ran this long, something is up */
-			if (limitcheck == mb.x)
-				return EXIT_FAILURE;
-
-			limitcheck++;
-		}
-
-		limitcheck = 0;
-
-		for (size_t i = 0; i < length; i++) {
-			/* Square out the blob as best as we can */
-			while (resize(out, r, length, &bin_width, &bin_height, mb, i)) {
-				if (limitcheck == mb.x)
-					return EXIT_FAILURE;
-
-				limitcheck++;
-			}
-		}
-	}
-
-	center(length, out, mb);
-
-	for (size_t i = 0; i < length; i++) {
-		printf("%d %d %d %d %lx\n", out[i].x, out[i].y, out[i].w, out[i].h, out[i].wid);
-	}
-
-	return EXIT_SUCCESS;
+//	print everything to stdout
 }
+
--- /dev/null
+++ b/binpack.h
@@ -1,0 +1,18 @@
+struct Input {
+	int minw;
+	int minh;
+	int maxw;
+	int maxh;
+	int id;
+};
+
+struct Output {
+	int w;
+	int h;
+	int x;
+	int y;
+	int id;
+};
+
+//bool bin_pack(int width, int height, &output[], &input[]);
+
--- a/test/test
+++ b/test/test
@@ -1,8 +1,9 @@
 #!/bin/sh
 ## Assume standard 6 px gap
 
-for i in */in**; do
+cd "$(dirname $0)"
+for i in */in*; do
 	size="$(dirname "$i")"
 	in="$(binpack -x "${size%x*}" -y "${size#*x}" -g 6 < "$i")"
-	grep -q "$in" "$size/out${i#*in*}" && echo "Test $size - ${i#*in*} success"
-done
+	grep "$in" "$size/out${i#*in*}" >/dev/null && echo "Test $size - ${i#*in*} success"
+done
\ No newline at end of file