From 5e427b6a8516ef2ffa0832e70509a5201c2e7d23 Mon Sep 17 00:00:00 2001 From: Michael Pfeiffer Date: Sat, 22 Nov 2003 11:02:57 +0000 Subject: [PATCH] - 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 --- src/apps/showimage/Filter.cpp | 165 +++++++++++++++++++++---- src/apps/showimage/Filter.h | 24 ++++ src/apps/showimage/ShowImageView.cpp | 61 +++++---- src/apps/showimage/ShowImageView.h | 4 +- src/apps/showimage/ShowImageWindow.cpp | 6 +- 5 files changed, 200 insertions(+), 60 deletions(-) diff --git a/src/apps/showimage/Filter.cpp b/src/apps/showimage/Filter.cpp index 4e46d33247..cdb8c5fa10 100644 --- a/src/apps/showimage/Filter.cpp +++ b/src/apps/showimage/Filter.cpp @@ -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((number) * kFPPrecisionFactor) -#define from_fixed_point(number) ((number) / kFPPrecisionFactor) -#define to_float(number) from_fixed_point(static_cast(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(totalSum[0] / deltaY); + destData[1] = static_cast(totalSum[1] / deltaY); + destData[2] = static_cast(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); + } } diff --git a/src/apps/showimage/Filter.h b/src/apps/showimage/Filter.h index 2b970899cf..f09d72450e 100644 --- a/src/apps/showimage/Filter.h +++ b/src/apps/showimage/Filter.h @@ -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((number) * kFPPrecisionFactor) +#define from_fixed_point(number) ((number) / kFPPrecisionFactor) +#define to_float(number) from_fixed_point(static_cast(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; }; diff --git a/src/apps/showimage/ShowImageView.cpp b/src/apps/showimage/ShowImageView.cpp index 9c924ab73a..25a362dd44 100644 --- a/src/apps/showimage/ShowImageView.cpp +++ b/src/apps/showimage/ShowImageView.cpp @@ -47,6 +47,7 @@ #include #include #include +#include #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; diff --git a/src/apps/showimage/ShowImageView.h b/src/apps/showimage/ShowImageView.h index a8f75affe4..c7dc301d7e 100644 --- a/src/apps/showimage/ShowImageView.h +++ b/src/apps/showimage/ShowImageView.h @@ -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) diff --git a/src/apps/showimage/ShowImageWindow.cpp b/src/apps/showimage/ShowImageWindow.cpp index 8546baf826..b6cce699eb 100644 --- a/src/apps/showimage/ShowImageWindow.cpp +++ b/src/apps/showimage/ShowImageWindow.cpp @@ -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); } }