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.0005;
31 const float CloudIcon::ALPHA_MAX = 1;
32 const float CloudIcon::ALPHA_MIN = 0.6;
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() - _lastUpdateTime;
79 	return delaySinceLastUpdate >= UPDATE_DELAY_MIN_MILLIS;
80 }
81 
update()82 void CloudIcon::update() {
83 	uint32 currentTime = g_system->getMillis();
84 	uint32 delaySinceLastUpdate = currentTime - _lastUpdateTime;
85 	_lastUpdateTime = currentTime;
86 
87 	switch (_state) {
88 	case kHidden:
89 		return; // Nothing to do
90 	case kShown:
91 		if (_alphaRising) {
92 			if (_currentAlpha < ALPHA_MIN)
93 				_currentAlpha += 5 * ALPHA_SPEED * delaySinceLastUpdate;
94 			else
95 				_currentAlpha += ALPHA_SPEED * delaySinceLastUpdate;
96 			if (_currentAlpha > ALPHA_MAX) {
97 				_currentAlpha = ALPHA_MAX;
98 				_alphaRising = false;
99 			}
100 		} else {
101 			_currentAlpha -= ALPHA_SPEED * delaySinceLastUpdate;
102 			if (_currentAlpha < ALPHA_MIN) {
103 				_currentAlpha = ALPHA_MIN;
104 				_alphaRising = true;
105 			}
106 		}
107 
108 		if (_hideTime != 0 && _hideTime <= currentTime) {
109 			_hideTime = 0;
110 			_state = kGoingToHide;
111 		}
112 		break;
113 	case kGoingToHide:
114 		_currentAlpha -= 5 * ALPHA_SPEED * delaySinceLastUpdate;
115 		if (_currentAlpha <= 0) {
116 			hide();
117 		}
118 		break;
119 	}
120 
121 	if (!_icon.getPixels() || !_disabledIcon.getPixels()) {
122 		// Loading the icons failed. Don't try to draw them.
123 		return;
124 	}
125 
126 	if (_state != kHidden) {
127 		makeAlphaIcon((_type == kDisabled ? _disabledIcon : _icon), _currentAlpha);
128 		g_system->displayActivityIconOnOSD(&_alphaIcon);
129 	} else {
130 		g_system->displayActivityIconOnOSD(nullptr);
131 	}
132 }
133 
134 #include "backends/cloud/cloudicon_data.h"
135 #include "backends/cloud/cloudicon_disabled_data.h"
136 
initIcons()137 void CloudIcon::initIcons() {
138 	loadIcon(_icon, cloudicon_data, ARRAYSIZE(cloudicon_data));
139 	loadIcon(_disabledIcon, cloudicon_disabled_data, ARRAYSIZE(cloudicon_disabled_data));
140 }
141 
loadIcon(Graphics::Surface & icon,byte * data,uint32 size)142 void CloudIcon::loadIcon(Graphics::Surface &icon, byte *data, uint32 size) {
143 	Image::PNGDecoder decoder;
144 	Common::MemoryReadStream stream(data, size);
145 	if (!decoder.loadStream(stream)) {
146 		warning("CloudIcon::loadIcon: error decoding PNG");
147 		return;
148 	}
149 
150 	const Graphics::Surface *s = decoder.getSurface();
151 	icon.copyFrom(*s);
152 }
153 
makeAlphaIcon(const Graphics::Surface & icon,float alpha)154 void CloudIcon::makeAlphaIcon(const Graphics::Surface &icon, float alpha) {
155 	_alphaIcon.copyFrom(icon);
156 
157 	byte *pixels = (byte *)_alphaIcon.getPixels();
158 	for (int y = 0; y < _alphaIcon.h; y++) {
159 		byte *row = pixels + y * _alphaIcon.pitch;
160 		for (int x = 0; x < _alphaIcon.w; x++) {
161 			uint32 srcColor;
162 			if (_alphaIcon.format.bytesPerPixel == 2)
163 				srcColor = READ_UINT16(row);
164 			else if (_alphaIcon.format.bytesPerPixel == 3)
165 				srcColor = READ_UINT24(row);
166 			else
167 				srcColor = READ_UINT32(row);
168 
169 			// Update color's alpha
170 			byte r, g, b, a;
171 			_alphaIcon.format.colorToARGB(srcColor, a, r, g, b);
172 			a = (byte)(a * alpha);
173 			uint32 color = _alphaIcon.format.ARGBToColor(a, r, g, b);
174 
175 			if (_alphaIcon.format.bytesPerPixel == 2)
176 				*((uint16 *)row) = color;
177 			else
178 				*((uint32 *)row) = color;
179 
180 			row += _alphaIcon.format.bytesPerPixel;
181 		}
182 	}
183 }
184 
185 } // End of namespace Cloud
186