xref: /haiku/src/libs/print/libprint/ValidRect.cpp (revision 002f37b0cca92e4cf72857c72ac95db5a8b09615)
1 /*
2  * ValidRect.cpp
3  * Copyright 1999-2000 Y.Takagi. All Rights Reserved.
4  * Copyright 2005 Michael Pfeiffer. All Rights Reserved.
5  * - Rewrote get_valid_rect from scratch.
6  */
7 
8 #include <Bitmap.h>
9 #include "ValidRect.h"
10 
11 #define INLINE inline
12 
13 class BoundsCalculator
14 {
15 public:
16 	bool getValidRect(BBitmap *bitmap, RECT *rect);
17 
18 private:
19 	const uchar *fBits;
20 	int fBPR;
21 	int fLeft;
22 	int fRight;
23 	int fTop;
24 	int fBottom;
25 	int fWidth;
26 
27 	int fLeftBound;
28 	int fRightBound;
29 
30 	INLINE bool isEmpty(const rgb_color *pixel);
31 
32 	INLINE bool isRowEmpty(const rgb_color *row);
33 
34 	INLINE const uchar *getRow(int x, int y);
35 
36 	int getTop();
37 
38 	int getBottom();
39 
40 	INLINE void updateLeftBound(const rgb_color *row);
41 	INLINE void updateRightBound(const rgb_color *row);
42 };
43 
44 
45 bool
46 BoundsCalculator::isEmpty(const rgb_color *pixel)
47 {
48 	return pixel->red == 0xff && pixel->green == 0xff && pixel->blue == 0xff;
49 }
50 
51 
52 bool
53 BoundsCalculator::isRowEmpty(const rgb_color *row)
54 {
55 	for (int x = 0; x < fWidth; x ++) {
56 		if (!isEmpty(row)) {
57 			return false;
58 		}
59 		row ++;
60 	}
61 	return true;
62 }
63 
64 
65 const uchar *
66 BoundsCalculator::getRow(int x, int y)
67 {
68 	return fBits + x + fBPR * y;
69 }
70 
71 
72 int
73 BoundsCalculator::getTop()
74 {
75 	const uchar* row = getRow(fLeft, fTop);
76 
77 	int top;
78 	for (top = fTop; top <= fBottom; top ++) {
79 		if (!isRowEmpty((const rgb_color*)row)) {
80 			break;
81 		}
82 		row += fBPR;
83 	}
84 
85 	return top;
86 }
87 
88 
89 int
90 BoundsCalculator::getBottom()
91 {
92 	const uchar *row = getRow(fLeft, fBottom);
93 
94 	int bottom;
95 	for (bottom = fBottom; bottom >= fTop; bottom --) {
96 		if (!isRowEmpty((const rgb_color*)row)) {
97 			break;
98 		}
99 		row -= fBPR;
100 	}
101 
102 	return bottom;
103 }
104 
105 
106 void
107 BoundsCalculator::updateLeftBound(const rgb_color *row)
108 {
109 	for (int x = fLeft; x < fLeftBound; x ++) {
110 		if (!isEmpty(row)) {
111 			fLeftBound = x;
112 			return;
113 		}
114 		row ++;
115 	}
116 }
117 
118 
119 void
120 BoundsCalculator::updateRightBound(const rgb_color *row)
121 {
122 	row += fWidth - 1;
123 	for (int x = fRight; x > fRightBound; x --) {
124 		if (!isEmpty(row)) {
125 			fRightBound = x;
126 			return;
127 		}
128 		row --;
129 	}
130 }
131 
132 
133 // returns false if the bitmap is empty or has wrong color space.
134 bool
135 BoundsCalculator::getValidRect(BBitmap *bitmap, RECT *rect)
136 {
137 	enum {
138 		kRectIsInvalid = false,
139 		kRectIsEmpty = false,
140 		kRectIsValid = true
141 	};
142 
143 	switch (bitmap->ColorSpace()) {
144 		case B_RGB32:
145 		case B_RGB32_BIG:
146 			break;
147 		default:
148 			return kRectIsInvalid;
149 			break;
150 	};
151 
152 	// initialize member variables
153 	fBits = (uchar*)bitmap->Bits();
154 	fBPR  = bitmap->BytesPerRow();
155 
156 	fLeft   = rect->left;
157 	fRight  = rect->right;
158 	fTop    = rect->top;
159 	fBottom = rect->bottom;
160 
161 	fWidth = fRight - fLeft + 1;
162 
163 	// get top bound
164 	fTop = getTop();
165 	if (fTop > fBottom) {
166 		return kRectIsEmpty;
167 	}
168 
169 	// get bottom bound
170 	fBottom = getBottom();
171 
172 	// calculate left and right bounds
173 	fLeftBound = fRight + 1;
174 	fRightBound = fLeft - 1;
175 
176 	const uchar *row = getRow(fLeft, fTop);
177 	for (int y = fTop; y <= fBottom; y ++) {
178 		updateLeftBound((const rgb_color*)row);
179 		updateRightBound((const rgb_color*)row);
180 		if (fLeft == fLeftBound && fRight == fRightBound) {
181 			break;
182 		}
183 		row += fBPR;
184 	}
185 
186 	// return bounds in rectangle
187 	rect->left = fLeftBound;
188 	rect->right = fRightBound;
189 	rect->top = fTop;
190 	rect->bottom = fBottom;
191 
192 	return kRectIsValid;
193 }
194 
195 
196 bool get_valid_rect(BBitmap *a_bitmap, RECT *rc)
197 {
198 	BoundsCalculator calculator;
199 	return calculator.getValidRect(a_bitmap, rc);
200 }
201 
202 
203 int color_space2pixel_depth(color_space cs)
204 {
205 	int pixel_depth;
206 
207 	switch (cs) {
208 	case B_GRAY1:		/* Y0[0],Y1[0],Y2[0],Y3[0],Y4[0],Y5[0],Y6[0],Y7[0]	*/
209 		pixel_depth = 1;
210 		break;
211 	case B_GRAY8:		/* Y[7:0]											*/
212 	case B_CMAP8:		/* D[7:0]  											*/
213 		pixel_depth = 8;
214 		break;
215 	case B_RGB15:		/* G[2:0],B[4:0]  	   -[0],R[4:0],G[4:3]			*/
216 	case B_RGB15_BIG:	/* -[0],R[4:0],G[4:3]  G[2:0],B[4:0]				*/
217 		pixel_depth = 16;
218 		break;
219 	case B_RGB32:		/* B[7:0]  G[7:0]  R[7:0]  -[7:0]					*/
220 	case B_RGB32_BIG:	/* -[7:0]  R[7:0]  G[7:0]  B[7:0]					*/
221 		pixel_depth = 32;
222 		break;
223 	default:
224 		pixel_depth = 0;
225 		break;
226 	}
227 	return pixel_depth;
228 }
229