1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #include "backends/cloud/cloudicon.h"
24 #include "common/memstream.h"
25 #include "common/system.h"
26 #include "image/png.h"
27 
28 namespace Cloud {
29 
30 const float CloudIcon::ALPHA_SPEED = 0.0005f;
31 const float CloudIcon::ALPHA_MAX = 1.f;
32 const float CloudIcon::ALPHA_MIN = 0.6f;
33 
CloudIcon()34 CloudIcon::CloudIcon() {
35 	initIcons();
36 	hide();
37 	_lastUpdateTime = g_system->getMillis();
38 }
39 
~CloudIcon()40 CloudIcon::~CloudIcon() {
41 	_icon.free();
42 	_disabledIcon.free();
43 	_alphaIcon.free();
44 }
45 
show(CloudIcon::Type icon,int duration)46 void CloudIcon::show(CloudIcon::Type icon, int duration) {
47 	if (_type == icon) {
48 		return; // Nothing to do
49 	}
50 
51 	if (icon != kNone) {
52 		_state = kShown;
53 		_type = icon;
54 
55 		if (duration) {
56 			_hideTime = g_system->getMillis() + duration;
57 		} else {
58 			_hideTime = 0;
59 		}
60 	} else {
61 		_state = kGoingToHide;
62 	}
63 }
64 
hide()65 void CloudIcon::hide() {
66 	_state = kHidden;
67 	_type = kNone;
68 	_hideTime = 0;
69 	_currentAlpha = 0;
70 	_alphaRising = true;
71 }
72 
getShownType() const73 CloudIcon::Type CloudIcon::getShownType() const {
74 	return _type;
75 }
76 
needsUpdate() const77 bool CloudIcon::needsUpdate() const {
78 	uint32 delaySinceLastUpdate = g_system->getMillis(true) - _lastUpdateTime;
79 	return delaySinceLastUpdate >= UPDATE_DELAY_MIN_MILLIS;
80 }
81 
update()82 void CloudIcon::update() {
83 	uint32 currentTime = g_system->getMillis(true);
84 	uint32 delaySinceLastUpdate = currentTime - _lastUpdateTime;
85 	_lastUpdateTime = currentTime;
86 
87 	switch (_state) {
88 	default:
89 		// fallthrough intended
90 	case kHidden:
91 		return; // Nothing to do
92 	case kShown:
93 		if (_alphaRising) {
94 			if (_currentAlpha < ALPHA_MIN)
95 				_currentAlpha += 5 * ALPHA_SPEED * delaySinceLastUpdate;
96 			else
97 				_currentAlpha += ALPHA_SPEED * delaySinceLastUpdate;
98 			if (_currentAlpha > ALPHA_MAX) {
99 				_currentAlpha = ALPHA_MAX;
100 				_alphaRising = false;
101 			}
102 		} else {
103 			_currentAlpha -= ALPHA_SPEED * delaySinceLastUpdate;
104 			if (_currentAlpha < ALPHA_MIN) {
105 				_currentAlpha = ALPHA_MIN;
106 				_alphaRising = true;
107 			}
108 		}
109 
110 		if (_hideTime != 0 && _hideTime <= currentTime) {
111 			_hideTime = 0;
112 			_state = kGoingToHide;
113 		}
114 		break;
115 	case kGoingToHide:
116 		_currentAlpha -= 5 * ALPHA_SPEED * delaySinceLastUpdate;
117 		if (_currentAlpha <= 0) {
118 			hide();
119 		}
120 		break;
121 	}
122 
123 	if (!_icon.getPixels() || !_disabledIcon.getPixels()) {
124 		// Loading the icons failed. Don't try to draw them.
125 		return;
126 	}
127 
128 	if (_state != kHidden) {
129 		makeAlphaIcon((_type == kDisabled ? _disabledIcon : _icon), _currentAlpha);
130 		g_system->displayActivityIconOnOSD(&_alphaIcon);
131 	} else {
132 		g_system->displayActivityIconOnOSD(nullptr);
133 	}
134 }
135 
136 #include "backends/cloud/cloudicon_data.h"
137 #include "backends/cloud/cloudicon_disabled_data.h"
138 
initIcons()139 void CloudIcon::initIcons() {
140 	loadIcon(_icon, cloudicon_data, ARRAYSIZE(cloudicon_data));
141 	loadIcon(_disabledIcon, cloudicon_disabled_data, ARRAYSIZE(cloudicon_disabled_data));
142 }
143 
loadIcon(Graphics::Surface & icon,byte * data,uint32 size)144 void CloudIcon::loadIcon(Graphics::Surface &icon, byte *data, uint32 size) {
145 	Image::PNGDecoder decoder;
146 	Common::MemoryReadStream stream(data, size);
147 	if (!decoder.loadStream(stream)) {
148 		warning("CloudIcon::loadIcon: error decoding PNG");
149 		return;
150 	}
151 
152 	const Graphics::Surface *s = decoder.getSurface();
153 	icon.copyFrom(*s);
154 }
155 
makeAlphaIcon(const Graphics::Surface & icon,float alpha)156 void CloudIcon::makeAlphaIcon(const Graphics::Surface &icon, float alpha) {
157 	_alphaIcon.copyFrom(icon);
158 
159 	byte *pixels = (byte *)_alphaIcon.getPixels();
160 	for (int y = 0; y < _alphaIcon.h; y++) {
161 		byte *row = pixels + y * _alphaIcon.pitch;
162 		for (int x = 0; x < _alphaIcon.w; x++) {
163 			uint32 srcColor;
164 			if (_alphaIcon.format.bytesPerPixel == 2)
165 				srcColor = READ_UINT16(row);
166 			else if (_alphaIcon.format.bytesPerPixel == 3)
167 				srcColor = READ_UINT24(row);
168 			else
169 				srcColor = READ_UINT32(row);
170 
171 			// Update color's alpha
172 			byte r, g, b, a;
173 			_alphaIcon.format.colorToARGB(srcColor, a, r, g, b);
174 			a = (byte)(a * alpha);
175 			uint32 color = _alphaIcon.format.ARGBToColor(a, r, g, b);
176 
177 			if (_alphaIcon.format.bytesPerPixel == 2)
178 				*((uint16 *)row) = color;
179 			else
180 				*((uint32 *)row) = color;
181 
182 			row += _alphaIcon.format.bytesPerPixel;
183 		}
184 	}
185 }
186 
187 } // End of namespace Cloud
188