Remove Big, which is no longer used
https://bugzilla.gnome.org/show_bug.cgi?id=614516
This commit is contained in:
parent
2320c393c9
commit
439203349d
@ -83,7 +83,6 @@ LIBS=$saved_LIBS
|
|||||||
|
|
||||||
PKG_CHECK_MODULES(TIDY, clutter-1.0)
|
PKG_CHECK_MODULES(TIDY, clutter-1.0)
|
||||||
PKG_CHECK_MODULES(ST, clutter-1.0 gtk+-2.0 libcroco-0.6 gnome-desktop-2.0 >= 2.26)
|
PKG_CHECK_MODULES(ST, clutter-1.0 gtk+-2.0 libcroco-0.6 gnome-desktop-2.0 >= 2.26)
|
||||||
PKG_CHECK_MODULES(BIG, clutter-1.0 gtk+-2.0 librsvg-2.0)
|
|
||||||
PKG_CHECK_MODULES(GDMUSER, dbus-glib-1 gtk+-2.0)
|
PKG_CHECK_MODULES(GDMUSER, dbus-glib-1 gtk+-2.0)
|
||||||
PKG_CHECK_MODULES(TRAY, gtk+-2.0)
|
PKG_CHECK_MODULES(TRAY, gtk+-2.0)
|
||||||
|
|
||||||
|
@ -1,68 +0,0 @@
|
|||||||
big_cflags = \
|
|
||||||
-I$(top_srcdir)/src \
|
|
||||||
-DPREFIX=\""$(prefix)"\" \
|
|
||||||
-DLIBDIR=\""$(libdir)"\" \
|
|
||||||
-DG_DISABLE_DEPRECATED \
|
|
||||||
-DG_LOG_DOMAIN=\"Big\" \
|
|
||||||
$(BIG_CFLAGS) \
|
|
||||||
$(NULL)
|
|
||||||
|
|
||||||
big_built_sources = \
|
|
||||||
big-enum-types.h \
|
|
||||||
big-enum-types.c \
|
|
||||||
$(NULL)
|
|
||||||
|
|
||||||
BUILT_SOURCES += $(big_built_sources)
|
|
||||||
|
|
||||||
BIG_STAMP_FILES = stamp-big-marshal.h stamp-big-enum-types.h
|
|
||||||
|
|
||||||
# please, keep this sorted alphabetically
|
|
||||||
big_source_h = \
|
|
||||||
big/box.h \
|
|
||||||
big/rectangle.h \
|
|
||||||
big/theme-image.h \
|
|
||||||
$(NULL)
|
|
||||||
|
|
||||||
# please, keep this sorted alphabetically
|
|
||||||
big_source_c = \
|
|
||||||
big/box.c \
|
|
||||||
big/rectangle.c \
|
|
||||||
big/theme-image.c \
|
|
||||||
$(NULL)
|
|
||||||
|
|
||||||
big-enum-types.h: stamp-big-enum-types.h Makefile
|
|
||||||
@true
|
|
||||||
stamp-big-enum-types.h: $(big_source_h) big/big-enum-types.h.in
|
|
||||||
$(AM_V_GEN) ( cd $(srcdir) && \
|
|
||||||
$(GLIB_MKENUMS) \
|
|
||||||
--template $(srcdir)/big/big-enum-types.h.in \
|
|
||||||
$(big_source_h) ) >> xgen-beth && \
|
|
||||||
(cmp -s xgen-beth big-enum-types.h || cp xgen-beth big-enum-types.h) && \
|
|
||||||
rm -f xgen-beth && \
|
|
||||||
echo timestamp > $(@F)
|
|
||||||
|
|
||||||
big-enum-types.c: stamp-big-enum-types.h big/big-enum-types.c.in
|
|
||||||
$(AM_V_GEN) ( cd $(srcdir) && \
|
|
||||||
$(GLIB_MKENUMS) \
|
|
||||||
--template $(srcdir)/big/big-enum-types.c.in \
|
|
||||||
$(big_source_h) ) >> xgen-betc && \
|
|
||||||
cp xgen-betc big-enum-types.c && \
|
|
||||||
rm -f xgen-betc
|
|
||||||
|
|
||||||
noinst_LTLIBRARIES += libbig-1.0.la
|
|
||||||
|
|
||||||
libbig_1_0_la_LIBADD = -lm $(BIG_LIBS)
|
|
||||||
libbig_1_0_la_SOURCES = \
|
|
||||||
$(big_source_c) \
|
|
||||||
$(big_source_h) \
|
|
||||||
$(big_built_sources) \
|
|
||||||
$(NULL)
|
|
||||||
libbig_1_0_la_CPPFLAGS = $(big_cflags)
|
|
||||||
libbig_1_0_la_LDFLAGS = $(LDADD)
|
|
||||||
|
|
||||||
CLEANFILES += $(BIG_STAMP_FILES) $(BUILT_SOURCES)
|
|
||||||
|
|
||||||
EXTRA_DIST += \
|
|
||||||
big/README \
|
|
||||||
big/big-enum-types.h.in \
|
|
||||||
big/big-enum-types.c.in
|
|
@ -24,7 +24,6 @@ gnome-shell: gnome-shell.in
|
|||||||
CLEANFILES += gnome-shell
|
CLEANFILES += gnome-shell
|
||||||
EXTRA_DIST += gnome-shell.in
|
EXTRA_DIST += gnome-shell.in
|
||||||
|
|
||||||
include Makefile-big.am
|
|
||||||
include Makefile-gdmuser.am
|
include Makefile-gdmuser.am
|
||||||
include Makefile-st.am
|
include Makefile-st.am
|
||||||
include Makefile-tray.am
|
include Makefile-tray.am
|
||||||
@ -154,16 +153,15 @@ libgnome_shell_la_LDFLAGS = -avoid-version -module
|
|||||||
libgnome_shell_la_LIBADD =-lm \
|
libgnome_shell_la_LIBADD =-lm \
|
||||||
$(MUTTER_PLUGIN_LIBS) \
|
$(MUTTER_PLUGIN_LIBS) \
|
||||||
$(LIBGNOMEUI_LIBS) \
|
$(LIBGNOMEUI_LIBS) \
|
||||||
libbig-1.0.la \
|
|
||||||
libst-1.0.la \
|
libst-1.0.la \
|
||||||
libgdmuser-1.0.la \
|
libgdmuser-1.0.la \
|
||||||
libtray.la
|
libtray.la
|
||||||
libgnome_shell_la_CPPFLAGS = $(gnome_shell_cflags)
|
libgnome_shell_la_CPPFLAGS = $(gnome_shell_cflags)
|
||||||
|
|
||||||
typelibdir = $(pkglibdir)
|
typelibdir = $(pkglibdir)
|
||||||
typelib_DATA = Shell-0.1.typelib Big-1.0.typelib St-1.0.typelib Gdm-1.0.typelib
|
typelib_DATA = Shell-0.1.typelib St-1.0.typelib Gdm-1.0.typelib
|
||||||
|
|
||||||
Shell-0.1.gir: $(mutter) $(G_IR_SCANNER) Big-1.0.gir St-1.0.gir libgnome-shell.la Makefile
|
Shell-0.1.gir: $(mutter) $(G_IR_SCANNER) St-1.0.gir libgnome-shell.la Makefile
|
||||||
$(AM_V_GEN) $(G_IR_SCANNER) \
|
$(AM_V_GEN) $(G_IR_SCANNER) \
|
||||||
--namespace=Shell \
|
--namespace=Shell \
|
||||||
--nsversion=0.1 \
|
--nsversion=0.1 \
|
||||||
@ -172,7 +170,6 @@ Shell-0.1.gir: $(mutter) $(G_IR_SCANNER) Big-1.0.gir St-1.0.gir libgnome-shell.l
|
|||||||
--include=Meta-2.29 \
|
--include=Meta-2.29 \
|
||||||
--libtool="$(LIBTOOL)" \
|
--libtool="$(LIBTOOL)" \
|
||||||
--add-include-path=$(builddir) \
|
--add-include-path=$(builddir) \
|
||||||
--include=Big-1.0 \
|
|
||||||
--include=St-1.0 \
|
--include=St-1.0 \
|
||||||
--program=mutter \
|
--program=mutter \
|
||||||
--program-arg=--mutter-plugins=$$(pwd)/libgnome-shell.la \
|
--program-arg=--mutter-plugins=$$(pwd)/libgnome-shell.la \
|
||||||
@ -184,7 +181,7 @@ CLEANFILES += Shell-0.1.gir
|
|||||||
|
|
||||||
# The dependency on libgnome-shell.la here is because g-ir-compiler opens it
|
# The dependency on libgnome-shell.la here is because g-ir-compiler opens it
|
||||||
# (not the fake library, since we've already done the rewriting)
|
# (not the fake library, since we've already done the rewriting)
|
||||||
Shell-0.1.typelib: libgnome-shell.la Shell-0.1.gir Big-1.0.gir
|
Shell-0.1.typelib: libgnome-shell.la Shell-0.1.gir
|
||||||
$(AM_V_GEN) \
|
$(AM_V_GEN) \
|
||||||
$(G_IR_COMPILER) \
|
$(G_IR_COMPILER) \
|
||||||
--includedir=. \
|
--includedir=. \
|
||||||
@ -192,25 +189,6 @@ Shell-0.1.typelib: libgnome-shell.la Shell-0.1.gir Big-1.0.gir
|
|||||||
Shell-0.1.gir -o $@
|
Shell-0.1.gir -o $@
|
||||||
CLEANFILES += Shell-0.1.typelib
|
CLEANFILES += Shell-0.1.typelib
|
||||||
|
|
||||||
Big-1.0.gir: $(mutter) $(G_IR_SCANNER) libbig-1.0.la Makefile
|
|
||||||
$(AM_V_GEN) $(G_IR_SCANNER) \
|
|
||||||
--namespace=Big \
|
|
||||||
--nsversion=1.0 \
|
|
||||||
--include=Clutter-1.0 \
|
|
||||||
--include=GdkPixbuf-2.0 \
|
|
||||||
--libtool="$(LIBTOOL)" \
|
|
||||||
--library=libbig-1.0.la \
|
|
||||||
$(addprefix $(srcdir)/,$(big_source_h)) \
|
|
||||||
$(addprefix $(srcdir)/,$(big_source_c)) \
|
|
||||||
$(srcdir)/big-enum-types.h \
|
|
||||||
$(big_cflags) \
|
|
||||||
-o $@
|
|
||||||
CLEANFILES += Big-1.0.gir
|
|
||||||
|
|
||||||
Big-1.0.typelib: libbig-1.0.la Big-1.0.gir
|
|
||||||
$(AM_V_GEN) $(G_IR_COMPILER) Big-1.0.gir -o $@
|
|
||||||
CLEANFILES += Big-1.0.typelib
|
|
||||||
|
|
||||||
St-1.0.gir: $(mutter) $(G_IR_SCANNER) libst-1.0.la Makefile
|
St-1.0.gir: $(mutter) $(G_IR_SCANNER) libst-1.0.la Makefile
|
||||||
$(AM_V_GEN) $(G_IR_SCANNER) \
|
$(AM_V_GEN) $(G_IR_SCANNER) \
|
||||||
--namespace=St \
|
--namespace=St \
|
||||||
@ -248,7 +226,7 @@ Gdm-1.0.gir: $(mutter) $(G_IR_SCANNER) libgdmuser-1.0.la Makefile
|
|||||||
-o $@
|
-o $@
|
||||||
CLEANFILES += Gdm-1.0.gir
|
CLEANFILES += Gdm-1.0.gir
|
||||||
|
|
||||||
Gdm-1.0.typelib: libbig-1.0.la Gdm-1.0.gir
|
Gdm-1.0.typelib: Gdm-1.0.gir
|
||||||
$(AM_V_GEN) $(G_IR_COMPILER) Gdm-1.0.gir -o $@
|
$(AM_V_GEN) $(G_IR_COMPILER) Gdm-1.0.gir -o $@
|
||||||
CLEANFILES += Gdm-1.0.typelib
|
CLEANFILES += Gdm-1.0.typelib
|
||||||
|
|
||||||
|
@ -1,25 +0,0 @@
|
|||||||
The Clutter actors and other files in this directory were created by
|
|
||||||
litl, LLC. They are released under the terms of the Library General
|
|
||||||
Public license.
|
|
||||||
|
|
||||||
The idea is that these actors may eventually make their way into Clutter
|
|
||||||
or into other libraries.
|
|
||||||
|
|
||||||
litl has requested that these actors should not be publically
|
|
||||||
installed under the 'big_*' names to avoid conflicts with their
|
|
||||||
development. So if you use them in your applications, do *NOT*
|
|
||||||
install:
|
|
||||||
|
|
||||||
- A 'libbig' library
|
|
||||||
- The header files
|
|
||||||
- gobject-introspection data for these actors
|
|
||||||
|
|
||||||
Into public locations. You can of course, take the code and rename it,
|
|
||||||
as long as you respect the provisions of the LGPL, or install into
|
|
||||||
private locations as we do for gnome-shell. (We install the typelib
|
|
||||||
into a private location, link the source files directly into the
|
|
||||||
gnome-shell plugin so no external library is needed, and we don't
|
|
||||||
install the header files at all.)
|
|
||||||
|
|
||||||
Patches applied:
|
|
||||||
http://bugzilla.gnome.org/show_bug.cgi?id=562929
|
|
@ -1,30 +0,0 @@
|
|||||||
/*** BEGIN file-header ***/
|
|
||||||
#include "big-enum-types.h"
|
|
||||||
/*** END file-header ***/
|
|
||||||
|
|
||||||
/*** BEGIN file-production ***/
|
|
||||||
/* enumerations from "@filename@" */
|
|
||||||
#include "@filename@"
|
|
||||||
/*** END file-production ***/
|
|
||||||
|
|
||||||
/*** BEGIN value-header ***/
|
|
||||||
GType
|
|
||||||
@enum_name@_get_type(void) {
|
|
||||||
static GType enum_type_id = 0;
|
|
||||||
if (G_UNLIKELY (!enum_type_id))
|
|
||||||
{
|
|
||||||
static const G@Type@Value values[] = {
|
|
||||||
/*** END value-header ***/
|
|
||||||
|
|
||||||
/*** BEGIN value-production ***/
|
|
||||||
{ @VALUENAME@, "@VALUENAME@", "@valuenick@" },
|
|
||||||
/*** END value-production ***/
|
|
||||||
|
|
||||||
/*** BEGIN value-tail ***/
|
|
||||||
{ 0, NULL, NULL }
|
|
||||||
};
|
|
||||||
enum_type_id = g_@type@_register_static("@EnumName@", values);
|
|
||||||
}
|
|
||||||
return enum_type_id;
|
|
||||||
}
|
|
||||||
/*** END value-tail ***/
|
|
@ -1,25 +0,0 @@
|
|||||||
/*** BEGIN file-header ***/
|
|
||||||
#ifndef __BIG_ENUM_TYPES_H__
|
|
||||||
#define __BIG_ENUM_TYPES_H__
|
|
||||||
|
|
||||||
#include <glib-object.h>
|
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
|
||||||
|
|
||||||
/*** END file-header ***/
|
|
||||||
|
|
||||||
/*** BEGIN file-production ***/
|
|
||||||
/* enumerations from "@filename@" */
|
|
||||||
/*** END file-production ***/
|
|
||||||
|
|
||||||
/*** BEGIN file-tail ***/
|
|
||||||
G_END_DECLS
|
|
||||||
|
|
||||||
#endif /* !__BIG_ENUM_TYPES_H__ */
|
|
||||||
/*** END file-tail ***/
|
|
||||||
|
|
||||||
/*** BEGIN value-header ***/
|
|
||||||
GType @enum_name@_get_type (void) G_GNUC_CONST;
|
|
||||||
#define BIG_TYPE_@ENUMSHORT@ (@enum_name@_get_type())
|
|
||||||
|
|
||||||
/*** END value-header ***/
|
|
3060
src/big/box.c
3060
src/big/box.c
File diff suppressed because it is too large
Load Diff
129
src/big/box.h
129
src/big/box.h
@ -1,129 +0,0 @@
|
|||||||
/* -*- mode: C; c-basic-offset: 2; indent-tabs-mode: nil; -*- */
|
|
||||||
/* big-box.h: Box container.
|
|
||||||
|
|
||||||
Copyright (C) 2006-2008 Red Hat, Inc.
|
|
||||||
Copyright (C) 2008 litl, LLC.
|
|
||||||
|
|
||||||
The libbigwidgets-lgpl is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Library General Public License as
|
|
||||||
published by the Free Software Foundation; either version 2 of the
|
|
||||||
License, or (at your option) any later version.
|
|
||||||
|
|
||||||
The libbigwidgets-lgpl 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
|
|
||||||
Library General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Library General Public
|
|
||||||
License along with the libbigwidgets-lgpl; see the file COPYING.LIB.
|
|
||||||
If not, write to the Free Software Foundation, Inc., 59 Temple Place -
|
|
||||||
Suite 330, Boston, MA 02111-1307, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __BIG_BOX_H__
|
|
||||||
#define __BIG_BOX_H__
|
|
||||||
|
|
||||||
#include <clutter/clutter.h>
|
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
|
||||||
|
|
||||||
#define BIG_TYPE_BOX (big_box_get_type ())
|
|
||||||
#define BIG_BOX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), BIG_TYPE_BOX, BigBox))
|
|
||||||
#define BIG_IS_BOX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BIG_TYPE_BOX))
|
|
||||||
#define BIG_BOX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), BIG_TYPE_BOX, BigBoxClass))
|
|
||||||
#define BIG_IS_BOX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), BIG_TYPE_BOX))
|
|
||||||
#define BIG_BOX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), BIG_TYPE_BOX, BigBoxClass))
|
|
||||||
|
|
||||||
typedef struct _BigBox BigBox;
|
|
||||||
typedef struct _BigBoxPrivate BigBoxPrivate;
|
|
||||||
typedef struct _BigBoxClass BigBoxClass;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
BIG_BOX_PACK_NONE = 0,
|
|
||||||
BIG_BOX_PACK_EXPAND = 1 << 0,
|
|
||||||
BIG_BOX_PACK_END = 1 << 1,
|
|
||||||
BIG_BOX_PACK_IF_FITS = 1 << 2,
|
|
||||||
BIG_BOX_PACK_FIXED = 1 << 3,
|
|
||||||
BIG_BOX_PACK_ALLOCATE_WHEN_HIDDEN = 1 << 4
|
|
||||||
} BigBoxPackFlags;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
BIG_BOX_ALIGNMENT_FIXED = 0,
|
|
||||||
BIG_BOX_ALIGNMENT_FILL = 1,
|
|
||||||
BIG_BOX_ALIGNMENT_START = 2,
|
|
||||||
BIG_BOX_ALIGNMENT_END = 3,
|
|
||||||
BIG_BOX_ALIGNMENT_CENTER = 4
|
|
||||||
} BigBoxAlignment;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
BIG_BOX_ORIENTATION_VERTICAL = 1,
|
|
||||||
BIG_BOX_ORIENTATION_HORIZONTAL = 2
|
|
||||||
} BigBoxOrientation;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
BIG_BOX_BACKGROUND_REPEAT_NONE = 0,
|
|
||||||
BIG_BOX_BACKGROUND_REPEAT_X = 1,
|
|
||||||
BIG_BOX_BACKGROUND_REPEAT_Y = 2,
|
|
||||||
BIG_BOX_BACKGROUND_REPEAT_BOTH = 3,
|
|
||||||
} BigBoxBackgroundRepeat;
|
|
||||||
|
|
||||||
struct _BigBox
|
|
||||||
{
|
|
||||||
ClutterActor parent_instance;
|
|
||||||
|
|
||||||
BigBoxPrivate *priv;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _BigBoxClass
|
|
||||||
{
|
|
||||||
ClutterActorClass parent_class;
|
|
||||||
};
|
|
||||||
|
|
||||||
GType big_box_get_type (void) G_GNUC_CONST;
|
|
||||||
|
|
||||||
ClutterActor *big_box_new (BigBoxOrientation orientation);
|
|
||||||
|
|
||||||
void big_box_prepend (BigBox *box,
|
|
||||||
ClutterActor *child,
|
|
||||||
BigBoxPackFlags flags);
|
|
||||||
|
|
||||||
void big_box_append (BigBox *box,
|
|
||||||
ClutterActor *child,
|
|
||||||
BigBoxPackFlags flags);
|
|
||||||
|
|
||||||
gboolean big_box_is_empty (BigBox *box);
|
|
||||||
|
|
||||||
void big_box_remove_all (BigBox *box);
|
|
||||||
|
|
||||||
void big_box_insert_after (BigBox *box,
|
|
||||||
ClutterActor *child,
|
|
||||||
ClutterActor *ref_child,
|
|
||||||
BigBoxPackFlags flags);
|
|
||||||
|
|
||||||
void big_box_insert_before (BigBox *box,
|
|
||||||
ClutterActor *child,
|
|
||||||
ClutterActor *ref_child,
|
|
||||||
BigBoxPackFlags flags);
|
|
||||||
|
|
||||||
void big_box_set_child_packing (BigBox *box,
|
|
||||||
ClutterActor *child,
|
|
||||||
BigBoxPackFlags flags);
|
|
||||||
|
|
||||||
void big_box_set_child_align (BigBox *box,
|
|
||||||
ClutterActor *child,
|
|
||||||
BigBoxAlignment fixed_x_align,
|
|
||||||
BigBoxAlignment fixed_y_align);
|
|
||||||
|
|
||||||
void big_box_set_padding (BigBox *box,
|
|
||||||
int padding);
|
|
||||||
|
|
||||||
void big_box_set_border_width (BigBox *box,
|
|
||||||
int border_width);
|
|
||||||
|
|
||||||
G_END_DECLS
|
|
||||||
|
|
||||||
#endif /* __BIG_BOX_H__ */
|
|
@ -1,658 +0,0 @@
|
|||||||
/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
|
|
||||||
/* rectangle.c: Rounded rectangle.
|
|
||||||
|
|
||||||
Copyright (C) 2008 litl, LLC.
|
|
||||||
|
|
||||||
The libbigwidgets-lgpl is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Library General Public License as
|
|
||||||
published by the Free Software Foundation; either version 2 of the
|
|
||||||
License, or (at your option) any later version.
|
|
||||||
|
|
||||||
The libbigwidgets-lgpl 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
|
|
||||||
Library General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Library General Public
|
|
||||||
License along with the libbigwidgets-lgpl; see the file COPYING.LIB.
|
|
||||||
If not, write to the Free Software Foundation, Inc., 59 Temple Place -
|
|
||||||
Suite 330, Boston, MA 02111-1307, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
#include <glib.h>
|
|
||||||
#include <clutter/clutter.h>
|
|
||||||
#include <cogl/cogl.h>
|
|
||||||
#include <cairo/cairo.h>
|
|
||||||
|
|
||||||
#include "rectangle.h"
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
gint ref_count;
|
|
||||||
|
|
||||||
ClutterColor color;
|
|
||||||
ClutterColor border_color;
|
|
||||||
int radius;
|
|
||||||
int border_width;
|
|
||||||
|
|
||||||
CoglHandle texture;
|
|
||||||
guint8 *data;
|
|
||||||
} Corner;
|
|
||||||
|
|
||||||
struct BigRectangle {
|
|
||||||
ClutterRectangle parent_instance;
|
|
||||||
float radius;
|
|
||||||
Corner *corner;
|
|
||||||
CoglHandle corner_material;
|
|
||||||
CoglHandle border_material;
|
|
||||||
CoglHandle background_material;
|
|
||||||
gboolean corners_dirty;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* map of { radius, border_width, border_color, color } to Corner textures */
|
|
||||||
static GHashTable *all_corners = NULL;
|
|
||||||
|
|
||||||
struct BigRectangleClass {
|
|
||||||
ClutterRectangleClass parent_class;
|
|
||||||
};
|
|
||||||
|
|
||||||
G_DEFINE_TYPE(BigRectangle, big_rectangle, CLUTTER_TYPE_RECTANGLE)
|
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
PROP_0,
|
|
||||||
|
|
||||||
PROP_CORNER_RADIUS
|
|
||||||
};
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
corner_equal(gconstpointer a,
|
|
||||||
gconstpointer b)
|
|
||||||
{
|
|
||||||
const Corner *corner_a;
|
|
||||||
const Corner *corner_b;
|
|
||||||
|
|
||||||
corner_a = a;
|
|
||||||
corner_b = b;
|
|
||||||
|
|
||||||
return *((guint32 *)&corner_a->color) == *((guint32 *)&corner_b->color) &&
|
|
||||||
*((guint32 *)&corner_a->border_color) == *((guint32 *)&corner_b->border_color) &&
|
|
||||||
corner_a->border_width == corner_b->border_width &&
|
|
||||||
corner_a->radius == corner_b->radius;
|
|
||||||
}
|
|
||||||
|
|
||||||
static guint
|
|
||||||
corner_hash(gconstpointer key)
|
|
||||||
{
|
|
||||||
const Corner *corner;
|
|
||||||
guint hashed[4];
|
|
||||||
|
|
||||||
corner = key;
|
|
||||||
|
|
||||||
hashed[0] = *((guint *)&(corner->color));
|
|
||||||
hashed[1] = *((guint *)&(corner->border_color));
|
|
||||||
hashed[2] = *((guint *)&(corner->border_width));
|
|
||||||
hashed[3] = *((guint *)&(corner->radius));
|
|
||||||
|
|
||||||
return hashed[0] ^ hashed[1] ^ hashed[2] ^ hashed[3];
|
|
||||||
}
|
|
||||||
|
|
||||||
static Corner *
|
|
||||||
create_corner_texture(Corner *src)
|
|
||||||
{
|
|
||||||
Corner *corner;
|
|
||||||
CoglHandle texture;
|
|
||||||
cairo_t *cr;
|
|
||||||
cairo_surface_t *surface;
|
|
||||||
guint x, y;
|
|
||||||
guint rowstride;
|
|
||||||
guint8 *data;
|
|
||||||
guint32 *src_p;
|
|
||||||
guint8 *dst_p;
|
|
||||||
guint size;
|
|
||||||
|
|
||||||
corner = g_memdup(src, sizeof(Corner));
|
|
||||||
|
|
||||||
size = 2 * MAX(corner->border_width, corner->radius);
|
|
||||||
rowstride = size * 4;
|
|
||||||
data = g_new0(guint8, size * rowstride);
|
|
||||||
|
|
||||||
surface = cairo_image_surface_create_for_data(data,
|
|
||||||
CAIRO_FORMAT_ARGB32,
|
|
||||||
size, size,
|
|
||||||
rowstride);
|
|
||||||
cr = cairo_create(surface);
|
|
||||||
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
|
|
||||||
cairo_scale(cr, size, size);
|
|
||||||
|
|
||||||
if (corner->border_width < corner->radius) {
|
|
||||||
double internal_radius = 0.5 * (1.0 - (double) corner->border_width / corner->radius);
|
|
||||||
|
|
||||||
if (corner->border_width != 0) {
|
|
||||||
cairo_set_source_rgba(cr,
|
|
||||||
(double)corner->border_color.red / G_MAXUINT8,
|
|
||||||
(double)corner->border_color.green / G_MAXUINT8,
|
|
||||||
(double)corner->border_color.blue / G_MAXUINT8,
|
|
||||||
(double)corner->border_color.alpha / G_MAXUINT8);
|
|
||||||
|
|
||||||
cairo_arc(cr, 0.5, 0.5, 0.5, 0, 2 * M_PI);
|
|
||||||
cairo_fill(cr);
|
|
||||||
}
|
|
||||||
|
|
||||||
cairo_set_source_rgba(cr,
|
|
||||||
(double)corner->color.red / G_MAXUINT8,
|
|
||||||
(double)corner->color.green / G_MAXUINT8,
|
|
||||||
(double)corner->color.blue / G_MAXUINT8,
|
|
||||||
(double)corner->color.alpha / G_MAXUINT8);
|
|
||||||
cairo_arc(cr, 0.5, 0.5, internal_radius, 0, 2 * M_PI);
|
|
||||||
cairo_fill(cr);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
double radius;
|
|
||||||
|
|
||||||
radius = (gdouble)corner->radius / corner->border_width;
|
|
||||||
|
|
||||||
cairo_set_source_rgba(cr,
|
|
||||||
(double)corner->border_color.red / G_MAXUINT8,
|
|
||||||
(double)corner->border_color.green / G_MAXUINT8,
|
|
||||||
(double)corner->border_color.blue / G_MAXUINT8,
|
|
||||||
(double)corner->border_color.alpha / G_MAXUINT8);
|
|
||||||
|
|
||||||
cairo_arc(cr, radius, radius, radius, M_PI, 3 * M_PI / 2);
|
|
||||||
cairo_line_to(cr, 1.0 - radius, 0.0);
|
|
||||||
cairo_arc(cr, 1.0 - radius, radius, radius, 3 * M_PI / 2, 2*M_PI);
|
|
||||||
cairo_line_to(cr, 1.0, 1.0 - radius);
|
|
||||||
cairo_arc(cr, 1.0 - radius, 1.0 - radius, radius, 0, M_PI / 2);
|
|
||||||
cairo_line_to(cr, radius, 1.0);
|
|
||||||
cairo_arc(cr, radius, 1.0 - radius, radius, M_PI / 2, M_PI);
|
|
||||||
cairo_fill(cr);
|
|
||||||
}
|
|
||||||
cairo_destroy(cr);
|
|
||||||
|
|
||||||
cairo_surface_destroy(surface);
|
|
||||||
|
|
||||||
corner->data = g_new0(guint8, size * rowstride);
|
|
||||||
|
|
||||||
/* cogl doesn't seem to support the conversion, do it manually */
|
|
||||||
/* borrowed from clutter-cairo, conversion from ARGB pre-multiplied
|
|
||||||
* to RGBA */
|
|
||||||
for (y = 0; y < size; y++) {
|
|
||||||
src_p = (guint32 *) (data + y * rowstride);
|
|
||||||
dst_p = corner->data + y * rowstride;
|
|
||||||
|
|
||||||
for (x = 0; x < size; x++) {
|
|
||||||
guint8 alpha = (*src_p >> 24) & 0xff;
|
|
||||||
|
|
||||||
if (alpha == 0) {
|
|
||||||
dst_p[0] = dst_p[1] = dst_p[2] = dst_p[3] = alpha;
|
|
||||||
} else {
|
|
||||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
|
||||||
dst_p[0] = (((*src_p >> 16) & 0xff) * 255 ) / alpha;
|
|
||||||
dst_p[1] = (((*src_p >> 8) & 0xff) * 255 ) / alpha;
|
|
||||||
dst_p[2] = (((*src_p >> 0) & 0xff) * 255 ) / alpha;
|
|
||||||
dst_p[3] = alpha;
|
|
||||||
#elif G_BYTE_ORDER == G_BIG_ENDIAN
|
|
||||||
dst_p[0] = alpha;
|
|
||||||
dst_p[1] = (((*src_p >> 0) & 0xff) * 255 ) / alpha;
|
|
||||||
dst_p[2] = (((*src_p >> 8) & 0xff) * 255 ) / alpha;
|
|
||||||
dst_p[3] = (((*src_p >> 16) & 0xff) * 255 ) / alpha;
|
|
||||||
#else /* !G_LITTLE_ENDIAN && !G_BIG_ENDIAN */
|
|
||||||
#error unknown ENDIAN type
|
|
||||||
#endif /* !G_LITTLE_ENDIAN && !G_BIG_ENDIAN */
|
|
||||||
}
|
|
||||||
dst_p += 4;
|
|
||||||
src_p++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
g_free(data);
|
|
||||||
|
|
||||||
texture = cogl_texture_new_from_data(size, size,
|
|
||||||
COGL_TEXTURE_NONE,
|
|
||||||
COGL_PIXEL_FORMAT_RGBA_8888,
|
|
||||||
COGL_PIXEL_FORMAT_ANY,
|
|
||||||
rowstride,
|
|
||||||
corner->data);
|
|
||||||
g_assert(texture != COGL_INVALID_HANDLE);
|
|
||||||
|
|
||||||
corner->ref_count = 1;
|
|
||||||
corner->texture = texture;
|
|
||||||
|
|
||||||
g_hash_table_insert(all_corners, corner, corner);
|
|
||||||
|
|
||||||
return corner;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
corner_unref(Corner *corner)
|
|
||||||
{
|
|
||||||
corner->ref_count --;
|
|
||||||
|
|
||||||
if (corner->ref_count == 0) {
|
|
||||||
g_hash_table_remove(all_corners, corner);
|
|
||||||
|
|
||||||
cogl_handle_unref(corner->texture);
|
|
||||||
g_free(corner->data);
|
|
||||||
g_free(corner);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static Corner *
|
|
||||||
corner_get(guint radius,
|
|
||||||
ClutterColor *color,
|
|
||||||
guint border_width,
|
|
||||||
ClutterColor *border_color)
|
|
||||||
{
|
|
||||||
Corner key;
|
|
||||||
Corner *corner;
|
|
||||||
|
|
||||||
if (all_corners == NULL) {
|
|
||||||
all_corners = g_hash_table_new(corner_hash, corner_equal);
|
|
||||||
}
|
|
||||||
|
|
||||||
key.radius = radius;
|
|
||||||
key.color = *color;
|
|
||||||
key.border_color = *border_color;
|
|
||||||
key.border_width = border_width;
|
|
||||||
|
|
||||||
corner = g_hash_table_lookup(all_corners, &key);
|
|
||||||
|
|
||||||
if (!corner) {
|
|
||||||
corner = create_corner_texture(&key);
|
|
||||||
} else {
|
|
||||||
corner->ref_count ++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return corner;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* To match the CSS specification, we want the border to look like it was
|
|
||||||
* drawn over the background. But actually drawing the border over the
|
|
||||||
* background will produce slightly bad antialiasing at the edges, so
|
|
||||||
* compute the effective border color instead.
|
|
||||||
*/
|
|
||||||
#define NORM(x) (t = (x) + 127, (t + (t >> 8)) >> 8)
|
|
||||||
#define MULT(c,a) NORM(c*a)
|
|
||||||
|
|
||||||
static void
|
|
||||||
premultiply (ClutterColor *color)
|
|
||||||
{
|
|
||||||
guint t;
|
|
||||||
color->red = MULT (color->red, color->alpha);
|
|
||||||
color->green = MULT (color->green, color->alpha);
|
|
||||||
color->blue = MULT (color->blue, color->alpha);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
unpremultiply (ClutterColor *color)
|
|
||||||
{
|
|
||||||
if (color->alpha != 0) {
|
|
||||||
color->red = (color->red * 255 + 127) / color->alpha;
|
|
||||||
color->green = (color->green * 255 + 127) / color->alpha;
|
|
||||||
color->blue = (color->blue * 255 + 127) / color->alpha;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
over (const ClutterColor *source,
|
|
||||||
const ClutterColor *destination,
|
|
||||||
ClutterColor *result)
|
|
||||||
{
|
|
||||||
guint t;
|
|
||||||
ClutterColor src = *source;
|
|
||||||
ClutterColor dst = *destination;
|
|
||||||
premultiply (&src);
|
|
||||||
premultiply (&dst);
|
|
||||||
|
|
||||||
result->alpha = src.alpha + NORM ((255 - src.alpha) * dst.alpha);
|
|
||||||
result->red = src.red + NORM ((255 - src.alpha) * dst.red);
|
|
||||||
result->green = src.green + NORM ((255 - src.alpha) * dst.green);
|
|
||||||
result->blue = src.blue + NORM ((255 - src.alpha) * dst.blue);
|
|
||||||
|
|
||||||
unpremultiply (result);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
big_rectangle_update_corners(BigRectangle *rectangle)
|
|
||||||
{
|
|
||||||
Corner *corner;
|
|
||||||
|
|
||||||
corner = NULL;
|
|
||||||
|
|
||||||
if (rectangle->radius != 0) {
|
|
||||||
ClutterColor *color;
|
|
||||||
ClutterColor *border_color;
|
|
||||||
ClutterColor effective_border;
|
|
||||||
guint border_width;
|
|
||||||
|
|
||||||
g_object_get(rectangle,
|
|
||||||
"border-color", &border_color,
|
|
||||||
"border-width", &border_width,
|
|
||||||
"color", &color,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
over (border_color, color, &effective_border);
|
|
||||||
|
|
||||||
corner = corner_get(rectangle->radius,
|
|
||||||
color,
|
|
||||||
border_width,
|
|
||||||
&effective_border);
|
|
||||||
|
|
||||||
clutter_color_free(border_color);
|
|
||||||
clutter_color_free(color);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rectangle->corner) {
|
|
||||||
corner_unref(rectangle->corner);
|
|
||||||
}
|
|
||||||
|
|
||||||
rectangle->corner = corner;
|
|
||||||
|
|
||||||
if (corner) {
|
|
||||||
if (!rectangle->corner_material)
|
|
||||||
rectangle->corner_material = cogl_material_new();
|
|
||||||
|
|
||||||
cogl_material_set_layer (rectangle->corner_material, 0,
|
|
||||||
rectangle->corner->texture);
|
|
||||||
}
|
|
||||||
|
|
||||||
rectangle->corners_dirty = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
big_rectangle_paint(ClutterActor *actor)
|
|
||||||
{
|
|
||||||
BigRectangle *rectangle;
|
|
||||||
ClutterColor *color;
|
|
||||||
ClutterColor *border_color;
|
|
||||||
guint8 actor_opacity;
|
|
||||||
CoglColor tmp_color;
|
|
||||||
guint border_width;
|
|
||||||
ClutterActorBox box;
|
|
||||||
float radius;
|
|
||||||
float width;
|
|
||||||
float height;
|
|
||||||
float max;
|
|
||||||
|
|
||||||
rectangle = BIG_RECTANGLE(actor);
|
|
||||||
|
|
||||||
/* We can't chain up, even when we the radius is 0, because of the different
|
|
||||||
* interpretation of the border/background relationship here than for
|
|
||||||
* ClutterRectangle.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (rectangle->corners_dirty)
|
|
||||||
big_rectangle_update_corners(rectangle);
|
|
||||||
|
|
||||||
g_object_get(rectangle,
|
|
||||||
"border-color", &border_color,
|
|
||||||
"border-width", &border_width,
|
|
||||||
"color", &color,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (border_color->alpha == 0 && color->alpha == 0)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
actor_opacity = clutter_actor_get_paint_opacity (actor);
|
|
||||||
|
|
||||||
clutter_actor_get_allocation_box(actor, &box);
|
|
||||||
|
|
||||||
/* translation was already done */
|
|
||||||
box.x2 -= box.x1;
|
|
||||||
box.y2 -= box.y1;
|
|
||||||
|
|
||||||
width = box.x2;
|
|
||||||
height = box.y2;
|
|
||||||
|
|
||||||
radius = rectangle->radius;
|
|
||||||
|
|
||||||
/* Optimization; if the border is transparent, it just looks like part of
|
|
||||||
* the background */
|
|
||||||
if (radius == 0 && border_color->alpha == 0)
|
|
||||||
border_width = 0;
|
|
||||||
|
|
||||||
max = MAX(border_width, radius);
|
|
||||||
|
|
||||||
if (radius != 0) {
|
|
||||||
cogl_color_set_from_4ub(&tmp_color,
|
|
||||||
actor_opacity, actor_opacity, actor_opacity, actor_opacity);
|
|
||||||
cogl_material_set_color(rectangle->corner_material, &tmp_color);
|
|
||||||
cogl_set_source(rectangle->corner_material);
|
|
||||||
|
|
||||||
/* NW */
|
|
||||||
cogl_rectangle_with_texture_coords(0, 0,
|
|
||||||
max, max,
|
|
||||||
0, 0,
|
|
||||||
0.5, 0.5);
|
|
||||||
|
|
||||||
/* NE */
|
|
||||||
cogl_rectangle_with_texture_coords(width - max, 0,
|
|
||||||
width, max,
|
|
||||||
0.5, 0,
|
|
||||||
1.0, 0.5);
|
|
||||||
|
|
||||||
/* SW */
|
|
||||||
cogl_rectangle_with_texture_coords(0, height - max,
|
|
||||||
max, height,
|
|
||||||
0, 0.5,
|
|
||||||
0.5, 1.0);
|
|
||||||
|
|
||||||
/* SE */
|
|
||||||
cogl_rectangle_with_texture_coords(width - max, height - max,
|
|
||||||
width, height,
|
|
||||||
0.5, 0.5,
|
|
||||||
1.0, 1.0);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (border_width != 0) {
|
|
||||||
ClutterColor effective_border;
|
|
||||||
over (border_color, color, &effective_border);
|
|
||||||
|
|
||||||
if (!rectangle->border_material)
|
|
||||||
rectangle->border_material = cogl_material_new ();
|
|
||||||
|
|
||||||
cogl_color_set_from_4ub(&tmp_color,
|
|
||||||
effective_border.red,
|
|
||||||
effective_border.green,
|
|
||||||
effective_border.blue,
|
|
||||||
actor_opacity * effective_border.alpha / 255);
|
|
||||||
cogl_color_premultiply (&tmp_color);
|
|
||||||
cogl_material_set_color(rectangle->border_material, &tmp_color);
|
|
||||||
cogl_set_source(rectangle->border_material);
|
|
||||||
|
|
||||||
if (radius > 0) { /* skip corners */
|
|
||||||
/* NORTH */
|
|
||||||
cogl_rectangle(max, 0,
|
|
||||||
width - max, border_width);
|
|
||||||
|
|
||||||
/* EAST */
|
|
||||||
cogl_rectangle(width - border_width, max,
|
|
||||||
width, height - max);
|
|
||||||
|
|
||||||
/* SOUTH */
|
|
||||||
cogl_rectangle(max, height - border_width,
|
|
||||||
width - max, height);
|
|
||||||
|
|
||||||
/* WEST */
|
|
||||||
cogl_rectangle(0, max,
|
|
||||||
border_width, height - max);
|
|
||||||
} else { /* include corners */
|
|
||||||
/* NORTH */
|
|
||||||
cogl_rectangle(0, 0,
|
|
||||||
width, border_width);
|
|
||||||
|
|
||||||
/* EAST */
|
|
||||||
cogl_rectangle(width - border_width, border_width,
|
|
||||||
width, height - border_width);
|
|
||||||
|
|
||||||
/* SOUTH */
|
|
||||||
cogl_rectangle(0, height - border_width,
|
|
||||||
width, height);
|
|
||||||
|
|
||||||
/* WEST */
|
|
||||||
cogl_rectangle(0, border_width,
|
|
||||||
border_width, height - border_width);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!rectangle->background_material)
|
|
||||||
rectangle->background_material = cogl_material_new ();
|
|
||||||
|
|
||||||
cogl_color_set_from_4ub(&tmp_color,
|
|
||||||
color->red,
|
|
||||||
color->green,
|
|
||||||
color->blue,
|
|
||||||
actor_opacity * color->alpha / 255);
|
|
||||||
cogl_color_premultiply (&tmp_color);
|
|
||||||
cogl_material_set_color(rectangle->background_material, &tmp_color);
|
|
||||||
cogl_set_source(rectangle->background_material);
|
|
||||||
|
|
||||||
if (radius > border_width) {
|
|
||||||
/* Once we've drawn the borders and corners, if the corners are bigger
|
|
||||||
* the the border width, the remaining area is shaped like
|
|
||||||
*
|
|
||||||
* ########
|
|
||||||
* ##########
|
|
||||||
* ##########
|
|
||||||
* ########
|
|
||||||
*
|
|
||||||
* We draw it in 3 pieces - first the top and bottom, then the main
|
|
||||||
* rectangle
|
|
||||||
*/
|
|
||||||
cogl_rectangle(radius, border_width,
|
|
||||||
width - radius, radius);
|
|
||||||
cogl_rectangle(radius, height - radius,
|
|
||||||
width - radius, height - border_width);
|
|
||||||
}
|
|
||||||
|
|
||||||
cogl_rectangle(border_width, max,
|
|
||||||
width - border_width, height - max);
|
|
||||||
|
|
||||||
out:
|
|
||||||
clutter_color_free(border_color);
|
|
||||||
clutter_color_free(color);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
big_rectangle_notify(GObject *object,
|
|
||||||
GParamSpec *pspec)
|
|
||||||
{
|
|
||||||
BigRectangle *rectangle;
|
|
||||||
|
|
||||||
rectangle = BIG_RECTANGLE(object);
|
|
||||||
|
|
||||||
if (g_str_equal(pspec->name, "border-width") ||
|
|
||||||
g_str_equal(pspec->name, "color") ||
|
|
||||||
g_str_equal(pspec->name, "border-color")) {
|
|
||||||
rectangle->corners_dirty = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
big_rectangle_set_property(GObject *object,
|
|
||||||
guint prop_id,
|
|
||||||
const GValue *value,
|
|
||||||
GParamSpec *pspec)
|
|
||||||
{
|
|
||||||
BigRectangle *rectangle;
|
|
||||||
|
|
||||||
rectangle = BIG_RECTANGLE(object);
|
|
||||||
|
|
||||||
switch (prop_id) {
|
|
||||||
case PROP_CORNER_RADIUS:
|
|
||||||
rectangle->radius = g_value_get_uint(value);
|
|
||||||
rectangle->corners_dirty = TRUE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
big_rectangle_get_property(GObject *object,
|
|
||||||
guint prop_id,
|
|
||||||
GValue *value,
|
|
||||||
GParamSpec *pspec)
|
|
||||||
{
|
|
||||||
BigRectangle *rectangle;
|
|
||||||
|
|
||||||
rectangle = BIG_RECTANGLE(object);
|
|
||||||
|
|
||||||
switch (prop_id) {
|
|
||||||
case PROP_CORNER_RADIUS:
|
|
||||||
g_value_set_uint(value, rectangle->radius);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
big_rectangle_dispose(GObject *object)
|
|
||||||
{
|
|
||||||
BigRectangle *rectangle;
|
|
||||||
|
|
||||||
rectangle = BIG_RECTANGLE(object);
|
|
||||||
|
|
||||||
if (rectangle->corner) {
|
|
||||||
corner_unref(rectangle->corner);
|
|
||||||
rectangle->corner = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rectangle->corner_material) {
|
|
||||||
cogl_handle_unref (rectangle->corner_material);
|
|
||||||
rectangle->corner_material = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rectangle->background_material) {
|
|
||||||
cogl_handle_unref (rectangle->background_material);
|
|
||||||
rectangle->background_material = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rectangle->border_material) {
|
|
||||||
cogl_handle_unref (rectangle->border_material);
|
|
||||||
rectangle->border_material = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (G_OBJECT_CLASS(big_rectangle_parent_class)->dispose)
|
|
||||||
G_OBJECT_CLASS(big_rectangle_parent_class)->dispose(object);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
big_rectangle_class_init(BigRectangleClass *klass)
|
|
||||||
{
|
|
||||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
|
||||||
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
|
||||||
|
|
||||||
gobject_class->dispose = big_rectangle_dispose;
|
|
||||||
gobject_class->set_property = big_rectangle_set_property;
|
|
||||||
gobject_class->get_property = big_rectangle_get_property;
|
|
||||||
gobject_class->notify = big_rectangle_notify;
|
|
||||||
|
|
||||||
actor_class->paint = big_rectangle_paint;
|
|
||||||
|
|
||||||
g_object_class_install_property
|
|
||||||
(gobject_class,
|
|
||||||
PROP_CORNER_RADIUS,
|
|
||||||
g_param_spec_uint("corner-radius",
|
|
||||||
"Corner radius",
|
|
||||||
"Radius of the rectangle rounded corner",
|
|
||||||
0, G_MAXUINT,
|
|
||||||
0,
|
|
||||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
big_rectangle_init(BigRectangle *rectangle)
|
|
||||||
{
|
|
||||||
}
|
|
@ -1,42 +0,0 @@
|
|||||||
/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
|
|
||||||
/*
|
|
||||||
Copyright (C) 2008 litl, LLC.
|
|
||||||
|
|
||||||
The libbigwidgets-lgpl is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Library General Public License as
|
|
||||||
published by the Free Software Foundation; either version 2 of the
|
|
||||||
License, or (at your option) any later version.
|
|
||||||
|
|
||||||
The libbigwidgets-lgpl 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
|
|
||||||
Library General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Library General Public
|
|
||||||
License along with the libbigwidgets-lgpl; see the file COPYING.LIB.
|
|
||||||
If not, write to the Free Software Foundation, Inc., 59 Temple Place -
|
|
||||||
Suite 330, Boston, MA 02111-1307, USA.
|
|
||||||
*/
|
|
||||||
#ifndef __BIG_RECTANGLE_H__
|
|
||||||
#define __BIG_RECTANGLE_H__
|
|
||||||
|
|
||||||
#include <glib-object.h>
|
|
||||||
#include <clutter/clutter.h>
|
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
|
||||||
|
|
||||||
#define BIG_TYPE_RECTANGLE (big_rectangle_get_type ())
|
|
||||||
#define BIG_RECTANGLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), BIG_TYPE_RECTANGLE, BigRectangle))
|
|
||||||
#define BIG_RECTANGLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), BIG_TYPE_RECTANGLE, BigRectangleClass))
|
|
||||||
#define BIG_IS_RECTANGLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BIG_TYPE_RECTANGLE))
|
|
||||||
#define BIG_IS_RECTANGLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), BIG_TYPE_RECTANGLE))
|
|
||||||
#define BIG_RECTANGLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), BIG_TYPE_RECTANGLE, BigRectangleClass))
|
|
||||||
|
|
||||||
typedef struct BigRectangle BigRectangle;
|
|
||||||
typedef struct BigRectangleClass BigRectangleClass;
|
|
||||||
|
|
||||||
GType big_rectangle_get_type (void) G_GNUC_CONST;
|
|
||||||
|
|
||||||
G_END_DECLS
|
|
||||||
|
|
||||||
#endif /* __BIG_RECTANGLE_H__ */
|
|
@ -1,791 +0,0 @@
|
|||||||
/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
|
|
||||||
/* theme-image.c: Stretched image.
|
|
||||||
|
|
||||||
Copyright (C) 2005-2008 Red Hat, Inc.
|
|
||||||
Copyright (C) 2008 litl, LLC.
|
|
||||||
|
|
||||||
The libbigwidgets-lgpl is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Library General Public License as
|
|
||||||
published by the Free Software Foundation; either version 2 of the
|
|
||||||
License, or (at your option) any later version.
|
|
||||||
|
|
||||||
The libbigwidgets-lgpl 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
|
|
||||||
Library General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Library General Public
|
|
||||||
License along with the libbigwidgets-lgpl; see the file COPYING.LIB.
|
|
||||||
If not, write to the Free Software Foundation, Inc., 59 Temple Place -
|
|
||||||
Suite 330, Boston, MA 02111-1307, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <glib.h>
|
|
||||||
|
|
||||||
#include <clutter/clutter.h>
|
|
||||||
|
|
||||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
|
||||||
|
|
||||||
#include <librsvg/rsvg.h>
|
|
||||||
#include <librsvg/rsvg-cairo.h>
|
|
||||||
|
|
||||||
#include "theme-image.h"
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
BIG_THEME_IMAGE_UNSET,
|
|
||||||
BIG_THEME_IMAGE_SVG,
|
|
||||||
BIG_THEME_IMAGE_SURFACE
|
|
||||||
|
|
||||||
} BigThemeImageType;
|
|
||||||
|
|
||||||
struct BigThemeImage {
|
|
||||||
ClutterCairoTexture parent_instance;
|
|
||||||
|
|
||||||
guint border_top;
|
|
||||||
guint border_bottom;
|
|
||||||
guint border_left;
|
|
||||||
guint border_right;
|
|
||||||
|
|
||||||
BigThemeImageType type;
|
|
||||||
|
|
||||||
union {
|
|
||||||
RsvgHandle *svg_handle;
|
|
||||||
cairo_surface_t *surface;
|
|
||||||
} u;
|
|
||||||
|
|
||||||
guint render_idle;
|
|
||||||
guint needs_render : 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct BigThemeImageClass {
|
|
||||||
ClutterCairoTextureClass parent_class;
|
|
||||||
};
|
|
||||||
|
|
||||||
G_DEFINE_TYPE(BigThemeImage, big_theme_image, CLUTTER_TYPE_CAIRO_TEXTURE)
|
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
PROP_0,
|
|
||||||
|
|
||||||
PROP_BORDER_TOP,
|
|
||||||
PROP_BORDER_BOTTOM,
|
|
||||||
PROP_BORDER_LEFT,
|
|
||||||
PROP_BORDER_RIGHT,
|
|
||||||
|
|
||||||
PROP_FILENAME,
|
|
||||||
PROP_PIXBUF
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
big_theme_image_render(BigThemeImage *image)
|
|
||||||
{
|
|
||||||
int source_width = 0;
|
|
||||||
int source_height = 0;
|
|
||||||
int source_x1 = 0, source_x2 = 0, source_y1 = 0, source_y2 = 0;
|
|
||||||
int dest_x1 = 0, dest_x2 = 0, dest_y1 = 0, dest_y2 = 0;
|
|
||||||
int i, j;
|
|
||||||
int dest_width;
|
|
||||||
int dest_height;
|
|
||||||
ClutterGeometry geometry;
|
|
||||||
cairo_t *cr;
|
|
||||||
|
|
||||||
image->needs_render = FALSE;
|
|
||||||
|
|
||||||
if (image->render_idle) {
|
|
||||||
g_source_remove(image->render_idle);
|
|
||||||
image->render_idle = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* To draw a theme image, we divide the source and destination into 9
|
|
||||||
* pieces and draw each piece separately. (Some pieces may not exist
|
|
||||||
* if we have 0-width borders, in which case they'll be skipped)
|
|
||||||
*
|
|
||||||
* i=0 i=1 i=2
|
|
||||||
* border_left border_right
|
|
||||||
* +------------+--------------------+--------------+
|
|
||||||
* j=0: border_top | | | |
|
|
||||||
* +------------+--------------------+--------------+
|
|
||||||
* j=1 | | | |
|
|
||||||
* +------------+--------------------+--------------+
|
|
||||||
* j=2: border_bottom | | | |
|
|
||||||
* +------------+--------------------+--------------+
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
switch (image->type) {
|
|
||||||
case BIG_THEME_IMAGE_SURFACE:
|
|
||||||
if (!image->u.surface)
|
|
||||||
return;
|
|
||||||
|
|
||||||
source_width = cairo_image_surface_get_width(image->u.surface);
|
|
||||||
source_height = cairo_image_surface_get_height(image->u.surface);
|
|
||||||
break;
|
|
||||||
case BIG_THEME_IMAGE_SVG:
|
|
||||||
{
|
|
||||||
RsvgDimensionData dimensions;
|
|
||||||
|
|
||||||
if (!image->u.svg_handle)
|
|
||||||
return;
|
|
||||||
|
|
||||||
rsvg_handle_get_dimensions(image->u.svg_handle, &dimensions);
|
|
||||||
source_width = dimensions.width;
|
|
||||||
source_height = dimensions.height;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
clutter_actor_get_allocation_geometry(CLUTTER_ACTOR(image), &geometry);
|
|
||||||
|
|
||||||
dest_width = geometry.width;
|
|
||||||
dest_height = geometry.height;
|
|
||||||
|
|
||||||
cr = clutter_cairo_texture_create(CLUTTER_CAIRO_TEXTURE(image));
|
|
||||||
|
|
||||||
for (j = 0; j < 3; j++) {
|
|
||||||
switch (j) {
|
|
||||||
case 0:
|
|
||||||
source_y1 = 0;
|
|
||||||
source_y2 = image->border_top;
|
|
||||||
dest_y1 = 0;
|
|
||||||
dest_y2 = image->border_top;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
source_y1 = image->border_top;
|
|
||||||
source_y2 = source_height - image->border_bottom;
|
|
||||||
dest_y1 = image->border_top;
|
|
||||||
dest_y2 = dest_height - image->border_bottom;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
source_y1 = source_height - image->border_bottom;
|
|
||||||
source_y2 = source_height;
|
|
||||||
dest_y1 = dest_height - image->border_bottom;
|
|
||||||
dest_y2 = dest_height;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dest_y2 <= dest_y1)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* pixbuf-theme-engine has a nice interpretation of source_y2 == source_y1,
|
|
||||||
* dest_y2 != dest_y1, which is to linearly interpolate between the surrounding
|
|
||||||
* areas. We could do that for the surface case by setting
|
|
||||||
*
|
|
||||||
* source_y1 == y - 0.5
|
|
||||||
* source_y2 == y + 0.5
|
|
||||||
*
|
|
||||||
* but it's hard for the SVG case. source_y2 < source_y1 is pathological ... someone
|
|
||||||
* specified borders that sum up larger than the image.
|
|
||||||
*/
|
|
||||||
if (source_y2 <= source_y1)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for (i = 0; i < 3; i++) {
|
|
||||||
switch (i) {
|
|
||||||
case 0:
|
|
||||||
source_x1 = 0;
|
|
||||||
source_x2 = image->border_left;
|
|
||||||
dest_x1 = 0;
|
|
||||||
dest_x2 = image->border_left;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
source_x1 = image->border_left;
|
|
||||||
source_x2 = source_width - image->border_right;
|
|
||||||
dest_x1 = image->border_left;
|
|
||||||
dest_x2 = dest_width - image->border_right;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
source_x1 = source_width - image->border_right;
|
|
||||||
source_x2 = source_width;
|
|
||||||
dest_x1 = dest_width - image->border_right;
|
|
||||||
dest_x2 = dest_width;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dest_x2 <= dest_x1)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (source_x2 <= source_x1)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
cairo_save(cr);
|
|
||||||
|
|
||||||
cairo_rectangle(cr, dest_x1, dest_y1, dest_x2 - dest_x1, dest_y2 - dest_y1);
|
|
||||||
cairo_clip(cr);
|
|
||||||
|
|
||||||
cairo_translate(cr, dest_x1, dest_y1);
|
|
||||||
cairo_scale(cr,
|
|
||||||
(double)(dest_x2 - dest_x1) / (source_x2 - source_x1),
|
|
||||||
(double)(dest_y2 - dest_y1) / (source_y2 - source_y1));
|
|
||||||
|
|
||||||
switch (image->type) {
|
|
||||||
case BIG_THEME_IMAGE_SURFACE:
|
|
||||||
cairo_set_source_surface(cr, image->u.surface, - source_x1, - source_y1);
|
|
||||||
cairo_paint(cr);
|
|
||||||
break;
|
|
||||||
case BIG_THEME_IMAGE_SVG:
|
|
||||||
cairo_translate(cr, - source_x1, - source_y1);
|
|
||||||
rsvg_handle_render_cairo(image->u.svg_handle, cr);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
cairo_restore(cr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This will cause the surface content to be uploaded as
|
|
||||||
* new texture content */
|
|
||||||
cairo_destroy(cr);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
big_theme_image_render_idle(gpointer data)
|
|
||||||
{
|
|
||||||
BigThemeImage *image;
|
|
||||||
|
|
||||||
image = data;
|
|
||||||
big_theme_image_render(image);
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
big_theme_image_queue_render(BigThemeImage *image)
|
|
||||||
{
|
|
||||||
image->needs_render = TRUE;
|
|
||||||
if (!image->render_idle)
|
|
||||||
image->render_idle = g_idle_add(big_theme_image_render_idle,
|
|
||||||
image);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
big_theme_image_paint(ClutterActor *actor)
|
|
||||||
{
|
|
||||||
BigThemeImage *image;
|
|
||||||
|
|
||||||
image = BIG_THEME_IMAGE(actor);
|
|
||||||
|
|
||||||
if (image->needs_render)
|
|
||||||
big_theme_image_render(image);
|
|
||||||
|
|
||||||
if (CLUTTER_ACTOR_CLASS(big_theme_image_parent_class)->paint)
|
|
||||||
CLUTTER_ACTOR_CLASS(big_theme_image_parent_class)->paint(actor);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
big_theme_image_allocate(ClutterActor *actor,
|
|
||||||
const ClutterActorBox *box,
|
|
||||||
ClutterAllocationFlags flags)
|
|
||||||
{
|
|
||||||
BigThemeImage *image;
|
|
||||||
guint old_width;
|
|
||||||
guint old_height;
|
|
||||||
guint width;
|
|
||||||
guint height;
|
|
||||||
|
|
||||||
image = BIG_THEME_IMAGE(actor);
|
|
||||||
|
|
||||||
width = ABS(box->x2 - box->x1);
|
|
||||||
height = ABS(box->y2 - box->y1);
|
|
||||||
|
|
||||||
g_object_get(actor,
|
|
||||||
"surface-width", &old_width,
|
|
||||||
"surface-height", &old_height,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (width != old_width || height != old_height) {
|
|
||||||
|
|
||||||
clutter_cairo_texture_set_surface_size(CLUTTER_CAIRO_TEXTURE(actor), width, height);
|
|
||||||
|
|
||||||
big_theme_image_queue_render(image);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CLUTTER_ACTOR_CLASS(big_theme_image_parent_class))
|
|
||||||
CLUTTER_ACTOR_CLASS(big_theme_image_parent_class)->allocate(actor,
|
|
||||||
box,
|
|
||||||
flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
big_theme_image_get_preferred_height(ClutterActor *actor,
|
|
||||||
float for_width,
|
|
||||||
float *min_height_p,
|
|
||||||
float *natural_height_p)
|
|
||||||
{
|
|
||||||
BigThemeImage *image;
|
|
||||||
|
|
||||||
image = BIG_THEME_IMAGE(actor);
|
|
||||||
|
|
||||||
if (min_height_p)
|
|
||||||
*min_height_p = 0;
|
|
||||||
|
|
||||||
if (!natural_height_p)
|
|
||||||
return;
|
|
||||||
|
|
||||||
*natural_height_p = 0;
|
|
||||||
|
|
||||||
switch (image->type) {
|
|
||||||
case BIG_THEME_IMAGE_SURFACE:
|
|
||||||
if (!image->u.surface)
|
|
||||||
break;
|
|
||||||
|
|
||||||
*natural_height_p = cairo_image_surface_get_height(image->u.surface);
|
|
||||||
break;
|
|
||||||
case BIG_THEME_IMAGE_SVG:
|
|
||||||
{
|
|
||||||
RsvgDimensionData dimensions;
|
|
||||||
|
|
||||||
if (!image->u.svg_handle)
|
|
||||||
return;
|
|
||||||
|
|
||||||
rsvg_handle_get_dimensions(image->u.svg_handle, &dimensions);
|
|
||||||
*natural_height_p = dimensions.height;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
big_theme_image_get_preferred_width(ClutterActor *actor,
|
|
||||||
float for_height,
|
|
||||||
float *min_width_p,
|
|
||||||
float *natural_width_p)
|
|
||||||
{
|
|
||||||
BigThemeImage *image;
|
|
||||||
|
|
||||||
image = BIG_THEME_IMAGE(actor);
|
|
||||||
|
|
||||||
if (min_width_p)
|
|
||||||
*min_width_p = 0;
|
|
||||||
|
|
||||||
if (!natural_width_p)
|
|
||||||
return;
|
|
||||||
|
|
||||||
*natural_width_p = 0;
|
|
||||||
|
|
||||||
switch (image->type) {
|
|
||||||
case BIG_THEME_IMAGE_SURFACE:
|
|
||||||
if (!image->u.surface)
|
|
||||||
break;
|
|
||||||
|
|
||||||
*natural_width_p = cairo_image_surface_get_width(image->u.surface);
|
|
||||||
break;
|
|
||||||
case BIG_THEME_IMAGE_SVG:
|
|
||||||
{
|
|
||||||
RsvgDimensionData dimensions;
|
|
||||||
|
|
||||||
if (!image->u.svg_handle)
|
|
||||||
return;
|
|
||||||
|
|
||||||
rsvg_handle_get_dimensions(image->u.svg_handle, &dimensions);
|
|
||||||
*natural_width_p = dimensions.width;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
big_theme_image_set_border_value(BigThemeImage *image, guint *old_value, const GValue *new_value)
|
|
||||||
{
|
|
||||||
guint border_value;
|
|
||||||
|
|
||||||
border_value = g_value_get_uint(new_value);
|
|
||||||
|
|
||||||
if (*old_value != border_value) {
|
|
||||||
*old_value = border_value;
|
|
||||||
|
|
||||||
big_theme_image_queue_render(image);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
big_theme_image_set_filename(BigThemeImage *image, const char *filename)
|
|
||||||
{
|
|
||||||
if (!filename)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (g_str_has_suffix(filename, ".png") ||
|
|
||||||
g_str_has_suffix(filename, ".PNG")) {
|
|
||||||
|
|
||||||
image->type = BIG_THEME_IMAGE_SURFACE;
|
|
||||||
|
|
||||||
image->u.surface = cairo_image_surface_create_from_png(filename);
|
|
||||||
|
|
||||||
if (image->u.surface == NULL) {
|
|
||||||
g_warning("Error when loading PNG from file %s", filename);
|
|
||||||
}
|
|
||||||
} else if (g_str_has_suffix(filename, ".svg") ||
|
|
||||||
g_str_has_suffix(filename, ".SVG")) {
|
|
||||||
|
|
||||||
GError *error;
|
|
||||||
|
|
||||||
error = NULL;
|
|
||||||
image->u.svg_handle = rsvg_handle_new_from_file(filename, &error);
|
|
||||||
|
|
||||||
if (image->u.svg_handle == NULL) {
|
|
||||||
g_warning("Error when loading SVG from file %s: %s", filename,
|
|
||||||
error?error->message:"Error not set by RSVG");
|
|
||||||
if (error)
|
|
||||||
g_error_free(error);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
image->type = BIG_THEME_IMAGE_SVG;
|
|
||||||
} else {
|
|
||||||
g_warning("%s: Unsupported file type", filename);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
big_theme_image_queue_render(image);
|
|
||||||
}
|
|
||||||
|
|
||||||
static cairo_surface_t *
|
|
||||||
create_surface_from_pixbuf(const GdkPixbuf *pixbuf)
|
|
||||||
{
|
|
||||||
gint width = gdk_pixbuf_get_width (pixbuf);
|
|
||||||
gint height = gdk_pixbuf_get_height (pixbuf);
|
|
||||||
guchar *gdk_pixels = gdk_pixbuf_get_pixels (pixbuf);
|
|
||||||
int gdk_rowstride = gdk_pixbuf_get_rowstride (pixbuf);
|
|
||||||
int n_channels = gdk_pixbuf_get_n_channels (pixbuf);
|
|
||||||
|
|
||||||
guchar *cairo_pixels;
|
|
||||||
cairo_format_t format;
|
|
||||||
cairo_surface_t *surface;
|
|
||||||
static const cairo_user_data_key_t key;
|
|
||||||
|
|
||||||
int j;
|
|
||||||
|
|
||||||
if (n_channels == 3)
|
|
||||||
format = CAIRO_FORMAT_RGB24;
|
|
||||||
else
|
|
||||||
format = CAIRO_FORMAT_ARGB32;
|
|
||||||
|
|
||||||
cairo_pixels = g_malloc (4 * width * height);
|
|
||||||
|
|
||||||
surface = cairo_image_surface_create_for_data((unsigned char *)cairo_pixels,
|
|
||||||
format,
|
|
||||||
width, height, 4 * width);
|
|
||||||
|
|
||||||
cairo_surface_set_user_data(surface, &key,
|
|
||||||
cairo_pixels, (cairo_destroy_func_t)g_free);
|
|
||||||
|
|
||||||
for (j = height; j; j--) {
|
|
||||||
guchar *p = gdk_pixels;
|
|
||||||
guchar *q = cairo_pixels;
|
|
||||||
|
|
||||||
if (n_channels == 3) {
|
|
||||||
guchar *end = p + 3 * width;
|
|
||||||
|
|
||||||
while (p < end) {
|
|
||||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
|
||||||
q[0] = p[2];
|
|
||||||
q[1] = p[1];
|
|
||||||
q[2] = p[0];
|
|
||||||
#else
|
|
||||||
q[1] = p[0];
|
|
||||||
q[2] = p[1];
|
|
||||||
q[3] = p[2];
|
|
||||||
#endif
|
|
||||||
p += 3;
|
|
||||||
q += 4;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
guchar *end = p + 4 * width;
|
|
||||||
guint t1,t2,t3;
|
|
||||||
|
|
||||||
#define MULT(d,c,a,t) G_STMT_START { t = c * a + 0x7f; d = ((t >> 8) + t) >> 8; } G_STMT_END
|
|
||||||
|
|
||||||
while (p < end) {
|
|
||||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
|
||||||
MULT(q[0], p[2], p[3], t1);
|
|
||||||
MULT(q[1], p[1], p[3], t2);
|
|
||||||
MULT(q[2], p[0], p[3], t3);
|
|
||||||
q[3] = p[3];
|
|
||||||
#else
|
|
||||||
q[0] = p[3];
|
|
||||||
MULT(q[1], p[0], p[3], t1);
|
|
||||||
MULT(q[2], p[1], p[3], t2);
|
|
||||||
MULT(q[3], p[2], p[3], t3);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
p += 4;
|
|
||||||
q += 4;
|
|
||||||
}
|
|
||||||
#undef MULT
|
|
||||||
}
|
|
||||||
|
|
||||||
gdk_pixels += gdk_rowstride;
|
|
||||||
cairo_pixels += 4 * width;
|
|
||||||
}
|
|
||||||
|
|
||||||
return surface;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
big_theme_image_set_pixbuf(BigThemeImage *image, GdkPixbuf *pixbuf)
|
|
||||||
{
|
|
||||||
if (!pixbuf)
|
|
||||||
return;
|
|
||||||
|
|
||||||
image->type = BIG_THEME_IMAGE_SURFACE;
|
|
||||||
|
|
||||||
image->u.surface = create_surface_from_pixbuf(pixbuf);
|
|
||||||
|
|
||||||
g_assert(image->u.surface != NULL);
|
|
||||||
|
|
||||||
big_theme_image_queue_render(image);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
big_theme_image_set_property(GObject *object,
|
|
||||||
guint prop_id,
|
|
||||||
const GValue *value,
|
|
||||||
GParamSpec *pspec)
|
|
||||||
{
|
|
||||||
BigThemeImage *image;
|
|
||||||
|
|
||||||
image = BIG_THEME_IMAGE(object);
|
|
||||||
|
|
||||||
switch (prop_id) {
|
|
||||||
case PROP_BORDER_TOP:
|
|
||||||
big_theme_image_set_border_value(image, &image->border_top, value);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PROP_BORDER_BOTTOM:
|
|
||||||
big_theme_image_set_border_value(image, &image->border_bottom, value);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PROP_BORDER_LEFT:
|
|
||||||
big_theme_image_set_border_value(image, &image->border_left, value);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PROP_BORDER_RIGHT:
|
|
||||||
big_theme_image_set_border_value(image, &image->border_right, value);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PROP_FILENAME:
|
|
||||||
big_theme_image_set_filename(image, g_value_get_string(value));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PROP_PIXBUF:
|
|
||||||
big_theme_image_set_pixbuf(image, g_value_get_object(value));
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
big_theme_image_get_property(GObject *object,
|
|
||||||
guint prop_id,
|
|
||||||
GValue *value,
|
|
||||||
GParamSpec *pspec)
|
|
||||||
{
|
|
||||||
BigThemeImage *image;
|
|
||||||
|
|
||||||
image = BIG_THEME_IMAGE(object);
|
|
||||||
|
|
||||||
switch (prop_id) {
|
|
||||||
case PROP_BORDER_TOP:
|
|
||||||
g_value_set_uint(value, image->border_top);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PROP_BORDER_BOTTOM:
|
|
||||||
g_value_set_uint(value, image->border_bottom);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PROP_BORDER_LEFT:
|
|
||||||
g_value_set_uint(value, image->border_left);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PROP_BORDER_RIGHT:
|
|
||||||
g_value_set_uint(value, image->border_right);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
big_theme_image_dispose(GObject *object)
|
|
||||||
{
|
|
||||||
BigThemeImage *image;
|
|
||||||
|
|
||||||
image = BIG_THEME_IMAGE(object);
|
|
||||||
|
|
||||||
if (image->render_idle) {
|
|
||||||
g_source_remove(image->render_idle);
|
|
||||||
image->render_idle = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (image->type) {
|
|
||||||
case BIG_THEME_IMAGE_SVG:
|
|
||||||
if (image->u.svg_handle) {
|
|
||||||
g_object_unref(image->u.svg_handle);
|
|
||||||
image->u.svg_handle = NULL;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case BIG_THEME_IMAGE_SURFACE:
|
|
||||||
if (image->u.surface) {
|
|
||||||
cairo_surface_destroy(image->u.surface);
|
|
||||||
image->u.surface = NULL;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (G_OBJECT_CLASS(big_theme_image_parent_class)->dispose)
|
|
||||||
G_OBJECT_CLASS(big_theme_image_parent_class)->dispose(object);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
big_theme_image_class_init(BigThemeImageClass *klass)
|
|
||||||
{
|
|
||||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
|
||||||
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
|
||||||
|
|
||||||
gobject_class->dispose = big_theme_image_dispose;
|
|
||||||
gobject_class->set_property = big_theme_image_set_property;
|
|
||||||
gobject_class->get_property = big_theme_image_get_property;
|
|
||||||
|
|
||||||
actor_class->allocate = big_theme_image_allocate;
|
|
||||||
actor_class->get_preferred_width = big_theme_image_get_preferred_width;
|
|
||||||
actor_class->get_preferred_height = big_theme_image_get_preferred_height;
|
|
||||||
actor_class->paint = big_theme_image_paint;
|
|
||||||
|
|
||||||
g_object_class_install_property
|
|
||||||
(gobject_class,
|
|
||||||
PROP_BORDER_TOP,
|
|
||||||
g_param_spec_uint("border-top",
|
|
||||||
"Border top",
|
|
||||||
"Top dimension of the image border "
|
|
||||||
"(none-scaled part)",
|
|
||||||
0, G_MAXUINT,
|
|
||||||
0,
|
|
||||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
|
||||||
|
|
||||||
g_object_class_install_property
|
|
||||||
(gobject_class,
|
|
||||||
PROP_BORDER_BOTTOM,
|
|
||||||
g_param_spec_uint("border-bottom",
|
|
||||||
"Border bottom",
|
|
||||||
"Bottom dimension of the image border "
|
|
||||||
"(none-scaled part)",
|
|
||||||
0, G_MAXUINT,
|
|
||||||
0,
|
|
||||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
|
||||||
|
|
||||||
g_object_class_install_property
|
|
||||||
(gobject_class,
|
|
||||||
PROP_BORDER_LEFT,
|
|
||||||
g_param_spec_uint("border-left",
|
|
||||||
"Border left",
|
|
||||||
"Left dimension of the image border "
|
|
||||||
"(none-scaled part)",
|
|
||||||
0, G_MAXUINT,
|
|
||||||
0,
|
|
||||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
|
||||||
|
|
||||||
g_object_class_install_property
|
|
||||||
(gobject_class,
|
|
||||||
PROP_BORDER_RIGHT,
|
|
||||||
g_param_spec_uint("border-right",
|
|
||||||
"Border right",
|
|
||||||
"Right dimension of the image border "
|
|
||||||
"(none-scaled part)",
|
|
||||||
0, G_MAXUINT,
|
|
||||||
0,
|
|
||||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
|
||||||
|
|
||||||
g_object_class_install_property
|
|
||||||
(gobject_class,
|
|
||||||
PROP_FILENAME,
|
|
||||||
g_param_spec_string("filename",
|
|
||||||
"Filename",
|
|
||||||
"Name of the file",
|
|
||||||
NULL,
|
|
||||||
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
|
|
||||||
|
|
||||||
g_object_class_install_property
|
|
||||||
(gobject_class,
|
|
||||||
PROP_PIXBUF,
|
|
||||||
g_param_spec_object("pixbuf",
|
|
||||||
"Pixbuf",
|
|
||||||
"Pixbuf of the image",
|
|
||||||
GDK_TYPE_PIXBUF,
|
|
||||||
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
big_theme_image_init(BigThemeImage *image)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
ClutterActor *
|
|
||||||
big_theme_image_new_from_file(const char *filename,
|
|
||||||
guint border_top,
|
|
||||||
guint border_bottom,
|
|
||||||
guint border_left,
|
|
||||||
guint border_right)
|
|
||||||
{
|
|
||||||
ClutterActor *actor;
|
|
||||||
|
|
||||||
actor = g_object_new(BIG_TYPE_THEME_IMAGE,
|
|
||||||
/* FIXME ClutterCairo requires creating a bogus
|
|
||||||
* surface with nonzero size
|
|
||||||
*/
|
|
||||||
"surface-width", 1,
|
|
||||||
"surface-height", 1,
|
|
||||||
"filename", filename,
|
|
||||||
"border-top", border_top,
|
|
||||||
"border-bottom", border_bottom,
|
|
||||||
"border-left", border_left,
|
|
||||||
"border-right", border_right,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
return actor;
|
|
||||||
}
|
|
||||||
|
|
||||||
ClutterActor *
|
|
||||||
big_theme_image_new_from_pixbuf(GdkPixbuf *pixbuf,
|
|
||||||
guint border_top,
|
|
||||||
guint border_bottom,
|
|
||||||
guint border_left,
|
|
||||||
guint border_right)
|
|
||||||
{
|
|
||||||
ClutterActor *actor;
|
|
||||||
|
|
||||||
actor = g_object_new(BIG_TYPE_THEME_IMAGE,
|
|
||||||
/* FIXME ClutterCairo requires creating a bogus
|
|
||||||
* surface with nonzero size
|
|
||||||
*/
|
|
||||||
"surface-width", 1,
|
|
||||||
"surface-height", 1,
|
|
||||||
"pixbuf", pixbuf,
|
|
||||||
"border-top", border_top,
|
|
||||||
"border-bottom", border_bottom,
|
|
||||||
"border-left", border_left,
|
|
||||||
"border-right", border_right,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
return actor;
|
|
||||||
}
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
|||||||
/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
|
|
||||||
/* Copyright 2008 litl, LLC. All Rights Reserved. */
|
|
||||||
|
|
||||||
#ifndef __BIG_THEME_IMAGE_H__
|
|
||||||
#define __BIG_THEME_IMAGE_H__
|
|
||||||
|
|
||||||
#include <glib-object.h>
|
|
||||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
|
||||||
#include <clutter/clutter.h>
|
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
|
||||||
|
|
||||||
#define BIG_TYPE_THEME_IMAGE (big_theme_image_get_type ())
|
|
||||||
#define BIG_THEME_IMAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), BIG_TYPE_THEME_IMAGE, BigThemeImage))
|
|
||||||
#define BIG_THEME_IMAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), BIG_TYPE_THEME_IMAGE, BigThemeImageClass))
|
|
||||||
#define BIG_IS_THEME_IMAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BIG_TYPE_THEME_IMAGE))
|
|
||||||
#define BIG_IS_THEME_IMAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), BIG_TYPE_THEME_IMAGE))
|
|
||||||
#define BIG_THEME_IMAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), BIG_TYPE_THEME_IMAGE, BigThemeImageClass))
|
|
||||||
|
|
||||||
typedef struct BigThemeImage BigThemeImage;
|
|
||||||
typedef struct BigThemeImageClass BigThemeImageClass;
|
|
||||||
|
|
||||||
GType big_theme_image_get_type (void) G_GNUC_CONST;
|
|
||||||
|
|
||||||
ClutterActor * big_theme_image_new_from_file (const gchar *filename,
|
|
||||||
guint border_top,
|
|
||||||
guint border_bottom,
|
|
||||||
guint border_left,
|
|
||||||
guint border_right);
|
|
||||||
|
|
||||||
ClutterActor * big_theme_image_new_from_pixbuf (GdkPixbuf *pixbuf,
|
|
||||||
guint border_top,
|
|
||||||
guint border_bottom,
|
|
||||||
guint border_left,
|
|
||||||
guint border_right);
|
|
||||||
|
|
||||||
G_END_DECLS
|
|
||||||
|
|
||||||
#endif /* __BIG_THEME_IMAGE_H__ */
|
|
Loading…
Reference in New Issue
Block a user