1 /* libsswf_blendmode.c++ -- written by Alexis WILKE for Made to Order Software Corp. (c) 2002-2008 */
2 
3 /*
4 
5 Copyright (c) 2002-2008 Made to Order Software Corp.
6 
7 Permission is hereby granted, free of charge, to any
8 person obtaining a copy of this software and
9 associated documentation files (the "Software"), to
10 deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify,
12 merge, publish, distribute, sublicense, and/or sell
13 copies of the Software, and to permit persons to whom
14 the Software is furnished to do so, subject to the
15 following conditions:
16 
17 The above copyright notice and this permission notice
18 shall be included in all copies or substantial
19 portions of the Software.
20 
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
22 ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
23 LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
24 FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
25 EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
27 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
28 ARISING FROM, OUT OF OR IN CONNECTION WITH THE
29 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 SOFTWARE.
31 
32 */
33 
34 /** \file
35  *
36  * \brief The implementation of the sswf::BlendMode class
37  *
38  * This file declares the body of the functions which are not
39  * inline. It is part of the SSWF library.
40  */
41 
42 #include	"sswf/libsswf.h"
43 
44 using namespace sswf;
45 
46 
47 
48 /////////////////////////////////////////// State
49 
50 
51 /** \class sswf::BlendMode
52  *
53  * \brief The mode used to render the object on the screen
54  *
55  * This class was introduced in version 1.8.0.
56  *
57  * This class is used to declare a blending mode which can be
58  * shared by different classes.
59  *
60  * \sa sswf::State
61  * \sa sswf::TagPlace
62  * \sa <a href="../SWFalexref.html#tag_placeobject3">SWF Alexis' Reference&mdash;Place Object 3</a>
63  */
64 
65 
66 /** \enum sswf::BlendMode::blend_mode_t
67  *
68  * \brief List all the available blend modes
69  *
70  * The following lists the blend modes available when placing an object
71  * on your screen.
72  *
73  * In the following, I included formulas which use the following variables:
74  *
75  *	\li R - the resulting color
76  *	\li C - the source color (i.e. the object in the TagPlace or State)
77  *	\li B - the background (i.e. what has been drawn before this object)
78  *
79  * In some cases, a specific component is affected. This is marked by
80  * a subscript with the component letter (one of RGBA as in: R<sub>a</sub>.)
81  */
82 
83 
84 /** \var sswf::BlendMode::blend_mode_t sswf::BlendMode::BLEND_MODE_UNDEFINED
85  *
86  * \brief According to Macromedia this is the same as sswf::BlendMode::BLEND_MODE_NORMAL
87  *
88  * This value should probably not be used, yet according to the
89  * Macromedia documentation, it is equivalent to sswf::BlendMode::BLEND_MODE_NORMAL
90  *
91  * This is a <i>do nothing</i> blending mode.
92  *
93  * \code
94  * R = C
95  * \endcode
96  */
97 
98 
99 /** \var sswf::BlendMode::blend_mode_t sswf::BlendMode::BLEND_MODE_NORMAL
100  *
101  * \brief A <i>do nothing</i> blending mode
102  *
103  * This blending mode has no effect on the object being placed.
104  *
105  * \note
106  * This may be a place holder in case you want to apply some blending mode
107  * with an ActionScript. Without it you may not be able to apply any blending
108  * mode from a script (TBD).
109  *
110  * \code
111  * R = C
112  * \endcode
113  */
114 
115 
116 /** \var sswf::BlendMode::blend_mode_t sswf::BlendMode::BLEND_MODE_LAYER
117  *
118  * \brief Use multiple objects
119  *
120  * This blending mode uses multiple objects to render the final output. At
121  * this time, it isn't clear to me what this does...
122  */
123 
124 
125 /** \var sswf::BlendMode::blend_mode_t sswf::BlendMode::BLEND_MODE_MULTIPLY
126  *
127  * \brief Multiply the background and the object colors (light effect)
128  *
129  * This blending mode can be used to multiply the background colors with
130  * the object being placed. When the object being placed is a grey scale,
131  * this is a way to apply brightness to the background. Thus you can
132  * generate the effect of a light (or a reflection of a light) on the
133  * screen.
134  *
135 \htmlonly
136 <div class="fragment"><pre class="fragment">
137  R = B &times; C / 255
138 </pre></div>
139 \endhtmlonly
140  */
141 
142 
143 
144 
145 /** \var sswf::BlendMode::blend_mode_t sswf::BlendMode::BLEND_MODE_SCREEN
146  *
147  * \brief Multiply the inverse of the background and the object colors
148  *
149  * There is probably no good reason to use the inverse color of the
150  * object since the object could be rendered properly in the first
151  * place (i.e. if you need 255, use white and if you need 0 use black).
152  * Yet, this filter multiplies the inverse of the background and the
153  * object colors together.
154  *
155 \htmlonly
156 <div class="fragment"><pre class="fragment">
157  R = (255 - B) &times; (255 - C) / 255
158 </pre></div>
159 \endhtmlonly
160  */
161 
162 
163 
164 /** \var sswf::BlendMode::blend_mode_t sswf::BlendMode::BLEND_MODE_LIGHTEN
165  *
166  * \brief Use the largest of the two colors
167  *
168  * Select which of the background or the object being placed has the
169  * largest component.
170  *
171  * Use black in your object to not affect the screen.
172  *
173  * \code
174  * R = max(B, C)
175  * \endcode
176  */
177 
178 
179 
180 /** \var sswf::BlendMode::blend_mode_t sswf::BlendMode::BLEND_MODE_DARKEN
181  *
182  * \brief Use the largest of the two colors
183  *
184  * Select which of the background or the object being placed has the
185  * smallest component.
186  *
187  * Use white in your object to not affect the screen.
188  *
189  * \code
190  * R = min(B, C)
191  * \endcode
192  */
193 
194 
195 
196 /** \var sswf::BlendMode::blend_mode_t sswf::BlendMode::BLEND_MODE_ADD
197  *
198  * \brief Add the object components to the background
199  *
200  * This filter can be used for a strong brightness effect. Watchout, do not
201  * create too bright an object for this blend mode. It would otherwise make
202  * your screen look bad.
203  *
204  * \code
205  * R = max(B + C, 255)
206  * \endcode
207  */
208 
209 
210 
211 /** \var sswf::BlendMode::blend_mode_t sswf::BlendMode::BLEND_MODE_SUBTRACT
212  *
213  * \brief Subject the object components from the background
214  *
215  * This filter can be used for a strong darkning effect. Watchout, do not
216  * create too bright an object for this blend mode. It would otherwise make
217  * your screen look bad.
218  *
219  * \code
220  * R = min(B - C, 0)
221  * \endcode
222  */
223 
224 
225 
226 /** \var sswf::BlendMode::blend_mode_t sswf::BlendMode::BLEND_MODE_DIFFERENCE
227  *
228  * \brief Take the absolute value of the object color minus the background color
229  *
230  * At this time, I'm not too sure what this is for. The colors will loop around
231  * with this object and in general this make the image look <i>weird</i>. May
232  * be a good idea to create some sort of negative effect.
233  *
234  * \code
235  * R = | B - C |
236  * \endcode
237  */
238 
239 
240 
241 /** \var sswf::BlendMode::blend_mode_t sswf::BlendMode::BLEND_MODE_INVERT
242  *
243  * \brief Inverse the background colors
244  *
245  * This filter does not use the source image for anything more than know where
246  * to apply the filter. Otherwise it inverts the color creating a negative
247  * (the same as when you take pictures with your camera, the resulting film
248  * is a negative -- the colors are invered.)
249  *
250  * \code
251  * R = 255 - B
252  * \endcode
253  */
254 
255 
256 
257 /** \var sswf::BlendMode::blend_mode_t sswf::BlendMode::BLEND_MODE_ALPHA
258  *
259  * \brief Copy the object alpha in the background
260  *
261  * This filter copies the alpha channel as is from the object to the background.
262  * Used in a Sprite, I suppose this can be used to switch between different
263  * alpha channels for the same object.
264  *
265 \htmlonly
266 <div class="fragment"><pre class="fragment">
267  R<sub>a</sub> = C<sub>a</sub>
268 </pre></div>
269 \endhtmlonly
270  */
271 
272 
273 
274 /** \var sswf::BlendMode::blend_mode_t sswf::BlendMode::BLEND_MODE_ERASE
275  *
276  * \brief Copy the inverse of the object alpha in the background
277  *
278  * This filter copies the inverts of the alpha channel from the object to
279  * the background. This as the effect of making the object itself
280  * disappear... and what's around appear, I would think.
281  *
282 \htmlonly
283 <div class="fragment"><pre class="fragment">
284  R<sub>a</sub> = 255 - C<sub>a</sub>
285 </pre></div>
286 \endhtmlonly
287  */
288 
289 
290 
291 /** \var sswf::BlendMode::blend_mode_t sswf::BlendMode::BLEND_MODE_OVERLAY
292  *
293  * \brief Applies a MULTIPLY or SCREEN effect depending on the current background colors
294  *
295  * This filter copies the alpha channel as is from the object to the background.
296  *
297 \htmlonly
298 <div class="fragment"><pre class="fragment">
299  R = (B &lt; 128 ? B &times; C : (255 - B) &times; (255 - C)) / 255
300 </pre></div>
301 \endhtmlonly
302  */
303 
304 
305 
306 /** \var sswf::BlendMode::blend_mode_t sswf::BlendMode::BLEND_MODE_HARDLIGHT
307  *
308  * \brief Applies a MULTIPLY or SCREEN effect depending on the current background colors
309  *
310  * This filter copies the alpha channel as is from the object to the background.
311  *
312 \htmlonly
313 <div class="fragment"><pre class="fragment">
314  R = (C &lt; 128 ? B &times; C : (255 - B) &times; (255 - C)) / 255
315 </pre></div>
316 \endhtmlonly
317  */
318 
319 
320 
321 /** \brief Initialize the blend mode to \e undefined
322  *
323  * The constructor initializes the blend mode to the default of:
324  * BLEND_MODE_UNDEFINED.
325  *
326  * \sa sswf::BlendMode::HasBlendMode(void) const
327  */
BlendMode(void)328 BlendMode::BlendMode(void)
329 {
330 	f_blend_mode = BLEND_MODE_UNDEFINED;
331 }
332 
333 
334 /** \brief Test whether a blending filter was defined
335  *
336  * This function determines whether a filter was defined in this BlendMode
337  * object.
338  *
339  * This is the same as testing wheter the BlendMode::HasBlendMode(void) const
340  * function returns BLEND_MODE_UNDEFINED.
341  *
342  * \return \e true when the blend mode is not BLEND_MODE_UNDEFINED; false otherwise
343  *
344  * \sa sswf::BlendMode::SetBlendMode(blend_mode_t blend_mode)
345  * \sa sswf::BlendMode::SetBlendModeByName(const char *blend_mode_name)
346  */
HasBlendMode(void) const347 bool BlendMode::HasBlendMode(void) const
348 {
349 	return f_blend_mode != BLEND_MODE_UNDEFINED;
350 }
351 
352 
353 /** \brief Get the current blending mode
354  *
355  * This function returns the current blending mode as set by SetBlendMode()
356  * or SetBlendModeByName().
357  *
358  * \return The current blend mode
359  *
360  * \sa sswf::BlendMode::SetBlendMode(blend_mode_t blend_mode)
361  * \sa sswf::BlendMode::SetBlendModeByName(const char *blend_mode_name)
362  */
GetBlendMode(void) const363 BlendMode::blend_mode_t BlendMode::GetBlendMode(void) const
364 {
365 	return f_blend_mode;
366 }
367 
368 
369 /** \brief Defines a filter by value
370  *
371  * This function defines the filter to use with a TagPlace or State object.
372  *
373  * \note
374  * Trying to set a mode which does not exist forces the mode to
375  * BLEND_MODE_UNDEFINED.
376  *
377  * \param blend_mode The new blend mode (BLEND_MODE_...)
378  *
379  * \sa sswf::BlendMode::SetBlendModeName(const char *blend_mode_name)
380  */
SetBlendMode(blend_mode_t blend_mode)381 void BlendMode::SetBlendMode(blend_mode_t blend_mode)
382 {
383 	switch(blend_mode) {
384 	default: // case BLEND_MODE_UNDEFINED:
385 		f_blend_mode = BLEND_MODE_UNDEFINED;
386 		break;
387 
388 	case BLEND_MODE_NORMAL:
389 	case BLEND_MODE_LAYER:
390 	case BLEND_MODE_MULTIPLY:
391 	case BLEND_MODE_SCREEN:
392 	case BLEND_MODE_LIGHTEN:
393 	case BLEND_MODE_DARKEN:
394 	case BLEND_MODE_DIFFERENCE:
395 	case BLEND_MODE_ADD:
396 	case BLEND_MODE_SUBTRACT:
397 	case BLEND_MODE_INVERT:
398 	case BLEND_MODE_ALPHA:
399 	case BLEND_MODE_ERASE:
400 	case BLEND_MODE_OVERLAY:
401 	case BLEND_MODE_HARDLIGHT:
402 		f_blend_mode = blend_mode;
403 		break;
404 
405 	}
406 
407 	return;
408 }
409 
410 
411 /** \brief Defines the filter by name
412  *
413  * This function is similar to the sswf::BlendMode::SetBlendMode(blend_mode_t blend_mode)
414  * except that it takes a name instead of a number to define the blending mode
415  * to use.
416  *
417  * The supported names are the same as those found in the
418  * sswf::BlendMode::blend_mode_t enumeration without the "BLEND_MODE_"
419  * part and excluding UNDEFINED (you can reset the blend mode to Undefined
420  * by calling sswf::BlendMode::SetBlendMode(sswf::BlendMode::BLEND_MODE_UNDEFINED) instead.)
421  *
422  * \param blend_mode_name The ASCII name of the blend mode to use
423  *
424  * \return The new blend mode value or BLEND_MODE_UNDEFINED when the input
425  * name was not a valid blend mode
426  *
427  * \sa sswf::TagBase::SetBlendMode(blend_mode_t blend_mode)
428  */
SetBlendModeByName(const char * blend_mode_name)429 bool BlendMode::SetBlendModeByName(const char *blend_mode_name)
430 {
431 	f_blend_mode = BLEND_MODE_UNDEFINED;
432 
433 	if(blend_mode_name != 0) switch(blend_mode_name[0]) {
434 	case 'A':
435 		if(strcasecmp(blend_mode_name, "ADD") == 0) {
436 			f_blend_mode = BLEND_MODE_ADD;
437 		}
438 		else if(strcasecmp(blend_mode_name, "ALPHA") == 0) {
439 			f_blend_mode = BLEND_MODE_ALPHA;
440 		}
441 		break;
442 
443 	case 'D':
444 		if(strcasecmp(blend_mode_name, "DARKEN") == 0) {
445 			f_blend_mode = BLEND_MODE_DARKEN;
446 		}
447 		else if(strcasecmp(blend_mode_name, "DIFFERENCE") == 0) {
448 			f_blend_mode = BLEND_MODE_DIFFERENCE;
449 		}
450 		break;
451 
452 	case 'E':
453 		if(strcasecmp(blend_mode_name, "ERASE") == 0) {
454 			f_blend_mode = BLEND_MODE_ERASE;
455 		}
456 		break;
457 
458 	case 'H':
459 		if(strcasecmp(blend_mode_name, "HARDLIGHT") == 0) {
460 			f_blend_mode = BLEND_MODE_HARDLIGHT;
461 		}
462 		break;
463 
464 	case 'I':
465 		if(strcasecmp(blend_mode_name, "INVERT") == 0) {
466 			f_blend_mode = BLEND_MODE_INVERT;
467 		}
468 		break;
469 
470 	case 'L':
471 		if(strcasecmp(blend_mode_name, "LAYER") == 0) {
472 			f_blend_mode = BLEND_MODE_LAYER;
473 		}
474 		else if(strcasecmp(blend_mode_name, "LIGHTEN") == 0) {
475 			f_blend_mode = BLEND_MODE_LIGHTEN;
476 		}
477 		break;
478 
479 	case 'M':
480 		if(strcasecmp(blend_mode_name, "MULTIPLY") == 0) {
481 			f_blend_mode = BLEND_MODE_MULTIPLY;
482 		}
483 		break;
484 
485 	case 'N':
486 		if(strcasecmp(blend_mode_name, "NORMAL") == 0) {
487 			f_blend_mode = BLEND_MODE_NORMAL;
488 		}
489 		break;
490 
491 	case 'O':
492 		if(strcasecmp(blend_mode_name, "OVERLAY") == 0) {
493 			f_blend_mode = BLEND_MODE_OVERLAY;
494 		}
495 		break;
496 
497 	case 'S':
498 		if(strcasecmp(blend_mode_name, "SCREEN") == 0) {
499 			f_blend_mode = BLEND_MODE_SCREEN;
500 		}
501 		else if(strcasecmp(blend_mode_name, "SUBTRACT") == 0) {
502 			f_blend_mode = BLEND_MODE_SUBTRACT;
503 		}
504 		break;
505 
506 	}
507 
508 	return f_blend_mode != BLEND_MODE_UNDEFINED;
509 }
510 
511 
512 
513 /** \brief Save the filter in the specified Data buffer
514  *
515  * This function saves the specified blend mode in the specified Data buffer.
516  *
517  * \param data The Data buffer where the blend mode is to be saved
518  */
Save(Data & data)519 void BlendMode::Save(Data& data)
520 {
521 	data.PutByte(f_blend_mode);
522 }
523 
524 
525 /* The following options fold the documentation; use 'zi' to turn on and off
526  *
527  * vim: foldexpr=getline(v\:lnum)!~'^/\\*\\*'&&getline(v\:lnum)!~'^\ \\*'?0\:1 foldcolumn=2 foldmethod=expr
528  */
529