- Made some settings persistent: Slide Show Delay, Scale Bilinear, Shrink/Zoom to Window, Show Caption in Full Screen Mode and PrintOptions.

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@5441 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Pfeiffer 2003-11-22 11:02:57 +00:00
parent 2d6fb9b82d
commit 5e427b6a85
5 changed files with 200 additions and 60 deletions

View File

@ -191,8 +191,6 @@ Scaler::Matches(BRect rect) const {
// Scale bilinear using floating point calculations
typedef int32 intType;
typedef struct {
intType srcColumn;
float alpha0;
@ -316,26 +314,6 @@ Scaler::ScaleBilinear(intType fromRow, int32 toRow)
// Scale bilinear using fixed point calculations
// Is already more than two times faster than floating point version
// on AMD Athlon 1 GHz and Intel Pentium III 866 MHz.
typedef int64 long_fixed_point;
typedef int32 fixed_point;
// Could use shift operator instead of multiplication and division,
// but compiler will optimize it for use anyway.
#define to_fixed_point(number) static_cast<fixed_point>((number) * kFPPrecisionFactor)
#define from_fixed_point(number) ((number) / kFPPrecisionFactor)
#define to_float(number) from_fixed_point(static_cast<float>(number))
#define int_value(number) ((number) & kFPInverseMask)
#define tail_value(number) ((number) & kFPPrecisionMask)
// Has to be called after muliplication of two fixed point values
#define mult_correction(number) ((number) / kFPPrecisionFactor)
const int32 kFPPrecision = 8; // (32-kFPPrecision).kFPPrecision
const int32 kFPPrecisionFactor = (1 << kFPPrecision);
const int32 kFPPrecisionMask = ((kFPPrecisionFactor)-1);
const int32 kFPInverseMask = (~kFPPrecisionMask);
const int32 kFPOne = to_fixed_point(1);
typedef struct {
int32 srcColumn;
@ -463,6 +441,143 @@ Scaler::ScaleBilinearFP(intType fromRow, int32 toRow)
delete[] columnData;
}
void
Scaler::RowValues(float* sum, const uchar* src, intType srcW, intType fromX, intType toX, const float a0X, const float a1X, const float deltaX, const int32 kBPP)
{
sum[0] = a0X * src[0];
sum[1] = a0X * src[1];
sum[2] = a0X * src[2];
src += kBPP;
for (int32 x = fromX+1; x < toX; x ++, src += kBPP) {
sum[0] += src[0];
sum[1] += src[1];
sum[2] += src[2];
}
if (toX <= srcW) {
sum[0] += a1X * src[0];
sum[1] += a1X * src[1];
sum[2] += a1X * src[2];
}
sum[0] /= deltaX;
sum[1] /= deltaX;
sum[2] /= deltaX;
}
typedef struct {
int32 from;
int32 to;
float alpha0;
float alpha1;
} DownScaleColumnData;
void
Scaler::DownScaleBilinear(intType fromRow, int32 toRow)
{
BBitmap* src;
BBitmap* dest;
intType srcW, srcH;
intType destW, destH;
intType x, y;
const uchar* srcBits;
uchar* destBits;
intType srcBPR, destBPR;
const uchar* srcData;
uchar* destDataRow;
uchar* destData;
const int32 kBPP = 4;
DownScaleColumnData* columnData;
src = GetSrcImage();
dest = GetDestImage();
srcW = src->Bounds().IntegerWidth();
srcH = src->Bounds().IntegerHeight();
destW = dest->Bounds().IntegerWidth();
destH = dest->Bounds().IntegerHeight();
srcBits = (uchar*)src->Bits();
destBits = (uchar*)dest->Bits();
srcBPR = src->BytesPerRow();
destBPR = dest->BytesPerRow();
destDataRow = destBits + fromRow * destBPR;
const float deltaX = (srcW + 1.0) / (destW + 1.0);
const float deltaY = (srcH + 1.0) / (destH + 1.0);
columnData = new DownScaleColumnData[destW+1];
DownScaleColumnData* cd = columnData;
for (x = 0; x <= destW; x ++, cd ++) {
const float fFromX = x * deltaX;
const float fToX = fFromX + deltaX;
cd->from = (intType)fFromX;
cd->to = (intType)fToX;
cd->alpha0 = 1.0 - (fFromX - cd->from);
cd->alpha1 = fToX - cd->to;
}
for (y = fromRow; IsRunning() && y <= toRow; y ++, destDataRow += destBPR) {
const float fFromY = y * deltaY;
const float fToY = fFromY + deltaY;
const intType fromY = (intType)fFromY;
const intType toY = (intType)fToY;
const float a0Y = 1.0 - (fFromY - fromY);
const float a1Y = fToY - toY;
const uchar* srcDataRow = srcBits + fromY * srcBPR;
destData = destDataRow;
cd = columnData;
for (x = 0; x <= destW; x ++, destData += kBPP, cd ++) {
const intType fromX = cd->from;
const intType toX = cd->to;
const float a0X = cd->alpha0;
const float a1X = cd->alpha1;
srcData = srcDataRow + fromX * kBPP;
float totalSum[3];
float sum[3];
RowValues(sum, srcData, srcW, fromX, toX, a0X, a1X, deltaX, kBPP);
totalSum[0] = a0Y * sum[0];
totalSum[1] = a0Y * sum[1];
totalSum[2] = a0Y * sum[2];
srcData += srcBPR;
for (int32 r = fromY+1; r < toY; r ++, srcData += srcBPR) {
RowValues(sum, srcData, srcW, fromX, toX, a0X, a1X, deltaX, kBPP);
totalSum[0] += sum[0];
totalSum[1] += sum[1];
totalSum[2] += sum[2];
}
if (toY <= srcH) {
RowValues(sum, srcData, srcW, fromX, toX, a0X, a1X, deltaX, kBPP);
totalSum[0] += a1Y * sum[0];
totalSum[1] += a1Y * sum[1];
totalSum[2] += a1Y * sum[2];
}
destData[0] = static_cast<uchar>(totalSum[0] / deltaY);
destData[1] = static_cast<uchar>(totalSum[1] / deltaY);
destData[2] = static_cast<uchar>(totalSum[2] / deltaY);
}
}
delete columnData;
}
void
Scaler::Run(int i, int n)
{
@ -474,5 +589,9 @@ Scaler::Run(int i, int n)
} else {
to = from + height - 1;
}
ScaleBilinearFP(from, to);
if (GetDestImage()->Bounds().Width() >= GetSrcImage()->Bounds().Width()) {
ScaleBilinearFP(from, to);
} else {
DownScaleBilinear(from, to);
}
}

View File

@ -38,6 +38,28 @@
class Filter;
typedef int32 intType;
typedef int64 long_fixed_point;
typedef int32 fixed_point;
// Could use shift operator instead of multiplication and division,
// but compiler will optimize it for use anyway.
#define to_fixed_point(number) static_cast<fixed_point>((number) * kFPPrecisionFactor)
#define from_fixed_point(number) ((number) / kFPPrecisionFactor)
#define to_float(number) from_fixed_point(static_cast<float>(number))
#define int_value(number) ((number) & kFPInverseMask)
#define tail_value(number) ((number) & kFPPrecisionMask)
// Has to be called after muliplication of two fixed point values
#define mult_correction(number) ((number) / kFPPrecisionFactor)
const int32 kFPPrecision = 8; // (32-kFPPrecision).kFPPrecision
const int32 kFPPrecisionFactor = (1 << kFPPrecision);
const int32 kFPPrecisionMask = ((kFPPrecisionFactor)-1);
const int32 kFPInverseMask = (~kFPPrecisionMask);
const int32 kFPOne = to_fixed_point(1);
// Used by class Filter
class FilterThread {
public:
@ -124,6 +146,8 @@ public:
private:
void ScaleBilinear(int32 fromRow, int32 toRow);
void ScaleBilinearFP(int32 fromRow, int32 toRow);
inline void RowValues(float* sum, const uchar* srcData, intType srcW, intType fromX, intType toX, const float a0X, const float a1X, const float deltaX, const int32 kBPP);
void DownScaleBilinear(int32 fromRow, int32 toRow);
BRect fRect;
};

View File

@ -47,6 +47,7 @@
#include <Clipboard.h>
#include <Path.h>
#include <PopUpMenu.h>
#include <Region.h>
#include "ShowImageApp.h"
@ -325,7 +326,7 @@ ShowImageView::SetShowCaption(bool show)
{
if (fShowCaption != show) {
fShowCaption = show;
Invalidate();
UpdateCaption();
}
}
@ -438,8 +439,9 @@ ShowImageView::AlignBitmap()
width = Bounds().Width()-2*PEN_SIZE+1;
height = Bounds().Height()-2*PEN_SIZE+1;
if (width == 0 || height == 0) return rect;
if (fShrinkToBounds && (rect.Width() >= Bounds().Width() || rect.Height() >= Bounds().Height()) ||
fZoomToBounds && rect.Width() < Bounds().Width() && rect.Height() < Bounds().Height()) {
fShrinkOrZoomToBounds = fShrinkToBounds && (rect.Width() >= Bounds().Width() || rect.Height() >= Bounds().Height()) ||
fZoomToBounds && rect.Width() < Bounds().Width() && rect.Height() < Bounds().Height();
if (fShrinkOrZoomToBounds) {
float s;
s = width / (rect.Width()+1.0);
@ -541,14 +543,12 @@ ShowImageView::DrawBorder(BRect border)
}
void
ShowImageView::DrawCaption()
ShowImageView::LayoutCaption(BFont &font, BPoint &pos, BRect &rect)
{
font_height fontHeight;
float width, height;
BRect bounds(Bounds());
BFont font(be_plain_font);
BPoint pos;
BRect rect;
font = be_plain_font;
width = font.StringWidth(fCaption.String()) + 1; // 1 for text shadow
font.GetHeight(&fontHeight);
height = fontHeight.ascent + fontHeight.descent;
@ -561,7 +561,16 @@ ShowImageView::DrawCaption()
rect.Set(0, 0, (width-1)+2, (height-1)+2+1); // 2 for border and 1 for text shadow
rect.OffsetTo(pos);
rect.OffsetBy(-1, -1-fontHeight.ascent); // -1 for border
}
void
ShowImageView::DrawCaption()
{
BFont font;
BPoint pos;
BRect rect;
LayoutCaption(font, pos, rect);
PushState();
// draw background
SetDrawingMode(B_OP_ALPHA);
@ -584,29 +593,19 @@ ShowImageView::DrawCaption()
}
void
ShowImageView::EraseCaption()
ShowImageView::UpdateCaption()
{
font_height fontHeight;
float width, height;
BRect bounds(Bounds());
BFont font(be_plain_font);
BFont font;
BPoint pos;
BRect rect;
width = font.StringWidth(fCaption.String()) + 1; // 1 for text shadow
font.GetHeight(&fontHeight);
height = fontHeight.ascent + fontHeight.descent;
// center text horizontally
pos.x = (bounds.left + bounds.right - width)/2;
// flush bottom
pos.y = bounds.bottom - fontHeight.descent - 5;
// background rectangle
rect.Set(0, 0, (width-1)+2, (height-1)+2+1); // 2 for border and 1 for text shadow
rect.OffsetTo(pos);
rect.OffsetBy(-1, -1-fontHeight.ascent); // -1 for border
LayoutCaption(font, pos, rect);
// draw over portion of image where caption is located
BRegion clip(rect);
PushState();
ConstrainClippingRegion(&clip);
Draw(rect);
PopState();
}
Scaler*
@ -1158,7 +1157,7 @@ ShowImageView::ScrollRestricted(float x, float y, bool absolute)
bool caption = fShowCaption;
if (caption) {
fShowCaption = false;
EraseCaption();
UpdateCaption();
}
ScrollBy(x, y);
@ -1166,7 +1165,7 @@ ShowImageView::ScrollRestricted(float x, float y, bool absolute)
if (caption) {
// show the caption again
fShowCaption = true;
DrawCaption();
UpdateCaption();
}
}
@ -1189,16 +1188,16 @@ ShowImageView::KeyDown (const char * bytes, int32 numBytes)
if (numBytes == 1) {
switch (*bytes) {
case B_DOWN_ARROW:
ScrollRestrictedBy(0, 10); Invalidate();
ScrollRestrictedBy(0, 10);
break;
case B_UP_ARROW:
ScrollRestrictedBy(0, -10); Invalidate();
ScrollRestrictedBy(0, -10);
break;
case B_LEFT_ARROW:
ScrollRestrictedBy(-10, 0); Invalidate();
ScrollRestrictedBy(-10, 0);
break;
case B_RIGHT_ARROW:
ScrollRestrictedBy(10, 0); Invalidate();
ScrollRestrictedBy(10, 0);
break;
case B_SPACE:
case B_ENTER:
@ -1299,7 +1298,7 @@ ShowImageView::FixupScrollBar(orientation o, float bitmapLength, float viewLengt
psb = ScrollBar(o);
if (psb) {
if (fHasBorder) {
if (fHasBorder && !fShrinkOrZoomToBounds) {
bitmapLength += BORDER_WIDTH*2;
}
range = bitmapLength - viewLength;

View File

@ -153,8 +153,9 @@ private:
uint32 GetMouseButtons();
void UpdateSelectionRect(BPoint point, bool final);
void DrawBorder(BRect border);
void LayoutCaption(BFont &font, BPoint &textPos, BRect &background);
void DrawCaption();
void EraseCaption();
void UpdateCaption();
void DrawSelectionBox(BRect &rect);
Scaler* GetScaler(BRect rect);
void DrawImage(BRect rect);
@ -176,6 +177,7 @@ private:
Scaler* fScaler; // holds the scaled image if bilinear scaling is enabled
bool fShrinkToBounds; // shrink images to view bounds that are larger than the view
bool fZoomToBounds; // zoom images to view bounds that are smaller than the view
bool fShrinkOrZoomToBounds;
bool fHasBorder; // should the image have a border?
alignment fHAlignment; // horizontal alignment (left and centered only)
vertical_alignment fVAlignment; // vertical alignment (left and centered only)

View File

@ -286,6 +286,7 @@ ShowImageWindow::LoadMenus(BMenuBar *pbar)
AddItemMenu(pmenu, "Next Page", MSG_PAGE_NEXT, B_RIGHT_ARROW, 0, 'W', true);
AddItemMenu(pmenu, "Previous Page", MSG_PAGE_PREV, B_LEFT_ARROW, 0, 'W', true);
fGoToPageMenu = new BMenu("Go To Page");
fGoToPageMenu->SetRadioMode(true);
pmenu->AddItem(fGoToPageMenu);
pmenu->AddSeparatorItem();
AddItemMenu(pmenu, "Next File", MSG_FILE_NEXT, B_DOWN_ARROW, 0, 'W', true);
@ -513,11 +514,6 @@ ShowImageWindow::MessageReceived(BMessage *pmsg)
BMenuItem *pcurItem;
pcurItem = fGoToPageMenu->ItemAt(curPage - 1);
if (!pcurItem->IsMarked()) {
// If the current page isn't marked, unmark everything
// then mark the current page
int32 items = fGoToPageMenu->CountItems();
for (int32 i = 0; i < items; i++)
fGoToPageMenu->ItemAt(i)->SetMarked(false);
pcurItem->SetMarked(true);
}
}