summaryrefslogtreecommitdiffstats
path: root/server/tree.c
diff options
context:
space:
mode:
Diffstat (limited to 'server/tree.c')
-rw-r--r--server/tree.c182
1 files changed, 182 insertions, 0 deletions
diff --git a/server/tree.c b/server/tree.c
new file mode 100644
index 00000000..ed7d39ad
--- /dev/null
+++ b/server/tree.c
@@ -0,0 +1,182 @@
+/*
+ Copyright (C) 2009-2015 Red Hat, Inc.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+#include <spice/qxl_dev.h>
+#include "red_parse_qxl.h"
+#include "display-channel.h"
+
+#include "tree.h"
+
+static const char *draw_type_to_str(uint8_t type)
+{
+ switch (type) {
+ case QXL_DRAW_FILL:
+ return "QXL_DRAW_FILL";
+ case QXL_DRAW_OPAQUE:
+ return "QXL_DRAW_OPAQUE";
+ case QXL_DRAW_COPY:
+ return "QXL_DRAW_COPY";
+ case QXL_DRAW_TRANSPARENT:
+ return "QXL_DRAW_TRANSPARENT";
+ case QXL_DRAW_ALPHA_BLEND:
+ return "QXL_DRAW_ALPHA_BLEND";
+ case QXL_COPY_BITS:
+ return "QXL_COPY_BITS";
+ case QXL_DRAW_BLEND:
+ return "QXL_DRAW_BLEND";
+ case QXL_DRAW_BLACKNESS:
+ return "QXL_DRAW_BLACKNESS";
+ case QXL_DRAW_WHITENESS:
+ return "QXL_DRAW_WHITENESS";
+ case QXL_DRAW_INVERS:
+ return "QXL_DRAW_INVERS";
+ case QXL_DRAW_ROP3:
+ return "QXL_DRAW_ROP3";
+ case QXL_DRAW_COMPOSITE:
+ return "QXL_DRAW_COMPOSITE";
+ case QXL_DRAW_STROKE:
+ return "QXL_DRAW_STROKE";
+ case QXL_DRAW_TEXT:
+ return "QXL_DRAW_TEXT";
+ default:
+ return "?";
+ }
+}
+
+static void show_red_drawable(RedDrawable *drawable, const char *prefix)
+{
+ if (prefix) {
+ printf("%s: ", prefix);
+ }
+
+ printf("%s effect %d bbox(%d %d %d %d)",
+ draw_type_to_str(drawable->type),
+ drawable->effect,
+ drawable->bbox.top,
+ drawable->bbox.left,
+ drawable->bbox.bottom,
+ drawable->bbox.right);
+
+ switch (drawable->type) {
+ case QXL_DRAW_FILL:
+ case QXL_DRAW_OPAQUE:
+ case QXL_DRAW_COPY:
+ case QXL_DRAW_TRANSPARENT:
+ case QXL_DRAW_ALPHA_BLEND:
+ case QXL_COPY_BITS:
+ case QXL_DRAW_BLEND:
+ case QXL_DRAW_BLACKNESS:
+ case QXL_DRAW_WHITENESS:
+ case QXL_DRAW_INVERS:
+ case QXL_DRAW_ROP3:
+ case QXL_DRAW_COMPOSITE:
+ case QXL_DRAW_STROKE:
+ case QXL_DRAW_TEXT:
+ break;
+ default:
+ spice_error("bad drawable type");
+ }
+ printf("\n");
+}
+
+static void show_draw_item(DrawItem *draw_item, const char *prefix)
+{
+ if (prefix) {
+ printf("%s: ", prefix);
+ }
+ printf("effect %d bbox(%d %d %d %d)\n",
+ draw_item->effect,
+ draw_item->base.rgn.extents.x1,
+ draw_item->base.rgn.extents.y1,
+ draw_item->base.rgn.extents.x2,
+ draw_item->base.rgn.extents.y2);
+}
+
+typedef struct DumpItem {
+ int level;
+ Container *container;
+} DumpItem;
+
+static void dump_item(TreeItem *item, void *data)
+{
+ DumpItem *di = data;
+ const char *item_prefix = "|--";
+ int i;
+
+ if (di->container) {
+ while (di->container != item->container) {
+ di->level--;
+ di->container = di->container->base.container;
+ }
+ }
+
+ switch (item->type) {
+ case TREE_ITEM_TYPE_DRAWABLE: {
+ Drawable *drawable = SPICE_CONTAINEROF(item, Drawable, tree_item);
+ const int max_indent = 200;
+ char indent_str[max_indent + 1];
+ int indent_str_len;
+
+ for (i = 0; i < di->level; i++) {
+ printf(" ");
+ }
+ printf(item_prefix, 0);
+ show_red_drawable(drawable->red_drawable, NULL);
+ for (i = 0; i < di->level; i++) {
+ printf(" ");
+ }
+ printf("| ");
+ show_draw_item(&drawable->tree_item, NULL);
+ indent_str_len = MIN(max_indent, strlen(item_prefix) + di->level * 2);
+ memset(indent_str, ' ', indent_str_len);
+ indent_str[indent_str_len] = 0;
+ region_dump(&item->rgn, indent_str);
+ printf("\n");
+ break;
+ }
+ case TREE_ITEM_TYPE_CONTAINER:
+ di->level++;
+ di->container = (Container *)item;
+ break;
+ case TREE_ITEM_TYPE_SHADOW:
+ break;
+ }
+}
+
+static void tree_foreach(TreeItem *item, void (*f)(TreeItem *, void *), void * data)
+{
+ if (!item)
+ return;
+
+ f(item, data);
+
+ if (item->type == TREE_ITEM_TYPE_CONTAINER) {
+ Container *container = (Container*)item;
+ RingItem *it;
+
+ RING_FOREACH(it, &container->items) {
+ tree_foreach(SPICE_CONTAINEROF(it, TreeItem, siblings_link), f, data);
+ }
+ }
+}
+
+void tree_item_dump(TreeItem *item)
+{
+ DumpItem di = { 0, };
+
+ spice_return_if_fail(item != NULL);
+ tree_foreach(item, dump_item, &di);
+}