Mercurial > mplayer.hg
annotate gui/win32/widgetrender.c @ 33534:22c3241467b3
Remove function Normalize().
This function changed ARGB data as if it had been RGB24 data (not quite
correctly) converted to ARGB with all colors transparent.
Instead now, set the alpha channel for RGB24 data and leave ARGB data
untouched.
For X11, the alpha channel is disregarded, so both approaches are equal,
but the new one is more intelligible as we get correct ARGB PNG data.
For legacy reasons, all kind of fuchsia/magenta must be treated as
transparent, because some skins are using at least both full opaque and
full transparent fuchsia/magenta for transparency.
author | ib |
---|---|
date | Thu, 16 Jun 2011 11:19:15 +0000 |
parents | 548499b3f354 |
children | c5a19bbeac2b |
rev | line source |
---|---|
23077 | 1 /* |
23079 | 2 * MPlayer GUI for Win32 |
3 * Copyright (C) 2003 Sascha Sommer <saschasommer@freenet.de> | |
4 * Copyright (C) 2006 Erik Augustson <erik_27can@yahoo.com> | |
5 * Copyright (C) 2006 Gianluigi Tiesi <sherpya@netfarm.it> | |
6 * | |
7 * This file is part of MPlayer. | |
8 * | |
9 * MPlayer is free software; you can redistribute it and/or modify | |
10 * it under the terms of the GNU General Public License as published by | |
11 * the Free Software Foundation; either version 2 of the License, or | |
12 * (at your option) any later version. | |
13 * | |
14 * MPlayer is distributed in the hope that it will be useful, | |
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 * GNU General Public License for more details. | |
18 * | |
26457 | 19 * You should have received a copy of the GNU General Public License along |
20 * with MPlayer; if not, write to the Free Software Foundation, Inc., | |
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
23079 | 22 */ |
23077 | 23 |
24 #include <stdio.h> | |
25 #include <ctype.h> | |
26 #include <windows.h> | |
23091
52488bb09d90
Consistently use quotes instead of angled brackets in #include
diego
parents:
23079
diff
changeset
|
27 |
26372
76413880bfad
Update include paths to account for build system changes.
diego
parents:
23091
diff
changeset
|
28 #include "gui/interface.h" |
23077 | 29 #include "gui.h" |
30 | |
31 #define MAX_LABELSIZE 250 | |
32 | |
33 static void render(int bitsperpixel, image *dst, image *src, int x, int y, int sx, int sy, int sw, int sh, int transparent) | |
34 { | |
35 int i; | |
36 int bpp = bitsperpixel / 8; | |
37 int offset = (dst->width * bpp * y) + (x * bpp); | |
38 int soffset = (src->width * bpp * sy) + (sx * bpp); | |
39 | |
40 for(i=0; i<sh; i++) | |
41 { | |
42 int c; | |
43 for(c=0; c < (sw * bpp); c += bpp) | |
44 { | |
45 if(bpp == 2) | |
46 { | |
47 if(!transparent || (((src->data + soffset + (i * src->width * bpp) + c)[0] != 0x1f) | |
48 && ((src->data + soffset + (i * src->width * bpp) + c)[1] != 0x7c))) | |
49 memcpy(dst->data + offset + c, src->data + soffset + (i * src->width * bpp) + c, bpp); | |
50 } | |
51 else if(bpp > 2) | |
52 { | |
33534 | 53 if(!transparent || !IS_TRANSPARENT(*((unsigned int *) (src->data + soffset + (i * src->width * bpp) + c)))) |
23077 | 54 memcpy(dst->data + offset + c, src->data + soffset + (i * src->width * bpp) + c, bpp); |
55 } | |
56 } | |
57 offset += (dst->width * bpp); | |
58 } | |
59 } | |
60 | |
61 static image *find_background(skin_t *skin, widget *item) | |
62 { | |
63 unsigned int i; | |
64 for (i=0; i < skin->windowcount; i++) | |
65 if(skin->windows[i]->type == item->window) | |
66 return skin->windows[i]->base->bitmap[0]; | |
67 return NULL; | |
68 } | |
69 | |
70 /******************************************************************/ | |
71 /* FONT related functions */ | |
72 /******************************************************************/ | |
73 | |
74 /* returns the pos of s2 inside s1 or -1 if s1 doesn't contain s2 */ | |
75 static int strpos(char *s1, const char* s2) | |
76 { | |
77 unsigned int i, x; | |
78 for (i=0; i < strlen(s1); i++) | |
79 { | |
80 if(s1[i] == s2[0]) | |
81 { | |
82 if(strlen(s1 + i) >= strlen(s2)) | |
83 { | |
84 for (x=0; x <strlen(s2); x++) | |
85 if(s1[i + x] != s2[x]) break; | |
86 if(x == strlen(s2)) return i; | |
87 } | |
88 } | |
89 } | |
90 return -1; | |
91 } | |
92 | |
93 /* replaces all occurences of what in dest with format */ | |
94 static void stringreplace(char *dest, const char *what, const char *format, ... ) | |
95 { | |
96 char tmp[MAX_LABELSIZE]; | |
97 int offset=0; | |
98 va_list va; | |
99 va_start(va, format); | |
100 vsnprintf(tmp, MAX_LABELSIZE, format, va); | |
101 va_end(va); | |
102 /* no search string == replace the entire string */ | |
103 if(!what) | |
104 { | |
105 memcpy(dest, tmp, strlen(tmp)); | |
106 dest[strlen(tmp)] = 0; | |
107 return; | |
108 } | |
109 while((offset = strpos(dest, what)) != -1) | |
110 { | |
111 memmove(dest + offset + strlen(tmp), dest + offset + strlen(what), strlen(dest + offset + strlen(what)) + 1); | |
112 memcpy(dest + offset, tmp, strlen(tmp)); | |
113 } | |
114 } | |
115 | |
116 /* replaces the chars with special meaning with the associated data from the player info struct */ | |
117 static char *generatetextfromlabel(widget *item) | |
118 { | |
119 char *text = malloc(MAX_LABELSIZE); | |
120 char tmp[MAX_LABELSIZE]; | |
121 unsigned int i; | |
122 if(!item) | |
123 { | |
124 free(text); | |
125 return NULL; | |
126 } | |
127 strcpy(text, item->label); | |
128 if(item->type == tySlabel) return text; | |
129 stringreplace(text, "$1", "%.2i:%.2i:%.2i", guiIntfStruct.TimeSec / 3600, | |
130 (guiIntfStruct.TimeSec / 60) % 60, guiIntfStruct.TimeSec % 60); | |
131 stringreplace(text, "$2", "%.4i:%.2i", guiIntfStruct.TimeSec / 60, guiIntfStruct.TimeSec % 60); | |
132 stringreplace(text, "$3", "%.2i", guiIntfStruct.TimeSec / 3600); | |
133 stringreplace(text, "$4", "%.2i", (guiIntfStruct.TimeSec / 60) % 60); | |
134 stringreplace(text, "$5", "%.2i", guiIntfStruct.TimeSec % 60); | |
135 stringreplace(text, "$6", "%.2i:%.2i:%.2i", guiIntfStruct.LengthInSec / 3600, | |
136 (guiIntfStruct.LengthInSec / 60) % 60, guiIntfStruct.LengthInSec % 60); | |
137 stringreplace(text, "$7", "%.4i:%.2i", guiIntfStruct.LengthInSec / 60, guiIntfStruct.LengthInSec % 60); | |
138 stringreplace(text, "$8", "%i:%.2i:%.2i", guiIntfStruct.TimeSec / 3600, | |
139 (guiIntfStruct.TimeSec / 60) % 60, guiIntfStruct.TimeSec % 60); | |
140 stringreplace(text, "$v", "%3.2f", guiIntfStruct.Volume); | |
141 stringreplace(text, "$V", "%3.1f", guiIntfStruct.Volume); | |
142 stringreplace(text, "$b", "%3.2f", guiIntfStruct.Balance); | |
143 stringreplace(text, "$B", "%3.1f", guiIntfStruct.Balance); | |
144 stringreplace(text, "$t", "%.2i", guiIntfStruct.Track); | |
145 stringreplace(text, "$o", "%s", guiIntfStruct.Filename); | |
146 stringreplace(text, "$x", "%i", guiIntfStruct.MovieWidth); | |
147 stringreplace(text, "$y", "%i", guiIntfStruct.MovieHeight); | |
148 stringreplace(text, "$C", "%s", guiIntfStruct.sh_video ? codecname : ""); | |
149 stringreplace(text, "$$", "$"); | |
150 | |
151 if(!strcmp(text, "$p") || !strcmp(text, "$s") || !strcmp(text, "$e")) | |
152 { | |
153 if(guiIntfStruct.Playing == 0) stringreplace(text, NULL, "s"); | |
154 else if(guiIntfStruct.Playing == 1) stringreplace(text, NULL, "p"); | |
155 else if(guiIntfStruct.Playing == 2) stringreplace(text, NULL, "e"); | |
156 } | |
157 | |
158 if(guiIntfStruct.AudioType == 0) stringreplace(text, "$a", "n"); | |
159 else if(guiIntfStruct.AudioType == 1) stringreplace(text, "$a", "m"); | |
160 else stringreplace(text, "$a", "t"); | |
161 | |
162 if(guiIntfStruct.StreamType == 0) | |
163 stringreplace(text, "$T", "f"); | |
27341
e7c989f7a7c9
Start unifying names of internal preprocessor directives.
diego
parents:
26457
diff
changeset
|
164 #ifdef CONFIG_DVDREAD |
23077 | 165 else if(guiIntfStruct.StreamType == STREAMTYPE_DVD || guiIntfStruct.StreamType == STREAMTYPE_DVDNAV) |
166 stringreplace(text, "$T", "d"); | |
167 #endif | |
168 else stringreplace(text, "$T", "u"); | |
169 | |
170 if(guiIntfStruct.Filename) | |
171 { | |
172 for (i=0; i<strlen(guiIntfStruct.Filename); i++) | |
173 tmp[i] = tolower(guiIntfStruct.Filename[i]); | |
174 stringreplace(text, "$f", tmp); | |
175 | |
176 for (i=0; i<strlen(guiIntfStruct.Filename); i++) | |
177 tmp[i] = toupper(guiIntfStruct.Filename[i]); | |
178 stringreplace(text, "$F", tmp); | |
179 } | |
180 | |
181 return text; | |
182 } | |
183 | |
184 /* cuts text to buflen scrolling from right to left */ | |
185 static void scrolltext(char *text, unsigned int buflen, float *value) | |
186 { | |
30702 | 187 char *buffer = malloc(buflen + 1); |
23077 | 188 unsigned int x,i; |
189 if(*value < buflen) x = 0; | |
190 else x = *value - buflen; | |
191 memset(buffer, ' ', buflen); | |
192 for (i = (*value>=buflen) ? 0 : buflen - *value; i<buflen; i++) | |
193 { | |
194 if(x < strlen(text)) | |
195 buffer[i] = text[x]; | |
196 x++; | |
197 } | |
198 buffer[buflen] = 0; | |
199 *value += 1.0f; | |
200 if(*value >= strlen(text) + buflen) *value = 0.0f; | |
201 strcpy(text, buffer); | |
202 free(buffer); | |
203 } | |
204 | |
205 /* updates all dlabels and slabels */ | |
206 void renderinfobox(skin_t *skin, window_priv_t *priv) | |
207 { | |
208 unsigned int i; | |
209 if (!priv) return; | |
210 | |
211 /* repaint the area behind the text*/ | |
212 /* we have to do this for all labels here, because they may overlap in buggy skins ;( */ | |
213 | |
214 for (i=0; i<skin->widgetcount; i++) | |
215 if((skin->widgets[i]->type == tyDlabel) || (skin->widgets[i]->type == tySlabel)) | |
216 { | |
217 if(skin->widgets[i]->window == priv->type) | |
218 render(skin->desktopbpp, | |
219 &priv->img, | |
220 find_background(skin, skin->widgets[i]), | |
221 skin->widgets[i]->x, | |
222 skin->widgets[i]->y, | |
223 skin->widgets[i]->x, | |
224 skin->widgets[i]->y, | |
225 skin->widgets[i]->length, | |
226 skin->widgets[i]->font->chars[0]->height, | |
227 1); | |
228 } | |
229 | |
230 /* load all slabels and dlabels */ | |
231 for (i=0; i<skin->widgetcount; i++) | |
232 { | |
233 widget *item = skin->widgets[i]; | |
234 if(item->window != priv->type) continue; | |
235 if((i == skin->widgetcount) || (item->type == tyDlabel) || (item->type == tySlabel)) | |
236 { | |
237 char *text = generatetextfromlabel(item); | |
238 unsigned int current, c; | |
239 int offset = 0; | |
240 unsigned int textlen; | |
241 if(!text) continue; | |
242 textlen = strlen(text); | |
243 | |
244 /* render(win, win->background, gui->skin->widgets[i]->x, gui->skin->widgets[i]->y, | |
245 gui->skin->widgets[i]->x, gui->skin->widgets[i]->y, | |
246 gui->skin->widgets[i]->length, gui->skin->widgets[i]->font->chars[0]->height,1); */ | |
247 | |
248 /* calculate text size */ | |
249 for (current=0; current<textlen; current++) | |
250 { | |
251 for (c=0; c<item->font->charcount; c++) | |
252 if(item->font->chars[c]->c == text[current]) | |
253 { | |
254 offset += item->font->chars[c]->width; | |
255 break; | |
256 } | |
257 } | |
258 | |
259 /* labels can be scrolled if they are to big */ | |
260 if((item->type == tyDlabel) && (item->length < offset)) | |
261 { | |
262 int tomuch = (offset - item->length) / (offset /textlen); | |
263 scrolltext(text, textlen - tomuch - 1, &skin->widgets[i]->value); | |
264 textlen = strlen(text); | |
265 } | |
266 | |
267 /* align the text */ | |
268 if(item->align == 1) | |
269 offset = (item->length-offset) / 2; | |
270 else if(item->align == 2) | |
271 offset = item->length-offset; | |
272 else | |
273 offset = 0; | |
274 | |
275 if(offset < 0) offset = 0; | |
276 | |
277 /* render the text */ | |
278 for (current=0; current<textlen; current++) | |
279 { | |
280 for (c=0; c<item->font->charcount; c++) | |
281 { | |
282 char_t *cchar = item->font->chars[c]; | |
283 if(cchar->c == *(text + current)) | |
284 { | |
285 render(skin->desktopbpp, | |
286 &priv->img, | |
287 item->font->image, | |
288 item->x + offset, | |
289 item->y, | |
290 cchar->x, | |
291 cchar->y, | |
292 (cchar->width + offset > item->length) ? item->length - offset : cchar->width, | |
293 cchar->height, | |
294 1); | |
295 offset += cchar->width; | |
296 break; | |
297 } | |
298 } | |
299 } | |
300 free(text); | |
301 } | |
302 } | |
303 } | |
304 | |
305 /******************************************************************/ | |
306 /* WIDGET related functions */ | |
307 /******************************************************************/ | |
308 | |
309 void renderwidget(skin_t *skin, image *dest, widget *item, int state) | |
310 { | |
311 image *img = NULL; | |
312 int height; | |
313 int y; | |
314 | |
315 if(!dest) return; | |
316 if((item->type == tyButton) || (item->type == tyHpotmeter) || (item->type == tyPotmeter)) | |
317 img = item->bitmap[0]; | |
318 | |
319 if(!img) return; | |
320 | |
321 y = item->y; | |
322 if(item->type == tyPotmeter) | |
323 { | |
324 height = img->height / item->phases; | |
325 y = height * (int)(item->value * item->phases / 100); | |
326 if(y > img->height-height) | |
327 y = img->height - height; | |
328 } | |
329 else | |
330 { | |
331 height = img->height / 3; | |
332 y = state * height; | |
333 } | |
334 | |
335 /* redraw background */ | |
336 if(item->type == tyButton) | |
337 render(skin->desktopbpp, dest, find_background(skin,item), item->x, item->y, item->x, item->y, img->width, height, 1); | |
338 | |
339 if((item->type == tyHpotmeter) || (item->type == tyPotmeter)) | |
340 { | |
341 /* repaint the area behind the slider */ | |
342 render(skin->desktopbpp, dest, find_background(skin, item), item->wx, item->wy, item->wx, item->wy, item->wwidth, item->height, 1); | |
343 item->x = item->value * (item->wwidth-item->width) / 100 + item->wx; | |
344 if((item->x + item->width) > (item->wx + item->wwidth)) | |
345 item->x = item->wx + item->wwidth - item->width; | |
346 if(item->x < item->wx) | |
347 item->x = item->wx; | |
348 /* workaround for blue */ | |
349 if(item->type == tyHpotmeter) | |
350 height = (item->height < img->height / 3) ? item->height : img->height / 3; | |
351 } | |
352 render(skin->desktopbpp, dest, img, item->x, item->y, 0, y, img->width, height, 1); | |
353 } |