- 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:
parent
2d6fb9b82d
commit
5e427b6a85
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user