xref: /haiku/src/apps/haikudepot/ui_generic/BitmapView.cpp (revision 1deede7388b04dbeec5af85cae7164735ea9e70d)
1 /*
2  * Copyright 2013, Stephan Aßmus <superstippi@gmx.de>.
3  * Copyright 2020, Andrew Lindesay <apl@lindesay.co.nz>.
4  * All rights reserved. Distributed under the terms of the MIT License.
5  */
6 
7 
8 #include "BitmapView.h"
9 
10 #include <algorithm>
11 
12 #include <Bitmap.h>
13 #include <LayoutUtils.h>
14 
15 
16 BitmapView::BitmapView(const char* name)
17 	:
18 	BView(name, B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE
19 		| B_TRANSPARENT_BACKGROUND),
20 	fBitmap(NULL),
21 	fScaleBitmap(true)
22 {
23 	 SetViewColor(B_TRANSPARENT_COLOR);
24 }
25 
26 
27 BitmapView::~BitmapView()
28 {
29 }
30 
31 
32 void
33 BitmapView::Draw(BRect updateRect)
34 {
35 	BRect bounds(Bounds());
36 
37 	if (fBitmap == NULL)
38 		return;
39 
40 	BRect bitmapBounds = fBitmap->Bounds();
41 	if (bitmapBounds.Width() <= 0.0f || bitmapBounds.Height() <= 0.0f)
42 		return;
43 
44 	float scale = 1.0f;
45 
46 	if (fScaleBitmap) {
47 		float hScale = bounds.Width() / bitmapBounds.Width();
48 		float vScale = bounds.Height() / bitmapBounds.Height();
49 
50 		scale = std::min(hScale, vScale);
51 	}
52 
53 	float width = bitmapBounds.Width() * scale;
54 	float height = bitmapBounds.Height() * scale;
55 
56 	switch (LayoutAlignment().horizontal) {
57 		case B_ALIGN_LEFT:
58 			break;
59 		case B_ALIGN_RIGHT:
60 			bounds.left = floorf(bounds.right - width);
61 			break;
62 		default:
63 		case B_ALIGN_HORIZONTAL_CENTER:
64 			bounds.left = floorf(bounds.left
65 				+ (bounds.Width() - width) / 2.0f);
66 			break;
67 	}
68 	switch (LayoutAlignment().vertical) {
69 		case B_ALIGN_TOP:
70 			break;
71 		case B_ALIGN_BOTTOM:
72 			bounds.top = floorf(bounds.bottom - height);
73 			break;
74 		default:
75 		case B_ALIGN_VERTICAL_CENTER:
76 			bounds.top = floorf(bounds.top
77 				+ (bounds.Height() - height) / 2.0f);
78 			break;
79 	}
80 
81 	bounds.right = ceilf(bounds.left + width);
82 	bounds.bottom = ceilf(bounds.top + height);
83 
84 	SetDrawingMode(B_OP_ALPHA);
85 	DrawBitmap(fBitmap, bitmapBounds, bounds, B_FILTER_BITMAP_BILINEAR);
86 }
87 
88 
89 BSize
90 BitmapView::MinSize()
91 {
92 	BSize size(0.0f, 0.0f);
93 
94 	if (fBitmap != NULL) {
95 		BRect bounds = fBitmap->Bounds();
96 		size.width = bounds.Width();
97 		size.height = bounds.Height();
98 	}
99 
100 	return BLayoutUtils::ComposeSize(ExplicitMinSize(), size);
101 }
102 
103 
104 BSize
105 BitmapView::PreferredSize()
106 {
107 	BSize size = MinSize();
108 	return BLayoutUtils::ComposeSize(ExplicitPreferredSize(), size);
109 }
110 
111 
112 BSize
113 BitmapView::MaxSize()
114 {
115 	BSize size = MinSize();
116 	return BLayoutUtils::ComposeSize(ExplicitMaxSize(), size);
117 }
118 
119 
120 void
121 BitmapView::SetBitmap(SharedBitmap* bitmap, BitmapSize bitmapSize)
122 {
123 	if (bitmap == fReference && bitmapSize == fBitmapSize)
124 		return;
125 
126 	BSize size = MinSize();
127 
128 	fReference.SetTo(bitmap);
129 	fBitmapSize = bitmapSize;
130 	fBitmap = bitmap->Bitmap(bitmapSize);
131 
132 	BSize newSize = MinSize();
133 	if (size != newSize)
134 		InvalidateLayout();
135 
136 	Invalidate();
137 }
138 
139 
140 void
141 BitmapView::UnsetBitmap()
142 {
143 	if (!fReference.IsSet())
144 		return;
145 
146 	fBitmap = NULL;
147 	fReference.Unset();
148 
149 	InvalidateLayout();
150 	Invalidate();
151 }
152 
153 
154 void
155 BitmapView::SetScaleBitmap(bool scaleBitmap)
156 {
157 	if (scaleBitmap == fScaleBitmap)
158 		return;
159 
160 	fScaleBitmap = scaleBitmap;
161 
162 	Invalidate();
163 }
164