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
16BitmapView::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
27BitmapView::~BitmapView()
28{
29}
30
31
32void
33BitmapView::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
89BSize
90BitmapView::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
104BSize
105BitmapView::PreferredSize()
106{
107	BSize size = MinSize();
108	return BLayoutUtils::ComposeSize(ExplicitPreferredSize(), size);
109}
110
111
112BSize
113BitmapView::MaxSize()
114{
115	BSize size = MinSize();
116	return BLayoutUtils::ComposeSize(ExplicitMaxSize(), size);
117}
118
119
120void
121BitmapView::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
140void
141BitmapView::UnsetBitmap()
142{
143	if (!fReference.IsSet())
144		return;
145
146	fBitmap = NULL;
147	fReference.Unset();
148
149	InvalidateLayout();
150	Invalidate();
151}
152
153
154void
155BitmapView::SetScaleBitmap(bool scaleBitmap)
156{
157	if (scaleBitmap == fScaleBitmap)
158		return;
159
160	fScaleBitmap = scaleBitmap;
161
162	Invalidate();
163}
164