Files
haiku-beta6/src/add-ons/print/drivers/shared/libprint/ValidRect.cpp
T
Michael Pfeiffer 5d4b78560b Rewrote get_valid_rect because it contained bugs.
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@11437 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-02-21 17:33:16 +00:00

220 lines
3.9 KiB
C++

/*
* ValidRect.cpp
* Copyright 1999-2000 Y.Takagi. All Rights Reserved.
* Copyright 2005 Michael Pfeiffer. All Rights Reserved.
* - Rewrote get_valid_rect from scratch.
*/
#include <Bitmap.h>
#include "ValidRect.h"
#define INLINE inline
class BoundsCalculator
{
public:
bool getValidRect(BBitmap *bitmap, RECT *rect);
private:
const uchar *fBits;
int fBPR;
int fLeft;
int fRight;
int fTop;
int fBottom;
int fWidth;
int fLeftBound;
int fRightBound;
INLINE bool isEmpty(const rgb_color *pixel);
INLINE bool isRowEmpty(const rgb_color *row);
INLINE const uchar *getRow(int x, int y);
int getTop();
int getBottom();
INLINE void updateLeftBound(const rgb_color *row);
INLINE void updateRightBound(const rgb_color *row);
};
bool
BoundsCalculator::isEmpty(const rgb_color *pixel)
{
return pixel->red == 0xff && pixel->green == 0xff && pixel->blue == 0xff;
}
bool
BoundsCalculator::isRowEmpty(const rgb_color *row)
{
for (int x = 0; x < fWidth; x ++) {
if (!isEmpty(row)) {
return false;
}
row ++;
}
return true;
}
const uchar *
BoundsCalculator::getRow(int x, int y)
{
return fBits + x + fBPR * y;
}
int
BoundsCalculator::getTop()
{
const uchar* row = getRow(fLeft, fTop);
int top;
for (top = fTop; top <= fBottom; top ++) {
if (!isRowEmpty((const rgb_color*)row)) {
break;
}
row += fBPR;
}
return top;
}
int
BoundsCalculator::getBottom()
{
const uchar *row = getRow(fLeft, fBottom);
int bottom;
for (bottom = fBottom; bottom >= fTop; bottom --) {
if (!isRowEmpty((const rgb_color*)row)) {
break;
}
row -= fBPR;
}
return bottom;
}
void
BoundsCalculator::updateLeftBound(const rgb_color *row)
{
for (int x = fLeft; x < fLeftBound; x ++) {
if (!isEmpty(row)) {
fLeftBound = x;
return;
}
row ++;
}
}
void
BoundsCalculator::updateRightBound(const rgb_color *row)
{
row += fWidth - 1;
for (int x = fRight; x > fRightBound; x --) {
if (!isEmpty(row)) {
fRightBound = x;
return;
}
row --;
}
}
// returns false if the bitmap is empty or has wrong color space.
bool
BoundsCalculator::getValidRect(BBitmap *bitmap, RECT *rect)
{
enum {
kRectIsInvalid = false,
kRectIsEmpty = false,
kRectIsValid = true
};
switch (bitmap->ColorSpace()) {
case B_RGB32:
case B_RGB32_BIG:
break;
default:
return kRectIsInvalid;
break;
};
// initialize member variables
fBits = (uchar*)bitmap->Bits();
fBPR = bitmap->BytesPerRow();
fLeft = rect->left;
fRight = rect->right;
fTop = rect->top;
fBottom = rect->bottom;
fWidth = fRight - fLeft + 1;
// get top bound
fTop = getTop();
if (fTop > fBottom) {
return kRectIsEmpty;
}
// get bottom bound
fBottom = getBottom();
// calculate left and right bounds
fLeftBound = fRight + 1;
fRightBound = fLeft - 1;
const uchar *row = getRow(fLeft, fTop);
for (int y = fTop; y <= fBottom; y ++) {
updateLeftBound((const rgb_color*)row);
updateRightBound((const rgb_color*)row);
if (fLeft == fLeftBound && fRight == fRightBound) {
break;
}
row += fBPR;
}
// return bounds in rectangle
rect->left = fLeftBound;
rect->right = fRightBound;
rect->top = fTop;
rect->bottom = fBottom;
return kRectIsValid;
}
bool get_valid_rect(BBitmap *a_bitmap, RECT *rc)
{
BoundsCalculator calculator;
return calculator.getValidRect(a_bitmap, rc);
}
int color_space2pixel_depth(color_space cs)
{
int pixel_depth;
switch (cs) {
case B_GRAY1: /* Y0[0],Y1[0],Y2[0],Y3[0],Y4[0],Y5[0],Y6[0],Y7[0] */
pixel_depth = 1;
break;
case B_GRAY8: /* Y[7:0] */
case B_CMAP8: /* D[7:0] */
pixel_depth = 8;
break;
case B_RGB15: /* G[2:0],B[4:0] -[0],R[4:0],G[4:3] */
case B_RGB15_BIG: /* -[0],R[4:0],G[4:3] G[2:0],B[4:0] */
pixel_depth = 16;
break;
case B_RGB32: /* B[7:0] G[7:0] R[7:0] -[7:0] */
case B_RGB32_BIG: /* -[7:0] R[7:0] G[7:0] B[7:0] */
pixel_depth = 32;
break;
default:
pixel_depth = 0;
break;
}
return pixel_depth;
}