2 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Free Software
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 3 of the License, or
8 // (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 #ifndef RENDER_HANDLER_H
23 #define RENDER_HANDLER_H
25 /// \page Renderer_intro Render handler introduction
27 /// Information for writing new render handlers.
29 /// The most important thing about drawing Flash shapes is to understand how
30 /// their fill styles work.
31 /// A single Flash character can contain any number shapes that use any number
32 /// of different fill styles and line styles. The shapes of a character are
33 /// defined by a number of "paths". Some important things about paths:
35 /// - A path is a list of connected straight lines and (quadratic bezier)
36 /// curves (=edges). Interesting to note is that in the Flash world there are
37 /// *no* primitive objects like circles, rectangles or similar. These objects
38 /// are always translated to lines and curves (a circle is a set of eight
41 /// - All paths together must by definition always build a fully closed shape.
42 /// You can't draw a rectangle with three edges, for example, contrary to
43 /// most graphics library polygon routines that connect the last anchor to
44 /// the first. However, a *single* path does *not* have to be closed. The
45 /// missing parts may be defined by other paths (you will see this makes
48 /// - Each path has up to two fill styles and no or one line style. The line
49 /// style should be obvious. The two fill styles define the fill to the left
50 /// (fill style zero) and to the right (fill style one) of the path if you
51 /// think of it like a vector. The fill style is defined by a index to a
52 /// list of previously defined fill style definitions. Index 0 means "no
53 /// style" and is equal to a fully transparent fill style ("hole", if you
56 /// - Paths are *never* self-intersecting.
58 /// Simple examples to understand this concept:
60 /// - A rectangle that contains another rectangle. Only the area between the
61 /// two rectangles is filled (so it looks like a "o"). In this case Flash
62 /// fill create two paths (one for each rectangle) and one fill style.
63 /// Assume both paths come in clockwise order, then the outer rectangle
64 /// will have fillstyle0=0 and fillstyle1=1. The inner rectangle will have
65 /// fillstyle0=1 and fillstyle1=0.
68 /// +--------------------------------+
69 /// |XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX|
70 /// |XXX+------------------------+XXX|
72 /// |XXX+------------------------+XXX|
73 /// |XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX|
74 /// +--------------------------------+
77 /// - A rectangle is divided vertically in two halves, both having different
81 /// +-------A-------+-------B--------+
82 /// |...............|################|
83 /// A...............C################B
84 /// |...............|################|
85 /// +-------A-------+-------B--------+
88 /// Flash will probably produce three paths (A,B,C) and two fill styles.
89 /// Paths "A" and "B" will have just one fill style (fillstyle1 will be
90 /// zero) while path "C" (which contains only one straight line!!) will
91 /// have two fill styles. To be exact the horizontal edges would not even
92 /// be necessary to render this shape (for a scanline based renderer) but
93 /// they are necessary then the character is about to be rotated.
95 /// Now, these are simple examples but complex graphics can be compressed very
96 /// efficiently this way. Also, this method was most probably intended for a
97 /// renderer engine that can produce the final character in just one pass
98 /// (like the AGG backend does too).
101 /// \page region_update Detection of updated regions
103 /// (this applies to the whole Gnash playback architecture)
105 /// After advancing the root movie (see gnash::Gui::advance_movie) it is checked
106 /// which region of the stage has been changed visibly (by computing the
107 /// bounds around updated characters). This has two advantages:
109 /// 1st, it allows a renderer/gui combination to avoid re-rendering of
110 /// unchanged parts in the scene. When supported by the rendering engine
111 /// this can be a huge performance gain. The original Flash player does
112 /// that too, btw. Altough he is able to define multiple smaller regions
113 /// for one frame. This could be implemented in Gnash, too.
115 /// 2nd, it can detect still frames (like a stopped movie). gui.cpp can
116 /// detect these and completely avoid calling any rendering function.
118 /// Of course, the most critical part is detection of changes. There is a
119 /// method gnash::character::set_invalidated() which gets called whenever a
120 /// critical property of a instance gets updated, like when it changes
121 /// position, for example.
122 /// It's really important to *always* call set_invalidated() *before*
123 /// any call that changes the character instance in a visible way.
125 /// Even if no renderer really uses this information it has effects when
126 /// skipping unchanged frames. If necessary, this feature can be switched
127 /// off easily in gui.cpp (maybe using a runtime option?).
129 /// Note the updated region is only passed to the gnash::Gui, which is itself
130 /// responsible of informing the renderer (see gnash::Gui::set_invalidated_region).
131 /// This is because it's pointless
132 /// to have a renderer which updates only a small part of the stage when
133 /// the GUI shows it all since the area around the region is undefined.
134 /// However, there can be a GUI which supports update regions without needing
135 /// the renderer to do so (for example, to save time during blitting).
136 /// The GUI can also completely ignore the region information.
138 /// It's also importanto to note that the bounds passed to the GUI are just
139 /// a hint and the GUI /is/ allowed to further process and alter the information
142 /// As for the integer/float discussion: I used SWFRect (floats) because all
143 /// the bounds calculation involves floats anyway and so it's probably
144 /// faster than converting between ints and floats all the way.
148 #include <boost/noncopyable.hpp>
150 #include "dsodefs.h" // for DSOEXPORT
152 #include "GnashEnums.h"
157 #include "snappingrange.h"
160 // Forward declarations.
172 // XXX: GnashImageProxy (delayed image rendering)
173 class GnashVaapiImageProxy
;
185 /// Base class for render handlers.
187 /// You must define a subclass of Renderer, and pass an
188 /// instance to the core (RunResources) *before* any SWF parsing begins.
190 /// For more info see page \ref Renderer_intro.
191 class DSOEXPORT Renderer
: boost::noncopyable
197 _quality(QUALITY_HIGH
)
200 virtual ~Renderer() {}
202 /// Return a description of this renderer.
203 virtual std::string
description() const = 0;
205 /// ==================================================================
206 /// Interfaces for adjusting renderer output.
207 /// ==================================================================
209 /// Sets the x/y scale for the movie
210 virtual void set_scale(float /*xscale*/, float /*yscale*/) {}
212 /// Sets the x/y offset for the movie in pixels. This applies to all
213 /// graphics drawn except the background, which must be drawn for the
214 /// entire canvas, regardless of the translation.
215 virtual void set_translation(float /*xoff*/, float /*yoff*/) {}
217 void setQuality(Quality q
) { _quality
= q
; }
219 /// ==================================================================
220 /// Caching utitilies for core.
221 /// ==================================================================
224 /// Given an image, returns a pointer to a bitmap_info class
225 /// that can later be passed to FillStyleX_bitmap(), to set a
226 /// bitmap fill style.
227 virtual CachedBitmap
* createCachedBitmap(
228 std::auto_ptr
<image::GnashImage
> im
) = 0;
231 /// ==================================================================
232 /// Rendering Interface.
233 /// ==================================================================
235 /// Draws a video frame.
237 /// The frame has already been decoded and is available in RGB format only.
239 /// @param frame The RGB video buffer frame.
240 /// Ownership of the buffer is left to the caller.
242 /// @param mat The SWFMatrix with world coordinates used to retrieve the x
243 /// and y coordinate of the video object. The scaling of the SWFMatrix
244 /// only refers to the Flash instance, *not* to the video inside that
245 /// instance. When a video object is placed on the stage and the loaded
246 /// video is smaller, then the SWFMatrix is still an "identity
247 /// matrix". However, if the video object is scaled via ActionScript,
248 /// for example, then the SWFMatrix will change. This means the
249 /// renderer has to find the correct scaling for the video inside the
252 /// @param bounds The minX/minY fields of this SWFRect are always zero.
253 /// The width and height determine the size of the Flash video instance
254 /// on the stage (in TWIPS) prior to SWFMatrix transformations.
256 virtual void drawVideoFrame(image::GnashImage
* frame
,
257 const Transform
& xform
, const SWFRect
* bounds
, bool smooth
) = 0;
259 /// Draw a line-strip directly, using a thin, solid line.
261 /// Can be used to draw empty boxes and cursors.
263 /// @coords an array of 16-bit signed integer coordinates. Even indices
264 /// (and 0) are x coordinates, while uneven ones are y coordinates.
266 /// @vertex_count the number of x-y coordinates (vertices).
268 /// @color the color to be used to draw the line strip.
270 /// @mat the SWFMatrix to be used to transform the vertices.
271 virtual void drawLine(const std::vector
<point
>& coords
,
272 const rgba
& color
, const SWFMatrix
& mat
) = 0;
274 /// Draw a simple, solid filled polygon with a thin (~1 pixel) outline.
276 /// This can't be used for
277 /// Flash shapes but is intended for internal drawings like bounding boxes
278 /// (editable text fields) and similar. The polygon should not contain
279 /// self-intersections. If you do not wish a outline or a fill, then simply
280 /// set the alpha value to zero.
282 /// The polygon need NOT be closed (ie: this function will automatically
283 /// add an additional vertex to close it.
285 /// When masked==false, then any potential mask currently active will be
286 /// ignored, otherwise it is respected.
288 virtual void draw_poly(const point
* corners
, size_t corner_count
,
289 const rgba
& fill
, const rgba
& outline
, const SWFMatrix
& mat
,
292 virtual void drawShape(const SWF::ShapeRecord
& shape
,
293 const Transform
& xform
) = 0;
296 /// Draws a glyph (font character).
298 /// Glyphs are defined just like shape characters with the difference that
299 /// they do not have any fill or line styles.
300 /// Instead, the shape must be drawn using the given color (solid fill).
301 /// Please note that although the glyph paths may indicate subshapes,
302 /// the renderer is to ignore that information.
309 virtual void drawGlyph(const SWF::ShapeRecord
& rec
, const rgba
& color
,
310 const SWFMatrix
& mat
) = 0;
312 /// Draw the current rendering buffer to an image file.
314 /// Although this can be done at any time during the rendering cycle
315 /// without harmful side effects, it's advisable only to do it when
316 /// between advance() calls, when the frame is fully renderered.
318 /// @param io The IOChannel to write to.
319 /// @param type The type of image output required (PNG, JPEG, GIF).
320 /// Note that not all FileTypes are images: rendering
321 /// to an FLV will not work.
322 virtual void renderToImage(boost::shared_ptr
<IOChannel
> /*io*/,
323 FileType
/*type*/) const {
325 log_debug(_("Rendering to image not implemented for this "
330 /// ==================================================================
331 /// Prepare drawing area and other utilities
332 /// ==================================================================
334 /// Sets the update region (called prior to begin_display).
337 /// might do clipping and leave the region outside these bounds unchanged,
338 /// but he is allowed to change them if that makes sense. After rendering
339 /// a frame the area outside the invalidated region can be undefined and
342 /// It is not required for all renderers.
343 /// Parameters are world coordinates (TWIPS).
345 /// For more info see page \ref region_update.
346 virtual void set_invalidated_regions(const InvalidatedRanges
& /*ranges*/)
350 /// ==================================================================
351 /// Machinery for delayed images rendering (e.g. Xv with YV12 or VAAPI)
352 /// ==================================================================
355 typedef boost::shared_ptr
<GnashVaapiImageProxy
> RenderImage
;
356 typedef std::vector
<RenderImage
> RenderImages
;
358 // Get first render image
359 virtual RenderImages::iterator
getFirstRenderImage()
360 { return _render_images
.begin(); }
361 virtual RenderImages::const_iterator
getFirstRenderImage() const
362 { return _render_images
.begin(); }
364 // Get last render image
365 virtual RenderImages::iterator
getLastRenderImage()
366 { return _render_images
.end(); }
367 virtual RenderImages::const_iterator
getLastRenderImage() const
368 { return _render_images
.end(); }
374 /// Masks are defined by drawing calls enclosed by begin_submit_mask()
375 /// and end_submit_mask(). Between these two calls, no drawing is to
376 /// occur. The shapes rendered between the two calls define the
377 /// visible region of the mask. Graphics that are irrelevant in the
378 /// context of a mask (lines and fill styles, for example) should be
379 /// ignored. After use, disable_mask() is called to remove the mask.
381 /// Masks may be nested. That is, end_submit_mask() may be followed
382 /// by a call to begin_submit_mask(). The resulting mask shall be an
383 /// intersection of the previously created mask. disable_mask() shall
384 /// result in the disabling or destruction of the last created mask.
385 virtual void begin_submit_mask() = 0;
386 virtual void end_submit_mask() = 0;
387 virtual void disable_mask() = 0;
390 /// ==================================================================
391 /// Interface for querying the renderer.
392 /// ==================================================================
394 /// Converts world coordinates to pixel coordinates
395 virtual geometry::Range2d
<int> world_to_pixel(const SWFRect
& worldbounds
) = 0;
397 /// Converts pixel coordinates to world coordinates (TWIPS)
398 virtual point
pixel_to_world(int x
, int y
) = 0;
400 virtual geometry::Range2d
<int> pixel_to_world(
401 const geometry::Range2d
<int>& pixelbounds
)
403 point topleft
= pixel_to_world(
404 pixelbounds
.getMinX(), pixelbounds
.getMinY());
405 point bottomright
= pixel_to_world(
406 pixelbounds
.getMaxX(), pixelbounds
.getMaxY());
408 return geometry::Range2d
<int> (topleft
.x
, topleft
.y
,
409 bottomright
.x
, bottomright
.y
);
412 virtual geometry::Range2d
<int> world_to_pixel(
413 const geometry::Range2d
<int>& worldbounds
)
415 if ((worldbounds
.isNull() || worldbounds
.isWorld())) return worldbounds
;
417 // We always get compiler warnings on casting floats to int
418 // here, so we cast it ourselves to get rid of the warning
419 // message. Note that in both cases this rounds the float to
420 // an integer by dropping the decimal part.
421 return world_to_pixel(SWFRect(static_cast<int>(worldbounds
.getMinX()),
422 static_cast<int>(worldbounds
.getMinY()),
423 static_cast<int>(worldbounds
.getMaxX()),
424 static_cast<int>(worldbounds
.getMaxY())));
428 /// Checks if the given bounds are (partially) in the current drawing
431 /// A render handler implementing invalidated bounds should implement
432 /// this method to avoid rendering of characters that are not visible
434 /// By default this method always returns true, which will ensure correct
435 /// rendering. If possible, it should be re-implemented by the renderer
436 /// handler for better performance.
437 /// 'bounds' contains TWIPS coordinates.
439 /// TODO: Take a Range2d<T> rather then a gnash::SWFRect ?
440 /// Would T==int be good ? TWIPS as integer types ?
442 /// See also gnash::renderer::bounds_in_clipping_area
444 virtual bool bounds_in_clipping_area(const SWFRect
& bounds
) {
445 return bounds_in_clipping_area(bounds
.getRange());
448 virtual bool bounds_in_clipping_area(const InvalidatedRanges
& ranges
)
450 for (unsigned int rno
=0; rno
<ranges
.size(); rno
++)
452 if (bounds_in_clipping_area(ranges
.getRange(rno
)))
459 virtual bool bounds_in_clipping_area(
460 const geometry::Range2d
<int>& /*bounds*/)
467 /// ==================================================================
468 /// Interfaces for testing only. Disabled when the testsuite isn't built.
469 /// ==================================================================
472 /// This function returns the color at any position in the stage. It is used
473 /// for automatic testing only, it should not be used for anything else!
474 /// x and y are pixel coordinates (<0 won't make any sense) and the color of
475 /// the nearest pixel is returned.
476 /// The function returns false when the coordinates are outside the
477 /// main frame buffer.
478 virtual bool getPixel(rgba
& /*color_return*/, int /*x*/, int /*y*/) const {
480 log_debug("getPixel() not implemented for this renderer");
482 return false; // avoid compiler warning
486 /// Returns the average RGB color for a square block on the stage. The
487 /// width and height of the block is defined by "radius" and x/y refer
488 /// to the center of the block. radius==1 equals getPixel() and radius==0
489 /// is illegal. For even "radius" values, the center point is not exactly
491 /// The function returns false when at least one pixel of the block was
492 /// outside the main frame buffer. In that case the value in color_return
494 /// This implementation is provided for simplicity. Renderers should
495 /// implement a specialized version for better performance.
496 virtual bool getAveragePixel(rgba
& color_return
, int x
, int y
,
497 unsigned int radius
) const
503 if (radius
==1) return getPixel(color_return
, x
, y
);
505 unsigned int r
=0, g
=0, b
=0, a
=0;
515 for (int yp
=y
; yp
<ye
; yp
++)
516 for (int xp
=x
; xp
<xe
; xp
++)
518 if (!getPixel(pixel
, xp
, yp
))
527 int pcount
= radius
*radius
;
528 color_return
.m_r
= r
/ pcount
;
529 color_return
.m_g
= g
/ pcount
;
530 color_return
.m_b
= b
/ pcount
;
531 color_return
.m_a
= a
/ pcount
;
538 /// Initializes the renderer for off-screen rendering used by the
541 /// This is a special function used for testcases ONLY. It is used by
542 /// MovieTester to prepare the renderer for off-screen rendering
543 /// without any GUI. The renderer is responsible to do all required
544 /// steps so that rendering is possible after the call. This may mean
545 /// that the renderer allocates memory for the given stage size.
547 /// The function returns false when the renderer is not able to do
548 /// off-screen rendering (default).
550 /// Note the function may be called again afterwards, resizing the stage.
551 /// Any number of calls to this function is possible and the renderer
552 /// is responsible to resize any buffer instead of wasting memory.
554 /// @param width stage width in pixels
556 /// @param height stage height in pixels
557 virtual bool initTestBuffer(unsigned /*width*/, unsigned /*height*/) {
561 /// Return color depth (bits per pixel) or 0 if unknown/unimplemented.
563 /// Default implementation returns 0 (unknown).
565 /// TODO: this should be a pure abstract function, just don't want
566 /// to scan ogl and cairo backend for an implementation *now*
567 /// but would be needed for automated testing... Quinn, can you help ?
568 virtual unsigned int getBitsPerPixel() const {
577 /// Prepare the renderer for external rendering
579 /// Note that all arguments except the background colour are useless
580 /// outside the ogl renderer.
581 External(Renderer
& r
, const rgba
& c
, int w
= 0, int h
= 0,
582 float x0
= 0, float x1
= 0, float y0
= 0, float y1
= 0)
586 _r
.begin_display(c
, w
, h
, x0
, x1
, y0
, y1
);
601 /// Prepare the renderer for internal rendering
602 Internal(Renderer
& r
, image::GnashImage
& im
)
605 _ext(_r
.startInternalRender(im
))
609 Renderer
* renderer() const {
614 _r
.endInternalRender();
624 /// Kept in parallel with movie_root's setting.
627 // Delayed imaged to render
628 RenderImages _render_images
;
632 /// Bracket the displaying of a frame from a movie.
634 /// Set up to render a full frame from a movie and fills the
635 /// background. Sets up necessary transforms, to scale the
636 /// movie to fit within the given dimensions. Call
637 /// end_display() when you're done.
639 /// Most of the arguments are only for the ogl renderer. See documentation
640 /// in that class. Do not use these arguments for new renderers!
641 virtual void begin_display(const rgba
& background_color
,
642 int viewport_width
, int viewport_height
,
643 float x0
, float x1
, float y0
, float y1
) = 0;
645 virtual void end_display() = 0;
647 /// Setup the renderer to draw to an internal buffer.
649 /// Implementations are free to return a new renderer if they choose.
651 /// @return 0 if the renderer does not support this.
652 virtual Renderer
* startInternalRender(image::GnashImage
& buffer
) = 0;
654 /// Finish internal rendering.
656 /// Any rendering after this function has been called must apply to the
658 virtual void endInternalRender() = 0;
669 // indent-tabs-mode: t