Update with current status
[gnash.git] / librender / Renderer.h
blob097c0be6049a2ae8a65b43b00dddab406b81af3f
1 //
2 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
3 // Free Software Foundation, Inc
4 //
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.
9 //
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.
14 //
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
19 #ifndef RENDER_HANDLER_H
20 #define RENDER_HANDLER_H
22 /// \page Renderer_intro Render handler introduction
23 ///
24 /// Information for writing new render handlers.
25 ///
26 /// The most important thing about drawing Flash shapes is to understand how
27 /// their fill styles work.
28 /// A single Flash character can contain any number shapes that use any number
29 /// of different fill styles and line styles. The shapes of a character are
30 /// defined by a number of "paths". Some important things about paths:
31 ///
32 /// - A path is a list of connected straight lines and (quadratic bezier)
33 /// curves (=edges). Interesting to note is that in the Flash world there are
34 /// *no* primitive objects like circles, rectangles or similar. These objects
35 /// are always translated to lines and curves (a circle is a set of eight
36 /// curves).
37 ///
38 /// - All paths together must by definition always build a fully closed shape.
39 /// You can't draw a rectangle with three edges, for example, contrary to
40 /// most graphics library polygon routines that connect the last anchor to
41 /// the first. However, a *single* path does *not* have to be closed. The
42 /// missing parts may be defined by other paths (you will see this makes
43 /// sense).
44 ///
45 /// - Each path has up to two fill styles and no or one line style. The line
46 /// style should be obvious. The two fill styles define the fill to the left
47 /// (fill style zero) and to the right (fill style one) of the path if you
48 /// think of it like a vector. The fill style is defined by a index to a
49 /// list of previously defined fill style definitions. Index 0 means "no
50 /// style" and is equal to a fully transparent fill style ("hole", if you
51 /// wish).
52 ///
53 /// - Paths are *never* self-intersecting.
54 ///
55 /// Simple examples to understand this concept:
56 ///
57 /// - A rectangle that contains another rectangle. Only the area between the
58 /// two rectangles is filled (so it looks like a "o"). In this case Flash
59 /// fill create two paths (one for each rectangle) and one fill style.
60 /// Assume both paths come in clockwise order, then the outer rectangle
61 /// will have fillstyle0=0 and fillstyle1=1. The inner rectangle will have
62 /// fillstyle0=1 and fillstyle1=0.
63 ///
64 /// \code
65 /// +--------------------------------+
66 /// |XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX|
67 /// |XXX+------------------------+XXX|
68 /// |XXX| |XXX|
69 /// |XXX+------------------------+XXX|
70 /// |XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX|
71 /// +--------------------------------+
72 /// \endcode
73 ///
74 /// - A rectangle is divided vertically in two halves, both having different
75 /// colors:
76 ///
77 /// \code
78 /// +-------A-------+-------B--------+
79 /// |...............|################|
80 /// A...............C################B
81 /// |...............|################|
82 /// +-------A-------+-------B--------+
83 /// \endcode
84 ///
85 /// Flash will probably produce three paths (A,B,C) and two fill styles.
86 /// Paths "A" and "B" will have just one fill style (fillstyle1 will be
87 /// zero) while path "C" (which contains only one straight line!!) will
88 /// have two fill styles. To be exact the horizontal edges would not even
89 /// be necessary to render this shape (for a scanline based renderer) but
90 /// they are necessary then the character is about to be rotated.
91 ///
92 /// Now, these are simple examples but complex graphics can be compressed very
93 /// efficiently this way. Also, this method was most probably intended for a
94 /// renderer engine that can produce the final character in just one pass
95 /// (like the AGG backend does too).
98 /// \page region_update Detection of updated regions
99 ///
100 /// (this applies to the whole Gnash playback architecture)
102 /// After advancing the root movie (see gnash::Gui::advance_movie) it is checked
103 /// which region of the stage has been changed visibly (by computing the
104 /// bounds around updated characters). This has two advantages:
105 ///
106 /// 1st, it allows a renderer/gui combination to avoid re-rendering of
107 /// unchanged parts in the scene. When supported by the rendering engine
108 /// this can be a huge performance gain. The original Flash player does
109 /// that too, btw.
110 ///
111 /// 2nd, it can detect still frames (like a stopped movie). gui.cpp can
112 /// detect these and completely avoid calling any rendering function.
113 ///
114 /// Of course, the most critical part is detection of changes. There is a
115 /// method gnash::character::set_invalidated() which gets called whenever a
116 /// critical property of a instance gets updated, like when it changes
117 /// position, for example.
118 /// It's really important to *always* call set_invalidated() *before*
119 /// any call that changes the character instance in a visible way.
120 ///
121 /// Even if no renderer really uses this information it has effects when
122 /// skipping unchanged frames. If necessary, this feature can be switched
123 /// off easily in gui.cpp (maybe using a runtime option?).
125 /// Note the updated region is only passed to the gnash::Gui, which is itself
126 /// responsible of informing the renderer
127 /// (see gnash::Gui::set_invalidated_region).
128 /// This is because it's pointless
129 /// to have a renderer which updates only a small part of the stage when
130 /// the GUI shows it all since the area around the region is undefined.
131 /// However, there can be a GUI which supports update regions without needing
132 /// the renderer to do so (for example, to save time during blitting).
133 /// The GUI can also completely ignore the region information.
135 /// It's also important to note that the bounds passed to the GUI are just
136 /// a hint and the GUI /is/ allowed to further process and alter the information
137 /// in any way.
138 ///
139 /// As for the integer/float discussion: I used SWFRect (floats) because all
140 /// the bounds calculation involves floats anyway and so it's probably
141 /// faster than converting between ints and floats all the way.
144 #include <vector>
145 #include <boost/noncopyable.hpp>
147 #include "dsodefs.h" // for DSOEXPORT
149 #include "GnashEnums.h"
150 #include "Range2d.h"
151 #include "Point2d.h"
152 #include "RGBA.h"
153 #include "log.h"
154 #include "snappingrange.h"
155 #include "SWFRect.h"
157 // Forward declarations.
158 namespace gnash {
159 class IOChannel;
160 class CachedBitmap;
161 class rgba;
162 class Transform;
163 class SWFMatrix;
164 class FillStyle;
165 class LineStyle;
166 class Shape;
167 class MorphShape;
169 // XXX: GnashImageProxy (delayed image rendering)
170 class GnashVaapiImageProxy;
172 namespace SWF {
173 class ShapeRecord;
175 namespace image {
176 class GnashImage;
180 namespace gnash {
182 /// Base class for render handlers.
184 /// You must define a subclass of Renderer, and pass an
185 /// instance to the core (RunResources) *before* any SWF parsing begins.
187 /// For more info see page \ref Renderer_intro.
188 class DSOEXPORT Renderer : boost::noncopyable
190 public:
192 Renderer(): _quality(QUALITY_HIGH) { }
194 virtual ~Renderer() {}
196 /// Return a description of this renderer.
197 virtual std::string description() const = 0;
199 /// ==================================================================
200 /// Interfaces for adjusting renderer output.
201 /// ==================================================================
203 /// Sets the x/y scale for the movie
204 virtual void set_scale(float /*xscale*/, float /*yscale*/) {}
206 /// Sets the x/y offset for the movie in pixels. This applies to all
207 /// graphics drawn except the background, which must be drawn for the
208 /// entire canvas, regardless of the translation.
209 virtual void set_translation(float /*xoff*/, float /*yoff*/) {}
211 void setQuality(Quality q) { _quality = q; }
213 /// ==================================================================
214 /// Caching utitilies for core.
215 /// ==================================================================
217 /// \brief
218 /// Given an image, returns a pointer to a CachedBitmap class
219 /// that can later be passed to FillStyleX_bitmap(), to set a
220 /// bitmap fill style.
221 virtual CachedBitmap *
222 createCachedBitmap(std::unique_ptr<image::GnashImage> im) = 0;
225 /// ==================================================================
226 /// Rendering Interface.
227 /// ==================================================================
229 /// Draws a video frame.
231 /// The frame has already been decoded and is available in RGB format only.
232 ///
233 /// @param frame The RGB video buffer frame.
234 /// Ownership of the buffer is left to the caller.
236 /// @param mat The SWFMatrix with world coordinates used to retrieve the x
237 /// and y coordinate of the video object. The scaling of the SWFMatrix
238 /// only refers to the Flash instance, *not* to the video inside that
239 /// instance. When a video object is placed on the stage and the loaded
240 /// video is smaller, then the SWFMatrix is still an "identity
241 /// matrix". However, if the video object is scaled via ActionScript,
242 /// for example, then the SWFMatrix will change. This means the
243 /// renderer has to find the correct scaling for the video inside the
244 /// bounds.
246 /// @param bounds The minX/minY fields of this SWFRect are always zero.
247 /// The width and height determine the size of the Flash video instance
248 /// on the stage (in TWIPS) prior to SWFMatrix transformations.
250 virtual void drawVideoFrame(image::GnashImage* frame,
251 const Transform& xform, const SWFRect* bounds, bool smooth) = 0;
253 /// Draw a line-strip directly, using a thin, solid line.
255 /// Can be used to draw empty boxes and cursors.
257 /// @coords an array of 16-bit signed integer coordinates. Even indices
258 /// (and 0) are x coordinates, while uneven ones are y coordinates.
260 /// @vertex_count the number of x-y coordinates (vertices).
262 /// @color the color to be used to draw the line strip.
264 /// @mat the SWFMatrix to be used to transform the vertices.
265 virtual void drawLine(const std::vector<point>& coords,
266 const rgba& color, const SWFMatrix& mat) = 0;
268 /// Draw a simple, solid filled polygon with a thin (~1 pixel) outline.
270 /// This can't be used for
271 /// Flash shapes but is intended for internal drawings like bounding boxes
272 /// (editable text fields) and similar. The polygon should not contain
273 /// self-intersections. If you do not wish a outline or a fill, then simply
274 /// set the alpha value to zero.
276 /// The polygon need NOT be closed (ie: this function will automatically
277 /// add an additional vertex to close it.
279 /// When masked==false, then any potential mask currently active will be
280 /// ignored, otherwise it is respected.
282 virtual void draw_poly(const std::vector<point>& corners,
283 const rgba& fill, const rgba& outline, const SWFMatrix& mat,
284 bool masked) = 0;
286 virtual void drawShape(const SWF::ShapeRecord& shape,
287 const Transform& xform) = 0;
289 /// \brief
290 /// Draws a glyph (font character).
292 /// Glyphs are defined just like shape characters with the difference that
293 /// they do not have any fill or line styles.
294 /// Instead, the shape must be drawn using the given color (solid fill).
295 /// Please note that although the glyph paths may indicate subshapes,
296 /// the renderer is to ignore that information.
297 ///
298 /// @param def
300 /// @param mat
302 /// @param color
303 virtual void drawGlyph(const SWF::ShapeRecord& rec, const rgba& color,
304 const SWFMatrix& mat) = 0;
306 /// Draw the current rendering buffer to an image file.
308 /// Although this can be done at any time during the rendering cycle
309 /// without harmful side effects, it's advisable only to do it when
310 /// between advance() calls, when the frame is fully renderered.
312 /// @param io The IOChannel to write to.
313 /// @param type The type of image output required (PNG, JPEG, GIF).
314 /// Note that not all FileTypes are images: rendering
315 /// to an FLV will not work.
316 virtual void renderToImage(std::unique_ptr<IOChannel> /*io*/,
317 FileType /*type*/, int /*quality*/) const {
319 log_debug(_("Rendering to image not implemented for this "
320 "renderer"));
324 /// ==================================================================
325 /// Prepare drawing area and other utilities
326 /// ==================================================================
328 /// Sets the update region (called prior to begin_display).
330 /// The renderer
331 /// might do clipping and leave the region outside these bounds unchanged,
332 /// but he is allowed to change them if that makes sense. After rendering
333 /// a frame the area outside the invalidated region can be undefined and
334 /// is not used.
336 /// It is not required for all renderers.
337 /// Parameters are world coordinates (TWIPS).
339 /// For more info see page \ref region_update.
340 virtual void set_invalidated_regions(const InvalidatedRanges& /*ranges*/)
344 /// ==================================================================
345 /// Machinery for delayed images rendering (e.g. Xv with YV12 or VAAPI)
346 /// ==================================================================
348 ///@{
349 typedef std::shared_ptr<GnashVaapiImageProxy> RenderImage;
350 typedef std::vector<RenderImage> RenderImages;
352 // Get first render image
353 virtual RenderImages::const_iterator getFirstRenderImage() const
354 { return _render_images.begin(); }
356 // Get last render image
357 virtual RenderImages::const_iterator getLastRenderImage() const
358 { return _render_images.end(); }
360 ///@}
362 ///@{ Masks
364 /// Masks are defined by drawing calls enclosed by begin_submit_mask()
365 /// and end_submit_mask(). Between these two calls, no drawing is to
366 /// occur. The shapes rendered between the two calls define the
367 /// visible region of the mask. Graphics that are irrelevant in the
368 /// context of a mask (lines and fill styles, for example) should be
369 /// ignored. After use, disable_mask() is called to remove the mask.
371 /// Masks may be nested. That is, end_submit_mask() may be followed
372 /// by a call to begin_submit_mask(). The resulting mask shall be an
373 /// intersection of the previously created mask. disable_mask() shall
374 /// result in the disabling or destruction of the last created mask.
375 virtual void begin_submit_mask() = 0;
376 virtual void end_submit_mask() = 0;
377 virtual void disable_mask() = 0;
378 ///@}
380 /// ==================================================================
381 /// Interface for querying the renderer.
382 /// ==================================================================
384 /// Converts world coordinates to pixel coordinates
385 virtual geometry::Range2d<int> world_to_pixel(const SWFRect& worldbounds)
386 const = 0;
388 geometry::Range2d<int> world_to_pixel(const geometry::Range2d<int>& wb)
389 const
391 if ((wb.isNull() || wb.isWorld())) return wb;
392 return world_to_pixel(SWFRect(wb.getMinX(), wb.getMinY(),
393 wb.getMaxX(), wb.getMaxY()));
396 /// Converts pixel coordinates to world coordinates (TWIPS)
397 virtual point pixel_to_world(int x, int y) const = 0;
399 geometry::Range2d<int> pixel_to_world(
400 const geometry::Range2d<int>& pixelbounds) const
402 point topleft = pixel_to_world(
403 pixelbounds.getMinX(), pixelbounds.getMinY());
404 point bottomright = pixel_to_world(
405 pixelbounds.getMaxX(), pixelbounds.getMaxY());
407 return geometry::Range2d<int> (topleft.x, topleft.y,
408 bottomright.x, bottomright.y);
411 /// \brief
412 /// Checks if the given bounds are (partially) in the current drawing
413 /// clipping area.
415 /// A render handler implementing invalidated bounds should implement
416 /// this method to avoid rendering of characters that are not visible
417 /// anyway.
418 /// By default this method always returns true, which will ensure correct
419 /// rendering. If possible, it should be re-implemented by the renderer
420 /// handler for better performance.
421 /// b contains TWIPS coordinates.
422 virtual bool bounds_in_clipping_area(const geometry::Range2d<int>& /*b*/)
423 const {
424 return true;
427 #ifdef USE_TESTSUITE
430 /// ==================================================================
431 /// Interfaces for testing only. Disabled when the testsuite isn't built.
432 /// ==================================================================
435 /// This function returns the color at any position in the stage. It is used
436 /// for automatic testing only, it should not be used for anything else!
437 /// x and y are pixel coordinates (<0 won't make any sense) and the color of
438 /// the nearest pixel is returned.
439 /// The function returns false when the coordinates are outside the
440 /// main frame buffer.
441 virtual bool getPixel(rgba& /*color_return*/, int /*x*/, int /*y*/) const {
443 log_debug("getPixel() not implemented for this renderer");
444 abort();
445 return false; // avoid compiler warning
448 void addRenderImage(std::shared_ptr<GnashVaapiImageProxy> image) {
449 _render_images.push_back(image);
452 /// Returns the average RGB color for a square block on the stage. The
453 /// width and height of the block is defined by "radius" and x/y refer
454 /// to the center of the block. radius==1 equals getPixel() and radius==0
455 /// is illegal. For even "radius" values, the center point is not exactly
456 /// defined.
457 /// The function returns false when at least one pixel of the block was
458 /// outside the main frame buffer. In that case the value in color_return
459 /// is undefined.
460 /// This implementation is provided for simplicity. Renderers should
461 /// implement a specialized version for better performance.
462 virtual bool getAveragePixel(rgba& color_return, int x, int y,
463 unsigned int radius) const
466 assert(radius>0);
468 // optimization:
469 if (radius==1) return getPixel(color_return, x, y);
471 unsigned int r=0, g=0, b=0, a=0;
473 x -= radius/2;
474 y -= radius/2;
476 int xe = x+radius;
477 int ye = y+radius;
479 rgba pixel;
481 for (int yp=y; yp<ye; yp++)
482 for (int xp=x; xp<xe; xp++)
484 if (!getPixel(pixel, xp, yp))
485 return false;
487 r += pixel.m_r;
488 g += pixel.m_g;
489 b += pixel.m_b;
490 a += pixel.m_a;
493 int pcount = radius*radius;
494 color_return.m_r = r / pcount;
495 color_return.m_g = g / pcount;
496 color_return.m_b = b / pcount;
497 color_return.m_a = a / pcount;
499 return true;
502 /// \brief
503 /// Initializes the renderer for off-screen rendering used by the
504 /// testsuite.
506 /// This is a special function used for testcases ONLY. It is used by
507 /// MovieTester to prepare the renderer for off-screen rendering
508 /// without any GUI. The renderer is responsible to do all required
509 /// steps so that rendering is possible after the call. This may mean
510 /// that the renderer allocates memory for the given stage size.
511 ///
512 /// The function returns false when the renderer is not able to do
513 /// off-screen rendering (default).
515 /// Note the function may be called again afterwards, resizing the stage.
516 /// Any number of calls to this function is possible and the renderer
517 /// is responsible to resize any buffer instead of wasting memory.
519 /// @param width stage width in pixels
521 /// @param height stage height in pixels
522 virtual bool initTestBuffer(unsigned /*width*/, unsigned /*height*/) {
523 return false;
526 /// Return color depth (bits per pixel) or 0 if unknown/unimplemented.
528 /// Default implementation returns 0 (unknown).
530 /// TODO: this should be a pure abstract function, just don't want
531 /// to scan ogl and cairo backend for an implementation *now*
532 /// but would be needed for automated testing...
533 virtual unsigned int getBitsPerPixel() const {
534 return 0;
537 #endif
539 class External
541 public:
542 /// Prepare the renderer for external rendering
544 /// Note that all arguments except the background colour are useless
545 /// outside the ogl renderer.
546 External(Renderer& r, const rgba& c, int w = 0, int h = 0,
547 float x0 = 0, float x1 = 0, float y0 = 0, float y1 = 0)
549 _r(r)
551 _r.begin_display(c, w, h, x0, x1, y0, y1);
554 ~External() {
555 _r.end_display();
558 private:
559 Renderer& _r;
562 class Internal
564 public:
565 /// Prepare the renderer for internal rendering
566 Internal(Renderer& r, image::GnashImage& im)
568 _r(r),
569 _ext(_r.startInternalRender(im))
573 Renderer* renderer() const {
574 return _ext;
577 ~Internal() {
578 _r.endInternalRender();
581 private:
582 Renderer& _r;
583 Renderer* _ext;
586 protected:
588 /// Kept in parallel with movie_root's setting.
589 Quality _quality;
591 // Delayed imaged to render
592 RenderImages _render_images;
594 private:
595 /// Bracket the displaying of a frame from a movie.
597 /// Set up to render a full frame from a movie and fills the
598 /// background. Sets up necessary transforms, to scale the
599 /// movie to fit within the given dimensions. Call
600 /// end_display() when you're done.
602 /// Most of the arguments are only for the ogl renderer. See documentation
603 /// in that class. Do not use these arguments for new renderers!
604 virtual void begin_display(const rgba& background_color,
605 int viewport_width, int viewport_height,
606 float x0, float x1, float y0, float y1) = 0;
608 virtual void end_display() = 0;
610 /// Setup the renderer to draw to an internal buffer.
612 /// Implementations are free to return a new renderer if they choose.
614 /// @return 0 if the renderer does not support this.
615 virtual Renderer* startInternalRender(image::GnashImage& buffer) = 0;
617 /// Finish internal rendering.
619 /// Any rendering after this function has been called must apply to the
620 /// external buffer.
621 virtual void endInternalRender() = 0;
625 } // namespace gnash
627 #endif
630 // Local Variables:
631 // mode: C++
632 // indent-tabs-mode: nil
633 // End: