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