xref: /haiku/src/libs/print/libprint/ValidRect.cpp (revision 08d759feae5967ad75d0f0d4ee33c21c72ae6db8)
112fd6cc2SKarsten Heimrich /*
212fd6cc2SKarsten Heimrich  * ValidRect.cpp
312fd6cc2SKarsten Heimrich  * Copyright 1999-2000 Y.Takagi. All Rights Reserved.
412fd6cc2SKarsten Heimrich  * Copyright 2005 Michael Pfeiffer. All Rights Reserved.
512fd6cc2SKarsten Heimrich  * - Rewrote get_valid_rect from scratch.
612fd6cc2SKarsten Heimrich  */
712fd6cc2SKarsten Heimrich 
812fd6cc2SKarsten Heimrich #include <Bitmap.h>
912fd6cc2SKarsten Heimrich #include "ValidRect.h"
1012fd6cc2SKarsten Heimrich 
1112fd6cc2SKarsten Heimrich #define INLINE inline
1212fd6cc2SKarsten Heimrich 
1312fd6cc2SKarsten Heimrich class BoundsCalculator
1412fd6cc2SKarsten Heimrich {
1512fd6cc2SKarsten Heimrich public:
1612fd6cc2SKarsten Heimrich 	bool getValidRect(BBitmap *bitmap, RECT *rect);
1712fd6cc2SKarsten Heimrich 
1812fd6cc2SKarsten Heimrich private:
1912fd6cc2SKarsten Heimrich 	const uchar *fBits;
2012fd6cc2SKarsten Heimrich 	int fBPR;
2112fd6cc2SKarsten Heimrich 	int fLeft;
2212fd6cc2SKarsten Heimrich 	int fRight;
2312fd6cc2SKarsten Heimrich 	int fTop;
2412fd6cc2SKarsten Heimrich 	int fBottom;
2512fd6cc2SKarsten Heimrich 	int fWidth;
2612fd6cc2SKarsten Heimrich 
2712fd6cc2SKarsten Heimrich 	int fLeftBound;
2812fd6cc2SKarsten Heimrich 	int fRightBound;
2912fd6cc2SKarsten Heimrich 
3012fd6cc2SKarsten Heimrich 	INLINE bool isEmpty(const rgb_color *pixel);
3112fd6cc2SKarsten Heimrich 
3212fd6cc2SKarsten Heimrich 	INLINE bool isRowEmpty(const rgb_color *row);
3312fd6cc2SKarsten Heimrich 
3412fd6cc2SKarsten Heimrich 	INLINE const uchar *getRow(int x, int y);
3512fd6cc2SKarsten Heimrich 
3612fd6cc2SKarsten Heimrich 	int getTop();
3712fd6cc2SKarsten Heimrich 
3812fd6cc2SKarsten Heimrich 	int getBottom();
3912fd6cc2SKarsten Heimrich 
4012fd6cc2SKarsten Heimrich 	INLINE void updateLeftBound(const rgb_color *row);
4112fd6cc2SKarsten Heimrich 	INLINE void updateRightBound(const rgb_color *row);
4212fd6cc2SKarsten Heimrich };
4312fd6cc2SKarsten Heimrich 
44*08d759feSMichael Pfeiffer 
4512fd6cc2SKarsten Heimrich bool
isEmpty(const rgb_color * pixel)4612fd6cc2SKarsten Heimrich BoundsCalculator::isEmpty(const rgb_color *pixel)
4712fd6cc2SKarsten Heimrich {
4812fd6cc2SKarsten Heimrich 	return pixel->red == 0xff && pixel->green == 0xff && pixel->blue == 0xff;
4912fd6cc2SKarsten Heimrich }
5012fd6cc2SKarsten Heimrich 
5112fd6cc2SKarsten Heimrich 
5212fd6cc2SKarsten Heimrich bool
isRowEmpty(const rgb_color * row)5312fd6cc2SKarsten Heimrich BoundsCalculator::isRowEmpty(const rgb_color *row)
5412fd6cc2SKarsten Heimrich {
5512fd6cc2SKarsten Heimrich 	for (int x = 0; x < fWidth; x ++) {
5612fd6cc2SKarsten Heimrich 		if (!isEmpty(row)) {
5712fd6cc2SKarsten Heimrich 			return false;
5812fd6cc2SKarsten Heimrich 		}
5912fd6cc2SKarsten Heimrich 		row ++;
6012fd6cc2SKarsten Heimrich 	}
6112fd6cc2SKarsten Heimrich 	return true;
6212fd6cc2SKarsten Heimrich }
6312fd6cc2SKarsten Heimrich 
64*08d759feSMichael Pfeiffer 
6512fd6cc2SKarsten Heimrich const uchar *
getRow(int x,int y)6612fd6cc2SKarsten Heimrich BoundsCalculator::getRow(int x, int y)
6712fd6cc2SKarsten Heimrich {
6812fd6cc2SKarsten Heimrich 	return fBits + x + fBPR * y;
6912fd6cc2SKarsten Heimrich }
7012fd6cc2SKarsten Heimrich 
71*08d759feSMichael Pfeiffer 
7212fd6cc2SKarsten Heimrich int
getTop()7312fd6cc2SKarsten Heimrich BoundsCalculator::getTop()
7412fd6cc2SKarsten Heimrich {
7512fd6cc2SKarsten Heimrich 	const uchar* row = getRow(fLeft, fTop);
7612fd6cc2SKarsten Heimrich 
7712fd6cc2SKarsten Heimrich 	int top;
7812fd6cc2SKarsten Heimrich 	for (top = fTop; top <= fBottom; top ++) {
7912fd6cc2SKarsten Heimrich 		if (!isRowEmpty((const rgb_color*)row)) {
8012fd6cc2SKarsten Heimrich 			break;
8112fd6cc2SKarsten Heimrich 		}
8212fd6cc2SKarsten Heimrich 		row += fBPR;
8312fd6cc2SKarsten Heimrich 	}
8412fd6cc2SKarsten Heimrich 
8512fd6cc2SKarsten Heimrich 	return top;
8612fd6cc2SKarsten Heimrich }
8712fd6cc2SKarsten Heimrich 
88*08d759feSMichael Pfeiffer 
8912fd6cc2SKarsten Heimrich int
getBottom()9012fd6cc2SKarsten Heimrich BoundsCalculator::getBottom()
9112fd6cc2SKarsten Heimrich {
9212fd6cc2SKarsten Heimrich 	const uchar *row = getRow(fLeft, fBottom);
9312fd6cc2SKarsten Heimrich 
9412fd6cc2SKarsten Heimrich 	int bottom;
9512fd6cc2SKarsten Heimrich 	for (bottom = fBottom; bottom >= fTop; bottom --) {
9612fd6cc2SKarsten Heimrich 		if (!isRowEmpty((const rgb_color*)row)) {
9712fd6cc2SKarsten Heimrich 			break;
9812fd6cc2SKarsten Heimrich 		}
9912fd6cc2SKarsten Heimrich 		row -= fBPR;
10012fd6cc2SKarsten Heimrich 	}
10112fd6cc2SKarsten Heimrich 
10212fd6cc2SKarsten Heimrich 	return bottom;
10312fd6cc2SKarsten Heimrich }
10412fd6cc2SKarsten Heimrich 
105*08d759feSMichael Pfeiffer 
10612fd6cc2SKarsten Heimrich void
updateLeftBound(const rgb_color * row)10712fd6cc2SKarsten Heimrich BoundsCalculator::updateLeftBound(const rgb_color *row)
10812fd6cc2SKarsten Heimrich {
10912fd6cc2SKarsten Heimrich 	for (int x = fLeft; x < fLeftBound; x ++) {
11012fd6cc2SKarsten Heimrich 		if (!isEmpty(row)) {
11112fd6cc2SKarsten Heimrich 			fLeftBound = x;
11212fd6cc2SKarsten Heimrich 			return;
11312fd6cc2SKarsten Heimrich 		}
11412fd6cc2SKarsten Heimrich 		row ++;
11512fd6cc2SKarsten Heimrich 	}
11612fd6cc2SKarsten Heimrich }
11712fd6cc2SKarsten Heimrich 
118*08d759feSMichael Pfeiffer 
11912fd6cc2SKarsten Heimrich void
updateRightBound(const rgb_color * row)12012fd6cc2SKarsten Heimrich BoundsCalculator::updateRightBound(const rgb_color *row)
12112fd6cc2SKarsten Heimrich {
12212fd6cc2SKarsten Heimrich 	row += fWidth - 1;
12312fd6cc2SKarsten Heimrich 	for (int x = fRight; x > fRightBound; x --) {
12412fd6cc2SKarsten Heimrich 		if (!isEmpty(row)) {
12512fd6cc2SKarsten Heimrich 			fRightBound = x;
12612fd6cc2SKarsten Heimrich 			return;
12712fd6cc2SKarsten Heimrich 		}
12812fd6cc2SKarsten Heimrich 		row --;
12912fd6cc2SKarsten Heimrich 	}
13012fd6cc2SKarsten Heimrich }
13112fd6cc2SKarsten Heimrich 
132*08d759feSMichael Pfeiffer 
13312fd6cc2SKarsten Heimrich // returns false if the bitmap is empty or has wrong color space.
13412fd6cc2SKarsten Heimrich bool
getValidRect(BBitmap * bitmap,RECT * rect)13512fd6cc2SKarsten Heimrich BoundsCalculator::getValidRect(BBitmap *bitmap, RECT *rect)
13612fd6cc2SKarsten Heimrich {
13712fd6cc2SKarsten Heimrich 	enum {
13812fd6cc2SKarsten Heimrich 		kRectIsInvalid = false,
13912fd6cc2SKarsten Heimrich 		kRectIsEmpty = false,
14012fd6cc2SKarsten Heimrich 		kRectIsValid = true
14112fd6cc2SKarsten Heimrich 	};
14212fd6cc2SKarsten Heimrich 
14312fd6cc2SKarsten Heimrich 	switch (bitmap->ColorSpace()) {
14412fd6cc2SKarsten Heimrich 		case B_RGB32:
14512fd6cc2SKarsten Heimrich 		case B_RGB32_BIG:
14612fd6cc2SKarsten Heimrich 			break;
14712fd6cc2SKarsten Heimrich 		default:
14812fd6cc2SKarsten Heimrich 			return kRectIsInvalid;
14912fd6cc2SKarsten Heimrich 			break;
15012fd6cc2SKarsten Heimrich 	};
15112fd6cc2SKarsten Heimrich 
15212fd6cc2SKarsten Heimrich 	// initialize member variables
15312fd6cc2SKarsten Heimrich 	fBits = (uchar*)bitmap->Bits();
15412fd6cc2SKarsten Heimrich 	fBPR  = bitmap->BytesPerRow();
15512fd6cc2SKarsten Heimrich 
15612fd6cc2SKarsten Heimrich 	fLeft   = rect->left;
15712fd6cc2SKarsten Heimrich 	fRight  = rect->right;
15812fd6cc2SKarsten Heimrich 	fTop    = rect->top;
15912fd6cc2SKarsten Heimrich 	fBottom = rect->bottom;
16012fd6cc2SKarsten Heimrich 
16112fd6cc2SKarsten Heimrich 	fWidth = fRight - fLeft + 1;
16212fd6cc2SKarsten Heimrich 
16312fd6cc2SKarsten Heimrich 	// get top bound
16412fd6cc2SKarsten Heimrich 	fTop = getTop();
16512fd6cc2SKarsten Heimrich 	if (fTop > fBottom) {
16612fd6cc2SKarsten Heimrich 		return kRectIsEmpty;
16712fd6cc2SKarsten Heimrich 	}
16812fd6cc2SKarsten Heimrich 
16912fd6cc2SKarsten Heimrich 	// get bottom bound
17012fd6cc2SKarsten Heimrich 	fBottom = getBottom();
17112fd6cc2SKarsten Heimrich 
17212fd6cc2SKarsten Heimrich 	// calculate left and right bounds
17312fd6cc2SKarsten Heimrich 	fLeftBound = fRight + 1;
17412fd6cc2SKarsten Heimrich 	fRightBound = fLeft - 1;
17512fd6cc2SKarsten Heimrich 
17612fd6cc2SKarsten Heimrich 	const uchar *row = getRow(fLeft, fTop);
17712fd6cc2SKarsten Heimrich 	for (int y = fTop; y <= fBottom; y ++) {
17812fd6cc2SKarsten Heimrich 		updateLeftBound((const rgb_color*)row);
17912fd6cc2SKarsten Heimrich 		updateRightBound((const rgb_color*)row);
18012fd6cc2SKarsten Heimrich 		if (fLeft == fLeftBound && fRight == fRightBound) {
18112fd6cc2SKarsten Heimrich 			break;
18212fd6cc2SKarsten Heimrich 		}
18312fd6cc2SKarsten Heimrich 		row += fBPR;
18412fd6cc2SKarsten Heimrich 	}
18512fd6cc2SKarsten Heimrich 
18612fd6cc2SKarsten Heimrich 	// return bounds in rectangle
18712fd6cc2SKarsten Heimrich 	rect->left = fLeftBound;
18812fd6cc2SKarsten Heimrich 	rect->right = fRightBound;
18912fd6cc2SKarsten Heimrich 	rect->top = fTop;
19012fd6cc2SKarsten Heimrich 	rect->bottom = fBottom;
19112fd6cc2SKarsten Heimrich 
19212fd6cc2SKarsten Heimrich 	return kRectIsValid;
19312fd6cc2SKarsten Heimrich }
19412fd6cc2SKarsten Heimrich 
195*08d759feSMichael Pfeiffer 
get_valid_rect(BBitmap * a_bitmap,RECT * rc)19612fd6cc2SKarsten Heimrich bool get_valid_rect(BBitmap *a_bitmap, RECT *rc)
19712fd6cc2SKarsten Heimrich {
19812fd6cc2SKarsten Heimrich 	BoundsCalculator calculator;
19912fd6cc2SKarsten Heimrich 	return calculator.getValidRect(a_bitmap, rc);
20012fd6cc2SKarsten Heimrich }
20112fd6cc2SKarsten Heimrich 
202*08d759feSMichael Pfeiffer 
color_space2pixel_depth(color_space cs)20312fd6cc2SKarsten Heimrich int color_space2pixel_depth(color_space cs)
20412fd6cc2SKarsten Heimrich {
20512fd6cc2SKarsten Heimrich 	int pixel_depth;
20612fd6cc2SKarsten Heimrich 
20712fd6cc2SKarsten Heimrich 	switch (cs) {
20812fd6cc2SKarsten Heimrich 	case B_GRAY1:		/* Y0[0],Y1[0],Y2[0],Y3[0],Y4[0],Y5[0],Y6[0],Y7[0]	*/
20912fd6cc2SKarsten Heimrich 		pixel_depth = 1;
21012fd6cc2SKarsten Heimrich 		break;
21112fd6cc2SKarsten Heimrich 	case B_GRAY8:		/* Y[7:0]											*/
21212fd6cc2SKarsten Heimrich 	case B_CMAP8:		/* D[7:0]  											*/
21312fd6cc2SKarsten Heimrich 		pixel_depth = 8;
21412fd6cc2SKarsten Heimrich 		break;
21512fd6cc2SKarsten Heimrich 	case B_RGB15:		/* G[2:0],B[4:0]  	   -[0],R[4:0],G[4:3]			*/
21612fd6cc2SKarsten Heimrich 	case B_RGB15_BIG:	/* -[0],R[4:0],G[4:3]  G[2:0],B[4:0]				*/
21712fd6cc2SKarsten Heimrich 		pixel_depth = 16;
21812fd6cc2SKarsten Heimrich 		break;
21912fd6cc2SKarsten Heimrich 	case B_RGB32:		/* B[7:0]  G[7:0]  R[7:0]  -[7:0]					*/
22012fd6cc2SKarsten Heimrich 	case B_RGB32_BIG:	/* -[7:0]  R[7:0]  G[7:0]  B[7:0]					*/
22112fd6cc2SKarsten Heimrich 		pixel_depth = 32;
22212fd6cc2SKarsten Heimrich 		break;
22312fd6cc2SKarsten Heimrich 	default:
22412fd6cc2SKarsten Heimrich 		pixel_depth = 0;
22512fd6cc2SKarsten Heimrich 		break;
22612fd6cc2SKarsten Heimrich 	}
22712fd6cc2SKarsten Heimrich 	return pixel_depth;
22812fd6cc2SKarsten Heimrich }
229