gskcairorenderer.c 5.08 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
#include "config.h"

#include "gskcairorendererprivate.h"

#include "gskdebugprivate.h"
#include "gskrendererprivate.h"
#include "gskrendernodeiter.h"
#include "gskrendernodeprivate.h"

struct _GskCairoRenderer
{
  GskRenderer parent_instance;

  graphene_rect_t viewport;
};

struct _GskCairoRendererClass
{
  GskRendererClass parent_class;
};

G_DEFINE_TYPE (GskCairoRenderer, gsk_cairo_renderer, GSK_TYPE_RENDERER)

static gboolean
gsk_cairo_renderer_realize (GskRenderer *renderer)
{
  return TRUE;
}

static void
gsk_cairo_renderer_unrealize (GskRenderer *renderer)
{

}

static void
gsk_cairo_renderer_render_node (GskCairoRenderer *self,
                                GskRenderNode    *node,
                                cairo_t          *cr)
{
  GskRenderNodeIter iter;
  GskRenderNode *child;
  gboolean pop_group = FALSE;
  graphene_matrix_t mvp;
  cairo_matrix_t ctm;
  graphene_rect_t frame;

  if (gsk_render_node_is_hidden (node))
    return;

  cairo_save (cr);

Emmanuele Bassi's avatar
Emmanuele Bassi committed
53 54 55
  if (!gsk_render_node_has_surface (node))
    goto out;

56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
  gsk_render_node_get_world_matrix (node, &mvp);
  if (graphene_matrix_to_2d (&mvp, &ctm.xx, &ctm.yx, &ctm.xy, &ctm.yy, &ctm.x0, &ctm.y0))
    {
      GSK_NOTE (CAIRO, g_print ("CTM = { .xx = %g, .yx = %g, .xy = %g, .yy = %g, .x0 = %g, .y0 = %g }\n",
                                ctm.xx, ctm.yx,
                                ctm.xy, ctm.yy,
                                ctm.x0, ctm.y0));
      cairo_transform (cr, &ctm);
    }
  else
    g_critical ("Invalid non-affine transformation for node %p", node);

  gsk_render_node_get_bounds (node, &frame);
  GSK_NOTE (CAIRO, g_print ("CLIP = { .x = %g, .y = %g, .width = %g, .height = %g }\n",
                            frame.origin.x, frame.origin.y,
                            frame.size.width, frame.size.height));

  if (!GSK_RENDER_MODE_CHECK (GEOMETRY))
    {
      cairo_rectangle (cr, frame.origin.x, frame.origin.y, frame.size.width, frame.size.height);
      cairo_clip (cr);
    }

  if (!gsk_render_node_is_opaque (node) && gsk_render_node_get_opacity (node) != 1.0)
    {
      GSK_NOTE (CAIRO, g_print ("Pushing opacity group (opacity:%g)\n",
                                gsk_render_node_get_opacity (node)));
      cairo_push_group (cr);
      pop_group = TRUE;
    }

Emmanuele Bassi's avatar
Emmanuele Bassi committed
87
  GSK_NOTE (CAIRO, g_print ("Rendering surface %p for node %s[%p] at %g, %g\n",
88
                            gsk_render_node_get_surface (node),
Emmanuele Bassi's avatar
Emmanuele Bassi committed
89
                            node->name,
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
                            node,
                            frame.origin.x, frame.origin.y));
  cairo_set_source_surface (cr, gsk_render_node_get_surface (node), frame.origin.x, frame.origin.y); 
  cairo_paint (cr);

  if (GSK_RENDER_MODE_CHECK (GEOMETRY))
    {
      cairo_save (cr);
      cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
      cairo_rectangle (cr, frame.origin.x - 1, frame.origin.y - 1, frame.size.width + 2, frame.size.height + 2);
      cairo_set_line_width (cr, 2);
      cairo_set_source_rgba (cr, 0, 0, 0, 0.5);
      cairo_stroke (cr);
      cairo_restore (cr);
    }

  cairo_matrix_invert (&ctm);
  cairo_transform (cr, &ctm);

Emmanuele Bassi's avatar
Emmanuele Bassi committed
109
out:
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
  if (gsk_render_node_get_n_children (node) != 0)
    {
      GSK_NOTE (CAIRO, g_print ("Drawing %d children of node [%p]\n",
                                gsk_render_node_get_n_children (node),
                                node));
      gsk_render_node_iter_init (&iter, node);
      while (gsk_render_node_iter_next (&iter, &child))
        gsk_cairo_renderer_render_node (self, child, cr);
    }

  if (pop_group)
    {
      cairo_pop_group_to_source (cr);
      cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
      cairo_paint_with_alpha (cr, gsk_render_node_get_opacity (node));
    }

  cairo_restore (cr);
}

static void
131 132
gsk_cairo_renderer_render (GskRenderer   *renderer,
                           GskRenderNode *root)
133 134
{
  GskCairoRenderer *self = GSK_CAIRO_RENDERER (renderer);
135
  GdkDrawingContext *context = gsk_renderer_get_drawing_context (renderer);
Emmanuele Bassi's avatar
Emmanuele Bassi committed
136 137 138 139 140
  cairo_t *cr;

  cr = gdk_drawing_context_get_cairo_context (context);
  if (cr == NULL)
    return;
141

142
  gsk_renderer_get_viewport (renderer, &self->viewport);
143

144 145 146 147 148
  cairo_save (cr);
  cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
  cairo_set_source_rgba (cr, 0, 0, 0, 0);
  cairo_paint (cr);
  cairo_restore (cr);
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181

  if (GSK_RENDER_MODE_CHECK (GEOMETRY))
    {
      cairo_save (cr);
      cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
      cairo_rectangle (cr,
                       self->viewport.origin.x,
                       self->viewport.origin.y,
                       self->viewport.size.width,
                       self->viewport.size.height);
      cairo_set_source_rgba (cr, 0, 0, 0.85, 0.5);
      cairo_stroke (cr);
      cairo_restore (cr);
    }

  gsk_cairo_renderer_render_node (self, root, cr);
}

static void
gsk_cairo_renderer_class_init (GskCairoRendererClass *klass)
{
  GskRendererClass *renderer_class = GSK_RENDERER_CLASS (klass);

  renderer_class->realize = gsk_cairo_renderer_realize;
  renderer_class->unrealize = gsk_cairo_renderer_unrealize;
  renderer_class->render = gsk_cairo_renderer_render;
}

static void
gsk_cairo_renderer_init (GskCairoRenderer *self)
{

}